From d769f8da23c6259541a50bcaee313b5372e026cb Mon Sep 17 00:00:00 2001 From: Peter Schaefer Date: Thu, 2 Aug 2012 17:23:16 +0200 Subject: [PATCH] =?utf8?q?[src]=20tbb=20src=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- src/tbb/CHANGES | 1264 ++ src/tbb/COPYING | 353 + src/tbb/Makefile | 88 + src/tbb/README | 11 + src/tbb/build/AIX.gcc.inc | 85 + src/tbb/build/AIX.inc | 75 + src/tbb/build/FreeBSD.gcc.inc | 95 + src/tbb/build/FreeBSD.inc | 83 + src/tbb/build/Makefile.rml | 160 + src/tbb/build/Makefile.tbb | 134 + src/tbb/build/Makefile.tbbmalloc | 208 + src/tbb/build/Makefile.tbbproxy | 116 + src/tbb/build/Makefile.test | 376 + src/tbb/build/SunOS.gcc.inc | 102 + src/tbb/build/SunOS.inc | 92 + src/tbb/build/SunOS.suncc.inc | 99 + src/tbb/build/big_iron.inc | 74 + src/tbb/build/codecov.txt | 7 + src/tbb/build/common.inc | 116 + src/tbb/build/common_rules.inc | 129 + src/tbb/build/detect.js | 183 + src/tbb/build/generate_tbbvars.bat | 74 + src/tbb/build/generate_tbbvars.sh | 76 + src/tbb/build/index.html | 232 + src/tbb/build/linux.gcc.inc | 145 + src/tbb/build/linux.icc.inc | 126 + src/tbb/build/linux.inc | 139 + src/tbb/build/linux.xl.inc | 113 + src/tbb/build/macos.clang.inc | 109 + src/tbb/build/macos.gcc.inc | 109 + src/tbb/build/macos.icc.inc | 103 + src/tbb/build/macos.inc | 98 + src/tbb/build/suncc.map.pause | 1 + src/tbb/build/test_launcher.bat | 36 + src/tbb/build/test_launcher.sh | 42 + src/tbb/build/version_info_aix.sh | 42 + src/tbb/build/version_info_linux.sh | 42 + src/tbb/build/version_info_macos.sh | 39 + src/tbb/build/version_info_sunos.sh | 39 + src/tbb/build/version_info_windows.js | 136 + src/tbb/build/vsproject/index.html | 30 + src/tbb/build/vsproject/makefile.sln | 100 + src/tbb/build/vsproject/tbb.vcproj | 530 + src/tbb/build/vsproject/tbbmalloc.vcproj | 410 + .../build/vsproject/tbbmalloc_proxy.vcproj | 206 + src/tbb/build/vsproject/version_string.ver | 1 + src/tbb/build/windows.cl.inc | 126 + src/tbb/build/windows.gcc.inc | 137 + src/tbb/build/windows.icl.inc | 167 + src/tbb/build/windows.inc | 110 + src/tbb/build/xbox360.cl.inc | 93 + src/tbb/build/xbox360.inc | 78 + src/tbb/doc/Release_Notes.txt | 126 + src/tbb/doc/html/a00005.html | 35 + src/tbb/doc/html/a00006.html | 37 + src/tbb/doc/html/a00007.html | 34 + src/tbb/doc/html/a00008.html | 34 + src/tbb/doc/html/a00009.html | 34 + src/tbb/doc/html/a00010.html | 45 + src/tbb/doc/html/a00011.html | 41 + src/tbb/doc/html/a00012.html | 43 + src/tbb/doc/html/a00013.html | 48 + src/tbb/doc/html/a00015.html | 35 + src/tbb/doc/html/a00017.html | 42 + src/tbb/doc/html/a00018.html | 34 + src/tbb/doc/html/a00019.html | 95 + src/tbb/doc/html/a00021.html | 36 + src/tbb/doc/html/a00022.html | 44 + src/tbb/doc/html/a00023.html | 42 + src/tbb/doc/html/a00031.html | 51 + src/tbb/doc/html/a00035.html | 55 + src/tbb/doc/html/a00036.html | 60 + src/tbb/doc/html/a00038.html | 69 + src/tbb/doc/html/a00044.html | 102 + src/tbb/doc/html/a00049.html | 66 + src/tbb/doc/html/a00053.html | 41 + src/tbb/doc/html/a00054.html | 38 + src/tbb/doc/html/a00055.html | 49 + src/tbb/doc/html/a00057.html | 53 + src/tbb/doc/html/a00060.html | 39 + src/tbb/doc/html/a00061.html | 51 + src/tbb/doc/html/a00062.html | 47 + src/tbb/doc/html/a00063.html | 48 + src/tbb/doc/html/a00064.html | 41 + src/tbb/doc/html/a00066.html | 44 + src/tbb/doc/html/a00068.html | 47 + src/tbb/doc/html/a00071.html | 54 + src/tbb/doc/html/a00072.html | 87 + src/tbb/doc/html/a00074.html | 90 + src/tbb/doc/html/a00075.html | 93 + src/tbb/doc/html/a00076.html | 91 + src/tbb/doc/html/a00077.html | 59 + src/tbb/doc/html/a00082.html | 53 + src/tbb/doc/html/a00084.html | 43 + src/tbb/doc/html/a00086.html | 34 + src/tbb/doc/html/a00088.html | 49 + src/tbb/doc/html/a00089.html | 39 + src/tbb/doc/html/a00090.html | 36 + src/tbb/doc/html/a00091.html | 38 + src/tbb/doc/html/a00092.html | 36 + src/tbb/doc/html/a00093.html | 40 + src/tbb/doc/html/a00094.html | 34 + src/tbb/doc/html/a00096.html | 33 + src/tbb/doc/html/a00097.html | 33 + src/tbb/doc/html/a00098.html | 37 + src/tbb/doc/html/a00099.html | 34 + src/tbb/doc/html/a00100.html | 37 + src/tbb/doc/html/a00101.html | 37 + src/tbb/doc/html/a00103.html | 37 + src/tbb/doc/html/a00104.html | 39 + src/tbb/doc/html/a00105.html | 54 + src/tbb/doc/html/a00106.html | 59 + src/tbb/doc/html/a00107.html | 44 + src/tbb/doc/html/a00108.html | 34 + src/tbb/doc/html/a00109.html | 41 + src/tbb/doc/html/a00110.html | 37 + src/tbb/doc/html/a00111.html | 38 + src/tbb/doc/html/a00112.html | 38 + src/tbb/doc/html/a00113.html | 40 + src/tbb/doc/html/a00114.html | 46 + src/tbb/doc/html/a00115.html | 37 + src/tbb/doc/html/a00116.html | 37 + src/tbb/doc/html/a00117.html | 44 + src/tbb/doc/html/a00118.html | 39 + src/tbb/doc/html/a00119.html | 48 + src/tbb/doc/html/a00121.html | 48 + src/tbb/doc/html/a00123.html | 35 + src/tbb/doc/html/a00125.html | 41 + src/tbb/doc/html/a00126.html | 39 + src/tbb/doc/html/a00127.html | 42 + src/tbb/doc/html/a00128.html | 42 + src/tbb/doc/html/a00130.html | 32 + src/tbb/doc/html/a00133.html | 90 + src/tbb/doc/html/a00134.html | 88 + src/tbb/doc/html/a00135.html | 40 + src/tbb/doc/html/a00142.html | 41 + src/tbb/doc/html/a00144.html | 51 + src/tbb/doc/html/a00146.html | 35 + src/tbb/doc/html/a00148.html | 44 + src/tbb/doc/html/a00150.html | 36 + src/tbb/doc/html/a00152.html | 34 + src/tbb/doc/html/a00153.html | 33 + src/tbb/doc/html/a00154.html | 33 + src/tbb/doc/html/a00155.html | 33 + src/tbb/doc/html/a00156.html | 33 + src/tbb/doc/html/a00157.html | 38 + src/tbb/doc/html/a00158.html | 44 + src/tbb/doc/html/a00159.html | 45 + src/tbb/doc/html/a00160.html | 37 + src/tbb/doc/html/a00165.html | 36 + src/tbb/doc/html/a00169.html | 34 + src/tbb/doc/html/a00170.html | 34 + src/tbb/doc/html/a00179.html | 33 + src/tbb/doc/html/a00183.html | 35 + src/tbb/doc/html/a00184.html | 41 + src/tbb/doc/html/a00249.html | 64 + src/tbb/doc/html/a00249.png | Bin 0 -> 674 bytes src/tbb/doc/html/a00250.html | 58 + src/tbb/doc/html/a00250.png | Bin 0 -> 671 bytes src/tbb/doc/html/a00251.html | 81 + src/tbb/doc/html/a00251.png | Bin 0 -> 792 bytes src/tbb/doc/html/a00252.html | 113 + src/tbb/doc/html/a00252.png | Bin 0 -> 787 bytes src/tbb/doc/html/a00253.html | 63 + src/tbb/doc/html/a00254.html | 61 + src/tbb/doc/html/a00255.html | 56 + src/tbb/doc/html/a00256.html | 59 + src/tbb/doc/html/a00257.html | 64 + src/tbb/doc/html/a00258.html | 50 + src/tbb/doc/html/a00259.html | 224 + src/tbb/doc/html/a00260.html | 86 + src/tbb/doc/html/a00261.html | 93 + src/tbb/doc/html/a00262.html | 92 + src/tbb/doc/html/a00262.png | Bin 0 -> 1270 bytes src/tbb/doc/html/a00263.html | 411 + src/tbb/doc/html/a00263.png | Bin 0 -> 2898 bytes src/tbb/doc/html/a00264.html | 111 + src/tbb/doc/html/a00265.html | 65 + src/tbb/doc/html/a00266.html | 157 + src/tbb/doc/html/a00266.png | Bin 0 -> 472 bytes src/tbb/doc/html/a00267.html | 84 + src/tbb/doc/html/a00268.html | 310 + src/tbb/doc/html/a00268.png | Bin 0 -> 731 bytes src/tbb/doc/html/a00269.html | 646 + src/tbb/doc/html/a00270.html | 68 + src/tbb/doc/html/a00270.png | Bin 0 -> 1371 bytes src/tbb/doc/html/a00271.html | 65 + src/tbb/doc/html/a00272.html | 102 + src/tbb/doc/html/a00272.png | Bin 0 -> 1376 bytes src/tbb/doc/html/a00273.html | 348 + src/tbb/doc/html/a00274.html | 169 + src/tbb/doc/html/a00275.html | 154 + src/tbb/doc/html/a00275.png | Bin 0 -> 720 bytes src/tbb/doc/html/a00276.html | 596 + src/tbb/doc/html/a00277.html | 46 + src/tbb/doc/html/a00278.html | 94 + src/tbb/doc/html/a00278.png | Bin 0 -> 777 bytes src/tbb/doc/html/a00279.html | 168 + src/tbb/doc/html/a00279.png | Bin 0 -> 668 bytes src/tbb/doc/html/a00280.html | 54 + src/tbb/doc/html/a00280.png | Bin 0 -> 387 bytes src/tbb/doc/html/a00281.html | 197 + src/tbb/doc/html/a00282.html | 236 + src/tbb/doc/html/a00282.png | Bin 0 -> 433 bytes src/tbb/doc/html/a00283.html | 76 + src/tbb/doc/html/a00284.html | 53 + src/tbb/doc/html/a00285.html | 54 + src/tbb/doc/html/a00286.html | 94 + src/tbb/doc/html/a00286.png | Bin 0 -> 942 bytes src/tbb/doc/html/a00287.html | 98 + src/tbb/doc/html/a00287.png | Bin 0 -> 1016 bytes src/tbb/doc/html/a00288.html | 276 + src/tbb/doc/html/a00289.html | 80 + src/tbb/doc/html/a00289.png | Bin 0 -> 5357 bytes src/tbb/doc/html/a00290.html | 50 + src/tbb/doc/html/a00291.html | 50 + src/tbb/doc/html/a00292.html | 143 + src/tbb/doc/html/a00292.png | Bin 0 -> 1209 bytes src/tbb/doc/html/a00293.html | 53 + src/tbb/doc/html/a00294.html | 53 + src/tbb/doc/html/a00295.html | 58 + src/tbb/doc/html/a00296.html | 132 + src/tbb/doc/html/a00297.html | 95 + src/tbb/doc/html/a00298.html | 50 + src/tbb/doc/html/a00299.html | 171 + src/tbb/doc/html/a00299.png | Bin 0 -> 604 bytes src/tbb/doc/html/a00300.html | 71 + src/tbb/doc/html/a00300.png | Bin 0 -> 982 bytes src/tbb/doc/html/a00301.html | 136 + src/tbb/doc/html/a00302.html | 77 + src/tbb/doc/html/a00303.html | 65 + src/tbb/doc/html/a00304.html | 59 + src/tbb/doc/html/a00305.html | 65 + src/tbb/doc/html/a00306.html | 65 + src/tbb/doc/html/a00307.html | 65 + src/tbb/doc/html/a00308.html | 140 + src/tbb/doc/html/a00309.html | 62 + src/tbb/doc/html/a00310.html | 111 + src/tbb/doc/html/a00311.html | 53 + src/tbb/doc/html/a00312.html | 133 + src/tbb/doc/html/a00312.png | Bin 0 -> 2103 bytes src/tbb/doc/html/a00313.html | 121 + src/tbb/doc/html/a00313.png | Bin 0 -> 2251 bytes src/tbb/doc/html/a00314.html | 71 + src/tbb/doc/html/a00315.html | 94 + src/tbb/doc/html/a00316.html | 77 + src/tbb/doc/html/a00317.html | 123 + src/tbb/doc/html/a00318.html | 221 + src/tbb/doc/html/a00319.html | 67 + src/tbb/doc/html/a00320.html | 65 + src/tbb/doc/html/a00321.html | 86 + src/tbb/doc/html/a00321.png | Bin 0 -> 3242 bytes src/tbb/doc/html/a00322.html | 118 + src/tbb/doc/html/a00323.html | 77 + src/tbb/doc/html/a00324.html | 325 + src/tbb/doc/html/a00325.html | 110 + src/tbb/doc/html/a00326.html | 65 + src/tbb/doc/html/a00327.html | 93 + src/tbb/doc/html/a00327.png | Bin 0 -> 2681 bytes src/tbb/doc/html/a00328.html | 112 + src/tbb/doc/html/a00328.png | Bin 0 -> 2045 bytes src/tbb/doc/html/a00329.html | 67 + src/tbb/doc/html/a00330.html | 135 + src/tbb/doc/html/a00330.png | Bin 0 -> 1084 bytes src/tbb/doc/html/a00331.html | 131 + src/tbb/doc/html/a00332.html | 97 + src/tbb/doc/html/a00333.html | 133 + src/tbb/doc/html/a00334.html | 149 + src/tbb/doc/html/a00335.html | 51 + src/tbb/doc/html/a00336.html | 75 + src/tbb/doc/html/a00336.png | Bin 0 -> 3005 bytes src/tbb/doc/html/a00337.html | 625 + src/tbb/doc/html/a00337.png | Bin 0 -> 393 bytes src/tbb/doc/html/a00338.html | 48 + src/tbb/doc/html/a00339.html | 43 + src/tbb/doc/html/a00341.html | 83 + src/tbb/doc/html/a00342.html | 168 + src/tbb/doc/html/a00343.html | 122 + src/tbb/doc/html/a00344.html | 65 + src/tbb/doc/html/a00345.html | 168 + src/tbb/doc/html/a00345.png | Bin 0 -> 894 bytes src/tbb/doc/html/a00346.html | 89 + src/tbb/doc/html/a00347.html | 56 + src/tbb/doc/html/a00348.html | 123 + src/tbb/doc/html/a00348.png | Bin 0 -> 426 bytes src/tbb/doc/html/a00349.html | 68 + src/tbb/doc/html/a00350.html | 83 + src/tbb/doc/html/a00351.html | 50 + src/tbb/doc/html/a00352.html | 55 + src/tbb/doc/html/a00353.html | 93 + src/tbb/doc/html/a00354.html | 68 + src/tbb/doc/html/a00372.html | 152 + src/tbb/doc/html/a00373.html | 66 + src/tbb/doc/html/a00392.html | 119 + src/tbb/doc/html/a00411.html | 83 + src/tbb/doc/html/a00414.html | 667 + src/tbb/doc/html/a00426.html | 364 + src/tbb/doc/html/a00427.html | 50 + src/tbb/doc/html/a00428.html | 319 + src/tbb/doc/html/a00429.html | 59 + src/tbb/doc/html/a00430.html | 32 + src/tbb/doc/html/a00431.html | 44 + src/tbb/doc/html/a00432.html | 219 + src/tbb/doc/html/a00440.html | 73 + src/tbb/doc/html/a00441.html | 452 + src/tbb/doc/html/a00449.html | 127 + src/tbb/doc/html/a00450.html | 113 + src/tbb/doc/html/a00451.html | 131 + src/tbb/doc/html/a00452.html | 153 + src/tbb/doc/html/a00454.html | 98 + src/tbb/doc/html/a00455.html | 1219 ++ src/tbb/doc/html/a00466.html | 260 + src/tbb/doc/html/a00473.html | 327 + src/tbb/doc/html/a00476.html | 371 + src/tbb/doc/html/a00480.html | 250 + src/tbb/doc/html/a00484.html | 199 + src/tbb/doc/html/a00487.html | 928 + src/tbb/doc/html/a00496.html | 163 + src/tbb/doc/html/a00499.html | 964 + src/tbb/doc/html/a00511.html | 1655 ++ src/tbb/doc/html/a00524.html | 269 + src/tbb/doc/html/a00531.html | 240 + src/tbb/doc/html/a00533.html | 81 + src/tbb/doc/html/a00534.html | 83 + src/tbb/doc/html/a00535.html | 480 + src/tbb/doc/html/a00544.html | 256 + src/tbb/doc/html/a00548.html | 92 + src/tbb/doc/html/a00550.html | 386 + src/tbb/doc/html/a00556.html | 476 + src/tbb/doc/html/a00562.html | 341 + src/tbb/doc/html/a00567.html | 229 + src/tbb/doc/html/a00571.html | 196 + src/tbb/doc/html/a00575.html | 500 + src/tbb/doc/html/a00587.html | 612 + src/tbb/doc/html/a00603.html | 136 + src/tbb/doc/html/a00604.html | 166 + src/tbb/doc/html/a00605.html | 179 + src/tbb/doc/html/a00606.html | 241 + src/tbb/doc/html/a00607.html | 137 + src/tbb/doc/html/a00608.html | 275 + src/tbb/doc/html/a00611.html | 192 + src/tbb/doc/html/a00612.html | 216 + src/tbb/doc/html/a00613.html | 733 + src/tbb/doc/html/a00623.html | 274 + src/tbb/doc/html/a00630.html | 117 + src/tbb/doc/html/a00631.html | 90 + src/tbb/doc/html/a00633.html | 98 + src/tbb/doc/html/a00634.html | 225 + src/tbb/doc/html/a00638.html | 323 + src/tbb/doc/html/a00639.html | 322 + src/tbb/doc/html/a00640.html | 782 + src/tbb/doc/html/a00647.html | 225 + src/tbb/doc/html/a00648.html | 302 + src/tbb/doc/html/a00655.html | 298 + src/tbb/doc/html/a00663.html | 96 + src/tbb/doc/html/a00665.html | 164 + src/tbb/doc/html/annotated.html | 139 + src/tbb/doc/html/concepts.html | 31 + src/tbb/doc/html/deprecated.html | 29 + src/tbb/doc/html/doxygen.css | 358 + src/tbb/doc/html/doxygen.png | Bin 0 -> 1281 bytes src/tbb/doc/html/files.html | 86 + src/tbb/doc/html/functions.html | 89 + src/tbb/doc/html/functions_0x62.html | 78 + src/tbb/doc/html/functions_0x63.html | 96 + src/tbb/doc/html/functions_0x64.html | 82 + src/tbb/doc/html/functions_0x65.html | 94 + src/tbb/doc/html/functions_0x66.html | 83 + src/tbb/doc/html/functions_0x67.html | 80 + src/tbb/doc/html/functions_0x69.html | 96 + src/tbb/doc/html/functions_0x6c.html | 79 + src/tbb/doc/html/functions_0x6d.html | 80 + src/tbb/doc/html/functions_0x6e.html | 77 + src/tbb/doc/html/functions_0x6f.html | 85 + src/tbb/doc/html/functions_0x70.html | 90 + src/tbb/doc/html/functions_0x71.html | 76 + src/tbb/doc/html/functions_0x72.html | 102 + src/tbb/doc/html/functions_0x73.html | 99 + src/tbb/doc/html/functions_0x74.html | 91 + src/tbb/doc/html/functions_0x75.html | 76 + src/tbb/doc/html/functions_0x76.html | 74 + src/tbb/doc/html/functions_0x77.html | 75 + src/tbb/doc/html/functions_0x7e.html | 98 + src/tbb/doc/html/functions_enum.html | 51 + src/tbb/doc/html/functions_eval.html | 61 + src/tbb/doc/html/functions_func.html | 84 + src/tbb/doc/html/functions_func_0x62.html | 77 + src/tbb/doc/html/functions_func_0x63.html | 93 + src/tbb/doc/html/functions_func_0x64.html | 78 + src/tbb/doc/html/functions_func_0x65.html | 80 + src/tbb/doc/html/functions_func_0x66.html | 77 + src/tbb/doc/html/functions_func_0x67.html | 79 + src/tbb/doc/html/functions_func_0x69.html | 94 + src/tbb/doc/html/functions_func_0x6c.html | 78 + src/tbb/doc/html/functions_func_0x6d.html | 76 + src/tbb/doc/html/functions_func_0x6e.html | 75 + src/tbb/doc/html/functions_func_0x6f.html | 81 + src/tbb/doc/html/functions_func_0x70.html | 87 + src/tbb/doc/html/functions_func_0x71.html | 75 + src/tbb/doc/html/functions_func_0x72.html | 96 + src/tbb/doc/html/functions_func_0x73.html | 94 + src/tbb/doc/html/functions_func_0x74.html | 90 + src/tbb/doc/html/functions_func_0x75.html | 75 + src/tbb/doc/html/functions_func_0x77.html | 74 + src/tbb/doc/html/functions_func_0x7e.html | 97 + src/tbb/doc/html/functions_rela.html | 49 + src/tbb/doc/html/functions_type.html | 61 + src/tbb/doc/html/functions_vars.html | 57 + src/tbb/doc/html/globals.html | 49 + src/tbb/doc/html/globals_func.html | 49 + src/tbb/doc/html/hierarchy.html | 181 + src/tbb/doc/html/index.html | 32 + src/tbb/doc/html/modules.html | 33 + src/tbb/doc/html/namespacemembers.html | 59 + src/tbb/doc/html/namespacemembers_enum.html | 44 + src/tbb/doc/html/namespacemembers_eval.html | 46 + src/tbb/doc/html/namespacemembers_func.html | 53 + src/tbb/doc/html/namespaces.html | 34 + src/tbb/doc/html/pages.html | 31 + src/tbb/doc/html/parallel_do_body_req.html | 38 + src/tbb/doc/html/parallel_for_body_req.html | 30 + .../doc/html/parallel_reduce_body_req.html | 31 + .../doc/html/parallel_reduce_lambda_req.html | 25 + src/tbb/doc/html/parallel_scan_body_req.html | 32 + src/tbb/doc/html/parallel_sort_iter_req.html | 29 + src/tbb/doc/html/range_req.html | 32 + src/tbb/doc/html/tab_b.gif | Bin 0 -> 35 bytes src/tbb/doc/html/tab_l.gif | Bin 0 -> 706 bytes src/tbb/doc/html/tab_r.gif | Bin 0 -> 2585 bytes src/tbb/doc/html/tabs.css | 102 + src/tbb/examples/GettingStarted/index.html | 24 + .../GettingStarted/sub_string_finder/Makefile | 76 + .../sub_string_finder/Makefile.windows | 58 + .../sub_string_finder/index.html | 67 + .../msvs/sub_string_finder.icproj | 11 + .../msvs/sub_string_finder.vcproj | 352 + .../msvs/sub_string_finder_cl.sln | 50 + .../msvs/sub_string_finder_extended.icproj | 11 + .../msvs/sub_string_finder_extended.vcproj | 352 + .../msvs/sub_string_finder_icl.sln | 74 + .../msvs/sub_string_finder_pretty.icproj | 11 + .../msvs/sub_string_finder_pretty.vcproj | 352 + .../sub_string_finder/sub_string_finder.cpp | 85 + .../sub_string_finder_extended.cpp | 171 + .../sub_string_finder_pretty.cpp | 98 + .../project.pbxproj | 573 + src/tbb/examples/Makefile | 157 + src/tbb/examples/common/copy_libraries.bat | 74 + src/tbb/examples/common/gui/Makefile.gmake | 77 + src/tbb/examples/common/gui/Makefile.win | 82 + src/tbb/examples/common/gui/convideo.cpp | 138 + src/tbb/examples/common/gui/d2dvideo.cpp | 209 + src/tbb/examples/common/gui/ddvideo.cpp | 589 + src/tbb/examples/common/gui/dxcheck.bat | 36 + src/tbb/examples/common/gui/gdivideo.cpp | 154 + src/tbb/examples/common/gui/macvideo.cpp | 166 + src/tbb/examples/common/gui/video.h | 244 + src/tbb/examples/common/gui/winvideo.h | 291 + .../common/gui/xcode/tbbExample/Info.plist | 59 + .../common/gui/xcode/tbbExample/OpenGLView.h | 35 + .../common/gui/xcode/tbbExample/OpenGLView.m | 106 + .../common/gui/xcode/tbbExample/PkgInfo | 1 + .../tbbExample/en.lproj/InfoPlist.strings | 2 + .../xcode/tbbExample/en.lproj/MainMenu.nib | Bin 0 -> 3312 bytes .../xcode/tbbExample/en.lproj/MainMenu.xib | 291 + .../common/gui/xcode/tbbExample/main.m | 27 + .../gui/xcode/tbbExample/tbbAppDelegate.h | 33 + .../gui/xcode/tbbExample/tbbAppDelegate.m | 51 + .../xcode/tbbExample/tbbExample-Info.plist | 45 + .../xcode/tbbExample/tbbExample-Prefix.pch | 27 + src/tbb/examples/common/gui/xvideo.cpp | 387 + src/tbb/examples/common/index.html | 39 + src/tbb/examples/common/utility/fast_random.h | 90 + src/tbb/examples/common/utility/utility.h | 396 + .../count_strings/Makefile | 59 + .../count_strings/Makefile.windows | 59 + .../count_strings/count_strings.cpp | 243 + .../count_strings/index.html | 55 + .../count_strings/msvs/count_strings.icproj | 11 + .../count_strings/msvs/count_strings.vcproj | 356 + .../count_strings/msvs/count_strings_cl.sln | 26 + .../count_strings/msvs/count_strings_icl.sln | 33 + .../count_strings.xcodeproj/project.pbxproj | 305 + .../examples/concurrent_hash_map/index.html | 24 + .../shortpath/Makefile | 61 + .../shortpath/Makefile.windows | 58 + .../shortpath/index.html | 82 + .../shortpath/msvs/shortpath.icproj | 11 + .../shortpath/msvs/shortpath.vcproj | 356 + .../shortpath/msvs/shortpath_cl.sln | 25 + .../shortpath/msvs/shortpath_icl.sln | 33 + .../shortpath/shortpath.cpp | 381 + .../xcode/shortpath.xcodeproj/project.pbxproj | 305 + src/tbb/examples/graph/binpack/Makefile | 58 + .../examples/graph/binpack/Makefile.windows | 58 + src/tbb/examples/graph/binpack/binpack.cpp | 310 + src/tbb/examples/graph/binpack/index.html | 72 + .../graph/binpack/msvs/binpack.icproj | 11 + .../graph/binpack/msvs/binpack.vcproj | 356 + .../graph/binpack/msvs/binpack_cl.sln | 25 + .../graph/binpack/msvs/binpack_icl.sln | 33 + .../xcode/binpack.xcodeproj/project.pbxproj | 305 + .../graph/dining_philosophers/Makefile | 55 + .../dining_philosophers/Makefile.windows | 54 + .../dining_philosophers.cpp | 324 + .../graph/dining_philosophers/index.html | 43 + .../msvs/dining_philosophers.icproj | 11 + .../msvs/dining_philosophers.vcproj | 356 + .../msvs/dining_philosophers_cl.sln | 25 + .../msvs/dining_philosophers_icl.sln | 33 + .../project.pbxproj | 305 + src/tbb/examples/graph/index.html | 28 + src/tbb/examples/graph/logic_sim/D_latch.h | 64 + src/tbb/examples/graph/logic_sim/Makefile | 57 + .../examples/graph/logic_sim/Makefile.windows | 61 + src/tbb/examples/graph/logic_sim/basics.h | 543 + .../examples/graph/logic_sim/four_bit_adder.h | 70 + src/tbb/examples/graph/logic_sim/index.html | 67 + .../graph/logic_sim/msvs/logic_sim_cl.sln | 52 + .../graph/logic_sim/msvs/logic_sim_icl.sln | 132 + .../graph/logic_sim/msvs/test_all.icproj | 11 + .../graph/logic_sim/msvs/test_all.vcproj | 356 + .../examples/graph/logic_sim/one_bit_adder.h | 82 + src/tbb/examples/graph/logic_sim/test_all.cpp | 580 + src/tbb/examples/index.html | 181 + src/tbb/examples/parallel_do/index.html | 24 + .../parallel_do/parallel_preorder/Graph.cpp | 109 + .../parallel_do/parallel_preorder/Graph.h | 88 + .../parallel_do/parallel_preorder/Makefile | 59 + .../parallel_preorder/Makefile.windows | 59 + .../parallel_do/parallel_preorder/Matrix.h | 68 + .../parallel_do/parallel_preorder/index.html | 94 + .../parallel_do/parallel_preorder/main.cpp | 101 + .../msvs/parallel_preorder.icproj | 11 + .../msvs/parallel_preorder.vcproj | 378 + .../msvs/parallel_preorder_cl.sln | 25 + .../msvs/parallel_preorder_icl.sln | 33 + .../parallel_preorder/parallel_preorder.cpp | 61 + .../project.pbxproj | 317 + .../parallel_for/game_of_life/Makefile | 53 + .../game_of_life/Makefile.windows | 54 + .../parallel_for/game_of_life/index.html | 54 + .../game_of_life/msvs/Game_of_life.sln | 37 + .../game_of_life/msvs/Game_of_life.vcproj | 794 + .../parallel_for/game_of_life/msvs/app.ico | Bin 0 -> 1078 bytes .../parallel_for/game_of_life/msvs/app.rc | 63 + .../parallel_for/game_of_life/msvs/resource.h | 3 + .../game_of_life/src/AssemblyInfo.cpp | 66 + .../parallel_for/game_of_life/src/Board.h | 115 + .../game_of_life/src/Evolution.cpp | 251 + .../parallel_for/game_of_life/src/Evolution.h | 203 + .../parallel_for/game_of_life/src/Form1.h | 314 + .../game_of_life/src/Game_of_life.cpp | 238 + .../game_of_life/src/Update_state.cpp | 410 + .../game_of_life.xcodeproj/project.pbxproj | 317 + src/tbb/examples/parallel_for/index.html | 30 + .../parallel_for/polygon_overlay/Makefile | 96 + .../polygon_overlay/Makefile.windows | 68 + .../parallel_for/polygon_overlay/index.html | 121 + .../polygon_overlay/msvs/pover.icproj | 11 + .../polygon_overlay/msvs/pover.rc | 61 + .../polygon_overlay/msvs/pover.vcproj | 832 + .../polygon_overlay/msvs/pover_cl.sln | 37 + .../polygon_overlay/msvs/pover_icl.sln | 53 + .../polygon_overlay/msvs/resource.h | 14 + .../parallel_for/polygon_overlay/polymain.cpp | 628 + .../parallel_for/polygon_overlay/polymain.h | 53 + .../parallel_for/polygon_overlay/polyover.cpp | 676 + .../parallel_for/polygon_overlay/polyover.h | 49 + .../polygon_overlay/pover_global.h | 101 + .../polygon_overlay/pover_video.cpp | 178 + .../polygon_overlay/pover_video.h | 72 + .../parallel_for/polygon_overlay/rpolygon.h | 163 + .../parallel_for/polygon_overlay/speedup.gif | Bin 0 -> 7162 bytes .../polygon_overlay.xcodeproj/project.pbxproj | 355 + .../xcschemes/tbbExample.xcscheme | 93 + .../examples/parallel_for/seismic/Makefile | 112 + .../parallel_for/seismic/Makefile.windows | 75 + .../examples/parallel_for/seismic/index.html | 113 + .../examples/parallel_for/seismic/main.cpp | 161 + .../seismic/msvs/SeismicSimulation.ico | Bin 0 -> 23558 bytes .../seismic/msvs/SeismicSimulation.icproj | 11 + .../seismic/msvs/SeismicSimulation.rc | 145 + .../seismic/msvs/SeismicSimulation.vcproj | 836 + .../seismic/msvs/SeismicSimulation_cl.sln | 37 + .../seismic/msvs/SeismicSimulation_icl.sln | 53 + .../parallel_for/seismic/msvs/resource.h | 32 + .../parallel_for/seismic/msvs/small.ico | Bin 0 -> 23558 bytes .../parallel_for/seismic/seismic_video.cpp | 156 + .../parallel_for/seismic/seismic_video.h | 62 + .../parallel_for/seismic/universe.cpp | 233 + .../examples/parallel_for/seismic/universe.h | 120 + .../xcode/seismic.xcodeproj/project.pbxproj | 345 + .../xcschemes/tbbExample.xcscheme | 93 + .../examples/parallel_for/tachyon/Makefile | 190 + .../parallel_for/tachyon/Makefile.windows | 139 + .../parallel_for/tachyon/dat/820spheres.dat | 1671 ++ .../parallel_for/tachyon/dat/balls.dat | 14804 +++++++++++++ .../parallel_for/tachyon/dat/balls3.dat | 14804 +++++++++++++ .../parallel_for/tachyon/dat/lattice.dat | 18012 ++++++++++++++++ .../parallel_for/tachyon/dat/model2.dat | 104 + .../parallel_for/tachyon/dat/teapot.dat | 9279 ++++++++ .../parallel_for/tachyon/dat/trypsin4pti.dat | 538 + .../examples/parallel_for/tachyon/index.html | 219 + .../parallel_for/tachyon/msvs/gui.ico | Bin 0 -> 23558 bytes .../examples/parallel_for/tachyon/msvs/gui.rc | 90 + .../parallel_for/tachyon/msvs/resource.h | 8 + .../parallel_for/tachyon/msvs/small.ico | Bin 0 -> 23558 bytes .../parallel_for/tachyon/msvs/tachyon.icproj | 11 + .../tachyon/msvs/tachyon.serial.icproj | 11 + .../tachyon/msvs/tachyon.serial.vcproj | 695 + .../tachyon/msvs/tachyon.tbb.icproj | 11 + .../tachyon/msvs/tachyon.tbb.vcproj | 731 + .../tachyon/msvs/tachyon.tbb1d.icproj | 11 + .../tachyon/msvs/tachyon.tbb1d.vcproj | 731 + .../parallel_for/tachyon/msvs/tachyon.vcproj | 1046 + .../parallel_for/tachyon/msvs/tachyon_cl.sln | 92 + .../parallel_for/tachyon/msvs/tachyon_icl.sln | 149 + .../examples/parallel_for/tachyon/src/api.cpp | 428 + .../examples/parallel_for/tachyon/src/api.h | 216 + .../parallel_for/tachyon/src/apigeom.cpp | 278 + .../parallel_for/tachyon/src/apitrigeom.cpp | 236 + .../parallel_for/tachyon/src/apitrigeom.h | 68 + .../parallel_for/tachyon/src/bndbox.cpp | 192 + .../parallel_for/tachyon/src/bndbox.h | 82 + .../examples/parallel_for/tachyon/src/box.cpp | 178 + .../examples/parallel_for/tachyon/src/box.h | 77 + .../parallel_for/tachyon/src/camera.cpp | 119 + .../parallel_for/tachyon/src/camera.h | 64 + .../parallel_for/tachyon/src/coordsys.cpp | 106 + .../parallel_for/tachyon/src/coordsys.h | 68 + .../parallel_for/tachyon/src/cylinder.cpp | 281 + .../parallel_for/tachyon/src/cylinder.h | 86 + .../parallel_for/tachyon/src/extvol.cpp | 321 + .../parallel_for/tachyon/src/extvol.h | 81 + .../parallel_for/tachyon/src/global.cpp | 85 + .../parallel_for/tachyon/src/global.h | 76 + .../parallel_for/tachyon/src/grid.cpp | 690 + .../examples/parallel_for/tachyon/src/grid.h | 128 + .../parallel_for/tachyon/src/imageio.cpp | 157 + .../parallel_for/tachyon/src/imageio.h | 73 + .../parallel_for/tachyon/src/imap.cpp | 177 + .../examples/parallel_for/tachyon/src/imap.h | 69 + .../parallel_for/tachyon/src/intersect.cpp | 187 + .../parallel_for/tachyon/src/intersect.h | 75 + .../parallel_for/tachyon/src/jpeg.cpp | 139 + .../examples/parallel_for/tachyon/src/jpeg.h | 64 + .../parallel_for/tachyon/src/light.cpp | 138 + .../examples/parallel_for/tachyon/src/light.h | 79 + .../parallel_for/tachyon/src/machine.h | 74 + .../parallel_for/tachyon/src/macros.h | 87 + .../parallel_for/tachyon/src/main.cpp | 257 + .../parallel_for/tachyon/src/objbound.cpp | 346 + .../parallel_for/tachyon/src/objbound.h | 74 + .../parallel_for/tachyon/src/parse.cpp | 871 + .../examples/parallel_for/tachyon/src/parse.h | 119 + .../parallel_for/tachyon/src/plane.cpp | 115 + .../examples/parallel_for/tachyon/src/plane.h | 80 + .../examples/parallel_for/tachyon/src/ppm.cpp | 138 + .../examples/parallel_for/tachyon/src/ppm.h | 68 + .../parallel_for/tachyon/src/pthread.cpp | 164 + .../parallel_for/tachyon/src/pthread.h | 117 + .../parallel_for/tachyon/src/quadric.cpp | 180 + .../parallel_for/tachyon/src/quadric.h | 83 + .../parallel_for/tachyon/src/render.cpp | 101 + .../parallel_for/tachyon/src/render.h | 65 + .../parallel_for/tachyon/src/ring.cpp | 141 + .../examples/parallel_for/tachyon/src/ring.h | 81 + .../parallel_for/tachyon/src/shade.cpp | 268 + .../examples/parallel_for/tachyon/src/shade.h | 70 + .../parallel_for/tachyon/src/sphere.cpp | 143 + .../parallel_for/tachyon/src/sphere.h | 81 + .../tachyon/src/tachyon_video.cpp | 128 + .../parallel_for/tachyon/src/tachyon_video.h | 70 + .../parallel_for/tachyon/src/texture.cpp | 395 + .../parallel_for/tachyon/src/texture.h | 77 + .../parallel_for/tachyon/src/tgafile.cpp | 245 + .../parallel_for/tachyon/src/tgafile.h | 69 + .../examples/parallel_for/tachyon/src/trace.h | 106 + .../parallel_for/tachyon/src/trace.serial.cpp | 185 + .../parallel_for/tachyon/src/trace.tbb.cpp | 271 + .../parallel_for/tachyon/src/trace.tbb1d.cpp | 213 + .../parallel_for/tachyon/src/trace_rest.cpp | 148 + .../parallel_for/tachyon/src/triangle.cpp | 255 + .../parallel_for/tachyon/src/triangle.h | 102 + .../examples/parallel_for/tachyon/src/types.h | 234 + .../examples/parallel_for/tachyon/src/ui.cpp | 125 + .../examples/parallel_for/tachyon/src/ui.h | 76 + .../parallel_for/tachyon/src/util.cpp | 182 + .../examples/parallel_for/tachyon/src/util.h | 86 + .../parallel_for/tachyon/src/vector.cpp | 144 + .../parallel_for/tachyon/src/vector.h | 76 + .../examples/parallel_for/tachyon/src/vol.cpp | 312 + .../examples/parallel_for/tachyon/src/vol.h | 71 + .../xcode/tachyon.xcodeproj/project.pbxproj | 938 + .../xcschemes/tachyon.serial.xcscheme | 98 + .../xcschemes/tachyon.tbb.xcscheme | 99 + .../xcschemes/tachyon.tbb1d.xcscheme | 99 + .../parallel_reduce/convex_hull/Makefile | 64 + .../convex_hull/Makefile.windows | 63 + .../parallel_reduce/convex_hull/convex_hull.h | 197 + .../convex_hull/convex_hull_bench.cpp | 646 + .../convex_hull/convex_hull_sample.cpp | 309 + .../parallel_reduce/convex_hull/index.html | 52 + .../msvs/convex_hull_benchmark.icproj | 11 + .../msvs/convex_hull_benchmark.vcproj | 366 + .../convex_hull/msvs/convex_hull_cl.sln | 35 + .../convex_hull/msvs/convex_hull_icl.sln | 51 + .../msvs/convex_hull_sample.icproj | 11 + .../msvs/convex_hull_sample.vcproj | 364 + .../convex_hull.xcodeproj/project.pbxproj | 441 + src/tbb/examples/parallel_reduce/index.html | 26 + .../examples/parallel_reduce/primes/Makefile | 69 + .../parallel_reduce/primes/Makefile.windows | 60 + .../parallel_reduce/primes/index.html | 63 + .../examples/parallel_reduce/primes/main.cpp | 132 + .../parallel_reduce/primes/msvs/primes.icproj | 11 + .../parallel_reduce/primes/msvs/primes.vcproj | 364 + .../parallel_reduce/primes/msvs/primes_cl.sln | 25 + .../primes/msvs/primes_icl.sln | 33 + .../parallel_reduce/primes/primes.cpp | 317 + .../examples/parallel_reduce/primes/primes.h | 52 + .../xcode/primes.xcodeproj/project.pbxproj | 311 + src/tbb/examples/pipeline/index.html | 24 + src/tbb/examples/pipeline/square/Makefile | 68 + .../examples/pipeline/square/Makefile.windows | 62 + .../examples/pipeline/square/gen_input.cpp | 44 + src/tbb/examples/pipeline/square/index.html | 71 + .../pipeline/square/msvs/gen_input.icproj | 11 + .../pipeline/square/msvs/gen_input.vcproj | 354 + .../pipeline/square/msvs/square.icproj | 11 + .../pipeline/square/msvs/square.vcproj | 384 + .../pipeline/square/msvs/square.vcproj.user | 37 + .../pipeline/square/msvs/square_cl.sln | 38 + .../pipeline/square/msvs/square_icl.sln | 54 + src/tbb/examples/pipeline/square/square.cpp | 284 + .../xcode/square.xcodeproj/project.pbxproj | 442 + src/tbb/examples/task/index.html | 24 + src/tbb/examples/task/tree_sum/Makefile | 59 + .../examples/task/tree_sum/Makefile.windows | 60 + .../tree_sum/OptimizedParallelSumTree.cpp | 77 + .../examples/task/tree_sum/SerialSumTree.cpp | 38 + .../task/tree_sum/SimpleParallelSumTree.cpp | 70 + src/tbb/examples/task/tree_sum/TreeMaker.h | 124 + src/tbb/examples/task/tree_sum/common.h | 44 + src/tbb/examples/task/tree_sum/index.html | 76 + src/tbb/examples/task/tree_sum/main.cpp | 116 + .../task/tree_sum/msvs/tree_sum.icproj | 11 + .../task/tree_sum/msvs/tree_sum.vcproj | 376 + .../task/tree_sum/msvs/tree_sum_cl.sln | 25 + .../task/tree_sum/msvs/tree_sum_icl.sln | 33 + .../xcode/tree_sum.xcodeproj/project.pbxproj | 325 + src/tbb/examples/task_group/index.html | 23 + src/tbb/examples/task_group/sudoku/Makefile | 72 + .../task_group/sudoku/Makefile.windows | 58 + src/tbb/examples/task_group/sudoku/index.html | 76 + src/tbb/examples/task_group/sudoku/input1 | 19 + src/tbb/examples/task_group/sudoku/input2 | 18 + src/tbb/examples/task_group/sudoku/input3 | 19 + src/tbb/examples/task_group/sudoku/input4 | 19 + .../task_group/sudoku/msvs/sudoku.icproj | 11 + .../task_group/sudoku/msvs/sudoku.vcproj | 356 + .../task_group/sudoku/msvs/sudoku_cl.sln | 25 + .../task_group/sudoku/msvs/sudoku_icl.sln | 33 + src/tbb/examples/task_group/sudoku/sudoku.cpp | 353 + .../xcode/sudoku.xcodeproj/project.pbxproj | 305 + .../examples/task_priority/fractal/Makefile | 93 + .../task_priority/fractal/Makefile.windows | 74 + .../task_priority/fractal/fractal.cpp | 277 + .../examples/task_priority/fractal/fractal.h | 122 + .../task_priority/fractal/fractal_video.h | 80 + .../examples/task_priority/fractal/index.html | 66 + .../examples/task_priority/fractal/main.cpp | 100 + .../task_priority/fractal/msvs/fractal.icproj | 11 + .../task_priority/fractal/msvs/fractal.vcproj | 853 + .../task_priority/fractal/msvs/fractal_cl.sln | 35 + .../fractal/msvs/fractal_icl.sln | 49 + .../task_priority/fractal/msvs/gui.ico | Bin 0 -> 23558 bytes .../task_priority/fractal/msvs/gui.rc | 90 + .../task_priority/fractal/msvs/resource.h | 8 + .../task_priority/fractal/msvs/small.ico | Bin 0 -> 23558 bytes .../xcode/fractal.xcodeproj/project.pbxproj | 349 + .../xcschemes/tbbExample.xcscheme | 93 + src/tbb/examples/task_priority/index.html | 23 + .../examples/test_all/fibonacci/Fibonacci.cpp | 601 + src/tbb/examples/test_all/fibonacci/Makefile | 52 + .../test_all/fibonacci/Makefile.windows | 53 + .../examples/test_all/fibonacci/index.html | 51 + .../test_all/fibonacci/msvs/fibonacci.icproj | 11 + .../test_all/fibonacci/msvs/fibonacci.vcproj | 356 + .../test_all/fibonacci/msvs/fibonacci_cl.sln | 25 + .../test_all/fibonacci/msvs/fibonacci_icl.sln | 33 + .../xcode/fibonacci.xcodeproj/project.pbxproj | 305 + src/tbb/examples/test_all/index.html | 24 + src/tbb/include/index.html | 23 + src/tbb/include/serial/tbb/parallel_for.h | 173 + src/tbb/include/serial/tbb/tbb_annotate.h | 44 + src/tbb/include/tbb/aggregator.h | 210 + src/tbb/include/tbb/aligned_space.h | 55 + src/tbb/include/tbb/atomic.h | 450 + src/tbb/include/tbb/blocked_range.h | 129 + src/tbb/include/tbb/blocked_range2d.h | 97 + src/tbb/include/tbb/blocked_range3d.h | 116 + src/tbb/include/tbb/cache_aligned_allocator.h | 146 + src/tbb/include/tbb/combinable.h | 80 + src/tbb/include/tbb/compat/condition_variable | 465 + src/tbb/include/tbb/compat/ppl.h | 70 + src/tbb/include/tbb/compat/thread | 54 + src/tbb/include/tbb/compat/tuple | 524 + src/tbb/include/tbb/concurrent_hash_map.h | 1336 ++ src/tbb/include/tbb/concurrent_lru_cache.h | 238 + .../include/tbb/concurrent_priority_queue.h | 353 + src/tbb/include/tbb/concurrent_queue.h | 420 + .../include/tbb/concurrent_unordered_map.h | 228 + .../include/tbb/concurrent_unordered_set.h | 177 + src/tbb/include/tbb/concurrent_vector.h | 1063 + src/tbb/include/tbb/critical_section.h | 141 + .../include/tbb/enumerable_thread_specific.h | 995 + src/tbb/include/tbb/flow_graph.h | 1782 ++ src/tbb/include/tbb/index.html | 29 + .../include/tbb/internal/_aggregator_impl.h | 162 + .../tbb/internal/_concurrent_queue_impl.h | 1026 + .../tbb/internal/_concurrent_unordered_impl.h | 1429 ++ .../include/tbb/internal/_flow_graph_impl.h | 580 + .../internal/_flow_graph_item_buffer_impl.h | 190 + .../tbb/internal/_flow_graph_join_impl.h | 1399 ++ .../tbb/internal/_flow_graph_node_impl.h | 470 + .../tbb/internal/_flow_graph_or_impl.h | 270 + .../internal/_flow_graph_tagged_buffer_impl.h | 203 + .../tbb/internal/_flow_graph_types_impl.h | 168 + src/tbb/include/tbb/internal/_tbb_windef.h | 81 + src/tbb/include/tbb/machine/gcc_generic.h | 124 + src/tbb/include/tbb/machine/ibm_aix51.h | 78 + src/tbb/include/tbb/machine/linux_common.h | 91 + src/tbb/include/tbb/machine/linux_ia32.h | 252 + src/tbb/include/tbb/machine/linux_ia64.h | 189 + src/tbb/include/tbb/machine/linux_intel64.h | 158 + src/tbb/include/tbb/machine/mac_ppc.h | 318 + src/tbb/include/tbb/machine/macos_common.h | 145 + src/tbb/include/tbb/machine/sunos_sparc.h | 209 + src/tbb/include/tbb/machine/windows_api.h | 56 + src/tbb/include/tbb/machine/windows_ia32.h | 218 + src/tbb/include/tbb/machine/windows_intel64.h | 145 + src/tbb/include/tbb/machine/xbox360_ppc.h | 127 + src/tbb/include/tbb/memory_pool.h | 269 + src/tbb/include/tbb/mutex.h | 240 + src/tbb/include/tbb/null_mutex.h | 63 + src/tbb/include/tbb/null_rw_mutex.h | 65 + src/tbb/include/tbb/parallel_do.h | 508 + src/tbb/include/tbb/parallel_for.h | 267 + src/tbb/include/tbb/parallel_for_each.h | 77 + src/tbb/include/tbb/parallel_invoke.h | 371 + src/tbb/include/tbb/parallel_reduce.h | 517 + src/tbb/include/tbb/parallel_scan.h | 351 + src/tbb/include/tbb/parallel_sort.h | 231 + src/tbb/include/tbb/parallel_while.h | 194 + src/tbb/include/tbb/partitioner.h | 509 + src/tbb/include/tbb/pipeline.h | 662 + src/tbb/include/tbb/queuing_mutex.h | 131 + src/tbb/include/tbb/queuing_rw_mutex.h | 171 + src/tbb/include/tbb/reader_writer_lock.h | 240 + src/tbb/include/tbb/recursive_mutex.h | 240 + src/tbb/include/tbb/runtime_loader.h | 188 + src/tbb/include/tbb/scalable_allocator.h | 281 + src/tbb/include/tbb/spin_mutex.h | 192 + src/tbb/include/tbb/spin_rw_mutex.h | 227 + src/tbb/include/tbb/task.h | 962 + src/tbb/include/tbb/task_group.h | 252 + src/tbb/include/tbb/task_scheduler_init.h | 147 + src/tbb/include/tbb/task_scheduler_observer.h | 74 + src/tbb/include/tbb/tbb.h | 84 + src/tbb/include/tbb/tbb_allocator.h | 227 + src/tbb/include/tbb/tbb_config.h | 337 + src/tbb/include/tbb/tbb_exception.h | 367 + src/tbb/include/tbb/tbb_machine.h | 875 + src/tbb/include/tbb/tbb_profiling.h | 205 + src/tbb/include/tbb/tbb_stddef.h | 396 + src/tbb/include/tbb/tbb_thread.h | 302 + src/tbb/include/tbb/tbbmalloc_proxy.h | 74 + src/tbb/include/tbb/tick_count.h | 155 + src/tbb/index.html | 43 + src/tbb/src/Makefile | 228 + src/tbb/src/index.html | 76 + src/tbb/src/old/concurrent_queue_v2.cpp | 378 + src/tbb/src/old/concurrent_queue_v2.h | 332 + src/tbb/src/old/concurrent_vector_v2.cpp | 276 + src/tbb/src/old/concurrent_vector_v2.h | 531 + src/tbb/src/old/spin_rw_mutex_v2.cpp | 163 + src/tbb/src/old/spin_rw_mutex_v2.h | 183 + src/tbb/src/old/task_v2.cpp | 46 + src/tbb/src/old/test_concurrent_queue_v2.cpp | 356 + src/tbb/src/old/test_concurrent_vector_v2.cpp | 566 + src/tbb/src/old/test_mutex_v2.cpp | 248 + .../src/perf/coarse_grained_raii_lru_cache.h | 153 + src/tbb/src/perf/fibonacci_cutoff.cpp | 134 + src/tbb/src/perf/fibonacci_impl_tbb.cpp | 86 + src/tbb/src/perf/perf.cpp | 866 + src/tbb/src/perf/perf.h | 265 + src/tbb/src/perf/perf_sched.cpp | 464 + src/tbb/src/perf/run_statistics.sh | 40 + src/tbb/src/perf/statistics.cpp | 452 + src/tbb/src/perf/statistics.h | 199 + src/tbb/src/perf/statistics_xml.h | 208 + src/tbb/src/perf/time_framework.h | 359 + src/tbb/src/perf/time_hash_map.cpp | 268 + src/tbb/src/perf/time_hash_map_fill.cpp | 170 + src/tbb/src/perf/time_hash_map_fill.html | 120 + src/tbb/src/perf/time_locked_work.cpp | 174 + .../src/perf/time_lru_cache_throughput.cpp | 224 + src/tbb/src/perf/time_sandbox.h | 179 + src/tbb/src/perf/time_vector.cpp | 257 + src/tbb/src/rml/client/index.html | 42 + src/tbb/src/rml/client/library_assert.h | 41 + src/tbb/src/rml/client/omp_dynamic_link.cpp | 32 + src/tbb/src/rml/client/omp_dynamic_link.h | 37 + src/tbb/src/rml/client/rml_factory.h | 108 + src/tbb/src/rml/client/rml_omp.cpp | 44 + src/tbb/src/rml/client/rml_tbb.cpp | 46 + src/tbb/src/rml/include/index.html | 29 + src/tbb/src/rml/include/rml_base.h | 196 + src/tbb/src/rml/include/rml_omp.h | 138 + src/tbb/src/rml/include/rml_tbb.h | 108 + src/tbb/src/rml/index.html | 31 + src/tbb/src/rml/perfor/omp_nested.cpp | 152 + src/tbb/src/rml/perfor/omp_simple.cpp | 168 + src/tbb/src/rml/perfor/tbb_multi_omp.cpp | 194 + src/tbb/src/rml/perfor/tbb_simple.cpp | 199 + src/tbb/src/rml/perfor/thread_level.h | 142 + src/tbb/src/rml/server/index.html | 18 + src/tbb/src/rml/server/irml.rc | 126 + src/tbb/src/rml/server/job_automaton.h | 153 + src/tbb/src/rml/server/lin-rml-export.def | 38 + src/tbb/src/rml/server/rml_server.cpp | 3327 +++ src/tbb/src/rml/server/thread_monitor.h | 220 + src/tbb/src/rml/server/wait_counter.h | 81 + src/tbb/src/rml/server/win32-rml-export.def | 35 + src/tbb/src/rml/server/win64-rml-export.def | 35 + src/tbb/src/rml/test/rml_omp_stub.cpp | 71 + src/tbb/src/rml/test/test_job_automaton.cpp | 153 + src/tbb/src/rml/test/test_rml_mixed.cpp | 302 + src/tbb/src/rml/test/test_rml_omp.cpp | 196 + src/tbb/src/rml/test/test_rml_omp_c_linkage.c | 34 + src/tbb/src/rml/test/test_rml_tbb.cpp | 201 + src/tbb/src/rml/test/test_server.h | 452 + src/tbb/src/rml/test/test_thread_monitor.cpp | 119 + src/tbb/src/tbb/arena.cpp | 456 + src/tbb/src/tbb/arena.h | 389 + src/tbb/src/tbb/cache_aligned_allocator.cpp | 263 + src/tbb/src/tbb/cilk-tbb-interop.h | 122 + src/tbb/src/tbb/concurrent_hash_map.cpp | 66 + src/tbb/src/tbb/concurrent_monitor.cpp | 145 + src/tbb/src/tbb/concurrent_monitor.h | 249 + src/tbb/src/tbb/concurrent_queue.cpp | 639 + src/tbb/src/tbb/concurrent_vector.cpp | 604 + src/tbb/src/tbb/condition_variable.cpp | 205 + src/tbb/src/tbb/critical_section.cpp | 39 + src/tbb/src/tbb/custom_scheduler.h | 618 + src/tbb/src/tbb/dynamic_link.cpp | 488 + src/tbb/src/tbb/dynamic_link.h | 123 + src/tbb/src/tbb/governor.cpp | 322 + src/tbb/src/tbb/governor.h | 147 + src/tbb/src/tbb/ia32-masm/atomic_support.asm | 196 + src/tbb/src/tbb/ia32-masm/lock_byte.asm | 46 + src/tbb/src/tbb/ia64-gas/atomic_support.s | 678 + src/tbb/src/tbb/ia64-gas/ia64_misc.s | 107 + src/tbb/src/tbb/ia64-gas/lock_byte.s | 54 + src/tbb/src/tbb/ia64-gas/log2.s | 66 + src/tbb/src/tbb/ia64-gas/pause.s | 41 + src/tbb/src/tbb/ibm_aix51/atomic_support.c | 63 + src/tbb/src/tbb/index.html | 31 + .../src/tbb/intel64-masm/atomic_support.asm | 80 + src/tbb/src/tbb/intel64-masm/intel64_misc.asm | 41 + src/tbb/src/tbb/intrusive_list.h | 252 + src/tbb/src/tbb/itt_notify.cpp | 97 + src/tbb/src/tbb/itt_notify.h | 133 + src/tbb/src/tbb/lin32-tbb-export.def | 57 + src/tbb/src/tbb/lin32-tbb-export.lst | 365 + src/tbb/src/tbb/lin64-tbb-export.def | 54 + src/tbb/src/tbb/lin64-tbb-export.lst | 349 + src/tbb/src/tbb/lin64ipf-tbb-export.def | 56 + src/tbb/src/tbb/lin64ipf-tbb-export.lst | 400 + src/tbb/src/tbb/mac32-tbb-export.def | 23 + src/tbb/src/tbb/mac32-tbb-export.lst | 367 + src/tbb/src/tbb/mac64-tbb-export.def | 23 + src/tbb/src/tbb/mac64-tbb-export.lst | 364 + src/tbb/src/tbb/mailbox.h | 229 + src/tbb/src/tbb/market.cpp | 594 + src/tbb/src/tbb/market.h | 367 + src/tbb/src/tbb/mutex.cpp | 148 + src/tbb/src/tbb/observer_proxy.cpp | 237 + src/tbb/src/tbb/observer_proxy.h | 69 + src/tbb/src/tbb/pipeline.cpp | 790 + src/tbb/src/tbb/private_server.cpp | 401 + src/tbb/src/tbb/queuing_mutex.cpp | 117 + src/tbb/src/tbb/queuing_rw_mutex.cpp | 505 + src/tbb/src/tbb/reader_writer_lock.cpp | 355 + src/tbb/src/tbb/recursive_mutex.cpp | 143 + src/tbb/src/tbb/scheduler.cpp | 1248 ++ src/tbb/src/tbb/scheduler.h | 700 + src/tbb/src/tbb/scheduler_common.h | 293 + src/tbb/src/tbb/scheduler_utility.h | 141 + src/tbb/src/tbb/semaphore.cpp | 101 + src/tbb/src/tbb/semaphore.h | 260 + src/tbb/src/tbb/spin_mutex.cpp | 68 + src/tbb/src/tbb/spin_rw_mutex.cpp | 166 + src/tbb/src/tbb/task.cpp | 271 + src/tbb/src/tbb/task_group_context.cpp | 452 + src/tbb/src/tbb/task_stream.h | 165 + src/tbb/src/tbb/tbb_assert_impl.h | 112 + src/tbb/src/tbb/tbb_main.cpp | 251 + src/tbb/src/tbb/tbb_main.h | 104 + src/tbb/src/tbb/tbb_misc.cpp | 245 + src/tbb/src/tbb/tbb_misc.h | 251 + src/tbb/src/tbb/tbb_misc_ex.cpp | 352 + src/tbb/src/tbb/tbb_resource.rc | 126 + src/tbb/src/tbb/tbb_statistics.cpp | 195 + src/tbb/src/tbb/tbb_statistics.h | 248 + src/tbb/src/tbb/tbb_thread.cpp | 172 + src/tbb/src/tbb/tbb_version.h | 127 + src/tbb/src/tbb/tls.h | 119 + src/tbb/src/tbb/tools_api/disable_warnings.h | 47 + .../src/tbb/tools_api/internal/ittnotify.h | 661 + src/tbb/src/tbb/tools_api/ittnotify.h | 3367 +++ src/tbb/src/tbb/tools_api/ittnotify_config.h | 450 + src/tbb/src/tbb/tools_api/ittnotify_static.c | 1015 + src/tbb/src/tbb/tools_api/ittnotify_static.h | 301 + src/tbb/src/tbb/tools_api/ittnotify_types.h | 81 + src/tbb/src/tbb/tools_api/legacy/ittnotify.h | 983 + .../src/tbb/tools_api/prototype/ittnotify.h | 148 + src/tbb/src/tbb/win32-tbb-export.def | 31 + src/tbb/src/tbb/win32-tbb-export.lst | 300 + src/tbb/src/tbb/win64-gcc-tbb-export.def | 53 + src/tbb/src/tbb/win64-gcc-tbb-export.lst | 350 + src/tbb/src/tbb/win64-tbb-export.def | 26 + src/tbb/src/tbb/win64-tbb-export.lst | 296 + src/tbb/src/tbb/xbox360-tbb-export.def | 234 + src/tbb/src/tbbmalloc/Customize.h | 152 + src/tbb/src/tbbmalloc/MapMemory.h | 129 + src/tbb/src/tbbmalloc/Statistics.h | 137 + src/tbb/src/tbbmalloc/TypeDefinitions.h | 118 + src/tbb/src/tbbmalloc/backend.cpp | 1125 + src/tbb/src/tbbmalloc/backref.cpp | 292 + src/tbb/src/tbbmalloc/frontend.cpp | 2645 +++ src/tbb/src/tbbmalloc/large_objects.cpp | 281 + src/tbb/src/tbbmalloc/lin32-proxy-export.def | 59 + .../src/tbbmalloc/lin32-tbbmalloc-export.def | 80 + src/tbb/src/tbbmalloc/lin64-proxy-export.def | 59 + .../src/tbbmalloc/lin64-tbbmalloc-export.def | 80 + .../src/tbbmalloc/lin64ipf-proxy-export.def | 59 + .../tbbmalloc/lin64ipf-tbbmalloc-export.def | 80 + .../src/tbbmalloc/mac32-tbbmalloc-export.def | 39 + .../src/tbbmalloc/mac64-tbbmalloc-export.def | 39 + src/tbb/src/tbbmalloc/proxy.cpp | 482 + src/tbb/src/tbbmalloc/proxy.h | 72 + .../tbbmalloc/tbb_function_replacement.cpp | 476 + .../src/tbbmalloc/tbb_function_replacement.h | 85 + src/tbb/src/tbbmalloc/tbbmalloc.cpp | 233 + src/tbb/src/tbbmalloc/tbbmalloc.rc | 129 + src/tbb/src/tbbmalloc/tbbmalloc_internal.h | 676 + .../src/tbbmalloc/tbbmalloc_internal_api.h | 45 + .../tbbmalloc/win32-gcc-tbbmalloc-export.def | 56 + .../src/tbbmalloc/win32-tbbmalloc-export.def | 51 + .../tbbmalloc/win64-gcc-tbbmalloc-export.def | 56 + .../src/tbbmalloc/win64-tbbmalloc-export.def | 52 + .../tbbmalloc/xbox360-tbbmalloc-export.def | 42 + src/tbb/src/tbbproxy/tbbproxy-windows.asm | 121 + src/tbb/src/tbbproxy/tbbproxy.cpp | 616 + src/tbb/src/test/harness.h | 546 + src/tbb/src/test/harness_allocator.h | 293 + src/tbb/src/test/harness_assert.h | 48 + src/tbb/src/test/harness_bad_expr.h | 85 + src/tbb/src/test/harness_barrier.h | 84 + .../src/test/harness_concurrency_tracker.h | 85 + src/tbb/src/test/harness_cpu.h | 129 + src/tbb/src/test/harness_defs.h | 50 + src/tbb/src/test/harness_dynamic_libs.h | 85 + src/tbb/src/test/harness_eh.h | 235 + src/tbb/src/test/harness_graph.h | 395 + src/tbb/src/test/harness_inject_scheduler.h | 69 + src/tbb/src/test/harness_iterator.h | 165 + src/tbb/src/test/harness_m128.h | 112 + src/tbb/src/test/harness_memory.h | 106 + src/tbb/src/test/harness_report.h | 178 + src/tbb/src/test/harness_task.h | 63 + src/tbb/src/test/harness_tbb_independence.h | 76 + .../src/test/harness_test_cases_framework.h | 243 + src/tbb/src/test/test_ScalableAllocator.cpp | 184 + .../src/test/test_ScalableAllocator_STL.cpp | 55 + src/tbb/src/test/test_aggregator.cpp | 193 + src/tbb/src/test/test_aligned_space.cpp | 122 + src/tbb/src/test/test_allocator.h | 223 + src/tbb/src/test/test_allocator_STL.h | 116 + src/tbb/src/test/test_assembly.cpp | 152 + src/tbb/src/test/test_atomic.cpp | 1170 + src/tbb/src/test/test_blocked_range.cpp | 128 + src/tbb/src/test/test_blocked_range2d.cpp | 156 + src/tbb/src/test/test_blocked_range3d.cpp | 187 + src/tbb/src/test/test_broadcast_node.cpp | 177 + src/tbb/src/test/test_buffer_node.cpp | 432 + .../src/test/test_cache_aligned_allocator.cpp | 90 + .../test/test_cache_aligned_allocator_STL.cpp | 43 + src/tbb/src/test/test_cilk_common.h | 91 + src/tbb/src/test/test_cilk_dynamic_load.cpp | 164 + src/tbb/src/test/test_cilk_interop.cpp | 162 + src/tbb/src/test/test_combinable.cpp | 459 + src/tbb/src/test/test_concurrent_hash_map.cpp | 955 + .../src/test/test_concurrent_lru_cache.cpp | 412 + src/tbb/src/test/test_concurrent_monitor.cpp | 374 + .../test/test_concurrent_priority_queue.cpp | 471 + src/tbb/src/test/test_concurrent_queue.cpp | 1376 ++ src/tbb/src/test/test_concurrent_queue.h | 98 + .../src/test/test_concurrent_unordered.cpp | 499 + src/tbb/src/test/test_concurrent_vector.cpp | 1025 + src/tbb/src/test/test_condition_variable.h | 695 + src/tbb/src/test/test_continue_node.cpp | 191 + src/tbb/src/test/test_critical_section.cpp | 224 + src/tbb/src/test/test_eh_algorithms.cpp | 1295 ++ src/tbb/src/test/test_eh_flow_graph.cpp | 113 + src/tbb/src/test/test_eh_tasks.cpp | 797 + .../test/test_enumerable_thread_specific.cpp | 1022 + src/tbb/src/test/test_fast_random.cpp | 217 + src/tbb/src/test/test_flow_graph.cpp | 232 + src/tbb/src/test/test_fp.cpp | 208 + src/tbb/src/test/test_function_node.cpp | 437 + src/tbb/src/test/test_halt.cpp | 117 + src/tbb/src/test/test_handle_perror.cpp | 77 + src/tbb/src/test/test_hw_concurrency.cpp | 104 + src/tbb/src/test/test_inits_loop.cpp | 102 + src/tbb/src/test/test_intrusive_list.cpp | 149 + src/tbb/src/test/test_ittnotify.cpp | 98 + src/tbb/src/test/test_join_node.cpp | 1254 ++ src/tbb/src/test/test_lambda.cpp | 251 + src/tbb/src/test/test_limiter_node.cpp | 212 + src/tbb/src/test/test_malloc_atexit.cpp | 94 + src/tbb/src/test/test_malloc_compliance.cpp | 1008 + .../src/test/test_malloc_init_shutdown.cpp | 175 + src/tbb/src/test/test_malloc_lib_unload.cpp | 241 + src/tbb/src/test/test_malloc_overload.cpp | 296 + src/tbb/src/test/test_malloc_pools.cpp | 491 + src/tbb/src/test/test_malloc_pure_c.c | 80 + src/tbb/src/test/test_malloc_regression.cpp | 150 + src/tbb/src/test/test_malloc_used_by_lib.cpp | 173 + src/tbb/src/test/test_malloc_whitebox.cpp | 606 + src/tbb/src/test/test_model_plugin.cpp | 254 + src/tbb/src/test/test_multifunction_node.cpp | 470 + src/tbb/src/test/test_mutex.cpp | 616 + .../src/test/test_mutex_native_threads.cpp | 228 + src/tbb/src/test/test_openmp.cpp | 230 + src/tbb/src/test/test_or_node.cpp | 458 + src/tbb/src/test/test_overwrite_node.cpp | 155 + src/tbb/src/test/test_parallel_do.cpp | 237 + src/tbb/src/test/test_parallel_for.cpp | 487 + src/tbb/src/test/test_parallel_for_each.cpp | 200 + src/tbb/src/test/test_parallel_invoke.cpp | 326 + src/tbb/src/test/test_parallel_pipeline.cpp | 716 + src/tbb/src/test/test_parallel_reduce.cpp | 342 + src/tbb/src/test/test_parallel_scan.cpp | 270 + src/tbb/src/test/test_parallel_sort.cpp | 531 + src/tbb/src/test/test_parallel_while.cpp | 179 + src/tbb/src/test/test_pipeline.cpp | 321 + src/tbb/src/test/test_pipeline_with_tbf.cpp | 493 + src/tbb/src/test/test_priority_queue_node.cpp | 347 + src/tbb/src/test/test_queue_node.cpp | 459 + src/tbb/src/test/test_reader_writer_lock.cpp | 221 + src/tbb/src/test/test_runtime_loader.cpp | 300 + .../src/test/test_rwm_upgrade_downgrade.cpp | 79 + src/tbb/src/test/test_semaphore.cpp | 297 + src/tbb/src/test/test_sequencer_node.cpp | 404 + src/tbb/src/test/test_source_node.cpp | 157 + src/tbb/src/test/test_split_node.cpp | 363 + src/tbb/src/test/test_std_thread.cpp | 41 + src/tbb/src/test/test_task.cpp | 809 + src/tbb/src/test/test_task_assertions.cpp | 118 + src/tbb/src/test/test_task_auto_init.cpp | 210 + src/tbb/src/test/test_task_enqueue.cpp | 329 + src/tbb/src/test/test_task_group.cpp | 859 + src/tbb/src/test/test_task_leaks.cpp | 293 + src/tbb/src/test/test_task_priority.cpp | 481 + src/tbb/src/test/test_task_scheduler_init.cpp | 151 + .../src/test/test_task_scheduler_observer.cpp | 128 + src/tbb/src/test/test_task_steal_limit.cpp | 81 + .../src/test/test_tbb_condition_variable.cpp | 45 + src/tbb/src/test/test_tbb_header.cpp | 212 + src/tbb/src/test/test_tbb_thread.cpp | 40 + src/tbb/src/test/test_tbb_version.cpp | 283 + src/tbb/src/test/test_thread.h | 290 + src/tbb/src/test/test_tick_count.cpp | 148 + src/tbb/src/test/test_tuple.cpp | 164 + src/tbb/src/test/test_write_once_node.cpp | 173 + src/tbb/src/test/test_yield.cpp | 73 + 1190 files changed, 280104 insertions(+) create mode 100644 src/tbb/CHANGES create mode 100644 src/tbb/COPYING create mode 100644 src/tbb/Makefile create mode 100644 src/tbb/README create mode 100644 src/tbb/build/AIX.gcc.inc create mode 100644 src/tbb/build/AIX.inc create mode 100644 src/tbb/build/FreeBSD.gcc.inc create mode 100644 src/tbb/build/FreeBSD.inc create mode 100644 src/tbb/build/Makefile.rml create mode 100644 src/tbb/build/Makefile.tbb create mode 100644 src/tbb/build/Makefile.tbbmalloc create mode 100644 src/tbb/build/Makefile.tbbproxy create mode 100644 src/tbb/build/Makefile.test create mode 100644 src/tbb/build/SunOS.gcc.inc create mode 100644 src/tbb/build/SunOS.inc create mode 100644 src/tbb/build/SunOS.suncc.inc create mode 100644 src/tbb/build/big_iron.inc create mode 100644 src/tbb/build/codecov.txt create mode 100644 src/tbb/build/common.inc create mode 100644 src/tbb/build/common_rules.inc create mode 100644 src/tbb/build/detect.js create mode 100644 src/tbb/build/generate_tbbvars.bat create mode 100644 src/tbb/build/generate_tbbvars.sh create mode 100644 src/tbb/build/index.html create mode 100644 src/tbb/build/linux.gcc.inc create mode 100644 src/tbb/build/linux.icc.inc create mode 100644 src/tbb/build/linux.inc create mode 100644 src/tbb/build/linux.xl.inc create mode 100644 src/tbb/build/macos.clang.inc create mode 100644 src/tbb/build/macos.gcc.inc create mode 100644 src/tbb/build/macos.icc.inc create mode 100644 src/tbb/build/macos.inc create mode 100644 src/tbb/build/suncc.map.pause create mode 100644 src/tbb/build/test_launcher.bat create mode 100644 src/tbb/build/test_launcher.sh create mode 100644 src/tbb/build/version_info_aix.sh create mode 100644 src/tbb/build/version_info_linux.sh create mode 100644 src/tbb/build/version_info_macos.sh create mode 100644 src/tbb/build/version_info_sunos.sh create mode 100644 src/tbb/build/version_info_windows.js create mode 100644 src/tbb/build/vsproject/index.html create mode 100644 src/tbb/build/vsproject/makefile.sln create mode 100644 src/tbb/build/vsproject/tbb.vcproj create mode 100644 src/tbb/build/vsproject/tbbmalloc.vcproj create mode 100644 src/tbb/build/vsproject/tbbmalloc_proxy.vcproj create mode 100644 src/tbb/build/vsproject/version_string.ver create mode 100644 src/tbb/build/windows.cl.inc create mode 100644 src/tbb/build/windows.gcc.inc create mode 100644 src/tbb/build/windows.icl.inc create mode 100644 src/tbb/build/windows.inc create mode 100644 src/tbb/build/xbox360.cl.inc create mode 100644 src/tbb/build/xbox360.inc create mode 100644 src/tbb/doc/Release_Notes.txt create mode 100644 src/tbb/doc/html/a00005.html create mode 100644 src/tbb/doc/html/a00006.html create mode 100644 src/tbb/doc/html/a00007.html create mode 100644 src/tbb/doc/html/a00008.html create mode 100644 src/tbb/doc/html/a00009.html create mode 100644 src/tbb/doc/html/a00010.html create mode 100644 src/tbb/doc/html/a00011.html create mode 100644 src/tbb/doc/html/a00012.html create mode 100644 src/tbb/doc/html/a00013.html create mode 100644 src/tbb/doc/html/a00015.html create mode 100644 src/tbb/doc/html/a00017.html create mode 100644 src/tbb/doc/html/a00018.html create mode 100644 src/tbb/doc/html/a00019.html create mode 100644 src/tbb/doc/html/a00021.html create mode 100644 src/tbb/doc/html/a00022.html create mode 100644 src/tbb/doc/html/a00023.html create mode 100644 src/tbb/doc/html/a00031.html create mode 100644 src/tbb/doc/html/a00035.html create mode 100644 src/tbb/doc/html/a00036.html create mode 100644 src/tbb/doc/html/a00038.html create mode 100644 src/tbb/doc/html/a00044.html create mode 100644 src/tbb/doc/html/a00049.html create mode 100644 src/tbb/doc/html/a00053.html create mode 100644 src/tbb/doc/html/a00054.html create mode 100644 src/tbb/doc/html/a00055.html create mode 100644 src/tbb/doc/html/a00057.html create mode 100644 src/tbb/doc/html/a00060.html create mode 100644 src/tbb/doc/html/a00061.html create mode 100644 src/tbb/doc/html/a00062.html create mode 100644 src/tbb/doc/html/a00063.html create mode 100644 src/tbb/doc/html/a00064.html create mode 100644 src/tbb/doc/html/a00066.html create mode 100644 src/tbb/doc/html/a00068.html create mode 100644 src/tbb/doc/html/a00071.html create mode 100644 src/tbb/doc/html/a00072.html create mode 100644 src/tbb/doc/html/a00074.html create mode 100644 src/tbb/doc/html/a00075.html create mode 100644 src/tbb/doc/html/a00076.html create mode 100644 src/tbb/doc/html/a00077.html create mode 100644 src/tbb/doc/html/a00082.html create mode 100644 src/tbb/doc/html/a00084.html create mode 100644 src/tbb/doc/html/a00086.html create mode 100644 src/tbb/doc/html/a00088.html create mode 100644 src/tbb/doc/html/a00089.html create mode 100644 src/tbb/doc/html/a00090.html create mode 100644 src/tbb/doc/html/a00091.html create mode 100644 src/tbb/doc/html/a00092.html create mode 100644 src/tbb/doc/html/a00093.html create mode 100644 src/tbb/doc/html/a00094.html create mode 100644 src/tbb/doc/html/a00096.html create mode 100644 src/tbb/doc/html/a00097.html create mode 100644 src/tbb/doc/html/a00098.html create mode 100644 src/tbb/doc/html/a00099.html create mode 100644 src/tbb/doc/html/a00100.html create mode 100644 src/tbb/doc/html/a00101.html create mode 100644 src/tbb/doc/html/a00103.html create mode 100644 src/tbb/doc/html/a00104.html create mode 100644 src/tbb/doc/html/a00105.html create mode 100644 src/tbb/doc/html/a00106.html create mode 100644 src/tbb/doc/html/a00107.html create mode 100644 src/tbb/doc/html/a00108.html create mode 100644 src/tbb/doc/html/a00109.html create mode 100644 src/tbb/doc/html/a00110.html create mode 100644 src/tbb/doc/html/a00111.html create mode 100644 src/tbb/doc/html/a00112.html create mode 100644 src/tbb/doc/html/a00113.html create mode 100644 src/tbb/doc/html/a00114.html create mode 100644 src/tbb/doc/html/a00115.html create mode 100644 src/tbb/doc/html/a00116.html create mode 100644 src/tbb/doc/html/a00117.html create mode 100644 src/tbb/doc/html/a00118.html create mode 100644 src/tbb/doc/html/a00119.html create mode 100644 src/tbb/doc/html/a00121.html create mode 100644 src/tbb/doc/html/a00123.html create mode 100644 src/tbb/doc/html/a00125.html create mode 100644 src/tbb/doc/html/a00126.html create mode 100644 src/tbb/doc/html/a00127.html create mode 100644 src/tbb/doc/html/a00128.html create mode 100644 src/tbb/doc/html/a00130.html create mode 100644 src/tbb/doc/html/a00133.html create mode 100644 src/tbb/doc/html/a00134.html create mode 100644 src/tbb/doc/html/a00135.html create mode 100644 src/tbb/doc/html/a00142.html create mode 100644 src/tbb/doc/html/a00144.html create mode 100644 src/tbb/doc/html/a00146.html create mode 100644 src/tbb/doc/html/a00148.html create mode 100644 src/tbb/doc/html/a00150.html create mode 100644 src/tbb/doc/html/a00152.html create mode 100644 src/tbb/doc/html/a00153.html create mode 100644 src/tbb/doc/html/a00154.html create mode 100644 src/tbb/doc/html/a00155.html create mode 100644 src/tbb/doc/html/a00156.html create mode 100644 src/tbb/doc/html/a00157.html create mode 100644 src/tbb/doc/html/a00158.html create mode 100644 src/tbb/doc/html/a00159.html create mode 100644 src/tbb/doc/html/a00160.html create mode 100644 src/tbb/doc/html/a00165.html create mode 100644 src/tbb/doc/html/a00169.html create mode 100644 src/tbb/doc/html/a00170.html create mode 100644 src/tbb/doc/html/a00179.html create mode 100644 src/tbb/doc/html/a00183.html create mode 100644 src/tbb/doc/html/a00184.html create mode 100644 src/tbb/doc/html/a00249.html create mode 100644 src/tbb/doc/html/a00249.png create mode 100644 src/tbb/doc/html/a00250.html create mode 100644 src/tbb/doc/html/a00250.png create mode 100644 src/tbb/doc/html/a00251.html create mode 100644 src/tbb/doc/html/a00251.png create mode 100644 src/tbb/doc/html/a00252.html create mode 100644 src/tbb/doc/html/a00252.png create mode 100644 src/tbb/doc/html/a00253.html create mode 100644 src/tbb/doc/html/a00254.html create mode 100644 src/tbb/doc/html/a00255.html create mode 100644 src/tbb/doc/html/a00256.html create mode 100644 src/tbb/doc/html/a00257.html create mode 100644 src/tbb/doc/html/a00258.html create mode 100644 src/tbb/doc/html/a00259.html create mode 100644 src/tbb/doc/html/a00260.html create mode 100644 src/tbb/doc/html/a00261.html create mode 100644 src/tbb/doc/html/a00262.html create mode 100644 src/tbb/doc/html/a00262.png create mode 100644 src/tbb/doc/html/a00263.html create mode 100644 src/tbb/doc/html/a00263.png create mode 100644 src/tbb/doc/html/a00264.html create mode 100644 src/tbb/doc/html/a00265.html create mode 100644 src/tbb/doc/html/a00266.html create mode 100644 src/tbb/doc/html/a00266.png create mode 100644 src/tbb/doc/html/a00267.html create mode 100644 src/tbb/doc/html/a00268.html create mode 100644 src/tbb/doc/html/a00268.png create mode 100644 src/tbb/doc/html/a00269.html create mode 100644 src/tbb/doc/html/a00270.html create mode 100644 src/tbb/doc/html/a00270.png create mode 100644 src/tbb/doc/html/a00271.html create mode 100644 src/tbb/doc/html/a00272.html create mode 100644 src/tbb/doc/html/a00272.png create mode 100644 src/tbb/doc/html/a00273.html create mode 100644 src/tbb/doc/html/a00274.html create mode 100644 src/tbb/doc/html/a00275.html create mode 100644 src/tbb/doc/html/a00275.png create mode 100644 src/tbb/doc/html/a00276.html create mode 100644 src/tbb/doc/html/a00277.html create mode 100644 src/tbb/doc/html/a00278.html create mode 100644 src/tbb/doc/html/a00278.png create mode 100644 src/tbb/doc/html/a00279.html create mode 100644 src/tbb/doc/html/a00279.png create mode 100644 src/tbb/doc/html/a00280.html create mode 100644 src/tbb/doc/html/a00280.png create mode 100644 src/tbb/doc/html/a00281.html create mode 100644 src/tbb/doc/html/a00282.html create mode 100644 src/tbb/doc/html/a00282.png create mode 100644 src/tbb/doc/html/a00283.html create mode 100644 src/tbb/doc/html/a00284.html create mode 100644 src/tbb/doc/html/a00285.html create mode 100644 src/tbb/doc/html/a00286.html create mode 100644 src/tbb/doc/html/a00286.png create mode 100644 src/tbb/doc/html/a00287.html create mode 100644 src/tbb/doc/html/a00287.png create mode 100644 src/tbb/doc/html/a00288.html create mode 100644 src/tbb/doc/html/a00289.html create mode 100644 src/tbb/doc/html/a00289.png create mode 100644 src/tbb/doc/html/a00290.html create mode 100644 src/tbb/doc/html/a00291.html create mode 100644 src/tbb/doc/html/a00292.html create mode 100644 src/tbb/doc/html/a00292.png create mode 100644 src/tbb/doc/html/a00293.html create mode 100644 src/tbb/doc/html/a00294.html create mode 100644 src/tbb/doc/html/a00295.html create mode 100644 src/tbb/doc/html/a00296.html create mode 100644 src/tbb/doc/html/a00297.html create mode 100644 src/tbb/doc/html/a00298.html create mode 100644 src/tbb/doc/html/a00299.html create mode 100644 src/tbb/doc/html/a00299.png create mode 100644 src/tbb/doc/html/a00300.html create mode 100644 src/tbb/doc/html/a00300.png create mode 100644 src/tbb/doc/html/a00301.html create mode 100644 src/tbb/doc/html/a00302.html create mode 100644 src/tbb/doc/html/a00303.html create mode 100644 src/tbb/doc/html/a00304.html create mode 100644 src/tbb/doc/html/a00305.html create mode 100644 src/tbb/doc/html/a00306.html create mode 100644 src/tbb/doc/html/a00307.html create mode 100644 src/tbb/doc/html/a00308.html create mode 100644 src/tbb/doc/html/a00309.html create mode 100644 src/tbb/doc/html/a00310.html create mode 100644 src/tbb/doc/html/a00311.html create mode 100644 src/tbb/doc/html/a00312.html create mode 100644 src/tbb/doc/html/a00312.png create mode 100644 src/tbb/doc/html/a00313.html create mode 100644 src/tbb/doc/html/a00313.png create mode 100644 src/tbb/doc/html/a00314.html create mode 100644 src/tbb/doc/html/a00315.html create mode 100644 src/tbb/doc/html/a00316.html create mode 100644 src/tbb/doc/html/a00317.html create mode 100644 src/tbb/doc/html/a00318.html create mode 100644 src/tbb/doc/html/a00319.html create mode 100644 src/tbb/doc/html/a00320.html create mode 100644 src/tbb/doc/html/a00321.html create mode 100644 src/tbb/doc/html/a00321.png create mode 100644 src/tbb/doc/html/a00322.html create mode 100644 src/tbb/doc/html/a00323.html create mode 100644 src/tbb/doc/html/a00324.html create mode 100644 src/tbb/doc/html/a00325.html create mode 100644 src/tbb/doc/html/a00326.html create mode 100644 src/tbb/doc/html/a00327.html create mode 100644 src/tbb/doc/html/a00327.png create mode 100644 src/tbb/doc/html/a00328.html create mode 100644 src/tbb/doc/html/a00328.png create mode 100644 src/tbb/doc/html/a00329.html create mode 100644 src/tbb/doc/html/a00330.html create mode 100644 src/tbb/doc/html/a00330.png create mode 100644 src/tbb/doc/html/a00331.html create mode 100644 src/tbb/doc/html/a00332.html create mode 100644 src/tbb/doc/html/a00333.html create mode 100644 src/tbb/doc/html/a00334.html create mode 100644 src/tbb/doc/html/a00335.html create mode 100644 src/tbb/doc/html/a00336.html create mode 100644 src/tbb/doc/html/a00336.png create mode 100644 src/tbb/doc/html/a00337.html create mode 100644 src/tbb/doc/html/a00337.png create mode 100644 src/tbb/doc/html/a00338.html create mode 100644 src/tbb/doc/html/a00339.html create mode 100644 src/tbb/doc/html/a00341.html create mode 100644 src/tbb/doc/html/a00342.html create mode 100644 src/tbb/doc/html/a00343.html create mode 100644 src/tbb/doc/html/a00344.html create mode 100644 src/tbb/doc/html/a00345.html create mode 100644 src/tbb/doc/html/a00345.png create mode 100644 src/tbb/doc/html/a00346.html create mode 100644 src/tbb/doc/html/a00347.html create mode 100644 src/tbb/doc/html/a00348.html create mode 100644 src/tbb/doc/html/a00348.png create mode 100644 src/tbb/doc/html/a00349.html create mode 100644 src/tbb/doc/html/a00350.html create mode 100644 src/tbb/doc/html/a00351.html create mode 100644 src/tbb/doc/html/a00352.html create mode 100644 src/tbb/doc/html/a00353.html create mode 100644 src/tbb/doc/html/a00354.html create mode 100644 src/tbb/doc/html/a00372.html create mode 100644 src/tbb/doc/html/a00373.html create mode 100644 src/tbb/doc/html/a00392.html create mode 100644 src/tbb/doc/html/a00411.html create mode 100644 src/tbb/doc/html/a00414.html create mode 100644 src/tbb/doc/html/a00426.html create mode 100644 src/tbb/doc/html/a00427.html create mode 100644 src/tbb/doc/html/a00428.html create mode 100644 src/tbb/doc/html/a00429.html create mode 100644 src/tbb/doc/html/a00430.html create mode 100644 src/tbb/doc/html/a00431.html create mode 100644 src/tbb/doc/html/a00432.html create mode 100644 src/tbb/doc/html/a00440.html create mode 100644 src/tbb/doc/html/a00441.html create mode 100644 src/tbb/doc/html/a00449.html create mode 100644 src/tbb/doc/html/a00450.html create mode 100644 src/tbb/doc/html/a00451.html create mode 100644 src/tbb/doc/html/a00452.html create mode 100644 src/tbb/doc/html/a00454.html create mode 100644 src/tbb/doc/html/a00455.html create mode 100644 src/tbb/doc/html/a00466.html create mode 100644 src/tbb/doc/html/a00473.html create mode 100644 src/tbb/doc/html/a00476.html create mode 100644 src/tbb/doc/html/a00480.html create mode 100644 src/tbb/doc/html/a00484.html create mode 100644 src/tbb/doc/html/a00487.html create mode 100644 src/tbb/doc/html/a00496.html create mode 100644 src/tbb/doc/html/a00499.html create mode 100644 src/tbb/doc/html/a00511.html create mode 100644 src/tbb/doc/html/a00524.html create mode 100644 src/tbb/doc/html/a00531.html create mode 100644 src/tbb/doc/html/a00533.html create mode 100644 src/tbb/doc/html/a00534.html create mode 100644 src/tbb/doc/html/a00535.html create mode 100644 src/tbb/doc/html/a00544.html create mode 100644 src/tbb/doc/html/a00548.html create mode 100644 src/tbb/doc/html/a00550.html create mode 100644 src/tbb/doc/html/a00556.html create mode 100644 src/tbb/doc/html/a00562.html create mode 100644 src/tbb/doc/html/a00567.html create mode 100644 src/tbb/doc/html/a00571.html create mode 100644 src/tbb/doc/html/a00575.html create mode 100644 src/tbb/doc/html/a00587.html create mode 100644 src/tbb/doc/html/a00603.html create mode 100644 src/tbb/doc/html/a00604.html create mode 100644 src/tbb/doc/html/a00605.html create mode 100644 src/tbb/doc/html/a00606.html create mode 100644 src/tbb/doc/html/a00607.html create mode 100644 src/tbb/doc/html/a00608.html create mode 100644 src/tbb/doc/html/a00611.html create mode 100644 src/tbb/doc/html/a00612.html create mode 100644 src/tbb/doc/html/a00613.html create mode 100644 src/tbb/doc/html/a00623.html create mode 100644 src/tbb/doc/html/a00630.html create mode 100644 src/tbb/doc/html/a00631.html create mode 100644 src/tbb/doc/html/a00633.html create mode 100644 src/tbb/doc/html/a00634.html create mode 100644 src/tbb/doc/html/a00638.html create mode 100644 src/tbb/doc/html/a00639.html create mode 100644 src/tbb/doc/html/a00640.html create mode 100644 src/tbb/doc/html/a00647.html create mode 100644 src/tbb/doc/html/a00648.html create mode 100644 src/tbb/doc/html/a00655.html create mode 100644 src/tbb/doc/html/a00663.html create mode 100644 src/tbb/doc/html/a00665.html create mode 100644 src/tbb/doc/html/annotated.html create mode 100644 src/tbb/doc/html/concepts.html create mode 100644 src/tbb/doc/html/deprecated.html create mode 100644 src/tbb/doc/html/doxygen.css create mode 100644 src/tbb/doc/html/doxygen.png create mode 100644 src/tbb/doc/html/files.html create mode 100644 src/tbb/doc/html/functions.html create mode 100644 src/tbb/doc/html/functions_0x62.html create mode 100644 src/tbb/doc/html/functions_0x63.html create mode 100644 src/tbb/doc/html/functions_0x64.html create mode 100644 src/tbb/doc/html/functions_0x65.html create mode 100644 src/tbb/doc/html/functions_0x66.html create mode 100644 src/tbb/doc/html/functions_0x67.html create mode 100644 src/tbb/doc/html/functions_0x69.html create mode 100644 src/tbb/doc/html/functions_0x6c.html create mode 100644 src/tbb/doc/html/functions_0x6d.html create mode 100644 src/tbb/doc/html/functions_0x6e.html create mode 100644 src/tbb/doc/html/functions_0x6f.html create mode 100644 src/tbb/doc/html/functions_0x70.html create mode 100644 src/tbb/doc/html/functions_0x71.html create mode 100644 src/tbb/doc/html/functions_0x72.html create mode 100644 src/tbb/doc/html/functions_0x73.html create mode 100644 src/tbb/doc/html/functions_0x74.html create mode 100644 src/tbb/doc/html/functions_0x75.html create mode 100644 src/tbb/doc/html/functions_0x76.html create mode 100644 src/tbb/doc/html/functions_0x77.html create mode 100644 src/tbb/doc/html/functions_0x7e.html create mode 100644 src/tbb/doc/html/functions_enum.html create mode 100644 src/tbb/doc/html/functions_eval.html create mode 100644 src/tbb/doc/html/functions_func.html create mode 100644 src/tbb/doc/html/functions_func_0x62.html create mode 100644 src/tbb/doc/html/functions_func_0x63.html create mode 100644 src/tbb/doc/html/functions_func_0x64.html create mode 100644 src/tbb/doc/html/functions_func_0x65.html create mode 100644 src/tbb/doc/html/functions_func_0x66.html create mode 100644 src/tbb/doc/html/functions_func_0x67.html create mode 100644 src/tbb/doc/html/functions_func_0x69.html create mode 100644 src/tbb/doc/html/functions_func_0x6c.html create mode 100644 src/tbb/doc/html/functions_func_0x6d.html create mode 100644 src/tbb/doc/html/functions_func_0x6e.html create mode 100644 src/tbb/doc/html/functions_func_0x6f.html create mode 100644 src/tbb/doc/html/functions_func_0x70.html create mode 100644 src/tbb/doc/html/functions_func_0x71.html create mode 100644 src/tbb/doc/html/functions_func_0x72.html create mode 100644 src/tbb/doc/html/functions_func_0x73.html create mode 100644 src/tbb/doc/html/functions_func_0x74.html create mode 100644 src/tbb/doc/html/functions_func_0x75.html create mode 100644 src/tbb/doc/html/functions_func_0x77.html create mode 100644 src/tbb/doc/html/functions_func_0x7e.html create mode 100644 src/tbb/doc/html/functions_rela.html create mode 100644 src/tbb/doc/html/functions_type.html create mode 100644 src/tbb/doc/html/functions_vars.html create mode 100644 src/tbb/doc/html/globals.html create mode 100644 src/tbb/doc/html/globals_func.html create mode 100644 src/tbb/doc/html/hierarchy.html create mode 100644 src/tbb/doc/html/index.html create mode 100644 src/tbb/doc/html/modules.html create mode 100644 src/tbb/doc/html/namespacemembers.html create mode 100644 src/tbb/doc/html/namespacemembers_enum.html create mode 100644 src/tbb/doc/html/namespacemembers_eval.html create mode 100644 src/tbb/doc/html/namespacemembers_func.html create mode 100644 src/tbb/doc/html/namespaces.html create mode 100644 src/tbb/doc/html/pages.html create mode 100644 src/tbb/doc/html/parallel_do_body_req.html create mode 100644 src/tbb/doc/html/parallel_for_body_req.html create mode 100644 src/tbb/doc/html/parallel_reduce_body_req.html create mode 100644 src/tbb/doc/html/parallel_reduce_lambda_req.html create mode 100644 src/tbb/doc/html/parallel_scan_body_req.html create mode 100644 src/tbb/doc/html/parallel_sort_iter_req.html create mode 100644 src/tbb/doc/html/range_req.html create mode 100644 src/tbb/doc/html/tab_b.gif create mode 100644 src/tbb/doc/html/tab_l.gif create mode 100644 src/tbb/doc/html/tab_r.gif create mode 100644 src/tbb/doc/html/tabs.css create mode 100644 src/tbb/examples/GettingStarted/index.html create mode 100644 src/tbb/examples/GettingStarted/sub_string_finder/Makefile create mode 100644 src/tbb/examples/GettingStarted/sub_string_finder/Makefile.windows create mode 100644 src/tbb/examples/GettingStarted/sub_string_finder/index.html create mode 100644 src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder.icproj create mode 100644 src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder.vcproj create mode 100644 src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_cl.sln create mode 100644 src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_extended.icproj create mode 100644 src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_extended.vcproj create mode 100644 src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_icl.sln create mode 100644 src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_pretty.icproj create mode 100644 src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_pretty.vcproj create mode 100644 src/tbb/examples/GettingStarted/sub_string_finder/sub_string_finder.cpp create mode 100644 src/tbb/examples/GettingStarted/sub_string_finder/sub_string_finder_extended.cpp create mode 100644 src/tbb/examples/GettingStarted/sub_string_finder/sub_string_finder_pretty.cpp create mode 100644 src/tbb/examples/GettingStarted/sub_string_finder/xcode/sub_string_finder.xcodeproj/project.pbxproj create mode 100644 src/tbb/examples/Makefile create mode 100644 src/tbb/examples/common/copy_libraries.bat create mode 100644 src/tbb/examples/common/gui/Makefile.gmake create mode 100644 src/tbb/examples/common/gui/Makefile.win create mode 100644 src/tbb/examples/common/gui/convideo.cpp create mode 100644 src/tbb/examples/common/gui/d2dvideo.cpp create mode 100644 src/tbb/examples/common/gui/ddvideo.cpp create mode 100644 src/tbb/examples/common/gui/dxcheck.bat create mode 100644 src/tbb/examples/common/gui/gdivideo.cpp create mode 100644 src/tbb/examples/common/gui/macvideo.cpp create mode 100644 src/tbb/examples/common/gui/video.h create mode 100644 src/tbb/examples/common/gui/winvideo.h create mode 100644 src/tbb/examples/common/gui/xcode/tbbExample/Info.plist create mode 100644 src/tbb/examples/common/gui/xcode/tbbExample/OpenGLView.h create mode 100644 src/tbb/examples/common/gui/xcode/tbbExample/OpenGLView.m create mode 100644 src/tbb/examples/common/gui/xcode/tbbExample/PkgInfo create mode 100644 src/tbb/examples/common/gui/xcode/tbbExample/en.lproj/InfoPlist.strings create mode 100644 src/tbb/examples/common/gui/xcode/tbbExample/en.lproj/MainMenu.nib create mode 100644 src/tbb/examples/common/gui/xcode/tbbExample/en.lproj/MainMenu.xib create mode 100644 src/tbb/examples/common/gui/xcode/tbbExample/main.m create mode 100644 src/tbb/examples/common/gui/xcode/tbbExample/tbbAppDelegate.h create mode 100644 src/tbb/examples/common/gui/xcode/tbbExample/tbbAppDelegate.m create mode 100644 src/tbb/examples/common/gui/xcode/tbbExample/tbbExample-Info.plist create mode 100644 src/tbb/examples/common/gui/xcode/tbbExample/tbbExample-Prefix.pch create mode 100644 src/tbb/examples/common/gui/xvideo.cpp create mode 100644 src/tbb/examples/common/index.html create mode 100644 src/tbb/examples/common/utility/fast_random.h create mode 100644 src/tbb/examples/common/utility/utility.h create mode 100644 src/tbb/examples/concurrent_hash_map/count_strings/Makefile create mode 100644 src/tbb/examples/concurrent_hash_map/count_strings/Makefile.windows create mode 100644 src/tbb/examples/concurrent_hash_map/count_strings/count_strings.cpp create mode 100644 src/tbb/examples/concurrent_hash_map/count_strings/index.html create mode 100644 src/tbb/examples/concurrent_hash_map/count_strings/msvs/count_strings.icproj create mode 100644 src/tbb/examples/concurrent_hash_map/count_strings/msvs/count_strings.vcproj create mode 100644 src/tbb/examples/concurrent_hash_map/count_strings/msvs/count_strings_cl.sln create mode 100644 src/tbb/examples/concurrent_hash_map/count_strings/msvs/count_strings_icl.sln create mode 100644 src/tbb/examples/concurrent_hash_map/count_strings/xcode/count_strings.xcodeproj/project.pbxproj create mode 100644 src/tbb/examples/concurrent_hash_map/index.html create mode 100644 src/tbb/examples/concurrent_priority_queue/shortpath/Makefile create mode 100644 src/tbb/examples/concurrent_priority_queue/shortpath/Makefile.windows create mode 100644 src/tbb/examples/concurrent_priority_queue/shortpath/index.html create mode 100644 src/tbb/examples/concurrent_priority_queue/shortpath/msvs/shortpath.icproj create mode 100644 src/tbb/examples/concurrent_priority_queue/shortpath/msvs/shortpath.vcproj create mode 100644 src/tbb/examples/concurrent_priority_queue/shortpath/msvs/shortpath_cl.sln create mode 100644 src/tbb/examples/concurrent_priority_queue/shortpath/msvs/shortpath_icl.sln create mode 100644 src/tbb/examples/concurrent_priority_queue/shortpath/shortpath.cpp create mode 100644 src/tbb/examples/concurrent_priority_queue/shortpath/xcode/shortpath.xcodeproj/project.pbxproj create mode 100644 src/tbb/examples/graph/binpack/Makefile create mode 100644 src/tbb/examples/graph/binpack/Makefile.windows create mode 100644 src/tbb/examples/graph/binpack/binpack.cpp create mode 100644 src/tbb/examples/graph/binpack/index.html create mode 100644 src/tbb/examples/graph/binpack/msvs/binpack.icproj create mode 100644 src/tbb/examples/graph/binpack/msvs/binpack.vcproj create mode 100644 src/tbb/examples/graph/binpack/msvs/binpack_cl.sln create mode 100644 src/tbb/examples/graph/binpack/msvs/binpack_icl.sln create mode 100644 src/tbb/examples/graph/binpack/xcode/binpack.xcodeproj/project.pbxproj create mode 100644 src/tbb/examples/graph/dining_philosophers/Makefile create mode 100644 src/tbb/examples/graph/dining_philosophers/Makefile.windows create mode 100644 src/tbb/examples/graph/dining_philosophers/dining_philosophers.cpp create mode 100644 src/tbb/examples/graph/dining_philosophers/index.html create mode 100644 src/tbb/examples/graph/dining_philosophers/msvs/dining_philosophers.icproj create mode 100644 src/tbb/examples/graph/dining_philosophers/msvs/dining_philosophers.vcproj create mode 100644 src/tbb/examples/graph/dining_philosophers/msvs/dining_philosophers_cl.sln create mode 100644 src/tbb/examples/graph/dining_philosophers/msvs/dining_philosophers_icl.sln create mode 100644 src/tbb/examples/graph/dining_philosophers/xcode/dining_philosophers.xcodeproj/project.pbxproj create mode 100644 src/tbb/examples/graph/index.html create mode 100644 src/tbb/examples/graph/logic_sim/D_latch.h create mode 100644 src/tbb/examples/graph/logic_sim/Makefile create mode 100644 src/tbb/examples/graph/logic_sim/Makefile.windows create mode 100644 src/tbb/examples/graph/logic_sim/basics.h create mode 100644 src/tbb/examples/graph/logic_sim/four_bit_adder.h create mode 100644 src/tbb/examples/graph/logic_sim/index.html create mode 100644 src/tbb/examples/graph/logic_sim/msvs/logic_sim_cl.sln create mode 100644 src/tbb/examples/graph/logic_sim/msvs/logic_sim_icl.sln create mode 100644 src/tbb/examples/graph/logic_sim/msvs/test_all.icproj create mode 100644 src/tbb/examples/graph/logic_sim/msvs/test_all.vcproj create mode 100644 src/tbb/examples/graph/logic_sim/one_bit_adder.h create mode 100644 src/tbb/examples/graph/logic_sim/test_all.cpp create mode 100644 src/tbb/examples/index.html create mode 100644 src/tbb/examples/parallel_do/index.html create mode 100644 src/tbb/examples/parallel_do/parallel_preorder/Graph.cpp create mode 100644 src/tbb/examples/parallel_do/parallel_preorder/Graph.h create mode 100644 src/tbb/examples/parallel_do/parallel_preorder/Makefile create mode 100644 src/tbb/examples/parallel_do/parallel_preorder/Makefile.windows create mode 100644 src/tbb/examples/parallel_do/parallel_preorder/Matrix.h create mode 100644 src/tbb/examples/parallel_do/parallel_preorder/index.html create mode 100644 src/tbb/examples/parallel_do/parallel_preorder/main.cpp create mode 100644 src/tbb/examples/parallel_do/parallel_preorder/msvs/parallel_preorder.icproj create mode 100644 src/tbb/examples/parallel_do/parallel_preorder/msvs/parallel_preorder.vcproj create mode 100644 src/tbb/examples/parallel_do/parallel_preorder/msvs/parallel_preorder_cl.sln create mode 100644 src/tbb/examples/parallel_do/parallel_preorder/msvs/parallel_preorder_icl.sln create mode 100644 src/tbb/examples/parallel_do/parallel_preorder/parallel_preorder.cpp create mode 100644 src/tbb/examples/parallel_do/parallel_preorder/xcode/parallel_preorder.xcodeproj/project.pbxproj create mode 100644 src/tbb/examples/parallel_for/game_of_life/Makefile create mode 100644 src/tbb/examples/parallel_for/game_of_life/Makefile.windows create mode 100644 src/tbb/examples/parallel_for/game_of_life/index.html create mode 100644 src/tbb/examples/parallel_for/game_of_life/msvs/Game_of_life.sln create mode 100644 src/tbb/examples/parallel_for/game_of_life/msvs/Game_of_life.vcproj create mode 100644 src/tbb/examples/parallel_for/game_of_life/msvs/app.ico create mode 100644 src/tbb/examples/parallel_for/game_of_life/msvs/app.rc create mode 100644 src/tbb/examples/parallel_for/game_of_life/msvs/resource.h create mode 100644 src/tbb/examples/parallel_for/game_of_life/src/AssemblyInfo.cpp create mode 100644 src/tbb/examples/parallel_for/game_of_life/src/Board.h create mode 100644 src/tbb/examples/parallel_for/game_of_life/src/Evolution.cpp create mode 100644 src/tbb/examples/parallel_for/game_of_life/src/Evolution.h create mode 100644 src/tbb/examples/parallel_for/game_of_life/src/Form1.h create mode 100644 src/tbb/examples/parallel_for/game_of_life/src/Game_of_life.cpp create mode 100644 src/tbb/examples/parallel_for/game_of_life/src/Update_state.cpp create mode 100644 src/tbb/examples/parallel_for/game_of_life/xcode/game_of_life.xcodeproj/project.pbxproj create mode 100644 src/tbb/examples/parallel_for/index.html create mode 100644 src/tbb/examples/parallel_for/polygon_overlay/Makefile create mode 100644 src/tbb/examples/parallel_for/polygon_overlay/Makefile.windows create mode 100644 src/tbb/examples/parallel_for/polygon_overlay/index.html create mode 100644 src/tbb/examples/parallel_for/polygon_overlay/msvs/pover.icproj create mode 100644 src/tbb/examples/parallel_for/polygon_overlay/msvs/pover.rc create mode 100644 src/tbb/examples/parallel_for/polygon_overlay/msvs/pover.vcproj create mode 100644 src/tbb/examples/parallel_for/polygon_overlay/msvs/pover_cl.sln create mode 100644 src/tbb/examples/parallel_for/polygon_overlay/msvs/pover_icl.sln create mode 100644 src/tbb/examples/parallel_for/polygon_overlay/msvs/resource.h create mode 100644 src/tbb/examples/parallel_for/polygon_overlay/polymain.cpp create mode 100644 src/tbb/examples/parallel_for/polygon_overlay/polymain.h create mode 100644 src/tbb/examples/parallel_for/polygon_overlay/polyover.cpp create mode 100644 src/tbb/examples/parallel_for/polygon_overlay/polyover.h create mode 100644 src/tbb/examples/parallel_for/polygon_overlay/pover_global.h create mode 100644 src/tbb/examples/parallel_for/polygon_overlay/pover_video.cpp create mode 100644 src/tbb/examples/parallel_for/polygon_overlay/pover_video.h create mode 100644 src/tbb/examples/parallel_for/polygon_overlay/rpolygon.h create mode 100644 src/tbb/examples/parallel_for/polygon_overlay/speedup.gif create mode 100644 src/tbb/examples/parallel_for/polygon_overlay/xcode/polygon_overlay.xcodeproj/project.pbxproj create mode 100644 src/tbb/examples/parallel_for/polygon_overlay/xcode/polygon_overlay.xcodeproj/xcshareddata/xcschemes/tbbExample.xcscheme create mode 100644 src/tbb/examples/parallel_for/seismic/Makefile create mode 100644 src/tbb/examples/parallel_for/seismic/Makefile.windows create mode 100644 src/tbb/examples/parallel_for/seismic/index.html create mode 100644 src/tbb/examples/parallel_for/seismic/main.cpp create mode 100644 src/tbb/examples/parallel_for/seismic/msvs/SeismicSimulation.ico create mode 100644 src/tbb/examples/parallel_for/seismic/msvs/SeismicSimulation.icproj create mode 100644 src/tbb/examples/parallel_for/seismic/msvs/SeismicSimulation.rc create mode 100644 src/tbb/examples/parallel_for/seismic/msvs/SeismicSimulation.vcproj create mode 100644 src/tbb/examples/parallel_for/seismic/msvs/SeismicSimulation_cl.sln create mode 100644 src/tbb/examples/parallel_for/seismic/msvs/SeismicSimulation_icl.sln create mode 100644 src/tbb/examples/parallel_for/seismic/msvs/resource.h create mode 100644 src/tbb/examples/parallel_for/seismic/msvs/small.ico create mode 100644 src/tbb/examples/parallel_for/seismic/seismic_video.cpp create mode 100644 src/tbb/examples/parallel_for/seismic/seismic_video.h create mode 100644 src/tbb/examples/parallel_for/seismic/universe.cpp create mode 100644 src/tbb/examples/parallel_for/seismic/universe.h create mode 100644 src/tbb/examples/parallel_for/seismic/xcode/seismic.xcodeproj/project.pbxproj create mode 100644 src/tbb/examples/parallel_for/seismic/xcode/seismic.xcodeproj/xcshareddata/xcschemes/tbbExample.xcscheme create mode 100644 src/tbb/examples/parallel_for/tachyon/Makefile create mode 100644 src/tbb/examples/parallel_for/tachyon/Makefile.windows create mode 100644 src/tbb/examples/parallel_for/tachyon/dat/820spheres.dat create mode 100644 src/tbb/examples/parallel_for/tachyon/dat/balls.dat create mode 100644 src/tbb/examples/parallel_for/tachyon/dat/balls3.dat create mode 100644 src/tbb/examples/parallel_for/tachyon/dat/lattice.dat create mode 100644 src/tbb/examples/parallel_for/tachyon/dat/model2.dat create mode 100644 src/tbb/examples/parallel_for/tachyon/dat/teapot.dat create mode 100644 src/tbb/examples/parallel_for/tachyon/dat/trypsin4pti.dat create mode 100644 src/tbb/examples/parallel_for/tachyon/index.html create mode 100644 src/tbb/examples/parallel_for/tachyon/msvs/gui.ico create mode 100644 src/tbb/examples/parallel_for/tachyon/msvs/gui.rc create mode 100644 src/tbb/examples/parallel_for/tachyon/msvs/resource.h create mode 100644 src/tbb/examples/parallel_for/tachyon/msvs/small.ico create mode 100644 src/tbb/examples/parallel_for/tachyon/msvs/tachyon.icproj create mode 100644 src/tbb/examples/parallel_for/tachyon/msvs/tachyon.serial.icproj create mode 100644 src/tbb/examples/parallel_for/tachyon/msvs/tachyon.serial.vcproj create mode 100644 src/tbb/examples/parallel_for/tachyon/msvs/tachyon.tbb.icproj create mode 100644 src/tbb/examples/parallel_for/tachyon/msvs/tachyon.tbb.vcproj create mode 100644 src/tbb/examples/parallel_for/tachyon/msvs/tachyon.tbb1d.icproj create mode 100644 src/tbb/examples/parallel_for/tachyon/msvs/tachyon.tbb1d.vcproj create mode 100644 src/tbb/examples/parallel_for/tachyon/msvs/tachyon.vcproj create mode 100644 src/tbb/examples/parallel_for/tachyon/msvs/tachyon_cl.sln create mode 100644 src/tbb/examples/parallel_for/tachyon/msvs/tachyon_icl.sln create mode 100644 src/tbb/examples/parallel_for/tachyon/src/api.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/api.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/apigeom.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/apitrigeom.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/apitrigeom.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/bndbox.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/bndbox.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/box.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/box.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/camera.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/camera.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/coordsys.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/coordsys.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/cylinder.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/cylinder.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/extvol.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/extvol.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/global.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/global.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/grid.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/grid.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/imageio.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/imageio.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/imap.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/imap.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/intersect.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/intersect.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/jpeg.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/jpeg.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/light.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/light.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/machine.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/macros.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/main.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/objbound.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/objbound.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/parse.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/parse.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/plane.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/plane.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/ppm.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/ppm.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/pthread.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/pthread.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/quadric.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/quadric.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/render.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/render.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/ring.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/ring.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/shade.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/shade.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/sphere.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/sphere.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/tachyon_video.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/tachyon_video.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/texture.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/texture.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/tgafile.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/tgafile.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/trace.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/trace.serial.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/trace.tbb.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/trace.tbb1d.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/trace_rest.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/triangle.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/triangle.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/types.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/ui.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/ui.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/util.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/util.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/vector.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/vector.h create mode 100644 src/tbb/examples/parallel_for/tachyon/src/vol.cpp create mode 100644 src/tbb/examples/parallel_for/tachyon/src/vol.h create mode 100644 src/tbb/examples/parallel_for/tachyon/xcode/tachyon.xcodeproj/project.pbxproj create mode 100644 src/tbb/examples/parallel_for/tachyon/xcode/tachyon.xcodeproj/xcshareddata/xcschemes/tachyon.serial.xcscheme create mode 100644 src/tbb/examples/parallel_for/tachyon/xcode/tachyon.xcodeproj/xcshareddata/xcschemes/tachyon.tbb.xcscheme create mode 100644 src/tbb/examples/parallel_for/tachyon/xcode/tachyon.xcodeproj/xcshareddata/xcschemes/tachyon.tbb1d.xcscheme create mode 100644 src/tbb/examples/parallel_reduce/convex_hull/Makefile create mode 100644 src/tbb/examples/parallel_reduce/convex_hull/Makefile.windows create mode 100644 src/tbb/examples/parallel_reduce/convex_hull/convex_hull.h create mode 100644 src/tbb/examples/parallel_reduce/convex_hull/convex_hull_bench.cpp create mode 100644 src/tbb/examples/parallel_reduce/convex_hull/convex_hull_sample.cpp create mode 100644 src/tbb/examples/parallel_reduce/convex_hull/index.html create mode 100644 src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_benchmark.icproj create mode 100644 src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_benchmark.vcproj create mode 100644 src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_cl.sln create mode 100644 src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_icl.sln create mode 100644 src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_sample.icproj create mode 100644 src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_sample.vcproj create mode 100644 src/tbb/examples/parallel_reduce/convex_hull/xcode/convex_hull.xcodeproj/project.pbxproj create mode 100644 src/tbb/examples/parallel_reduce/index.html create mode 100644 src/tbb/examples/parallel_reduce/primes/Makefile create mode 100644 src/tbb/examples/parallel_reduce/primes/Makefile.windows create mode 100644 src/tbb/examples/parallel_reduce/primes/index.html create mode 100644 src/tbb/examples/parallel_reduce/primes/main.cpp create mode 100644 src/tbb/examples/parallel_reduce/primes/msvs/primes.icproj create mode 100644 src/tbb/examples/parallel_reduce/primes/msvs/primes.vcproj create mode 100644 src/tbb/examples/parallel_reduce/primes/msvs/primes_cl.sln create mode 100644 src/tbb/examples/parallel_reduce/primes/msvs/primes_icl.sln create mode 100644 src/tbb/examples/parallel_reduce/primes/primes.cpp create mode 100644 src/tbb/examples/parallel_reduce/primes/primes.h create mode 100644 src/tbb/examples/parallel_reduce/primes/xcode/primes.xcodeproj/project.pbxproj create mode 100644 src/tbb/examples/pipeline/index.html create mode 100644 src/tbb/examples/pipeline/square/Makefile create mode 100644 src/tbb/examples/pipeline/square/Makefile.windows create mode 100644 src/tbb/examples/pipeline/square/gen_input.cpp create mode 100644 src/tbb/examples/pipeline/square/index.html create mode 100644 src/tbb/examples/pipeline/square/msvs/gen_input.icproj create mode 100644 src/tbb/examples/pipeline/square/msvs/gen_input.vcproj create mode 100644 src/tbb/examples/pipeline/square/msvs/square.icproj create mode 100644 src/tbb/examples/pipeline/square/msvs/square.vcproj create mode 100644 src/tbb/examples/pipeline/square/msvs/square.vcproj.user create mode 100644 src/tbb/examples/pipeline/square/msvs/square_cl.sln create mode 100644 src/tbb/examples/pipeline/square/msvs/square_icl.sln create mode 100644 src/tbb/examples/pipeline/square/square.cpp create mode 100644 src/tbb/examples/pipeline/square/xcode/square.xcodeproj/project.pbxproj create mode 100644 src/tbb/examples/task/index.html create mode 100644 src/tbb/examples/task/tree_sum/Makefile create mode 100644 src/tbb/examples/task/tree_sum/Makefile.windows create mode 100644 src/tbb/examples/task/tree_sum/OptimizedParallelSumTree.cpp create mode 100644 src/tbb/examples/task/tree_sum/SerialSumTree.cpp create mode 100644 src/tbb/examples/task/tree_sum/SimpleParallelSumTree.cpp create mode 100644 src/tbb/examples/task/tree_sum/TreeMaker.h create mode 100644 src/tbb/examples/task/tree_sum/common.h create mode 100644 src/tbb/examples/task/tree_sum/index.html create mode 100644 src/tbb/examples/task/tree_sum/main.cpp create mode 100644 src/tbb/examples/task/tree_sum/msvs/tree_sum.icproj create mode 100644 src/tbb/examples/task/tree_sum/msvs/tree_sum.vcproj create mode 100644 src/tbb/examples/task/tree_sum/msvs/tree_sum_cl.sln create mode 100644 src/tbb/examples/task/tree_sum/msvs/tree_sum_icl.sln create mode 100644 src/tbb/examples/task/tree_sum/xcode/tree_sum.xcodeproj/project.pbxproj create mode 100644 src/tbb/examples/task_group/index.html create mode 100644 src/tbb/examples/task_group/sudoku/Makefile create mode 100644 src/tbb/examples/task_group/sudoku/Makefile.windows create mode 100644 src/tbb/examples/task_group/sudoku/index.html create mode 100644 src/tbb/examples/task_group/sudoku/input1 create mode 100644 src/tbb/examples/task_group/sudoku/input2 create mode 100644 src/tbb/examples/task_group/sudoku/input3 create mode 100644 src/tbb/examples/task_group/sudoku/input4 create mode 100644 src/tbb/examples/task_group/sudoku/msvs/sudoku.icproj create mode 100644 src/tbb/examples/task_group/sudoku/msvs/sudoku.vcproj create mode 100644 src/tbb/examples/task_group/sudoku/msvs/sudoku_cl.sln create mode 100644 src/tbb/examples/task_group/sudoku/msvs/sudoku_icl.sln create mode 100644 src/tbb/examples/task_group/sudoku/sudoku.cpp create mode 100644 src/tbb/examples/task_group/sudoku/xcode/sudoku.xcodeproj/project.pbxproj create mode 100644 src/tbb/examples/task_priority/fractal/Makefile create mode 100644 src/tbb/examples/task_priority/fractal/Makefile.windows create mode 100644 src/tbb/examples/task_priority/fractal/fractal.cpp create mode 100644 src/tbb/examples/task_priority/fractal/fractal.h create mode 100644 src/tbb/examples/task_priority/fractal/fractal_video.h create mode 100644 src/tbb/examples/task_priority/fractal/index.html create mode 100644 src/tbb/examples/task_priority/fractal/main.cpp create mode 100644 src/tbb/examples/task_priority/fractal/msvs/fractal.icproj create mode 100644 src/tbb/examples/task_priority/fractal/msvs/fractal.vcproj create mode 100644 src/tbb/examples/task_priority/fractal/msvs/fractal_cl.sln create mode 100644 src/tbb/examples/task_priority/fractal/msvs/fractal_icl.sln create mode 100644 src/tbb/examples/task_priority/fractal/msvs/gui.ico create mode 100644 src/tbb/examples/task_priority/fractal/msvs/gui.rc create mode 100644 src/tbb/examples/task_priority/fractal/msvs/resource.h create mode 100644 src/tbb/examples/task_priority/fractal/msvs/small.ico create mode 100644 src/tbb/examples/task_priority/fractal/xcode/fractal.xcodeproj/project.pbxproj create mode 100644 src/tbb/examples/task_priority/fractal/xcode/fractal.xcodeproj/xcshareddata/xcschemes/tbbExample.xcscheme create mode 100644 src/tbb/examples/task_priority/index.html create mode 100644 src/tbb/examples/test_all/fibonacci/Fibonacci.cpp create mode 100644 src/tbb/examples/test_all/fibonacci/Makefile create mode 100644 src/tbb/examples/test_all/fibonacci/Makefile.windows create mode 100644 src/tbb/examples/test_all/fibonacci/index.html create mode 100644 src/tbb/examples/test_all/fibonacci/msvs/fibonacci.icproj create mode 100644 src/tbb/examples/test_all/fibonacci/msvs/fibonacci.vcproj create mode 100644 src/tbb/examples/test_all/fibonacci/msvs/fibonacci_cl.sln create mode 100644 src/tbb/examples/test_all/fibonacci/msvs/fibonacci_icl.sln create mode 100644 src/tbb/examples/test_all/fibonacci/xcode/fibonacci.xcodeproj/project.pbxproj create mode 100644 src/tbb/examples/test_all/index.html create mode 100644 src/tbb/include/index.html create mode 100644 src/tbb/include/serial/tbb/parallel_for.h create mode 100644 src/tbb/include/serial/tbb/tbb_annotate.h create mode 100644 src/tbb/include/tbb/aggregator.h create mode 100644 src/tbb/include/tbb/aligned_space.h create mode 100644 src/tbb/include/tbb/atomic.h create mode 100644 src/tbb/include/tbb/blocked_range.h create mode 100644 src/tbb/include/tbb/blocked_range2d.h create mode 100644 src/tbb/include/tbb/blocked_range3d.h create mode 100644 src/tbb/include/tbb/cache_aligned_allocator.h create mode 100644 src/tbb/include/tbb/combinable.h create mode 100644 src/tbb/include/tbb/compat/condition_variable create mode 100644 src/tbb/include/tbb/compat/ppl.h create mode 100644 src/tbb/include/tbb/compat/thread create mode 100644 src/tbb/include/tbb/compat/tuple create mode 100644 src/tbb/include/tbb/concurrent_hash_map.h create mode 100644 src/tbb/include/tbb/concurrent_lru_cache.h create mode 100644 src/tbb/include/tbb/concurrent_priority_queue.h create mode 100644 src/tbb/include/tbb/concurrent_queue.h create mode 100644 src/tbb/include/tbb/concurrent_unordered_map.h create mode 100644 src/tbb/include/tbb/concurrent_unordered_set.h create mode 100644 src/tbb/include/tbb/concurrent_vector.h create mode 100644 src/tbb/include/tbb/critical_section.h create mode 100644 src/tbb/include/tbb/enumerable_thread_specific.h create mode 100644 src/tbb/include/tbb/flow_graph.h create mode 100644 src/tbb/include/tbb/index.html create mode 100644 src/tbb/include/tbb/internal/_aggregator_impl.h create mode 100644 src/tbb/include/tbb/internal/_concurrent_queue_impl.h create mode 100644 src/tbb/include/tbb/internal/_concurrent_unordered_impl.h create mode 100644 src/tbb/include/tbb/internal/_flow_graph_impl.h create mode 100644 src/tbb/include/tbb/internal/_flow_graph_item_buffer_impl.h create mode 100644 src/tbb/include/tbb/internal/_flow_graph_join_impl.h create mode 100644 src/tbb/include/tbb/internal/_flow_graph_node_impl.h create mode 100644 src/tbb/include/tbb/internal/_flow_graph_or_impl.h create mode 100644 src/tbb/include/tbb/internal/_flow_graph_tagged_buffer_impl.h create mode 100644 src/tbb/include/tbb/internal/_flow_graph_types_impl.h create mode 100644 src/tbb/include/tbb/internal/_tbb_windef.h create mode 100644 src/tbb/include/tbb/machine/gcc_generic.h create mode 100644 src/tbb/include/tbb/machine/ibm_aix51.h create mode 100644 src/tbb/include/tbb/machine/linux_common.h create mode 100644 src/tbb/include/tbb/machine/linux_ia32.h create mode 100644 src/tbb/include/tbb/machine/linux_ia64.h create mode 100644 src/tbb/include/tbb/machine/linux_intel64.h create mode 100644 src/tbb/include/tbb/machine/mac_ppc.h create mode 100644 src/tbb/include/tbb/machine/macos_common.h create mode 100644 src/tbb/include/tbb/machine/sunos_sparc.h create mode 100644 src/tbb/include/tbb/machine/windows_api.h create mode 100644 src/tbb/include/tbb/machine/windows_ia32.h create mode 100644 src/tbb/include/tbb/machine/windows_intel64.h create mode 100644 src/tbb/include/tbb/machine/xbox360_ppc.h create mode 100644 src/tbb/include/tbb/memory_pool.h create mode 100644 src/tbb/include/tbb/mutex.h create mode 100644 src/tbb/include/tbb/null_mutex.h create mode 100644 src/tbb/include/tbb/null_rw_mutex.h create mode 100644 src/tbb/include/tbb/parallel_do.h create mode 100644 src/tbb/include/tbb/parallel_for.h create mode 100644 src/tbb/include/tbb/parallel_for_each.h create mode 100644 src/tbb/include/tbb/parallel_invoke.h create mode 100644 src/tbb/include/tbb/parallel_reduce.h create mode 100644 src/tbb/include/tbb/parallel_scan.h create mode 100644 src/tbb/include/tbb/parallel_sort.h create mode 100644 src/tbb/include/tbb/parallel_while.h create mode 100644 src/tbb/include/tbb/partitioner.h create mode 100644 src/tbb/include/tbb/pipeline.h create mode 100644 src/tbb/include/tbb/queuing_mutex.h create mode 100644 src/tbb/include/tbb/queuing_rw_mutex.h create mode 100644 src/tbb/include/tbb/reader_writer_lock.h create mode 100644 src/tbb/include/tbb/recursive_mutex.h create mode 100644 src/tbb/include/tbb/runtime_loader.h create mode 100644 src/tbb/include/tbb/scalable_allocator.h create mode 100644 src/tbb/include/tbb/spin_mutex.h create mode 100644 src/tbb/include/tbb/spin_rw_mutex.h create mode 100644 src/tbb/include/tbb/task.h create mode 100644 src/tbb/include/tbb/task_group.h create mode 100644 src/tbb/include/tbb/task_scheduler_init.h create mode 100644 src/tbb/include/tbb/task_scheduler_observer.h create mode 100644 src/tbb/include/tbb/tbb.h create mode 100644 src/tbb/include/tbb/tbb_allocator.h create mode 100644 src/tbb/include/tbb/tbb_config.h create mode 100644 src/tbb/include/tbb/tbb_exception.h create mode 100644 src/tbb/include/tbb/tbb_machine.h create mode 100644 src/tbb/include/tbb/tbb_profiling.h create mode 100644 src/tbb/include/tbb/tbb_stddef.h create mode 100644 src/tbb/include/tbb/tbb_thread.h create mode 100644 src/tbb/include/tbb/tbbmalloc_proxy.h create mode 100644 src/tbb/include/tbb/tick_count.h create mode 100644 src/tbb/index.html create mode 100644 src/tbb/src/Makefile create mode 100644 src/tbb/src/index.html create mode 100644 src/tbb/src/old/concurrent_queue_v2.cpp create mode 100644 src/tbb/src/old/concurrent_queue_v2.h create mode 100644 src/tbb/src/old/concurrent_vector_v2.cpp create mode 100644 src/tbb/src/old/concurrent_vector_v2.h create mode 100644 src/tbb/src/old/spin_rw_mutex_v2.cpp create mode 100644 src/tbb/src/old/spin_rw_mutex_v2.h create mode 100644 src/tbb/src/old/task_v2.cpp create mode 100644 src/tbb/src/old/test_concurrent_queue_v2.cpp create mode 100644 src/tbb/src/old/test_concurrent_vector_v2.cpp create mode 100644 src/tbb/src/old/test_mutex_v2.cpp create mode 100644 src/tbb/src/perf/coarse_grained_raii_lru_cache.h create mode 100644 src/tbb/src/perf/fibonacci_cutoff.cpp create mode 100644 src/tbb/src/perf/fibonacci_impl_tbb.cpp create mode 100644 src/tbb/src/perf/perf.cpp create mode 100644 src/tbb/src/perf/perf.h create mode 100644 src/tbb/src/perf/perf_sched.cpp create mode 100644 src/tbb/src/perf/run_statistics.sh create mode 100644 src/tbb/src/perf/statistics.cpp create mode 100644 src/tbb/src/perf/statistics.h create mode 100644 src/tbb/src/perf/statistics_xml.h create mode 100644 src/tbb/src/perf/time_framework.h create mode 100644 src/tbb/src/perf/time_hash_map.cpp create mode 100644 src/tbb/src/perf/time_hash_map_fill.cpp create mode 100644 src/tbb/src/perf/time_hash_map_fill.html create mode 100644 src/tbb/src/perf/time_locked_work.cpp create mode 100644 src/tbb/src/perf/time_lru_cache_throughput.cpp create mode 100644 src/tbb/src/perf/time_sandbox.h create mode 100644 src/tbb/src/perf/time_vector.cpp create mode 100644 src/tbb/src/rml/client/index.html create mode 100644 src/tbb/src/rml/client/library_assert.h create mode 100644 src/tbb/src/rml/client/omp_dynamic_link.cpp create mode 100644 src/tbb/src/rml/client/omp_dynamic_link.h create mode 100644 src/tbb/src/rml/client/rml_factory.h create mode 100644 src/tbb/src/rml/client/rml_omp.cpp create mode 100644 src/tbb/src/rml/client/rml_tbb.cpp create mode 100644 src/tbb/src/rml/include/index.html create mode 100644 src/tbb/src/rml/include/rml_base.h create mode 100644 src/tbb/src/rml/include/rml_omp.h create mode 100644 src/tbb/src/rml/include/rml_tbb.h create mode 100644 src/tbb/src/rml/index.html create mode 100644 src/tbb/src/rml/perfor/omp_nested.cpp create mode 100644 src/tbb/src/rml/perfor/omp_simple.cpp create mode 100644 src/tbb/src/rml/perfor/tbb_multi_omp.cpp create mode 100644 src/tbb/src/rml/perfor/tbb_simple.cpp create mode 100644 src/tbb/src/rml/perfor/thread_level.h create mode 100644 src/tbb/src/rml/server/index.html create mode 100644 src/tbb/src/rml/server/irml.rc create mode 100644 src/tbb/src/rml/server/job_automaton.h create mode 100644 src/tbb/src/rml/server/lin-rml-export.def create mode 100644 src/tbb/src/rml/server/rml_server.cpp create mode 100644 src/tbb/src/rml/server/thread_monitor.h create mode 100644 src/tbb/src/rml/server/wait_counter.h create mode 100644 src/tbb/src/rml/server/win32-rml-export.def create mode 100644 src/tbb/src/rml/server/win64-rml-export.def create mode 100644 src/tbb/src/rml/test/rml_omp_stub.cpp create mode 100644 src/tbb/src/rml/test/test_job_automaton.cpp create mode 100644 src/tbb/src/rml/test/test_rml_mixed.cpp create mode 100644 src/tbb/src/rml/test/test_rml_omp.cpp create mode 100644 src/tbb/src/rml/test/test_rml_omp_c_linkage.c create mode 100644 src/tbb/src/rml/test/test_rml_tbb.cpp create mode 100644 src/tbb/src/rml/test/test_server.h create mode 100644 src/tbb/src/rml/test/test_thread_monitor.cpp create mode 100644 src/tbb/src/tbb/arena.cpp create mode 100644 src/tbb/src/tbb/arena.h create mode 100644 src/tbb/src/tbb/cache_aligned_allocator.cpp create mode 100644 src/tbb/src/tbb/cilk-tbb-interop.h create mode 100644 src/tbb/src/tbb/concurrent_hash_map.cpp create mode 100644 src/tbb/src/tbb/concurrent_monitor.cpp create mode 100644 src/tbb/src/tbb/concurrent_monitor.h create mode 100644 src/tbb/src/tbb/concurrent_queue.cpp create mode 100644 src/tbb/src/tbb/concurrent_vector.cpp create mode 100644 src/tbb/src/tbb/condition_variable.cpp create mode 100644 src/tbb/src/tbb/critical_section.cpp create mode 100644 src/tbb/src/tbb/custom_scheduler.h create mode 100644 src/tbb/src/tbb/dynamic_link.cpp create mode 100644 src/tbb/src/tbb/dynamic_link.h create mode 100644 src/tbb/src/tbb/governor.cpp create mode 100644 src/tbb/src/tbb/governor.h create mode 100644 src/tbb/src/tbb/ia32-masm/atomic_support.asm create mode 100644 src/tbb/src/tbb/ia32-masm/lock_byte.asm create mode 100644 src/tbb/src/tbb/ia64-gas/atomic_support.s create mode 100644 src/tbb/src/tbb/ia64-gas/ia64_misc.s create mode 100644 src/tbb/src/tbb/ia64-gas/lock_byte.s create mode 100644 src/tbb/src/tbb/ia64-gas/log2.s create mode 100644 src/tbb/src/tbb/ia64-gas/pause.s create mode 100644 src/tbb/src/tbb/ibm_aix51/atomic_support.c create mode 100644 src/tbb/src/tbb/index.html create mode 100644 src/tbb/src/tbb/intel64-masm/atomic_support.asm create mode 100644 src/tbb/src/tbb/intel64-masm/intel64_misc.asm create mode 100644 src/tbb/src/tbb/intrusive_list.h create mode 100644 src/tbb/src/tbb/itt_notify.cpp create mode 100644 src/tbb/src/tbb/itt_notify.h create mode 100644 src/tbb/src/tbb/lin32-tbb-export.def create mode 100644 src/tbb/src/tbb/lin32-tbb-export.lst create mode 100644 src/tbb/src/tbb/lin64-tbb-export.def create mode 100644 src/tbb/src/tbb/lin64-tbb-export.lst create mode 100644 src/tbb/src/tbb/lin64ipf-tbb-export.def create mode 100644 src/tbb/src/tbb/lin64ipf-tbb-export.lst create mode 100644 src/tbb/src/tbb/mac32-tbb-export.def create mode 100644 src/tbb/src/tbb/mac32-tbb-export.lst create mode 100644 src/tbb/src/tbb/mac64-tbb-export.def create mode 100644 src/tbb/src/tbb/mac64-tbb-export.lst create mode 100644 src/tbb/src/tbb/mailbox.h create mode 100644 src/tbb/src/tbb/market.cpp create mode 100644 src/tbb/src/tbb/market.h create mode 100644 src/tbb/src/tbb/mutex.cpp create mode 100644 src/tbb/src/tbb/observer_proxy.cpp create mode 100644 src/tbb/src/tbb/observer_proxy.h create mode 100644 src/tbb/src/tbb/pipeline.cpp create mode 100644 src/tbb/src/tbb/private_server.cpp create mode 100644 src/tbb/src/tbb/queuing_mutex.cpp create mode 100644 src/tbb/src/tbb/queuing_rw_mutex.cpp create mode 100644 src/tbb/src/tbb/reader_writer_lock.cpp create mode 100644 src/tbb/src/tbb/recursive_mutex.cpp create mode 100644 src/tbb/src/tbb/scheduler.cpp create mode 100644 src/tbb/src/tbb/scheduler.h create mode 100644 src/tbb/src/tbb/scheduler_common.h create mode 100644 src/tbb/src/tbb/scheduler_utility.h create mode 100644 src/tbb/src/tbb/semaphore.cpp create mode 100644 src/tbb/src/tbb/semaphore.h create mode 100644 src/tbb/src/tbb/spin_mutex.cpp create mode 100644 src/tbb/src/tbb/spin_rw_mutex.cpp create mode 100644 src/tbb/src/tbb/task.cpp create mode 100644 src/tbb/src/tbb/task_group_context.cpp create mode 100644 src/tbb/src/tbb/task_stream.h create mode 100644 src/tbb/src/tbb/tbb_assert_impl.h create mode 100644 src/tbb/src/tbb/tbb_main.cpp create mode 100644 src/tbb/src/tbb/tbb_main.h create mode 100644 src/tbb/src/tbb/tbb_misc.cpp create mode 100644 src/tbb/src/tbb/tbb_misc.h create mode 100644 src/tbb/src/tbb/tbb_misc_ex.cpp create mode 100644 src/tbb/src/tbb/tbb_resource.rc create mode 100644 src/tbb/src/tbb/tbb_statistics.cpp create mode 100644 src/tbb/src/tbb/tbb_statistics.h create mode 100644 src/tbb/src/tbb/tbb_thread.cpp create mode 100644 src/tbb/src/tbb/tbb_version.h create mode 100644 src/tbb/src/tbb/tls.h create mode 100644 src/tbb/src/tbb/tools_api/disable_warnings.h create mode 100644 src/tbb/src/tbb/tools_api/internal/ittnotify.h create mode 100644 src/tbb/src/tbb/tools_api/ittnotify.h create mode 100644 src/tbb/src/tbb/tools_api/ittnotify_config.h create mode 100644 src/tbb/src/tbb/tools_api/ittnotify_static.c create mode 100644 src/tbb/src/tbb/tools_api/ittnotify_static.h create mode 100644 src/tbb/src/tbb/tools_api/ittnotify_types.h create mode 100644 src/tbb/src/tbb/tools_api/legacy/ittnotify.h create mode 100644 src/tbb/src/tbb/tools_api/prototype/ittnotify.h create mode 100644 src/tbb/src/tbb/win32-tbb-export.def create mode 100644 src/tbb/src/tbb/win32-tbb-export.lst create mode 100644 src/tbb/src/tbb/win64-gcc-tbb-export.def create mode 100644 src/tbb/src/tbb/win64-gcc-tbb-export.lst create mode 100644 src/tbb/src/tbb/win64-tbb-export.def create mode 100644 src/tbb/src/tbb/win64-tbb-export.lst create mode 100644 src/tbb/src/tbb/xbox360-tbb-export.def create mode 100644 src/tbb/src/tbbmalloc/Customize.h create mode 100644 src/tbb/src/tbbmalloc/MapMemory.h create mode 100644 src/tbb/src/tbbmalloc/Statistics.h create mode 100644 src/tbb/src/tbbmalloc/TypeDefinitions.h create mode 100644 src/tbb/src/tbbmalloc/backend.cpp create mode 100644 src/tbb/src/tbbmalloc/backref.cpp create mode 100644 src/tbb/src/tbbmalloc/frontend.cpp create mode 100644 src/tbb/src/tbbmalloc/large_objects.cpp create mode 100644 src/tbb/src/tbbmalloc/lin32-proxy-export.def create mode 100644 src/tbb/src/tbbmalloc/lin32-tbbmalloc-export.def create mode 100644 src/tbb/src/tbbmalloc/lin64-proxy-export.def create mode 100644 src/tbb/src/tbbmalloc/lin64-tbbmalloc-export.def create mode 100644 src/tbb/src/tbbmalloc/lin64ipf-proxy-export.def create mode 100644 src/tbb/src/tbbmalloc/lin64ipf-tbbmalloc-export.def create mode 100644 src/tbb/src/tbbmalloc/mac32-tbbmalloc-export.def create mode 100644 src/tbb/src/tbbmalloc/mac64-tbbmalloc-export.def create mode 100644 src/tbb/src/tbbmalloc/proxy.cpp create mode 100644 src/tbb/src/tbbmalloc/proxy.h create mode 100644 src/tbb/src/tbbmalloc/tbb_function_replacement.cpp create mode 100644 src/tbb/src/tbbmalloc/tbb_function_replacement.h create mode 100644 src/tbb/src/tbbmalloc/tbbmalloc.cpp create mode 100644 src/tbb/src/tbbmalloc/tbbmalloc.rc create mode 100644 src/tbb/src/tbbmalloc/tbbmalloc_internal.h create mode 100644 src/tbb/src/tbbmalloc/tbbmalloc_internal_api.h create mode 100644 src/tbb/src/tbbmalloc/win32-gcc-tbbmalloc-export.def create mode 100644 src/tbb/src/tbbmalloc/win32-tbbmalloc-export.def create mode 100644 src/tbb/src/tbbmalloc/win64-gcc-tbbmalloc-export.def create mode 100644 src/tbb/src/tbbmalloc/win64-tbbmalloc-export.def create mode 100644 src/tbb/src/tbbmalloc/xbox360-tbbmalloc-export.def create mode 100644 src/tbb/src/tbbproxy/tbbproxy-windows.asm create mode 100644 src/tbb/src/tbbproxy/tbbproxy.cpp create mode 100644 src/tbb/src/test/harness.h create mode 100644 src/tbb/src/test/harness_allocator.h create mode 100644 src/tbb/src/test/harness_assert.h create mode 100644 src/tbb/src/test/harness_bad_expr.h create mode 100644 src/tbb/src/test/harness_barrier.h create mode 100644 src/tbb/src/test/harness_concurrency_tracker.h create mode 100644 src/tbb/src/test/harness_cpu.h create mode 100644 src/tbb/src/test/harness_defs.h create mode 100644 src/tbb/src/test/harness_dynamic_libs.h create mode 100644 src/tbb/src/test/harness_eh.h create mode 100644 src/tbb/src/test/harness_graph.h create mode 100644 src/tbb/src/test/harness_inject_scheduler.h create mode 100644 src/tbb/src/test/harness_iterator.h create mode 100644 src/tbb/src/test/harness_m128.h create mode 100644 src/tbb/src/test/harness_memory.h create mode 100644 src/tbb/src/test/harness_report.h create mode 100644 src/tbb/src/test/harness_task.h create mode 100644 src/tbb/src/test/harness_tbb_independence.h create mode 100644 src/tbb/src/test/harness_test_cases_framework.h create mode 100644 src/tbb/src/test/test_ScalableAllocator.cpp create mode 100644 src/tbb/src/test/test_ScalableAllocator_STL.cpp create mode 100644 src/tbb/src/test/test_aggregator.cpp create mode 100644 src/tbb/src/test/test_aligned_space.cpp create mode 100644 src/tbb/src/test/test_allocator.h create mode 100644 src/tbb/src/test/test_allocator_STL.h create mode 100644 src/tbb/src/test/test_assembly.cpp create mode 100644 src/tbb/src/test/test_atomic.cpp create mode 100644 src/tbb/src/test/test_blocked_range.cpp create mode 100644 src/tbb/src/test/test_blocked_range2d.cpp create mode 100644 src/tbb/src/test/test_blocked_range3d.cpp create mode 100644 src/tbb/src/test/test_broadcast_node.cpp create mode 100644 src/tbb/src/test/test_buffer_node.cpp create mode 100644 src/tbb/src/test/test_cache_aligned_allocator.cpp create mode 100644 src/tbb/src/test/test_cache_aligned_allocator_STL.cpp create mode 100644 src/tbb/src/test/test_cilk_common.h create mode 100644 src/tbb/src/test/test_cilk_dynamic_load.cpp create mode 100644 src/tbb/src/test/test_cilk_interop.cpp create mode 100644 src/tbb/src/test/test_combinable.cpp create mode 100644 src/tbb/src/test/test_concurrent_hash_map.cpp create mode 100644 src/tbb/src/test/test_concurrent_lru_cache.cpp create mode 100644 src/tbb/src/test/test_concurrent_monitor.cpp create mode 100644 src/tbb/src/test/test_concurrent_priority_queue.cpp create mode 100644 src/tbb/src/test/test_concurrent_queue.cpp create mode 100644 src/tbb/src/test/test_concurrent_queue.h create mode 100644 src/tbb/src/test/test_concurrent_unordered.cpp create mode 100644 src/tbb/src/test/test_concurrent_vector.cpp create mode 100644 src/tbb/src/test/test_condition_variable.h create mode 100644 src/tbb/src/test/test_continue_node.cpp create mode 100644 src/tbb/src/test/test_critical_section.cpp create mode 100644 src/tbb/src/test/test_eh_algorithms.cpp create mode 100644 src/tbb/src/test/test_eh_flow_graph.cpp create mode 100644 src/tbb/src/test/test_eh_tasks.cpp create mode 100644 src/tbb/src/test/test_enumerable_thread_specific.cpp create mode 100644 src/tbb/src/test/test_fast_random.cpp create mode 100644 src/tbb/src/test/test_flow_graph.cpp create mode 100644 src/tbb/src/test/test_fp.cpp create mode 100644 src/tbb/src/test/test_function_node.cpp create mode 100644 src/tbb/src/test/test_halt.cpp create mode 100644 src/tbb/src/test/test_handle_perror.cpp create mode 100644 src/tbb/src/test/test_hw_concurrency.cpp create mode 100644 src/tbb/src/test/test_inits_loop.cpp create mode 100644 src/tbb/src/test/test_intrusive_list.cpp create mode 100644 src/tbb/src/test/test_ittnotify.cpp create mode 100644 src/tbb/src/test/test_join_node.cpp create mode 100644 src/tbb/src/test/test_lambda.cpp create mode 100644 src/tbb/src/test/test_limiter_node.cpp create mode 100644 src/tbb/src/test/test_malloc_atexit.cpp create mode 100644 src/tbb/src/test/test_malloc_compliance.cpp create mode 100644 src/tbb/src/test/test_malloc_init_shutdown.cpp create mode 100644 src/tbb/src/test/test_malloc_lib_unload.cpp create mode 100644 src/tbb/src/test/test_malloc_overload.cpp create mode 100644 src/tbb/src/test/test_malloc_pools.cpp create mode 100644 src/tbb/src/test/test_malloc_pure_c.c create mode 100644 src/tbb/src/test/test_malloc_regression.cpp create mode 100644 src/tbb/src/test/test_malloc_used_by_lib.cpp create mode 100644 src/tbb/src/test/test_malloc_whitebox.cpp create mode 100644 src/tbb/src/test/test_model_plugin.cpp create mode 100644 src/tbb/src/test/test_multifunction_node.cpp create mode 100644 src/tbb/src/test/test_mutex.cpp create mode 100644 src/tbb/src/test/test_mutex_native_threads.cpp create mode 100644 src/tbb/src/test/test_openmp.cpp create mode 100644 src/tbb/src/test/test_or_node.cpp create mode 100644 src/tbb/src/test/test_overwrite_node.cpp create mode 100644 src/tbb/src/test/test_parallel_do.cpp create mode 100644 src/tbb/src/test/test_parallel_for.cpp create mode 100644 src/tbb/src/test/test_parallel_for_each.cpp create mode 100644 src/tbb/src/test/test_parallel_invoke.cpp create mode 100644 src/tbb/src/test/test_parallel_pipeline.cpp create mode 100644 src/tbb/src/test/test_parallel_reduce.cpp create mode 100644 src/tbb/src/test/test_parallel_scan.cpp create mode 100644 src/tbb/src/test/test_parallel_sort.cpp create mode 100644 src/tbb/src/test/test_parallel_while.cpp create mode 100644 src/tbb/src/test/test_pipeline.cpp create mode 100644 src/tbb/src/test/test_pipeline_with_tbf.cpp create mode 100644 src/tbb/src/test/test_priority_queue_node.cpp create mode 100644 src/tbb/src/test/test_queue_node.cpp create mode 100644 src/tbb/src/test/test_reader_writer_lock.cpp create mode 100644 src/tbb/src/test/test_runtime_loader.cpp create mode 100644 src/tbb/src/test/test_rwm_upgrade_downgrade.cpp create mode 100644 src/tbb/src/test/test_semaphore.cpp create mode 100644 src/tbb/src/test/test_sequencer_node.cpp create mode 100644 src/tbb/src/test/test_source_node.cpp create mode 100644 src/tbb/src/test/test_split_node.cpp create mode 100644 src/tbb/src/test/test_std_thread.cpp create mode 100644 src/tbb/src/test/test_task.cpp create mode 100644 src/tbb/src/test/test_task_assertions.cpp create mode 100644 src/tbb/src/test/test_task_auto_init.cpp create mode 100644 src/tbb/src/test/test_task_enqueue.cpp create mode 100644 src/tbb/src/test/test_task_group.cpp create mode 100644 src/tbb/src/test/test_task_leaks.cpp create mode 100644 src/tbb/src/test/test_task_priority.cpp create mode 100644 src/tbb/src/test/test_task_scheduler_init.cpp create mode 100644 src/tbb/src/test/test_task_scheduler_observer.cpp create mode 100644 src/tbb/src/test/test_task_steal_limit.cpp create mode 100644 src/tbb/src/test/test_tbb_condition_variable.cpp create mode 100644 src/tbb/src/test/test_tbb_header.cpp create mode 100644 src/tbb/src/test/test_tbb_thread.cpp create mode 100644 src/tbb/src/test/test_tbb_version.cpp create mode 100644 src/tbb/src/test/test_thread.h create mode 100644 src/tbb/src/test/test_tick_count.cpp create mode 100644 src/tbb/src/test/test_tuple.cpp create mode 100644 src/tbb/src/test/test_write_once_node.cpp create mode 100644 src/tbb/src/test/test_yield.cpp diff --git a/src/tbb/CHANGES b/src/tbb/CHANGES new file mode 100644 index 0000000..8fbdbe9 --- /dev/null +++ b/src/tbb/CHANGES @@ -0,0 +1,1264 @@ +TBB 4.0 Update 5 + +Changes (w.r.t. TBB 4.0 Update 4): + +- Parallel pipeline optimization (directly storing small objects in the + interstage data buffers) limited to trivially-copyable types for + C++11 and a short list of types for earlier compilers. +- _VARIADIC_MAX switch is honored for TBB tuple implementation + and flow::graph nodes based on tuple. +- Support of Cocoa framework was added to the GUI examples on Mac OS* X + systems + +Bugs fixed: + +- Fixed a tv_nsec overflow bug in condition_variable::wait_for. +- Fixed execution order of enqueued tasks with different priorities. +- Fixed a bug with task priority changes causing lack of progress + for fire-and-forget tasks when TBB was initialized to use 1 thread. +- Fixed duplicate symbol problem when linking multiple compilation + units that include flow_graph.h on VC 10. + +------------------------------------------------------------------------ +TBB 4.0 Update 4 + +Changes (w.r.t. TBB 4.0 Update 3): + +- The TBB memory allocator transparently supports large pages on Linux. +- A new flow_graph example, logic_sim, was added. +- Support for DirectX* 9 was added to GUI examples. + +Community Preview Features: + +- Added: aggregator, a new concurrency control mechanism. + +Bugs fixed: + +- The abort operation on concurrent_bounded_queue now leaves the queue + in a reusable state. If a bad_alloc or bad_last_alloc exception is + thrown while the queue is recovering from an abort, that exception + will be reported instead of user_abort on the thread on which it + occurred, and the queue will not be reusable. +- Steal limiting heuristic fixed to avoid premature stealing disabling + when large amount of __thread data is allocated on thread stack. +- Fixed a low-probability leak of arenas in the task scheduler. +- In STL-compatible allocator classes, the method construct() was fixed + to comply with C++11 requirements. +- Fixed a bug that prevented creation of fixed-size memory pools + smaller than 2M. +- Significantly reduced the amount of warnings from various compilers. + +Open-source contributions integrated: + +- Multiple improvements by Raf Schietekat. +- Basic support for Clang on Mac OS X* by Blas Rodriguez Somoza. +- Fixes for warnings and corner-case bugs by Blas Rodriguez Somoza + and Edward Lam. + +------------------------------------------------------------------------ +TBB 4.0 Update 3 + +Changes (w.r.t. TBB 4.0 Update 2): + +- Modifications to the low-level API for memory pools: + added support for aligned allocations; + pool policies reworked to allow backward-compatible extensions; + added a policy to not return memory space till destruction; + pool_reset() does not return memory space anymore. +- Class tbb::flow::graph_iterator added to iterate over all nodes + registered with a graph instance. +- multioutput_function_node has been renamed multifunction_node. + multifunction_node and split_node are now fully-supported features. +- For the tagged join node, the policy for try_put of an item with + already existing tag has been defined: the item will be rejected. +- Matching the behavior on Windows, on other platforms the optional + shared libraries (libtbbmalloc, libirml) now are also searched + only in the directory where libtbb is located. +- The platform isolation layer based on GCC built-ins is extended. + +Backward-incompatible API changes: + +- a graph reference parameter is now required to be passed to the + constructors of the following flow graph nodes: overwrite_node, + write_once_node, broadcast_node, and the CPF or_node. +- the following tbb::flow node methods and typedefs have been renamed: + Old New + join_node and or_node: + inputs() -> input_ports() + input_ports_tuple_type -> input_ports_type + multifunction_node and split_node: + ports_type -> output_ports_type + +Bugs fixed: + +- Not all logical processors were utilized on systems with more than + 64 cores split by Windows into several processor groups. + +------------------------------------------------------------------------ +TBB 4.0 Update 2 commercial-aligned release + +Changes (w.r.t. TBB 4.0 Update 1 commercial-aligned release): + +- concurrent_bounded_queue now has an abort() operation that releases + threads involved in pending push or pop operations. The released + threads will receive a tbb::user_abort exception. +- Added Community Preview Feature: concurrent_lru_cache container, + a concurrent implementation of LRU (least-recently-used) cache. + +Bugs fixed: + +- fixed a race condition in the TBB scalable allocator. +- concurrent_queue counter wraparound bug was fixed, which occurred when + the number of push and pop operations exceeded ~>4 billion on IA32. +- fixed races in the TBB scheduler that could put workers asleep too + early, especially in presense of affinitized tasks. + +------------------------------------------------------------------------ +TBB 4.0 Update 1 commercial-aligned release + +Changes (w.r.t. TBB 4.0 commercial-aligned release): + +- Memory leaks fixed in binpack example. +- Improvements and fixes in the TBB allocator. + +------------------------------------------------------------------------ +TBB 4.0 commercial-aligned release + +Changes (w.r.t. TBB 3.0 Update 8 commercial-aligned release): + +- concurrent_priority_queue is now a fully supported feature. + Capacity control methods were removed. +- Flow graph is now a fully supported feature. +- A new memory backend has been implemented in the TBB allocator. + It can reuse freed memory for both small and large objects, and + returns unused memory blocks to the OS more actively. +- Improved partitioning algorithms for parallel_for and parallel_reduce + to better handle load imbalance. +- The convex_hull example has been refactored for reproducible + performance results. +- The major interface version has changed from 5 to 6. + Deprecated interfaces might be removed in future releases. + +Community Preview Features: + +- Added: serial subset, i.e. sequential implementations of TBB generic + algorithms (currently, only provided for parallel_for). +- Preview of new flow graph nodes: + or_node (accepts multiple inputs, forwards each input separately + to all successors), + split_node (accepts tuples, and forwards each element of a tuple + to a corresponding successor), and + multioutput_function_node (accepts one input, and passes the input + and a tuple of output ports to the function body to support outputs + to multiple successors). +- Added: memory pools for more control on memory source, grouping, + and collective deallocation. + +------------------------------------------------------------------------ +TBB 3.0 Update 8 commercial-aligned release + +Changes (w.r.t. TBB 3.0 Update 7 commercial-aligned release): + +- Task priorities become an official feature of TBB, + not community preview as before. +- Atomics API extended, and implementation refactored. +- Added task::set_parent() method. +- Added concurrent_unordered_set container. + +Open-source contributions integrated: + +- PowerPC support by Raf Schietekat. +- Fix of potential task pool overrun and other improvements + in the task scheduler by Raf Schietekat. +- Fix in parallel_for_each to work with std::set in Visual* C++ 2010. + +Community Preview Features: + +- Graph community preview feature was renamed to flow graph. + Multiple improvements in the implementation. + Binpack example was added for the feature. +- A number of improvements to concurrent_priority_queue. + Shortpath example was added for the feature. +- TBB runtime loaded functionality was added (Windows*-only). + It allows to specify which versions of TBB should be used, + as well as to set directories for the library search. +- parallel_deterministic_reduce template function was added. + +------------------------------------------------------------------------ +TBB 3.0 Update 7 commercial-aligned release + +Changes (w.r.t. TBB 3.0 Update 6 commercial-aligned release): + +- Added implementation of the platform isolation layer based on + GCC atomic built-ins; it is supposed to work on any platform + where GCC has these built-ins. + +Community Preview Features: + +- Graph's dining_philosophers example added. +- A number of improvements to graph and concurrent_priority_queue. + + +------------------------------------------------------------------------ +TBB 3.0 Update 6 commercial-aligned release + +Changes (w.r.t. TBB 3.0 Update 5 commercial-aligned release): + +- Added Community Preview feature: task and task group priority, and + Fractal example demonstrating it. +- parallel_pipeline optimized for data items of small and large sizes. +- Graph's join_node is now parametrized with a tuple of up to 10 types. +- Improved performance of concurrent_priority_queue. + +Open-source contributions integrated: + +- Initial NetBSD support by Aleksej Saushev. + +Bugs fixed: + +- Failure to enable interoperability with Intel(R) Cilk(tm) Plus runtime + library, and a crash caused by invoking the interoperability layer + after one of the libraries was unloaded. +- Data race that could result in concurrent_unordered_map structure + corruption after call to clear() method. +- Stack corruption caused by PIC version of 64-bit CAS compiled by Intel + compiler on Linux. +- Inconsistency of exception propagation mode possible when application + built with Microsoft* Visual Studio* 2008 or earlier uses TBB built + with Microsoft* Visual Studio* 2010. +- Affinitizing master thread to a subset of available CPUs after TBB + scheduler was initialized tied all worker threads to the same CPUs. +- Method is_stolen_task() always returned 'false' for affinitized tasks. +- write_once_node and overwrite_node did not immediately send buffered + items to successors + +------------------------------------------------------------------------ +TBB 3.0 Update 5 commercial-aligned release + +Changes (w.r.t. TBB 3.0 Update 4 commercial-aligned release): + +- Added Community Preview feature: graph. +- Added automatic propagation of master thread FPU settings to + TBB worker threads. +- Added a public function to perform a sequentially consistent full + memory fence: tbb::atomic_fence() in tbb/atomic.h. + +Bugs fixed: + +- Data race that could result in scheduler data structures corruption + when using fire-and-forget tasks. +- Potential referencing of destroyed concurrent_hash_map element after + using erase(accessor&A) method with A acquired as const_accessor. +- Fixed a correctness bug in the convex hull example. + +Open-source contributions integrated: + +- Patch for calls to internal::atomic_do_once() by Andrey Semashev. + +------------------------------------------------------------------------ +TBB 3.0 Update 4 commercial-aligned release + +Changes (w.r.t. TBB 3.0 Update 3 commercial-aligned release): + +- Added Community Preview feature: concurrent_priority_queue. +- Fixed library loading to avoid possibility for remote code execution, + see http://www.microsoft.com/technet/security/advisory/2269637.mspx. +- Added support of more than 64 cores for appropriate Microsoft* + Windows* versions. For more details, see + http://msdn.microsoft.com/en-us/library/dd405503.aspx. +- Default number of worker threads is adjusted in accordance with + process affinity mask. + +Bugs fixed: + +- Calls of scalable_* functions from inside the allocator library + caused issues if the functions were overridden by another module. +- A crash occurred if methods run() and wait() were called concurrently + for an empty tbb::task_group (1736). +- The tachyon example exhibited build problems associated with + bug 554339 on Microsoft* Visual Studio* 2010. Project files were + modified as a partial workaround to overcome the problem. See + http://connect.microsoft.com/VisualStudio/feedback/details/554339. + +------------------------------------------------------------------------ +TBB 3.0 Update 3 commercial-aligned release + +Changes (w.r.t. TBB 3.0 Update 2 commercial-aligned release): + +- cache_aligned_allocator class reworked to use scalable_aligned_malloc. +- Improved performance of count() and equal_range() methods + in concurrent_unordered_map. +- Improved implementation of 64-bit atomic loads and stores on 32-bit + platforms, including compilation with VC 7.1. +- Added implementation of atomic operations on top of OSAtomic API + provided by Mac OS* X. +- Removed gratuitous try/catch blocks surrounding thread function calls + in tbb_thread. +- Xcode* projects were added for sudoku and game_of_life examples. +- Xcode* projects were updated to work without TBB framework. + +Bugs fixed: + +- Fixed a data race in task scheduler destruction that on rare occasion + could result in memory corruption. +- Fixed idle spinning in thread bound filters in tbb::pipeline (1670). + +Open-source contributions integrated: + +- MinGW-64 basic support by brsomoza (partially). +- Patch for atomic.h by Andrey Semashev. +- Support for AIX & GCC on PowerPC by Giannis Papadopoulos. +- Various improvements by Raf Schietekat. + +------------------------------------------------------------------------ +TBB 3.0 Update 2 commercial-aligned release + +Changes (w.r.t. TBB 3.0 Update 1 commercial-aligned release): + +- Destructor of tbb::task_group class throws missing_wait exception + if there are tasks running when it is invoked. +- Interoperability layer with Intel Cilk Plus runtime library added + to protect TBB TLS in case of nested usage with Intel Cilk Plus. +- Compilation fix for dependent template names in concurrent_queue. +- Memory allocator code refactored to ease development and maintenance. + +Bugs fixed: + +- Improved interoperability with other Intel software tools on Linux in + case of dynamic replacement of memory allocator (1700) +- Fixed install issues that prevented installation on + Mac OS* X 10.6.4 (1711). + +------------------------------------------------------------------------ +TBB 3.0 Update 1 commercial-aligned release + +Changes (w.r.t. TBB 3.0 commercial-aligned release): + +- Decreased memory fragmentation by allocations bigger than 8K. +- Lazily allocate worker threads, to avoid creating unnecessary stacks. + +Bugs fixed: + +- TBB allocator used much more memory than malloc (1703) - see above. +- Deadlocks happened in some specific initialization scenarios + of the TBB allocator (1701, 1704). +- Regression in enumerable_thread_specific: excessive requirements + for object constructors. +- A bug in construction of parallel_pipeline filters when body instance + was a temporary object. +- Incorrect usage of memory fences on PowerPC and XBOX360 platforms. +- A subtle issue in task group context binding that could result + in cancelation signal being missed by nested task groups. +- Incorrect construction of concurrent_unordered_map if specified + number of buckets is not power of two. +- Broken count() and equal_range() of concurrent_unordered_map. +- Return type of postfix form of operator++ for hash map's iterators. + +------------------------------------------------------------------------ +TBB 3.0 commercial-aligned release + +Changes (w.r.t. TBB 2.2 Update 3 commercial-aligned release): + +- All open-source-release changes down to TBB 2.2 U3 below + were incorporated into this release. + +------------------------------------------------------------------------ +20100406 open-source release + +Changes (w.r.t. 20100310 open-source release): + +- Added support for Microsoft* Visual Studio* 2010, including binaries. +- Added a PDF file with recommended Design Patterns for TBB. +- Added parallel_pipeline function and companion classes and functions + that provide a strongly typed lambda-friendly pipeline interface. +- Reworked enumerable_thread_specific to use a custom implementation of + hash map that is more efficient for ETS usage models. +- Added example for class task_group; see examples/task_group/sudoku. +- Removed two examples, as they were long outdated and superceded: + pipeline/text_filter (use pipeline/square); + parallel_while/parallel_preorder (use parallel_do/parallel_preorder). +- PDF documentation updated. +- Other fixes and changes in code, tests, and examples. + +Bugs fixed: + +- Eliminated build errors with MinGW32. +- Fixed post-build step and other issues in VS projects for examples. +- Fixed discrepancy between scalable_realloc and scalable_msize that + caused crashes with malloc replacement on Windows. + +------------------------------------------------------------------------ +20100310 open-source release + +Changes (w.r.t. TBB 2.2 Update 3 commercial-aligned release): + +- Version macros changed in anticipation of a future release. +- Directory structure aligned with Intel(R) C++ Compiler; + now TBB binaries reside in //[bin|lib] + (in TBB 2.x, it was [bin|lib]//). +- Visual Studio projects changed for examples: instead of separate set + of files for each VS version, now there is single 'msvs' directory + that contains workspaces for MS C++ compiler (_cl.sln) and + Intel C++ compiler (_icl.sln). Works with VS 2005 and above. +- The name versioning scheme for backward compatibility was improved; + now compatibility-breaking changes are done in a separate namespace. +- Added concurrent_unordered_map implementation based on a prototype + developed in Microsoft for a future version of PPL. +- Added PPL-compatible writer-preference RW lock (reader_writer_lock). +- Added TBB_IMPLEMENT_CPP0X macro to control injection of C++0x names + implemented in TBB into namespace std. +- Added almost-C++0x-compatible std::condition_variable, plus a bunch + of other C++0x classes required by condition_variable. +- With TBB_IMPLEMENT_CPP0X, tbb_thread can be also used as std::thread. +- task.cpp was split into several translation units to structure + TBB scheduler sources layout. Static data layout and library + initialization logic were also updated. +- TBB scheduler reworked to prevent master threads from stealing + work belonging to other masters. +- Class task was extended with enqueue() method, and slightly changed + semantics of methods spawn() and destroy(). For exact semantics, + refer to TBB Reference manual. +- task_group_context now allows for destruction by non-owner threads. +- Added TBB_USE_EXCEPTIONS macro to control use of exceptions in TBB + headers. It turns off (i.e. sets to 0) automatically if specified + compiler options disable exception handling. +- TBB is enabled to run on top of Microsoft's Concurrency Runtime + on Windows* 7 (via our worker dispatcher known as RML). +- Removed old unused busy-waiting code in concurrent_queue. +- Described the advanced build & test options in src/index.html. +- Warning level for GCC raised with -Wextra and a few other options. +- Multiple fixes and improvements in code, tests, examples, and docs. + +Open-source contributions integrated: + +- Xbox support by Roman Lut (Deep Shadows), though further changes are + required to make it working; e.g. post-2.1 entry points are missing. +- "Eventcount" by Dmitry Vyukov evolved into concurrent_monitor, + an internal class used in the implementation of concurrent_queue. + +------------------------------------------------------------------------ +TBB 2.2 Update 3 commercial-aligned release + +Changes (w.r.t. TBB 2.2 Update 2 commercial-aligned release): + +- PDF documentation updated. + +Bugs fixed: + +- concurrent_hash_map compatibility issue exposed on Linux in case + two versions of the container were used by different modules. +- enforce 16 byte stack alignment for consistence with GCC; required + to work correctly with 128-bit variables processed by SSE. +- construct() methods of allocator classes now use global operator new. + +------------------------------------------------------------------------ +TBB 2.2 Update 2 commercial-aligned release + +Changes (w.r.t. TBB 2.2 Update 1 commercial-aligned release): + +- parallel_invoke and parallel_for_each now take function objects + by const reference, not by value. +- Building TBB with /MT is supported, to avoid dependency on particular + versions of Visual C++* runtime DLLs. TBB DLLs built with /MT + are located in vc_mt directory. +- Class critical_section introduced. +- Improvements in exception support: new exception classes introduced, + all exceptions are thrown via an out-of-line internal method. +- Improvements and fixes in the TBB allocator and malloc replacement, + including robust memory identification, and more reliable dynamic + function substitution on Windows*. +- Method swap() added to class tbb_thread. +- Methods rehash() and bucket_count() added to concurrent_hash_map. +- Added support for Visual Studio* 2010 Beta2. No special binaries + provided, but CRT-independent DLLs (vc_mt) should work. +- Other fixes and improvements in code, tests, examples, and docs. + +Open-source contributions integrated: + +- The fix to build 32-bit TBB on Mac OS* X 10.6. +- GCC-based port for SPARC Solaris by Michailo Matijkiw, with use of + earlier work by Raf Schietekat. + +Bugs fixed: + +- 159 - TBB build for PowerPC* running Mac OS* X. +- 160 - IBM* Java segfault if used with TBB allocator. +- crash in concurrent_queue (1616). + +------------------------------------------------------------------------ +TBB 2.2 Update 1 commercial-aligned release + +Changes (w.r.t. TBB 2.2 commercial-aligned release): + +- Incorporates all changes from open-source releases below. +- Documentation was updated. +- TBB scheduler auto-initialization now covers all possible use cases. +- concurrent_queue: made argument types of sizeof used in paddings + consistent with those actually used. +- Memory allocator was improved: supported corner case of user's malloc + calling scalable_malloc (non-Windows), corrected processing of + memory allocation requests during tbb memory allocator startup + (Linux). +- Windows malloc replacement has got better support for static objects. +- In pipeline setups that do not allow actual parallelism, execution + by a single thread is guaranteed, idle spinning eliminated, and + performance improved. +- RML refactoring and clean-up. +- New constructor for concurrent_hash_map allows reserving space for + a number of items. +- Operator delete() added to the TBB exception classes. +- Lambda support was improved in parallel_reduce. +- gcc 4.3 warnings were fixed for concurrent_queue. +- Fixed possible initialization deadlock in modules using TBB entities + during construction of global static objects. +- Copy constructor in concurrent_hash_map was fixed. +- Fixed a couple of rare crashes in the scheduler possible before + in very specific use cases. +- Fixed a rare crash in the TBB allocator running out of memory. +- New tests were implemented, including test_lambda.cpp that checks + support for lambda expressions. +- A few other small changes in code, tests, and documentation. + +------------------------------------------------------------------------ +20090809 open-source release + +Changes (w.r.t. TBB 2.2 commercial-aligned release): + +- Fixed known exception safety issues in concurrent_vector. +- Better concurrency of simultaneous grow requests in concurrent_vector. +- TBB allocator further improves performance of large object allocation. +- Problem with source of text relocations was fixed on Linux +- Fixed bugs related to malloc replacement under Windows +- A few other small changes in code and documentation. + +------------------------------------------------------------------------ +TBB 2.2 commercial-aligned release + +Changes (w.r.t. TBB 2.1 U4 commercial-aligned release): + +- Incorporates all changes from open-source releases below. +- Architecture folders renamed from em64t to intel64 and from itanium + to ia64. +- Major Interface version changed from 3 to 4. Deprecated interfaces + might be removed in future releases. +- Parallel algorithms that use partitioners have switched to use + the auto_partitioner by default. +- Improved memory allocator performance for allocations bigger than 8K. +- Added new thread-bound filters functionality for pipeline. +- New implementation of concurrent_hash_map that improves performance + significantly. +- A few other small changes in code and documentation. + +------------------------------------------------------------------------ +20090511 open-source release + +Changes (w.r.t. previous open-source release): + +- Basic support for MinGW32 development kit. +- Added tbb::zero_allocator class that initializes memory with zeros. + It can be used as an adaptor to any STL-compatible allocator class. +- Added tbb::parallel_for_each template function as alias to parallel_do. +- Added more overloads for tbb::parallel_for. +- Added support for exact exception propagation (can only be used with + compilers that support C++0x std::exception_ptr). +- tbb::atomic template class can be used with enumerations. +- mutex, recursive_mutex, spin_mutex, spin_rw_mutex classes extended + with explicit lock/unlock methods. +- Fixed size() and grow_to_at_least() methods of tbb::concurrent_vector + to provide space allocation guarantees. More methods added for + compatibility with std::vector, including some from C++0x. +- Preview of a lambda-friendly interface for low-level use of tasks. +- scalable_msize function added to the scalable allocator (Windows only). +- Rationalized internal auxiliary functions for spin-waiting and backoff. +- Several tests undergo decent refactoring. + +Changes affecting backward compatibility: + +- Improvements in concurrent_queue, including limited API changes. + The previous version is deprecated; its functionality is accessible + via methods of the new tbb::concurrent_bounded_queue class. +- grow* and push_back methods of concurrent_vector changed to return + iterators; old semantics is deprecated. + +------------------------------------------------------------------------ +TBB 2.1 Update 4 commercial-aligned release + +Changes (w.r.t. TBB 2.1 U3 commercial-aligned release): + +- Added tests for aligned memory allocations and malloc replacement. +- Several improvements for better bundling with Intel(R) C++ Compiler. +- A few other small changes in code and documentaion. + +Bugs fixed: + +- 150 - request to build TBB examples with debug info in release mode. +- backward compatibility issue with concurrent_queue on Windows. +- dependency on VS 2005 SP1 runtime libraries removed. +- compilation of GUI examples under Xcode* 3.1 (1577). +- On Windows, TBB allocator classes can be instantiated with const types + for compatibility with MS implementation of STL containers (1566). + +------------------------------------------------------------------------ +20090313 open-source release + +Changes (w.r.t. 20081109 open-source release): + +- Includes all changes introduced in TBB 2.1 Update 2 & Update 3 + commercial-aligned releases (see below for details). +- Added tbb::parallel_invoke template function. It runs up to 10 + user-defined functions in parallel and waits for them to complete. +- Added a special library providing ability to replace the standard + memory allocation routines in Microsoft* C/C++ RTL (malloc/free, + global new/delete, etc.) with the TBB memory allocator. + Usage details are described in include/tbb/tbbmalloc_proxy.h file. +- Task scheduler switched to use new implementation of its core + functionality (deque based task pool, new structure of arena slots). +- Preview of Microsoft* Visual Studio* 2005 project files for + building the library is available in build/vsproject folder. +- Added tests for aligned memory allocations and malloc replacement. +- Added parallel_for/game_of_life.net example (for Windows only) + showing TBB usage in a .NET application. +- A number of other fixes and improvements to code, tests, makefiles, + examples and documents. + +Bugs fixed: + +- The same list as in TBB 2.1 Update 4 right above. + +------------------------------------------------------------------------ +TBB 2.1 Update 3 commercial-aligned release + +Changes (w.r.t. TBB 2.1 U2 commercial-aligned release): + +- Added support for aligned allocations to the TBB memory allocator. +- Added a special library to use with LD_PRELOAD on Linux* in order to + replace the standard memory allocation routines in C/C++ with the + TBB memory allocator. +- Added null_mutex and null_rw_mutex: no-op classes interface-compliant + to other TBB mutexes. +- Improved performance of parallel_sort, to close most of the serial gap + with std::sort, and beat it on 2 and more cores. +- A few other small changes. + +Bugs fixed: + +- the problem where parallel_for hanged after exception throw + if affinity_partitioner was used (1556). +- get rid of VS warnings about mbstowcs deprecation (1560), + as well as some other warnings. +- operator== for concurrent_vector::iterator fixed to work correctly + with different vector instances. + +------------------------------------------------------------------------ +TBB 2.1 Update 2 commercial-aligned release + +Changes (w.r.t. TBB 2.1 U1 commercial-aligned release): + +- Incorporates all open-source-release changes down to TBB 2.1 U1, + except for: + - 20081019 addition of enumerable_thread_specific; +- Warning level for Microsoft* Visual C++* compiler raised to /W4 /Wp64; + warnings found on this level were cleaned or suppressed. +- Added TBB_runtime_interface_version API function. +- Added new example: pipeline/square. +- Added exception handling and cancellation support + for parallel_do and pipeline. +- Added copy constructor and [begin,end) constructor to concurrent_queue. +- Added some support for beta version of Intel(R) Parallel Amplifier. +- Added scripts to set environment for cross-compilation of 32-bit + applications on 64-bit Linux with Intel(R) C++ Compiler. +- Fixed semantics of concurrent_vector::clear() to not deallocate + internal arrays. Fixed compact() to perform such deallocation later. +- Fixed the issue with atomic when T is incomplete type. +- Improved support for PowerPC* Macintosh*, including the fix + for a bug in masked compare-and-swap reported by a customer. +- As usual, a number of other improvements everywhere. + +------------------------------------------------------------------------ +20081109 open-source release + +Changes (w.r.t. previous open-source release): + +- Added new serial out of order filter for tbb::pipeline. +- Fixed the issue with atomic::operator= reported at the forum. +- Fixed the issue with using tbb::task::self() in task destructor + reported at the forum. +- A number of other improvements to code, tests, makefiles, examples + and documents. + +Open-source contributions integrated: +- Changes in the memory allocator were partially integrated. + +------------------------------------------------------------------------ +20081019 open-source release + +Changes (w.r.t. previous open-source release): + +- Introduced enumerable_thread_specific. This new class provides a + wrapper around native thread local storage as well as iterators and + ranges for accessing the thread local copies (1533). +- Improved support for Intel(R) Threading Analysis Tools + on Intel(R) 64 architecture. +- Dependency from Microsoft* CRT was integrated to the libraries using + manifests, to avoid issues if called from code that uses different + version of Visual C++* runtime than the library. +- Introduced new defines TBB_USE_ASSERT, TBB_USE_DEBUG, + TBB_USE_PERFORMANCE_WARNINGS, TBB_USE_THREADING_TOOLS. +- A number of other improvements to code, tests, makefiles, examples + and documents. + +Open-source contributions integrated: + +- linker optimization: /incremental:no . + +------------------------------------------------------------------------ +20080925 open-source release + +Changes (w.r.t. previous open-source release): + +- Same fix for a memory leak in the memory allocator as in TBB 2.1 U1. +- Improved support for lambda functions. +- Fixed more concurrent_queue issues reported at the forum. +- A number of other improvements to code, tests, makefiles, examples + and documents. + +------------------------------------------------------------------------ +TBB 2.1 Update 1 commercial-aligned release + +Changes (w.r.t. TBB 2.1 commercial-aligned release): + +- Fixed small memory leak in the memory allocator. +- Incorporates all open-source-release changes since TBB 2.1, except for: + - 20080825 changes for parallel_do; + +------------------------------------------------------------------------ +20080825 open-source release + +Changes (w.r.t. previous open-source release): + +- Added exception handling and cancellation support for parallel_do. +- Added default HashCompare template argument for concurrent_hash_map. +- Fixed concurrent_queue.clear() issues due to incorrect assumption + about clear() being private method. +- Added the possibility to use TBB in applications that change + default calling conventions (Windows* only). +- Many improvements to code, tests, examples, makefiles and documents. + +Bugs fixed: + +- 120, 130 - memset declaration missed in concurrent_hash_map.h + +------------------------------------------------------------------------ +20080724 open-source release + +Changes (w.r.t. previous open-source release): + +- Inline assembly for atomic operations improved for gcc 4.3 +- A few more improvements to the code. + +------------------------------------------------------------------------ +20080709 open-source release + +Changes (w.r.t. previous open-source release): + +- operator=() was added to the tbb_thread class according to + the current working draft for std::thread. +- Recognizing SPARC* in makefiles for Linux* and Sun Solaris*. + +Bugs fixed: + +- 127 - concurrent_hash_map::range fixed to split correctly. + +Open-source contributions integrated: + +- fix_set_midpoint.diff by jyasskin +- SPARC* support in makefiles by Raf Schietekat + +------------------------------------------------------------------------ +20080622 open-source release + +Changes (w.r.t. previous open-source release): + +- Fixed a hang that rarely happened on Linux + during deinitialization of the TBB scheduler. +- Improved support for Intel(R) Thread Checker. +- A few more improvements to the code. + +------------------------------------------------------------------------ +TBB 2.1 commercial-aligned release + +Changes (w.r.t. TBB 2.0 U3 commercial-aligned release): + +- All open-source-release changes down to, and including, TBB 2.0 below, + were incorporated into this release. + +------------------------------------------------------------------------ +20080605 open-source release + +Changes (w.r.t. previous open-source release): + +- Explicit control of exported symbols by version scripts added on Linux. +- Interfaces polished for exception handling & algorithm cancellation. +- Cache behavior improvements in the scalable allocator. +- Improvements in text_filter, polygon_overlay, and other examples. +- A lot of other stability improvements in code, tests, and makefiles. +- First release where binary packages include headers/docs/examples, so + binary packages are now self-sufficient for using TBB. + +Open-source contributions integrated: + +- atomics patch (partially). +- tick_count warning patch. + +Bugs fixed: + +- 118 - fix for boost compatibility. +- 123 - fix for tbb_machine.h. + +------------------------------------------------------------------------ +20080512 open-source release + +Changes (w.r.t. previous open-source release): + +- Fixed a problem with backward binary compatibility + of debug Linux builds. +- Sun* Studio* support added. +- soname support added on Linux via linker script. To restore backward + binary compatibility, *.so -> *.so.2 softlinks should be created. +- concurrent_hash_map improvements - added few new forms of insert() + method and fixed precondition and guarantees of erase() methods. + Added runtime warning reporting about bad hash function used for + the container. Various improvements for performance and concurrency. +- Cancellation mechanism reworked so that it does not hurt scalability. +- Algorithm parallel_do reworked. Requirement for Body::argument_type + definition removed, and work item argument type can be arbitrarily + cv-qualified. +- polygon_overlay example added. +- A few more improvements to code, tests, examples and Makefiles. + +Open-source contributions integrated: + +- Soname support patch for Bugzilla #112. + +Bugs fixed: + +- 112 - fix for soname support. + +------------------------------------------------------------------------ +TBB 2.0 U3 commercial-aligned release (package 017, April 20, 2008) + +Corresponds to commercial 019 (for Linux*, 020; for Mac OS* X, 018) +packages. + +Changes (w.r.t. TBB 2.0 U2 commercial-aligned release): + +- Does not contain open-source-release changes below; this release is + only a minor update of TBB 2.0 U2. +- Removed spin-waiting in pipeline and concurrent_queue. +- A few more small bug fixes from open-source releases below. + +------------------------------------------------------------------------ +20080408 open-source release + +Changes (w.r.t. previous open-source release): + +- count_strings example reworked: new word generator implemented, hash + function replaced, and tbb_allocator is used with std::string class. +- Static methods of spin_rw_mutex were replaced by normal member + functions, and the class name was versioned. +- tacheon example was renamed to tachyon. +- Improved support for Intel(R) Thread Checker. +- A few more minor improvements. + +Open-source contributions integrated: + +- Two sets of Sun patches for IA Solaris support. + +------------------------------------------------------------------------ +20080402 open-source release + +Changes (w.r.t. previous open-source release): + +- Exception handling and cancellation support for tasks and algorithms + fully enabled. +- Exception safety guaranties defined and fixed for all concurrent + containers. +- User-defined memory allocator support added to all concurrent + containers. +- Performance improvement of concurrent_hash_map, spin_rw_mutex. +- Critical fix for a rare race condition during scheduler + initialization/de-initialization. +- New methods added for concurrent containers to be closer to STL, + as well as automatic filters removal from pipeline + and __TBB_AtomicAND function. +- The volatile keyword dropped from where it is not really needed. +- A few more minor improvements. + +------------------------------------------------------------------------ +20080319 open-source release + +Changes (w.r.t. previous open-source release): + +- Support for gcc version 4.3 was added. +- tbb_thread class, near compatible with std::thread expected in C++0x, + was added. + +Bugs fixed: + +- 116 - fix for compilation issues with gcc version 4.2.1. +- 120 - fix for compilation issues with gcc version 4.3. + +------------------------------------------------------------------------ +20080311 open-source release + +Changes (w.r.t. previous open-source release): + +- An enumerator added for pipeline filter types (serial vs. parallel). +- New task_scheduler_observer class introduced, to observe when + threads start and finish interacting with the TBB task scheduler. +- task_scheduler_init reverted to not use internal versioned class; + binary compatibility guaranteed with stable releases only. +- Various improvements to code, tests, examples and Makefiles. + +------------------------------------------------------------------------ +20080304 open-source release + +Changes (w.r.t. previous open-source release): + +- Task-to-thread affinity support, previously kept under a macro, + now fully legalized. +- Work-in-progress on cache_aligned_allocator improvements. +- Pipeline really supports parallel input stage; it's no more serialized. +- Various improvements to code, tests, examples and Makefiles. + +Bugs fixed: + +- 119 - fix for scalable_malloc sometimes failing to return a big block. +- TR575 - fixed a deadlock occurring on Windows in startup/shutdown + under some conditions. + +------------------------------------------------------------------------ +20080226 open-source release + +Changes (w.r.t. previous open-source release): + +- Introduced tbb_allocator to select between standard allocator and + tbb::scalable_allocator when available. +- Removed spin-waiting in pipeline and concurrent_queue. +- Improved performance of concurrent_hash_map by using tbb_allocator. +- Improved support for Intel(R) Thread Checker. +- Various improvements to code, tests, examples and Makefiles. + +------------------------------------------------------------------------ +TBB 2.0 U2 commercial-aligned release (package 017, February 14, 2008) + +Corresponds to commercial 017 (for Linux*, 018; for Mac OS* X, 016) +packages. + +Changes (w.r.t. TBB 2.0 U1 commercial-aligned release): + +- Does not contain open-source-release changes below; this release is + only a minor update of TBB 2.0 U1. +- Add support for Microsoft* Visual Studio* 2008, including binary + libraries and VS2008 projects for examples. +- Use SwitchToThread() not Sleep() to yield threads on Windows*. +- Enhancements to Doxygen-readable comments in source code. +- A few more small bug fixes from open-source releases below. + +Bugs fixed: + +- TR569 - Memory leak in concurrent_queue. + +------------------------------------------------------------------------ +20080207 open-source release + +Changes (w.r.t. previous open-source release): + +- Improvements and minor fixes in VS2008 projects for examples. +- Improvements in code for gating worker threads that wait for work, + previously consolidated under #if IMPROVED_GATING, now legalized. +- Cosmetic changes in code, examples, tests. + +Bugs fixed: + +- 113 - Iterators and ranges should be convertible to their const + counterparts. +- TR569 - Memory leak in concurrent_queue. + +------------------------------------------------------------------------ +20080122 open-source release + +Changes (w.r.t. previous open-source release): + +- Updated examples/parallel_for/seismic to improve the visuals and to + use the affinity_partitioner (20071127 and forward) for better + performance. +- Minor improvements to unittests and performance tests. + +------------------------------------------------------------------------ +20080115 open-source release + +Changes (w.r.t. previous open-source release): + +- Cleanup, simplifications and enhancements to the Makefiles for + building the libraries (see build/index.html for high-level + changes) and the examples. +- Use SwitchToThread() not Sleep() to yield threads on Windows*. +- Engineering work-in-progress on exception safety/support. +- Engineering work-in-progress on affinity_partitioner for + parallel_reduce. +- Engineering work-in-progress on improved gating for worker threads + (idle workers now block in the OS instead of spinning). +- Enhancements to Doxygen-readable comments in source code. + +Bugs fixed: + +- 102 - Support for parallel build with gmake -j +- 114 - /Wp64 build warning on Windows*. + +------------------------------------------------------------------------ +20071218 open-source release + +Changes (w.r.t. previous open-source release): + +- Full support for Microsoft* Visual Studio* 2008 in open-source. + Binaries for vc9/ will be available in future stable releases. +- New recursive_mutex class. +- Full support for 32-bit PowerMac including export files for builds. +- Improvements to parallel_do. + +------------------------------------------------------------------------ +20071206 open-source release + +Changes (w.r.t. previous open-source release): + +- Support for Microsoft* Visual Studio* 2008 in building libraries + from source as well as in vc9/ projects for examples. +- Small fixes to the affinity_partitioner first introduced in 20071127. +- Small fixes to the thread-stack size hook first introduced in 20071127. +- Engineering work in progress on concurrent_vector. +- Engineering work in progress on exception behavior. +- Unittest improvements. + +------------------------------------------------------------------------ +20071127 open-source release + +Changes (w.r.t. previous open-source release): + +- Task-to-thread affinity support (affinity partitioner) first appears. +- More work on concurrent_vector. +- New parallel_do algorithm (function-style version of parallel while) + and parallel_do/parallel_preorder example. +- New task_scheduler_init() hooks for getting default_num_threads() and + for setting thread stack size. +- Support for weak memory consistency models in the code base. +- Futex usage in the task scheduler (Linux). +- Started adding 32-bit PowerMac support. +- Intel(R) 9.1 compilers are now the base supported Intel(R) compiler + version. +- TBB libraries added to link line automatically on Microsoft Windows* + systems via #pragma comment linker directives. + +Open-source contributions integrated: + +- FreeBSD platform support patches. +- AIX weak memory model patch. + +Bugs fixed: + +- 108 - Removed broken affinity.h reference. +- 101 - Does not build on Debian Lenny (replaced arch with uname -m). + +------------------------------------------------------------------------ +20071030 open-source release + +Changes (w.r.t. previous open-source release): + +- More work on concurrent_vector. +- Better support for building with -Wall -Werror (or not) as desired. +- A few fixes to eliminate extraneous warnings. +- Begin introduction of versioning hooks so that the internal/API + version is tracked via TBB_INTERFACE_VERSION. The newest binary + libraries should always work with previously-compiled code when- + ever possible. +- Engineering work in progress on using futex inside the mutexes (Linux). +- Engineering work in progress on exception behavior. +- Engineering work in progress on a new parallel_do algorithm. +- Unittest improvements. + +------------------------------------------------------------------------ +20070927 open-source release + +Changes (w.r.t. TBB 2.0 U1 commercial-aligned release): + +- Minor update to TBB 2.0 U1 below. +- Begin introduction of new concurrent_vector interfaces not released + with TBB 2.0 U1. + +------------------------------------------------------------------------ +TBB 2.0 U1 commercial-aligned release (package 014, October 1, 2007) + +Corresponds to commercial 014 (for Linux*, 016) packages. + +Changes (w.r.t. TBB 2.0 commercial-aligned release): + +- All open-source-release changes down to, and including, TBB 2.0 below, + were incorporated into this release. +- Made a number of changes to the officially supported OS list: + Added Linux* OSs: + Asianux* 3, Debian* 4.0, Fedora Core* 6, Fedora* 7, + Turbo Linux* 11, Ubuntu* 7.04; + Dropped Linux* OSs: + Asianux* 2, Fedora Core* 4, Haansoft* Linux 2006 Server, + Mandriva/Mandrake* 10.1, Miracle Linux* 4.0, + Red Flag* DC Server 5.0; + Only Mac OS* X 10.4.9 (and forward) and Xcode* tool suite 2.4.1 (and + forward) are now supported. +- Commercial installers on Linux* fixed to recommend the correct + binaries to use in more cases, with less unnecessary warnings. +- Changes to eliminate spurious build warnings. + +Open-source contributions integrated: + +- Two small header guard macro patches; it also fixed bug #94. +- New blocked_range3d class. + +Bugs fixed: + +- 93 - Removed misleading comments in task.h. +- 94 - See above. + +------------------------------------------------------------------------ +20070815 open-source release + +Changes: + +- Changes to eliminate spurious build warnings. +- Engineering work in progress on concurrent_vector allocator behavior. +- Added hooks to use the Intel(R) compiler code coverage tools. + +Open-source contributions integrated: + +- Mac OS* X build warning patch. + +Bugs fixed: + +- 88 - Fixed TBB compilation errors if both VS2005 and Windows SDK are + installed. + +------------------------------------------------------------------------ +20070719 open-source release + +Changes: + +- Minor update to TBB 2.0 commercial-aligned release below. +- Changes to eliminate spurious build warnings. + +------------------------------------------------------------------------ +TBB 2.0 commercial-aligned release (package 010, July 19, 2007) + +Corresponds to commercial 010 (for Linux*, 012) packages. + +- TBB open-source debut release. + +------------------------------------------------------------------------ +TBB 1.1 commercial release (April 10, 2007) + +Changes (w.r.t. TBB 1.0 commercial release): + +- auto_partitioner which offered an automatic alternative to specifying + a grain size parameter to estimate the best granularity for tasks. +- The release was added to the Intel(R) C++ Compiler 10.0 Pro. + +------------------------------------------------------------------------ +TBB 1.0 Update 2 commercial release + +Changes (w.r.t. TBB 1.0 Update 1 commercial release): + +- Mac OS* X 64-bit support added. +- Source packages for commercial releases introduced. + +------------------------------------------------------------------------ +TBB 1.0 Update 1 commercial-aligned release + +Changes (w.r.t. TBB 1.0 commercial release): + +- Fix for critical package issue on Mac OS* X. + +------------------------------------------------------------------------ +TBB 1.0 commercial release (August 29, 2006) + +Changes (w.r.t. TBB 1.0 beta commercial release): + +- New namespace (and compatibility headers for old namespace). + Namespaces are tbb and tbb::internal and all classes are in the + underscore_style not the WindowsStyle. +- New class: scalable_allocator (and cache_aligned_allocator using that + if it exists). +- Added parallel_for/tacheon example. +- Removed C-style casts from headers for better C++ compliance. +- Bug fixes. +- Documentation improvements. +- Improved performance of the concurrent_hash_map class. +- Upgraded parallel_sort() to support STL-style random-access iterators + instead of just pointers. +- The Windows vs7_1 directories renamed to vs7.1 in examples. +- New class: spin version of reader-writer lock. +- Added push_back() interface to concurrent_vector(). + +------------------------------------------------------------------------ +TBB 1.0 beta commercial release + +Initial release. + +Features / APIs: + +- Concurrent containers: ConcurrentHashTable, ConcurrentVector, + ConcurrentQueue. +- Parallel algorithms: ParallelFor, ParallelReduce, ParallelScan, + ParallelWhile, Pipeline, ParallelSort. +- Support: AlignedSpace, BlockedRange (i.e., 1D), BlockedRange2D +- Task scheduler with multi-master support. +- Atomics: read, write, fetch-and-store, fetch-and-add, compare-and-swap. +- Locks: spin, reader-writer, queuing, OS-wrapper. +- Memory allocation: STL-style memory allocator that avoids false + sharing. +- Timers. + +Tools Support: +- Intel(R) Thread Checker 3.0. +- Intel(R) Thread Profiler 3.0. + +Documentation: +- First Use Documents: README.txt, INSTALL.txt, Release_Notes.txt, + Doc_Index.html, Getting_Started.pdf, Tutorial.pdf, Reference.pdf. +- Class hierarchy HTML pages (Doxygen). +- Tree of index.html pages for navigating the installed package, esp. + for the examples. + +Examples: +- One for each of these TBB features: ConcurrentHashTable, ParallelFor, + ParallelReduce, ParallelWhile, Pipeline, Task. +- Live copies of examples from Getting_Started.pdf. +- TestAll example that exercises every class and header in the package + (i.e., a "liveness test"). +- Compilers: see Release_Notes.txt. +- APIs: OpenMP, WinThreads, Pthreads. + +Packaging: +- Package for Windows installs IA-32 and EM64T bits. +- Package for Linux installs IA-32, EM64T and IPF bits. +- Package for Mac OS* X installs IA-32 bits. +- All packages support Intel(R) software setup assistant (ISSA) and + install-time FLEXlm license checking. +- ISSA support allows license file to be specified directly in case of + no Internet connection or problems with IRC or serial #s. +- Linux installer allows root or non-root, RPM or non-RPM installs. +- FLEXlm license servers (for those who need floating/counted licenses) + are provided separately on Intel(R) Premier. + +------------------------------------------------------------------------ +Intel and Cilk are registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. + +* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/COPYING b/src/tbb/COPYING new file mode 100644 index 0000000..5af6ed8 --- /dev/null +++ b/src/tbb/COPYING @@ -0,0 +1,353 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. +---------------- END OF Gnu General Public License ---------------- + +The source code of Threading Building Blocks is distributed under version 2 +of the GNU General Public License, with the so-called "runtime exception," +as follows (or see any header or implementation file): + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. diff --git a/src/tbb/Makefile b/src/tbb/Makefile new file mode 100644 index 0000000..b35d19f --- /dev/null +++ b/src/tbb/Makefile @@ -0,0 +1,88 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +tbb_root?=. +include $(tbb_root)/build/common.inc +.PHONY: default all tbb tbbmalloc tbbproxy test examples + +#workaround for non-depend targets tbb and tbbmalloc which both depend on version_string.ver +#According to documentation submakes should run in parallel +.NOTPARALLEL: tbb tbbmalloc tbbproxy + +default: tbb tbbmalloc $(if $(use_proxy),tbbproxy) + +all: tbb tbbmalloc tbbproxy test examples + +tbb: mkdir + $(MAKE) -C "$(work_dir)_debug" -r -f $(tbb_root)/build/Makefile.tbb cfg=debug tbb_root=$(tbb_root) + $(MAKE) -C "$(work_dir)_release" -r -f $(tbb_root)/build/Makefile.tbb cfg=release tbb_root=$(tbb_root) + +tbbmalloc: mkdir + $(MAKE) -C "$(work_dir)_debug" -r -f $(tbb_root)/build/Makefile.tbbmalloc cfg=debug malloc tbb_root=$(tbb_root) + $(MAKE) -C "$(work_dir)_release" -r -f $(tbb_root)/build/Makefile.tbbmalloc cfg=release malloc tbb_root=$(tbb_root) + +tbbproxy: mkdir + $(MAKE) -C "$(work_dir)_debug" -r -f $(tbb_root)/build/Makefile.tbbproxy cfg=debug tbbproxy tbb_root=$(tbb_root) + $(MAKE) -C "$(work_dir)_release" -r -f $(tbb_root)/build/Makefile.tbbproxy cfg=release tbbproxy tbb_root=$(tbb_root) + +test: tbb tbbmalloc $(if $(use_proxy),tbbproxy) + -$(MAKE) -C "$(work_dir)_debug" -r -f $(tbb_root)/build/Makefile.tbbmalloc cfg=debug malloc_test tbb_root=$(tbb_root) + -$(MAKE) -C "$(work_dir)_debug" -r -f $(tbb_root)/build/Makefile.test cfg=debug tbb_root=$(tbb_root) + -$(MAKE) -C "$(work_dir)_release" -r -f $(tbb_root)/build/Makefile.tbbmalloc cfg=release malloc_test tbb_root=$(tbb_root) + -$(MAKE) -C "$(work_dir)_release" -r -f $(tbb_root)/build/Makefile.test cfg=release tbb_root=$(tbb_root) + +rml: mkdir + $(MAKE) -C "$(work_dir)_debug" -r -f $(tbb_root)/build/Makefile.rml cfg=debug tbb_root=$(tbb_root) + $(MAKE) -C "$(work_dir)_release" -r -f $(tbb_root)/build/Makefile.rml cfg=release tbb_root=$(tbb_root) + + +examples: tbb tbbmalloc + $(MAKE) -C examples -r -f Makefile tbb_root=.. release test + +.PHONY: clean clean_examples mkdir info + +clean: clean_examples + $(shell $(RM) $(work_dir)_release$(SLASH)*.* >$(NUL) 2>$(NUL)) + $(shell $(RD) $(work_dir)_release >$(NUL) 2>$(NUL)) + $(shell $(RM) $(work_dir)_debug$(SLASH)*.* >$(NUL) 2>$(NUL)) + $(shell $(RD) $(work_dir)_debug >$(NUL) 2>$(NUL)) + @echo clean done + +clean_examples: + $(shell $(MAKE) -s -i -r -C examples -f Makefile tbb_root=.. clean >$(NUL) 2>$(NUL)) + +mkdir: + $(shell $(MD) "$(work_dir)_release" >$(NUL) 2>$(NUL)) + $(shell $(MD) "$(work_dir)_debug" >$(NUL) 2>$(NUL)) + @echo Created $(work_dir)_release and ..._debug directories + +info: + @echo OS: $(tbb_os) + @echo arch=$(arch) + @echo compiler=$(compiler) + @echo runtime=$(runtime) + @echo tbb_build_prefix=$(tbb_build_prefix) + diff --git a/src/tbb/README b/src/tbb/README new file mode 100644 index 0000000..67ab8ad --- /dev/null +++ b/src/tbb/README @@ -0,0 +1,11 @@ +Threading Building Blocks - README + +See index.html for directions and documentation. + +If source is present (./Makefile and src/ directories), +type 'gmake' in this directory to build and test. + +See examples/index.html for runnable examples and directions. + +See http://threadingbuildingblocks.org for full documentation +and software information. diff --git a/src/tbb/build/AIX.gcc.inc b/src/tbb/build/AIX.gcc.inc new file mode 100644 index 0000000..252f3af --- /dev/null +++ b/src/tbb/build/AIX.gcc.inc @@ -0,0 +1,85 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +COMPILE_ONLY = -c -MMD +PREPROC_ONLY = -E -x c++ +INCLUDE_KEY = -I +DEFINE_KEY = -D +OUTPUT_KEY = -o # +OUTPUTOBJ_KEY = -o # +PIC_KEY = -fPIC +WARNING_AS_ERROR_KEY = -Werror +WARNING_KEY = -Wall +DYLIB_KEY = -shared +LIBDL = -ldl + +TBB_NOSTRICT = 1 + +CPLUS = g++ +CONLY = gcc +LIB_LINK_FLAGS = -shared +LIBS = -lpthread -ldl +C_FLAGS = $(CPLUS_FLAGS) -x c + +ifeq ($(cfg), release) + CPLUS_FLAGS = -O2 -DUSE_PTHREAD -pthread +endif +ifeq ($(cfg), debug) + CPLUS_FLAGS = -DTBB_USE_DEBUG -g -O0 -DUSE_PTHREAD -pthread +endif + +ASM= +ASM_FLAGS= + +TBB_ASM.OBJ= + +ifeq (powerpc,$(arch)) + CPLUS_FLAGS += -maix64 -Wl,-G + LIB_LINK_FLAGS += -maix64 -Wl,-b64 -Wl,-brtl -Wl,-G +endif + +#------------------------------------------------------------------------------ +# Setting assembler data. +#------------------------------------------------------------------------------ + +ASSEMBLY_SOURCE=ibm_aix51 +ifeq (powerpc,$(arch)) + TBB_ASM.OBJ = atomic_support.o +endif + +#------------------------------------------------------------------------------ +# End of setting assembler data. +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# Setting tbbmalloc data. +#------------------------------------------------------------------------------ + +M_CPLUS_FLAGS = $(CPLUS_FLAGS) -fno-rtti -fno-exceptions -fno-schedule-insns2 + +#------------------------------------------------------------------------------ +# End of setting tbbmalloc data. +#------------------------------------------------------------------------------ diff --git a/src/tbb/build/AIX.inc b/src/tbb/build/AIX.inc new file mode 100644 index 0000000..3a80f20 --- /dev/null +++ b/src/tbb/build/AIX.inc @@ -0,0 +1,75 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +ifndef arch + arch:=$(shell uname -p) + export arch +endif + +ifndef runtime + gcc_version:=$(shell gcc -v 2>&1 | grep 'gcc version' | sed -e 's/^gcc version //' | sed -e 's/ .*$$//') + os_version:=$(shell uname -r) + os_kernel_version:=$(shell uname -r | sed -e 's/-.*$$//') + export runtime:=cc$(gcc_version)_kernel$(os_kernel_version) +endif + +native_compiler := gcc +export compiler ?= gcc +debugger ?= gdb + +CMD=$(SHELL) -c +CWD=$(shell pwd) +RM?=rm -f +RD?=rmdir +MD?=mkdir -p +NUL= /dev/null +SLASH=/ +MAKE_VERSIONS=sh $(tbb_root)/build/version_info_aix.sh $(CPLUS) $(CPLUS_FLAGS) $(INCLUDES) >version_string.ver +MAKE_TBBVARS=sh $(tbb_root)/build/generate_tbbvars.sh + +ifdef LIBPATH + export LIBPATH := .:$(LIBPATH) +else + export LIBPATH := . +endif + +####### Build settings ######################################################## + +OBJ = o +DLL = so + +TBB.LST = +TBB.DEF = +TBB.DLL = libtbb$(CPF_SUFFIX)$(DEBUG_SUFFIX).$(DLL) +TBB.LIB = $(TBB.DLL) +LINK_TBB.LIB = $(TBB.LIB) + +MALLOC.DLL = libtbbmalloc$(DEBUG_SUFFIX).$(DLL) +MALLOC.LIB = $(MALLOC.DLL) + +TBB_NOSTRICT=1 + +TEST_LAUNCHER=sh $(tbb_root)/build/test_launcher.sh diff --git a/src/tbb/build/FreeBSD.gcc.inc b/src/tbb/build/FreeBSD.gcc.inc new file mode 100644 index 0000000..8905476 --- /dev/null +++ b/src/tbb/build/FreeBSD.gcc.inc @@ -0,0 +1,95 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +COMPILE_ONLY = -c -MMD +PREPROC_ONLY = -E -x c++ +INCLUDE_KEY = -I +DEFINE_KEY = -D +OUTPUT_KEY = -o # +OUTPUTOBJ_KEY = -o # +PIC_KEY = -fPIC +WARNING_AS_ERROR_KEY = -Werror +WARNING_KEY = -Wall +DYLIB_KEY = -shared + +TBB_NOSTRICT = 1 + +CPLUS = g++ +CONLY = gcc +LIB_LINK_FLAGS = -shared +LIBS = -lpthread +C_FLAGS = $(CPLUS_FLAGS) + +ifeq ($(cfg), release) + CPLUS_FLAGS = -O2 -DUSE_PTHREAD +endif +ifeq ($(cfg), debug) + CPLUS_FLAGS = -DTBB_USE_DEBUG -g -O0 -DUSE_PTHREAD +endif + +ASM= +ASM_FLAGS= + +TBB_ASM.OBJ= +MALLOC_ASM.OBJ= + +ifeq (ia64,$(arch)) +# Position-independent code (PIC) is a must on IA-64, even for regular (not shared) executables + CPLUS_FLAGS += $(PIC_KEY) +endif + +ifeq (intel64,$(arch)) + CPLUS_FLAGS += -m64 + LIB_LINK_FLAGS += -m64 +endif + +ifeq (ia32,$(arch)) + CPLUS_FLAGS += -m32 + LIB_LINK_FLAGS += -m32 +endif + +#------------------------------------------------------------------------------ +# Setting assembler data. +#------------------------------------------------------------------------------ +ASSEMBLY_SOURCE=$(arch)-gas +ifeq (ia64,$(arch)) + ASM=as + TBB_ASM.OBJ = atomic_support.o lock_byte.o log2.o pause.o + MALLOC_ASM.OBJ = atomic_support.o lock_byte.o pause.o +endif +#------------------------------------------------------------------------------ +# End of setting assembler data. +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# Setting tbbmalloc data. +#------------------------------------------------------------------------------ + +M_CPLUS_FLAGS = $(CPLUS_FLAGS) -fno-rtti -fno-exceptions -fno-schedule-insns2 + +#------------------------------------------------------------------------------ +# End of setting tbbmalloc data. +#------------------------------------------------------------------------------ diff --git a/src/tbb/build/FreeBSD.inc b/src/tbb/build/FreeBSD.inc new file mode 100644 index 0000000..9b3c21f --- /dev/null +++ b/src/tbb/build/FreeBSD.inc @@ -0,0 +1,83 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +ifndef arch + ifeq ($(shell uname -m),i386) + export arch:=ia32 + endif + ifeq ($(shell uname -m),ia64) + export arch:=ia64 + endif + ifeq ($(shell uname -m),amd64) + export arch:=intel64 + endif +endif + +ifndef runtime + gcc_version:=$(shell gcc -v 2>&1 | grep 'gcc version' | sed -e 's/^gcc version //' | sed -e 's/ .*$$//') + os_version:=$(shell uname -r) + os_kernel_version:=$(shell uname -r | sed -e 's/-.*$$//') + export runtime:=cc$(gcc_version)_kernel$(os_kernel_version) +endif + +native_compiler := gcc +export compiler ?= gcc +debugger ?= gdb + +CMD=$(SHELL) -c +CWD=$(shell pwd) +RM?=rm -f +RD?=rmdir +MD?=mkdir -p +NUL= /dev/null +SLASH=/ +MAKE_VERSIONS=sh $(tbb_root)/build/version_info_linux.sh $(CPLUS) $(CPLUS_FLAGS) $(INCLUDES) >version_string.ver +MAKE_TBBVARS=sh $(tbb_root)/build/generate_tbbvars.sh + +ifdef LD_LIBRARY_PATH + export LD_LIBRARY_PATH := .:$(LD_LIBRARY_PATH) +else + export LD_LIBRARY_PATH := . +endif + +####### Build settings ######################################################## + +OBJ = o +DLL = so +LIBEXT=so + +TBB.LST = +TBB.DEF = +TBB.DLL = libtbb$(CPF_SUFFIX)$(DEBUG_SUFFIX).$(DLL) +TBB.LIB = $(TBB.DLL) +LINK_TBB.LIB = $(TBB.LIB) + +MALLOC.DLL = libtbbmalloc$(DEBUG_SUFFIX).$(DLL) +MALLOC.LIB = $(MALLOC.DLL) + +TBB_NOSTRICT=1 + +TEST_LAUNCHER=sh $(tbb_root)/build/test_launcher.sh diff --git a/src/tbb/build/Makefile.rml b/src/tbb/build/Makefile.rml new file mode 100644 index 0000000..809b013 --- /dev/null +++ b/src/tbb/build/Makefile.rml @@ -0,0 +1,160 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +tbb_root ?= $(TBBROOT) +BUILDING_PHASE=1 +TEST_RESOURCE = $(RML.RES) +include $(tbb_root)/build/common.inc +DEBUG_SUFFIX=$(findstring _debug,_$(cfg)) + +# default target +default_rml: rml rml_test + +RML_ROOT ?= $(tbb_root)/src/rml +RML_SERVER_ROOT = $(RML_ROOT)/server + +VPATH = $(tbb_root)/src/tbb $(tbb_root)/src/tbb/$(ASSEMBLY_SOURCE) +VPATH += $(RML_ROOT)/server $(RML_ROOT)/client $(RML_ROOT)/test $(tbb_root)/src/test + +include $(tbb_root)/build/common_rules.inc + +#-------------------------------------------------------------------------- +# Define rules for making the RML server shared library and client objects. +#-------------------------------------------------------------------------- + +# Object files that make up RML server +RML_SERVER.OBJ = rml_server.$(OBJ) + +# Object files that RML clients need +RML_TBB_CLIENT.OBJ = rml_tbb.$(OBJ) dynamic_link_rml.$(OBJ) +RML_OMP_CLIENT.OBJ = rml_omp.$(OBJ) omp_dynamic_link.$(OBJ) + +RML.OBJ = $(RML_SERVER.OBJ) $(RML_TBB_CLIENT.OBJ) $(RML_OMP_CLIENT.OBJ) +ifeq (windows,$(tbb_os)) +RML_ASM.OBJ = $(if $(findstring intel64,$(arch)),$(TBB_ASM.OBJ)) +endif +ifeq (linux,$(tbb_os)) +RML_ASM.OBJ = $(if $(findstring ia64,$(arch)),$(TBB_ASM.OBJ)) +endif + +RML_TBB_DEP= cache_aligned_allocator_rml.$(OBJ) dynamic_link_rml.$(OBJ) concurrent_vector_rml.$(OBJ) semaphore_rml.$(OBJ) tbb_misc_rml.$(OBJ) tbb_misc_ex_rml.$(OBJ) +TBB_DEP_NON_RML_TEST= cache_aligned_allocator_rml.$(OBJ) dynamic_link_rml.$(OBJ) $(RML_ASM.OBJ) tbb_misc_rml.$(OBJ) tbb_misc_ex_rml.$(OBJ) +TBB_DEP_RML_TEST= $(RML_ASM.OBJ) +ifeq ($(cfg),debug) +RML_TBB_DEP+= spin_mutex_rml.$(OBJ) +TBB_DEP_RML_TEST+= tbb_misc_rml.$(OBJ) +endif +LIBS += $(LIBDL) + +INCLUDES += $(INCLUDE_KEY)$(RML_ROOT)/include $(INCLUDE_KEY). +T_INCLUDES = $(INCLUDES) $(INCLUDE_KEY)$(tbb_root)/src/test $(INCLUDE_KEY)$(RML_SERVER_ROOT) + +# Suppress superfluous warnings for RML compilation +R_CPLUS_FLAGS = $(subst DO_ITT_NOTIFY,DO_ITT_NOTIFY=0,$(CPLUS_FLAGS)) $(WARNING_SUPPRESS) \ + $(DEFINE_KEY)TBB_USE_THREADING_TOOLS=0 $(DEFINE_KEY)__TBB_RML_STATIC=1 $(DEFINE_KEY)__TBB_NO_IMPLICIT_LINKAGE=1 + +%.$(OBJ): %.cpp + $(CPLUS) $(COMPILE_ONLY) $(R_CPLUS_FLAGS) $(PIC_KEY) $(INCLUDES) $< + +ifeq (linux,$(tbb_os)) +omp_dynamic_link.$(OBJ): CPLUS_FLAGS+=-fno-exceptions +endif + +tbb_misc_rml.$(OBJ): version_string.ver + +RML_TEST.OBJ = test_job_automaton.$(OBJ) test_thread_monitor.$(OBJ) test_rml_tbb.$(OBJ) test_rml_omp.$(OBJ) test_rml_mixed.$(OBJ) + +$(RML_TBB_DEP): %_rml.$(OBJ): %.cpp + $(CPLUS) $(COMPILE_ONLY) $(OUTPUTOBJ_KEY)$@ $(R_CPLUS_FLAGS) $(PIC_KEY) $(INCLUDES) $< + +$(RML_TEST.OBJ): %.$(OBJ): %.cpp + $(CPLUS) $(COMPILE_ONLY) $(R_CPLUS_FLAGS) $(PIC_KEY) $(T_INCLUDES) $< + +ifneq (,$(RML.DEF)) +rml.def: $(RML.DEF) + $(CPLUS) $(PREPROC_ONLY) $< $(CPLUS_FLAGS) $(INCLUDES) > $@ + +LIB_LINK_FLAGS += $(EXPORT_KEY)rml.def +$(RML.DLL): rml.def +endif + +$(RML.DLL): BUILDING_LIBRARY = $(RML.DLL) +$(RML.DLL): $(RML_TBB_DEP) $(RML_SERVER.OBJ) $(RML.RES) $(RML_NO_VERSION.DLL) $(RML_ASM.OBJ) + $(LIB_LINK_CMD) $(LIB_OUTPUT_KEY)$(RML.DLL) $(RML_SERVER.OBJ) $(RML_TBB_DEP) $(RML_ASM.OBJ) $(RML.RES) $(LIB_LINK_LIBS) $(LIB_LINK_FLAGS) + +ifneq (,$(RML_NO_VERSION.DLL)) +$(RML_NO_VERSION.DLL): + echo "INPUT ($(RML.DLL))" > $(RML_NO_VERSION.DLL) +endif + +rml: $(RML.DLL) $(RML_TBB_CLIENT.OBJ) $(RML_OMP_CLIENT.OBJ) + +#------------------------------------------------------ +# End of rules for making the RML server shared library +#------------------------------------------------------ + +#------------------------------------------------------ +# Define rules for making the RML unit tests +#------------------------------------------------------ + +add_debug=$(basename $(1))_debug$(suffix $(1)) +cross_suffix=$(if $(crosstest),$(if $(DEBUG_SUFFIX),$(subst _debug,,$(1)),$(call add_debug,$(1))),$(1)) + +RML_TESTS = test_job_automaton.$(TEST_EXT) test_thread_monitor.$(TEST_EXT) test_rml_tbb.$(TEST_EXT) test_rml_omp.$(TEST_EXT) test_rml_mixed.$(TEST_EXT) test_rml_omp_c_linkage.$(TEST_EXT) + +test_rml_tbb.$(TEST_EXT): test_rml_tbb.$(OBJ) $(RML_TBB_CLIENT.OBJ) $(TBB_DEP_RML_TEST) + $(CPLUS) $(OUTPUT_KEY)$@ $(CPLUS_FLAGS) test_rml_tbb.$(OBJ) $(RML_TBB_CLIENT.OBJ) $(TBB_DEP_RML_TEST) $(LIBS) $(LINK_FLAGS) + +test_rml_omp.$(TEST_EXT): test_rml_omp.$(OBJ) $(RML_OMP_CLIENT.OBJ) $(TBB_DEP_NON_RML_TEST) + $(CPLUS) $(OUTPUT_KEY)$@ $(CPLUS_FLAGS) test_rml_omp.$(OBJ) $(RML_OMP_CLIENT.OBJ) $(TBB_DEP_NON_RML_TEST) $(LIBS) $(LINK_FLAGS) + +test_rml_mixed.$(TEST_EXT): test_rml_mixed.$(OBJ) $(RML_TBB_CLIENT.OBJ) $(RML_OMP_CLIENT.OBJ) $(TBB_DEP_RML_TEST) + $(CPLUS) $(OUTPUT_KEY)$@ $(CPLUS_FLAGS) test_rml_mixed.$(OBJ) $(RML_TBB_CLIENT.OBJ) $(RML_OMP_CLIENT.OBJ) $(TBB_DEP_RML_TEST) $(LIBS) $(LINK_FLAGS) + +rml_omp_stub.$(OBJ): rml_omp_stub.cpp + $(CPLUS) $(COMPILE_ONLY) $(M_CPLUS_FLAGS) $(WARNING_SUPPRESS) $(T_INCLUDES) $(PIC_KEY) $< + +test_rml_omp_c_linkage.$(TEST_EXT): test_rml_omp_c_linkage.$(OBJ) rml_omp_stub.$(OBJ) omp_dynamic_link.$(OBJ) + $(CONLY) $(C_FLAGS) $(OUTPUT_KEY)$@ test_rml_omp_c_linkage.$(OBJ) rml_omp_stub.$(OBJ) omp_dynamic_link.$(OBJ) $(LIBS) $(LINK_FLAGS) + +test_%.$(TEST_EXT): test_%.$(OBJ) $(TBB_DEP_NON_RML_TEST) + $(CPLUS) $(OUTPUT_KEY)$@ $(CPLUS_FLAGS) $< $(TBB_DEP_NON_RML_TEST) $(LIBS) $(LINK_FLAGS) + +### run_cmd is usually empty +rml_test: $(call cross_suffix,$(RML.DLL)) $(TEST_PREREQUISITE) $(RML_TESTS) + $(run_cmd) ./test_job_automaton.$(TEST_EXT) $(args) + $(run_cmd) ./test_thread_monitor.$(TEST_EXT) $(args) + $(run_cmd) ./test_rml_tbb.$(TEST_EXT) $(args) + $(run_cmd) ./test_rml_omp.$(TEST_EXT) $(args) + $(run_cmd) ./test_rml_mixed.$(TEST_EXT) $(args) + $(run_cmd) ./test_rml_omp_c_linkage.$(TEST_EXT) $(args) + +#------------------------------------------------------ +# End of rules for making the TBBMalloc unit tests +#------------------------------------------------------ + +# Include automatically generated dependences +-include *.d diff --git a/src/tbb/build/Makefile.tbb b/src/tbb/build/Makefile.tbb new file mode 100644 index 0000000..fded71b --- /dev/null +++ b/src/tbb/build/Makefile.tbb @@ -0,0 +1,134 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +#------------------------------------------------------------------------------ +# Define rules for making the TBB shared library. +#------------------------------------------------------------------------------ + +tbb_root ?= "$(TBBROOT)" +BUILDING_PHASE=1 +include $(tbb_root)/build/common.inc +DEBUG_SUFFIX=$(findstring _debug,_$(cfg)) + +#------------------------------------------------------------ +# Define static pattern rules dealing with .cpp source files +#------------------------------------------------------------ +$(warning CONFIG: cfg=$(cfg) arch=$(arch) compiler=$(compiler) os=$(tbb_os) runtime=$(runtime)) + +default_tbb: $(TBB.DLL) +.PHONY: default_tbb tbbvars clean +.PRECIOUS: %.$(OBJ) + +VPATH = $(tbb_root)/src/tbb/$(ASSEMBLY_SOURCE) $(tbb_root)/src/tbb $(tbb_root)/src/old $(tbb_root)/src/rml/client + +CPLUS_FLAGS += $(PIC_KEY) $(DEFINE_KEY)__TBB_BUILD=1 + +# A template to switch off strict-ansi for certain compilation units +# ifeq (1,$(TBB_NOSTRICT)) +# KNOWN_NOSTRICT = +# endif + +# suppress warnings for build of itt_notify by GCC3 +ifneq (,$(findstring gcc_cc3., $(compiler)_$(runtime))) +KNOWN_WARNINGS += itt_notify.$(OBJ) +endif + +# Object files (that were compiled from C++ code) that gmake up TBB +TBB_CPLUS.OBJ = concurrent_hash_map.$(OBJ) \ + concurrent_queue.$(OBJ) \ + concurrent_vector.$(OBJ) \ + dynamic_link.$(OBJ) \ + itt_notify.$(OBJ) \ + cache_aligned_allocator.$(OBJ) \ + pipeline.$(OBJ) \ + queuing_mutex.$(OBJ) \ + queuing_rw_mutex.$(OBJ) \ + reader_writer_lock.$(OBJ) \ + spin_rw_mutex.$(OBJ) \ + spin_mutex.$(OBJ) \ + critical_section.$(OBJ) \ + task.$(OBJ) \ + tbb_misc.$(OBJ) \ + tbb_misc_ex.$(OBJ) \ + mutex.$(OBJ) \ + recursive_mutex.$(OBJ) \ + condition_variable.$(OBJ) \ + tbb_thread.$(OBJ) \ + concurrent_monitor.$(OBJ) \ + semaphore.$(OBJ) \ + private_server.$(OBJ) \ + rml_tbb.$(OBJ) \ + task_group_context.$(OBJ) \ + governor.$(OBJ) \ + market.$(OBJ) \ + arena.$(OBJ) \ + scheduler.$(OBJ) \ + observer_proxy.$(OBJ) \ + tbb_statistics.$(OBJ) \ + tbb_main.$(OBJ) + +# OLD/Legacy object files for backward binary compatibility +ifeq (,$(findstring $(DEFINE_KEY)TBB_NO_LEGACY,$(CPLUS_FLAGS))) +TBB_CPLUS_OLD.OBJ = \ + concurrent_vector_v2.$(OBJ) \ + concurrent_queue_v2.$(OBJ) \ + spin_rw_mutex_v2.$(OBJ) \ + task_v2.$(OBJ) +endif + +# Object files that gmake up TBB (TBB_ASM.OBJ is platform-specific) +TBB.OBJ = $(TBB_CPLUS.OBJ) $(TBB_CPLUS_OLD.OBJ) $(TBB_ASM.OBJ) + +# Suppress superfluous warnings for TBB compilation +WARNING_KEY += $(WARNING_SUPPRESS) + +include $(tbb_root)/build/common_rules.inc + +ifneq (,$(TBB.DEF)) +tbb.def: $(TBB.DEF) $(TBB.LST) + $(CPLUS) $(PREPROC_ONLY) $< $(CPLUS_FLAGS) $(INCLUDES) > $@ + +LIB_LINK_FLAGS += $(EXPORT_KEY)tbb.def +$(TBB.DLL): tbb.def +endif + +tbbvars.sh: + $(MAKE_TBBVARS) + +$(TBB.DLL): BUILDING_LIBRARY = $(TBB.DLL) +$(TBB.DLL): $(TBB.OBJ) $(TBB.RES) tbbvars.sh $(TBB_NO_VERSION.DLL) + $(LIB_LINK_CMD) $(LIB_OUTPUT_KEY)$(TBB.DLL) $(TBB.OBJ) $(TBB.RES) $(LIB_LINK_LIBS) $(LIB_LINK_FLAGS) + +ifneq (,$(TBB_NO_VERSION.DLL)) +$(TBB_NO_VERSION.DLL): + echo "INPUT ($(TBB.DLL))" > $(TBB_NO_VERSION.DLL) +endif + +#clean: +# $(RM) *.$(OBJ) *.$(DLL) *.res *.map *.ilk *.pdb *.exp *.manifest *.tmp *.d core core.*[0-9][0-9] *.ver + +# Include automatically generated dependences +-include *.d diff --git a/src/tbb/build/Makefile.tbbmalloc b/src/tbb/build/Makefile.tbbmalloc new file mode 100644 index 0000000..48cbdb0 --- /dev/null +++ b/src/tbb/build/Makefile.tbbmalloc @@ -0,0 +1,208 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# default target +default_malloc: malloc malloc_test + +tbb_root ?= $(TBBROOT) +BUILDING_PHASE=1 +TEST_RESOURCE = $(MALLOC.RES) +include $(tbb_root)/build/common.inc +DEBUG_SUFFIX=$(findstring _debug,_$(cfg)) + +MALLOC_ROOT ?= $(tbb_root)/src/tbbmalloc +MALLOC_SOURCE_ROOT ?= $(MALLOC_ROOT) + +VPATH = $(tbb_root)/src/tbb/$(ASSEMBLY_SOURCE) $(tbb_root)/src/tbb $(tbb_root)/src/test +VPATH += $(MALLOC_ROOT) $(MALLOC_SOURCE_ROOT) + +CPLUS_FLAGS += $(if $(crosstest),$(DEFINE_KEY)__TBBMALLOC_NO_IMPLICIT_LINKAGE=1) + +include $(tbb_root)/build/common_rules.inc + +#------------------------------------------------------ +# Define rules for making the TBBMalloc shared library. +#------------------------------------------------------ + +# Object files that make up TBBMalloc +MALLOC_CPLUS.OBJ = backend.$(OBJ) large_objects.$(OBJ) backref.$(OBJ) tbbmalloc.$(OBJ) +MALLOC.OBJ := $(MALLOC_CPLUS.OBJ) $(MALLOC_ASM.OBJ) itt_notify_malloc.$(OBJ) frontend.$(OBJ) +PROXY.OBJ := proxy.$(OBJ) tbb_function_replacement.$(OBJ) +M_CPLUS_FLAGS := $(subst $(WARNING_KEY),,$(M_CPLUS_FLAGS)) $(DEFINE_KEY)__TBBMALLOC_BUILD=1 +M_INCLUDES = $(INCLUDES) $(INCLUDE_KEY)$(MALLOC_ROOT) $(INCLUDE_KEY)$(MALLOC_SOURCE_ROOT) + +# Suppress superfluous warnings for TBBmalloc compilation +$(MALLOC.OBJ): M_CPLUS_FLAGS += $(WARNING_SUPPRESS) + +frontend.$(OBJ): frontend.cpp version_string.ver + $(CPLUS) $(COMPILE_ONLY) $(M_CPLUS_FLAGS) $(PIC_KEY) $(M_INCLUDES) $(INCLUDE_KEY). $< + +$(PROXY.OBJ): %.$(OBJ): %.cpp + $(CPLUS) $(COMPILE_ONLY) $(CPLUS_FLAGS) $(PIC_KEY) $(DEFINE_KEY)__TBBMALLOC_BUILD=1 $(M_INCLUDES) $< + +$(MALLOC_CPLUS.OBJ): %.$(OBJ): %.cpp + $(CPLUS) $(COMPILE_ONLY) $(M_CPLUS_FLAGS) $(PIC_KEY) $(M_INCLUDES) $< + +itt_notify_malloc.$(OBJ): itt_notify.cpp + $(CPLUS) $(COMPILE_ONLY) $(M_CPLUS_FLAGS) $(PIC_KEY) $(OUTPUTOBJ_KEY)$@ $(INCLUDES) $< + +MALLOC_LINK_FLAGS = $(LIB_LINK_FLAGS) +PROXY_LINK_FLAGS = $(LIB_LINK_FLAGS) + +ifneq (,$(MALLOC.DEF)) +tbbmalloc.def: $(MALLOC.DEF) + $(CPLUS) $(PREPROC_ONLY) $< $(CPLUS_FLAGS) $(INCLUDES) > $@ + +MALLOC_LINK_FLAGS += $(EXPORT_KEY)tbbmalloc.def +$(MALLOC.DLL): tbbmalloc.def +endif + +$(MALLOC.DLL): BUILDING_LIBRARY = $(MALLOC.DLL) +$(MALLOC.DLL): $(MALLOC.OBJ) $(MALLOC.RES) $(MALLOC_NO_VERSION.DLL) + $(subst $(CPLUS),$(CONLY),$(LIB_LINK_CMD)) $(LIB_OUTPUT_KEY)$(MALLOC.DLL) $(MALLOC.OBJ) $(MALLOC.RES) $(LIB_LINK_LIBS) $(MALLOC_LINK_FLAGS) + +ifneq (,$(MALLOCPROXY.DEF)) +tbbmallocproxy.def: $(MALLOCPROXY.DEF) + $(CPLUS) $(PREPROC_ONLY) $< $(CPLUS_FLAGS) $(INCLUDES) > $@ + +PROXY_LINK_FLAGS += $(EXPORT_KEY)tbbmallocproxy.def +$(MALLOCPROXY.DLL): tbbmallocproxy.def +endif + +ifneq (,$(MALLOCPROXY.DLL)) +$(MALLOCPROXY.DLL): BUILDING_LIBRARY = $(MALLOCPROXY.DLL) +$(MALLOCPROXY.DLL): $(PROXY.OBJ) $(MALLOCPROXY_NO_VERSION.DLL) $(MALLOC.DLL) $(MALLOC.RES) + $(LIB_LINK_CMD) $(LIB_OUTPUT_KEY)$(MALLOCPROXY.DLL) $(PROXY.OBJ) $(MALLOC.RES) $(LIB_LINK_LIBS) $(LINK_MALLOC.LIB) $(PROXY_LINK_FLAGS) +endif + +ifneq (,$(MALLOC_NO_VERSION.DLL)) +$(MALLOC_NO_VERSION.DLL): + echo "INPUT ($(MALLOC.DLL))" > $(MALLOC_NO_VERSION.DLL) +endif + +ifneq (,$(MALLOCPROXY_NO_VERSION.DLL)) +$(MALLOCPROXY_NO_VERSION.DLL): + echo "INPUT ($(MALLOCPROXY.DLL))" > $(MALLOCPROXY_NO_VERSION.DLL) +endif + +malloc: $(MALLOC.DLL) $(MALLOCPROXY.DLL) + +malloc_dll: $(MALLOC.DLL) + +malloc_proxy_dll: $(MALLOCPROXY.DLL) + +.PHONY: malloc malloc_dll malloc_proxy_dll + +#------------------------------------------------------ +# End of rules for making the TBBMalloc shared library +#------------------------------------------------------ + +#------------------------------------------------------ +# Define rules for making the TBBMalloc unit tests +#------------------------------------------------------ + +add_debug=$(basename $(1))_debug$(suffix $(1)) +cross_suffix=$(if $(crosstest),$(if $(DEBUG_SUFFIX),$(subst _debug,,$(1)),$(call add_debug,$(1))),$(1)) + +MALLOC_MAIN_TESTS = test_ScalableAllocator.$(TEST_EXT) \ + test_ScalableAllocator_STL.$(TEST_EXT) \ + test_malloc_compliance.$(TEST_EXT) \ + test_malloc_regression.$(TEST_EXT) \ + test_malloc_init_shutdown.$(TEST_EXT) \ + test_malloc_pools.$(TEST_EXT) +MALLOC_OVERLOAD_TESTS = test_malloc_overload.$(TEST_EXT) test_malloc_overload_proxy.$(TEST_EXT) test_malloc_atexit.$(TEST_EXT) + +MALLOC_LIB = $(call cross_suffix,$(MALLOC.LIB)) +MALLOC_PROXY_LIB = $(call cross_suffix,$(MALLOCPROXY.LIB)) + +ifeq (windows.gcc,$(tbb_os).$(compiler)) +test_malloc_overload.$(TEST_EXT): LIBS += $(MALLOC_PROXY_LIB) +endif + +test_malloc_overload.$(TEST_EXT): test_malloc_overload.cpp + $(CPLUS) $(OUTPUT_KEY)$@ $(subst /MT,/MD,$(M_CPLUS_FLAGS)) $(M_INCLUDES) $< $(LIBDL) $(LIBS) $(LINK_FLAGS) +test_malloc_overload_proxy.$(TEST_EXT): test_malloc_overload.cpp $(MALLOC_PROXY_LIB) + $(CPLUS) $(OUTPUT_KEY)$@ $(subst /MT,/MD,$(M_CPLUS_FLAGS)) $(M_INCLUDES) $< $(LIBDL) $(MALLOC_PROXY_LIB) $(LIBS) $(LINK_FLAGS) + +test_malloc_whitebox.$(TEST_EXT): test_malloc_whitebox.cpp $(MALLOC_ASM.OBJ) version_string.ver + $(CPLUS) $(OUTPUT_KEY)$@ $(M_CPLUS_FLAGS) $(M_INCLUDES) $(INCLUDE_KEY). $< $(MALLOC_ASM.OBJ) $(LIBS) $(LIBDL) $(LINK_FLAGS) + +test_malloc_lib_unload.$(TEST_EXT): test_malloc_lib_unload.cpp test_malloc_lib_unload_dll.$(DLL) + $(CPLUS) $(OUTPUT_KEY)$@ $(M_CPLUS_FLAGS) $(M_INCLUDES) $< $(LIBS) test_malloc_lib_unload_dll.$(LIBEXT) $(LIBDL) $(LINK_FLAGS) + +# TODO: use generic rules +test_malloc_used_by_lib.$(TEST_EXT): test_malloc_used_by_lib.cpp test_malloc_used_by_lib.$(DLL) + $(CPLUS) $(OUTPUT_KEY)$@ $(M_CPLUS_FLAGS) $(M_INCLUDES) $< $(LIBS) $(LIBDL) $(LINK_FLAGS) + +test_malloc_used_by_lib.$(DLL): test_malloc_used_by_lib.cpp + $(CPLUS) $(OUTPUT_KEY)$@ $(subst /MT,/LD,$(M_CPLUS_FLAGS)) $(PIC_KEY) $(M_INCLUDES) $(DEFINE_KEY)_USRDLL $< $(MALLOC_LIB) $(LINK_FLAGS) $(DYLIB_KEY) + +$(MALLOC_MAIN_TESTS): %.$(TEST_EXT): %.$(OBJ) $(MALLOC_LIB) + $(CPLUS) $(OUTPUT_KEY)$@ $(CPLUS_FLAGS) $< $(MALLOC_LIB) $(LIBS) $(LINK_FLAGS) + +MALLOC_C_TESTS = test_malloc_pure_c.$(TEST_EXT) + +$(MALLOC_C_TESTS): %.$(TEST_EXT): %.$(OBJ) $(MALLOC_LIB) + $(CPLUS) $(OUTPUT_KEY)$@ $(CPLUS_FLAGS) $^ $(LIBS) $(LINK_FLAGS) + +# Rules for generating a test DLL +%_dll.$(DLL): %_dll.$(OBJ) + $(LIB_LINK_CMD) $(OUTPUT_KEY)$@ $(CPLUS_FLAGS) $(PIC_KEY) $< $(LIBS) $(LINK_FLAGS) $(DYLIB_KEY) + +test_malloc_atexit.$(TEST_EXT): test_malloc_atexit.$(OBJ) test_malloc_atexit_dll.$(DLL) + $(CPLUS) $(OUTPUT_KEY)$@ $(CPLUS_FLAGS) $< $(MALLOC_PROXY_LIB) $(MALLOC_LIB) test_malloc_atexit_dll.$(LIBEXT) $(LIBS) $(LINK_FLAGS) + +MALLOC_TESTS = $(MALLOC_MAIN_TESTS) $(MALLOC_C_TESTS) test_malloc_whitebox.$(TEST_EXT) test_malloc_used_by_lib.$(TEST_EXT) +ifneq (,$(MALLOCPROXY.DLL)) +MALLOC_TESTS += $(MALLOC_OVERLOAD_TESTS) test_malloc_lib_unload.$(TEST_EXT) +endif + +# run_cmd is usually empty +malloc_test: $(call cross_suffix,$(MALLOC.DLL)) malloc_test_no_depends + +malloc_test_no_depends: $(TEST_PREREQUISITE) $(MALLOC_TESTS) + $(run_cmd) ./test_malloc_pools.$(TEST_EXT) $(args) 1:4 +ifneq (,$(MALLOCPROXY.DLL)) + $(run_cmd) ./test_malloc_atexit.$(TEST_EXT) $(args) + $(run_cmd) ./test_malloc_lib_unload.$(TEST_EXT) $(args) + $(run_cmd) $(TEST_LAUNCHER) -l $(call cross_suffix,$(MALLOCPROXY.DLL)) test_malloc_overload.$(TEST_EXT) $(args) + $(run_cmd) $(TEST_LAUNCHER) test_malloc_overload_proxy.$(TEST_EXT) $(args) +endif + $(run_cmd) ./test_malloc_used_by_lib.$(TEST_EXT) + $(run_cmd) ./test_malloc_whitebox.$(TEST_EXT) $(args) 1:4 + $(run_cmd) $(TEST_LAUNCHER) test_malloc_compliance.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_ScalableAllocator.$(TEST_EXT) $(args) + $(run_cmd) ./test_ScalableAllocator_STL.$(TEST_EXT) $(args) + $(run_cmd) ./test_malloc_regression.$(TEST_EXT) $(args) + $(run_cmd) ./test_malloc_init_shutdown.$(TEST_EXT) $(args) + $(run_cmd) ./test_malloc_pure_c.$(TEST_EXT) $(args) + +#------------------------------------------------------ +# End of rules for making the TBBMalloc unit tests +#------------------------------------------------------ + +# Include automatically generated dependences +-include *.d diff --git a/src/tbb/build/Makefile.tbbproxy b/src/tbb/build/Makefile.tbbproxy new file mode 100644 index 0000000..eb60d2f --- /dev/null +++ b/src/tbb/build/Makefile.tbbproxy @@ -0,0 +1,116 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# default target +default_tbbproxy: tbbproxy tbbproxy_test + +tbb_root ?= $(TBBROOT) +BUILDING_PHASE=1 +include $(tbb_root)/build/common.inc +DEBUG_SUFFIX=$(findstring _debug,_$(cfg)) + +PROXY_ROOT ?= $(tbb_root)/src/tbbproxy +PROXY_SOURCE_ROOT ?= $(PROXY_ROOT) + +VPATH = $(tbb_root)/src/tbb/$(ASSEMBLY_SOURCE) $(tbb_root)/src/tbb $(tbb_root)/src/test +VPATH += $(PROXY_ROOT) $(PROXY_SOURCE_ROOT) + +CPLUS_FLAGS += $(DEFINE_KEY)__TBB_DLL_NAME=$(TBB.DLL) +CPLUS_FLAGS += $(DEFINE_KEY)__TBB_LST=$(TBB.LST) +CPLUS_FLAGS += $(foreach dir,$(VPATH),$(INCLUDE_KEY)$(dir)) +CPLUS_FLAGS += $(PIC_KEY) + +include $(tbb_root)/build/common_rules.inc + +#------------------------------------------------------ +# Define rules for making the TBB Proxy static library. +#------------------------------------------------------ + +# Object files that make up TBB Proxy +PROXY_CPLUS.OBJ = tbbproxy.$(OBJ) +PROXY_ASM.OBJ = tbbproxy-asm.$(OBJ) +PROXY.OBJ := $(PROXY_CPLUS.OBJ) $(PROXY_ASM.OBJ) + +# Not using intrinsics prevents undesired dependence from ICL libraries (e.g. libirc). +# Not using default libs prevents link issues caused by different CRT versions in tbbproxy and in an app. +$(PROXY.OBJ): CPLUS_FLAGS += $(DEFINE_KEY)ARCH_$(arch) $(DEFINE_KEY)OS_$(tbb_os) $(NOINTRINSIC_KEY) $(NODEFAULTLIB_KEY) + +$(PROXY_CPLUS.OBJ): %.$(OBJ): %.cpp + $(CPLUS) $(COMPILE_ONLY) $(CPLUS_FLAGS) $(INCLUDES) $< + +$(PROXY.LIB): $(PROXY.OBJ) + $(AR) $(AR_FLAGS) $(AR_OUTPUT_KEY)$@ $^ + +.PRECIOUS : %.$(ASMEXT) +tbbproxy-asm.$(ASMEXT) : tbbproxy-$(tbb_os).$(ASMEXT) $(TBB.LST) $(TBB-OBJECTS.LST) + $(CPLUS) $(PREPROC_ONLY) $< $(INCLUDES) $(CPLUS_FLAGS) > $@ + +.PHONY: tbbproxy +ifeq (windows,$(tbb_os)) +tbbproxy: $(PROXY.LIB) +else +tbbproxy: +endif + +#------------------------------------------------------ +# End of rules for making the TBB Proxy static library +#------------------------------------------------------ + +#------------------------------------------------------ +# Define rules for making the TBB Proxy unit tests +#------------------------------------------------------ + +add_debug=$(basename $(1))_debug$(suffix $(1)) +cross_suffix=$(if $(crosstest),$(if $(DEBUG_SUFFIX),$(subst _debug,,$(1)),$(call add_debug,$(1))),$(1)) + +PROXY_LIB = $(call cross_suffix,$(PROXY.LIB)) +PROXY_TESTS_SRCS = test_runtime_loader.cpp +PROXY_TESTS_OBJS = $(PROXY_TESTS_SRCS:.cpp=.$(OBJ)) +PROXY_TESTS_EXES = $(PROXY_TESTS_OBJS:.$(OBJ)=.$(TEST_EXT)) + +# Run rules. +.PHONY: tbbproxy_test +ifeq (windows,$(tbb_os)) +tbbproxy_test: $(call cross_suffix,$(PROXY.LIB)) $(TEST_PREREQUISITE) $(PROXY_TESTS_EXES) + $(run_cmd) ./test_runtime_loader.$(TEST_EXT) $(args) +else +tbbproxy_test: +endif + +# Link rules. +$(PROXY_TESTS_EXES): %.$(TEST_EXT): %.$(OBJ) $(PROXY_LIB) + $(CPLUS) $(OUTPUT_KEY)$@ $(CPLUS_FLAGS) $< $(PROXY_LIB) $(LIBS) $(LIBDL) $(LINK_FLAGS) + +# Compilation rules. +$(PROXY_TESTS_OBJS): %.$(OBJ): %.cpp + $(CPLUS) $(COMPILE_ONLY) $(CPLUS_FLAGS) $(CXX_ONLY_FLAGS) $(CXX_WARN_SUPPRESS) $(INCLUDES) $(OUTPUT_KEY)$@ $< + +#------------------------------------------------------ +# End of rules for making the TBB Proxy unit tests +#------------------------------------------------------ + +# Include automatically generated dependences +-include *.d diff --git a/src/tbb/build/Makefile.test b/src/tbb/build/Makefile.test new file mode 100644 index 0000000..4266466 --- /dev/null +++ b/src/tbb/build/Makefile.test @@ -0,0 +1,376 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +#------------------------------------------------------------------------------ +# Define rules for making the TBB tests. +#------------------------------------------------------------------------------ +.PHONY: default test_tbb_plain test_tbb_openmp test_tbb_cilk test_tbb_old clean + +default: test_tbb_plain test_tbb_openmp test_tbb_cilk test_tbb_old + +tbb_root ?= $(TBBROOT) +BUILDING_PHASE=1 +TEST_RESOURCE = $(TBB.RES) +include $(tbb_root)/build/common.inc +DEBUG_SUFFIX=$(findstring _debug,$(call cross_cfg,_$(cfg))) + +#------------------------------------------------------------ +# Define static pattern rules dealing with .cpp source files +#------------------------------------------------------------ + +VPATH = $(tbb_root)/src/tbb/$(ASSEMBLY_SOURCE) $(tbb_root)/src/tbb $(tbb_root)/src/rml/client $(tbb_root)/src/old $(tbb_root)/src/test $(tbb_root)/src/perf + +CPLUS_FLAGS += $(if $(crosstest),$(DEFINE_KEY)__TBB_NO_IMPLICIT_LINKAGE=1) +ifdef use_proxy + USE_PROXY_FLAG = $(DEFINE_KEY)HARNESS_USE_PROXY + CPLUS_FLAGS += $(USE_PROXY_FLAG) + LINK_TBB.LIB = $(PROXY.LIB) + LIBS += $(LIBDL) +endif + +include $(tbb_root)/build/common_rules.inc + +# Rule for generating executable test +%.$(TEST_EXT): %.$(OBJ) $(TBB.LIB) $(if $(use_proxy),$(LINK_TBB.LIB)) + $(CPLUS) $(OUTPUT_KEY)$@ $(CPLUS_FLAGS) $< $(LINK_TBB.LIB) $(LIBS) $(AUX_LIBS) $(LINK_FLAGS) + +# Rules for generating a test DLL +%_dll.$(DLL): %_dll.$(OBJ) $(TBB.LIB) + $(CPLUS) $(OUTPUT_KEY)$@ $(CPLUS_FLAGS) $(PIC_KEY) $< $(LINK_TBB.LIB) $(LIBS) $(LINK_FLAGS) $(DYLIB_KEY) +.PRECIOUS: %_dll.$(OBJ) %_dll.$(DLL) + +# Rules for the tests, which use TBB in a dynamically loadable library +test_model_plugin.$(TEST_EXT): CPLUS_FLAGS := $(CPLUS_FLAGS:$(USE_PROXY_FLAG)=) +test_model_plugin.$(TEST_EXT): test_model_plugin.$(OBJ) test_model_plugin_dll.$(DLL) + $(CPLUS) $(OUTPUT_KEY)$@ $(CPLUS_FLAGS) $< $(LIBDL) $(LIBS) $(LINK_FLAGS) + + +# tbb_misc.$(OBJ) has to be specified here (instead of harness_inject_scheduler.h) because it carries dependency on version_string.ver +SCHEDULER_DEPENDENCIES = $(TBB_ASM.OBJ) tbb_misc.$(OBJ) + +# These executables don't depend on the TBB library, but include core .cpp files directly +SCHEDULER_DIRECTLY_INCLUDED = test_task_leaks.$(TEST_EXT) \ + test_task_assertions.$(TEST_EXT) \ + test_fast_random.$(TEST_EXT) + +# Necessary to locate version_string.ver referenced from directly included tbb_misc.cpp +INCLUDES += $(INCLUDE_KEY). + +$(SCHEDULER_DIRECTLY_INCLUDED): WARNING_KEY += $(WARNING_SUPPRESS) + +$(SCHEDULER_DIRECTLY_INCLUDED): %.$(TEST_EXT) : %.$(OBJ) $(SCHEDULER_DEPENDENCIES) + $(CPLUS) $(OUTPUT_KEY)$@ $(CPLUS_FLAGS) $^ $(LIBDL) $(LIBS) $(LINK_FLAGS) + +# Tests that use some features of C++11 +TEST_TBB_CPP11 = test_lambda.$(TEST_EXT) test_cache_aligned_allocator_STL.$(TEST_EXT) + +$(TEST_TBB_CPP11:%.$(TEST_EXT)=%.$(OBJ)): %.$(OBJ): %.cpp + $(CPLUS) $(COMPILE_ONLY) $(CPLUS_FLAGS) $(CPP11_FLAGS) $(CXX_ONLY_FLAGS) $(CXX_WARN_SUPPRESS) $(INCLUDES) $< +$(TEST_TBB_CPP11): %.$(TEST_EXT): %.$(OBJ) $(TBB.LIB) $(if $(use_proxy),$(LINK_TBB.LIB)) + $(CPLUS) $(OUTPUT_KEY)$@ $(CPLUS_FLAGS) $(CPP11_FLAGS) $< $(LINK_TBB.LIB) $(LIBS) $(AUX_LIBS) $(LINK_FLAGS) + +test_tbb_header2.$(OBJ): test_tbb_header.cpp + $(CPLUS) $(COMPILE_ONLY) $(CPLUS_FLAGS) $(CXX_ONLY_FLAGS) $(CXX_WARN_SUPPRESS) $(INCLUDES) $(DEFINE_KEY)__TBB_TEST_SECONDARY=1 $< $(OUTPUTOBJ_KEY)$@ + +# Detecting "multiple definition" linker error using the test that covers the whole library +test_tbb_header.$(TEST_EXT): test_tbb_header.$(OBJ) test_tbb_header2.$(OBJ) $(TBB.LIB) + $(CPLUS) $(OUTPUT_KEY)$@ $(CPLUS_FLAGS) test_tbb_header.$(OBJ) test_tbb_header2.$(OBJ) $(LINK_TBB.LIB) $(LIBS) $(LINK_FLAGS) + +# Checks that TBB atomics work correctly in position independent code +test_atomic_pic.$(TEST_EXT): test_atomic.cpp + $(CPLUS) $(OUTPUT_KEY)$@ $(CPLUS_FLAGS) $(PIC_KEY) $(CXX_ONLY_FLAGS) $(CXX_WARN_SUPPRESS) $(INCLUDES) $(DEFINE_KEY)__TBB_TEST_PIC=1 $< $(LINK_TBB.LIB) $(LIBS) $(AUX_LIBS) $(LINK_FLAGS) + +#Test of generic gcc port +%_gcc_builtins.$(TEST_EXT): CPLUS_FLAGS+=$(DEFINE_KEY)__TBB_TEST_GCC_BUILTINS=1 +%_gcc_builtins.$(TEST_EXT): %.cpp + $(CPLUS) $(OUTPUT_KEY)$@ $(CPLUS_FLAGS) $(CXX_ONLY_FLAGS) $(CXX_WARN_SUPPRESS) $(INCLUDES) $< $(LIBS) $(AUX_LIBS) $(LINK_FLAGS) + +# The main list of TBB tests +TEST_TBB_PLAIN.EXE = test_assembly.$(TEST_EXT) \ + test_assembly_gcc_builtins.$(TEST_EXT) \ + test_aligned_space.$(TEST_EXT) \ + test_atomic.$(TEST_EXT) \ + test_atomic_pic.$(TEST_EXT) \ + test_atomic_gcc_builtins.$(TEST_EXT) \ + test_blocked_range.$(TEST_EXT) \ + test_blocked_range2d.$(TEST_EXT) \ + test_blocked_range3d.$(TEST_EXT) \ + test_concurrent_queue.$(TEST_EXT) \ + test_concurrent_vector.$(TEST_EXT) \ + test_concurrent_unordered.$(TEST_EXT) \ + test_concurrent_hash_map.$(TEST_EXT) \ + test_enumerable_thread_specific.$(TEST_EXT) \ + test_handle_perror.$(TEST_EXT) \ + test_halt.$(TEST_EXT) \ + test_model_plugin.$(TEST_EXT) \ + test_mutex.$(TEST_EXT) \ + test_mutex_native_threads.$(TEST_EXT) \ + test_rwm_upgrade_downgrade.$(TEST_EXT) \ + test_cache_aligned_allocator.$(TEST_EXT) \ + test_parallel_for.$(TEST_EXT) \ + test_parallel_reduce.$(TEST_EXT) \ + test_parallel_sort.$(TEST_EXT) \ + test_parallel_scan.$(TEST_EXT) \ + test_parallel_while.$(TEST_EXT) \ + test_parallel_do.$(TEST_EXT) \ + test_pipeline.$(TEST_EXT) \ + test_pipeline_with_tbf.$(TEST_EXT) \ + test_parallel_pipeline.$(TEST_EXT) \ + test_task_scheduler_init.$(TEST_EXT) \ + test_task_scheduler_observer.$(TEST_EXT) \ + test_task.$(TEST_EXT) \ + test_tbb_thread.$(TEST_EXT) \ + test_std_thread.$(TEST_EXT) \ + test_tick_count.$(TEST_EXT) \ + test_inits_loop.$(TEST_EXT) \ + test_yield.$(TEST_EXT) \ + test_eh_tasks.$(TEST_EXT) \ + test_eh_algorithms.$(TEST_EXT) \ + test_eh_flow_graph.$(TEST_EXT) \ + test_parallel_invoke.$(TEST_EXT) \ + test_task_group.$(TEST_EXT) \ + test_ittnotify.$(TEST_EXT) \ + test_parallel_for_each.$(TEST_EXT) \ + test_tbb_header.$(TEST_EXT) \ + test_combinable.$(TEST_EXT) \ + test_task_auto_init.$(TEST_EXT) \ + test_concurrent_monitor.$(TEST_EXT) \ + test_semaphore.$(TEST_EXT) \ + test_critical_section.$(TEST_EXT) \ + test_reader_writer_lock.$(TEST_EXT) \ + test_tbb_condition_variable.$(TEST_EXT) \ + test_intrusive_list.$(TEST_EXT) \ + test_concurrent_priority_queue.$(TEST_EXT) \ + test_task_priority.$(TEST_EXT) \ + test_task_enqueue.$(TEST_EXT) \ + test_task_steal_limit.$(TEST_EXT) \ + test_hw_concurrency.$(TEST_EXT) \ + test_fp.$(TEST_EXT) \ + test_flow_graph.$(TEST_EXT) \ + test_broadcast_node.$(TEST_EXT) \ + test_continue_node.$(TEST_EXT) \ + test_function_node.$(TEST_EXT) \ + test_limiter_node.$(TEST_EXT) \ + test_join_node.$(TEST_EXT) \ + test_buffer_node.$(TEST_EXT) \ + test_queue_node.$(TEST_EXT) \ + test_priority_queue_node.$(TEST_EXT) \ + test_sequencer_node.$(TEST_EXT) \ + test_source_node.$(TEST_EXT) \ + test_overwrite_node.$(TEST_EXT) \ + test_write_once_node.$(TEST_EXT) \ + test_or_node.$(TEST_EXT) \ + test_multifunction_node.$(TEST_EXT) \ + test_split_node.$(TEST_EXT) \ + test_tbb_version.$(TEST_EXT) # insert new files right above + +TEST_TBB_PLAIN.EXE += $(TEST_TBB_CPP11) + +ifdef OPENMP_FLAG +test_openmp.$(TEST_EXT): test_openmp.cpp + $(CPLUS) $(OPENMP_FLAG) $(OUTPUT_KEY)$@ $(CPLUS_FLAGS) $(INCLUDES) $< $(LIBS) $(LINK_TBB.LIB) $(LINK_FLAGS) +test_tbb_openmp: $(TEST_PREREQUISITE) test_openmp.$(TEST_EXT) + $(run_cmd) ./test_openmp.$(TEST_EXT) 1:4 +else +test_tbb_openmp: + @echo "OpenMP is not available" +endif + +ifdef CILK_AVAILABLE +test_cilk_dynamic_load.$(TEST_EXT): test_cilk_dynamic_load.$(OBJ) test_cilk_dynamic_load_dll.$(DLL) + $(CPLUS) $(OUTPUT_KEY)$@ $(CPLUS_FLAGS) $< $(LINK_TBB.LIB) $(LIBDL) $(LIBS) $(LINK_FLAGS) +# Workaround on cilkrts linkage known issue (see Intel(R) C++ Composer XE 2011 Release Notes) +# The issue reveals itself if a version of binutils is prior to 2.17 +ifeq (linux_icc,$(tbb_os)_$(compiler)) +test_cilk_interop.$(TEST_EXT): LIBS += -lcilkrts +endif +test_tbb_cilk: test_cilk_interop.$(TEST_EXT) test_cilk_dynamic_load.$(TEST_EXT) + $(run_cmd) ./test_cilk_interop.$(TEST_EXT) $(args) + $(run_cmd) ./test_cilk_dynamic_load.$(TEST_EXT) $(args) +else +test_tbb_cilk: + @echo "Intel(R) Cilk Plus is not available" +endif + +$(TEST_TBB_PLAIN.EXE): WARNING_KEY += $(TEST_WARNING_KEY) + +# Run tests that are in SCHEDULER_DIRECTLY_INCLUDED and TEST_TBB_PLAIN.EXE +# Note that usually run_cmd is empty, and tests run directly +test_tbb_plain: $(TEST_PREREQUISITE) $(SCHEDULER_DIRECTLY_INCLUDED) $(TEST_TBB_PLAIN.EXE) + $(run_cmd) ./test_tbb_version.$(TEST_EXT) $(args) + # Checking TBB version first to make sure the following testing has anything in it + $(run_cmd) ./test_assembly.$(TEST_EXT) $(args) + $(run_cmd) ./test_assembly_gcc_builtins.$(TEST_EXT) $(args) + $(run_cmd) ./test_atomic.$(TEST_EXT) $(args) + $(run_cmd) ./test_atomic_pic.$(TEST_EXT) $(args) + $(run_cmd) ./test_atomic_gcc_builtins.$(TEST_EXT) $(args) + # Yes, 4:8 is intended on the next line. + $(run_cmd) ./test_yield.$(TEST_EXT) $(args) 4:8 + $(run_cmd) ./test_handle_perror.$(TEST_EXT) $(args) + $(run_cmd) ./test_task_auto_init.$(TEST_EXT) $(args) + $(run_cmd) ./test_task_scheduler_init.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_task_scheduler_observer.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_task.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_task_assertions.$(TEST_EXT) $(args) + $(run_cmd) ./test_task_leaks.$(TEST_EXT) $(args) + $(run_cmd) ./test_fast_random.$(TEST_EXT) $(args) 1:16 + $(run_cmd) ./test_eh_tasks.$(TEST_EXT) $(args) 2:4 + $(run_cmd) ./test_cache_aligned_allocator.$(TEST_EXT) $(args) + $(run_cmd) ./test_cache_aligned_allocator_STL.$(TEST_EXT) $(args) + $(run_cmd) ./test_blocked_range.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_blocked_range2d.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_blocked_range3d.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_parallel_for.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_parallel_sort.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_aligned_space.$(TEST_EXT) $(args) + $(run_cmd) ./test_parallel_reduce.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_parallel_scan.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_parallel_while.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_parallel_do.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_inits_loop.$(TEST_EXT) $(args) + $(run_cmd) ./test_lambda.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_mutex.$(TEST_EXT) $(args) 1:3 + $(run_cmd) ./test_mutex_native_threads.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_rwm_upgrade_downgrade.$(TEST_EXT) $(args) 4 + # Yes, 4:8 is intended on the next line. + $(run_cmd) ./test_halt.$(TEST_EXT) $(args) 4:8 + $(run_cmd) ./test_pipeline.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_pipeline_with_tbf.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_parallel_pipeline.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_tick_count.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_concurrent_queue.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_concurrent_vector.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_concurrent_unordered.$(TEST_EXT) $(args) + $(run_cmd) ./test_concurrent_hash_map.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_enumerable_thread_specific.$(TEST_EXT) $(args) 0:4 + $(run_cmd) ./test_combinable.$(TEST_EXT) $(args) 0:4 + $(run_cmd) ./test_model_plugin.$(TEST_EXT) $(args) 4 + $(run_cmd) ./test_eh_algorithms.$(TEST_EXT) $(args) 2:4 + $(run_cmd) ./test_eh_flow_graph.$(TEST_EXT) $(args) 2:4 + $(run_cmd) ./test_tbb_thread.$(TEST_EXT) $(args) + $(run_cmd) ./test_std_thread.$(TEST_EXT) $(args) + $(run_cmd) ./test_parallel_invoke.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_task_group.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_ittnotify.$(TEST_EXT) $(args) 2:2 + $(run_cmd) ./test_parallel_for_each.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_tbb_header.$(TEST_EXT) $(args) + $(run_cmd) ./test_concurrent_monitor.$(TEST_EXT) $(args) 6:8 + $(run_cmd) ./test_critical_section.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_semaphore.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_reader_writer_lock.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_tbb_condition_variable.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_intrusive_list.$(TEST_EXT) $(args) + $(run_cmd) ./test_concurrent_priority_queue.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_task_priority.$(TEST_EXT) $(args) + $(run_cmd) ./test_task_enqueue.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_task_steal_limit.$(TEST_EXT) $(args) + $(run_cmd) ./test_hw_concurrency.$(TEST_EXT) $(args) + $(run_cmd) ./test_fp.$(TEST_EXT) $(args) + $(run_cmd) ./test_flow_graph.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_broadcast_node.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_continue_node.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_function_node.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_limiter_node.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_join_node.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_buffer_node.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_queue_node.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_priority_queue_node.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_sequencer_node.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_source_node.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_overwrite_node.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_write_once_node.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_or_node.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_multifunction_node.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_split_node.$(TEST_EXT) $(args) 1:4 + +CPLUS_FLAGS_DEPRECATED = $(DEFINE_KEY)TBB_DEPRECATED=1 $(subst $(WARNING_KEY),,$(CPLUS_FLAGS)) $(WARNING_SUPPRESS) + +TEST_TBB_OLD.OBJ = test_concurrent_vector_v2.$(OBJ) test_concurrent_queue_v2.$(OBJ) test_mutex_v2.$(OBJ) + +TEST_TBB_DEPRECATED.OBJ = test_concurrent_queue_deprecated.$(OBJ) \ + test_concurrent_vector_deprecated.$(OBJ) \ + + +# For deprecated files, we don't mind warnings etc., thus compilation rules are most relaxed +$(TEST_TBB_OLD.OBJ): %.$(OBJ): %.cpp + $(CPLUS) $(COMPILE_ONLY) $(CPLUS_FLAGS_DEPRECATED) $(CXX_ONLY_FLAGS) $(INCLUDES) $< + +%_deprecated.$(OBJ): %.cpp + $(CPLUS) $(COMPILE_ONLY) $(OUTPUTOBJ_KEY)$@ $(CPLUS_FLAGS_DEPRECATED) $(CXX_ONLY_FLAGS) $(INCLUDES) $< + +TEST_TBB_OLD.EXE = $(subst .$(OBJ),.$(TEST_EXT),$(TEST_TBB_OLD.OBJ) $(TEST_TBB_DEPRECATED.OBJ)) + +ifeq (,$(NO_LEGACY_TESTS)) +test_tbb_old: $(TEST_PREREQUISITE) $(TEST_TBB_OLD.EXE) + $(run_cmd) ./test_concurrent_vector_v2.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_concurrent_vector_deprecated.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_concurrent_queue_v2.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_concurrent_queue_deprecated.$(TEST_EXT) $(args) 1:4 + $(run_cmd) ./test_mutex_v2.$(TEST_EXT) $(args) 1 + $(run_cmd) ./test_mutex_v2.$(TEST_EXT) $(args) 2 + $(run_cmd) ./test_mutex_v2.$(TEST_EXT) $(args) 4 +else +test_tbb_old: + @echo Legacy tests skipped +endif + +ifneq (,$(codecov)) +codecov_gen: + profmerge + codecov $(if $(findstring -,$(codecov)),$(codecov),) -demang -comp $(tbb_root)/build/codecov.txt +endif + +test_% debug_%: test_%.$(TEST_EXT) $(TEST_PREREQUISITE) +ifeq (,$(repeat)) + $(run_cmd) ./$< $(args) +else +ifeq (windows,$(tbb_os)) + for /L %%i in (1,1,$(repeat)) do echo %%i of $(repeat): && $(run_cmd) $< $(args) +else + for ((i=1;i<=$(repeat);++i)); do echo $$i of $(repeat): && $(run_cmd) ./$< $(args); done +endif +endif # repeat +ifneq (,$(codecov)) + profmerge + codecov $(if $(findstring -,$(codecov)),$(codecov),) -demang -comp $(tbb_root)/build/codecov.txt +endif + +time_%: time_%.$(TEST_EXT) $(TEST_PREREQUISITE) + $(run_cmd) ./$< $(args) + + +perf_%: AUX_LIBS = perf_dll.$(LIBEXT) +perf_%: perf_dll.$(DLL) perf_%.$(TEST_EXT) + $(run_cmd) ./$@.$(TEST_EXT) $(args) + +clean_%: + $(RM) $*.$(OBJ) $*.exe $*.$(DLL) $*.$(LIBEXT) $*.res $*.map $*.ilk $*.pdb $*.exp $*.*manifest $*.tmp $*.d *.ver + +clean: + $(RM) *.$(OBJ) *.exe *.$(DLL) *.$(LIBEXT) *.res *.map *.ilk *.pdb *.exp *.manifest *.tmp *.d pgopti.* *.dyn core core.*[0-9][0-9] *.ver + +# Include automatically generated dependences +-include *.d diff --git a/src/tbb/build/SunOS.gcc.inc b/src/tbb/build/SunOS.gcc.inc new file mode 100644 index 0000000..4508447 --- /dev/null +++ b/src/tbb/build/SunOS.gcc.inc @@ -0,0 +1,102 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +COMPILE_ONLY = -c -MMD +PREPROC_ONLY = -E -x c++ +INCLUDE_KEY = -I +DEFINE_KEY = -D +OUTPUT_KEY = -o # +OUTPUTOBJ_KEY = -o # +PIC_KEY = -fPIC +WARNING_AS_ERROR_KEY = -Werror +WARNING_KEY = -Wall +TEST_WARNING_KEY = -Wshadow -Wcast-qual -Woverloaded-virtual -Wnon-virtual-dtor $(if $(findstring cc4., $(runtime)),-Wextra) +WARNING_SUPPRESS = -Wno-parentheses -Wno-non-virtual-dtor +DYLIB_KEY = -shared +LIBDL = -ldl + +TBB_NOSTRICT = 1 + +CPLUS = g++ +CONLY = gcc +LIB_LINK_FLAGS = -shared +LIBS = -lpthread -lrt -ldl +C_FLAGS = $(CPLUS_FLAGS) -x c + +ifeq ($(cfg), release) + CPLUS_FLAGS = -O2 -DUSE_PTHREAD +endif +ifeq ($(cfg), debug) + CPLUS_FLAGS = -DTBB_USE_DEBUG -g -O0 -DUSE_PTHREAD +endif + +ASM= +ASM_FLAGS= + +TBB_ASM.OBJ= + +ifeq (ia64,$(arch)) +# Position-independent code (PIC) is a must for IA-64 + CPLUS_FLAGS += $(PIC_KEY) +endif + +ifeq (intel64,$(arch)) + CPLUS_FLAGS += -m64 + LIB_LINK_FLAGS += -m64 +endif + +ifeq (ia32,$(arch)) + CPLUS_FLAGS += -m32 + LIB_LINK_FLAGS += -m32 +endif + +# for some gcc versions on Solaris, -m64 may imply V9, but perhaps not everywhere (TODO: verify) +ifeq (sparc,$(arch)) + CPLUS_FLAGS += -mcpu=v9 -m64 + LIB_LINK_FLAGS += -mcpu=v9 -m64 +endif + +#------------------------------------------------------------------------------ +# Setting assembler data. +#------------------------------------------------------------------------------ +ASSEMBLY_SOURCE=$(arch)-gas +ifeq (ia64,$(arch)) + ASM=ias + TBB_ASM.OBJ = atomic_support.o lock_byte.o log2.o pause.o +endif +#------------------------------------------------------------------------------ +# End of setting assembler data. +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# Setting tbbmalloc data. +#------------------------------------------------------------------------------ + +M_CPLUS_FLAGS = $(CPLUS_FLAGS) -fno-rtti -fno-exceptions -fno-schedule-insns2 + +#------------------------------------------------------------------------------ +# End of setting tbbmalloc data. +#------------------------------------------------------------------------------ diff --git a/src/tbb/build/SunOS.inc b/src/tbb/build/SunOS.inc new file mode 100644 index 0000000..4b4e854 --- /dev/null +++ b/src/tbb/build/SunOS.inc @@ -0,0 +1,92 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +ifndef arch + arch:=$(shell uname -p) + ifeq ($(arch),i386) + ifeq ($(shell isainfo -b),64) + arch:=intel64 + else + arch:=ia32 + endif + endif + export arch +# For non-IA systems running Sun OS, 'arch' will contain whatever is printed by uname -p. +# In particular, for SPARC architecture it will contain "sparc". +endif + +ifndef runtime + gcc_version:=$(shell gcc -v 2>&1 | grep 'gcc version' | sed -e 's/^gcc version //' | sed -e 's/ .*$$//') + os_version:=$(shell uname -r) + os_kernel_version:=$(shell uname -r | sed -e 's/-.*$$//') + export runtime:=cc$(gcc_version)_kernel$(os_kernel_version) +endif + +ifeq ($(arch),sparc) + native_compiler := gcc + export compiler ?= gcc +else + native_compiler := suncc + export compiler ?= suncc +endif +# debugger ?= gdb + +CMD=$(SHELL) -c +CWD=$(shell pwd) +RM?=rm -f +RD?=rmdir +MD?=mkdir -p +NUL= /dev/null +SLASH=/ +MAKE_VERSIONS=bash $(tbb_root)/build/version_info_sunos.sh $(CPLUS) $(CPLUS_FLAGS) $(INCLUDES) >version_string.ver +MAKE_TBBVARS=bash $(tbb_root)/build/generate_tbbvars.sh + +ifdef LD_LIBRARY_PATH + export LD_LIBRARY_PATH := .:$(LD_LIBRARY_PATH) +else + export LD_LIBRARY_PATH := . +endif + +####### Build settings ######################################################## + +OBJ = o +DLL = so +LIBEXT=so + +TBB.LST = +TBB.DEF = +TBB.DLL = libtbb$(CPF_SUFFIX)$(DEBUG_SUFFIX).$(DLL) +TBB.LIB = $(TBB.DLL) +LINK_TBB.LIB = $(TBB.LIB) + +MALLOC.DLL = libtbbmalloc$(DEBUG_SUFFIX).$(DLL) +MALLOC.LIB = $(MALLOC.DLL) + +MALLOCPROXY.DLL = libtbbmalloc_proxy$(DEBUG_SUFFIX).$(DLL) + +TBB_NOSTRICT=1 + +TEST_LAUNCHER=sh $(tbb_root)/build/test_launcher.sh diff --git a/src/tbb/build/SunOS.suncc.inc b/src/tbb/build/SunOS.suncc.inc new file mode 100644 index 0000000..46add22 --- /dev/null +++ b/src/tbb/build/SunOS.suncc.inc @@ -0,0 +1,99 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +COMPILE_ONLY = -c -xMMD -errtags +PREPROC_ONLY = -E -xMMD +INCLUDE_KEY = -I +DEFINE_KEY = -D +OUTPUT_KEY = -o # +OUTPUTOBJ_KEY = -o # +PIC_KEY = -KPIC +DYLIB_KEY = -G +LIBDL = -ldl +# WARNING_AS_ERROR_KEY = -errwarn=%all +WARNING_AS_ERROR_KEY = Warning as error +# Supported Solaris Studio* 12.2 and above, remove ',inlasmpnu' in the line below to build by compiler prior Solaris Studio* 12.2 +WARNING_SUPPRESS = -erroff=unassigned,attrskipunsup,badargtype2w,badbinaryopw,wbadasg,wvarhidemem,inlasmpnu +tbb_strict=0 + +TBB_NOSTRICT = 1 + +CPLUS = CC +CONLY = cc +LIB_LINK_FLAGS = -G -R . -M$(tbb_root)/build/suncc.map.pause +LINK_FLAGS += -M$(tbb_root)/build/suncc.map.pause +LIBS = -lpthread -lrt -R . +C_FLAGS = $(CPLUS_FLAGS) + +ifeq ($(cfg), release) + CPLUS_FLAGS = -mt -xO2 -library=stlport4 -DUSE_PTHREAD $(WARNING_SUPPRESS) +endif +ifeq ($(cfg), debug) + CPLUS_FLAGS = -mt -DTBB_USE_DEBUG -g -library=stlport4 -DUSE_PTHREAD $(WARNING_SUPPRESS) +endif + +ASM= +ASM_FLAGS= + +TBB_ASM.OBJ= + +ifeq (intel64,$(arch)) + CPLUS_FLAGS += -m64 + ASM_FLAGS += -m64 + LIB_LINK_FLAGS += -m64 +endif + +ifeq (ia32,$(arch)) + CPLUS_FLAGS += -m32 + LIB_LINK_FLAGS += -m32 +endif + +# TODO: verify whether -m64 implies V9 on relevant Sun Studio versions +# (those that handle gcc assembler syntax) +ifeq (sparc,$(arch)) + CPLUS_FLAGS += -m64 + LIB_LINK_FLAGS += -m64 +endif + +export TBB_CUSTOM_VARS_SH=export CXXFLAGS="-I$${TBBROOT}/include -library=stlport4 $(CXXFLAGS) -M$${TBBROOT}/build/suncc.map.pause" +export TBB_CUSTOM_VARS_CSH=setenv CXXFLAGS "-I$${TBBROOT}/include -library=stlport4 $(CXXFLAGS) -M$${TBBROOT}/build/suncc.map.pause" + +#------------------------------------------------------------------------------ +# Setting assembler data. +#------------------------------------------------------------------------------ +ASSEMBLY_SOURCE=$(arch)-fbe +#------------------------------------------------------------------------------ +# End of setting assembler data. +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# Setting tbbmalloc data. +#------------------------------------------------------------------------------ +M_INCLUDES = $(INCLUDES) -I$(MALLOC_ROOT) -I$(MALLOC_SOURCE_ROOT) +M_CPLUS_FLAGS = $(CPLUS_FLAGS) +#------------------------------------------------------------------------------ +# End of setting tbbmalloc data. +#------------------------------------------------------------------------------ diff --git a/src/tbb/build/big_iron.inc b/src/tbb/build/big_iron.inc new file mode 100644 index 0000000..c76f116 --- /dev/null +++ b/src/tbb/build/big_iron.inc @@ -0,0 +1,74 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +#------------------------------------------------------------------------------ +# Defines settings for building the TBB run-time as a static library. +# Use these only on platforms where dynamic linking is impractical. +# +# IF YOU USE TBB AS A STATIC LIBRARY, YOU MUST GUARANTEE THAT ONLY ONE COPY OF +# THE TBB RUN-TIME IS LINKED INTO AN APPLICATION! LINKING IN MULTIPLE COPIES +# OF THE TBB RUN-TIME, DIRECTLY OR INDIRECTLY, MAY CAUSE PROGRAM FAILURE! +#------------------------------------------------------------------------------ + +# Note that ITT_NOTIFY allows to selectively remove the definition of +# DO_ITT_NOTIFY without sabotaging deferred expansion of CPLUS_FLAGS. +# TODO: currently only in linux.{gcc,xl}.inc + +# Note that -pthread with xl gives "1501-210 (W) command option t contains an incorrect subargument"; +# multithreading is instead achieved by using the _r affix in the compiler name. +# TODO: is -lpthread still relevant/needed with XL and _r affix? + +# Note that -D__TBB_NO_DLOPEN is only for scalability, +# and is not necessarily needed by any static build. + +# OS specific settings => + LIB_LINK_CMD = ar rcs + LIB_LINK_FLAGS = + LIB_LINK_LIBS = + LIB_OUTPUT_KEY = + ifeq ($(tbb_os),linux) + ifeq ($(compiler),gcc) + LIBS = -pthread -ldl -lrt + endif + ifeq ($(compiler),xl) + LIBS = -lpthread -ldl -lrt + endif + LINK_FLAGS = + endif + override CXXFLAGS += -D__TBB_DYNAMIC_LOAD_ENABLED=0 -D__TBB_SOURCE_DIRECTLY_INCLUDED=1 + ITT_NOTIFY = + LIBEXT = a + LIBPREF = lib +# <= OS specific settings + +TBB.DLL = $(LIBPREF)tbb$(DEBUG_SUFFIX).$(LIBEXT) +TBB.LST = +TBB.DEF = +MALLOC.DLL = $(LIBPREF)tbbmalloc$(DEBUG_SUFFIX).$(LIBEXT) +MALLOC.DEF = +MALLOCPROXY.DLL = +MALLOCPROXY.DEF = +LINK_TBB.LIB = $(TBB.DLL) diff --git a/src/tbb/build/codecov.txt b/src/tbb/build/codecov.txt new file mode 100644 index 0000000..e22f805 --- /dev/null +++ b/src/tbb/build/codecov.txt @@ -0,0 +1,7 @@ +src/tbb +src/tbbmalloc +include/tbb +src/rml/server +src/rml/client +src/rml/include +source/malloc diff --git a/src/tbb/build/common.inc b/src/tbb/build/common.inc new file mode 100644 index 0000000..b1b3034 --- /dev/null +++ b/src/tbb/build/common.inc @@ -0,0 +1,116 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +ifndef tbb_os + + # Windows sets environment variable OS; for other systems, ask uname + ifeq ($(OS),) + OS:=$(shell uname) + ifeq ($(OS),) + $(error "Cannot detect operating system") + endif + export tbb_os=$(OS) + endif + + ifeq ($(OS), Windows_NT) + export tbb_os=windows + endif + ifeq ($(OS), Linux) + export tbb_os=linux + endif + ifeq ($(OS), Darwin) + export tbb_os=macos + endif + +endif # !tbb_os + +ifeq ($(tbb_cpf),1) + export CPF_SUFFIX ?=_preview +endif + +ifeq ($(wildcard $(tbb_root)/build/$(tbb_os).inc),) + $(error "$(tbb_os)" is not supported. Add build/$(tbb_os).inc file with os-specific settings ) +endif + +# detect arch and runtime versions, provide common os-specific definitions +include $(tbb_root)/build/$(tbb_os).inc + +ifeq ($(arch),) + $(error Architecture not detected) +endif +ifeq ($(runtime),) + $(error Runtime version not detected) +endif +ifeq ($(wildcard $(tbb_root)/build/$(tbb_os).$(compiler).inc),) + $(error Compiler "$(compiler)" is not supported on $(tbb_os). Add build/$(tbb_os).$(compiler).inc file with compiler-specific settings ) +endif + +ifdef target + ifeq ($(wildcard $(tbb_root)/build/$(target).inc),) + $(error "$(target)" is not supported. Add build/$(target).inc file) + endif + include $(tbb_root)/build/$(target).inc +endif + +# Support for running debug tests to release library and vice versa +flip_cfg=$(subst _flipcfg,_release,$(subst _release,_debug,$(subst _debug,_flipcfg,$(1)))) +cross_cfg = $(if $(crosstest),$(call flip_cfg,$(1)),$(1)) + +ifdef BUILDING_PHASE + # Setting default configuration to release + cfg?=release + # No lambas or other C++0x extensions by default for compilers that implement them as experimental features + # TODO: it should become unnecessary when all relevant tests are "moved" to the TEST_TBB_CPP11 set + lambdas ?= 0 + cpp0x ?= 0 + # include compiler-specific build configurations + -include $(tbb_root)/build/$(tbb_os).$(compiler).inc + ifdef extra_inc + -include $(tbb_root)/build/$(extra_inc) + endif +endif +ifneq ($(BUILDING_PHASE),1) + # definitions for top-level Makefiles + origin_build_dir:=$(origin tbb_build_dir) + tbb_build_dir?=$(tbb_root)$(SLASH)build + tbb_build_prefix?=$(tbb_os)_$(arch)_$(compiler)_$(runtime) + work_dir=$(tbb_build_dir)$(SLASH)$(tbb_build_prefix) + ifneq ($(BUILDING_PHASE),0) + work_dir:=$(work_dir) + # assign new value for tbb_root if path is not absolute (the filter keeps only /* paths) + ifeq ($(filter /% $(SLASH)%, $(subst :, ,$(tbb_root)) ),) + ifeq ($(origin_build_dir),undefined) + override tbb_root:=../.. + else + override tbb_root:=$(CWD)/$(tbb_root) + endif + endif + export tbb_root + endif # BUILDING_PHASE != 0 +endif # BUILDING_PHASE != 1 + +.DELETE_ON_ERROR: # Make will delete target if error occurred when building it. + diff --git a/src/tbb/build/common_rules.inc b/src/tbb/build/common_rules.inc new file mode 100644 index 0000000..6aa20f2 --- /dev/null +++ b/src/tbb/build/common_rules.inc @@ -0,0 +1,129 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +ifeq ($(tbb_strict),1) + ifeq ($(WARNING_AS_ERROR_KEY),) + $(error WARNING_AS_ERROR_KEY is empty) + endif + # Do not remove line below! + WARNING_KEY += $(WARNING_AS_ERROR_KEY) +endif + +ifndef TEST_EXT + TEST_EXT = exe +endif + +.PRECIOUS: %.$(OBJ) %.$(TEST_EXT) %.res + +INCLUDES += $(INCLUDE_KEY)$(tbb_root)/src $(INCLUDE_KEY)$(tbb_root)/src/rml/include $(INCLUDE_KEY)$(tbb_root)/include + +CPLUS_FLAGS += $(WARNING_KEY) $(CXXFLAGS) +ifeq ($(tbb_cpf),1) +CPLUS_FLAGS += $(DEFINE_KEY)__TBB_CPF_BUILD=1 +endif +LINK_FLAGS += $(LDFLAGS) +LIB_LINK_FLAGS += $(LDFLAGS) +CPLUS_FLAGS_NOSTRICT = $(subst -strict-ansi,-ansi,$(CPLUS_FLAGS)) + +LIB_LINK_CMD ?= $(CPLUS) $(PIC_KEY) +ifeq ($(origin LIB_OUTPUT_KEY), undefined) + LIB_OUTPUT_KEY = $(OUTPUT_KEY) +endif +ifeq ($(origin LIB_LINK_LIBS), undefined) + LIB_LINK_LIBS = $(LIBDL) $(LIBS) +endif + +CONLY ?= $(CPLUS) + +# The most generic rules +%.$(OBJ): %.cpp + $(CPLUS) $(COMPILE_ONLY) $(CPLUS_FLAGS) $(CXX_ONLY_FLAGS) $(CXX_WARN_SUPPRESS) $(INCLUDES) $< + +%.$(OBJ): %.c + $(CONLY) $(COMPILE_ONLY) $(C_FLAGS) $(INCLUDES) $< + +%.$(OBJ): %.asm + $(ASM) $(ASM_FLAGS) $< + +%.$(OBJ): %.s + cpp <$< | grep -v '^#' >$*.tmp + $(ASM) $(ASM_FLAGS) -o $@ $*.tmp + +# Rule for generating .E file if needed for visual inspection +# Note that due to mapping for ICL all uses of PREPROC_ONLY should be immediately followed by a file name +%.E: %.cpp + $(CPLUS) $(CPLUS_FLAGS) $(CXX_ONLY_FLAGS) $(INCLUDES) $(PREPROC_ONLY) $< >$@ + +# TODO Rule for generating .asm file if needed for visual inspection +%.asm: %.cpp + $(CPLUS) /c /FAs /Fa $(CPLUS_FLAGS) $(CXX_ONLY_FLAGS) $(INCLUDES) $< + +# TODO Rule for generating .s file if needed for visual inspection +%.s: %.cpp + $(CPLUS) -S $(CPLUS_FLAGS) $(CXX_ONLY_FLAGS) $(INCLUDES) $< + +# Customizations + +ifeq (1,$(TBB_NOSTRICT)) +# GNU 3.2.3 headers have a ISO syntax that is rejected by Intel compiler in -strict-ansi mode. +# The Mac uses gcc, so the list is empty for that platform. +# The files below need the -strict-ansi flag downgraded to -ansi to compile + +$(KNOWN_NOSTRICT): %.$(OBJ): %.cpp + $(CPLUS) $(COMPILE_ONLY) $(CPLUS_FLAGS_NOSTRICT) $(CXX_ONLY_FLAGS) $(CXX_WARN_SUPPRESS) $(INCLUDES) $< +endif + +$(KNOWN_WARNINGS): %.$(OBJ): %.cpp + $(CPLUS) $(COMPILE_ONLY) $(subst $(WARNING_KEY),,$(CPLUS_FLAGS)) $(CXX_ONLY_FLAGS) $(CXX_WARN_SUPPRESS) $(INCLUDES) $< + +tbb_misc.$(OBJ): tbb_misc.cpp version_string.ver + $(CPLUS) $(COMPILE_ONLY) $(CPLUS_FLAGS) $(CXX_ONLY_FLAGS) $(CXX_WARN_SUPPRESS) $(INCLUDE_KEY). $(INCLUDES) $< + +tbb_misc.E: tbb_misc.cpp version_string.ver + $(CPLUS) $(CPLUS_FLAGS) $(CXX_ONLY_FLAGS) $(INCLUDE_KEY). $(INCLUDES) $(PREPROC_ONLY) $< >$@ + +%.res: %.rc version_string.ver $(TBB.MANIFEST) + rc /Fo$@ $(INCLUDES) $(filter /D%,$(CPLUS_FLAGS)) $< + +ifneq (,$(TBB.MANIFEST)) +$(TBB.MANIFEST): + cmd /C "echo #include ^ >tbbmanifest.c" + cmd /C "echo int main(){return 0;} >>tbbmanifest.c" + cl /nologo $(C_FLAGS) tbbmanifest.c + +version_string.ver: $(TBB.MANIFEST) + $(MAKE_VERSIONS) + cmd /C "echo #define TBB_MANIFEST 1 >> version_string.ver" + +else +version_string.ver: + $(MAKE_VERSIONS) +endif + + +# Rules for generating a test DLL +%_dll.$(OBJ): %.cpp + $(CPLUS) $(COMPILE_ONLY) $(OUTPUTOBJ_KEY)$@ $(CPLUS_FLAGS) $(PIC_KEY) $(DEFINE_KEY)_USRDLL $(INCLUDES) $< diff --git a/src/tbb/build/detect.js b/src/tbb/build/detect.js new file mode 100644 index 0000000..894422b --- /dev/null +++ b/src/tbb/build/detect.js @@ -0,0 +1,183 @@ +// Copyright 2005-2012 Intel Corporation. All Rights Reserved. +// +// This file is part of Threading Building Blocks. +// +// Threading Building Blocks is free software; you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// Threading Building Blocks is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Threading Building Blocks; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +function doWork() { + var WshShell = WScript.CreateObject("WScript.Shell"); + + var fso = new ActiveXObject("Scripting.FileSystemObject"); + + var tmpExec; + tmpExec = WshShell.Run("cmd /c echo int main(){return 0;} >detect.c", 0, true); + + // The next block deals with GCC (MinGW) + if ( WScript.Arguments.Count() > 1 && WScript.Arguments(1) == "gcc" ) { + if ( WScript.Arguments(0) == "/arch" ) { + // Get predefined macros + tmpExec = WshShell.Run("cmd /C gcc -dM -E detect.c > detect.map", 0, true); + var file = fso.OpenTextFile("detect.map", 1, 0); + var defs = file.readAll(); + file.Close(); + + //detect target architecture + var intel64=/x86_64|amd64/mgi; + var ia32=/i386/mgi; + if ( defs.match(intel64) ) { + WScript.Echo( "intel64" ); + } else if ( defs.match(ia32) ) { + WScript.Echo( "ia32" ); + } else { + WScript.Echo( "unknown" ); + } + } else { + tmpExec = WshShell.Exec("gcc -dumpversion"); + var gcc_version = tmpExec.StdOut.ReadLine(); + if ( WScript.Arguments(0) == "/runtime" ) { + WScript.Echo( "mingw"+gcc_version ); + } + else if ( WScript.Arguments(0) == "/minversion" ) { + // Comparing strings, not numbers; will not work for two-digit versions + if ( gcc_version >= WScript.Arguments(2) ) { + WScript.Echo( "ok" ); + } else { + WScript.Echo( "fail" ); + } + } + } + return; + } + + //Compile binary + tmpExec = WshShell.Exec("cl /MD detect.c /link /MAP"); + while ( tmpExec.Status == 0 ) { + WScript.Sleep(100); + } + //compiler banner that includes version and target arch was printed to stderr + var clVersion = tmpExec.StdErr.ReadAll(); + + if ( WScript.Arguments(0) == "/arch" ) { + //detect target architecture + var intel64=/AMD64|EM64T|x64/mgi; + var ia64=/IA-64|Itanium/mgi; + var ia32=/[80|\s]x86/mgi; + if ( clVersion.match(intel64) ) { + WScript.Echo( "intel64" ); + } else if ( clVersion.match(ia64) ) { + WScript.Echo( "ia64" ); + } else if ( clVersion.match(ia32) ) { + WScript.Echo( "ia32" ); + } else { + WScript.Echo( "unknown" ); + } + return; + } + + if ( WScript.Arguments(0) == "/runtime" ) { + //read map-file + var map = fso.OpenTextFile("detect.map", 1, 0); + var mapContext = map.readAll(); + map.Close(); + + //detect runtime + var vc71=/MSVCR71\.DLL/mgi; + var vc80=/MSVCR80\.DLL/mgi; + var vc90=/MSVCR90\.DLL/mgi; + var vc100=/MSVCR100\.DLL/mgi; + var vc110=/MSVCR110\.DLL/mgi; + var psdk=/MSVCRT\.DLL/mgi; + if ( mapContext.match(vc71) ) { + WScript.Echo( "vc7.1" ); + } else if ( mapContext.match(vc80) ) { + WScript.Echo( "vc8" ); + } else if ( mapContext.match(vc90) ) { + WScript.Echo( "vc9" ); + } else if ( mapContext.match(vc100) ) { + WScript.Echo( "vc10" ); + } else if ( mapContext.match(vc110) ) { + WScript.Echo( "vc11" ); + } else { + WScript.Echo( "unknown" ); + } + return; + } + + if ( WScript.Arguments(0) == "/minversion" ) { + var compiler_version; + if ( WScript.Arguments(1) == "cl" ) { + compiler_version = clVersion.match(/Compiler Version ([0-9.]+)\s/mi)[1]; + // compiler_version is in xx.xx.xxxxx.xx format, i.e. a string. + // It will compare well with major.minor versions where major has two digits, + // which is sufficient as the versions of interest start from 13 (for VC7). + } else if ( WScript.Arguments(1) == "icl" ) { + // Get predefined ICL macros + tmpExec = WshShell.Run("cmd /C icl /QdM /E detect.c > detect.map", 0, true); + var file = fso.OpenTextFile("detect.map", 1, 0); + var defs = file.readAll(); + file.Close(); + // In #define __INTEL_COMPILER XXYY, XX is the major ICL version, YY is minor + compiler_version = defs.match(/__INTEL_COMPILER[ \t]*([0-9]+).*$/mi)[1]/100; + // compiler version is a number; it compares well with another major.minor + // version number, where major has one, two, and perhaps more digits (9.1, 11, etc). + } + if ( compiler_version >= WScript.Arguments(2) ) { + WScript.Echo( "ok" ); + } else { + WScript.Echo( "fail" ); + } + return; + } +} + +function doClean() { + var fso = new ActiveXObject("Scripting.FileSystemObject"); + // delete intermediate files + if ( fso.FileExists("detect.c") ) + fso.DeleteFile ("detect.c", false); + if ( fso.FileExists("detect.obj") ) + fso.DeleteFile ("detect.obj", false); + if ( fso.FileExists("detect.map") ) + fso.DeleteFile ("detect.map", false); + if ( fso.FileExists("detect.exe") ) + fso.DeleteFile ("detect.exe", false); + if ( fso.FileExists("detect.exe.manifest") ) + fso.DeleteFile ("detect.exe.manifest", false); +} + +if ( WScript.Arguments.Count() > 0 ) { + + try { + doWork(); + } catch( error ) { + WScript.Echo( "unknown" ); + } + doClean(); + +} else { + WScript.Echo( "Supported options:\n" + + "\t/arch [compiler]\n" + + "\t/runtime [compiler]\n" + + "\t/minversion compiler version" ); +} + diff --git a/src/tbb/build/generate_tbbvars.bat b/src/tbb/build/generate_tbbvars.bat new file mode 100644 index 0000000..d64adef --- /dev/null +++ b/src/tbb/build/generate_tbbvars.bat @@ -0,0 +1,74 @@ +@echo off +REM +REM Copyright 2005-2012 Intel Corporation. All Rights Reserved. +REM +REM This file is part of Threading Building Blocks. +REM +REM Threading Building Blocks is free software; you can redistribute it +REM and/or modify it under the terms of the GNU General Public License +REM version 2 as published by the Free Software Foundation. +REM +REM Threading Building Blocks is distributed in the hope that it will be +REM useful, but WITHOUT ANY WARRANTY; without even the implied warranty +REM of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +REM GNU General Public License for more details. +REM +REM You should have received a copy of the GNU General Public License +REM along with Threading Building Blocks; if not, write to the Free Software +REM Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +REM +REM As a special exception, you may use this file as part of a free software +REM library without restriction. Specifically, if other files instantiate +REM templates or use macros or inline functions from this file, or you compile +REM this file and link it with other files to produce an executable, this +REM file does not by itself cause the resulting executable to be covered by +REM the GNU General Public License. This exception does not however +REM invalidate any other reasons why the executable file might be covered by +REM the GNU General Public License. +REM +setlocal +for %%D in ("%tbb_root%") do set actual_root=%%~fD +set fslash_root=%actual_root:\=/% +set bin_dir=%CD% +set fslash_bin_dir=%bin_dir:\=/% +set _INCLUDE=INCLUDE& set _LIB=LIB +if not x%UNIXMODE%==x set _INCLUDE=CPATH& set _LIB=LIBRARY_PATH + +if exist tbbvars.bat goto skipbat +echo Generating local tbbvars.bat +echo @echo off>tbbvars.bat +echo SET TBBROOT=%actual_root%>>tbbvars.bat +echo SET TBB_ARCH_PLATFORM=%arch%\%runtime%>>tbbvars.bat +echo SET TBB_TARGET_ARCH=%arch%>>tbbvars.bat +echo SET %_INCLUDE%=%%TBBROOT%%\include;%%%_INCLUDE%%%>>tbbvars.bat +echo SET %_LIB%=%bin_dir%;%%%_LIB%%%>>tbbvars.bat +echo SET PATH=%bin_dir%;%%PATH%%>>tbbvars.bat +if not x%UNIXMODE%==x echo SET LD_LIBRARY_PATH=%bin_dir%;%%LD_LIBRARY_PATH%%>>tbbvars.bat +:skipbat + +if exist tbbvars.sh goto skipsh +echo Generating local tbbvars.sh +echo #!/bin/sh>tbbvars.sh +echo export TBBROOT="%fslash_root%">>tbbvars.sh +echo export TBB_ARCH_PLATFORM="%arch%\%runtime%">>tbbvars.sh +echo export TBB_TARGET_ARCH="%arch%">>tbbvars.sh +echo export %_INCLUDE%="${TBBROOT}/include;$%_INCLUDE%">>tbbvars.sh +echo export %_LIB%="%fslash_bin_dir%;$%_LIB%">>tbbvars.sh +echo export PATH="%fslash_bin_dir%;$PATH">>tbbvars.sh +if not x%UNIXMODE%==x echo export LD_LIBRARY_PATH="%fslash_bin_dir%;$LD_LIBRARY_PATH">>tbbvars.sh +:skipsh + +if exist tbbvars.csh goto skipcsh +echo Generating local tbbvars.csh +echo #!/bin/csh>tbbvars.csh +echo setenv TBBROOT "%actual_root%">>tbbvars.csh +echo setenv TBB_ARCH_PLATFORM "%arch%\%runtime%">>tbbvars.csh +echo setenv TBB_TARGET_ARCH "%arch%">>tbbvars.csh +echo setenv %_INCLUDE% "${TBBROOT}\include;$%_INCLUDE%">>tbbvars.csh +echo setenv %_LIB% "%bin_dir%;$%_LIB%">>tbbvars.csh +echo setenv PATH "%bin_dir%;$PATH">>tbbvars.csh +if not x%UNIXMODE%==x echo setenv LD_LIBRARY_PATH "%bin_dir%;$LD_LIBRARY_PATH">>tbbvars.csh +:skipcsh + +endlocal +exit diff --git a/src/tbb/build/generate_tbbvars.sh b/src/tbb/build/generate_tbbvars.sh new file mode 100644 index 0000000..dad0319 --- /dev/null +++ b/src/tbb/build/generate_tbbvars.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Script used to generate tbbvars.[c]sh scripts +bin_dir="$PWD" # +cd "$tbb_root" # keep this comments here +tbb_root="$PWD" # to make it unsensible +cd "$bin_dir" # to EOL encoding +[ "`uname`" = "Darwin" ] && dll_path="DYLD_LIBRARY_PATH" || dll_path="LD_LIBRARY_PATH" # +[ -f ./tbbvars.sh ] || cat >./tbbvars.sh <./tbbvars.csh < + + +

Overview

+This directory contains the internal Makefile infrastructure for Threading Building Blocks. + +

+See below for how to build TBB and how to port TBB +to a new platform, operating system or architecture. +

+ +

Files

+The files here are not intended to be used directly. See below for usage. +
+
Makefile.tbb +
Main Makefile to build the TBB library. + Invoked via 'make tbb' from top-level Makefile. +
Makefile.tbbmalloc +
Main Makefile to build the TBB scalable memory allocator library as well as its tests. + Invoked via 'make tbbmalloc' from top-level Makefile. +
Makefile.test +
Main Makefile to build and run the tests for the TBB library. + Invoked via 'make test' from top-level Makefile. +
common.inc +
Main common included Makefile that includes OS-specific and compiler-specific Makefiles. +
<os>.inc +
OS-specific Makefile for a particular <os>. +
<os>.<compiler>.inc +
Compiler-specific Makefile for a particular <os> / <compiler> combination. +
*.sh +
Infrastructure utilities for Linux*, Mac OS* X, and UNIX*-related systems. +
*.js, *.bat +
Infrastructure utilities for Windows* systems. +
+ +

To Build

+

+To port TBB to a new platform, operating system or architecture, see the porting directions below. +

+ +

Software prerequisites:

+
    +
  1. C++ compiler for the platform, operating system and architecture of interest. + Either the native compiler for your system, or, optionally, the appropriate Intel® C++ compiler, may be used. +
  2. GNU make utility. On Windows*, if a UNIX* emulator is used to run GNU make, + it should be able to run Windows* utilities and commands. On Linux*, Mac OS* X, etc., + shell commands issued by GNU make should execute in a Bourne or BASH compatible shell. +
+ +

+TBB libraries can be built by performing the following steps. +On systems that support only one ABI (e.g., 32-bit), these steps build the libraries for that ABI. +On systems that support both 64-bit and 32-bit libraries, these steps build the 64-bit libraries +(Linux*, Mac OS* X, and related systems) or whichever ABI is selected in the development environment (Windows* systems). +

+
    +
  1. Change to the top-level directory of the installed software. +
  2. If using the Intel® C++ compiler, make sure the appropriate compiler is available in your PATH + (e.g., by sourcing the appropriate iccvars script for the compiler to be used). +
  3. Invoke GNU make using no arguments, for example, 'gmake'. +
+ +

+To build TBB libraries for other than the default ABI (e.g., to build 32-bit libraries on Linux*, Mac OS* X, +or related systems that support both 64-bit and 32-bit libraries), perform the following steps. +

+
    +
  1. Change to the top-level directory of the installed software. +
  2. If using the Intel® C++ compiler, make sure the appropriate compiler is available in your PATH + (e.g., by sourcing the appropriate iccvars script for the compiler to be used). +
  3. Invoke GNU make as follows, 'gmake arch=ia32'. +
+ +

The default make target will build the release and debug versions of the TBB library.

+

Other targets are available in the top-level Makefile. You might find the following targets useful: +

    +
  • 'make test' will build and run TBB unit-tests; +
  • 'make examples' will build and run TBB examples; +
  • 'make all' will do all of the above. +
+See also the list of other targets below. +

+ +

+By default, the libraries will be built in sub-directories within the build/ directory. +The sub-directories are named according to the operating system, architecture, compiler and software environment used +(the sub-directory names also distinguish release vs. debug libraries). On Linux*, the software environment comprises +the GCC, libc and kernel version used. On Mac OS* X, the software environment comprises the GCC and OS version used. +On Windows, the software environment comprises the Microsoft* Visual Studio* version used. +See below for how to change the default build directory. +

+ +

+To perform different build and/or test operations, use the following steps. +

+
    +
  1. Change to the top-level directory of the installed software. +
  2. If using the Intel® C++ compiler, make sure the appropriate compiler is available in your PATH + (e.g., by sourcing the appropriate iccvars script for the compiler to be used). +
  3. Invoke GNU make by using one or more of the following commands. +
    +
    make +
    Default build. Equivalent to 'make tbb tbbmalloc'. +
    make all +
    Equivalent to 'make tbb tbbmalloc test examples'. +
    cd src;make release +
    Build and test release libraries only. +
    cd src;make debug +
    Build and test debug libraries only. +
    make tbb +
    Make TBB release and debug libraries. +
    make tbbmalloc +
    Make TBB scalable memory allocator libraries. +
    make test +
    Compile and run unit-tests +
    make examples +
    Build libraries and run all examples, like doing 'make debug clean release' from + the general example Makefile. +
    make compiler={icl, icc} [(above options or targets)] +
    Build and run as above, but use Intel® compilers instead of default, native compilers + (e.g., icl instead of cl.exe on Windows* systems, or icc instead of g++ on Linux* or Mac OS* X systems). +
    make arch={ia32, intel64, ia64} [(above options or targets)] +
    Build and run as above, but build libraries for the selected ABI. + Might be useful for cross-compilation; ensure proper environment is set before running this command. +
    make tbb_root={(TBB directory)} [(above options or targets)] +
    Build and run as above; for use when invoking 'make' from a directory other than + the top-level directory. +
    make tbb_build_dir={(build directory)} [(above options or targets)] +
    Build and run as above, but place the built libraries in the specified directory, rather than in the default + sub-directory within the build/ directory. This command might have troubles with the build in case the sources + installed to the directory with spaces in the path. +
    make tbb_build_prefix={(build sub-directory)} [(above options or targets)] +
    Build and run as above, but place the built libraries in the specified sub-directory within the build/ directory, + rather than using the default sub-directory name. +
    make tbb_cpf=1 [(above options or targets)] +
    Build and run as above, but build and use libraries with the Community Preview Features enabled, + rather than the default libraries. +
    make [(above options)] clean +
    Remove any executables or intermediate files produced by the above commands. + Includes build directories, object files, libraries and test executables. +
    +
+ +

To Port

+

+This section provides information on how to port TBB to a new platform, operating system or architecture. +A subset or a superset of these steps may be required for porting to a given platform. +

+ +

To port the TBB source code:

+
    +
  1. If porting to a new architecture, create a file that describes the architecture-specific details for that architecture. +
      +
    • Create a <os>_<architecture>.h file in the include/tbb/machine directory + that describes these details. +
        +
      • The <os>_<architecture>.h is named after the operating system and architecture as recognized by + include/tbb/tbb_machine.h and the Makefile infrastructure. +
      • This file defines the implementations of synchronization operations, and also the + scheduler yield function, for the operating system and architecture. +
      • Several examples of <os>_<architecture>.h files can be found in the + include/tbb/machine directory. +
          +
        • A minimal implementation defines the 4-byte and 8-byte compare-and-swap operations, + and the scheduler yield function. See include/tbb/machine/mac_ppc.h + for an example of a minimal implementation. +
        • More complex implementation examples can also be found in the + include/tbb/machine directory + that implement all the individual variants of synchronization operations that TBB uses. + Such implementations are more verbose but may achieve better performance on a given architecture. +
        • In a given implementation, any synchronization operation that is not defined is implemented, by default, + in terms of 4-byte or 8-byte compare-and-swap. More operations can thus be added incrementally to increase + the performance of an implementation. +
        • In most cases, synchronization operations are implemented as inline assembly code; examples also exist, + (e.g., for Intel® Itanium® processors) that use out-of-line assembly code in *.s or *.asm files + (see the assembly code sub-directories in the src/tbb directory). +
        +
      +
    • Modify include/tbb/tbb_machine.h, if needed, to invoke the appropriate + <os>_<architecture>.h file in the include/tbb/machine directory. +
    +
  2. Add an implementation of DetectNumberOfWorkers() in src/tbb/tbb_misc.h, + if needed, that returns the number of cores found on the system. This is used to determine the default + number of threads for the TBB task scheduler. +
  3. Either properly define FillDynamicLinks for use in + src/tbb/cache_aligned_allocator.cpp, + or hardcode the allocator to be used. +
  4. Additional types might be required in the union defined in + include/tbb/aligned_space.h + to ensure proper alignment on your platform. +
  5. Changes may be required in include/tbb/tick_count.h + for systems that do not provide gettimeofday. +
+ +

To port the Makefile infrastructure:

+Modify the appropriate files in the Makefile infrastructure to add a new platform, operating system or architecture as needed. +See the Makefile infrastructure files for examples. +
    +
  1. The top-level Makefile includes common.inc to determine the operating system. +
      +
    • To add a new operating system, add the appropriate test to common.inc, + and create the needed <os>.inc and <os>.<compiler>.inc files (see below). +
    +
  2. The <os>.inc file makes OS-specific settings for a particular <os>. +
      +
    • For example, linux.inc makes settings specific to Linux* systems. +
    • This file performs OS-dependent tests to determine the specific platform and/or architecture, + and sets other platform-dependent values. +
    • Add a new <os>.inc file for each new operating system added. +
    +
  3. The <os>.<compiler>.inc file makes compiler-specific settings for a particular + <os> / <compiler> combination. +
      +
    • For example, linux.gcc.inc makes specific settings for using GCC on Linux* systems, + and linux.icc.inc makes specific settings for using the Intel® C++ compiler on Linux* systems. +
    • This file sets particular compiler, assembler and linker options required when using a particular + <os> / <compiler> combination. +
    • Add a new <os>.<compiler>.inc file for each new <os> / <compiler> combination added. +
    +
+ +
+Up to parent directory +

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel and Itanium are registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. + + diff --git a/src/tbb/build/linux.gcc.inc b/src/tbb/build/linux.gcc.inc new file mode 100644 index 0000000..8e455a8 --- /dev/null +++ b/src/tbb/build/linux.gcc.inc @@ -0,0 +1,145 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +COMPILE_ONLY = -c -MMD +PREPROC_ONLY = -E -x c++ +INCLUDE_KEY = -I +DEFINE_KEY = -D +OUTPUT_KEY = -o # +OUTPUTOBJ_KEY = -o # +PIC_KEY = -fPIC +WARNING_AS_ERROR_KEY = -Werror +WARNING_KEY = -Wall +TEST_WARNING_KEY = -Wshadow -Wcast-qual -Woverloaded-virtual -Wnon-virtual-dtor $(if $(findstring cc4., $(runtime)),-Wextra) + +WARNING_SUPPRESS = -Wno-parentheses -Wno-non-virtual-dtor +DYLIB_KEY = -shared +EXPORT_KEY = -Wl,--version-script, +LIBDL = -ldl + +TBB_NOSTRICT = 1 + +CPLUS = g++ +CONLY = gcc +LIB_LINK_FLAGS = $(DYLIB_KEY) -Wl,-soname=$(BUILDING_LIBRARY) +LIBS += -lpthread -lrt +LINK_FLAGS = -Wl,-rpath-link=. +C_FLAGS = $(CPLUS_FLAGS) +# gcc 4.4 and higher support -std=c++0x +ifneq (,$(shell gcc -dumpversion | egrep "^(4\.[4-9]|[5-9])")) + CPP11_FLAGS = -std=c++0x -D_TBB_CPP0X +endif + +# gcc 4.2 and higher support OpenMP +ifneq (,$(shell gcc -dumpversion | egrep "^(4\.[2-9]|[5-9])")) + OPENMP_FLAG = -fopenmp +endif + +ITT_NOTIFY = -DDO_ITT_NOTIFY +ifeq ($(cfg), release) + CPLUS_FLAGS = $(ITT_NOTIFY) -g -O2 -DUSE_PTHREAD +endif +ifeq ($(cfg), debug) + CPLUS_FLAGS = -DTBB_USE_DEBUG $(ITT_NOTIFY) -g -O0 -DUSE_PTHREAD +endif + +ifneq (00,$(lambdas)$(cpp0x)) + CXX_ONLY_FLAGS += $(CPP11_FLAGS) +endif + +TBB_ASM.OBJ= +MALLOC_ASM.OBJ= + +ifeq (ia64,$(arch)) + ITT_NOTIFY = +# Position-independent code (PIC) is a must on IA-64, even for regular (not shared) executables + CPLUS_FLAGS += $(PIC_KEY) +endif + +ifeq (intel64,$(arch)) + CPLUS_FLAGS += -m64 + LIB_LINK_FLAGS += -m64 +endif + +ifeq (ia32,$(arch)) + CPLUS_FLAGS += -m32 -march=pentium4 + LIB_LINK_FLAGS += -m32 +endif + +ifeq (ppc64,$(arch)) + CPLUS_FLAGS += -m64 + LIB_LINK_FLAGS += -m64 +endif + +ifeq (ppc32,$(arch)) + CPLUS_FLAGS += -m32 + LIB_LINK_FLAGS += -m32 +endif + +ifeq (bgp,$(arch)) + CPLUS = mpicxx + CONLY = mpicc +endif + +# for some gcc versions on Solaris, -m64 may imply V9, but perhaps not everywhere (TODO: verify) +ifeq (sparc,$(arch)) + CPLUS_FLAGS += -mcpu=v9 -m64 + LIB_LINK_FLAGS += -mcpu=v9 -m64 +endif + +#------------------------------------------------------------------------------ +# Setting assembler data. +#------------------------------------------------------------------------------ +ASM = as +ifeq (intel64,$(arch)) + ASM_FLAGS += --64 +endif +ifeq (ia32,$(arch)) + ASM_FLAGS += --32 +endif +ifeq ($(cfg),debug) + ASM_FLAGS += -g +endif + +ASSEMBLY_SOURCE=$(arch)-gas +ifeq (ia64,$(arch)) + ASM_FLAGS += -xexplicit + TBB_ASM.OBJ += atomic_support.o lock_byte.o log2.o pause.o ia64_misc.o + MALLOC_ASM.OBJ += atomic_support.o lock_byte.o pause.o log2.o +endif +#------------------------------------------------------------------------------ +# End of setting assembler data. +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# Setting tbbmalloc data. +#------------------------------------------------------------------------------ + +M_CPLUS_FLAGS = $(CPLUS_FLAGS) -fno-rtti -fno-exceptions -fno-schedule-insns2 + +#------------------------------------------------------------------------------ +# End of setting tbbmalloc data. +#------------------------------------------------------------------------------ diff --git a/src/tbb/build/linux.icc.inc b/src/tbb/build/linux.icc.inc new file mode 100644 index 0000000..8aa5a39 --- /dev/null +++ b/src/tbb/build/linux.icc.inc @@ -0,0 +1,126 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +COMPILE_ONLY = -c -MMD +PREPROC_ONLY = -E -x c++ +INCLUDE_KEY = -I +DEFINE_KEY = -D +OUTPUT_KEY = -o # +OUTPUTOBJ_KEY = -o # +PIC_KEY = -fPIC +WARNING_AS_ERROR_KEY = -Werror +WARNING_KEY = -w1 +DYLIB_KEY = -shared +EXPORT_KEY = -Wl,--version-script, +NOINTRINSIC_KEY = -fno-builtin +LIBDL = -ldl + +TBB_NOSTRICT = 1 + +CPLUS = icpc +CONLY = icc + +ITT_NOTIFY = -DDO_ITT_NOTIFY +ifeq (release,$(cfg)) +CPLUS_FLAGS = $(ITT_NOTIFY) -O2 -g -DUSE_PTHREAD +else +CPLUS_FLAGS = $(ITT_NOTIFY) -O0 -g -DUSE_PTHREAD -DTBB_USE_DEBUG +endif + +OPENMP_FLAG = -openmp +LIB_LINK_FLAGS = -shared -i-static -Wl,-soname=$(BUILDING_LIBRARY) +LIBS += -lpthread -lrt +C_FLAGS = $(CPLUS_FLAGS) +# ICC 11.0 and higher support -std=c++0x +ifneq (,$(shell icc -dumpversion | egrep "^1[1-9]\.")) + CPP11_FLAGS = -std=c++0x -D_TBB_CPP0X +endif + +# ICC 12.0 and higher provide Intel(R) Cilk Plus +ifneq (,$(shell icc -dumpversion | egrep "^1[2-9]\.")) + CILK_AVAILABLE = yes +endif + +TBB_ASM.OBJ= +MALLOC_ASM.OBJ= + +ifeq (ia32,$(arch)) + CPLUS_FLAGS += -m32 -falign-stack=maintain-16-byte + LIB_LINK_FLAGS += -m32 +endif + +ifeq (ia64,$(arch)) + ITT_NOTIFY = +# Position-independent code (PIC) is a must on IA-64, even for regular (not shared) executables +# strict-ansi does not work with on RHEL 4 AS + CPLUS_FLAGS += $(PIC_KEY) $(if $(findstring cc3.,$(runtime)),-ansi,-strict-ansi) +else + CPLUS_FLAGS += -strict-ansi +endif + +ifneq (,$(codecov)) +# no tool support for code coverage, need profile data generation + ITT_NOTIFY = -prof-genx +endif + +ifneq (00,$(lambdas)$(cpp0x)) + CPLUS_FLAGS += $(CPP11_FLAGS) +endif + +#------------------------------------------------------------------------------ +# Setting assembler data. +#------------------------------------------------------------------------------ +ASM = as +ifeq (intel64,$(arch)) + ASM_FLAGS += --64 +endif +ifeq (ia32,$(arch)) + ASM_FLAGS += --32 +endif +ifeq ($(cfg),debug) + ASM_FLAGS += -g +endif + +ASSEMBLY_SOURCE=$(arch)-gas +ifeq (ia64,$(arch)) + ASM_FLAGS += -xexplicit + TBB_ASM.OBJ += atomic_support.o lock_byte.o log2.o pause.o ia64_misc.o + MALLOC_ASM.OBJ += atomic_support.o lock_byte.o pause.o log2.o +endif +#------------------------------------------------------------------------------ +# End of setting assembler data. +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# Setting tbbmalloc data. +#------------------------------------------------------------------------------ + +M_CPLUS_FLAGS = $(CPLUS_FLAGS) -fno-rtti -fno-exceptions + +#------------------------------------------------------------------------------ +# End of setting tbbmalloc data. +#------------------------------------------------------------------------------ + diff --git a/src/tbb/build/linux.inc b/src/tbb/build/linux.inc new file mode 100644 index 0000000..a27408f --- /dev/null +++ b/src/tbb/build/linux.inc @@ -0,0 +1,139 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +####### Detections and Commands ############################################### + +ifeq (icc,$(compiler)) + export COMPILER_VERSION := ICC: $(shell icc -V &1 | grep 'Version') + ifneq (,$(findstring IA-32, $(COMPILER_VERSION))) + export arch:=ia32 + endif + ifneq (,$(findstring Intel(R) 64, $(COMPILER_VERSION))) + export arch:=intel64 + endif + ifneq (,$(findstring IA-64, $(COMPILER_VERSION))) + export arch:=ia64 + endif + ifeq (,$(arch)) + $(warning "Unknown Intel compiler") + endif +endif + +ifndef arch + uname_m:=$(shell uname -m) + ifeq ($(uname_m),i686) + export arch:=ia32 + endif + ifeq ($(uname_m),ia64) + export arch:=ia64 + endif + ifeq ($(uname_m),x86_64) + export arch:=intel64 + endif + ifeq ($(uname_m),sparc64) + export arch:=sparc + endif + ifndef arch + export arch:=$(uname_m) + endif +endif + +ifndef runtime + gcc_version = $(shell gcc -dumpversion) + os_version:=$(shell uname -r) + os_kernel_version:=$(shell uname -r | sed -e 's/-.*$$//') + export os_glibc_version_full:=$(shell getconf GNU_LIBC_VERSION | grep glibc | sed -e 's/^glibc //') + os_glibc_version:=$(shell echo "$(os_glibc_version_full)" | sed -e '2,$$d' -e 's/-.*$$//') + export runtime:=cc$(gcc_version)_libc$(os_glibc_version)_kernel$(os_kernel_version) +endif + +native_compiler := gcc +export compiler ?= gcc +debugger ?= gdb + +CMD=sh -c +CWD=$(shell pwd) +RM?=rm -f +RD?=rmdir +MD?=mkdir -p +NUL= /dev/null +SLASH=/ +MAKE_VERSIONS=sh $(tbb_root)/build/version_info_linux.sh $(CPLUS) $(CPLUS_FLAGS) $(INCLUDES) >version_string.ver +MAKE_TBBVARS=sh $(tbb_root)/build/generate_tbbvars.sh + +ifdef LD_LIBRARY_PATH + export LD_LIBRARY_PATH := .:$(LD_LIBRARY_PATH) +else + export LD_LIBRARY_PATH := . +endif + +####### Build settings ######################################################## + +OBJ = o +DLL = so +LIBEXT = so +SONAME_SUFFIX =$(shell grep TBB_COMPATIBLE_INTERFACE_VERSION $(tbb_root)/include/tbb/tbb_stddef.h | egrep -o [0-9.]+) + +ifeq ($(arch),ia64) + def_prefix = lin64ipf +endif +ifeq ($(arch),sparc) + def_prefix = lin64 +endif +ifeq (,$(def_prefix)) + ifeq (64,$(findstring 64,$(arch))) + def_prefix = lin64 + else + def_prefix = lin32 + endif +endif +TBB.LST = $(tbb_root)/src/tbb/$(def_prefix)-tbb-export.lst +TBB.DEF = $(TBB.LST:.lst=.def) + +TBB.DLL = $(TBB_NO_VERSION.DLL).$(SONAME_SUFFIX) +TBB.LIB = $(TBB.DLL) +TBB_NO_VERSION.DLL=libtbb$(CPF_SUFFIX)$(DEBUG_SUFFIX).$(DLL) +LINK_TBB.LIB = $(TBB_NO_VERSION.DLL) + +MALLOC_NO_VERSION.DLL = libtbbmalloc$(DEBUG_SUFFIX).$(DLL) +MALLOC.DEF = $(MALLOC_ROOT)/$(def_prefix)-tbbmalloc-export.def +MALLOC.DLL = $(MALLOC_NO_VERSION.DLL).$(SONAME_SUFFIX) +MALLOC.LIB = $(MALLOC_NO_VERSION.DLL) +LINK_MALLOC.LIB = $(MALLOC_NO_VERSION.DLL) + +MALLOCPROXY_NO_VERSION.DLL = libtbbmalloc_proxy$(DEBUG_SUFFIX).$(DLL) +MALLOCPROXY.DEF = $(MALLOC_ROOT)/$(def_prefix)-proxy-export.def +MALLOCPROXY.DLL = $(MALLOCPROXY_NO_VERSION.DLL).$(SONAME_SUFFIX) +MALLOCPROXY.LIB = $(MALLOCPROXY_NO_VERSION.DLL) + +RML_NO_VERSION.DLL = libirml$(DEBUG_SUFFIX).$(DLL) +RML.DEF = $(RML_SERVER_ROOT)/lin-rml-export.def +RML.DLL = $(RML_NO_VERSION.DLL).1 +RML.LIB = $(RML_NO_VERSION.DLL) + +TBB_NOSTRICT=1 + +TEST_LAUNCHER=sh $(tbb_root)/build/test_launcher.sh diff --git a/src/tbb/build/linux.xl.inc b/src/tbb/build/linux.xl.inc new file mode 100644 index 0000000..c56098a --- /dev/null +++ b/src/tbb/build/linux.xl.inc @@ -0,0 +1,113 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +####### Detections and Commands ############################################### + +COMPILE_ONLY = -c +PREPROC_ONLY = -E -qsourcetype=c +INCLUDE_KEY = -I +DEFINE_KEY = -D +OUTPUT_KEY = -o # +OUTPUTOBJ_KEY = -o # +PIC_KEY = -qpic +WARNING_AS_ERROR_KEY = -qhalt=w +WARNING_KEY = +TEST_WARNING_KEY = + +WARNING_SUPPRESS = +DYLIB_KEY = -qmkshrobj +EXPORT_KEY = -Wl,--version-script, +LIBDL = -ldl + +TBB_NOSTRICT = 1 + +CPLUS = xlc++_r +CONLY = xlc_r +LIB_LINK_FLAGS = $(DYLIB_KEY) -Wl,-soname=$(BUILDING_LIBRARY) +LIBS = -lpthread -lrt +C_FLAGS = $(CPLUS_FLAGS) + +ITT_NOTIFY = -DDO_ITT_NOTIFY +ifeq ($(cfg), release) + CPLUS_FLAGS = $(ITT_NOTIFY) -O2 -DUSE_PTHREAD +endif +ifeq ($(cfg), debug) + CPLUS_FLAGS = -DTBB_USE_DEBUG $(ITT_NOTIFY) -g -O0 -DUSE_PTHREAD +endif + +# Adding directly to CPLUS_FLAGS instead of to WARNING_SUPPRESS because otherwise it would not be used in several tests (why not?). +# Suppress warnings like: +# - "1500-029: (W) WARNING: subprogram [...] could not be inlined into [...]." +# - "1501-201: (W) Maximum number of common component diagnostics, 10 has been exceeded." +# see http://www-01.ibm.com/support/docview.wss?uid=swg1LI72843 +# it seems that the internal compiler error that would ensue has now been avoided, making the condition harmless +# - "1540-0198 (W) The omitted keyword "private" is assumed for base class "no_copy"." +# - "1540-0822 (W) The name "__FUNCTION__" must not be defined as a macro." +CPLUS_FLAGS += -qsuppress=1500-029:1501-201:1540-0198:1540-0822 + +ASM= +ASM_FLAGS= + +TBB_ASM.OBJ= + +ifeq (intel64,$(arch)) + CPLUS_FLAGS += -q64 + LIB_LINK_FLAGS += -q64 +endif + +# TODO: equivalent for -march=pentium4 in CPLUS_FLAGS +ifeq (ia32,$(arch)) + CPLUS_FLAGS += -q32 -qarch=pentium4 + LIB_LINK_FLAGS += -q32 +endif + +ifeq (ppc64,$(arch)) + CPLUS_FLAGS += -q64 + LIB_LINK_FLAGS += -q64 +endif + +ifeq (ppc32,$(arch)) + CPLUS_FLAGS += -q32 + LIB_LINK_FLAGS += -q32 +endif + +ifeq (bgp,$(arch)) + CPLUS = bgxlC_r + CONLY = bgxlc_r +endif + +#------------------------------------------------------------------------------ +# Setting tbbmalloc data. +#------------------------------------------------------------------------------ + +# Suppress innumerable warnings like "1540-1088 (W) The exception specification is being ignored." +# Suppress warnings like "1540-1090 (I) The destructor of "lock" might not be called." +# TODO: aren't these warnings an indication that -qnoeh might not be appropriate? +M_CPLUS_FLAGS = $(CPLUS_FLAGS) -qnortti -qnoeh -qsuppress=1540-1088:1540-1090 + +#------------------------------------------------------------------------------ +# End of setting tbbmalloc data. +#------------------------------------------------------------------------------ diff --git a/src/tbb/build/macos.clang.inc b/src/tbb/build/macos.clang.inc new file mode 100644 index 0000000..92c2cf4 --- /dev/null +++ b/src/tbb/build/macos.clang.inc @@ -0,0 +1,109 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +CPLUS = clang++ +CONLY = clang +COMPILE_ONLY = -c -MMD +PREPROC_ONLY = -E -x c++ +INCLUDE_KEY = -I +DEFINE_KEY = -D +OUTPUT_KEY = -o # +OUTPUTOBJ_KEY = -o # +PIC_KEY = -fPIC +WARNING_AS_ERROR_KEY = -Werror +WARNING_KEY = -Wall +TEST_WARNING_KEY = -Wextra -Wshadow -Wcast-qual -Woverloaded-virtual -Wnon-virtual-dtor +WARNING_SUPPRESS = -Wno-non-virtual-dtor +DYLIB_KEY = -dynamiclib +EXPORT_KEY = -Wl,-exported_symbols_list, +LIBDL = -ldl + +LIBS = -lpthread +LINK_FLAGS = +LIB_LINK_FLAGS = -dynamiclib +C_FLAGS = $(CPLUS_FLAGS) + +ifeq ($(cfg), release) + CPLUS_FLAGS = -O2 +else + CPLUS_FLAGS = -g -O0 -DTBB_USE_DEBUG +endif + +CPLUS_FLAGS += -DUSE_PTHREAD + +ifeq (intel64,$(arch)) + CPLUS_FLAGS += -m64 + LINK_FLAGS += -m64 + LIB_LINK_FLAGS += -m64 +endif + +ifeq (ia32,$(arch)) + CPLUS_FLAGS += -m32 + LINK_FLAGS += -m32 + LIB_LINK_FLAGS += -m32 +endif + +ifeq (ppc64,$(arch)) + CPLUS_FLAGS += -arch ppc64 + LINK_FLAGS += -arch ppc64 + LIB_LINK_FLAGS += -arch ppc64 +endif + +ifeq (ppc32,$(arch)) + CPLUS_FLAGS += -arch ppc + LINK_FLAGS += -arch ppc + LIB_LINK_FLAGS += -arch ppc +endif + +#------------------------------------------------------------------------------ +# Setting assembler data. +#------------------------------------------------------------------------------ + +ASM = as +ifeq (intel64,$(arch)) + ASM_FLAGS += -arch x86_64 +endif +ifeq (ia32,$(arch)) + ASM_FLAGS += -arch i386 +endif +ifeq ($(cfg), debug) + ASM_FLAGS += -g +endif + +#------------------------------------------------------------------------------ +# End of setting assembler data. +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# Setting tbbmalloc data. +#------------------------------------------------------------------------------ + +M_CPLUS_FLAGS = $(CPLUS_FLAGS) -fno-rtti -fno-exceptions + +#------------------------------------------------------------------------------ +# End of setting tbbmalloc data. +#------------------------------------------------------------------------------ + diff --git a/src/tbb/build/macos.gcc.inc b/src/tbb/build/macos.gcc.inc new file mode 100644 index 0000000..cd9d9a1 --- /dev/null +++ b/src/tbb/build/macos.gcc.inc @@ -0,0 +1,109 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +CPLUS = g++ +CONLY = gcc +COMPILE_ONLY = -c -MMD +PREPROC_ONLY = -E -x c++ +INCLUDE_KEY = -I +DEFINE_KEY = -D +OUTPUT_KEY = -o # +OUTPUTOBJ_KEY = -o # +PIC_KEY = -fPIC +WARNING_AS_ERROR_KEY = -Werror +WARNING_KEY = -Wall +TEST_WARNING_KEY = -Wextra -Wshadow -Wcast-qual -Woverloaded-virtual -Wnon-virtual-dtor +WARNING_SUPPRESS = -Wno-non-virtual-dtor +DYLIB_KEY = -dynamiclib +EXPORT_KEY = -Wl,-exported_symbols_list, +LIBDL = -ldl + +LIBS = -lpthread +LINK_FLAGS = +LIB_LINK_FLAGS = -dynamiclib +C_FLAGS = $(CPLUS_FLAGS) + +ifeq ($(cfg), release) + CPLUS_FLAGS = -O2 +else + CPLUS_FLAGS = -g -O0 -DTBB_USE_DEBUG +endif + +CPLUS_FLAGS += -DUSE_PTHREAD + +ifeq (intel64,$(arch)) + CPLUS_FLAGS += -m64 + LINK_FLAGS += -m64 + LIB_LINK_FLAGS += -m64 +endif + +ifeq (ia32,$(arch)) + CPLUS_FLAGS += -m32 + LINK_FLAGS += -m32 + LIB_LINK_FLAGS += -m32 +endif + +ifeq (ppc64,$(arch)) + CPLUS_FLAGS += -arch ppc64 + LINK_FLAGS += -arch ppc64 + LIB_LINK_FLAGS += -arch ppc64 +endif + +ifeq (ppc32,$(arch)) + CPLUS_FLAGS += -arch ppc + LINK_FLAGS += -arch ppc + LIB_LINK_FLAGS += -arch ppc +endif + +#------------------------------------------------------------------------------ +# Setting assembler data. +#------------------------------------------------------------------------------ + +ASM = as +ifeq (intel64,$(arch)) + ASM_FLAGS += -arch x86_64 +endif +ifeq (ia32,$(arch)) + ASM_FLAGS += -arch i386 +endif +ifeq ($(cfg), debug) + ASM_FLAGS += -g +endif + +#------------------------------------------------------------------------------ +# End of setting assembler data. +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# Setting tbbmalloc data. +#------------------------------------------------------------------------------ + +M_CPLUS_FLAGS = $(CPLUS_FLAGS) -fno-rtti -fno-exceptions -fno-schedule-insns2 + +#------------------------------------------------------------------------------ +# End of setting tbbmalloc data. +#------------------------------------------------------------------------------ + diff --git a/src/tbb/build/macos.icc.inc b/src/tbb/build/macos.icc.inc new file mode 100644 index 0000000..c689f61 --- /dev/null +++ b/src/tbb/build/macos.icc.inc @@ -0,0 +1,103 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +CPLUS = icpc +CONLY = icc +COMPILE_ONLY = -c -MMD +PREPROC_ONLY = -E -x c++ +INCLUDE_KEY = -I +DEFINE_KEY = -D +OUTPUT_KEY = -o # +OUTPUTOBJ_KEY = -o # +PIC_KEY = -fPIC +WARNING_AS_ERROR_KEY = -Werror +WARNING_KEY = -w1 +DYLIB_KEY = -dynamiclib +EXPORT_KEY = -Wl,-exported_symbols_list, +LIBDL = -ldl + +OPENMP_FLAG = -openmp +LIBS = -lpthread +LINK_FLAGS = +LIB_LINK_FLAGS = -dynamiclib -i-static +C_FLAGS = $(CPLUS_FLAGS) +# ICC 11.0 and higher support -std=c++0x +ifneq (,$(shell icc -dumpversion | egrep "^1[1-9]\.")) + CPP11_FLAGS = -std=c++0x -D_TBB_CPP0X +endif + +# ICC 12.0 and higher provide Intel(R) Cilk Plus +ifneq (,$(shell icc -dumpversion | egrep "^1[2-9]\.")) + CILK_AVAILABLE = yes +endif + +ifeq ($(cfg), release) + CPLUS_FLAGS = -O2 -fno-omit-frame-pointer +else + CPLUS_FLAGS = -g -O0 -DTBB_USE_DEBUG +endif + +CPLUS_FLAGS += -DUSE_PTHREAD + +ifneq (,$(codecov)) + CPLUS_FLAGS += -prof-genx +endif + +ifneq (00,$(lambdas)$(cpp0x)) + CPLUS_FLAGS += $(CPP11_FLAGS) +endif + +#------------------------------------------------------------------------------ +# Setting assembler data. +#------------------------------------------------------------------------------ + +ASM = as +ifeq (intel64,$(arch)) + ASM_FLAGS += -arch x86_64 +endif +ifeq (ia32,$(arch)) + CPLUS_FLAGS += -m32 + LINK_FLAGS += -m32 + LIB_LINK_FLAGS += -m32 + ASM_FLAGS += -arch i386 +endif +ifeq ($(cfg), debug) + ASM_FLAGS += -g +endif + +#------------------------------------------------------------------------------ +# End of setting assembler data. +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# Setting tbbmalloc data. +#------------------------------------------------------------------------------ + +M_CPLUS_FLAGS = $(CPLUS_FLAGS) -fno-rtti -fno-exceptions + +#------------------------------------------------------------------------------ +# End of setting tbbmalloc data. +#------------------------------------------------------------------------------ diff --git a/src/tbb/build/macos.inc b/src/tbb/build/macos.inc new file mode 100644 index 0000000..31a80f0 --- /dev/null +++ b/src/tbb/build/macos.inc @@ -0,0 +1,98 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +####### Detections and Commands ############################################### + +ifeq (icc,$(compiler)) + export COMPILER_VERSION := ICC: $(shell icc -V &1 | grep 'Version') + ifneq (,$(findstring IA-32, $(COMPILER_VERSION))) + export arch:=ia32 + endif + ifneq (,$(findstring Intel(R) 64, $(COMPILER_VERSION))) + export arch:=intel64 + endif + ifeq (,$(arch)) + $(warning "Unknown Intel compiler") + endif +endif + +ifndef arch + ifeq ($(shell /usr/sbin/sysctl -n hw.machine),Power Macintosh) + ifeq ($(shell /usr/sbin/sysctl -n hw.optional.64bitops),1) + export arch:=ppc64 + else + export arch:=ppc32 + endif + else + ifeq ($(shell /usr/sbin/sysctl -n hw.optional.x86_64 2>/dev/null),1) + export arch:=intel64 + else + export arch:=ia32 + endif + endif +endif + +ifndef runtime + gcc_version = $(shell gcc -dumpversion) + os_version:=$(shell /usr/bin/sw_vers -productVersion) + export runtime:=cc$(gcc_version)_os$(os_version) +endif + +native_compiler := gcc +export compiler ?= gcc +debugger ?= gdb + +CMD=$(SHELL) -c +CWD=$(shell pwd) +RM?=rm -f +RD?=rmdir +MD?=mkdir -p +NUL= /dev/null +SLASH=/ +MAKE_VERSIONS=sh $(tbb_root)/build/version_info_macos.sh $(CPLUS) $(CPLUS_FLAGS) $(INCLUDES) >version_string.ver +MAKE_TBBVARS=sh $(tbb_root)/build/generate_tbbvars.sh + +####### Build settings ######################################################## + +OBJ=o +DLL=dylib +LIBEXT=dylib + +def_prefix = $(if $(findstring 64,$(arch)),mac64,mac32) + +TBB.LST = $(tbb_root)/src/tbb/$(def_prefix)-tbb-export.lst +TBB.DEF = $(TBB.LST:.lst=.def) +TBB.DLL = libtbb$(CPF_SUFFIX)$(DEBUG_SUFFIX).$(DLL) +TBB.LIB = $(TBB.DLL) +LINK_TBB.LIB = $(TBB.LIB) + +MALLOC.DEF = $(MALLOC_ROOT)/$(def_prefix)-tbbmalloc-export.def +MALLOC.DLL = libtbbmalloc$(DEBUG_SUFFIX).$(DLL) +MALLOC.LIB = $(MALLOC.DLL) + +TBB_NOSTRICT=1 + +TEST_LAUNCHER=sh $(tbb_root)/build/test_launcher.sh diff --git a/src/tbb/build/suncc.map.pause b/src/tbb/build/suncc.map.pause new file mode 100644 index 0000000..a92d08e --- /dev/null +++ b/src/tbb/build/suncc.map.pause @@ -0,0 +1 @@ +hwcap_1 = OVERRIDE; \ No newline at end of file diff --git a/src/tbb/build/test_launcher.bat b/src/tbb/build/test_launcher.bat new file mode 100644 index 0000000..dad7769 --- /dev/null +++ b/src/tbb/build/test_launcher.bat @@ -0,0 +1,36 @@ +@echo off +REM +REM Copyright 2005-2012 Intel Corporation. All Rights Reserved. +REM +REM This file is part of Threading Building Blocks. +REM +REM Threading Building Blocks is free software; you can redistribute it +REM and/or modify it under the terms of the GNU General Public License +REM version 2 as published by the Free Software Foundation. +REM +REM Threading Building Blocks is distributed in the hope that it will be +REM useful, but WITHOUT ANY WARRANTY; without even the implied warranty +REM of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +REM GNU General Public License for more details. +REM +REM You should have received a copy of the GNU General Public License +REM along with Threading Building Blocks; if not, write to the Free Software +REM Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +REM +REM As a special exception, you may use this file as part of a free software +REM library without restriction. Specifically, if other files instantiate +REM templates or use macros or inline functions from this file, or you compile +REM this file and link it with other files to produce an executable, this +REM file does not by itself cause the resulting executable to be covered by +REM the GNU General Public License. This exception does not however +REM invalidate any other reasons why the executable file might be covered by +REM the GNU General Public License. +REM + +REM no LD_PRELOAD under Windows +if "%1"=="-l" ( + echo skip + exit +) + +%* diff --git a/src/tbb/build/test_launcher.sh b/src/tbb/build/test_launcher.sh new file mode 100644 index 0000000..0e80d43 --- /dev/null +++ b/src/tbb/build/test_launcher.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +while getopts "l:" flag # +do # + if [ `uname` != 'Linux' ] ; then # + echo 'skip' # + exit # + fi # + LD_PRELOAD=$OPTARG # + shift `expr $OPTIND - 1` # +done # +# Set stack limit +ulimit -s 10240 # +# Run the command line passed via parameters +export LD_PRELOAD # +./$* # diff --git a/src/tbb/build/version_info_aix.sh b/src/tbb/build/version_info_aix.sh new file mode 100644 index 0000000..30e9deb --- /dev/null +++ b/src/tbb/build/version_info_aix.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Script used to generate version info string +echo "#define __TBB_VERSION_STRINGS(N) \\" +echo '#N": BUILD_HOST'"\t\t"`hostname -s`" ("`uname -m`")"'" ENDL \' +# find OS name in *-release and issue* files by filtering blank lines and lsb-release content out +echo '#N": BUILD_OS'"\t\t"`lsb_release -sd 2>/dev/null | grep -ih '[a-z] ' - /etc/*release /etc/issue 2>/dev/null | head -1 | sed -e 's/["\\\\]//g'`'" ENDL \' +echo '#N": BUILD_KERNEL'"\t"`uname -srv`'" ENDL \' +echo '#N": BUILD_GCC'"\t\t"`g++ -v &1 | grep 'gcc.*version'`'" ENDL \' +[ -z "$COMPILER_VERSION" ] || echo '#N": BUILD_COMPILER'"\t"$COMPILER_VERSION'" ENDL \' +echo '#N": BUILD_GLIBC'"\t"`getconf GNU_LIBC_VERSION | grep glibc | sed -e 's/^glibc //'`'" ENDL \' +echo '#N": BUILD_LD'"\t\t"`ld -v 2>&1 | grep 'version'`'" ENDL \' +echo '#N": BUILD_TARGET'"\t$arch on $runtime"'" ENDL \' +echo '#N": BUILD_COMMAND'"\t"$*'" ENDL \' +echo "" +echo "#define __TBB_DATETIME \""`date -u`"\"" diff --git a/src/tbb/build/version_info_linux.sh b/src/tbb/build/version_info_linux.sh new file mode 100644 index 0000000..c11a85d --- /dev/null +++ b/src/tbb/build/version_info_linux.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Script used to generate version info string +echo "#define __TBB_VERSION_STRINGS(N) \\" +echo '#N": BUILD_HOST'"\t\t"`hostname -s`" ("`uname -m`")"'" ENDL \' +# find OS name in *-release and issue* files by filtering blank lines and lsb-release content out +echo '#N": BUILD_OS'"\t\t"`lsb_release -sd 2>/dev/null | grep -ih '[a-z] ' - /etc/*release /etc/issue 2>/dev/null | head -1 | sed -e 's/["\\\\]//g'`'" ENDL \' +echo '#N": BUILD_KERNEL'"\t"`uname -srv`'" ENDL \' +echo '#N": BUILD_GCC'"\t\t"`g++ -v &1 | grep 'gcc.*version '`'" ENDL \' +[ -z "$COMPILER_VERSION" ] || echo '#N": BUILD_COMPILER'"\t"$COMPILER_VERSION'" ENDL \' +echo '#N": BUILD_GLIBC'"\t"`getconf GNU_LIBC_VERSION | grep glibc | sed -e 's/^glibc //'`'" ENDL \' +echo '#N": BUILD_LD'"\t\t"`ld -v 2>&1 | grep 'version'`'" ENDL \' +echo '#N": BUILD_TARGET'"\t$arch on $runtime"'" ENDL \' +echo '#N": BUILD_COMMAND'"\t"$*'" ENDL \' +echo "" +echo "#define __TBB_DATETIME \""`date -u`"\"" diff --git a/src/tbb/build/version_info_macos.sh b/src/tbb/build/version_info_macos.sh new file mode 100644 index 0000000..43c706d --- /dev/null +++ b/src/tbb/build/version_info_macos.sh @@ -0,0 +1,39 @@ +#!/bin/sh +# +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Script used to generate version info string +echo "#define __TBB_VERSION_STRINGS(N) \\" +echo '#N": BUILD_HOST'"\t\t"`hostname -s`" ("`arch`")"'" ENDL \' +echo '#N": BUILD_OS'"\t\t"`sw_vers -productName`" version "`sw_vers -productVersion`'" ENDL \' +echo '#N": BUILD_KERNEL'"\t"`uname -v`'" ENDL \' +echo '#N": BUILD_GCC'"\t\t"`gcc -v &1 | grep 'version'`'" ENDL \' +[ -z "$COMPILER_VERSION" ] || echo '#N": BUILD_COMPILER'"\t"$COMPILER_VERSION'" ENDL \' +echo '#N": BUILD_TARGET'"\t$arch on $runtime"'" ENDL \' +echo '#N": BUILD_COMMAND'"\t"$*'" ENDL \' +echo "" +echo "#define __TBB_DATETIME \""`date -u`"\"" diff --git a/src/tbb/build/version_info_sunos.sh b/src/tbb/build/version_info_sunos.sh new file mode 100644 index 0000000..ac1cbcf --- /dev/null +++ b/src/tbb/build/version_info_sunos.sh @@ -0,0 +1,39 @@ +#!/bin/sh +# +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Script used to generate version info string +echo "#define __TBB_VERSION_STRINGS(N) \\" +echo '#N": BUILD_HOST'"\t"`hostname`" ("`arch`")"'" ENDL \' +echo '#N": BUILD_OS'"\t\t"`uname`'" ENDL \' +echo '#N": BUILD_KERNEL'"\t"`uname -srv`'" ENDL \' +echo '#N": BUILD_SUNCC'"\t"`CC -V &1 | grep 'C++'`'" ENDL \' +[ -z "$COMPILER_VERSION" ] || echo '#N": BUILD_COMPILER'"\t"$COMPILER_VERSION'" ENDL \' +echo '#N": BUILD_TARGET'"\t$arch on $runtime"'" ENDL \' +echo '#N": BUILD_COMMAND'"\t"$*'" ENDL \' +echo "" +echo "#define __TBB_DATETIME \""`date -u`"\"" diff --git a/src/tbb/build/version_info_windows.js b/src/tbb/build/version_info_windows.js new file mode 100644 index 0000000..3dcf09a --- /dev/null +++ b/src/tbb/build/version_info_windows.js @@ -0,0 +1,136 @@ +// Copyright 2005-2012 Intel Corporation. All Rights Reserved. +// +// This file is part of Threading Building Blocks. +// +// Threading Building Blocks is free software; you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// Threading Building Blocks is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Threading Building Blocks; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +var WshShell = WScript.CreateObject("WScript.Shell"); + +var tmpExec; + +WScript.Echo("#define __TBB_VERSION_STRINGS(N) \\"); + +//Getting BUILD_HOST +WScript.echo( "#N \": BUILD_HOST\\t\\t" + + WshShell.ExpandEnvironmentStrings("%COMPUTERNAME%") + + "\" ENDL \\" ); + +//Getting BUILD_OS +tmpExec = WshShell.Exec("cmd /c ver"); +while ( tmpExec.Status == 0 ) { + WScript.Sleep(100); +} +tmpExec.StdOut.ReadLine(); + +WScript.echo( "#N \": BUILD_OS\\t\\t" + + tmpExec.StdOut.ReadLine() + + "\" ENDL \\" ); + +if ( WScript.Arguments(0).toLowerCase().match("gcc") ) { + tmpExec = WshShell.Exec("gcc --version"); + WScript.echo( "#N \": BUILD_COMPILER\\t" + + tmpExec.StdOut.ReadLine() + + "\" ENDL \\" ); + +} else { // MS / Intel compilers + //Getting BUILD_CL + tmpExec = WshShell.Exec("cmd /c echo #define 0 0>empty.cpp"); + tmpExec = WshShell.Exec("cl -c empty.cpp "); + while ( tmpExec.Status == 0 ) { + WScript.Sleep(100); + } + var clVersion = tmpExec.StdErr.ReadLine(); + WScript.echo( "#N \": BUILD_CL\\t\\t" + + clVersion + + "\" ENDL \\" ); + + //Getting BUILD_COMPILER + if ( WScript.Arguments(0).toLowerCase().match("icl") ) { + tmpExec = WshShell.Exec("icl -c empty.cpp "); + while ( tmpExec.Status == 0 ) { + WScript.Sleep(100); + } + WScript.echo( "#N \": BUILD_COMPILER\\t" + + tmpExec.StdErr.ReadLine() + + "\" ENDL \\" ); + } else { + WScript.echo( "#N \": BUILD_COMPILER\\t\\t" + + clVersion + + "\" ENDL \\" ); + } + tmpExec = WshShell.Exec("cmd /c del /F /Q empty.obj empty.cpp"); +} + +//Getting BUILD_TARGET +WScript.echo( "#N \": BUILD_TARGET\\t" + + WScript.Arguments(1) + + "\" ENDL \\" ); + +//Getting BUILD_COMMAND +WScript.echo( "#N \": BUILD_COMMAND\\t" + WScript.Arguments(2) + "\" ENDL" ); + +//Getting __TBB_DATETIME and __TBB_VERSION_YMD +var date = new Date(); +WScript.echo( "#define __TBB_DATETIME \"" + date.toUTCString() + "\"" ); +WScript.echo( "#define __TBB_VERSION_YMD " + date.getUTCFullYear() + ", " + + (date.getUTCMonth() > 8 ? (date.getUTCMonth()+1):("0"+(date.getUTCMonth()+1))) + + (date.getUTCDate() > 9 ? date.getUTCDate():("0"+date.getUTCDate())) ); + + +/* + +Original strings + +#define __TBB_VERSION_STRINGS \ +"TBB: BUILD_HOST\t\tvpolin-mobl1 (ia32)" ENDL \ +"TBB: BUILD_OS\t\tMicrosoft Windows XP [Version 5.1.2600]" ENDL \ +"TBB: BUILD_CL\t\tMicrosoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86" ENDL \ +"TBB: BUILD_COMPILER\tIntel(R) C++ Compiler for 32-bit applications, Version 9.1 Build 20070109Z Package ID: W_CC_C_9.1.034 " ENDL \ +"TBB: BUILD_TARGET\t" ENDL \ +"TBB: BUILD_COMMAND\t" ENDL \ + +#define __TBB_DATETIME "Mon Jun 4 10:16:07 UTC 2007" +#define __TBB_VERSION_YMD 2007, 0604 + + + +# The script must be run from two directory levels below this level. +x='"TBB: ' +y='" ENDL \' +echo "#define __TBB_VERSION_STRINGS \\" +echo $x "BUILD_HOST\t\t"`hostname`" ("`../../arch.exe`")"$y +echo $x "BUILD_OS\t\t"`../../win_version.bat|grep -i 'Version'`$y +echo >empty.cpp +echo $x "BUILD_CL\t\t"`cl -c empty.cpp 2>&1 | grep -i Version`$y +echo $x "BUILD_COMPILER\t"`icl -c empty.cpp 2>&1 | grep -i Version`$y +echo $x "BUILD_TARGET\t"$TBB_ARCH$y +echo $x "BUILD_COMMAND\t"$*$y +echo "" +# A workaround for MKS 8.6 where `date -u` crashes. +date -u > date.tmp +echo "#define __TBB_DATETIME \""`cat date.tmp`"\"" +echo "#define __TBB_VERSION_YMD "`date '+%Y, %m%d'` +rm empty.cpp +rm empty.obj +rm date.tmp +*/ diff --git a/src/tbb/build/vsproject/index.html b/src/tbb/build/vsproject/index.html new file mode 100644 index 0000000..6607338 --- /dev/null +++ b/src/tbb/build/vsproject/index.html @@ -0,0 +1,30 @@ + + + +

Overview

+This directory contains the visual studio* 2005 solution to build Threading Building Blocks. + + +

Files

+
+
makefile.sln +
Solution file. +
tbb.vcproj +
Library project file. +
tbbmalloc.vcproj +
Scalable allocator library project file. Allocator sources are expected to be located in ../../src/tbbmalloc folder. +
tbbmalloc_proxy.vcproj +
Standard allocator replacement project file. +
+ +
+Up to parent directory +

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. + + diff --git a/src/tbb/build/vsproject/makefile.sln b/src/tbb/build/vsproject/makefile.sln new file mode 100644 index 0000000..1fd7a8d --- /dev/null +++ b/src/tbb/build/vsproject/makefile.sln @@ -0,0 +1,100 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tbb", "tbb.vcproj", "{F62787DD-1327-448B-9818-030062BCFAA5}" + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.Debug = "False" + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tbbmalloc", "tbbmalloc.vcproj", "{B15F131E-328A-4D42-ADC2-9FF4CA6306D8}" + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.Debug = "False" + EndProjectSection + ProjectSection(ProjectDependencies) = postProject + {F62787DD-1327-448B-9818-030062BCFAA5} = {F62787DD-1327-448B-9818-030062BCFAA5} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8898CE0B-0BFB-45AE-AA71-83735ED2510D}" + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.Debug = "False" + EndProjectSection + ProjectSection(SolutionItems) = preProject + index.html = index.html + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tbbmalloc_proxy", "tbbmalloc_proxy.vcproj", "{02F61511-D5B6-46E6-B4BB-DEAA96E6BCC7}" + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.Debug = "False" + EndProjectSection + ProjectSection(ProjectDependencies) = postProject + {B15F131E-328A-4D42-ADC2-9FF4CA6306D8} = {B15F131E-328A-4D42-ADC2-9FF4CA6306D8} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Debug-MT|Win32 = Debug-MT|Win32 + Debug-MT|x64 = Debug-MT|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + Release-MT|Win32 = Release-MT|Win32 + Release-MT|x64 = Release-MT|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F62787DD-1327-448B-9818-030062BCFAA5}.Debug|Win32.ActiveCfg = Debug|Win32 + {F62787DD-1327-448B-9818-030062BCFAA5}.Debug|Win32.Build.0 = Debug|Win32 + {F62787DD-1327-448B-9818-030062BCFAA5}.Debug|x64.ActiveCfg = Debug|x64 + {F62787DD-1327-448B-9818-030062BCFAA5}.Debug|x64.Build.0 = Debug|x64 + {F62787DD-1327-448B-9818-030062BCFAA5}.Debug-MT|Win32.ActiveCfg = Debug-MT|Win32 + {F62787DD-1327-448B-9818-030062BCFAA5}.Debug-MT|Win32.Build.0 = Debug-MT|Win32 + {F62787DD-1327-448B-9818-030062BCFAA5}.Debug-MT|x64.ActiveCfg = Debug-MT|x64 + {F62787DD-1327-448B-9818-030062BCFAA5}.Debug-MT|x64.Build.0 = Debug-MT|x64 + {F62787DD-1327-448B-9818-030062BCFAA5}.Release|Win32.ActiveCfg = Release|Win32 + {F62787DD-1327-448B-9818-030062BCFAA5}.Release|Win32.Build.0 = Release|Win32 + {F62787DD-1327-448B-9818-030062BCFAA5}.Release|x64.ActiveCfg = Release|x64 + {F62787DD-1327-448B-9818-030062BCFAA5}.Release|x64.Build.0 = Release|x64 + {F62787DD-1327-448B-9818-030062BCFAA5}.Release-MT|Win32.ActiveCfg = Release-MT|Win32 + {F62787DD-1327-448B-9818-030062BCFAA5}.Release-MT|Win32.Build.0 = Release-MT|Win32 + {F62787DD-1327-448B-9818-030062BCFAA5}.Release-MT|x64.ActiveCfg = Release-MT|x64 + {F62787DD-1327-448B-9818-030062BCFAA5}.Release-MT|x64.Build.0 = Release-MT|x64 + {B15F131E-328A-4D42-ADC2-9FF4CA6306D8}.Debug|Win32.ActiveCfg = Debug|Win32 + {B15F131E-328A-4D42-ADC2-9FF4CA6306D8}.Debug|Win32.Build.0 = Debug|Win32 + {B15F131E-328A-4D42-ADC2-9FF4CA6306D8}.Debug|x64.ActiveCfg = Debug|x64 + {B15F131E-328A-4D42-ADC2-9FF4CA6306D8}.Debug|x64.Build.0 = Debug|x64 + {B15F131E-328A-4D42-ADC2-9FF4CA6306D8}.Debug-MT|Win32.ActiveCfg = Debug-MT|Win32 + {B15F131E-328A-4D42-ADC2-9FF4CA6306D8}.Debug-MT|Win32.Build.0 = Debug-MT|Win32 + {B15F131E-328A-4D42-ADC2-9FF4CA6306D8}.Debug-MT|x64.ActiveCfg = Debug-MT|x64 + {B15F131E-328A-4D42-ADC2-9FF4CA6306D8}.Debug-MT|x64.Build.0 = Debug-MT|x64 + {B15F131E-328A-4D42-ADC2-9FF4CA6306D8}.Release|Win32.ActiveCfg = Release|Win32 + {B15F131E-328A-4D42-ADC2-9FF4CA6306D8}.Release|Win32.Build.0 = Release|Win32 + {B15F131E-328A-4D42-ADC2-9FF4CA6306D8}.Release|x64.ActiveCfg = Release|x64 + {B15F131E-328A-4D42-ADC2-9FF4CA6306D8}.Release|x64.Build.0 = Release|x64 + {B15F131E-328A-4D42-ADC2-9FF4CA6306D8}.Release-MT|Win32.ActiveCfg = Release-MT|Win32 + {B15F131E-328A-4D42-ADC2-9FF4CA6306D8}.Release-MT|Win32.Build.0 = Release-MT|Win32 + {B15F131E-328A-4D42-ADC2-9FF4CA6306D8}.Release-MT|x64.ActiveCfg = Release-MT|x64 + {B15F131E-328A-4D42-ADC2-9FF4CA6306D8}.Release-MT|x64.Build.0 = Release-MT|x64 + {02F61511-D5B6-46E6-B4BB-DEAA96E6BCC7}.Debug|Win32.ActiveCfg = Debug|Win32 + {02F61511-D5B6-46E6-B4BB-DEAA96E6BCC7}.Debug|Win32.Build.0 = Debug|Win32 + {02F61511-D5B6-46E6-B4BB-DEAA96E6BCC7}.Debug|x64.ActiveCfg = Debug|x64 + {02F61511-D5B6-46E6-B4BB-DEAA96E6BCC7}.Debug|x64.Build.0 = Debug|x64 + {02F61511-D5B6-46E6-B4BB-DEAA96E6BCC7}.Debug-MT|Win32.ActiveCfg = Debug-MT|Win32 + {02F61511-D5B6-46E6-B4BB-DEAA96E6BCC7}.Debug-MT|Win32.Build.0 = Debug-MT|Win32 + {02F61511-D5B6-46E6-B4BB-DEAA96E6BCC7}.Debug-MT|x64.ActiveCfg = Debug-MT|x64 + {02F61511-D5B6-46E6-B4BB-DEAA96E6BCC7}.Debug-MT|x64.Build.0 = Debug-MT|x64 + {02F61511-D5B6-46E6-B4BB-DEAA96E6BCC7}.Release|Win32.ActiveCfg = Release|Win32 + {02F61511-D5B6-46E6-B4BB-DEAA96E6BCC7}.Release|Win32.Build.0 = Release|Win32 + {02F61511-D5B6-46E6-B4BB-DEAA96E6BCC7}.Release|x64.ActiveCfg = Release|x64 + {02F61511-D5B6-46E6-B4BB-DEAA96E6BCC7}.Release|x64.Build.0 = Release|x64 + {02F61511-D5B6-46E6-B4BB-DEAA96E6BCC7}.Release-MT|Win32.ActiveCfg = Release-MT|Win32 + {02F61511-D5B6-46E6-B4BB-DEAA96E6BCC7}.Release-MT|Win32.Build.0 = Release-MT|Win32 + {02F61511-D5B6-46E6-B4BB-DEAA96E6BCC7}.Release-MT|x64.ActiveCfg = Release-MT|x64 + {02F61511-D5B6-46E6-B4BB-DEAA96E6BCC7}.Release-MT|x64.Build.0 = Release-MT|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/build/vsproject/tbb.vcproj b/src/tbb/build/vsproject/tbb.vcproj new file mode 100644 index 0000000..1c77711 --- /dev/null +++ b/src/tbb/build/vsproject/tbb.vcproj @@ -0,0 +1,530 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/build/vsproject/tbbmalloc.vcproj b/src/tbb/build/vsproject/tbbmalloc.vcproj new file mode 100644 index 0000000..f0078ad --- /dev/null +++ b/src/tbb/build/vsproject/tbbmalloc.vcproj @@ -0,0 +1,410 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/build/vsproject/tbbmalloc_proxy.vcproj b/src/tbb/build/vsproject/tbbmalloc_proxy.vcproj new file mode 100644 index 0000000..12a60f7 --- /dev/null +++ b/src/tbb/build/vsproject/tbbmalloc_proxy.vcproj @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/build/vsproject/version_string.ver b/src/tbb/build/vsproject/version_string.ver new file mode 100644 index 0000000..5d8f04e --- /dev/null +++ b/src/tbb/build/vsproject/version_string.ver @@ -0,0 +1 @@ +#define __TBB_VERSION_STRINGS(N) "Empty" diff --git a/src/tbb/build/windows.cl.inc b/src/tbb/build/windows.cl.inc new file mode 100644 index 0000000..d4ae95b --- /dev/null +++ b/src/tbb/build/windows.cl.inc @@ -0,0 +1,126 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +#------------------------------------------------------------------------------ +# Define compiler-specific variables. +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# Setting compiler flags. +#------------------------------------------------------------------------------ +CPLUS = cl /nologo +LINK_FLAGS = /link /nologo +LIB_LINK_FLAGS=/link /nologo /DLL /MAP /DEBUG /fixed:no /INCREMENTAL:NO +ifeq ($(runtime), vc_mt) + MS_CRT_KEY = /MT$(if $(findstring debug,$(cfg)),d) +else + MS_CRT_KEY = /MD$(if $(findstring debug,$(cfg)),d) +endif +EH_FLAGS = /EHsc /GR + +ifeq ($(cfg), release) + CPLUS_FLAGS = $(MS_CRT_KEY) /O2 /Zi $(EH_FLAGS) /Zc:forScope /Zc:wchar_t /D__TBB_LIB_NAME=$(TBB.LIB) + ASM_FLAGS = +endif +ifeq ($(cfg), debug) + CPLUS_FLAGS = $(MS_CRT_KEY) /Od /Ob0 /Zi $(EH_FLAGS) /Zc:forScope /Zc:wchar_t /DTBB_USE_DEBUG /D__TBB_LIB_NAME=$(TBB.LIB) + ASM_FLAGS = /DUSE_FRAME_POINTER +endif + + +COMPILE_ONLY = /c +PREPROC_ONLY = /TP /EP +INCLUDE_KEY = /I +DEFINE_KEY = /D +OUTPUT_KEY = /Fe +OUTPUTOBJ_KEY = /Fo +WARNING_AS_ERROR_KEY = /WX + +ifeq ($(runtime),vc7.1) + WARNING_KEY = /W3 +else + WARNING_KEY = /W4 +endif + +DYLIB_KEY = /DLL +EXPORT_KEY = /DEF: +NODEFAULTLIB_KEY = /Zl +NOINTRINSIC_KEY = /Oi- + +ifeq ($(runtime),vc8) + OPENMP_FLAG = /openmp + WARNING_KEY += /Wp64 + CPLUS_FLAGS += /D_USE_RTM_VERSION +endif +ifeq ($(runtime),vc9) + OPENMP_FLAG = /openmp +endif +ifeq ($(runtime),vc_mt) + OPENMP_FLAG = /openmp +endif +ifeq (intel64,$(arch)) + CPLUS_FLAGS += /GS- +endif + +CPLUS_FLAGS += /DDO_ITT_NOTIFY /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE \ + /D_WIN32_WINNT=$(_WIN32_WINNT) +C_FLAGS = $(CPLUS_FLAGS) +#------------------------------------------------------------------------------ +# End of setting compiler flags. +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# Setting assembler data. +#------------------------------------------------------------------------------ +ASSEMBLY_SOURCE=$(arch)-masm +ifeq (intel64,$(arch)) + ASM=ml64 /nologo + ASM_FLAGS += /DEM64T=1 /c /Zi + TBB_ASM.OBJ = atomic_support.obj intel64_misc.obj + MALLOC_ASM.OBJ = atomic_support.obj +else + ASM=ml /nologo + ASM_FLAGS += /c /coff /Zi + TBB_ASM.OBJ = atomic_support.obj lock_byte.obj +endif +#------------------------------------------------------------------------------ +# End of setting assembler data. +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# Setting tbbmalloc data. +#------------------------------------------------------------------------------ +M_CPLUS_FLAGS = $(subst $(EH_FLAGS),/EHs-,$(CPLUS_FLAGS)) +#------------------------------------------------------------------------------ +# End of setting tbbmalloc data. +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# End of define compiler-specific variables. +#------------------------------------------------------------------------------ diff --git a/src/tbb/build/windows.gcc.inc b/src/tbb/build/windows.gcc.inc new file mode 100644 index 0000000..15851db --- /dev/null +++ b/src/tbb/build/windows.gcc.inc @@ -0,0 +1,137 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +#------------------------------------------------------------------------------ +# Overriding settings from windows.inc +#------------------------------------------------------------------------------ + +SLASH= $(strip \) +OBJ = o +LIBEXT = dll # MinGW allows linking with DLLs directly + +TBB.RES = +MALLOC.RES = +RML.RES = +TBB.MANIFEST = +MALLOC.MANIFEST = +RML.MANIFEST = + +ifeq (ia32,$(arch)) + TBB.LST = $(tbb_root)/src/tbb/lin32-tbb-export.lst +else + TBB.LST = $(tbb_root)/src/tbb/win64-gcc-tbb-export.lst +endif +MALLOC.DEF = $(MALLOC_ROOT)/$(def_prefix)-gcc-tbbmalloc-export.def +RML.DEF = $(RML_SERVER_ROOT)/lin-rml-export.def + +LINK_TBB.LIB = $(TBB.LIB) + +#------------------------------------------------------------------------------ +# End of overridden settings +#------------------------------------------------------------------------------ +# Compiler-specific variables +#------------------------------------------------------------------------------ + +CPLUS = g++ +COMPILE_ONLY = -c -MMD +PREPROC_ONLY = -E -x c++ +INCLUDE_KEY = -I +DEFINE_KEY = -D +OUTPUT_KEY = -o # +OUTPUTOBJ_KEY = -o # +PIC_KEY = +WARNING_AS_ERROR_KEY = -Werror +WARNING_KEY = -Wall +TEST_WARNING_KEY = -Wextra -Wshadow -Wcast-qual -Woverloaded-virtual -Wnon-virtual-dtor -Wno-uninitialized +WARNING_SUPPRESS = -Wno-parentheses -Wno-uninitialized +DYLIB_KEY = -shared +LIBDL = +EXPORT_KEY = -Wl,--version-script, +LIBS = -lpsapi + +#------------------------------------------------------------------------------ +# End of compiler-specific variables +#------------------------------------------------------------------------------ +# Command lines +#------------------------------------------------------------------------------ + +LINK_FLAGS = -Wl,--enable-auto-import +LIB_LINK_FLAGS = $(DYLIB_KEY) +# gcc 4.4 and higher support -std=c++0x +ifeq (ok,$(shell cmd /C "cscript /nologo /E:jscript $(tbb_root)/build/detect.js /minversion gcc 4.4")) + CPP11_FLAGS = -std=c++0x -D_TBB_CPP0X +endif + +ifeq ($(cfg), release) + CPLUS_FLAGS = -O2 +endif +ifeq ($(cfg), debug) + CPLUS_FLAGS = -g -O0 -DTBB_USE_DEBUG +endif +CPLUS_FLAGS += -DUSE_WINTHREAD +CPLUS_FLAGS += -D_WIN32_WINNT=$(_WIN32_WINNT) + +# MinGW specific +CPLUS_FLAGS += -DMINGW_HAS_SECURE_API=1 -D__MSVCRT_VERSION__=0x0700 -msse -mthreads + +CONLY = gcc +C_FLAGS = $(CPLUS_FLAGS) + +ifeq (intel64,$(arch)) + CPLUS_FLAGS += -m64 + LIB_LINK_FLAGS += -m64 +endif + +ifeq (ia32,$(arch)) + CPLUS_FLAGS += -m32 -march=i686 + LIB_LINK_FLAGS += -m32 +endif + +# For examples +export UNIXMODE = 1 + +#------------------------------------------------------------------------------ +# End of command lines +#------------------------------------------------------------------------------ +# Setting assembler data +#------------------------------------------------------------------------------ + +ASM= +ASM_FLAGS= +TBB_ASM.OBJ= +ASSEMBLY_SOURCE=$(arch)-gas + +#------------------------------------------------------------------------------ +# End of setting assembler data +#------------------------------------------------------------------------------ +# Setting tbbmalloc data +#------------------------------------------------------------------------------ + +M_CPLUS_FLAGS = $(CPLUS_FLAGS) -fno-rtti -fno-exceptions + +#------------------------------------------------------------------------------ +# End of setting tbbmalloc data +#------------------------------------------------------------------------------ diff --git a/src/tbb/build/windows.icl.inc b/src/tbb/build/windows.icl.inc new file mode 100644 index 0000000..7f38b22 --- /dev/null +++ b/src/tbb/build/windows.icl.inc @@ -0,0 +1,167 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +#------------------------------------------------------------------------------ +# Define compiler-specific variables. +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# Setting default configuration to release. +#------------------------------------------------------------------------------ +cfg ?= release +#------------------------------------------------------------------------------ +# End of setting default configuration to release. +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# Setting compiler flags. +#------------------------------------------------------------------------------ +CPLUS = icl /nologo $(VCCOMPAT_FLAG) +LINK_FLAGS = /link /nologo +LIB_LINK_FLAGS= /link /nologo /DLL /MAP /DEBUG /fixed:no /INCREMENTAL:NO + +# ICC 11.0 and higher support -std=c++0x +ifeq (ok,$(shell cmd /C "cscript /nologo /E:jscript $(tbb_root)/build/detect.js /minversion icl 11")) + CPP11_FLAGS = /Qstd=c++0x /D_TBB_CPP0X +endif + +# ICC 12.0 and higher provide Intel(R) Cilk Plus +ifeq (ok,$(shell cmd /C "cscript /nologo /E:jscript $(tbb_root)/build/detect.js /minversion icl 12")) + CILK_AVAILABLE = yes +endif + +ifeq ($(runtime), vc_mt) + MS_CRT_KEY = /MT$(if $(findstring debug,$(cfg)),d) +else + MS_CRT_KEY = /MD$(if $(findstring debug,$(cfg)),d) +endif +EH_FLAGS = /EHsc /GR + +ifeq ($(cfg), release) + CPLUS_FLAGS = $(MS_CRT_KEY) /O2 /Zi $(EH_FLAGS) /Zc:forScope /Zc:wchar_t /D__TBB_LIB_NAME=$(TBB.LIB) + ASM_FLAGS = +endif +ifeq ($(cfg), debug) + CPLUS_FLAGS = $(MS_CRT_KEY) /Od /Ob0 /Zi $(EH_FLAGS) /Zc:forScope /Zc:wchar_t /DTBB_USE_DEBUG /D__TBB_LIB_NAME=$(TBB.LIB) + ASM_FLAGS = /DUSE_FRAME_POINTER +endif + + +COMPILE_ONLY = /c /QMMD +# PREPROC_ONLY should really use /TP which applies to all files in the command line. +# But with /TP, ICL does not preprocess *.def files. +PREPROC_ONLY = /EP /Tp +INCLUDE_KEY = /I +DEFINE_KEY = /D +OUTPUT_KEY = /Fe +OUTPUTOBJ_KEY = /Fo +WARNING_AS_ERROR_KEY = /WX +WARNING_KEY = /W3 +DYLIB_KEY = /DLL +EXPORT_KEY = /DEF: +NODEFAULTLIB_KEY = /Zl +NOINTRINSIC_KEY = /Oi- + +ifeq (intel64,$(arch)) + CPLUS_FLAGS += /GS- +endif + +ifneq (,$(codecov)) + CPLUS_FLAGS += /Qprof-genx +else + CPLUS_FLAGS += /DDO_ITT_NOTIFY +endif + +OPENMP_FLAG = /Qopenmp +CPLUS_FLAGS += /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE \ + /D_WIN32_WINNT=$(_WIN32_WINNT) + +ifeq ($(runtime),vc8) + CPLUS_FLAGS += /D_USE_RTM_VERSION +endif + + +C_FLAGS = $(CPLUS_FLAGS) + +ifneq (00,$(lambdas)$(cpp0x)) + CPLUS_FLAGS += $(CPP11_FLAGS) +endif + +VCVERSION:=$(runtime) +VCCOMPAT_FLAG ?= $(if $(findstring vc7.1, $(VCVERSION)),/Qvc7.1) +ifeq ($(VCCOMPAT_FLAG),) + VCCOMPAT_FLAG := $(if $(findstring vc8, $(VCVERSION)),/Qvc8) +endif +ifeq ($(VCCOMPAT_FLAG),) + VCCOMPAT_FLAG := $(if $(findstring vc_mt, $(VCVERSION)),/Qvc10) +endif +ifeq ($(VCCOMPAT_FLAG),) + VCCOMPAT_FLAG := $(if $(findstring vc9, $(VCVERSION)),/Qvc9) +endif +ifeq ($(VCCOMPAT_FLAG),) + VCCOMPAT_FLAG := $(if $(findstring vc10, $(VCVERSION)),/Qvc10) +endif +ifeq ($(VCCOMPAT_FLAG),) + $(error VC version not detected correctly: $(VCVERSION) ) +endif +export VCCOMPAT_FLAG +#------------------------------------------------------------------------------ +# End of setting compiler flags. +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# Setting assembler data. +#------------------------------------------------------------------------------ +ASSEMBLY_SOURCE=$(arch)-masm +ifeq (intel64,$(arch)) + ASM=ml64 /nologo + ASM_FLAGS += /DEM64T=1 /c /Zi + TBB_ASM.OBJ = atomic_support.obj intel64_misc.obj + MALLOC_ASM.OBJ = atomic_support.obj +else + ASM=ml /nologo + ASM_FLAGS += /c /coff /Zi + TBB_ASM.OBJ = atomic_support.obj lock_byte.obj +endif +#------------------------------------------------------------------------------ +# End of setting assembler data. +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# Setting tbbmalloc data. +#------------------------------------------------------------------------------ +M_CPLUS_FLAGS = $(subst $(EH_FLAGS),/EHs-,$(CPLUS_FLAGS)) +#------------------------------------------------------------------------------ +# End of setting tbbmalloc data. +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# End of define compiler-specific variables. +#------------------------------------------------------------------------------ diff --git a/src/tbb/build/windows.inc b/src/tbb/build/windows.inc new file mode 100644 index 0000000..03c8661 --- /dev/null +++ b/src/tbb/build/windows.inc @@ -0,0 +1,110 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +export SHELL = cmd + +ifdef tbb_build_dir + test_dir:=$(tbb_build_dir) +else + test_dir:=. +endif + +# TODO give an error if archs doesn't match +ifndef arch + export arch:=$(shell cmd /C "cscript /nologo /E:jscript $(tbb_root)/build/detect.js /arch $(compiler)") +endif + +ifndef runtime + export runtime:=$(shell cmd /C "cscript /nologo /E:jscript $(tbb_root)/build/detect.js /runtime $(compiler)") +endif + +native_compiler := cl +export compiler ?= cl +debugger ?= devenv /debugexe + +CMD=cmd /C +CWD=$(shell cmd /C echo %CD%) +RM=cmd /C del /Q /F +RD=cmd /C rmdir +MD=cmd /c mkdir +SLASH=\\ +NUL = nul + +AR=lib +AR_OUTPUT_KEY=/out: +AR_FLAGS=/nologo /nodefaultlib + +OBJ = obj +DLL = dll +LIBEXT = lib +ASMEXT = asm + +def_prefix = $(if $(findstring ia32,$(arch)),win32,win64) + +# Target Windows version. Do not increase beyond 0x0501 without prior discussion! +# Used as the value for macro definition opiton in windows.cl.inc etc. +_WIN32_WINNT=0x0501 + +TBB.LST = $(tbb_root)/src/tbb/$(def_prefix)-tbb-export.lst +TBB.DEF = $(TBB.LST:.lst=.def) +TBB.DLL = tbb$(CPF_SUFFIX)$(DEBUG_SUFFIX).$(DLL) +TBB.LIB = tbb$(CPF_SUFFIX)$(DEBUG_SUFFIX).$(LIBEXT) +TBB.RES = tbb_resource.res +# On Windows, we use #pragma comment to set the proper TBB lib to link with +# But for cross-configuration testing, need to link explicitly +LINK_TBB.LIB = $(if $(crosstest),$(TBB.LIB)) +TBB.MANIFEST = +ifneq ($(filter vc8 vc9,$(runtime)),) + TBB.MANIFEST = tbbmanifest.exe.manifest +endif + +MALLOC.DEF = $(MALLOC_ROOT)/$(def_prefix)-tbbmalloc-export.def +MALLOC.DLL = tbbmalloc$(DEBUG_SUFFIX).$(DLL) +MALLOC.LIB = tbbmalloc$(DEBUG_SUFFIX).$(LIBEXT) +MALLOC.RES = tbbmalloc.res +MALLOC.MANIFEST = +ifneq ($(filter vc8 vc9,$(runtime)),) +MALLOC.MANIFEST = tbbmanifest.exe.manifest +endif +LINK_MALLOC.LIB = $(MALLOC.LIB) + +MALLOCPROXY.DLL = tbbmalloc_proxy$(DEBUG_SUFFIX).$(DLL) +MALLOCPROXY.LIB = tbbmalloc_proxy$(DEBUG_SUFFIX).$(LIBEXT) + +PROXY.LIB = tbbproxy$(DEBUG_SUFFIX).$(LIBEXT) + +RML.DEF = $(RML_SERVER_ROOT)/$(def_prefix)-rml-export.def +RML.DLL = irml$(DEBUG_SUFFIX).$(DLL) +RML.LIB = irml$(DEBUG_SUFFIX).$(LIBEXT) +RML.RES = irml.res +ifneq ($(filter vc8 vc9,$(runtime)),) +RML.MANIFEST = tbbmanifest.exe.manifest +endif + +MAKE_VERSIONS = cmd /C cscript /nologo /E:jscript $(subst \,/,$(tbb_root))/build/version_info_windows.js $(compiler) $(arch) $(subst \,/,"$(CPLUS) $(CPLUS_FLAGS)") > version_string.ver +MAKE_TBBVARS = cmd /C "$(subst /,\,$(tbb_root))\build\generate_tbbvars.bat" + +TEST_LAUNCHER = $(subst /,\,$(tbb_root))\build\test_launcher.bat diff --git a/src/tbb/build/xbox360.cl.inc b/src/tbb/build/xbox360.cl.inc new file mode 100644 index 0000000..7efa4e9 --- /dev/null +++ b/src/tbb/build/xbox360.cl.inc @@ -0,0 +1,93 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +#------------------------------------------------------------------------------ +# Define compiler-specific variables. +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# Setting compiler flags. +#------------------------------------------------------------------------------ +CPLUS = cl /nologo +LINK_FLAGS = /link /nologo +LIB_LINK_FLAGS=/link /nologo /DLL /MAP /DEBUG +MS_CRT_KEY = /MT$(if $(findstring debug,$(cfg)),d) +EH_FLAGS = /EHsc /GR + +ifeq ($(cfg), release) + CPLUS_FLAGS = $(MS_CRT_KEY) /O2 /Zi $(EH_FLAGS) /Zc:forScope /D_XBOX /DTBB_NO_LEGACY=1 + ASM_FLAGS = +endif +ifeq ($(cfg), debug) + CPLUS_FLAGS = $(MS_CRT_KEY) /Od /Ob0 /Zi $(EH_FLAGS) /Zc:forScope \ + /DTBB_USE_DEBUG /D_XBOX /DTBB_NO_LEGACY=1 + ASM_FLAGS = /DUSE_FRAME_POINTER +endif + + +COMPILE_ONLY = /c +PREPROC_ONLY = /TP /EP +INCLUDE_KEY = /I +DEFINE_KEY = /D +OUTPUT_KEY = /Fe +OUTPUTOBJ_KEY = /Fo +WARNING_AS_ERROR_KEY = /WX +WARNING_KEY = /W3 +DYLIB_KEY = /DLL +EXPORT_KEY = /DEF: + +ifeq (em64t,$(arch)) + CPLUS_FLAGS += /GS- +endif + +CPLUS_FLAGS += /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=$(_WIN32_WINNT) +C_FLAGS = $(CPLUS_FLAGS) /TC +#------------------------------------------------------------------------------ +# End of setting compiler flags. +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# Setting assembler data. +#------------------------------------------------------------------------------ +# nothing for XBOX360 +#------------------------------------------------------------------------------ +# End of setting assembler data. +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# Setting tbbmalloc data. +#------------------------------------------------------------------------------ +M_CPLUS_FLAGS = $(subst $(EH_FLAGS),/EHs-,$(CPLUS_FLAGS)) +#------------------------------------------------------------------------------ +# End of setting tbbmalloc data. +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# End of define compiler-specific variables. +#------------------------------------------------------------------------------ diff --git a/src/tbb/build/xbox360.inc b/src/tbb/build/xbox360.inc new file mode 100644 index 0000000..b215942 --- /dev/null +++ b/src/tbb/build/xbox360.inc @@ -0,0 +1,78 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +ifdef tbb_build_dir + test_dir:=$(tbb_build_dir) +else + test_dir:=. +endif + +# TODO give an error if archs doesn't match +ifndef arch + export arch:=xbox360 +endif + +ifndef runtime + export runtime:=xdk +endif + +native_compiler := cl +export compiler ?= cl +debugger ?= devenv /debugexe + +CMD=cmd /C +CWD=$(shell cmd /C echo %CD%) +RM=cmd /C del /Q /F +RD=cmd /C rmdir +MD=cmd /c mkdir +SLASH=\\ +NUL = nul + +OBJ = obj +DLL = dll +LIBEXT = lib + +def_prefix = $(arch) + +# Target Windows version. Do not increase beyond 0x0500 without prior discussion! +# Used as the value for macro definition opiton in compiler specific inc files. +_WIN32_WINNT=0x0400 + +TBB.LST = +TBB.DEF = $(tbb_root)/src/tbb/$(def_prefix)-tbb-export.def +TBB.DLL = tbb$(CPF_SUFFIX)$(DEBUG_SUFFIX).$(DLL) +TBB.LIB = tbb$(CPF_SUFFIX)$(DEBUG_SUFFIX).$(LIBEXT) +TBB.RES = +#On Windows we specify appropriate tbb library using #pragma comment +LINK_TBB.LIB = + +MALLOC.DEF = $(MALLOC_ROOT)/$(def_prefix)-tbbmalloc-export.def +MALLOC.DLL = tbbmalloc$(DEBUG_SUFFIX).$(DLL) +MALLOC.LIB = tbbmalloc$(DEBUG_SUFFIX).$(LIBEXT) +MALLOC.RES = + +MAKE_VERSIONS = cmd /C cscript /nologo /E:jscript $(subst \,/,$(tbb_root))/build/version_info_windows.js $(compiler) $(arch) $(subst \,/,"$(CPLUS) $(CPLUS_FLAGS) $(INCLUDES)") > version_string.ver +MAKE_TBBVARS = cmd /C "$(subst /,\,$(tbb_root))\build\generate_tbbvars.bat" diff --git a/src/tbb/doc/Release_Notes.txt b/src/tbb/doc/Release_Notes.txt new file mode 100644 index 0000000..e7290e5 --- /dev/null +++ b/src/tbb/doc/Release_Notes.txt @@ -0,0 +1,126 @@ +------------------------------------------------------------------------ +Intel(R) Threading Building Blocks - Release Notes + Version 4.0 +------------------------------------------------------------------------ + + +System Requirements +------------------- + +Intel(R) Threading Building Blocks (Intel(R) TBB) is available +commercially (see http://software.intel.com/en-us/intel-tbb) as a +binary distribution, and in open source, in both source and binary +forms (see http://threadingbuildingblocks.org). + +When built from source, Intel(R) TBB is intended to be highly portable +and so supports a wide variety of operating systems and platforms (see +http://threadingbuildingblocks.org for more details). + +Binary distributions, including commercial distributions, are validated +and officially supported for the hardware, software, operating systems +and compilers listed here. + +Hardware - Recommended + + Microsoft* Windows* Systems + Intel(R) Core(TM) 2 Duo processor or Intel(R) Xeon(R) processor + or higher + Linux* Systems + Intel(R) Core(TM) 2 Duo processor or Intel(R) Xeon(R) processor + or higher + Mac OS* X Systems + Intel(R) Core(TM) 2 Duo processor or higher + +Hardware - Supported + + Intel(R) Pentium(R) 4 processor family and higher + Non Intel(R) processors compatible with the above processors + +Software - Minimum Requirements + + Supported operating system (see below) + Supported compiler (see below) + Adobe(R) Reader(R)* 7.0 or higher + +Software - Recommended + + Intel(R) Parallel Studio XE 2011 and higher + Intel(R) Parallel Studio 2011 and higher + +Software - Supported Operating Systems + + Microsoft* Windows* Systems + Microsoft* Windows* 7 + Microsoft* Windows* Server 2008 + Microsoft* Windows* Vista + Microsoft* Windows* XP Professional + Microsoft* Windows* Server 2003 (deprecated) + Linux* Systems + Red Hat* Enterprise Linux* 6, 5, 4 (deprecated) + Fedora* 15 + Asianux* 4.0, 3.0 + Debian* GNU/Linux* 6.0 + Ubuntu* 11.04, 10.04 LTS + SuSE* Linux* Enterprise Server 10, 11SP1 + Mac OS* X Systems + Mac OS* X 10.6.7 or higher + +Software - Supported Compilers + + Intel(R) C++ Composer XE 2011 and higher + Intel(R) C++ Compiler 11.1 + Microsoft* Visual C++ 10.0 (Microsoft* Visual Studio* 2010, + Windows* systems only) + Microsoft* Visual C++ 9.0 (Microsoft* Visual Studio* 2008, + Windows* systems only) + Microsoft* Visual C++ 8.0 (Microsoft* Visual Studio* 2005, + Windows* systems only, deprecated) + For each supported Linux* operating system, the standard gcc + version provided with that operating system is supported, + including gcc 3.4 through 4.6 + For each supported Mac OS* X operating system, the standard gcc + version provided with that operating system is supported, + including: 4.0.1 or higher (Xcode* tool suite 3.2.5 or higher) + + +Known Issues +------------ + +Please note the following with respect to this particular release of +Intel(R) Threading Building Blocks. + +Library Issues + + - If an application uses static version of MSVCRT libraries or uses + TBB DLL built with static MSVCRT (vc_mt variant), and throws + an exception from a functor passed to task_group::run_and_wait(), + the exception will not be intercepted by TBB and will not result + in cancellation of the task_group. For a workaround, catch the + exception in the functor and explicitly cancel the task_group. + + - If you are using Intel(R) Threading Building Blocks and OpenMP* + constructs mixed together in rapid succession in the same + program, and you are using Intel(R) compilers for your OpenMP* + code, set KMP_BLOCKTIME to a small value (e.g., 20 milliseconds) + to improve performance. This setting can also be made within + your OpenMP* code via the kmp_set_blocktime() library call. See + the Intel(R) compiler OpenMP* documentation for more details on + KMP_BLOCKTIME and kmp_set_blocktime(). + + - In general, non-debug ("release") builds of applications or + examples should link against the non-debug versions of the + Intel(R) Threading Building Blocks libraries, and debug builds + should link against the debug versions of these libraries. On + Windows* systems, compile with /MD and use Intel(R) Threading + Building Blocks release libraries, or compile with /MDd and use + debug libraries; not doing so may cause run-time failures. See + the Tutorial in the product "doc" sub-directory for more details + on debug vs. release libraries. + +------------------------------------------------------------------------ +Copyright (C) 2005-2012 Intel Corporation. All Rights Reserved. + +Intel, Xeon and Pentium are registered trademarks or trademarks of +Intel Corporation or its subsidiaries in the United States and other countries. + +* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00005.html b/src/tbb/doc/html/a00005.html new file mode 100644 index 0000000..13dede1 --- /dev/null +++ b/src/tbb/doc/html/a00005.html @@ -0,0 +1,35 @@ + + +Member List + + + + + + +

tbb::interface6::aggregator_ext< handler_type > Member List

This is the complete list of members for tbb::interface6::aggregator_ext< handler_type >, including all inherited members.

+ + + +
aggregator_ext(const handler_type &h) (defined in tbb::interface6::aggregator_ext< handler_type >)tbb::interface6::aggregator_ext< handler_type > [inline]
execute_impl(aggregator_operation &op)tbb::interface6::aggregator_ext< handler_type > [inline, protected]
process(aggregator_operation *op)tbb::interface6::aggregator_ext< handler_type > [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00006.html b/src/tbb/doc/html/a00006.html new file mode 100644 index 0000000..48d1954 --- /dev/null +++ b/src/tbb/doc/html/a00006.html @@ -0,0 +1,37 @@ + + +Member List + + + + + + +

tbb::interface6::aggregator Member List

This is the complete list of members for tbb::interface6::aggregator, including all inherited members.

+ + + + + +
aggregator() (defined in tbb::interface6::aggregator)tbb::interface6::aggregator [inline]
aggregator_ext(const handler_type &h) (defined in tbb::interface6::aggregator_ext< handler_type >)tbb::interface6::aggregator_ext< handler_type > [inline, private]
execute(const Body &b)tbb::interface6::aggregator [inline]
execute_impl(aggregator_operation &op)tbb::interface6::aggregator_ext< handler_type > [inline, private]
process(aggregator_operation *op)tbb::interface6::aggregator_ext< handler_type > [inline, private]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00007.html b/src/tbb/doc/html/a00007.html new file mode 100644 index 0000000..8834756 --- /dev/null +++ b/src/tbb/doc/html/a00007.html @@ -0,0 +1,34 @@ + + +Member List + + + + + + +

tbb::aligned_space< T, N > Member List

This is the complete list of members for tbb::aligned_space< T, N >, including all inherited members.

+ + +
begin()tbb::aligned_space< T, N > [inline]
end()tbb::aligned_space< T, N > [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00008.html b/src/tbb/doc/html/a00008.html new file mode 100644 index 0000000..318ca84 --- /dev/null +++ b/src/tbb/doc/html/a00008.html @@ -0,0 +1,34 @@ + + +Member List + + + + + + +

tbb::atomic< T > Member List

This is the complete list of members for tbb::atomic< T >, including all inherited members.

+ + +
operator=(T rhs) (defined in tbb::atomic< T >)tbb::atomic< T > [inline]
operator=(const atomic< T > &rhs) (defined in tbb::atomic< T >)tbb::atomic< T > [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00009.html b/src/tbb/doc/html/a00009.html new file mode 100644 index 0000000..823bc54 --- /dev/null +++ b/src/tbb/doc/html/a00009.html @@ -0,0 +1,34 @@ + + +Member List + + + + + + +

tbb::atomic< void * > Member List

This is the complete list of members for tbb::atomic< void * >, including all inherited members.

+ + +
operator=(void *rhs) (defined in tbb::atomic< void * >)tbb::atomic< void * > [inline]
operator=(const atomic< void * > &rhs) (defined in tbb::atomic< void * >)tbb::atomic< void * > [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00010.html b/src/tbb/doc/html/a00010.html new file mode 100644 index 0000000..7a86408 --- /dev/null +++ b/src/tbb/doc/html/a00010.html @@ -0,0 +1,45 @@ + + +Member List + + + + + + +

tbb::blocked_range< Value > Member List

This is the complete list of members for tbb::blocked_range< Value >, including all inherited members.

+ + + + + + + + + + + + + +
begin() const tbb::blocked_range< Value > [inline]
blocked_range()tbb::blocked_range< Value > [inline]
blocked_range(Value begin_, Value end_, size_type grainsize_=1)tbb::blocked_range< Value > [inline]
blocked_range(blocked_range &r, split)tbb::blocked_range< Value > [inline]
blocked_range2d (defined in tbb::blocked_range< Value >)tbb::blocked_range< Value > [friend]
blocked_range3d (defined in tbb::blocked_range< Value >)tbb::blocked_range< Value > [friend]
const_iterator typedeftbb::blocked_range< Value >
empty() const tbb::blocked_range< Value > [inline]
end() const tbb::blocked_range< Value > [inline]
grainsize() const tbb::blocked_range< Value > [inline]
is_divisible() const tbb::blocked_range< Value > [inline]
size() const tbb::blocked_range< Value > [inline]
size_type typedeftbb::blocked_range< Value >


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00011.html b/src/tbb/doc/html/a00011.html new file mode 100644 index 0000000..c3a6787 --- /dev/null +++ b/src/tbb/doc/html/a00011.html @@ -0,0 +1,41 @@ + + +Member List + + + + + + +

tbb::blocked_range2d< RowValue, ColValue > Member List

This is the complete list of members for tbb::blocked_range2d< RowValue, ColValue >, including all inherited members.

+ + + + + + + + + +
blocked_range2d(RowValue row_begin, RowValue row_end, typename row_range_type::size_type row_grainsize, ColValue col_begin, ColValue col_end, typename col_range_type::size_type col_grainsize) (defined in tbb::blocked_range2d< RowValue, ColValue >)tbb::blocked_range2d< RowValue, ColValue > [inline]
blocked_range2d(RowValue row_begin, RowValue row_end, ColValue col_begin, ColValue col_end) (defined in tbb::blocked_range2d< RowValue, ColValue >)tbb::blocked_range2d< RowValue, ColValue > [inline]
blocked_range2d(blocked_range2d &r, split) (defined in tbb::blocked_range2d< RowValue, ColValue >)tbb::blocked_range2d< RowValue, ColValue > [inline]
col_range_type typedef (defined in tbb::blocked_range2d< RowValue, ColValue >)tbb::blocked_range2d< RowValue, ColValue >
cols() const tbb::blocked_range2d< RowValue, ColValue > [inline]
empty() const tbb::blocked_range2d< RowValue, ColValue > [inline]
is_divisible() const tbb::blocked_range2d< RowValue, ColValue > [inline]
row_range_type typedeftbb::blocked_range2d< RowValue, ColValue >
rows() const tbb::blocked_range2d< RowValue, ColValue > [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00012.html b/src/tbb/doc/html/a00012.html new file mode 100644 index 0000000..0599205 --- /dev/null +++ b/src/tbb/doc/html/a00012.html @@ -0,0 +1,43 @@ + + +Member List + + + + + + +

tbb::blocked_range3d< PageValue, RowValue, ColValue > Member List

This is the complete list of members for tbb::blocked_range3d< PageValue, RowValue, ColValue >, including all inherited members.

+ + + + + + + + + + + +
blocked_range3d(PageValue page_begin, PageValue page_end, RowValue row_begin, RowValue row_end, ColValue col_begin, ColValue col_end) (defined in tbb::blocked_range3d< PageValue, RowValue, ColValue >)tbb::blocked_range3d< PageValue, RowValue, ColValue > [inline]
blocked_range3d(PageValue page_begin, PageValue page_end, typename page_range_type::size_type page_grainsize, RowValue row_begin, RowValue row_end, typename row_range_type::size_type row_grainsize, ColValue col_begin, ColValue col_end, typename col_range_type::size_type col_grainsize) (defined in tbb::blocked_range3d< PageValue, RowValue, ColValue >)tbb::blocked_range3d< PageValue, RowValue, ColValue > [inline]
blocked_range3d(blocked_range3d &r, split) (defined in tbb::blocked_range3d< PageValue, RowValue, ColValue >)tbb::blocked_range3d< PageValue, RowValue, ColValue > [inline]
col_range_type typedef (defined in tbb::blocked_range3d< PageValue, RowValue, ColValue >)tbb::blocked_range3d< PageValue, RowValue, ColValue >
cols() const tbb::blocked_range3d< PageValue, RowValue, ColValue > [inline]
empty() const tbb::blocked_range3d< PageValue, RowValue, ColValue > [inline]
is_divisible() const tbb::blocked_range3d< PageValue, RowValue, ColValue > [inline]
page_range_type typedeftbb::blocked_range3d< PageValue, RowValue, ColValue >
pages() const tbb::blocked_range3d< PageValue, RowValue, ColValue > [inline]
row_range_type typedef (defined in tbb::blocked_range3d< PageValue, RowValue, ColValue >)tbb::blocked_range3d< PageValue, RowValue, ColValue >
rows() const tbb::blocked_range3d< PageValue, RowValue, ColValue > [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00013.html b/src/tbb/doc/html/a00013.html new file mode 100644 index 0000000..abb30bd --- /dev/null +++ b/src/tbb/doc/html/a00013.html @@ -0,0 +1,48 @@ + + +Member List + + + + + + +

tbb::cache_aligned_allocator< T > Member List

This is the complete list of members for tbb::cache_aligned_allocator< T >, including all inherited members.

+ + + + + + + + + + + + + + + + +
address(reference x) const (defined in tbb::cache_aligned_allocator< T >)tbb::cache_aligned_allocator< T > [inline]
address(const_reference x) const (defined in tbb::cache_aligned_allocator< T >)tbb::cache_aligned_allocator< T > [inline]
allocate(size_type n, const void *hint=0)tbb::cache_aligned_allocator< T > [inline]
cache_aligned_allocator() (defined in tbb::cache_aligned_allocator< T >)tbb::cache_aligned_allocator< T > [inline]
cache_aligned_allocator(const cache_aligned_allocator &) (defined in tbb::cache_aligned_allocator< T >)tbb::cache_aligned_allocator< T > [inline]
cache_aligned_allocator(const cache_aligned_allocator< U > &) (defined in tbb::cache_aligned_allocator< T >)tbb::cache_aligned_allocator< T > [inline]
const_pointer typedef (defined in tbb::cache_aligned_allocator< T >)tbb::cache_aligned_allocator< T >
const_reference typedef (defined in tbb::cache_aligned_allocator< T >)tbb::cache_aligned_allocator< T >
construct(pointer p, Args &&...args)tbb::cache_aligned_allocator< T > [inline]
deallocate(pointer p, size_type)tbb::cache_aligned_allocator< T > [inline]
difference_type typedef (defined in tbb::cache_aligned_allocator< T >)tbb::cache_aligned_allocator< T >
max_size() const tbb::cache_aligned_allocator< T > [inline]
pointer typedef (defined in tbb::cache_aligned_allocator< T >)tbb::cache_aligned_allocator< T >
reference typedef (defined in tbb::cache_aligned_allocator< T >)tbb::cache_aligned_allocator< T >
size_type typedef (defined in tbb::cache_aligned_allocator< T >)tbb::cache_aligned_allocator< T >
value_type typedef (defined in tbb::cache_aligned_allocator< T >)tbb::cache_aligned_allocator< T >


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00015.html b/src/tbb/doc/html/a00015.html new file mode 100644 index 0000000..e20af72 --- /dev/null +++ b/src/tbb/doc/html/a00015.html @@ -0,0 +1,35 @@ + + +Member List + + + + + + +

tbb::cache_aligned_allocator< void > Member List

This is the complete list of members for tbb::cache_aligned_allocator< void >, including all inherited members.

+ + + +
const_pointer typedef (defined in tbb::cache_aligned_allocator< void >)tbb::cache_aligned_allocator< void >
pointer typedef (defined in tbb::cache_aligned_allocator< void >)tbb::cache_aligned_allocator< void >
value_type typedef (defined in tbb::cache_aligned_allocator< void >)tbb::cache_aligned_allocator< void >


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00017.html b/src/tbb/doc/html/a00017.html new file mode 100644 index 0000000..40f9017 --- /dev/null +++ b/src/tbb/doc/html/a00017.html @@ -0,0 +1,42 @@ + + +Member List + + + + + + +

tbb::combinable< T > Member List

This is the complete list of members for tbb::combinable< T >, including all inherited members.

+ + + + + + + + + + +
clear() (defined in tbb::combinable< T >)tbb::combinable< T > [inline]
combinable() (defined in tbb::combinable< T >)tbb::combinable< T > [inline]
combinable(finit _finit) (defined in tbb::combinable< T >)tbb::combinable< T > [inline]
combinable(const combinable &other) (defined in tbb::combinable< T >)tbb::combinable< T > [inline]
combine(combine_func_t f_combine) (defined in tbb::combinable< T >)tbb::combinable< T > [inline]
combine_each(combine_func_t f_combine) (defined in tbb::combinable< T >)tbb::combinable< T > [inline]
local() (defined in tbb::combinable< T >)tbb::combinable< T > [inline]
local(bool &exists) (defined in tbb::combinable< T >)tbb::combinable< T > [inline]
operator=(const combinable &other) (defined in tbb::combinable< T >)tbb::combinable< T > [inline]
~combinable()tbb::combinable< T > [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00018.html b/src/tbb/doc/html/a00018.html new file mode 100644 index 0000000..c0fcf95 --- /dev/null +++ b/src/tbb/doc/html/a00018.html @@ -0,0 +1,34 @@ + + +Member List + + + + + + +

tbb::tbb_hash_compare< Key > Member List

This is the complete list of members for tbb::tbb_hash_compare< Key >, including all inherited members.

+ + +
equal(const Key &a, const Key &b) (defined in tbb::tbb_hash_compare< Key >)tbb::tbb_hash_compare< Key > [inline, static]
hash(const Key &a) (defined in tbb::tbb_hash_compare< Key >)tbb::tbb_hash_compare< Key > [inline, static]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00019.html b/src/tbb/doc/html/a00019.html new file mode 100644 index 0000000..9e12c85 --- /dev/null +++ b/src/tbb/doc/html/a00019.html @@ -0,0 +1,95 @@ + + +Member List + + + + + + +

tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > Member List

This is the complete list of members for tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
allocator_type typedef (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >
begin() (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
begin() const (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
bucket_count() const tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
clear()tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >
concurrent_hash_map(const allocator_type &a=allocator_type())tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
concurrent_hash_map(size_type n, const allocator_type &a=allocator_type())tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
concurrent_hash_map(const concurrent_hash_map &table, const allocator_type &a=allocator_type())tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
concurrent_hash_map(I first, I last, const allocator_type &a=allocator_type())tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
const_accessor (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [friend]
const_iterator typedef (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >
const_pointer typedef (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >
const_range_type typedef (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >
const_reference typedef (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >
count(const Key &key) const tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
delete_node(node_base *n) (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline, protected]
difference_type typedef (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >
empty() const tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
end() (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
end() const (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
equal_range(const Key &key) (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
equal_range(const Key &key) const (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
erase(const Key &key)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >
erase(const_accessor &item_accessor)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
erase(accessor &item_accessor)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
exclude(const_accessor &item_accessor)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [protected]
find(const_accessor &result, const Key &key) const tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
find(accessor &result, const Key &key)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
get_allocator() const tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
insert(const_accessor &result, const Key &key)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
insert(accessor &result, const Key &key)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
insert(const_accessor &result, const value_type &value)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
insert(accessor &result, const value_type &value)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
insert(const value_type &value)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
insert(I first, I last)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
internal::hash_map_iterator (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [friend]
internal::hash_map_range (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [friend]
internal_copy(const concurrent_hash_map &source)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [protected]
internal_copy(I first, I last) (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [protected]
internal_equal_range(const Key &key, I end) const tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [protected]
internal_fast_find(const Key &key) const tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline, protected]
iterator typedef (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >
key_type typedef (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >
lookup(bool op_insert, const Key &key, const T *t, const_accessor *result, bool write)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [protected]
mapped_type typedef (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >
max_size() const tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
my_allocator (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [protected]
my_hash_compare (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [protected]
node_allocator_type typedef (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [protected]
operator=(const concurrent_hash_map &table)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
pointer typedef (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >
range(size_type grainsize=1) (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
range(size_type grainsize=1) const (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
range_type typedef (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >
reference typedef (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >
rehash(size_type n=0)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >
rehash_bucket(bucket *b_new, const hashcode_t h) (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline, protected]
search_bucket(const key_type &key, bucket *b) const (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline, protected]
size() const tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]
size_type typedef (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >
swap(concurrent_hash_map &table)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >
value_type typedef (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >
~concurrent_hash_map()tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00021.html b/src/tbb/doc/html/a00021.html new file mode 100644 index 0000000..912ea6f --- /dev/null +++ b/src/tbb/doc/html/a00021.html @@ -0,0 +1,36 @@ + + +Member List + + + + + + +

tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::bucket_accessor Member List

This is the complete list of members for tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::bucket_accessor, including all inherited members.

+ + + + +
acquire(concurrent_hash_map *base, const hashcode_t h, bool writer=false)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::bucket_accessor [inline]
bucket_accessor(concurrent_hash_map *base, const hashcode_t h, bool writer=false) (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::bucket_accessor)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::bucket_accessor [inline]
is_writer()tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::bucket_accessor [inline]
operator()()tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::bucket_accessor [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00022.html b/src/tbb/doc/html/a00022.html new file mode 100644 index 0000000..21504d7 --- /dev/null +++ b/src/tbb/doc/html/a00022.html @@ -0,0 +1,44 @@ + + +Member List + + + + + + +

tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor Member List

This is the complete list of members for tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor, including all inherited members.

+ + + + + + + + + + + + +
accessor (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor [friend]
concurrent_hash_map< Key, T, HashCompare, Allocator > (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor [friend]
const_accessor()tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor [inline]
empty() const tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor [inline]
is_writer() (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor [inline, protected]
my_hash (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor [protected]
my_node (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor [protected]
operator *() const tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor [inline]
operator->() const tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor [inline]
release()tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor [inline]
value_type typedeftbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor
~const_accessor()tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00023.html b/src/tbb/doc/html/a00023.html new file mode 100644 index 0000000..dc39faf --- /dev/null +++ b/src/tbb/doc/html/a00023.html @@ -0,0 +1,42 @@ + + +Member List + + + + + + +

tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::accessor Member List

This is the complete list of members for tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::accessor, including all inherited members.

+ + + + + + + + + + +
const_accessor()tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor [inline]
empty() const tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor [inline]
is_writer() (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor [inline, protected]
my_hash (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor [protected]
my_node (defined in tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor)tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor [protected]
operator *() const tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::accessor [inline]
operator->() const tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::accessor [inline]
release()tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor [inline]
value_type typedeftbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::accessor
~const_accessor()tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00031.html b/src/tbb/doc/html/a00031.html new file mode 100644 index 0000000..a7971f4 --- /dev/null +++ b/src/tbb/doc/html/a00031.html @@ -0,0 +1,51 @@ + + +Member List + + + + + + +

tbb::interface5::concurrent_priority_queue< T, Compare, A > Member List

This is the complete list of members for tbb::interface5::concurrent_priority_queue< T, Compare, A >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + +
allocator_type typedeftbb::interface5::concurrent_priority_queue< T, Compare, A >
clear()tbb::interface5::concurrent_priority_queue< T, Compare, A > [inline]
concurrent_priority_queue(const allocator_type &a=allocator_type())tbb::interface5::concurrent_priority_queue< T, Compare, A > [inline, explicit]
concurrent_priority_queue(size_type init_capacity, const allocator_type &a=allocator_type())tbb::interface5::concurrent_priority_queue< T, Compare, A > [inline, explicit]
concurrent_priority_queue(InputIterator begin, InputIterator end, const allocator_type &a=allocator_type())tbb::interface5::concurrent_priority_queue< T, Compare, A > [inline]
concurrent_priority_queue(const concurrent_priority_queue &src)tbb::interface5::concurrent_priority_queue< T, Compare, A > [inline, explicit]
concurrent_priority_queue(const concurrent_priority_queue &src, const allocator_type &a)tbb::interface5::concurrent_priority_queue< T, Compare, A > [inline]
const_reference typedeftbb::interface5::concurrent_priority_queue< T, Compare, A >
difference_type typedeftbb::interface5::concurrent_priority_queue< T, Compare, A >
empty() const tbb::interface5::concurrent_priority_queue< T, Compare, A > [inline]
get_allocator() const tbb::interface5::concurrent_priority_queue< T, Compare, A > [inline]
operator=(const concurrent_priority_queue &src)tbb::interface5::concurrent_priority_queue< T, Compare, A > [inline]
push(const_reference elem)tbb::interface5::concurrent_priority_queue< T, Compare, A > [inline]
reference typedeftbb::interface5::concurrent_priority_queue< T, Compare, A >
size() const tbb::interface5::concurrent_priority_queue< T, Compare, A > [inline]
size_type typedeftbb::interface5::concurrent_priority_queue< T, Compare, A >
swap(concurrent_priority_queue &q)tbb::interface5::concurrent_priority_queue< T, Compare, A > [inline]
try_pop(reference elem)tbb::interface5::concurrent_priority_queue< T, Compare, A > [inline]
value_type typedeftbb::interface5::concurrent_priority_queue< T, Compare, A >


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00035.html b/src/tbb/doc/html/a00035.html new file mode 100644 index 0000000..bead577 --- /dev/null +++ b/src/tbb/doc/html/a00035.html @@ -0,0 +1,55 @@ + + +Member List + + + + + + +

tbb::strict_ppl::concurrent_queue< T, A > Member List

This is the complete list of members for tbb::strict_ppl::concurrent_queue< T, A >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + +
allocator_type typedeftbb::strict_ppl::concurrent_queue< T, A >
clear()tbb::strict_ppl::concurrent_queue< T, A >
concurrent_queue(const allocator_type &a=allocator_type())tbb::strict_ppl::concurrent_queue< T, A > [inline, explicit]
concurrent_queue(InputIterator begin, InputIterator end, const allocator_type &a=allocator_type())tbb::strict_ppl::concurrent_queue< T, A > [inline]
concurrent_queue(const concurrent_queue &src, const allocator_type &a=allocator_type())tbb::strict_ppl::concurrent_queue< T, A > [inline]
const_iterator typedef (defined in tbb::strict_ppl::concurrent_queue< T, A >)tbb::strict_ppl::concurrent_queue< T, A >
const_reference typedeftbb::strict_ppl::concurrent_queue< T, A >
difference_type typedeftbb::strict_ppl::concurrent_queue< T, A >
empty() const tbb::strict_ppl::concurrent_queue< T, A > [inline]
get_allocator() const tbb::strict_ppl::concurrent_queue< T, A > [inline]
internal::concurrent_queue_iterator (defined in tbb::strict_ppl::concurrent_queue< T, A >)tbb::strict_ppl::concurrent_queue< T, A > [friend]
iterator typedef (defined in tbb::strict_ppl::concurrent_queue< T, A >)tbb::strict_ppl::concurrent_queue< T, A >
push(const T &source)tbb::strict_ppl::concurrent_queue< T, A > [inline]
reference typedeftbb::strict_ppl::concurrent_queue< T, A >
size_type typedeftbb::strict_ppl::concurrent_queue< T, A >
try_pop(T &result)tbb::strict_ppl::concurrent_queue< T, A > [inline]
unsafe_begin() (defined in tbb::strict_ppl::concurrent_queue< T, A >)tbb::strict_ppl::concurrent_queue< T, A > [inline]
unsafe_begin() const (defined in tbb::strict_ppl::concurrent_queue< T, A >)tbb::strict_ppl::concurrent_queue< T, A > [inline]
unsafe_end() (defined in tbb::strict_ppl::concurrent_queue< T, A >)tbb::strict_ppl::concurrent_queue< T, A > [inline]
unsafe_end() const (defined in tbb::strict_ppl::concurrent_queue< T, A >)tbb::strict_ppl::concurrent_queue< T, A > [inline]
unsafe_size() const tbb::strict_ppl::concurrent_queue< T, A > [inline]
value_type typedeftbb::strict_ppl::concurrent_queue< T, A >
~concurrent_queue()tbb::strict_ppl::concurrent_queue< T, A >


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00036.html b/src/tbb/doc/html/a00036.html new file mode 100644 index 0000000..3df8f83 --- /dev/null +++ b/src/tbb/doc/html/a00036.html @@ -0,0 +1,60 @@ + + +Member List + + + + + + +

tbb::concurrent_bounded_queue< T, A > Member List

This is the complete list of members for tbb::concurrent_bounded_queue< T, A >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
abort()tbb::concurrent_bounded_queue< T, A > [inline]
allocator_type typedeftbb::concurrent_bounded_queue< T, A >
capacity() const tbb::concurrent_bounded_queue< T, A > [inline]
clear()tbb::concurrent_bounded_queue< T, A >
concurrent_bounded_queue(const allocator_type &a=allocator_type())tbb::concurrent_bounded_queue< T, A > [inline, explicit]
concurrent_bounded_queue(const concurrent_bounded_queue &src, const allocator_type &a=allocator_type())tbb::concurrent_bounded_queue< T, A > [inline]
concurrent_bounded_queue(InputIterator begin, InputIterator end, const allocator_type &a=allocator_type())tbb::concurrent_bounded_queue< T, A > [inline]
const_iterator typedef (defined in tbb::concurrent_bounded_queue< T, A >)tbb::concurrent_bounded_queue< T, A >
const_reference typedeftbb::concurrent_bounded_queue< T, A >
difference_type typedeftbb::concurrent_bounded_queue< T, A >
empty() const tbb::concurrent_bounded_queue< T, A > [inline]
get_allocator() const tbb::concurrent_bounded_queue< T, A > [inline]
internal::concurrent_queue_iterator (defined in tbb::concurrent_bounded_queue< T, A >)tbb::concurrent_bounded_queue< T, A > [friend]
iterator typedef (defined in tbb::concurrent_bounded_queue< T, A >)tbb::concurrent_bounded_queue< T, A >
pop(T &destination)tbb::concurrent_bounded_queue< T, A > [inline]
push(const T &source)tbb::concurrent_bounded_queue< T, A > [inline]
reference typedeftbb::concurrent_bounded_queue< T, A >
set_capacity(size_type new_capacity)tbb::concurrent_bounded_queue< T, A > [inline]
size() const tbb::concurrent_bounded_queue< T, A > [inline]
size_type typedeftbb::concurrent_bounded_queue< T, A >
try_pop(T &destination)tbb::concurrent_bounded_queue< T, A > [inline]
try_push(const T &source)tbb::concurrent_bounded_queue< T, A > [inline]
unsafe_begin() (defined in tbb::concurrent_bounded_queue< T, A >)tbb::concurrent_bounded_queue< T, A > [inline]
unsafe_begin() const (defined in tbb::concurrent_bounded_queue< T, A >)tbb::concurrent_bounded_queue< T, A > [inline]
unsafe_end() (defined in tbb::concurrent_bounded_queue< T, A >)tbb::concurrent_bounded_queue< T, A > [inline]
unsafe_end() const (defined in tbb::concurrent_bounded_queue< T, A >)tbb::concurrent_bounded_queue< T, A > [inline]
value_type typedeftbb::concurrent_bounded_queue< T, A >
~concurrent_bounded_queue()tbb::concurrent_bounded_queue< T, A >


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00038.html b/src/tbb/doc/html/a00038.html new file mode 100644 index 0000000..1664dba --- /dev/null +++ b/src/tbb/doc/html/a00038.html @@ -0,0 +1,69 @@ + + +Member List + + + + + + +

tbb::deprecated::concurrent_queue< T, A > Member List

This is the complete list of members for tbb::deprecated::concurrent_queue< T, A >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
abort()tbb::concurrent_bounded_queue< T, A > [inline]
allocator_type typedeftbb::concurrent_bounded_queue< T, A >
begin() (defined in tbb::deprecated::concurrent_queue< T, A >)tbb::deprecated::concurrent_queue< T, A > [inline]
begin() const (defined in tbb::deprecated::concurrent_queue< T, A >)tbb::deprecated::concurrent_queue< T, A > [inline]
capacity() const tbb::concurrent_bounded_queue< T, A > [inline]
clear()tbb::concurrent_bounded_queue< T, A >
concurrent_bounded_queue(const allocator_type &a=allocator_type())tbb::concurrent_bounded_queue< T, A > [inline, explicit]
concurrent_bounded_queue(const concurrent_bounded_queue &src, const allocator_type &a=allocator_type())tbb::concurrent_bounded_queue< T, A > [inline]
concurrent_bounded_queue(InputIterator begin, InputIterator end, const allocator_type &a=allocator_type())tbb::concurrent_bounded_queue< T, A > [inline]
concurrent_queue(const A &a=A())tbb::deprecated::concurrent_queue< T, A > [inline, explicit]
concurrent_queue(const concurrent_queue &src, const A &a=A())tbb::deprecated::concurrent_queue< T, A > [inline]
concurrent_queue(InputIterator b, InputIterator e, const A &a=A())tbb::deprecated::concurrent_queue< T, A > [inline]
const_iterator typedef (defined in tbb::deprecated::concurrent_queue< T, A >)tbb::deprecated::concurrent_queue< T, A >
const_reference typedeftbb::concurrent_bounded_queue< T, A >
difference_type typedeftbb::concurrent_bounded_queue< T, A >
empty() const tbb::concurrent_bounded_queue< T, A > [inline]
end() (defined in tbb::deprecated::concurrent_queue< T, A >)tbb::deprecated::concurrent_queue< T, A > [inline]
end() const (defined in tbb::deprecated::concurrent_queue< T, A >)tbb::deprecated::concurrent_queue< T, A > [inline]
get_allocator() const tbb::concurrent_bounded_queue< T, A > [inline]
internal::concurrent_queue_iterator (defined in tbb::deprecated::concurrent_queue< T, A >)tbb::deprecated::concurrent_queue< T, A > [friend]
iterator typedef (defined in tbb::deprecated::concurrent_queue< T, A >)tbb::deprecated::concurrent_queue< T, A >
pop(T &destination)tbb::concurrent_bounded_queue< T, A > [inline]
pop_if_present(T &destination)tbb::deprecated::concurrent_queue< T, A > [inline]
push(const T &source)tbb::concurrent_bounded_queue< T, A > [inline]
push_if_not_full(const T &source)tbb::deprecated::concurrent_queue< T, A > [inline]
reference typedeftbb::concurrent_bounded_queue< T, A >
set_capacity(size_type new_capacity)tbb::concurrent_bounded_queue< T, A > [inline]
size() const tbb::concurrent_bounded_queue< T, A > [inline]
size_type typedeftbb::concurrent_bounded_queue< T, A >
try_pop(T &destination)tbb::concurrent_bounded_queue< T, A > [inline]
try_push(const T &source)tbb::concurrent_bounded_queue< T, A > [inline]
unsafe_begin() (defined in tbb::concurrent_bounded_queue< T, A >)tbb::concurrent_bounded_queue< T, A > [inline]
unsafe_begin() const (defined in tbb::concurrent_bounded_queue< T, A >)tbb::concurrent_bounded_queue< T, A > [inline]
unsafe_end() (defined in tbb::concurrent_bounded_queue< T, A >)tbb::concurrent_bounded_queue< T, A > [inline]
unsafe_end() const (defined in tbb::concurrent_bounded_queue< T, A >)tbb::concurrent_bounded_queue< T, A > [inline]
value_type typedeftbb::concurrent_bounded_queue< T, A >
~concurrent_bounded_queue()tbb::concurrent_bounded_queue< T, A >


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00044.html b/src/tbb/doc/html/a00044.html new file mode 100644 index 0000000..b5a85c5 --- /dev/null +++ b/src/tbb/doc/html/a00044.html @@ -0,0 +1,102 @@ + + +Member List + + + + + + +

tbb::concurrent_vector< T, A > Member List

This is the complete list of members for tbb::concurrent_vector< T, A >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
allocator_type typedef (defined in tbb::concurrent_vector< T, A >)tbb::concurrent_vector< T, A >
assign(size_type n, const_reference t)tbb::concurrent_vector< T, A > [inline]
assign(I first, I last)tbb::concurrent_vector< T, A > [inline]
at(size_type index)tbb::concurrent_vector< T, A > [inline]
at(size_type index) const tbb::concurrent_vector< T, A > [inline]
back()tbb::concurrent_vector< T, A > [inline]
back() const tbb::concurrent_vector< T, A > [inline]
begin()tbb::concurrent_vector< T, A > [inline]
begin() const tbb::concurrent_vector< T, A > [inline]
capacity() const tbb::concurrent_vector< T, A > [inline]
cbegin() const tbb::concurrent_vector< T, A > [inline]
cend() const tbb::concurrent_vector< T, A > [inline]
clear()tbb::concurrent_vector< T, A > [inline]
compact()tbb::concurrent_vector< T, A > [inline]
concurrent_vector(const allocator_type &a=allocator_type())tbb::concurrent_vector< T, A > [inline, explicit]
concurrent_vector(const concurrent_vector &vector, const allocator_type &a=allocator_type())tbb::concurrent_vector< T, A > [inline]
concurrent_vector(const concurrent_vector< T, M > &vector, const allocator_type &a=allocator_type())tbb::concurrent_vector< T, A > [inline]
concurrent_vector(size_type n)tbb::concurrent_vector< T, A > [inline, explicit]
concurrent_vector(size_type n, const_reference t, const allocator_type &a=allocator_type())tbb::concurrent_vector< T, A > [inline]
concurrent_vector(I first, I last, const allocator_type &a=allocator_type())tbb::concurrent_vector< T, A > [inline]
const_iterator typedef (defined in tbb::concurrent_vector< T, A >)tbb::concurrent_vector< T, A >
const_pointer typedef (defined in tbb::concurrent_vector< T, A >)tbb::concurrent_vector< T, A >
const_range_type typedef (defined in tbb::concurrent_vector< T, A >)tbb::concurrent_vector< T, A >
const_reference typedef (defined in tbb::concurrent_vector< T, A >)tbb::concurrent_vector< T, A >
const_reverse_iterator typedef (defined in tbb::concurrent_vector< T, A >)tbb::concurrent_vector< T, A >
const_reverse_iterator typedef (defined in tbb::concurrent_vector< T, A >)tbb::concurrent_vector< T, A >
crbegin() const tbb::concurrent_vector< T, A > [inline]
crend() const tbb::concurrent_vector< T, A > [inline]
difference_type typedef (defined in tbb::concurrent_vector< T, A >)tbb::concurrent_vector< T, A >
empty() const tbb::concurrent_vector< T, A > [inline]
end()tbb::concurrent_vector< T, A > [inline]
end() const tbb::concurrent_vector< T, A > [inline]
front()tbb::concurrent_vector< T, A > [inline]
front() const tbb::concurrent_vector< T, A > [inline]
get_allocator() const tbb::concurrent_vector< T, A > [inline]
grow_by(size_type delta)tbb::concurrent_vector< T, A > [inline]
grow_by(size_type delta)tbb::concurrent_vector< T, A > [inline]
grow_by(size_type delta, const_reference t)tbb::concurrent_vector< T, A > [inline]
grow_by(size_type delta, const_reference t)tbb::concurrent_vector< T, A > [inline]
grow_to_at_least(size_type n)tbb::concurrent_vector< T, A > [inline]
grow_to_at_least(size_type n)tbb::concurrent_vector< T, A > [inline]
internal::vector_iterator (defined in tbb::concurrent_vector< T, A >)tbb::concurrent_vector< T, A > [friend]
internal_vector_base() const (defined in tbb::concurrent_vector< T, A >)tbb::concurrent_vector< T, A > [inline]
iterator typedef (defined in tbb::concurrent_vector< T, A >)tbb::concurrent_vector< T, A >
max_size() const tbb::concurrent_vector< T, A > [inline]
operator=(const concurrent_vector &vector)tbb::concurrent_vector< T, A > [inline]
operator=(const concurrent_vector< T, M > &vector)tbb::concurrent_vector< T, A > [inline]
operator[](size_type index)tbb::concurrent_vector< T, A > [inline]
operator[](size_type index) const tbb::concurrent_vector< T, A > [inline]
pointer typedef (defined in tbb::concurrent_vector< T, A >)tbb::concurrent_vector< T, A >
push_back(const_reference item) iterator push_back(const _reference item)tbb::concurrent_vector< T, A > [inline]
range(size_t grainsize=1)tbb::concurrent_vector< T, A > [inline]
range(size_t grainsize=1) const tbb::concurrent_vector< T, A > [inline]
range_type typedef (defined in tbb::concurrent_vector< T, A >)tbb::concurrent_vector< T, A >
rbegin()tbb::concurrent_vector< T, A > [inline]
rbegin() const tbb::concurrent_vector< T, A > [inline]
reference typedef (defined in tbb::concurrent_vector< T, A >)tbb::concurrent_vector< T, A >
rend()tbb::concurrent_vector< T, A > [inline]
rend() const tbb::concurrent_vector< T, A > [inline]
reserve(size_type n)tbb::concurrent_vector< T, A > [inline]
resize(size_type n)tbb::concurrent_vector< T, A > [inline]
resize(size_type n, const_reference t)tbb::concurrent_vector< T, A > [inline]
reverse_iterator typedef (defined in tbb::concurrent_vector< T, A >)tbb::concurrent_vector< T, A >
reverse_iterator typedef (defined in tbb::concurrent_vector< T, A >)tbb::concurrent_vector< T, A >
shrink_to_fit()tbb::concurrent_vector< T, A >
size() const tbb::concurrent_vector< T, A > [inline]
size_type typedef (defined in tbb::concurrent_vector< T, A >)tbb::concurrent_vector< T, A >
swap(concurrent_vector &vector)tbb::concurrent_vector< T, A > [inline]
value_type typedef (defined in tbb::concurrent_vector< T, A >)tbb::concurrent_vector< T, A >
~concurrent_vector()tbb::concurrent_vector< T, A > [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00049.html b/src/tbb/doc/html/a00049.html new file mode 100644 index 0000000..0ca50e2 --- /dev/null +++ b/src/tbb/doc/html/a00049.html @@ -0,0 +1,66 @@ + + +Member List + + + + + + +

tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > Member List

This is the complete list of members for tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
allocator_type typedeftbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >
begin()tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [inline]
begin() const tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [inline]
clear()tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [inline]
combine(combine_func_t f_combine) (defined in tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [inline]
combine_each(combine_func_t f_combine) (defined in tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [inline]
const_iterator typedef (defined in tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >
const_pointer typedef (defined in tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >
const_range_type typedef (defined in tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >
const_reference typedef (defined in tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >
difference_type typedef (defined in tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >
empty() const tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [inline]
end()tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [inline]
end() const tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [inline]
enumerable_thread_specific (defined in tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [friend]
enumerable_thread_specific()tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [inline]
enumerable_thread_specific(Finit finit)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [inline]
enumerable_thread_specific(const T &exemplar)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [inline]
enumerable_thread_specific(const enumerable_thread_specific< U, Alloc, Cachetype > &other) (defined in tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [inline]
enumerable_thread_specific(const enumerable_thread_specific &other) (defined in tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [inline]
iterator typedef (defined in tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >
local()tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [inline]
local(bool &exists)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [inline]
operator=(const enumerable_thread_specific &other) (defined in tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [inline]
operator=(const enumerable_thread_specific< U, Alloc, Cachetype > &other) (defined in tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [inline]
pointer typedef (defined in tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >
range(size_t grainsize=1)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [inline]
range(size_t grainsize=1) const tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [inline]
range_type typedef (defined in tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >
reference typedef (defined in tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >
size() const tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [inline]
size_type typedef (defined in tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >
value_type typedef (defined in tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >)tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >
~enumerable_thread_specific()tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00053.html b/src/tbb/doc/html/a00053.html new file mode 100644 index 0000000..09bc581 --- /dev/null +++ b/src/tbb/doc/html/a00053.html @@ -0,0 +1,41 @@ + + +Member List + + + + + + +

tbb::flow::interface6::sender< T > Member List

This is the complete list of members for tbb::flow::interface6::sender< T >, including all inherited members.

+ + + + + + + + + +
output_type typedeftbb::flow::interface6::sender< T >
register_successor(successor_type &r)=0tbb::flow::interface6::sender< T > [pure virtual]
remove_successor(successor_type &r)=0tbb::flow::interface6::sender< T > [pure virtual]
successor_type typedeftbb::flow::interface6::sender< T >
try_consume()tbb::flow::interface6::sender< T > [inline, virtual]
try_get(T &)tbb::flow::interface6::sender< T > [inline, virtual]
try_release()tbb::flow::interface6::sender< T > [inline, virtual]
try_reserve(T &)tbb::flow::interface6::sender< T > [inline, virtual]
~sender() (defined in tbb::flow::interface6::sender< T >)tbb::flow::interface6::sender< T > [inline, virtual]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00054.html b/src/tbb/doc/html/a00054.html new file mode 100644 index 0000000..bf62763 --- /dev/null +++ b/src/tbb/doc/html/a00054.html @@ -0,0 +1,38 @@ + + +Member List + + + + + + +

tbb::flow::interface6::receiver< T > Member List

This is the complete list of members for tbb::flow::interface6::receiver< T >, including all inherited members.

+ + + + + + +
input_type typedeftbb::flow::interface6::receiver< T >
predecessor_type typedeftbb::flow::interface6::receiver< T >
register_predecessor(predecessor_type &)tbb::flow::interface6::receiver< T > [inline, virtual]
remove_predecessor(predecessor_type &)tbb::flow::interface6::receiver< T > [inline, virtual]
try_put(const T &t)=0tbb::flow::interface6::receiver< T > [pure virtual]
~receiver()tbb::flow::interface6::receiver< T > [inline, virtual]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00055.html b/src/tbb/doc/html/a00055.html new file mode 100644 index 0000000..038a1d1 --- /dev/null +++ b/src/tbb/doc/html/a00055.html @@ -0,0 +1,49 @@ + + +Member List + + + + + + +

tbb::flow::interface6::continue_receiver Member List

This is the complete list of members for tbb::flow::interface6::continue_receiver, including all inherited members.

+ + + + + + + + + + + + + + + + + +
continue_receiver(int number_of_predecessors=0)tbb::flow::interface6::continue_receiver [inline]
continue_receiver(const continue_receiver &src)tbb::flow::interface6::continue_receiver [inline]
execute()=0tbb::flow::interface6::continue_receiver [protected, pure virtual]
input_type typedeftbb::flow::interface6::continue_receiver
my_current_count (defined in tbb::flow::interface6::continue_receiver)tbb::flow::interface6::continue_receiver [protected]
my_initial_predecessor_count (defined in tbb::flow::interface6::continue_receiver)tbb::flow::interface6::continue_receiver [protected]
my_mutex (defined in tbb::flow::interface6::continue_receiver)tbb::flow::interface6::continue_receiver [protected]
my_predecessor_count (defined in tbb::flow::interface6::continue_receiver)tbb::flow::interface6::continue_receiver [protected]
predecessor_type typedeftbb::flow::interface6::continue_receiver
register_predecessor(predecessor_type &)tbb::flow::interface6::continue_receiver [inline]
tbb::flow::interface6::receiver::register_predecessor(predecessor_type &)tbb::flow::interface6::receiver< T > [inline, virtual]
remove_predecessor(predecessor_type &)tbb::flow::interface6::continue_receiver [inline]
tbb::flow::interface6::receiver::remove_predecessor(predecessor_type &)tbb::flow::interface6::receiver< T > [inline, virtual]
try_put(const input_type &)tbb::flow::interface6::continue_receiver [inline]
tbb::flow::interface6::receiver::try_put(const T &t)=0tbb::flow::interface6::receiver< T > [pure virtual]
~continue_receiver()tbb::flow::interface6::continue_receiver [inline, virtual]
~receiver()tbb::flow::interface6::receiver< T > [inline, virtual]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00057.html b/src/tbb/doc/html/a00057.html new file mode 100644 index 0000000..477218c --- /dev/null +++ b/src/tbb/doc/html/a00057.html @@ -0,0 +1,53 @@ + + +Member List + + + + + + +

tbb::flow::interface6::graph Member List

This is the complete list of members for tbb::flow::interface6::graph, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + +
begin()tbb::flow::interface6::graph [inline]
begin() const tbb::flow::interface6::graph [inline]
cbegin() const tbb::flow::interface6::graph [inline]
cend() const tbb::flow::interface6::graph [inline]
const_iterator typedef (defined in tbb::flow::interface6::graph)tbb::flow::interface6::graph
decrement_wait_count()tbb::flow::interface6::graph [inline]
end()tbb::flow::interface6::graph [inline]
end() const tbb::flow::interface6::graph [inline]
exception_thrown() (defined in tbb::flow::interface6::graph)tbb::flow::interface6::graph [inline]
graph()tbb::flow::interface6::graph [inline, explicit]
graph(task_group_context &use_this_context)tbb::flow::interface6::graph [inline, explicit]
graph_iterator (defined in tbb::flow::interface6::graph)tbb::flow::interface6::graph [friend]
graph_node (defined in tbb::flow::interface6::graph)tbb::flow::interface6::graph [friend]
increment_wait_count()tbb::flow::interface6::graph [inline]
is_cancelled()tbb::flow::interface6::graph [inline]
iterator typedef (defined in tbb::flow::interface6::graph)tbb::flow::interface6::graph
root_task()tbb::flow::interface6::graph [inline]
run(Receiver &r, Body body)tbb::flow::interface6::graph [inline]
run(Body body)tbb::flow::interface6::graph [inline]
wait_for_all()tbb::flow::interface6::graph [inline]
~graph()tbb::flow::interface6::graph [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00060.html b/src/tbb/doc/html/a00060.html new file mode 100644 index 0000000..c21afe8 --- /dev/null +++ b/src/tbb/doc/html/a00060.html @@ -0,0 +1,39 @@ + + +Member List + + + + + + +

tbb::flow::interface6::graph_node Member List

This is the complete list of members for tbb::flow::interface6::graph_node, including all inherited members.

+ + + + + + + +
graph (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [friend]
graph_iterator (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [friend]
graph_node(graph &g) (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline]
my_graph (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
next (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
prev (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
~graph_node() (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline, virtual]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00061.html b/src/tbb/doc/html/a00061.html new file mode 100644 index 0000000..8f133ba --- /dev/null +++ b/src/tbb/doc/html/a00061.html @@ -0,0 +1,51 @@ + + +Member List + + + + + + +

tbb::flow::interface6::source_node< Output > Member List

This is the complete list of members for tbb::flow::interface6::source_node< Output >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + +
activate()tbb::flow::interface6::source_node< Output > [inline]
graph_node(graph &g) (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline]
internal::source_task< source_node< output_type > > (defined in tbb::flow::interface6::source_node< Output >)tbb::flow::interface6::source_node< Output > [friend]
my_graph (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
next (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
output_type typedeftbb::flow::interface6::source_node< Output >
prev (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
register_successor(receiver< output_type > &r)tbb::flow::interface6::source_node< Output > [inline, virtual]
remove_successor(receiver< output_type > &r)tbb::flow::interface6::source_node< Output > [inline, virtual]
source_node(graph &g, Body body, bool is_active=true)tbb::flow::interface6::source_node< Output > [inline]
source_node(const source_node &src)tbb::flow::interface6::source_node< Output > [inline]
successor_type typedeftbb::flow::interface6::source_node< Output >
try_consume()tbb::flow::interface6::source_node< Output > [inline, virtual]
try_get(output_type &v)tbb::flow::interface6::source_node< Output > [inline, virtual]
try_release()tbb::flow::interface6::source_node< Output > [inline, virtual]
try_reserve(output_type &v)tbb::flow::interface6::source_node< Output > [inline, virtual]
~graph_node() (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline, virtual]
~sender() (defined in tbb::flow::interface6::sender< Output >)tbb::flow::interface6::sender< Output > [inline, virtual]
~source_node()tbb::flow::interface6::source_node< Output > [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00062.html b/src/tbb/doc/html/a00062.html new file mode 100644 index 0000000..f872024 --- /dev/null +++ b/src/tbb/doc/html/a00062.html @@ -0,0 +1,47 @@ + + +Member List + + + + + + +

tbb::flow::interface6::function_node< Input, Output,, Allocator > Member List

This is the complete list of members for tbb::flow::interface6::function_node< Input, Output,, Allocator >, including all inherited members.

+ + + + + + + + + + + + + + + +
fInput_type typedef (defined in tbb::flow::interface6::function_node< Input, Output,, Allocator >)tbb::flow::interface6::function_node< Input, Output,, Allocator >
fOutput_type typedef (defined in tbb::flow::interface6::function_node< Input, Output,, Allocator >)tbb::flow::interface6::function_node< Input, Output,, Allocator >
function_node(graph &g, size_t concurrency, Body body)tbb::flow::interface6::function_node< Input, Output,, Allocator > [inline]
function_node(const function_node &src)tbb::flow::interface6::function_node< Input, Output,, Allocator > [inline]
graph_node(graph &g) (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline]
input_type typedef (defined in tbb::flow::interface6::function_node< Input, Output,, Allocator >)tbb::flow::interface6::function_node< Input, Output,, Allocator >
my_graph (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
next (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
output_type typedef (defined in tbb::flow::interface6::function_node< Input, Output,, Allocator >)tbb::flow::interface6::function_node< Input, Output,, Allocator >
predecessor_type typedef (defined in tbb::flow::interface6::function_node< Input, Output,, Allocator >)tbb::flow::interface6::function_node< Input, Output,, Allocator >
prev (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
successor_type typedef (defined in tbb::flow::interface6::function_node< Input, Output,, Allocator >)tbb::flow::interface6::function_node< Input, Output,, Allocator >
successors() (defined in tbb::flow::interface6::function_node< Input, Output,, Allocator >)tbb::flow::interface6::function_node< Input, Output,, Allocator > [inline, protected]
try_put(const input_type &i) (defined in tbb::flow::interface6::function_node< Input, Output,, Allocator >)tbb::flow::interface6::function_node< Input, Output,, Allocator > [inline]
~graph_node() (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline, virtual]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00063.html b/src/tbb/doc/html/a00063.html new file mode 100644 index 0000000..6454e71 --- /dev/null +++ b/src/tbb/doc/html/a00063.html @@ -0,0 +1,48 @@ + + +Member List + + + + + + +

tbb::flow::interface6::function_node< Input, Output, queueing, Allocator > Member List

This is the complete list of members for tbb::flow::interface6::function_node< Input, Output, queueing, Allocator >, including all inherited members.

+ + + + + + + + + + + + + + + + +
fInput_type typedef (defined in tbb::flow::interface6::function_node< Input, Output, queueing, Allocator >)tbb::flow::interface6::function_node< Input, Output, queueing, Allocator >
fOutput_type typedef (defined in tbb::flow::interface6::function_node< Input, Output, queueing, Allocator >)tbb::flow::interface6::function_node< Input, Output, queueing, Allocator >
function_node(graph &g, size_t concurrency, Body body)tbb::flow::interface6::function_node< Input, Output, queueing, Allocator > [inline]
function_node(const function_node &src)tbb::flow::interface6::function_node< Input, Output, queueing, Allocator > [inline]
graph_node(graph &g) (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline]
input_type typedef (defined in tbb::flow::interface6::function_node< Input, Output, queueing, Allocator >)tbb::flow::interface6::function_node< Input, Output, queueing, Allocator >
my_graph (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
next (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
output_type typedef (defined in tbb::flow::interface6::function_node< Input, Output, queueing, Allocator >)tbb::flow::interface6::function_node< Input, Output, queueing, Allocator >
predecessor_type typedef (defined in tbb::flow::interface6::function_node< Input, Output, queueing, Allocator >)tbb::flow::interface6::function_node< Input, Output, queueing, Allocator >
prev (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
queue_type typedef (defined in tbb::flow::interface6::function_node< Input, Output, queueing, Allocator >)tbb::flow::interface6::function_node< Input, Output, queueing, Allocator >
successor_type typedef (defined in tbb::flow::interface6::function_node< Input, Output, queueing, Allocator >)tbb::flow::interface6::function_node< Input, Output, queueing, Allocator >
successors() (defined in tbb::flow::interface6::function_node< Input, Output, queueing, Allocator >)tbb::flow::interface6::function_node< Input, Output, queueing, Allocator > [inline, protected]
try_put(const input_type &i) (defined in tbb::flow::interface6::function_node< Input, Output, queueing, Allocator >)tbb::flow::interface6::function_node< Input, Output, queueing, Allocator > [inline]
~graph_node() (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline, virtual]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00064.html b/src/tbb/doc/html/a00064.html new file mode 100644 index 0000000..8e76336 --- /dev/null +++ b/src/tbb/doc/html/a00064.html @@ -0,0 +1,41 @@ + + +Member List + + + + + + +

tbb::flow::interface6::multifunction_node< Input, Output,, Allocator > Member List

This is the complete list of members for tbb::flow::interface6::multifunction_node< Input, Output,, Allocator >, including all inherited members.

+ + + + + + + + + +
graph_node(graph &g) (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline]
input_type typedef (defined in tbb::flow::interface6::multifunction_node< Input, Output,, Allocator >)tbb::flow::interface6::multifunction_node< Input, Output,, Allocator >
multifunction_node(graph &g, size_t concurrency, Body body) (defined in tbb::flow::interface6::multifunction_node< Input, Output,, Allocator >)tbb::flow::interface6::multifunction_node< Input, Output,, Allocator > [inline]
multifunction_node(const multifunction_node &other) (defined in tbb::flow::interface6::multifunction_node< Input, Output,, Allocator >)tbb::flow::interface6::multifunction_node< Input, Output,, Allocator > [inline]
my_graph (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
next (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
output_ports_type typedef (defined in tbb::flow::interface6::multifunction_node< Input, Output,, Allocator >)tbb::flow::interface6::multifunction_node< Input, Output,, Allocator >
prev (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
~graph_node() (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline, virtual]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00066.html b/src/tbb/doc/html/a00066.html new file mode 100644 index 0000000..ff77f55 --- /dev/null +++ b/src/tbb/doc/html/a00066.html @@ -0,0 +1,44 @@ + + +Member List + + + + + + +

tbb::flow::interface6::split_node< TupleType, Allocator > Member List

This is the complete list of members for tbb::flow::interface6::split_node< TupleType, Allocator >, including all inherited members.

+ + + + + + + + + + + + +
allocator_type typedef (defined in tbb::flow::interface6::split_node< TupleType, Allocator >)tbb::flow::interface6::split_node< TupleType, Allocator >
graph_node(graph &g) (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline]
input_type typedef (defined in tbb::flow::interface6::split_node< TupleType, Allocator >)tbb::flow::interface6::split_node< TupleType, Allocator >
multifunction_node(graph &g, size_t concurrency, Body body) (defined in tbb::flow::interface6::multifunction_node< TupleType, TupleType, rejecting, Allocator >)tbb::flow::interface6::multifunction_node< TupleType, TupleType, rejecting, Allocator > [inline]
multifunction_node(const multifunction_node &other) (defined in tbb::flow::interface6::multifunction_node< TupleType, TupleType, rejecting, Allocator >)tbb::flow::interface6::multifunction_node< TupleType, TupleType, rejecting, Allocator > [inline]
my_graph (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
next (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
output_ports_type typedef (defined in tbb::flow::interface6::split_node< TupleType, Allocator >)tbb::flow::interface6::split_node< TupleType, Allocator >
prev (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
split_node(graph &g) (defined in tbb::flow::interface6::split_node< TupleType, Allocator >)tbb::flow::interface6::split_node< TupleType, Allocator > [inline]
split_node(const split_node &other) (defined in tbb::flow::interface6::split_node< TupleType, Allocator >)tbb::flow::interface6::split_node< TupleType, Allocator > [inline]
~graph_node() (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline, virtual]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00068.html b/src/tbb/doc/html/a00068.html new file mode 100644 index 0000000..bc68351 --- /dev/null +++ b/src/tbb/doc/html/a00068.html @@ -0,0 +1,47 @@ + + +Member List + + + + + + +

tbb::flow::interface6::continue_node< Output > Member List

This is the complete list of members for tbb::flow::interface6::continue_node< Output >, including all inherited members.

+ + + + + + + + + + + + + + + +
continue_node(graph &g, Body body)tbb::flow::interface6::continue_node< Output > [inline]
continue_node(graph &g, int number_of_predecessors, Body body)tbb::flow::interface6::continue_node< Output > [inline]
continue_node(const continue_node &src)tbb::flow::interface6::continue_node< Output > [inline]
fOutput_type typedef (defined in tbb::flow::interface6::continue_node< Output >)tbb::flow::interface6::continue_node< Output >
graph_node(graph &g) (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline]
input_type typedef (defined in tbb::flow::interface6::continue_node< Output >)tbb::flow::interface6::continue_node< Output >
my_graph (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
next (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
output_type typedef (defined in tbb::flow::interface6::continue_node< Output >)tbb::flow::interface6::continue_node< Output >
predecessor_type typedef (defined in tbb::flow::interface6::continue_node< Output >)tbb::flow::interface6::continue_node< Output >
prev (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
successor_type typedef (defined in tbb::flow::interface6::continue_node< Output >)tbb::flow::interface6::continue_node< Output >
successors() (defined in tbb::flow::interface6::continue_node< Output >)tbb::flow::interface6::continue_node< Output > [inline, protected]
try_put(const input_type &i) (defined in tbb::flow::interface6::continue_node< Output >)tbb::flow::interface6::continue_node< Output > [inline]
~graph_node() (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline, virtual]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00071.html b/src/tbb/doc/html/a00071.html new file mode 100644 index 0000000..4a960d6 --- /dev/null +++ b/src/tbb/doc/html/a00071.html @@ -0,0 +1,54 @@ + + +Member List + + + + + + +

tbb::flow::interface6::broadcast_node< T > Member List

This is the complete list of members for tbb::flow::interface6::broadcast_node< T >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + +
broadcast_node(graph &g) (defined in tbb::flow::interface6::broadcast_node< T >)tbb::flow::interface6::broadcast_node< T > [inline]
broadcast_node(const broadcast_node &src) (defined in tbb::flow::interface6::broadcast_node< T >)tbb::flow::interface6::broadcast_node< T > [inline]
graph_node(graph &g) (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline]
input_type typedeftbb::flow::interface6::broadcast_node< T >
my_graph (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
next (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
output_type typedeftbb::flow::interface6::broadcast_node< T >
predecessor_type typedeftbb::flow::interface6::broadcast_node< T >
prev (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
register_predecessor(predecessor_type &)tbb::flow::interface6::receiver< T > [inline, virtual]
register_successor(receiver< T > &r)tbb::flow::interface6::broadcast_node< T > [inline, virtual]
remove_predecessor(predecessor_type &)tbb::flow::interface6::receiver< T > [inline, virtual]
remove_successor(receiver< T > &r)tbb::flow::interface6::broadcast_node< T > [inline, virtual]
successor_type typedeftbb::flow::interface6::broadcast_node< T >
try_consume()tbb::flow::interface6::sender< T > [inline, virtual]
try_get(T &)tbb::flow::interface6::sender< T > [inline, virtual]
try_put(const T &t)tbb::flow::interface6::broadcast_node< T > [inline, virtual]
try_release()tbb::flow::interface6::sender< T > [inline, virtual]
try_reserve(T &)tbb::flow::interface6::sender< T > [inline, virtual]
~graph_node() (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline, virtual]
~receiver()tbb::flow::interface6::receiver< T > [inline, virtual]
~sender() (defined in tbb::flow::interface6::sender< T >)tbb::flow::interface6::sender< T > [inline, virtual]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00072.html b/src/tbb/doc/html/a00072.html new file mode 100644 index 0000000..1fe10f4 --- /dev/null +++ b/src/tbb/doc/html/a00072.html @@ -0,0 +1,87 @@ + + +Member List + + + + + + +

tbb::flow::interface6::buffer_node< T, A > Member List

This is the complete list of members for tbb::flow::interface6::buffer_node< T, A >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
buffer_node(graph &g)tbb::flow::interface6::buffer_node< T, A > [inline]
buffer_node(const buffer_node &src)tbb::flow::interface6::buffer_node< T, A > [inline]
con_res enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
FAILED enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
forward()tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
forwarder_busy (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
graph_node(graph &g) (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline]
handle_operations(buffer_operation *op_list) (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
input_type typedeftbb::flow::interface6::buffer_node< T, A >
internal::aggregating_functor< my_class, buffer_operation > (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [friend]
internal::forward_task< buffer_node< T, A > > (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [friend]
internal_consume(buffer_operation *op) (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
internal_forward(buffer_operation *op)tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
internal_pop(buffer_operation *op) (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
internal_push(buffer_operation *op) (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
internal_reg_succ(buffer_operation *op)tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
internal_release(buffer_operation *op) (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
internal_rem_succ(buffer_operation *op)tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
internal_reserve(buffer_operation *op) (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
my_aggregator (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
my_class typedef (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A >
my_graph (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
my_handler typedef (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
my_parent (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
my_successors (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
next (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
op_stat enum name (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
op_type enum name (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
output_type typedeftbb::flow::interface6::buffer_node< T, A >
predecessor_type typedeftbb::flow::interface6::buffer_node< T, A >
prev (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
put_item enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
reg_succ enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
register_predecessor(predecessor_type &)tbb::flow::interface6::receiver< T > [inline, virtual]
register_successor(receiver< output_type > &r)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
rel_res enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
rem_succ enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
remove_predecessor(predecessor_type &)tbb::flow::interface6::receiver< T > [inline, virtual]
remove_successor(receiver< output_type > &r)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
req_item enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
res_item enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
size_type typedef (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
SUCCEEDED enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
successor_type typedeftbb::flow::interface6::buffer_node< T, A >
try_consume()tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
try_fwd enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
try_get(T &v)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
try_put(const T &t)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
try_release()tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
try_reserve(T &v)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
WAIT enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
~buffer_node() (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
~graph_node() (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline, virtual]
~receiver()tbb::flow::interface6::receiver< T > [inline, virtual]
~sender() (defined in tbb::flow::interface6::sender< T >)tbb::flow::interface6::sender< T > [inline, virtual]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00074.html b/src/tbb/doc/html/a00074.html new file mode 100644 index 0000000..89f85fc --- /dev/null +++ b/src/tbb/doc/html/a00074.html @@ -0,0 +1,90 @@ + + +Member List + + + + + + +

tbb::flow::interface6::queue_node< T, A > Member List

This is the complete list of members for tbb::flow::interface6::queue_node< T, A >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
buffer_node(graph &g)tbb::flow::interface6::buffer_node< T, A > [inline]
buffer_node(const buffer_node &src)tbb::flow::interface6::buffer_node< T, A > [inline]
con_res enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
FAILED enum value (defined in tbb::flow::interface6::queue_node< T, A >)tbb::flow::interface6::queue_node< T, A > [protected]
forward()tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
forwarder_busy (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
graph_node(graph &g) (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline]
handle_operations(buffer_operation *op_list) (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
input_type typedeftbb::flow::interface6::queue_node< T, A >
internal::aggregating_functor< my_class, buffer_operation > (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [friend]
internal::forward_task< buffer_node< T, A > > (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [friend]
internal_consume(queue_operation *op) (defined in tbb::flow::interface6::queue_node< T, A >)tbb::flow::interface6::queue_node< T, A > [inline, protected, virtual]
internal_forward(queue_operation *op)tbb::flow::interface6::queue_node< T, A > [inline, protected, virtual]
internal_pop(queue_operation *op) (defined in tbb::flow::interface6::queue_node< T, A >)tbb::flow::interface6::queue_node< T, A > [inline, protected, virtual]
internal_push(buffer_operation *op) (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
internal_reg_succ(buffer_operation *op)tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
internal_release(buffer_operation *op) (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
internal_rem_succ(buffer_operation *op)tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
internal_reserve(queue_operation *op) (defined in tbb::flow::interface6::queue_node< T, A >)tbb::flow::interface6::queue_node< T, A > [inline, protected, virtual]
my_aggregator (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
my_class typedef (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A >
my_graph (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
my_handler typedef (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
my_parent (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
my_successors (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
next (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
op_stat enum name (defined in tbb::flow::interface6::queue_node< T, A >)tbb::flow::interface6::queue_node< T, A > [protected]
op_type enum name (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
output_type typedeftbb::flow::interface6::queue_node< T, A >
predecessor_type typedeftbb::flow::interface6::queue_node< T, A >
prev (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
put_item enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
queue_node(graph &g)tbb::flow::interface6::queue_node< T, A > [inline]
queue_node(const queue_node &src)tbb::flow::interface6::queue_node< T, A > [inline]
queue_operation typedef (defined in tbb::flow::interface6::queue_node< T, A >)tbb::flow::interface6::queue_node< T, A > [protected]
reg_succ enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
register_predecessor(predecessor_type &)tbb::flow::interface6::receiver< T > [inline, virtual]
register_successor(receiver< output_type > &r)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
rel_res enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
rem_succ enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
remove_predecessor(predecessor_type &)tbb::flow::interface6::receiver< T > [inline, virtual]
remove_successor(receiver< output_type > &r)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
req_item enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
res_item enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
size_type typedef (defined in tbb::flow::interface6::queue_node< T, A >)tbb::flow::interface6::queue_node< T, A > [protected]
SUCCEEDED enum value (defined in tbb::flow::interface6::queue_node< T, A >)tbb::flow::interface6::queue_node< T, A > [protected]
successor_type typedeftbb::flow::interface6::queue_node< T, A >
try_consume()tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
try_fwd enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
try_get(T &v)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
try_put(const T &t)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
try_release()tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
try_reserve(T &v)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
WAIT enum value (defined in tbb::flow::interface6::queue_node< T, A >)tbb::flow::interface6::queue_node< T, A > [protected]
~buffer_node() (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
~graph_node() (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline, virtual]
~receiver()tbb::flow::interface6::receiver< T > [inline, virtual]
~sender() (defined in tbb::flow::interface6::sender< T >)tbb::flow::interface6::sender< T > [inline, virtual]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00075.html b/src/tbb/doc/html/a00075.html new file mode 100644 index 0000000..6bf48b6 --- /dev/null +++ b/src/tbb/doc/html/a00075.html @@ -0,0 +1,93 @@ + + +Member List + + + + + + +

tbb::flow::interface6::sequencer_node< T, A > Member List

This is the complete list of members for tbb::flow::interface6::sequencer_node< T, A >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
buffer_node(graph &g)tbb::flow::interface6::buffer_node< T, A > [inline]
buffer_node(const buffer_node &src)tbb::flow::interface6::buffer_node< T, A > [inline]
con_res enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
FAILED enum value (defined in tbb::flow::interface6::sequencer_node< T, A >)tbb::flow::interface6::sequencer_node< T, A > [protected]
forward()tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
forwarder_busy (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
graph_node(graph &g) (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline]
handle_operations(buffer_operation *op_list) (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
input_type typedeftbb::flow::interface6::sequencer_node< T, A >
internal::aggregating_functor< my_class, buffer_operation > (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [friend]
internal::forward_task< buffer_node< T, A > > (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [friend]
internal_consume(queue_operation *op) (defined in tbb::flow::interface6::queue_node< T, A >)tbb::flow::interface6::queue_node< T, A > [inline, protected, virtual]
internal_forward(queue_operation *op)tbb::flow::interface6::queue_node< T, A > [inline, protected, virtual]
internal_pop(queue_operation *op) (defined in tbb::flow::interface6::queue_node< T, A >)tbb::flow::interface6::queue_node< T, A > [inline, protected, virtual]
internal_reg_succ(buffer_operation *op)tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
internal_release(buffer_operation *op) (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
internal_rem_succ(buffer_operation *op)tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
internal_reserve(queue_operation *op) (defined in tbb::flow::interface6::queue_node< T, A >)tbb::flow::interface6::queue_node< T, A > [inline, protected, virtual]
my_aggregator (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
my_class typedef (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A >
my_graph (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
my_handler typedef (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
my_parent (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
my_successors (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
next (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
op_stat enum name (defined in tbb::flow::interface6::sequencer_node< T, A >)tbb::flow::interface6::sequencer_node< T, A > [protected]
op_type enum name (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
output_type typedeftbb::flow::interface6::sequencer_node< T, A >
predecessor_type typedeftbb::flow::interface6::sequencer_node< T, A >
prev (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
put_item enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
queue_node(graph &g)tbb::flow::interface6::queue_node< T, A > [inline]
queue_node(const queue_node &src)tbb::flow::interface6::queue_node< T, A > [inline]
queue_operation typedef (defined in tbb::flow::interface6::queue_node< T, A >)tbb::flow::interface6::queue_node< T, A > [protected]
reg_succ enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
register_predecessor(predecessor_type &)tbb::flow::interface6::receiver< T > [inline, virtual]
register_successor(receiver< output_type > &r)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
rel_res enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
rem_succ enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
remove_predecessor(predecessor_type &)tbb::flow::interface6::receiver< T > [inline, virtual]
remove_successor(receiver< output_type > &r)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
req_item enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
res_item enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
sequencer_node(graph &g, const Sequencer &s)tbb::flow::interface6::sequencer_node< T, A > [inline]
sequencer_node(const sequencer_node &src)tbb::flow::interface6::sequencer_node< T, A > [inline]
sequencer_operation typedef (defined in tbb::flow::interface6::sequencer_node< T, A >)tbb::flow::interface6::sequencer_node< T, A > [protected]
size_type typedef (defined in tbb::flow::interface6::sequencer_node< T, A >)tbb::flow::interface6::sequencer_node< T, A > [protected]
SUCCEEDED enum value (defined in tbb::flow::interface6::sequencer_node< T, A >)tbb::flow::interface6::sequencer_node< T, A > [protected]
successor_type typedeftbb::flow::interface6::sequencer_node< T, A >
try_consume()tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
try_fwd enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
try_get(T &v)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
try_put(const T &t)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
try_release()tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
try_reserve(T &v)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
WAIT enum value (defined in tbb::flow::interface6::sequencer_node< T, A >)tbb::flow::interface6::sequencer_node< T, A > [protected]
~buffer_node() (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
~graph_node() (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline, virtual]
~receiver()tbb::flow::interface6::receiver< T > [inline, virtual]
~sender() (defined in tbb::flow::interface6::sender< T >)tbb::flow::interface6::sender< T > [inline, virtual]
~sequencer_node()tbb::flow::interface6::sequencer_node< T, A > [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00076.html b/src/tbb/doc/html/a00076.html new file mode 100644 index 0000000..6617254 --- /dev/null +++ b/src/tbb/doc/html/a00076.html @@ -0,0 +1,91 @@ + + +Member List + + + + + + +

tbb::flow::interface6::priority_queue_node< T, Compare, A > Member List

This is the complete list of members for tbb::flow::interface6::priority_queue_node< T, Compare, A >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
buffer_node(graph &g)tbb::flow::interface6::buffer_node< T, A > [inline]
buffer_node(const buffer_node &src)tbb::flow::interface6::buffer_node< T, A > [inline]
con_res enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
FAILED enum value (defined in tbb::flow::interface6::priority_queue_node< T, Compare, A >)tbb::flow::interface6::priority_queue_node< T, Compare, A > [protected]
forward()tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
forwarder_busy (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
graph_node(graph &g) (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline]
handle_operations(prio_operation *op_list) (defined in tbb::flow::interface6::priority_queue_node< T, Compare, A >)tbb::flow::interface6::priority_queue_node< T, Compare, A > [inline, protected, virtual]
input_type typedeftbb::flow::interface6::priority_queue_node< T, Compare, A >
internal::aggregating_functor< my_class, buffer_operation > (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [friend]
internal::forward_task< buffer_node< T, A > > (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [friend]
internal_consume(prio_operation *op) (defined in tbb::flow::interface6::priority_queue_node< T, Compare, A >)tbb::flow::interface6::priority_queue_node< T, Compare, A > [inline, protected, virtual]
internal_forward(prio_operation *op)tbb::flow::interface6::priority_queue_node< T, Compare, A > [inline, protected, virtual]
internal_pop(prio_operation *op) (defined in tbb::flow::interface6::priority_queue_node< T, Compare, A >)tbb::flow::interface6::priority_queue_node< T, Compare, A > [inline, protected, virtual]
internal_push(prio_operation *op) (defined in tbb::flow::interface6::priority_queue_node< T, Compare, A >)tbb::flow::interface6::priority_queue_node< T, Compare, A > [inline, protected, virtual]
internal_reg_succ(buffer_operation *op)tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
internal_release(prio_operation *op) (defined in tbb::flow::interface6::priority_queue_node< T, Compare, A >)tbb::flow::interface6::priority_queue_node< T, Compare, A > [inline, protected, virtual]
internal_rem_succ(buffer_operation *op)tbb::flow::interface6::buffer_node< T, A > [inline, protected, virtual]
internal_reserve(prio_operation *op) (defined in tbb::flow::interface6::priority_queue_node< T, Compare, A >)tbb::flow::interface6::priority_queue_node< T, Compare, A > [inline, protected, virtual]
item_type typedef (defined in tbb::flow::interface6::priority_queue_node< T, Compare, A >)tbb::flow::interface6::priority_queue_node< T, Compare, A > [protected]
my_aggregator (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
my_class typedef (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A >
my_graph (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
my_handler typedef (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
my_parent (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
my_successors (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
next (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
op_stat enum name (defined in tbb::flow::interface6::priority_queue_node< T, Compare, A >)tbb::flow::interface6::priority_queue_node< T, Compare, A > [protected]
op_type enum name (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
output_type typedeftbb::flow::interface6::priority_queue_node< T, Compare, A >
predecessor_type typedeftbb::flow::interface6::priority_queue_node< T, Compare, A >
prev (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
prio_operation typedef (defined in tbb::flow::interface6::priority_queue_node< T, Compare, A >)tbb::flow::interface6::priority_queue_node< T, Compare, A > [protected]
priority_queue_node(graph &g)tbb::flow::interface6::priority_queue_node< T, Compare, A > [inline]
priority_queue_node(const priority_queue_node &src)tbb::flow::interface6::priority_queue_node< T, Compare, A > [inline]
put_item enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
reg_succ enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
register_predecessor(predecessor_type &)tbb::flow::interface6::receiver< T > [inline, virtual]
register_successor(receiver< output_type > &r)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
rel_res enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
rem_succ enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
remove_predecessor(predecessor_type &)tbb::flow::interface6::receiver< T > [inline, virtual]
remove_successor(receiver< output_type > &r)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
req_item enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
res_item enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
size_type typedef (defined in tbb::flow::interface6::priority_queue_node< T, Compare, A >)tbb::flow::interface6::priority_queue_node< T, Compare, A > [protected]
SUCCEEDED enum value (defined in tbb::flow::interface6::priority_queue_node< T, Compare, A >)tbb::flow::interface6::priority_queue_node< T, Compare, A > [protected]
successor_type typedeftbb::flow::interface6::priority_queue_node< T, Compare, A >
try_consume()tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
try_fwd enum value (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [protected]
try_get(T &v)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
try_put(const T &t)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
try_release()tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
try_reserve(T &v)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
WAIT enum value (defined in tbb::flow::interface6::priority_queue_node< T, Compare, A >)tbb::flow::interface6::priority_queue_node< T, Compare, A > [protected]
~buffer_node() (defined in tbb::flow::interface6::buffer_node< T, A >)tbb::flow::interface6::buffer_node< T, A > [inline, virtual]
~graph_node() (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline, virtual]
~receiver()tbb::flow::interface6::receiver< T > [inline, virtual]
~sender() (defined in tbb::flow::interface6::sender< T >)tbb::flow::interface6::sender< T > [inline, virtual]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00077.html b/src/tbb/doc/html/a00077.html new file mode 100644 index 0000000..febb8e1 --- /dev/null +++ b/src/tbb/doc/html/a00077.html @@ -0,0 +1,59 @@ + + +Member List + + + + + + +

tbb::flow::interface6::limiter_node< T > Member List

This is the complete list of members for tbb::flow::interface6::limiter_node< T >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
decrementtbb::flow::interface6::limiter_node< T >
graph_node(graph &g) (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline]
input_type typedeftbb::flow::interface6::limiter_node< T >
internal::decrementer< limiter_node< T > > (defined in tbb::flow::interface6::limiter_node< T >)tbb::flow::interface6::limiter_node< T > [friend]
internal::forward_task< limiter_node< T > > (defined in tbb::flow::interface6::limiter_node< T >)tbb::flow::interface6::limiter_node< T > [friend]
limiter_node(graph &g, size_t threshold, int num_decrement_predecessors=0)tbb::flow::interface6::limiter_node< T > [inline]
limiter_node(const limiter_node &src)tbb::flow::interface6::limiter_node< T > [inline]
my_graph (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
next (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
output_type typedeftbb::flow::interface6::limiter_node< T >
predecessor_type typedeftbb::flow::interface6::limiter_node< T >
prev (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [protected]
register_predecessor(predecessor_type &src)tbb::flow::interface6::limiter_node< T > [inline]
tbb::flow::interface6::receiver::register_predecessor(predecessor_type &)tbb::flow::interface6::receiver< T > [inline, virtual]
register_successor(receiver< output_type > &r)tbb::flow::interface6::limiter_node< T > [inline, virtual]
remove_predecessor(predecessor_type &src)tbb::flow::interface6::limiter_node< T > [inline]
tbb::flow::interface6::receiver::remove_predecessor(predecessor_type &)tbb::flow::interface6::receiver< T > [inline, virtual]
remove_successor(receiver< output_type > &r)tbb::flow::interface6::limiter_node< T > [inline, virtual]
successor_type typedeftbb::flow::interface6::limiter_node< T >
try_consume()tbb::flow::interface6::sender< T > [inline, virtual]
try_get(T &)tbb::flow::interface6::sender< T > [inline, virtual]
try_put(const T &t)tbb::flow::interface6::limiter_node< T > [inline, virtual]
try_release()tbb::flow::interface6::sender< T > [inline, virtual]
try_reserve(T &)tbb::flow::interface6::sender< T > [inline, virtual]
~graph_node() (defined in tbb::flow::interface6::graph_node)tbb::flow::interface6::graph_node [inline, virtual]
~receiver()tbb::flow::interface6::receiver< T > [inline, virtual]
~sender() (defined in tbb::flow::interface6::sender< T >)tbb::flow::interface6::sender< T > [inline, virtual]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00082.html b/src/tbb/doc/html/a00082.html new file mode 100644 index 0000000..ab4eeb1 --- /dev/null +++ b/src/tbb/doc/html/a00082.html @@ -0,0 +1,53 @@ + + +Member List + + + + + + +

tbb::interface6::memory_pool_allocator< T, P > Member List

This is the complete list of members for tbb::interface6::memory_pool_allocator< T, P >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + +
address(reference x) const (defined in tbb::interface6::memory_pool_allocator< T, P >)tbb::interface6::memory_pool_allocator< T, P > [inline]
address(const_reference x) const (defined in tbb::interface6::memory_pool_allocator< T, P >)tbb::interface6::memory_pool_allocator< T, P > [inline]
allocate(size_type n, const void *=0)tbb::interface6::memory_pool_allocator< T, P > [inline]
const_pointer typedef (defined in tbb::interface6::memory_pool_allocator< T, P >)tbb::interface6::memory_pool_allocator< T, P >
const_reference typedef (defined in tbb::interface6::memory_pool_allocator< T, P >)tbb::interface6::memory_pool_allocator< T, P >
construct(pointer p, Args &&...args)tbb::interface6::memory_pool_allocator< T, P > [inline]
deallocate(pointer p, size_type)tbb::interface6::memory_pool_allocator< T, P > [inline]
difference_type typedef (defined in tbb::interface6::memory_pool_allocator< T, P >)tbb::interface6::memory_pool_allocator< T, P >
max_size() const tbb::interface6::memory_pool_allocator< T, P > [inline]
memory_pool_allocator (defined in tbb::interface6::memory_pool_allocator< T, P >)tbb::interface6::memory_pool_allocator< T, P > [friend]
memory_pool_allocator(pool_type &pool) (defined in tbb::interface6::memory_pool_allocator< T, P >)tbb::interface6::memory_pool_allocator< T, P > [inline]
memory_pool_allocator(const memory_pool_allocator &src) (defined in tbb::interface6::memory_pool_allocator< T, P >)tbb::interface6::memory_pool_allocator< T, P > [inline]
memory_pool_allocator(const memory_pool_allocator< U, P > &src) (defined in tbb::interface6::memory_pool_allocator< T, P >)tbb::interface6::memory_pool_allocator< T, P > [inline]
my_pool (defined in tbb::interface6::memory_pool_allocator< T, P >)tbb::interface6::memory_pool_allocator< T, P > [protected]
operator!= (defined in tbb::interface6::memory_pool_allocator< T, P >)tbb::interface6::memory_pool_allocator< T, P > [friend]
operator== (defined in tbb::interface6::memory_pool_allocator< T, P >)tbb::interface6::memory_pool_allocator< T, P > [friend]
pointer typedef (defined in tbb::interface6::memory_pool_allocator< T, P >)tbb::interface6::memory_pool_allocator< T, P >
pool_type typedef (defined in tbb::interface6::memory_pool_allocator< T, P >)tbb::interface6::memory_pool_allocator< T, P > [protected]
reference typedef (defined in tbb::interface6::memory_pool_allocator< T, P >)tbb::interface6::memory_pool_allocator< T, P >
size_type typedef (defined in tbb::interface6::memory_pool_allocator< T, P >)tbb::interface6::memory_pool_allocator< T, P >
value_type typedef (defined in tbb::interface6::memory_pool_allocator< T, P >)tbb::interface6::memory_pool_allocator< T, P >


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00084.html b/src/tbb/doc/html/a00084.html new file mode 100644 index 0000000..fe9265a --- /dev/null +++ b/src/tbb/doc/html/a00084.html @@ -0,0 +1,43 @@ + + +Member List + + + + + + +

tbb::interface6::memory_pool_allocator< void, P > Member List

This is the complete list of members for tbb::interface6::memory_pool_allocator< void, P >, including all inherited members.

+ + + + + + + + + + + +
const_pointer typedef (defined in tbb::interface6::memory_pool_allocator< void, P >)tbb::interface6::memory_pool_allocator< void, P >
memory_pool_allocator (defined in tbb::interface6::memory_pool_allocator< void, P >)tbb::interface6::memory_pool_allocator< void, P > [friend]
memory_pool_allocator(pool_type &pool) (defined in tbb::interface6::memory_pool_allocator< void, P >)tbb::interface6::memory_pool_allocator< void, P > [inline]
memory_pool_allocator(const memory_pool_allocator &src) (defined in tbb::interface6::memory_pool_allocator< void, P >)tbb::interface6::memory_pool_allocator< void, P > [inline]
memory_pool_allocator(const memory_pool_allocator< U, P > &src) (defined in tbb::interface6::memory_pool_allocator< void, P >)tbb::interface6::memory_pool_allocator< void, P > [inline]
my_pool (defined in tbb::interface6::memory_pool_allocator< void, P >)tbb::interface6::memory_pool_allocator< void, P > [protected]
operator!= (defined in tbb::interface6::memory_pool_allocator< void, P >)tbb::interface6::memory_pool_allocator< void, P > [friend]
operator== (defined in tbb::interface6::memory_pool_allocator< void, P >)tbb::interface6::memory_pool_allocator< void, P > [friend]
pointer typedef (defined in tbb::interface6::memory_pool_allocator< void, P >)tbb::interface6::memory_pool_allocator< void, P >
pool_type typedef (defined in tbb::interface6::memory_pool_allocator< void, P >)tbb::interface6::memory_pool_allocator< void, P >
value_type typedef (defined in tbb::interface6::memory_pool_allocator< void, P >)tbb::interface6::memory_pool_allocator< void, P >


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00086.html b/src/tbb/doc/html/a00086.html new file mode 100644 index 0000000..46fd5dd --- /dev/null +++ b/src/tbb/doc/html/a00086.html @@ -0,0 +1,34 @@ + + +Member List + + + + + + +

tbb::interface6::memory_pool< Alloc > Member List

This is the complete list of members for tbb::interface6::memory_pool< Alloc >, including all inherited members.

+ + +
memory_pool(const Alloc &src=Alloc())tbb::interface6::memory_pool< Alloc >
~memory_pool()tbb::interface6::memory_pool< Alloc > [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00088.html b/src/tbb/doc/html/a00088.html new file mode 100644 index 0000000..a97e5c6 --- /dev/null +++ b/src/tbb/doc/html/a00088.html @@ -0,0 +1,49 @@ + + +Member List + + + + + + +

tbb::mutex Member List

This is the complete list of members for tbb::mutex, including all inherited members.

+ + + + + + + + + + + + + + + + + +
DESTROYED enum value (defined in tbb::mutex)tbb::mutex
HELD enum value (defined in tbb::mutex)tbb::mutex
INITIALIZED enum value (defined in tbb::mutex)tbb::mutex
is_fair_mutex (defined in tbb::mutex)tbb::mutex [static]
is_recursive_mutex (defined in tbb::mutex)tbb::mutex [static]
is_rw_mutex (defined in tbb::mutex)tbb::mutex [static]
lock()tbb::mutex [inline]
mutex()tbb::mutex [inline]
native_handle() (defined in tbb::mutex)tbb::mutex [inline]
native_handle_type typedeftbb::mutex
native_handle_type typedef (defined in tbb::mutex)tbb::mutex
scoped_lock (defined in tbb::mutex)tbb::mutex [friend]
set_state(state_t to)tbb::mutex [inline]
state_t enum name (defined in tbb::mutex)tbb::mutex
try_lock()tbb::mutex [inline]
unlock()tbb::mutex [inline]
~mutex() (defined in tbb::mutex)tbb::mutex [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00089.html b/src/tbb/doc/html/a00089.html new file mode 100644 index 0000000..ddb367b --- /dev/null +++ b/src/tbb/doc/html/a00089.html @@ -0,0 +1,39 @@ + + +Member List + + + + + + +

tbb::mutex::scoped_lock Member List

This is the complete list of members for tbb::mutex::scoped_lock, including all inherited members.

+ + + + + + + +
acquire(mutex &mutex)tbb::mutex::scoped_lock [inline]
mutex (defined in tbb::mutex::scoped_lock)tbb::mutex::scoped_lock [friend]
release()tbb::mutex::scoped_lock [inline]
scoped_lock()tbb::mutex::scoped_lock [inline]
scoped_lock(mutex &mutex)tbb::mutex::scoped_lock [inline]
try_acquire(mutex &mutex)tbb::mutex::scoped_lock [inline]
~scoped_lock()tbb::mutex::scoped_lock [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00090.html b/src/tbb/doc/html/a00090.html new file mode 100644 index 0000000..d868cc3 --- /dev/null +++ b/src/tbb/doc/html/a00090.html @@ -0,0 +1,36 @@ + + +Member List + + + + + + +

tbb::null_mutex Member List

This is the complete list of members for tbb::null_mutex, including all inherited members.

+ + + + +
is_fair_mutex (defined in tbb::null_mutex)tbb::null_mutex [static]
is_recursive_mutex (defined in tbb::null_mutex)tbb::null_mutex [static]
is_rw_mutex (defined in tbb::null_mutex)tbb::null_mutex [static]
null_mutex() (defined in tbb::null_mutex)tbb::null_mutex [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00091.html b/src/tbb/doc/html/a00091.html new file mode 100644 index 0000000..bdd2323 --- /dev/null +++ b/src/tbb/doc/html/a00091.html @@ -0,0 +1,38 @@ + + +Member List + + + + + + +

tbb::null_mutex::scoped_lock Member List

This is the complete list of members for tbb::null_mutex::scoped_lock, including all inherited members.

+ + + + + + +
acquire(null_mutex &) (defined in tbb::null_mutex::scoped_lock)tbb::null_mutex::scoped_lock [inline]
release() (defined in tbb::null_mutex::scoped_lock)tbb::null_mutex::scoped_lock [inline]
scoped_lock() (defined in tbb::null_mutex::scoped_lock)tbb::null_mutex::scoped_lock [inline]
scoped_lock(null_mutex &) (defined in tbb::null_mutex::scoped_lock)tbb::null_mutex::scoped_lock [inline]
try_acquire(null_mutex &) (defined in tbb::null_mutex::scoped_lock)tbb::null_mutex::scoped_lock [inline]
~scoped_lock() (defined in tbb::null_mutex::scoped_lock)tbb::null_mutex::scoped_lock [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00092.html b/src/tbb/doc/html/a00092.html new file mode 100644 index 0000000..6fb88b3 --- /dev/null +++ b/src/tbb/doc/html/a00092.html @@ -0,0 +1,36 @@ + + +Member List + + + + + + +

tbb::null_rw_mutex Member List

This is the complete list of members for tbb::null_rw_mutex, including all inherited members.

+ + + + +
is_fair_mutex (defined in tbb::null_rw_mutex)tbb::null_rw_mutex [static]
is_recursive_mutex (defined in tbb::null_rw_mutex)tbb::null_rw_mutex [static]
is_rw_mutex (defined in tbb::null_rw_mutex)tbb::null_rw_mutex [static]
null_rw_mutex() (defined in tbb::null_rw_mutex)tbb::null_rw_mutex [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00093.html b/src/tbb/doc/html/a00093.html new file mode 100644 index 0000000..c547bac --- /dev/null +++ b/src/tbb/doc/html/a00093.html @@ -0,0 +1,40 @@ + + +Member List + + + + + + +

tbb::null_rw_mutex::scoped_lock Member List

This is the complete list of members for tbb::null_rw_mutex::scoped_lock, including all inherited members.

+ + + + + + + + +
acquire(null_rw_mutex &, bool=true) (defined in tbb::null_rw_mutex::scoped_lock)tbb::null_rw_mutex::scoped_lock [inline]
downgrade_to_reader() (defined in tbb::null_rw_mutex::scoped_lock)tbb::null_rw_mutex::scoped_lock [inline]
release() (defined in tbb::null_rw_mutex::scoped_lock)tbb::null_rw_mutex::scoped_lock [inline]
scoped_lock() (defined in tbb::null_rw_mutex::scoped_lock)tbb::null_rw_mutex::scoped_lock [inline]
scoped_lock(null_rw_mutex &, bool=true) (defined in tbb::null_rw_mutex::scoped_lock)tbb::null_rw_mutex::scoped_lock [inline]
try_acquire(null_rw_mutex &, bool=true) (defined in tbb::null_rw_mutex::scoped_lock)tbb::null_rw_mutex::scoped_lock [inline]
upgrade_to_writer() (defined in tbb::null_rw_mutex::scoped_lock)tbb::null_rw_mutex::scoped_lock [inline]
~scoped_lock() (defined in tbb::null_rw_mutex::scoped_lock)tbb::null_rw_mutex::scoped_lock [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00094.html b/src/tbb/doc/html/a00094.html new file mode 100644 index 0000000..8c6bf6b --- /dev/null +++ b/src/tbb/doc/html/a00094.html @@ -0,0 +1,34 @@ + + +Member List + + + + + + +

tbb::parallel_do_feeder< Item > Member List

This is the complete list of members for tbb::parallel_do_feeder< Item >, including all inherited members.

+ + +
add(const Item &item)tbb::parallel_do_feeder< Item > [inline]
internal::parallel_do_feeder_impl (defined in tbb::parallel_do_feeder< Item >)tbb::parallel_do_feeder< Item > [friend]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00096.html b/src/tbb/doc/html/a00096.html new file mode 100644 index 0000000..8d215e3 --- /dev/null +++ b/src/tbb/doc/html/a00096.html @@ -0,0 +1,33 @@ + + +Member List + + + + + + +

tbb::pre_scan_tag Member List

This is the complete list of members for tbb::pre_scan_tag, including all inherited members.

+ +
is_final_scan() (defined in tbb::pre_scan_tag)tbb::pre_scan_tag [inline, static]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00097.html b/src/tbb/doc/html/a00097.html new file mode 100644 index 0000000..ad8bd18 --- /dev/null +++ b/src/tbb/doc/html/a00097.html @@ -0,0 +1,33 @@ + + +Member List + + + + + + +

tbb::final_scan_tag Member List

This is the complete list of members for tbb::final_scan_tag, including all inherited members.

+ +
is_final_scan() (defined in tbb::final_scan_tag)tbb::final_scan_tag [inline, static]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00098.html b/src/tbb/doc/html/a00098.html new file mode 100644 index 0000000..b92ef81 --- /dev/null +++ b/src/tbb/doc/html/a00098.html @@ -0,0 +1,37 @@ + + +Member List + + + + + + +

tbb::parallel_while< Body > Member List

This is the complete list of members for tbb::parallel_while< Body >, including all inherited members.

+ + + + + +
add(const value_type &item)tbb::parallel_while< Body >
parallel_while()tbb::parallel_while< Body > [inline]
run(Stream &stream, const Body &body)tbb::parallel_while< Body >
value_type typedeftbb::parallel_while< Body >
~parallel_while()tbb::parallel_while< Body > [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00099.html b/src/tbb/doc/html/a00099.html new file mode 100644 index 0000000..8ec61c6 --- /dev/null +++ b/src/tbb/doc/html/a00099.html @@ -0,0 +1,34 @@ + + +Member List + + + + + + +

tbb::internal::affinity_partitioner_base_v3 Member List

This is the complete list of members for tbb::internal::affinity_partitioner_base_v3, including all inherited members.

+ + +
tbb::affinity_partitioner (defined in tbb::internal::affinity_partitioner_base_v3)tbb::internal::affinity_partitioner_base_v3 [friend]
tbb::interface6::internal::affinity_partition_type (defined in tbb::internal::affinity_partitioner_base_v3)tbb::internal::affinity_partitioner_base_v3 [friend]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00100.html b/src/tbb/doc/html/a00100.html new file mode 100644 index 0000000..30a59c7 --- /dev/null +++ b/src/tbb/doc/html/a00100.html @@ -0,0 +1,37 @@ + + +Member List + + + + + + +

tbb::internal::partition_type_base Member List

This is the complete list of members for tbb::internal::partition_type_base, including all inherited members.

+ + + + + +
continue_after_execute_range() (defined in tbb::internal::partition_type_base)tbb::internal::partition_type_base [inline]
decide_whether_to_delay() (defined in tbb::internal::partition_type_base)tbb::internal::partition_type_base [inline]
note_affinity(task::affinity_id) (defined in tbb::internal::partition_type_base)tbb::internal::partition_type_base [inline]
set_affinity(task &) (defined in tbb::internal::partition_type_base)tbb::internal::partition_type_base [inline]
spawn_or_delay(bool, task &b) (defined in tbb::internal::partition_type_base)tbb::internal::partition_type_base [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00101.html b/src/tbb/doc/html/a00101.html new file mode 100644 index 0000000..ec1ce9b --- /dev/null +++ b/src/tbb/doc/html/a00101.html @@ -0,0 +1,37 @@ + + +Member List + + + + + + +

tbb::simple_partitioner Member List

This is the complete list of members for tbb::simple_partitioner, including all inherited members.

+ + + + + +
interface6::internal::start_for (defined in tbb::simple_partitioner)tbb::simple_partitioner [friend]
interface6::internal::start_reduce (defined in tbb::simple_partitioner)tbb::simple_partitioner [friend]
internal::start_scan (defined in tbb::simple_partitioner)tbb::simple_partitioner [friend]
serial::interface6::start_for (defined in tbb::simple_partitioner)tbb::simple_partitioner [friend]
simple_partitioner() (defined in tbb::simple_partitioner)tbb::simple_partitioner [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00103.html b/src/tbb/doc/html/a00103.html new file mode 100644 index 0000000..1ba82c5 --- /dev/null +++ b/src/tbb/doc/html/a00103.html @@ -0,0 +1,37 @@ + + +Member List + + + + + + +

tbb::auto_partitioner Member List

This is the complete list of members for tbb::auto_partitioner, including all inherited members.

+ + + + + +
auto_partitioner() (defined in tbb::auto_partitioner)tbb::auto_partitioner [inline]
interface6::internal::start_for (defined in tbb::auto_partitioner)tbb::auto_partitioner [friend]
interface6::internal::start_reduce (defined in tbb::auto_partitioner)tbb::auto_partitioner [friend]
internal::start_scan (defined in tbb::auto_partitioner)tbb::auto_partitioner [friend]
serial::interface6::start_for (defined in tbb::auto_partitioner)tbb::auto_partitioner [friend]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00104.html b/src/tbb/doc/html/a00104.html new file mode 100644 index 0000000..4087aae --- /dev/null +++ b/src/tbb/doc/html/a00104.html @@ -0,0 +1,39 @@ + + +Member List + + + + + + +

tbb::affinity_partitioner Member List

This is the complete list of members for tbb::affinity_partitioner, including all inherited members.

+ + + + + + + +
affinity_partitioner() (defined in tbb::affinity_partitioner)tbb::affinity_partitioner [inline]
interface6::internal::start_for (defined in tbb::affinity_partitioner)tbb::affinity_partitioner [friend]
interface6::internal::start_reduce (defined in tbb::affinity_partitioner)tbb::affinity_partitioner [friend]
internal::start_scan (defined in tbb::affinity_partitioner)tbb::affinity_partitioner [friend]
serial::interface6::start_for (defined in tbb::affinity_partitioner)tbb::affinity_partitioner [friend]
tbb::affinity_partitioner (defined in tbb::internal::affinity_partitioner_base_v3)tbb::internal::affinity_partitioner_base_v3 [friend]
tbb::interface6::internal::affinity_partition_type (defined in tbb::internal::affinity_partitioner_base_v3)tbb::internal::affinity_partitioner_base_v3 [friend]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00105.html b/src/tbb/doc/html/a00105.html new file mode 100644 index 0000000..19a6239 --- /dev/null +++ b/src/tbb/doc/html/a00105.html @@ -0,0 +1,54 @@ + + +Member List + + + + + + +

tbb::filter Member List

This is the complete list of members for tbb::filter, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + +
exact_exception_propagationtbb::filter [protected, static]
filter(mode filter_mode) (defined in tbb::filter)tbb::filter [inline, protected]
filter_is_boundtbb::filter [protected, static]
filter_is_out_of_ordertbb::filter [protected, static]
filter_is_serialtbb::filter [protected, static]
filter_may_emit_nulltbb::filter [protected, static]
finalize(void *)tbb::filter [inline, virtual]
internal::pipeline_root_task (defined in tbb::filter)tbb::filter [friend]
internal::stage_task (defined in tbb::filter)tbb::filter [friend]
is_bound() const tbb::filter [inline]
is_ordered() const tbb::filter [inline]
is_serial() const tbb::filter [inline]
my_pipeline(NULL) (defined in tbb::filter)tbb::filter [protected]
next_segment(NULL) (defined in tbb::filter)tbb::filter [inline, protected]
object_may_be_null()tbb::filter [inline]
operator()(void *item)=0tbb::filter [pure virtual]
pipeline (defined in tbb::filter)tbb::filter [friend]
prev_filter_in_pipeline(not_in_pipeline()) (defined in tbb::filter)tbb::filter [protected]
set_end_of_input() (defined in tbb::filter)tbb::filter [protected]
thread_bound_filter (defined in tbb::filter)tbb::filter [friend]
x1((is_serial_?serial:parallel)|exact_exception_propagation)) (defined in tbb::filter)tbb::filter [protected]
~filter()tbb::filter [virtual]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00106.html b/src/tbb/doc/html/a00106.html new file mode 100644 index 0000000..d86c682 --- /dev/null +++ b/src/tbb/doc/html/a00106.html @@ -0,0 +1,59 @@ + + +Member List + + + + + + +

tbb::thread_bound_filter Member List

This is the complete list of members for tbb::thread_bound_filter, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
end_of_stream enum value (defined in tbb::thread_bound_filter)tbb::thread_bound_filter
exact_exception_propagationtbb::filter [protected, static]
filter(mode filter_mode) (defined in tbb::filter)tbb::filter [inline, protected]
filter_is_boundtbb::filter [protected, static]
filter_is_out_of_ordertbb::filter [protected, static]
filter_is_serialtbb::filter [protected, static]
filter_may_emit_nulltbb::filter [protected, static]
finalize(void *)tbb::filter [inline, virtual]
internal::pipeline_root_task (defined in tbb::filter)tbb::filter [friend]
internal::stage_task (defined in tbb::filter)tbb::filter [friend]
is_bound() const tbb::filter [inline]
is_ordered() const tbb::filter [inline]
is_serial() const tbb::filter [inline]
item_not_available enum value (defined in tbb::thread_bound_filter)tbb::thread_bound_filter
my_pipeline(NULL) (defined in tbb::filter)tbb::filter [protected]
next_segment(NULL) (defined in tbb::filter)tbb::filter [inline, protected]
object_may_be_null()tbb::filter [inline]
operator()(void *item)=0tbb::filter [pure virtual]
prev_filter_in_pipeline(not_in_pipeline()) (defined in tbb::filter)tbb::filter [protected]
process_item()tbb::thread_bound_filter
result_type enum name (defined in tbb::thread_bound_filter)tbb::thread_bound_filter
set_end_of_input() (defined in tbb::filter)tbb::filter [protected]
success enum value (defined in tbb::thread_bound_filter)tbb::thread_bound_filter
thread_bound_filter(mode filter_mode) (defined in tbb::thread_bound_filter)tbb::thread_bound_filter [inline, protected]
try_process_item()tbb::thread_bound_filter
x1((is_serial_?serial:parallel)|exact_exception_propagation)) (defined in tbb::filter)tbb::filter [protected]
~filter()tbb::filter [virtual]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00107.html b/src/tbb/doc/html/a00107.html new file mode 100644 index 0000000..2ed6c4b --- /dev/null +++ b/src/tbb/doc/html/a00107.html @@ -0,0 +1,44 @@ + + +Member List + + + + + + +

tbb::pipeline Member List

This is the complete list of members for tbb::pipeline, including all inherited members.

+ + + + + + + + + + + + +
add_filter(filter &filter_)tbb::pipeline
clear()tbb::pipeline
filter (defined in tbb::pipeline)tbb::pipeline [friend]
internal::pipeline_cleaner (defined in tbb::pipeline)tbb::pipeline [friend]
internal::pipeline_root_task (defined in tbb::pipeline)tbb::pipeline [friend]
internal::stage_task (defined in tbb::pipeline)tbb::pipeline [friend]
pipeline()tbb::pipeline
run(size_t max_number_of_live_tokens)tbb::pipeline
run(size_t max_number_of_live_tokens, tbb::task_group_context &context)tbb::pipeline
tbb::interface6::internal::pipeline_proxy (defined in tbb::pipeline)tbb::pipeline [friend]
thread_bound_filter (defined in tbb::pipeline)tbb::pipeline [friend]
~pipeline()tbb::pipeline [virtual]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00108.html b/src/tbb/doc/html/a00108.html new file mode 100644 index 0000000..768cfad --- /dev/null +++ b/src/tbb/doc/html/a00108.html @@ -0,0 +1,34 @@ + + +Member List + + + + + + +

tbb::interface6::flow_control Member List

This is the complete list of members for tbb::interface6::flow_control, including all inherited members.

+ + +
internal::concrete_filter (defined in tbb::interface6::flow_control)tbb::interface6::flow_control [friend]
stop() (defined in tbb::interface6::flow_control)tbb::interface6::flow_control [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00109.html b/src/tbb/doc/html/a00109.html new file mode 100644 index 0000000..346452e --- /dev/null +++ b/src/tbb/doc/html/a00109.html @@ -0,0 +1,41 @@ + + +Member List + + + + + + +

tbb::interface6::filter_t< T, U > Member List

This is the complete list of members for tbb::interface6::filter_t< T, U >, including all inherited members.

+ + + + + + + + + +
clear() (defined in tbb::interface6::filter_t< T, U >)tbb::interface6::filter_t< T, U > [inline]
filter_t() (defined in tbb::interface6::filter_t< T, U >)tbb::interface6::filter_t< T, U > [inline]
filter_t(const filter_t< T, U > &rhs) (defined in tbb::interface6::filter_t< T, U >)tbb::interface6::filter_t< T, U > [inline]
filter_t(tbb::filter::mode mode, const Body &body) (defined in tbb::interface6::filter_t< T, U >)tbb::interface6::filter_t< T, U > [inline]
internal::pipeline_proxy (defined in tbb::interface6::filter_t< T, U >)tbb::interface6::filter_t< T, U > [friend]
make_filter(tbb::filter::mode, const Body &)tbb::interface6::filter_t< T, U > [friend]
operator & (defined in tbb::interface6::filter_t< T, U >)tbb::interface6::filter_t< T, U > [friend]
operator=(const filter_t< T, U > &rhs) (defined in tbb::interface6::filter_t< T, U >)tbb::interface6::filter_t< T, U > [inline]
~filter_t() (defined in tbb::interface6::filter_t< T, U >)tbb::interface6::filter_t< T, U > [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00110.html b/src/tbb/doc/html/a00110.html new file mode 100644 index 0000000..2130b67 --- /dev/null +++ b/src/tbb/doc/html/a00110.html @@ -0,0 +1,37 @@ + + +Member List + + + + + + +

tbb::queuing_mutex Member List

This is the complete list of members for tbb::queuing_mutex, including all inherited members.

+ + + + + +
internal_construct() (defined in tbb::queuing_mutex)tbb::queuing_mutex
is_fair_mutex (defined in tbb::queuing_mutex)tbb::queuing_mutex [static]
is_recursive_mutex (defined in tbb::queuing_mutex)tbb::queuing_mutex [static]
is_rw_mutex (defined in tbb::queuing_mutex)tbb::queuing_mutex [static]
queuing_mutex()tbb::queuing_mutex [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00111.html b/src/tbb/doc/html/a00111.html new file mode 100644 index 0000000..a8da238 --- /dev/null +++ b/src/tbb/doc/html/a00111.html @@ -0,0 +1,38 @@ + + +Member List + + + + + + +

tbb::queuing_mutex::scoped_lock Member List

This is the complete list of members for tbb::queuing_mutex::scoped_lock, including all inherited members.

+ + + + + + +
acquire(queuing_mutex &m)tbb::queuing_mutex::scoped_lock
release()tbb::queuing_mutex::scoped_lock
scoped_lock()tbb::queuing_mutex::scoped_lock [inline]
scoped_lock(queuing_mutex &m)tbb::queuing_mutex::scoped_lock [inline]
try_acquire(queuing_mutex &m)tbb::queuing_mutex::scoped_lock
~scoped_lock()tbb::queuing_mutex::scoped_lock [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00112.html b/src/tbb/doc/html/a00112.html new file mode 100644 index 0000000..c3a3d9d --- /dev/null +++ b/src/tbb/doc/html/a00112.html @@ -0,0 +1,38 @@ + + +Member List + + + + + + +

tbb::queuing_rw_mutex Member List

This is the complete list of members for tbb::queuing_rw_mutex, including all inherited members.

+ + + + + + +
internal_construct() (defined in tbb::queuing_rw_mutex)tbb::queuing_rw_mutex
is_fair_mutex (defined in tbb::queuing_rw_mutex)tbb::queuing_rw_mutex [static]
is_recursive_mutex (defined in tbb::queuing_rw_mutex)tbb::queuing_rw_mutex [static]
is_rw_mutex (defined in tbb::queuing_rw_mutex)tbb::queuing_rw_mutex [static]
queuing_rw_mutex()tbb::queuing_rw_mutex [inline]
~queuing_rw_mutex()tbb::queuing_rw_mutex [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00113.html b/src/tbb/doc/html/a00113.html new file mode 100644 index 0000000..091c401 --- /dev/null +++ b/src/tbb/doc/html/a00113.html @@ -0,0 +1,40 @@ + + +Member List + + + + + + +

tbb::queuing_rw_mutex::scoped_lock Member List

This is the complete list of members for tbb::queuing_rw_mutex::scoped_lock, including all inherited members.

+ + + + + + + + +
acquire(queuing_rw_mutex &m, bool write=true)tbb::queuing_rw_mutex::scoped_lock
downgrade_to_reader()tbb::queuing_rw_mutex::scoped_lock
release()tbb::queuing_rw_mutex::scoped_lock
scoped_lock()tbb::queuing_rw_mutex::scoped_lock [inline]
scoped_lock(queuing_rw_mutex &m, bool write=true)tbb::queuing_rw_mutex::scoped_lock [inline]
try_acquire(queuing_rw_mutex &m, bool write=true)tbb::queuing_rw_mutex::scoped_lock
upgrade_to_writer()tbb::queuing_rw_mutex::scoped_lock
~scoped_lock()tbb::queuing_rw_mutex::scoped_lock [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00114.html b/src/tbb/doc/html/a00114.html new file mode 100644 index 0000000..b4cb5fd --- /dev/null +++ b/src/tbb/doc/html/a00114.html @@ -0,0 +1,46 @@ + + +Member List + + + + + + +

tbb::interface5::reader_writer_lock Member List

This is the complete list of members for tbb::interface5::reader_writer_lock, including all inherited members.

+ + + + + + + + + + + + + + +
active enum value (defined in tbb::interface5::reader_writer_lock)tbb::interface5::reader_writer_lock
invalid enum value (defined in tbb::interface5::reader_writer_lock)tbb::interface5::reader_writer_lock
lock()tbb::interface5::reader_writer_lock
lock_read()tbb::interface5::reader_writer_lock
reader_writer_lock()tbb::interface5::reader_writer_lock [inline]
scoped_lock (defined in tbb::interface5::reader_writer_lock)tbb::interface5::reader_writer_lock [friend]
scoped_lock_read (defined in tbb::interface5::reader_writer_lock)tbb::interface5::reader_writer_lock [friend]
status_t enum nametbb::interface5::reader_writer_lock
try_lock()tbb::interface5::reader_writer_lock
try_lock_read()tbb::interface5::reader_writer_lock
unlock()tbb::interface5::reader_writer_lock
waiting enum value (defined in tbb::interface5::reader_writer_lock)tbb::interface5::reader_writer_lock
waiting_nonblocking enum value (defined in tbb::interface5::reader_writer_lock)tbb::interface5::reader_writer_lock
~reader_writer_lock()tbb::interface5::reader_writer_lock [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00115.html b/src/tbb/doc/html/a00115.html new file mode 100644 index 0000000..3d9f6c6 --- /dev/null +++ b/src/tbb/doc/html/a00115.html @@ -0,0 +1,37 @@ + + +Member List + + + + + + +

tbb::interface5::reader_writer_lock::scoped_lock Member List

This is the complete list of members for tbb::interface5::reader_writer_lock::scoped_lock, including all inherited members.

+ + + + + +
operator delete(void *p) (defined in tbb::interface5::reader_writer_lock::scoped_lock)tbb::interface5::reader_writer_lock::scoped_lock [inline]
operator new(size_t s) (defined in tbb::interface5::reader_writer_lock::scoped_lock)tbb::interface5::reader_writer_lock::scoped_lock [inline]
reader_writer_lock (defined in tbb::interface5::reader_writer_lock::scoped_lock)tbb::interface5::reader_writer_lock::scoped_lock [friend]
scoped_lock(reader_writer_lock &lock)tbb::interface5::reader_writer_lock::scoped_lock [inline]
~scoped_lock()tbb::interface5::reader_writer_lock::scoped_lock [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00116.html b/src/tbb/doc/html/a00116.html new file mode 100644 index 0000000..a9a041f --- /dev/null +++ b/src/tbb/doc/html/a00116.html @@ -0,0 +1,37 @@ + + +Member List + + + + + + +

tbb::interface5::reader_writer_lock::scoped_lock_read Member List

This is the complete list of members for tbb::interface5::reader_writer_lock::scoped_lock_read, including all inherited members.

+ + + + + +
operator delete(void *p) (defined in tbb::interface5::reader_writer_lock::scoped_lock_read)tbb::interface5::reader_writer_lock::scoped_lock_read [inline]
operator new(size_t s) (defined in tbb::interface5::reader_writer_lock::scoped_lock_read)tbb::interface5::reader_writer_lock::scoped_lock_read [inline]
reader_writer_lock (defined in tbb::interface5::reader_writer_lock::scoped_lock_read)tbb::interface5::reader_writer_lock::scoped_lock_read [friend]
scoped_lock_read(reader_writer_lock &lock)tbb::interface5::reader_writer_lock::scoped_lock_read [inline]
~scoped_lock_read()tbb::interface5::reader_writer_lock::scoped_lock_read [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00117.html b/src/tbb/doc/html/a00117.html new file mode 100644 index 0000000..7db7b57 --- /dev/null +++ b/src/tbb/doc/html/a00117.html @@ -0,0 +1,44 @@ + + +Member List + + + + + + +

tbb::recursive_mutex Member List

This is the complete list of members for tbb::recursive_mutex, including all inherited members.

+ + + + + + + + + + + + +
is_fair_mutex (defined in tbb::recursive_mutex)tbb::recursive_mutex [static]
is_recursive_mutex (defined in tbb::recursive_mutex)tbb::recursive_mutex [static]
is_rw_mutex (defined in tbb::recursive_mutex)tbb::recursive_mutex [static]
lock()tbb::recursive_mutex [inline]
native_handle() (defined in tbb::recursive_mutex)tbb::recursive_mutex [inline]
native_handle_type typedeftbb::recursive_mutex
native_handle_type typedef (defined in tbb::recursive_mutex)tbb::recursive_mutex
recursive_mutex()tbb::recursive_mutex [inline]
scoped_lock (defined in tbb::recursive_mutex)tbb::recursive_mutex [friend]
try_lock()tbb::recursive_mutex [inline]
unlock()tbb::recursive_mutex [inline]
~recursive_mutex() (defined in tbb::recursive_mutex)tbb::recursive_mutex [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00118.html b/src/tbb/doc/html/a00118.html new file mode 100644 index 0000000..7360b9b --- /dev/null +++ b/src/tbb/doc/html/a00118.html @@ -0,0 +1,39 @@ + + +Member List + + + + + + +

tbb::recursive_mutex::scoped_lock Member List

This is the complete list of members for tbb::recursive_mutex::scoped_lock, including all inherited members.

+ + + + + + + +
acquire(recursive_mutex &mutex)tbb::recursive_mutex::scoped_lock [inline]
recursive_mutex (defined in tbb::recursive_mutex::scoped_lock)tbb::recursive_mutex::scoped_lock [friend]
release()tbb::recursive_mutex::scoped_lock [inline]
scoped_lock()tbb::recursive_mutex::scoped_lock [inline]
scoped_lock(recursive_mutex &mutex)tbb::recursive_mutex::scoped_lock [inline]
try_acquire(recursive_mutex &mutex)tbb::recursive_mutex::scoped_lock [inline]
~scoped_lock()tbb::recursive_mutex::scoped_lock [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00119.html b/src/tbb/doc/html/a00119.html new file mode 100644 index 0000000..2f41f37 --- /dev/null +++ b/src/tbb/doc/html/a00119.html @@ -0,0 +1,48 @@ + + +Member List + + + + + + +

tbb::interface6::runtime_loader Member List

This is the complete list of members for tbb::interface6::runtime_loader, including all inherited members.

+ + + + + + + + + + + + + + + + +
ec_bad_arg enum valuetbb::interface6::runtime_loader
ec_bad_call enum valuetbb::interface6::runtime_loader
ec_bad_lib enum valuetbb::interface6::runtime_loader
ec_bad_ver enum valuetbb::interface6::runtime_loader
ec_no_lib enum valuetbb::interface6::runtime_loader
ec_ok enum valuetbb::interface6::runtime_loader
em_abort enum valuetbb::interface6::runtime_loader
em_status enum valuetbb::interface6::runtime_loader
em_throw enum valuetbb::interface6::runtime_loader
error_code enum nametbb::interface6::runtime_loader
error_mode enum nametbb::interface6::runtime_loader
load(char const *path[], int min_ver=TBB_INTERFACE_VERSION, int max_ver=INT_MAX)tbb::interface6::runtime_loader
runtime_loader(error_mode mode=em_abort)tbb::interface6::runtime_loader
runtime_loader(char const *path[], int min_ver=TBB_INTERFACE_VERSION, int max_ver=INT_MAX, error_mode mode=em_abort)tbb::interface6::runtime_loader
status()tbb::interface6::runtime_loader
~runtime_loader()tbb::interface6::runtime_loader


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00121.html b/src/tbb/doc/html/a00121.html new file mode 100644 index 0000000..0abc0aa --- /dev/null +++ b/src/tbb/doc/html/a00121.html @@ -0,0 +1,48 @@ + + +Member List + + + + + + +

tbb::scalable_allocator< T > Member List

This is the complete list of members for tbb::scalable_allocator< T >, including all inherited members.

+ + + + + + + + + + + + + + + + +
address(reference x) const (defined in tbb::scalable_allocator< T >)tbb::scalable_allocator< T > [inline]
address(const_reference x) const (defined in tbb::scalable_allocator< T >)tbb::scalable_allocator< T > [inline]
allocate(size_type n, const void *=0)tbb::scalable_allocator< T > [inline]
const_pointer typedef (defined in tbb::scalable_allocator< T >)tbb::scalable_allocator< T >
const_reference typedef (defined in tbb::scalable_allocator< T >)tbb::scalable_allocator< T >
construct(pointer p, Args &&...args) (defined in tbb::scalable_allocator< T >)tbb::scalable_allocator< T > [inline]
deallocate(pointer p, size_type)tbb::scalable_allocator< T > [inline]
difference_type typedef (defined in tbb::scalable_allocator< T >)tbb::scalable_allocator< T >
max_size() const tbb::scalable_allocator< T > [inline]
pointer typedef (defined in tbb::scalable_allocator< T >)tbb::scalable_allocator< T >
reference typedef (defined in tbb::scalable_allocator< T >)tbb::scalable_allocator< T >
scalable_allocator() (defined in tbb::scalable_allocator< T >)tbb::scalable_allocator< T > [inline]
scalable_allocator(const scalable_allocator &) (defined in tbb::scalable_allocator< T >)tbb::scalable_allocator< T > [inline]
scalable_allocator(const scalable_allocator< U > &) (defined in tbb::scalable_allocator< T >)tbb::scalable_allocator< T > [inline]
size_type typedef (defined in tbb::scalable_allocator< T >)tbb::scalable_allocator< T >
value_type typedef (defined in tbb::scalable_allocator< T >)tbb::scalable_allocator< T >


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00123.html b/src/tbb/doc/html/a00123.html new file mode 100644 index 0000000..ca11399 --- /dev/null +++ b/src/tbb/doc/html/a00123.html @@ -0,0 +1,35 @@ + + +Member List + + + + + + +

tbb::scalable_allocator< void > Member List

This is the complete list of members for tbb::scalable_allocator< void >, including all inherited members.

+ + + +
const_pointer typedef (defined in tbb::scalable_allocator< void >)tbb::scalable_allocator< void >
pointer typedef (defined in tbb::scalable_allocator< void >)tbb::scalable_allocator< void >
value_type typedef (defined in tbb::scalable_allocator< void >)tbb::scalable_allocator< void >


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00125.html b/src/tbb/doc/html/a00125.html new file mode 100644 index 0000000..68002b9 --- /dev/null +++ b/src/tbb/doc/html/a00125.html @@ -0,0 +1,41 @@ + + +Member List + + + + + + +

tbb::spin_mutex Member List

This is the complete list of members for tbb::spin_mutex, including all inherited members.

+ + + + + + + + + +
internal_construct() (defined in tbb::spin_mutex)tbb::spin_mutex
is_fair_mutex (defined in tbb::spin_mutex)tbb::spin_mutex [static]
is_recursive_mutex (defined in tbb::spin_mutex)tbb::spin_mutex [static]
is_rw_mutex (defined in tbb::spin_mutex)tbb::spin_mutex [static]
lock()tbb::spin_mutex [inline]
scoped_lock (defined in tbb::spin_mutex)tbb::spin_mutex [friend]
spin_mutex()tbb::spin_mutex [inline]
try_lock()tbb::spin_mutex [inline]
unlock()tbb::spin_mutex [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00126.html b/src/tbb/doc/html/a00126.html new file mode 100644 index 0000000..b3d0629 --- /dev/null +++ b/src/tbb/doc/html/a00126.html @@ -0,0 +1,39 @@ + + +Member List + + + + + + +

tbb::spin_mutex::scoped_lock Member List

This is the complete list of members for tbb::spin_mutex::scoped_lock, including all inherited members.

+ + + + + + + +
acquire(spin_mutex &m)tbb::spin_mutex::scoped_lock [inline]
release()tbb::spin_mutex::scoped_lock [inline]
scoped_lock()tbb::spin_mutex::scoped_lock [inline]
scoped_lock(spin_mutex &m)tbb::spin_mutex::scoped_lock [inline]
spin_mutex (defined in tbb::spin_mutex::scoped_lock)tbb::spin_mutex::scoped_lock [friend]
try_acquire(spin_mutex &m)tbb::spin_mutex::scoped_lock [inline]
~scoped_lock()tbb::spin_mutex::scoped_lock [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00127.html b/src/tbb/doc/html/a00127.html new file mode 100644 index 0000000..51f45e0 --- /dev/null +++ b/src/tbb/doc/html/a00127.html @@ -0,0 +1,42 @@ + + +Member List + + + + + + +

tbb::spin_rw_mutex_v3 Member List

This is the complete list of members for tbb::spin_rw_mutex_v3, including all inherited members.

+ + + + + + + + + + +
is_fair_mutex (defined in tbb::spin_rw_mutex_v3)tbb::spin_rw_mutex_v3 [static]
is_recursive_mutex (defined in tbb::spin_rw_mutex_v3)tbb::spin_rw_mutex_v3 [static]
is_rw_mutex (defined in tbb::spin_rw_mutex_v3)tbb::spin_rw_mutex_v3 [static]
lock()tbb::spin_rw_mutex_v3 [inline]
lock_read()tbb::spin_rw_mutex_v3 [inline]
spin_rw_mutex_v3()tbb::spin_rw_mutex_v3 [inline]
try_lock()tbb::spin_rw_mutex_v3 [inline]
try_lock_read()tbb::spin_rw_mutex_v3 [inline]
unlock()tbb::spin_rw_mutex_v3 [inline]
~spin_rw_mutex_v3()tbb::spin_rw_mutex_v3 [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00128.html b/src/tbb/doc/html/a00128.html new file mode 100644 index 0000000..55ac4c9 --- /dev/null +++ b/src/tbb/doc/html/a00128.html @@ -0,0 +1,42 @@ + + +Member List + + + + + + +

tbb::spin_rw_mutex_v3::scoped_lock Member List

This is the complete list of members for tbb::spin_rw_mutex_v3::scoped_lock, including all inherited members.

+ + + + + + + + + + +
acquire(spin_rw_mutex &m, bool write=true)tbb::spin_rw_mutex_v3::scoped_lock [inline]
downgrade_to_reader()tbb::spin_rw_mutex_v3::scoped_lock [inline]
is_writertbb::spin_rw_mutex_v3::scoped_lock [protected]
mutextbb::spin_rw_mutex_v3::scoped_lock [protected]
release()tbb::spin_rw_mutex_v3::scoped_lock [inline]
scoped_lock()tbb::spin_rw_mutex_v3::scoped_lock [inline]
scoped_lock(spin_rw_mutex &m, bool write=true)tbb::spin_rw_mutex_v3::scoped_lock [inline]
try_acquire(spin_rw_mutex &m, bool write=true)tbb::spin_rw_mutex_v3::scoped_lock [inline]
upgrade_to_writer()tbb::spin_rw_mutex_v3::scoped_lock [inline]
~scoped_lock()tbb::spin_rw_mutex_v3::scoped_lock [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00130.html b/src/tbb/doc/html/a00130.html new file mode 100644 index 0000000..2aefa04 --- /dev/null +++ b/src/tbb/doc/html/a00130.html @@ -0,0 +1,32 @@ + + +Member List + + + + + + +

tbb::interface5::internal::task_base Member List

This is the complete list of members for tbb::interface5::internal::task_base, including all inherited members.

+


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00133.html b/src/tbb/doc/html/a00133.html new file mode 100644 index 0000000..84e3739 --- /dev/null +++ b/src/tbb/doc/html/a00133.html @@ -0,0 +1,90 @@ + + +Member List + + + + + + +

tbb::task Member List

This is the complete list of members for tbb::task, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
add_to_depth(int) (defined in tbb::task)tbb::task [inline]
affinity() const tbb::task [inline]
affinity_id typedeftbb::task
allocate_child()tbb::task [inline]
allocate_continuation()tbb::task [inline]
allocate_root()tbb::task [inline, static]
allocate_root(task_group_context &ctx)tbb::task [inline, static]
allocated enum valuetbb::task
cancel_group_execution()tbb::task [inline]
change_group(task_group_context &ctx)tbb::task
context()tbb::task [inline]
decrement_ref_count()tbb::task [inline]
depth() const (defined in tbb::task)tbb::task [inline]
destroy(task &t)tbb::task
enqueue(task &t)tbb::task [inline, static]
enqueue(task &t, priority_t p)tbb::task [inline, static]
execute()=0tbb::task [pure virtual]
executing enum valuetbb::task
freed enum valuetbb::task
group()tbb::task [inline]
group_priority() const tbb::task [inline]
increment_ref_count()tbb::task [inline]
interface5::internal::task_base (defined in tbb::task)tbb::task [friend]
internal::allocate_additional_child_of_proxy (defined in tbb::task)tbb::task [friend]
internal::allocate_child_proxy (defined in tbb::task)tbb::task [friend]
internal::allocate_continuation_proxy (defined in tbb::task)tbb::task [friend]
internal::allocate_root_proxy (defined in tbb::task)tbb::task [friend]
internal::allocate_root_with_context_proxy (defined in tbb::task)tbb::task [friend]
internal::scheduler (defined in tbb::task)tbb::task [friend]
is_cancelled() const tbb::task [inline]
is_owned_by_current_thread() const tbb::task
is_stolen_task() const tbb::task [inline]
note_affinity(affinity_id id)tbb::task [virtual]
parent() const tbb::task [inline]
ready enum valuetbb::task
recycle enum valuetbb::task
recycle_as_child_of(task &new_parent)tbb::task [inline]
recycle_as_continuation()tbb::task [inline]
recycle_as_safe_continuation()tbb::task [inline]
recycle_to_reexecute()tbb::task [inline]
reexecute enum valuetbb::task
ref_count() const tbb::task [inline]
self()tbb::task [static]
set_affinity(affinity_id id)tbb::task [inline]
set_depth(intptr_t) (defined in tbb::task)tbb::task [inline]
set_group_priority(priority_t p)tbb::task [inline]
set_parent(task *p)tbb::task [inline]
set_ref_count(int count)tbb::task [inline]
spawn_and_wait_for_all(task &child)tbb::task [inline]
spawn_and_wait_for_all(task_list &list)tbb::task
spawn_root_and_wait(task &root)tbb::task [inline, static]
spawn_root_and_wait(task_list &root_list)tbb::task [inline, static]
state() const tbb::task [inline]
state_type enum nametbb::task
task()tbb::task [inline, protected]
task_list (defined in tbb::task)tbb::task [friend]
wait_for_all()tbb::task [inline]
~task()tbb::task [inline, virtual]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00134.html b/src/tbb/doc/html/a00134.html new file mode 100644 index 0000000..ea31f2e --- /dev/null +++ b/src/tbb/doc/html/a00134.html @@ -0,0 +1,88 @@ + + +Member List + + + + + + +

tbb::empty_task Member List

This is the complete list of members for tbb::empty_task, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
add_to_depth(int) (defined in tbb::task)tbb::task [inline]
affinity() const tbb::task [inline]
affinity_id typedeftbb::task
allocate_child()tbb::task [inline]
allocate_continuation()tbb::task [inline]
allocate_root()tbb::task [inline, static]
allocate_root(task_group_context &ctx)tbb::task [inline, static]
allocated enum valuetbb::task
cancel_group_execution()tbb::task [inline]
change_group(task_group_context &ctx)tbb::task
context()tbb::task [inline]
decrement_ref_count()tbb::task [inline]
depth() const (defined in tbb::task)tbb::task [inline]
destroy(task &t)tbb::task
enqueue(task &t)tbb::task [inline, static]
enqueue(task &t, priority_t p)tbb::task [inline, static]
executing enum valuetbb::task
freed enum valuetbb::task
group()tbb::task [inline]
group_priority() const tbb::task [inline]
increment_ref_count()tbb::task [inline]
interface5::internal::task_base (defined in tbb::task)tbb::task [friend]
internal::allocate_additional_child_of_proxy (defined in tbb::task)tbb::task [friend]
internal::allocate_child_proxy (defined in tbb::task)tbb::task [friend]
internal::allocate_continuation_proxy (defined in tbb::task)tbb::task [friend]
internal::allocate_root_proxy (defined in tbb::task)tbb::task [friend]
internal::allocate_root_with_context_proxy (defined in tbb::task)tbb::task [friend]
internal::scheduler (defined in tbb::task)tbb::task [friend]
is_cancelled() const tbb::task [inline]
is_owned_by_current_thread() const tbb::task
is_stolen_task() const tbb::task [inline]
note_affinity(affinity_id id)tbb::task [virtual]
parent() const tbb::task [inline]
ready enum valuetbb::task
recycle enum valuetbb::task
recycle_as_child_of(task &new_parent)tbb::task [inline]
recycle_as_continuation()tbb::task [inline]
recycle_as_safe_continuation()tbb::task [inline]
recycle_to_reexecute()tbb::task [inline]
reexecute enum valuetbb::task
ref_count() const tbb::task [inline]
self()tbb::task [static]
set_affinity(affinity_id id)tbb::task [inline]
set_depth(intptr_t) (defined in tbb::task)tbb::task [inline]
set_group_priority(priority_t p)tbb::task [inline]
set_parent(task *p)tbb::task [inline]
set_ref_count(int count)tbb::task [inline]
spawn_and_wait_for_all(task &child)tbb::task [inline]
spawn_and_wait_for_all(task_list &list)tbb::task
spawn_root_and_wait(task &root)tbb::task [inline, static]
spawn_root_and_wait(task_list &root_list)tbb::task [inline, static]
state() const tbb::task [inline]
state_type enum nametbb::task
task()tbb::task [inline, protected]
wait_for_all()tbb::task [inline]
~task()tbb::task [inline, virtual]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00135.html b/src/tbb/doc/html/a00135.html new file mode 100644 index 0000000..ab14bbf --- /dev/null +++ b/src/tbb/doc/html/a00135.html @@ -0,0 +1,40 @@ + + +Member List + + + + + + +

tbb::task_list Member List

This is the complete list of members for tbb::task_list, including all inherited members.

+ + + + + + + + +
clear()tbb::task_list [inline]
empty() const tbb::task_list [inline]
interface5::internal::task_base (defined in tbb::task_list)tbb::task_list [friend]
pop_front()tbb::task_list [inline]
push_back(task &task)tbb::task_list [inline]
task (defined in tbb::task_list)tbb::task_list [friend]
task_list()tbb::task_list [inline]
~task_list()tbb::task_list [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00142.html b/src/tbb/doc/html/a00142.html new file mode 100644 index 0000000..17fcd35 --- /dev/null +++ b/src/tbb/doc/html/a00142.html @@ -0,0 +1,41 @@ + + +Member List + + + + + + +

tbb::task_scheduler_init Member List

This is the complete list of members for tbb::task_scheduler_init, including all inherited members.

+ + + + + + + + + +
automatictbb::task_scheduler_init [static]
default_num_threads()tbb::task_scheduler_init [static]
deferredtbb::task_scheduler_init [static]
initialize(int number_of_threads=automatic)tbb::task_scheduler_init
initialize(int number_of_threads, stack_size_type thread_stack_size)tbb::task_scheduler_init
is_active() const tbb::task_scheduler_init [inline]
task_scheduler_init(int number_of_threads=automatic, stack_size_type thread_stack_size=0)tbb::task_scheduler_init [inline]
terminate()tbb::task_scheduler_init
~task_scheduler_init()tbb::task_scheduler_init [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00144.html b/src/tbb/doc/html/a00144.html new file mode 100644 index 0000000..d5e415c --- /dev/null +++ b/src/tbb/doc/html/a00144.html @@ -0,0 +1,51 @@ + + +Member List + + + + + + +

tbb::tbb_allocator< T > Member List

This is the complete list of members for tbb::tbb_allocator< T >, including all inherited members.

+ + + + + + + + + + + + + + + + + + + +
address(reference x) const (defined in tbb::tbb_allocator< T >)tbb::tbb_allocator< T > [inline]
address(const_reference x) const (defined in tbb::tbb_allocator< T >)tbb::tbb_allocator< T > [inline]
allocate(size_type n, const void *=0)tbb::tbb_allocator< T > [inline]
const_pointer typedef (defined in tbb::tbb_allocator< T >)tbb::tbb_allocator< T >
const_reference typedef (defined in tbb::tbb_allocator< T >)tbb::tbb_allocator< T >
construct(pointer p, Args &&...args)tbb::tbb_allocator< T > [inline]
deallocate(pointer p, size_type)tbb::tbb_allocator< T > [inline]
difference_type typedef (defined in tbb::tbb_allocator< T >)tbb::tbb_allocator< T >
malloc_type enum nametbb::tbb_allocator< T >
max_size() const tbb::tbb_allocator< T > [inline]
pointer typedef (defined in tbb::tbb_allocator< T >)tbb::tbb_allocator< T >
reference typedef (defined in tbb::tbb_allocator< T >)tbb::tbb_allocator< T >
scalable enum value (defined in tbb::tbb_allocator< T >)tbb::tbb_allocator< T >
size_type typedef (defined in tbb::tbb_allocator< T >)tbb::tbb_allocator< T >
standard enum value (defined in tbb::tbb_allocator< T >)tbb::tbb_allocator< T >
tbb_allocator() (defined in tbb::tbb_allocator< T >)tbb::tbb_allocator< T > [inline]
tbb_allocator(const tbb_allocator &) (defined in tbb::tbb_allocator< T >)tbb::tbb_allocator< T > [inline]
tbb_allocator(const tbb_allocator< U > &) (defined in tbb::tbb_allocator< T >)tbb::tbb_allocator< T > [inline]
value_type typedef (defined in tbb::tbb_allocator< T >)tbb::tbb_allocator< T >


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00146.html b/src/tbb/doc/html/a00146.html new file mode 100644 index 0000000..33b67d9 --- /dev/null +++ b/src/tbb/doc/html/a00146.html @@ -0,0 +1,35 @@ + + +Member List + + + + + + +

tbb::tbb_allocator< void > Member List

This is the complete list of members for tbb::tbb_allocator< void >, including all inherited members.

+ + + +
const_pointer typedef (defined in tbb::tbb_allocator< void >)tbb::tbb_allocator< void >
pointer typedef (defined in tbb::tbb_allocator< void >)tbb::tbb_allocator< void >
value_type typedef (defined in tbb::tbb_allocator< void >)tbb::tbb_allocator< void >


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00148.html b/src/tbb/doc/html/a00148.html new file mode 100644 index 0000000..8749dc9 --- /dev/null +++ b/src/tbb/doc/html/a00148.html @@ -0,0 +1,44 @@ + + +Member List + + + + + + +

tbb::zero_allocator< T, Allocator > Member List

This is the complete list of members for tbb::zero_allocator< T, Allocator >, including all inherited members.

+ + + + + + + + + + + + +
allocate(const size_type n, const void *hint=0) (defined in tbb::zero_allocator< T, Allocator >)tbb::zero_allocator< T, Allocator > [inline]
base_allocator_type typedef (defined in tbb::zero_allocator< T, Allocator >)tbb::zero_allocator< T, Allocator >
const_pointer typedef (defined in tbb::zero_allocator< T, Allocator >)tbb::zero_allocator< T, Allocator >
const_reference typedef (defined in tbb::zero_allocator< T, Allocator >)tbb::zero_allocator< T, Allocator >
difference_type typedef (defined in tbb::zero_allocator< T, Allocator >)tbb::zero_allocator< T, Allocator >
pointer typedef (defined in tbb::zero_allocator< T, Allocator >)tbb::zero_allocator< T, Allocator >
reference typedef (defined in tbb::zero_allocator< T, Allocator >)tbb::zero_allocator< T, Allocator >
size_type typedef (defined in tbb::zero_allocator< T, Allocator >)tbb::zero_allocator< T, Allocator >
value_type typedef (defined in tbb::zero_allocator< T, Allocator >)tbb::zero_allocator< T, Allocator >
zero_allocator() (defined in tbb::zero_allocator< T, Allocator >)tbb::zero_allocator< T, Allocator > [inline]
zero_allocator(const zero_allocator &a) (defined in tbb::zero_allocator< T, Allocator >)tbb::zero_allocator< T, Allocator > [inline]
zero_allocator(const zero_allocator< U > &a) (defined in tbb::zero_allocator< T, Allocator >)tbb::zero_allocator< T, Allocator > [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00150.html b/src/tbb/doc/html/a00150.html new file mode 100644 index 0000000..53d3c66 --- /dev/null +++ b/src/tbb/doc/html/a00150.html @@ -0,0 +1,36 @@ + + +Member List + + + + + + +

tbb::zero_allocator< void, Allocator > Member List

This is the complete list of members for tbb::zero_allocator< void, Allocator >, including all inherited members.

+ + + + +
base_allocator_type typedef (defined in tbb::zero_allocator< void, Allocator >)tbb::zero_allocator< void, Allocator >
const_pointer typedef (defined in tbb::zero_allocator< void, Allocator >)tbb::zero_allocator< void, Allocator >
pointer typedef (defined in tbb::zero_allocator< void, Allocator >)tbb::zero_allocator< void, Allocator >
value_type typedef (defined in tbb::zero_allocator< void, Allocator >)tbb::zero_allocator< void, Allocator >


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00152.html b/src/tbb/doc/html/a00152.html new file mode 100644 index 0000000..fb2070e --- /dev/null +++ b/src/tbb/doc/html/a00152.html @@ -0,0 +1,34 @@ + + +Member List + + + + + + +

tbb::bad_last_alloc Member List

This is the complete list of members for tbb::bad_last_alloc, including all inherited members.

+ + +
what() const (defined in tbb::bad_last_alloc)tbb::bad_last_alloc
~bad_last_alloc() (defined in tbb::bad_last_alloc)tbb::bad_last_alloc [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00153.html b/src/tbb/doc/html/a00153.html new file mode 100644 index 0000000..f5f1d14 --- /dev/null +++ b/src/tbb/doc/html/a00153.html @@ -0,0 +1,33 @@ + + +Member List + + + + + + +

tbb::improper_lock Member List

This is the complete list of members for tbb::improper_lock, including all inherited members.

+ +
what() const (defined in tbb::improper_lock)tbb::improper_lock


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00154.html b/src/tbb/doc/html/a00154.html new file mode 100644 index 0000000..a180181 --- /dev/null +++ b/src/tbb/doc/html/a00154.html @@ -0,0 +1,33 @@ + + +Member List + + + + + + +

tbb::user_abort Member List

This is the complete list of members for tbb::user_abort, including all inherited members.

+ +
what() const (defined in tbb::user_abort)tbb::user_abort


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00155.html b/src/tbb/doc/html/a00155.html new file mode 100644 index 0000000..16a42a3 --- /dev/null +++ b/src/tbb/doc/html/a00155.html @@ -0,0 +1,33 @@ + + +Member List + + + + + + +

tbb::missing_wait Member List

This is the complete list of members for tbb::missing_wait, including all inherited members.

+ +
what() const (defined in tbb::missing_wait)tbb::missing_wait


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00156.html b/src/tbb/doc/html/a00156.html new file mode 100644 index 0000000..2de2c80 --- /dev/null +++ b/src/tbb/doc/html/a00156.html @@ -0,0 +1,33 @@ + + +Member List + + + + + + +

tbb::invalid_multiple_scheduling Member List

This is the complete list of members for tbb::invalid_multiple_scheduling, including all inherited members.

+ +
what() const (defined in tbb::invalid_multiple_scheduling)tbb::invalid_multiple_scheduling


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00157.html b/src/tbb/doc/html/a00157.html new file mode 100644 index 0000000..2376ebd --- /dev/null +++ b/src/tbb/doc/html/a00157.html @@ -0,0 +1,38 @@ + + +Member List + + + + + + +

tbb::tbb_exception Member List

This is the complete list of members for tbb::tbb_exception, including all inherited members.

+ + + + + + +
destroy()=0tbb::tbb_exception [pure virtual]
move()=0tbb::tbb_exception [pure virtual]
name() const =0tbb::tbb_exception [pure virtual]
operator delete(void *p)tbb::tbb_exception [inline]
throw_self()=0tbb::tbb_exception [pure virtual]
what() const =0tbb::tbb_exception [pure virtual]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00158.html b/src/tbb/doc/html/a00158.html new file mode 100644 index 0000000..7799031 --- /dev/null +++ b/src/tbb/doc/html/a00158.html @@ -0,0 +1,44 @@ + + +Member List + + + + + + +

tbb::captured_exception Member List

This is the complete list of members for tbb::captured_exception, including all inherited members.

+ + + + + + + + + + + + +
captured_exception(const captured_exception &src) (defined in tbb::captured_exception)tbb::captured_exception [inline]
captured_exception(const char *name_, const char *info) (defined in tbb::captured_exception)tbb::captured_exception [inline]
clear() (defined in tbb::captured_exception)tbb::captured_exception
destroy()tbb::captured_exception [virtual]
move()tbb::captured_exception [virtual]
name() const tbb::captured_exception [virtual]
operator delete(void *p)tbb::tbb_exception [inline]
operator=(const captured_exception &src) (defined in tbb::captured_exception)tbb::captured_exception [inline]
set(const char *name, const char *info) (defined in tbb::captured_exception)tbb::captured_exception
throw_self()tbb::captured_exception [inline, virtual]
what() const tbb::captured_exception [virtual]
~captured_exception() (defined in tbb::captured_exception)tbb::captured_exception


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00159.html b/src/tbb/doc/html/a00159.html new file mode 100644 index 0000000..e9cf7cf --- /dev/null +++ b/src/tbb/doc/html/a00159.html @@ -0,0 +1,45 @@ + + +Member List + + + + + + +

tbb::movable_exception< ExceptionData > Member List

This is the complete list of members for tbb::movable_exception< ExceptionData >, including all inherited members.

+ + + + + + + + + + + + + +
data() (defined in tbb::movable_exception< ExceptionData >)tbb::movable_exception< ExceptionData > [inline]
data() const (defined in tbb::movable_exception< ExceptionData >)tbb::movable_exception< ExceptionData > [inline]
destroy()tbb::movable_exception< ExceptionData > [inline, virtual]
movable_exception(const ExceptionData &data_) (defined in tbb::movable_exception< ExceptionData >)tbb::movable_exception< ExceptionData > [inline]
movable_exception(const movable_exception &src) (defined in tbb::movable_exception< ExceptionData >)tbb::movable_exception< ExceptionData > [inline]
move()tbb::movable_exception< ExceptionData > [inline, virtual]
my_exception_datatbb::movable_exception< ExceptionData > [protected]
name() const tbb::movable_exception< ExceptionData > [inline, virtual]
operator delete(void *p)tbb::tbb_exception [inline]
operator=(const movable_exception &src) (defined in tbb::movable_exception< ExceptionData >)tbb::movable_exception< ExceptionData > [inline]
throw_self()tbb::movable_exception< ExceptionData > [inline, virtual]
what() const tbb::movable_exception< ExceptionData > [inline, virtual]
~movable_exception() (defined in tbb::movable_exception< ExceptionData >)tbb::movable_exception< ExceptionData > [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00160.html b/src/tbb/doc/html/a00160.html new file mode 100644 index 0000000..689f460 --- /dev/null +++ b/src/tbb/doc/html/a00160.html @@ -0,0 +1,37 @@ + + +Member List + + + + + + +

tbb::internal::tbb_exception_ptr Member List

This is the complete list of members for tbb::internal::tbb_exception_ptr, including all inherited members.

+ + + + + +
allocate() (defined in tbb::internal::tbb_exception_ptr)tbb::internal::tbb_exception_ptr [static]
allocate(const tbb_exception &tag) (defined in tbb::internal::tbb_exception_ptr)tbb::internal::tbb_exception_ptr [static]
allocate(captured_exception &src)tbb::internal::tbb_exception_ptr [static]
destroy()tbb::internal::tbb_exception_ptr
throw_self()tbb::internal::tbb_exception_ptr [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00165.html b/src/tbb/doc/html/a00165.html new file mode 100644 index 0000000..85205fc --- /dev/null +++ b/src/tbb/doc/html/a00165.html @@ -0,0 +1,36 @@ + + +Member List + + + + + + +

tbb::internal::atomic_backoff Member List

This is the complete list of members for tbb::internal::atomic_backoff, including all inherited members.

+ + + + +
atomic_backoff() (defined in tbb::internal::atomic_backoff)tbb::internal::atomic_backoff [inline]
bounded_pause() (defined in tbb::internal::atomic_backoff)tbb::internal::atomic_backoff [inline]
pause()tbb::internal::atomic_backoff [inline]
reset() (defined in tbb::internal::atomic_backoff)tbb::internal::atomic_backoff [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00169.html b/src/tbb/doc/html/a00169.html new file mode 100644 index 0000000..ebb7c32 --- /dev/null +++ b/src/tbb/doc/html/a00169.html @@ -0,0 +1,34 @@ + + +Member List + + + + + + +

tbb::internal::machine_load_store_seq_cst< T, 8 > Member List

This is the complete list of members for tbb::internal::machine_load_store_seq_cst< T, 8 >, including all inherited members.

+ + +
load(const volatile T &location) (defined in tbb::internal::machine_load_store_seq_cst< T, 8 >)tbb::internal::machine_load_store_seq_cst< T, 8 > [inline, static]
store(volatile T &location, T value) (defined in tbb::internal::machine_load_store_seq_cst< T, 8 >)tbb::internal::machine_load_store_seq_cst< T, 8 > [inline, static]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00170.html b/src/tbb/doc/html/a00170.html new file mode 100644 index 0000000..cf23eda --- /dev/null +++ b/src/tbb/doc/html/a00170.html @@ -0,0 +1,34 @@ + + +Member List + + + + + + +

tbb::internal::machine_load_store_relaxed< T, S > Member List

This is the complete list of members for tbb::internal::machine_load_store_relaxed< T, S >, including all inherited members.

+ + +
load(const volatile T &location) (defined in tbb::internal::machine_load_store_relaxed< T, S >)tbb::internal::machine_load_store_relaxed< T, S > [inline, static]
store(volatile T &location, T value) (defined in tbb::internal::machine_load_store_relaxed< T, S >)tbb::internal::machine_load_store_relaxed< T, S > [inline, static]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00179.html b/src/tbb/doc/html/a00179.html new file mode 100644 index 0000000..36a0907 --- /dev/null +++ b/src/tbb/doc/html/a00179.html @@ -0,0 +1,33 @@ + + +Member List + + + + + + +

tbb::internal::work_around_alignment_bug< Size, T > Member List

This is the complete list of members for tbb::internal::work_around_alignment_bug< Size, T >, including all inherited members.

+ +
alignment (defined in tbb::internal::work_around_alignment_bug< Size, T >)tbb::internal::work_around_alignment_bug< Size, T > [static]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00183.html b/src/tbb/doc/html/a00183.html new file mode 100644 index 0000000..ee5ff29 --- /dev/null +++ b/src/tbb/doc/html/a00183.html @@ -0,0 +1,35 @@ + + +Member List + + + + + + +

tbb::tick_count Member List

This is the complete list of members for tbb::tick_count, including all inherited members.

+ + + +
now()tbb::tick_count [inline, static]
operator-(const tick_count &t1, const tick_count &t0)tbb::tick_count [friend]
tick_count()tbb::tick_count [inline]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00184.html b/src/tbb/doc/html/a00184.html new file mode 100644 index 0000000..e402627 --- /dev/null +++ b/src/tbb/doc/html/a00184.html @@ -0,0 +1,41 @@ + + +Member List + + + + + + +

tbb::tick_count::interval_t Member List

This is the complete list of members for tbb::tick_count::interval_t, including all inherited members.

+ + + + + + + + + +
interval_t()tbb::tick_count::interval_t [inline]
interval_t(double sec)tbb::tick_count::interval_t [inline, explicit]
operator+(const interval_t &i, const interval_t &j)tbb::tick_count::interval_t [friend]
operator+=(const interval_t &i)tbb::tick_count::interval_t [inline]
operator-(const tick_count &t1, const tick_count &t0)tbb::tick_count::interval_t [friend]
operator-(const interval_t &i, const interval_t &j)tbb::tick_count::interval_t [friend]
operator-=(const interval_t &i)tbb::tick_count::interval_t [inline]
seconds() const tbb::tick_count::interval_t [inline]
tbb::tick_count (defined in tbb::tick_count::interval_t)tbb::tick_count::interval_t [friend]


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00249.html b/src/tbb/doc/html/a00249.html new file mode 100644 index 0000000..efaa794 --- /dev/null +++ b/src/tbb/doc/html/a00249.html @@ -0,0 +1,64 @@ + + +tbb::affinity_partitioner Class Reference + + + + + + + +

tbb::affinity_partitioner Class Reference

An affinity partitioner. +More... +

+#include <partitioner.h> +

+

Inheritance diagram for tbb::affinity_partitioner: +

+ +tbb::internal::affinity_partitioner_base_v3 + +List of all members. + + + + + + + + + + +

Friends

+class serial::interface6::start_for
+class interface6::internal::start_for
+class interface6::internal::start_reduce
+class internal::start_scan
+

Detailed Description

+An affinity partitioner. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00249.png b/src/tbb/doc/html/a00249.png new file mode 100644 index 0000000000000000000000000000000000000000..31d2cc35eedac0f0cd433104693908f80e41e139 GIT binary patch literal 674 zcmV;T0$u%yP)coMfJefl$@Fcc=_{D%^9El7>;p-Y zM762%Wq<*_8uJNhiI>+>&yJY525$7H)xOPH0k4_sV3L^$j6@i`*J8Qnl#tjEi^o2v ziG)&@OvRi;p1~%niOr%eE-z}yQ>_>osE1X0{?lPTM9OBGs$9KtN#Zah(Ux#}}sIqF})v;i&^FQ2ir9k|@;GDB~5J}9rI^c9R{n{;c% zjZ`?S|>1E(K>$G{Kvy-zj&4uMP$$O`8o4p!!cc?WtlP80vTpykZ^&J9Lg= znBE}pTmJZ|1vv=`B23P)BPK$#j)R%PHDfwNm*#?6;7awVkz&fYTBpEMMO5(AgHx9{ zeR^uV37r1Rbzt3CERHO}$$AgiEh=^u?A9v&?W+Cp8E=De1AOwR%dM7ad}ljwdGLCL z#f0=BN6^!UbKqBkuHCQWV3)qiVLTXS-9Ye3-QX*Lt$yDA0I4FO>u=9aH2?qr07*qo IM6N<$f_u+9i~s-t literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/a00250.html b/src/tbb/doc/html/a00250.html new file mode 100644 index 0000000..287624f --- /dev/null +++ b/src/tbb/doc/html/a00250.html @@ -0,0 +1,58 @@ + + +tbb::internal::affinity_partitioner_base_v3 Class Reference + + + + + + + +

tbb::internal::affinity_partitioner_base_v3 Class Reference

Defines entry point for affinity partitioner into tbb run-time library. +More... +

+#include <partitioner.h> +

+

Inheritance diagram for tbb::internal::affinity_partitioner_base_v3: +

+ +tbb::affinity_partitioner + +List of all members. + + + + + + +

Friends

+class tbb::affinity_partitioner
+class tbb::interface6::internal::affinity_partition_type
+

Detailed Description

+Defines entry point for affinity partitioner into tbb run-time library. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00250.png b/src/tbb/doc/html/a00250.png new file mode 100644 index 0000000000000000000000000000000000000000..18c7d5848b0aef71c5ba04b26782303f3cfb6f90 GIT binary patch literal 671 zcmV;Q0$}}#P)@)7fjj+Sw(ny$z+2`vm>LsAaNcXN+;d7GHpJpXM-- zNt6+6LQQmwhPZsGC*ON-MCb=fGdrt}Srx=cQ`VscYXb)Hl! zF7bA%WnO=ekH`=0vH1tVQVH-3Eb)EgDA+H$LknE;*Xa$O12+46dq(Ls)&D=>kNefY z_j|e+*iOkhf$2)t2~1bAPGGu{bpq3stP_~7WSzitCF=yHD_JKnUCBCu=}OiKOjoi_ zV7iiZ0@IbwO#U{K`?{Iv^9{Z_I7DgMZ45Dl<}Ve+3=j5ez@c4lfj7*f;D{I*hJ1s- zx8Pi|6-p8kM7YJsj+hADIu2$E*NnW0Q8rUPF_c}+U}&V8a^0*`;9Em9@NER=E_258 z)OZmXSb}w7u{g2@XX`cKxT-idaNMf+x1;vQXS@%_4*29&*HbO4@tGaK^}*{A7Bl3R z96@(KoC7~o7}|f=ad4F5hA + +tbb::interface6::aggregator Class Reference + + + + + + + +

tbb::interface6::aggregator Class Reference

Basic aggregator interface. +More... +

+#include <aggregator.h> +

+

Inheritance diagram for tbb::interface6::aggregator: +

+ +tbb::interface6::aggregator_ext< handler_type > + +List of all members. + + + + + + +

Public Member Functions

template<typename Body>
void execute (const Body &b)
 BASIC INTERFACE: Enter a function for exclusvie execution by the aggregator.
+

Detailed Description

+Basic aggregator interface. +

+


Member Function Documentation

+ +
+
+
+template<typename Body>
+ + + + + + + + + +
void tbb::interface6::aggregator::execute (const Body &  b  )  [inline]
+
+
+ +

+BASIC INTERFACE: Enter a function for exclusvie execution by the aggregator. +

+The calling thread stores the function object in a basic_operation and places the operation in the aggregator's mailbox +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00251.png b/src/tbb/doc/html/a00251.png new file mode 100644 index 0000000000000000000000000000000000000000..123e10d27781ec7a0bff853e60cd3613b1a9e61b GIT binary patch literal 792 zcmeAS@N?(olHy`uVBq!ia0y~yV3Y*116Y`WEaktG3V{{z@pa*Jg$k)bQv}>M>sCK z%OHRA|12#P#!bn89!=w^`LQgSRq^C;raPTK<2?93i(bFzd-=NWW$}wGFFvZ3rH*9dyt7k@MXVl-H%zbl{$?a6%{`3lQ=a&?b3|)1HmZ? z!eMt=o{RSC-&>JYEU{im^;+5Wp9i=jj89E!N(;8M(#d(}ebH8m!H>C#BV~nEy|7pz z^NZUI0=$Q>{Pa!SIZ@sG!^aaJ@7{Cy`o-k1$*V@E!uRsKzN}h1`=8+ zv(6e5>4e0kHyOCK&$2~CWSSi~ + +tbb::interface6::aggregator_ext< handler_type > Class Template Reference + + + + + + + +

tbb::interface6::aggregator_ext< handler_type > Class Template Reference

Aggregator base class and expert interface. +More... +

+#include <aggregator.h> +

+

Inheritance diagram for tbb::interface6::aggregator_ext< handler_type >: +

+ +tbb::interface6::aggregator + +List of all members. + + + + + + + + + + +

Public Member Functions

aggregator_ext (const handler_type &h)
void process (aggregator_operation *op)
 EXPERT INTERFACE: Enter a user-made operation into the aggregator's mailbox.

Protected Member Functions

void execute_impl (aggregator_operation &op)
+

Detailed Description

+

template<typename handler_type>
+ class tbb::interface6::aggregator_ext< handler_type >

+ +Aggregator base class and expert interface. +

+An aggregator for collecting operations coming from multiple sources and executing them serially on a single thread. +

+


Member Function Documentation

+ +
+
+
+template<typename handler_type>
+ + + + + + + + + +
void tbb::interface6::aggregator_ext< handler_type >::execute_impl (aggregator_operation &  op  )  [inline, protected]
+
+
+ +

+Place operation in mailbox, then either handle mailbox or wait for the operation to be completed by a different thread. +

+

+ +

+
+
+template<typename handler_type>
+ + + + + + + + + +
void tbb::interface6::aggregator_ext< handler_type >::process (aggregator_operation *  op  )  [inline]
+
+
+ +

+EXPERT INTERFACE: Enter a user-made operation into the aggregator's mailbox. +

+Details of user-made operations must be handled by user-provided handler +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00252.png b/src/tbb/doc/html/a00252.png new file mode 100644 index 0000000000000000000000000000000000000000..0f01bcf85ce9b466ee90e0d3febf13086eb3aabd GIT binary patch literal 787 zcmeAS@N?(olHy`uVBq!ia0y~yV3Y*116Y`WEaktG3V{{i-k`Vc-j)5aXFMEXq~uY zdf@Q4_{*H04LSOLn-ZJl{^YYYO*oRyc<)G~BCGfu*}EpmKqT1v+>K|eW8zhoxFK%Yo(H#& zZT}gY6sa*m@<)}(|HRxmRaLVRrM^1so7K-Bn|<}W@AYG*+YgwmJ1BGRZ07QkMSjZ9 zm+|*mA64I~cVW_jlW$+{Tv@(KE@7YImSDvbb3c`Iom41a6~95qU+}Nr&#L7XZM&+L zS2%nBf8$phz5Dv*)B45rUA3*txs)ug^EmayTt^_VL7UWsRGQ443VZI4BtzXpyeoY2`pYlw+-ljjT2%d#L(hb5y{DUO zr!gu?ZP2t8>E9J+=&~i>;y#;h5*zO_*RBrLTT%V;dES95npK3KFd4~by9*X)q`0o~ zJ?+bO)0OF-wfVIx%J*ED58P~2FniU}Rxd1OIQ`vP6U~*&mrE|Y`E9Fbu6+8X6FWVR z&%N|~+2s>EUpDVF`RaF-`HXo>nU>qmVClI@MknUJ5?^y9_z2Ie{Os>lzh13==4bP0l+XkKE8}Sn literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/a00253.html b/src/tbb/doc/html/a00253.html new file mode 100644 index 0000000..2e7bd94 --- /dev/null +++ b/src/tbb/doc/html/a00253.html @@ -0,0 +1,63 @@ + + +tbb::aligned_space< T, N > Class Template Reference + + + + + + + +

tbb::aligned_space< T, N > Class Template Reference
+ +[Memory Allocation] +

Block of space aligned sufficiently to construct an array T with N elements. +More... +

+#include <aligned_space.h> +

+List of all members. + + + + + + + + +

Public Member Functions

+T * begin ()
 Pointer to beginning of array.
+T * end ()
 Pointer to one past last element in array.
+


Detailed Description

+

template<typename T, size_t N>
+ class tbb::aligned_space< T, N >

+ +Block of space aligned sufficiently to construct an array T with N elements. +

+The elements are not constructed or destroyed by this class. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00254.html b/src/tbb/doc/html/a00254.html new file mode 100644 index 0000000..5acb7a9 --- /dev/null +++ b/src/tbb/doc/html/a00254.html @@ -0,0 +1,61 @@ + + +tbb::atomic< T > Struct Template Reference + + + + + + + +

tbb::atomic< T > Struct Template Reference
+ +[Synchronization] +

Primary template for atomic. +More... +

+#include <atomic.h> +

+List of all members. + + + + + + +

Public Member Functions

+T operator= (T rhs)
+atomic< T > & operator= (const atomic< T > &rhs)
+


Detailed Description

+

template<typename T>
+ struct tbb::atomic< T >

+ +Primary template for atomic. +

+See the Reference for details. +

+


The documentation for this struct was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00255.html b/src/tbb/doc/html/a00255.html new file mode 100644 index 0000000..6b2eece --- /dev/null +++ b/src/tbb/doc/html/a00255.html @@ -0,0 +1,56 @@ + + +tbb::atomic< void * > Struct Template Reference + + + + + + + +

tbb::atomic< void * > Struct Template Reference

Specialization for atomic<void*>, for sake of not allowing arithmetic or operator->. +More... +

+#include <atomic.h> +

+List of all members. + + + + + + +

Public Member Functions

+void * operator= (void *rhs)
+atomic< void * > & operator= (const atomic< void * > &rhs)
+


Detailed Description

+

template<>
+ struct tbb::atomic< void * >

+ +Specialization for atomic<void*>, for sake of not allowing arithmetic or operator->. +

+


The documentation for this struct was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00256.html b/src/tbb/doc/html/a00256.html new file mode 100644 index 0000000..bd57357 --- /dev/null +++ b/src/tbb/doc/html/a00256.html @@ -0,0 +1,59 @@ + + +tbb::internal::atomic_backoff Class Reference + + + + + + + +

tbb::internal::atomic_backoff Class Reference

Class that implements exponential backoff. +More... +

+#include <tbb_machine.h> +

+List of all members. + + + + + + + + + +

Public Member Functions

+void pause ()
 Pause for a while.
+bool bounded_pause ()
+void reset ()
+


Detailed Description

+Class that implements exponential backoff. +

+See implementation of spin_wait_while_eq for an example. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00257.html b/src/tbb/doc/html/a00257.html new file mode 100644 index 0000000..ad7e043 --- /dev/null +++ b/src/tbb/doc/html/a00257.html @@ -0,0 +1,64 @@ + + +tbb::auto_partitioner Class Reference + + + + + + + +

tbb::auto_partitioner Class Reference
+ +[Algorithms] +

An auto partitioner. +More... +

+#include <partitioner.h> +

+List of all members. + + + + + + + + + + +

Friends

+class serial::interface6::start_for
+class interface6::internal::start_for
+class interface6::internal::start_reduce
+class internal::start_scan
+


Detailed Description

+An auto partitioner. +

+The range is initial divided into several large chunks. Chunks are further subdivided into smaller pieces if demand detected and they are divisible. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00258.html b/src/tbb/doc/html/a00258.html new file mode 100644 index 0000000..86ac2f2 --- /dev/null +++ b/src/tbb/doc/html/a00258.html @@ -0,0 +1,50 @@ + + +tbb::bad_last_alloc Class Reference + + + + + + + +

tbb::bad_last_alloc Class Reference

Exception for concurrent containers. +More... +

+#include <tbb_exception.h> +

+List of all members. + + + + +

Public Member Functions

+const char * what () const throw ()
+


Detailed Description

+Exception for concurrent containers. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00259.html b/src/tbb/doc/html/a00259.html new file mode 100644 index 0000000..84c752a --- /dev/null +++ b/src/tbb/doc/html/a00259.html @@ -0,0 +1,224 @@ + + +tbb::blocked_range< Value > Class Template Reference + + + + + + + +

tbb::blocked_range< Value > Class Template Reference
+ +[Algorithms] +

A range over which to iterate. +More... +

+#include <blocked_range.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

typedef Value const_iterator
 Type of a value.
+typedef std::size_t size_type
 Type for size of a range.

Public Member Functions

 blocked_range ()
 Construct range with default-constructed values for begin and end.
blocked_range (Value begin_, Value end_, size_type grainsize_=1)
 Construct range over half-open interval [begin,end), with the given grainsize.
+const_iterator begin () const
 Beginning of range.
+const_iterator end () const
 One past last value in range.
size_type size () const
 Size of the range.
+size_type grainsize () const
 The grain size for this range.
+bool empty () const
 True if range is empty.
bool is_divisible () const
 True if range is divisible.
 blocked_range (blocked_range &r, split)
 Split range.

Friends

+class blocked_range2d
+class blocked_range3d
+


Detailed Description

+

template<typename Value>
+ class tbb::blocked_range< Value >

+ +A range over which to iterate. +

+


Member Typedef Documentation

+ +
+
+
+template<typename Value>
+ + + + +
typedef Value tbb::blocked_range< Value >::const_iterator
+
+
+ +

+Type of a value. +

+Called a const_iterator for sake of algorithms that need to treat a blocked_range as an STL container. +

+

+


Constructor & Destructor Documentation

+ +
+
+
+template<typename Value>
+ + + + + + + + +
tbb::blocked_range< Value >::blocked_range (  )  [inline]
+
+
+ +

+Construct range with default-constructed values for begin and end. +

+Requires that Value have a default constructor. +

+

+ +

+
+
+template<typename Value>
+ + + + + + + + + + + + + + + + + + +
tbb::blocked_range< Value >::blocked_range (blocked_range< Value > &  r,
split  
) [inline]
+
+
+ +

+Split range. +

+The new Range *this has the second half, the old range r has the first half. Unspecified if end()<begin() or !is_divisible(). +

+

+


Member Function Documentation

+ +
+
+
+template<typename Value>
+ + + + + + + + +
bool tbb::blocked_range< Value >::is_divisible (  )  const [inline]
+
+
+ +

+True if range is divisible. +

+Unspecified if end()<begin(). +

+

+ +

+
+
+template<typename Value>
+ + + + + + + + +
size_type tbb::blocked_range< Value >::size (  )  const [inline]
+
+
+ +

+Size of the range. +

+Unspecified if end()<begin(). +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00260.html b/src/tbb/doc/html/a00260.html new file mode 100644 index 0000000..330e299 --- /dev/null +++ b/src/tbb/doc/html/a00260.html @@ -0,0 +1,86 @@ + + +tbb::blocked_range2d< RowValue, ColValue > Class Template Reference + + + + + + + +

tbb::blocked_range2d< RowValue, ColValue > Class Template Reference
+ +[Algorithms] +

A 2-dimensional range that models the Range concept. +More... +

+#include <blocked_range2d.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef blocked_range< RowValue > row_range_type
 Type for size of an iteration range.
+typedef blocked_range< ColValue > col_range_type

Public Member Functions

blocked_range2d (RowValue row_begin, RowValue row_end, typename row_range_type::size_type row_grainsize, ColValue col_begin, ColValue col_end, typename col_range_type::size_type col_grainsize)
blocked_range2d (RowValue row_begin, RowValue row_end, ColValue col_begin, ColValue col_end)
+bool empty () const
 True if range is empty.
+bool is_divisible () const
 True if range is divisible into two pieces.
blocked_range2d (blocked_range2d &r, split)
+const row_range_typerows () const
 The rows of the iteration space.
+const col_range_typecols () const
 The columns of the iteration space.
+


Detailed Description

+

template<typename RowValue, typename ColValue = RowValue>
+ class tbb::blocked_range2d< RowValue, ColValue >

+ +A 2-dimensional range that models the Range concept. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00261.html b/src/tbb/doc/html/a00261.html new file mode 100644 index 0000000..b72441d --- /dev/null +++ b/src/tbb/doc/html/a00261.html @@ -0,0 +1,93 @@ + + +tbb::blocked_range3d< PageValue, RowValue, ColValue > Class Template Reference + + + + + + + +

tbb::blocked_range3d< PageValue, RowValue, ColValue > Class Template Reference
+ +[Algorithms] +

A 3-dimensional range that models the Range concept. +More... +

+#include <blocked_range3d.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef blocked_range< PageValue > page_range_type
 Type for size of an iteration range.
+typedef blocked_range< RowValue > row_range_type
+typedef blocked_range< ColValue > col_range_type

Public Member Functions

blocked_range3d (PageValue page_begin, PageValue page_end, RowValue row_begin, RowValue row_end, ColValue col_begin, ColValue col_end)
blocked_range3d (PageValue page_begin, PageValue page_end, typename page_range_type::size_type page_grainsize, RowValue row_begin, RowValue row_end, typename row_range_type::size_type row_grainsize, ColValue col_begin, ColValue col_end, typename col_range_type::size_type col_grainsize)
+bool empty () const
 True if range is empty.
+bool is_divisible () const
 True if range is divisible into two pieces.
blocked_range3d (blocked_range3d &r, split)
+const page_range_typepages () const
 The pages of the iteration space.
+const row_range_typerows () const
 The rows of the iteration space.
+const col_range_typecols () const
 The columns of the iteration space.
+


Detailed Description

+

template<typename PageValue, typename RowValue = PageValue, typename ColValue = RowValue>
+ class tbb::blocked_range3d< PageValue, RowValue, ColValue >

+ +A 3-dimensional range that models the Range concept. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00262.html b/src/tbb/doc/html/a00262.html new file mode 100644 index 0000000..c4b0dd8 --- /dev/null +++ b/src/tbb/doc/html/a00262.html @@ -0,0 +1,92 @@ + + +tbb::flow::interface6::broadcast_node< T > Class Template Reference + + + + + + + +

tbb::flow::interface6::broadcast_node< T > Class Template Reference

Forwards messages of type T to all successors. +More... +

+#include <flow_graph.h> +

+

Inheritance diagram for tbb::flow::interface6::broadcast_node< T >: +

+ +tbb::flow::interface6::graph_node +tbb::flow::interface6::receiver< T > +tbb::flow::interface6::sender< T > + +List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef T input_type
 The input type of this receiver.
+typedef T output_type
 The output type of this sender.
+typedef sender< input_typepredecessor_type
 The predecessor type for this node.
+typedef receiver< output_typesuccessor_type
 The successor type for this node.

Public Member Functions

broadcast_node (graph &g)
broadcast_node (const broadcast_node &src)
+virtual bool register_successor (receiver< T > &r)
 Adds a successor.
+virtual bool remove_successor (receiver< T > &r)
 Removes s as a successor.
+bool try_put (const T &t)
 Put an item to the receiver.
+

Detailed Description

+

template<typename T>
+ class tbb::flow::interface6::broadcast_node< T >

+ +Forwards messages of type T to all successors. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00262.png b/src/tbb/doc/html/a00262.png new file mode 100644 index 0000000000000000000000000000000000000000..5a7b1d592e7c8597c00916282b5785e8de117ee7 GIT binary patch literal 1270 zcma)+e^AnQ7{@>O1#BwX$}%gAnwrTdo8?SX@n;HZ{CjrC zDXy8?VPc9#v-+A#O;RL%-Ui`Q*8E3iY390|wL2jNX=4tw9<&*xe;Bn8~V4sdnboRY5o zx-g@8Fx6gj&-bYX*`ha>G6ORfB%=*RPA3$bAu%QwqJ!+?z#K+&U^zT(eKn$v-}rO7 zlcnNvsR*Ce{3GBb6CIPDL_Qk8T(EPpN5^iqm{KWsfu;|K`W#-Dgz~pSu>XWcLHg5O zyJP~a?p(cg>m93ZdZ7u*nJAP_?y@QY%f-USyAKLshZgtq>!ju7$%l&e*=W(JFNRGw z)g9_`^HM#$NS6e!2DtX_^eYLJPe0v39T&2|&V)p_*eoqKK0La(3k#~|YV1`PX`Hd+ zQfuOeyCcwAqw&W(&`b)U;R%=gU4(|AjFA9p^n9RWCv__!7VL1BFxqSll~1V{u@NRew_WO#Y5{=ip1l z>kzy9vH-MPgpRrWZ%WUw4zE@y?NZLaU0E;=S!h^ zuy%8r%4$yz&XhDmZ5!#Jd!y_A61_Uv1C{Qp03u%swNg7(D2Bx5xs4wcAidGp*pPAs z@#;>*NSuW^EN9X|oBRwUme{O^AElVW2j=mLu4%yge^kXFefL`|VJ*Fe=Er*xYx@7? zd|v57xXj7l?rh?UZZa8}(V?bMrGXEpG)nLQK|J7R_fg=RICf+bP07ouYtq+l3h7%z zCZ0O%lN+AO;4iC-h~Ss{@TR>pg`{)%2=D$2aec-0QhRAbFCzE`UYL(Px-o2F%e)y! zCa_kQX>=%WQWAA^fRu!BKFU8>>zG0cqJwWo^A3+k*Ye}NC%<{0EQf(9uFfk$+X2+3EXyJxwa~jCL;t6 zHowRt!L + +tbb::flow::interface6::buffer_node< T, A > Class Template Reference + + + + + + + +

tbb::flow::interface6::buffer_node< T, A > Class Template Reference

Forwards messages in arbitrary order. +More... +

+#include <flow_graph.h> +

+

Inheritance diagram for tbb::flow::interface6::buffer_node< T, A >: +

+ +tbb::flow::interface6::graph_node +tbb::flow::interface6::receiver< T > +tbb::flow::interface6::sender< T > +tbb::flow::interface6::priority_queue_node< T, Compare, A > +tbb::flow::interface6::queue_node< T, A > +tbb::flow::interface6::sequencer_node< T, A > + +List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef T input_type
 The input type of this receiver.
+typedef T output_type
 The output type of this sender.
+typedef sender< input_typepredecessor_type
 The predecessor type for this node.
+typedef receiver< output_typesuccessor_type
 The successor type for this node.
+typedef buffer_node< T, A > my_class

Public Member Functions

buffer_node (graph &g)
 Constructor.
buffer_node (const buffer_node &src)
 Copy constructor.
bool register_successor (receiver< output_type > &r)
 Adds a new successor.
bool remove_successor (receiver< output_type > &r)
 Removes a successor.
bool try_get (T &v)
 Request an item from the buffer_node.
bool try_reserve (T &v)
 Reserves an item.
bool try_release ()
 Release a reserved item.
bool try_consume ()
 Consumes a reserved item.
bool try_put (const T &t)
 Receive an item.

Protected Types

+typedef size_t size_type
+typedef internal::aggregating_functor<
+ my_class, buffer_operation > 
my_handler
reg_succ
rem_succ
req_item
res_item
rel_res
con_res
put_item
try_fwd
WAIT = 0
SUCCEEDED
FAILED
enum  op_type {
+  reg_succ, +rem_succ, +req_item, +res_item, +
+  rel_res, +con_res, +put_item, +try_fwd +
+ }
enum  op_stat { WAIT = 0, +SUCCEEDED, +FAILED + }

Protected Member Functions

+virtual void handle_operations (buffer_operation *op_list)
+virtual void forward ()
 This is executed by an enqueued task, the "forwarder".
+virtual void internal_reg_succ (buffer_operation *op)
 Register successor.
+virtual void internal_rem_succ (buffer_operation *op)
 Remove successor.
+virtual void internal_forward (buffer_operation *op)
 Tries to forward valid items to successors.
+virtual void internal_push (buffer_operation *op)
+virtual void internal_pop (buffer_operation *op)
+virtual void internal_reserve (buffer_operation *op)
+virtual void internal_consume (buffer_operation *op)
+virtual void internal_release (buffer_operation *op)

Protected Attributes

+internal::round_robin_cache<
+ T, null_rw_mutex
my_successors
+taskmy_parent
+bool forwarder_busy
+internal::aggregator< my_handler,
+ buffer_operation > 
my_aggregator

Friends

+class internal::forward_task< buffer_node< T, A > >
+class internal::aggregating_functor< my_class, buffer_operation >

Classes

class  buffer_operation
+

Detailed Description

+

template<typename T, typename A = cache_aligned_allocator<T>>
+ class tbb::flow::interface6::buffer_node< T, A >

+ +Forwards messages in arbitrary order. +

+


Member Function Documentation

+ +
+
+
+template<typename T, typename A = cache_aligned_allocator<T>>
+ + + + + + + + + +
bool tbb::flow::interface6::buffer_node< T, A >::register_successor (receiver< output_type > &  r  )  [inline, virtual]
+
+
+ +

+Adds a new successor. +

+Adds successor r to the list of successors; may forward tasks. +

+Implements tbb::flow::interface6::sender< T >. +

+

+ +

+
+
+template<typename T, typename A = cache_aligned_allocator<T>>
+ + + + + + + + + +
bool tbb::flow::interface6::buffer_node< T, A >::remove_successor (receiver< output_type > &  r  )  [inline, virtual]
+
+
+ +

+Removes a successor. +

+Removes successor r from the list of successors. It also calls r.remove_predecessor(*this) to remove this node as a predecessor. +

+Implements tbb::flow::interface6::sender< T >. +

+

+ +

+
+
+template<typename T, typename A = cache_aligned_allocator<T>>
+ + + + + + + + +
bool tbb::flow::interface6::buffer_node< T, A >::try_consume (  )  [inline, virtual]
+
+
+ +

+Consumes a reserved item. +

+true = item is removed from sender and reservation removed +

+Reimplemented from tbb::flow::interface6::sender< T >. +

+

+ +

+
+
+template<typename T, typename A = cache_aligned_allocator<T>>
+ + + + + + + + + +
bool tbb::flow::interface6::buffer_node< T, A >::try_get (T &  v  )  [inline, virtual]
+
+
+ +

+Request an item from the buffer_node. +

+true = v contains the returned item
+ false = no item has been returned +

+Reimplemented from tbb::flow::interface6::sender< T >. +

+

+ +

+
+
+template<typename T, typename A = cache_aligned_allocator<T>>
+ + + + + + + + + +
bool tbb::flow::interface6::buffer_node< T, A >::try_put (const T &  t  )  [inline, virtual]
+
+
+ +

+Receive an item. +

+true is always returned +

+Implements tbb::flow::interface6::receiver< T >. +

+

+ +

+
+
+template<typename T, typename A = cache_aligned_allocator<T>>
+ + + + + + + + +
bool tbb::flow::interface6::buffer_node< T, A >::try_release (  )  [inline, virtual]
+
+
+ +

+Release a reserved item. +

+true = item has been released and so remains in sender +

+Reimplemented from tbb::flow::interface6::sender< T >. +

+

+ +

+
+
+template<typename T, typename A = cache_aligned_allocator<T>>
+ + + + + + + + + +
bool tbb::flow::interface6::buffer_node< T, A >::try_reserve (T &  v  )  [inline, virtual]
+
+
+ +

+Reserves an item. +

+false = no item can be reserved
+ true = an item is reserved +

+Reimplemented from tbb::flow::interface6::sender< T >. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00263.png b/src/tbb/doc/html/a00263.png new file mode 100644 index 0000000000000000000000000000000000000000..425350bed7dfddecd861bf9a25e11c499b9b1d3e GIT binary patch literal 2898 zcmb_ec|4SB8=efZ4f?W92bHyP#y+-)h@xUNXe{B#{&E|mDVPEoR9ff(|NwaLN30n0r&=z93jC4=RC8(m#pkv#|VtnkRKYZfSw z;o_tR2*krMyKvq*4F9pnKdn?-us^}JaM*gf>j7^~NV$Hx!Snre;*K)bCEhHlq-Dmx zOvWWaYT@FmvdY)#vAOGOmwsZHR5D^~U@=Jw##>9wT1z5Tfgn_C@h1@NNF*&g|K_=9 zau+U(va&JSHg#)XB2y%ztvuAV3_Yx_XwmgoB{-G(FcG9C>PA2hLsh%IMEJ_W+ zeEuw7k380C**v~wyCC+d|EpKprv>Y~;fjsRTr0`-#pLcsc}85(L3+7jJUo1utPe9; zc_*74IbNg7-6-_F>=AqOfPpKdAZ=n>LvAML_6JYyY@e2F(w@y-gnkXKbH z*Y4l>a7h<6l0J6!(R|Ece9uV~2QmNb_?+X}RZX4k@yvrq2=jy>EgV_KR7l#FDUreU1Pj_UZmz(At-*|rNodRtufC)a zkn9m|?VLy=!4{Bx%?WRJ0s#$o)LX8Q;(*YKAWAd6IA#Jm_)|^hjf^ELUV!L_rW4t| zaL`mdFkkF&{@oe_4;B{ua99h)0t7#`PVL4@I#AC!Zrq0-r-7+s=(*Zo!{hAi=vibe zTvh40vf3t$*P*qAM{4dC>G}|&#T{oJRM6_AI`Py}A)Hb`&*h}=-1&YLpT8 zasS@nWrO`YuA9~dN!jKPE8p3-a2{+m#+DhTB0vDWb>vl^fcd*ODXZbAbyTtJgaZaqE{%4QqH{;b#$QB9Ul!reO{l6Vxf|YvA zLbubq%y>betQ7ydSv8_&q)iC8=7@|8oP^IFJp#mW5;?sh;wVniUU3yF)vMCJ6S|RGpNU0gQmjQ=@CaflTPp+;3aK5Ao) zvQ{J!q363)WE{2qrT2t>pf^k)c<+_Mc=E-vBH2wo67?LB65RG3603HhY)CSREEBpf zErd;PsL`JY6WVmUJkAzaB>FZEQAfWD2=-f)&nDmYx)B-Hr%S4Jg_O*vxTfk!On>IA z!AMNg#IPo`u$(p(N?K$Sg-*&uNV3YPuzU(_o||-}Tj`z+-uE%AT7r^3p%;aQ!Bm=~ zv>iAo^$Y86_U>feFjQ5X7x!ZIG?=PgA)j-KCfSpH35KgBG4H4i`9D6afqw=Y;&tf2 z06{B4)q@r6;iO$D7){r8fsBA?Ajn_AaQFVvh|Dz6uoLod&>P`HBNY6>HJ%WMFa+tzgkC#%WNmwN^OoWkPHd*nB+6su8TCIn;m9GiQ# zN#CTLKiA6kjJ*V`wB}lauC=M%zjt8w=HB+I=gz9}(!N8jSMZ*D@OrcTzepnGuK88g ziKAe*aB@gCubK_zH!mHA@yf0iIfl`d(DE5pt5#Tb=-t_^67FqNsG8CWeirj(v%4yU z=I1Q6$P}Ted?Lp(&uGNVm?B$hRa<>Nqfx>k_BV}}-gvaHHhzLnFHXu58nLI;r_X=4 z0XpnNw#xhsYc)TM&&lgrO|g{$KgmjqI}4@}2e06HDk8^YOTr4nk`h~lMo001SGF}j zB08??G^s=nHG5PdBBsXEFxiAZa5rhLx zVJRQ?y@X)o>}*_?!$Kgp-u-}FVU)yBW9u#Doc$}n&iseo^WDd=KUcRmV4oeMhoK`J zuwjLLRtt9_Kp*Fsaagv^S15pls`7EPU$FV8#L8;W52buxZ~Bo9x6%Ly@)Hq(6O%T{ z`^BwxH#61uTFHg2=Kd8c|0YQCGS z>}%8a7=Cu|Jtu*m@emlKDL_S7pN`oVgvjD$2YYFQVmHx@T23yh;|8e$V4fg-g20pJ z_gtt4j@nlkQTj^i`_}&YW0sck3pww&6R-MKR%={jCL%VDn@bjHzn&@!H)%06u83i% zO}B_rJIWCjV|)C49WCi0L*1?AQeQQl&q{!Q+D{&$S=lmD3ob z?cf@#eu8{JZIEvuuI5FrKm!)Evp(hi&qy&)`E}-N)_i zLTK8ZtR)xtY8~w;-@Zi%Ne)+a-`cXEl3dNt(#S|K^_8%bqVjWIjUfQ6bbsygliYH| z6iZ)~=naTM#WtwL32*%gUr323Ah;0j+hl5&AwtWj7=RAghQZBB%tamZ+#TH^tyE}u zt&STc+-V50*rC_f0~7!w5o>7lO`tBb<~ErE@v^6<3OjAO)?xG~>RS|tX_HY#b1VwNIpJbXT6vf6`I7V1Z?00{u>!Ryl3JNFc%BFjL$ev T>aSw`0E5g-EH2a;xy1htd9+jF literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/a00264.html b/src/tbb/doc/html/a00264.html new file mode 100644 index 0000000..fa87fba --- /dev/null +++ b/src/tbb/doc/html/a00264.html @@ -0,0 +1,111 @@ + + +tbb::cache_aligned_allocator< T > Class Template Reference + + + + + + + +

tbb::cache_aligned_allocator< T > Class Template Reference
+ +[Memory Allocation] +

Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5. +More... +

+#include <cache_aligned_allocator.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef internal::allocator_type<
+ T >::value_type 
value_type
+typedef value_type * pointer
+typedef const value_type * const_pointer
+typedef value_type & reference
+typedef const value_type & const_reference
+typedef size_t size_type
+typedef ptrdiff_t difference_type

Public Member Functions

cache_aligned_allocator (const cache_aligned_allocator &) throw ()
+template<typename U>
 cache_aligned_allocator (const cache_aligned_allocator< U > &) throw ()
+pointer address (reference x) const
+const_pointer address (const_reference x) const
+pointer allocate (size_type n, const void *hint=0)
 Allocate space for n objects, starting on a cache/sector line.
+void deallocate (pointer p, size_type)
 Free block of memory that starts on a cache line.
+size_type max_size () const throw ()
 Largest value for which method allocate might succeed.
+template<typename... Args>
void construct (pointer p, Args &&...args)
 Copy-construct value at location pointed to by p.

Classes

struct  rebind
+


Detailed Description

+

template<typename T>
+ class tbb::cache_aligned_allocator< T >

+ +Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5. +

+The members are ordered the same way they are in section 20.4.1 of the ISO C++ standard. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00265.html b/src/tbb/doc/html/a00265.html new file mode 100644 index 0000000..83226cb --- /dev/null +++ b/src/tbb/doc/html/a00265.html @@ -0,0 +1,65 @@ + + +tbb::cache_aligned_allocator< void > Class Template Reference + + + + + + + +

tbb::cache_aligned_allocator< void > Class Template Reference
+ +[Memory Allocation] +

Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1. +More... +

+#include <cache_aligned_allocator.h> +

+List of all members. + + + + + + + + + + + +

Public Types

+typedef void * pointer
+typedef const void * const_pointer
+typedef void value_type

Classes

struct  rebind
+


Detailed Description

+

template<>
+ class tbb::cache_aligned_allocator< void >

+ +Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00266.html b/src/tbb/doc/html/a00266.html new file mode 100644 index 0000000..aa6a0dc --- /dev/null +++ b/src/tbb/doc/html/a00266.html @@ -0,0 +1,157 @@ + + +tbb::captured_exception Class Reference + + + + + + + +

tbb::captured_exception Class Reference

This class is used by TBB to propagate information about unhandled exceptions into the root thread. +More... +

+#include <tbb_exception.h> +

+

Inheritance diagram for tbb::captured_exception: +

+ +tbb::tbb_exception + +List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Member Functions

captured_exception (const captured_exception &src)
captured_exception (const char *name_, const char *info)
+captured_exceptionoperator= (const captured_exception &src)
captured_exception *__TBB_EXPORTED_METHOD move () throw ()
 Creates and returns pointer to the deep copy of this exception object.
void __TBB_EXPORTED_METHOD destroy () throw ()
 Destroys objects created by the move() method.
void throw_self ()
 Throws this exception object.
+const char *__TBB_EXPORTED_METHOD name () const throw ()
 Returns RTTI name of the originally intercepted exception.
+const char *__TBB_EXPORTED_METHOD what () const throw ()
 Returns the result of originally intercepted exception's what() method.
+void __TBB_EXPORTED_METHOD set (const char *name, const char *info) throw ()
+void __TBB_EXPORTED_METHOD clear () throw ()
+

Detailed Description

+This class is used by TBB to propagate information about unhandled exceptions into the root thread. +

+Exception of this type is thrown by TBB in the root thread (thread that started a parallel algorithm ) if an unhandled exception was intercepted during the algorithm execution in one of the workers.

See also:
tbb::tbb_exception
+ +

+


Member Function Documentation

+ +
+
+ + + + + + + + +
void __TBB_EXPORTED_METHOD tbb::captured_exception::destroy (  )  throw () [virtual]
+
+
+ +

+Destroys objects created by the move() method. +

+Frees memory and calls destructor for this exception object. Can and must be used only on objects created by the move method. +

+Implements tbb::tbb_exception. +

+

+ +

+
+ + + + + + + + +
captured_exception* __TBB_EXPORTED_METHOD tbb::captured_exception::move (  )  throw () [virtual]
+
+
+ +

+Creates and returns pointer to the deep copy of this exception object. +

+Move semantics is allowed. +

+Implements tbb::tbb_exception. +

+

+ +

+
+ + + + + + + + +
void tbb::captured_exception::throw_self (  )  [inline, virtual]
+
+
+ +

+Throws this exception object. +

+Make sure that if you have several levels of derivation from this interface you implement or override this method on the most derived level. The implementation is as simple as "throw *this;". Failure to do this will result in exception of a base class type being thrown. +

+Implements tbb::tbb_exception. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00266.png b/src/tbb/doc/html/a00266.png new file mode 100644 index 0000000000000000000000000000000000000000..2470beabf4e1a926efb457d09628b050185df0cb GIT binary patch literal 472 zcmV;}0Vn>6P)6KCdo?j`%78mVT$@&((-jX(qma}N4jP2CTWr;X_6*slKwjhyd)&2yyGO}VmX4M+fM5I#I=U zby|^H@5s)LVFQ9F=A?H~d)G+^Vz~L65Hls!S5>zuC3Bw0yrf2nW6#s+)6(JT7^ O0000 + +tbb::combinable< T > Class Template Reference + + + + + + + +

tbb::combinable< T > Class Template Reference
+ +[Containers] +

Thread-local storage with optional reduction. +More... +

+#include <combinable.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + +

Public Member Functions

+template<typename finit>
 combinable (finit _finit)
~combinable ()
 destructor
combinable (const combinable &other)
+combinableoperator= (const combinable &other)
+void clear ()
+T & local ()
+T & local (bool &exists)
+template<typename combine_func_t>
combine (combine_func_t f_combine)
+template<typename combine_func_t>
void combine_each (combine_func_t f_combine)
+


Detailed Description

+

template<typename T>
+ class tbb::combinable< T >

+ +Thread-local storage with optional reduction. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00268.html b/src/tbb/doc/html/a00268.html new file mode 100644 index 0000000..04afb29 --- /dev/null +++ b/src/tbb/doc/html/a00268.html @@ -0,0 +1,310 @@ + + +tbb::concurrent_bounded_queue< T, A > Class Template Reference + + + + + + + +

tbb::concurrent_bounded_queue< T, A > Class Template Reference
+ +[Containers] +

A high-performance thread-safe blocking concurrent bounded queue. +More... +

+#include <concurrent_queue.h> +

+

Inheritance diagram for tbb::concurrent_bounded_queue< T, A >: +

+ +tbb::deprecated::concurrent_queue< T, A > + +List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef T value_type
 Element type in the queue.
+typedef A allocator_type
 Allocator type.
+typedef T & reference
 Reference type.
+typedef const T & const_reference
 Const reference type.
typedef std::ptrdiff_t size_type
 Integral type for representing size of the queue.
+typedef std::ptrdiff_t difference_type
 Difference type for iterator.
+typedef internal::concurrent_queue_iterator<
+ concurrent_bounded_queue,
+ T > 
iterator
+typedef internal::concurrent_queue_iterator<
+ concurrent_bounded_queue,
+ const T > 
const_iterator

Public Member Functions

concurrent_bounded_queue (const allocator_type &a=allocator_type())
 Construct empty queue.
concurrent_bounded_queue (const concurrent_bounded_queue &src, const allocator_type &a=allocator_type())
 Copy constructor.
+template<typename InputIterator>
 concurrent_bounded_queue (InputIterator begin, InputIterator end, const allocator_type &a=allocator_type())
 [begin,end) constructor
~concurrent_bounded_queue ()
 Destroy queue.
+void push (const T &source)
 Enqueue an item at tail of queue.
void pop (T &destination)
 Dequeue item from head of queue.
+void abort ()
 Abort all pending queue operations.
bool try_push (const T &source)
 Enqueue an item at tail of queue if queue is not already full.
bool try_pop (T &destination)
 Attempt to dequeue an item from head of queue.
size_type size () const
 Return number of pushes minus number of pops.
+bool empty () const
 Equivalent to size()<=0.
+size_type capacity () const
 Maximum number of allowed elements.
void set_capacity (size_type new_capacity)
 Set the capacity.
+allocator_type get_allocator () const
 return allocator object
+void clear ()
 clear the queue. not thread-safe.
+iterator unsafe_begin ()
+iterator unsafe_end ()
+const_iterator unsafe_begin () const
+const_iterator unsafe_end () const

Friends

+class internal::concurrent_queue_iterator

Classes

class  destroyer
 Class used to ensure exception-safety of method "pop".
+

Detailed Description

+

template<typename T, class A = cache_aligned_allocator<T>>
+ class tbb::concurrent_bounded_queue< T, A >

+ +A high-performance thread-safe blocking concurrent bounded queue. +

+This is the pre-PPL TBB concurrent queue which supports boundedness and blocking semantics. Note that method names agree with the PPL-style concurrent queue. Multiple threads may each push and pop concurrently. Assignment construction is not allowed. +

+


Member Typedef Documentation

+ +
+
+
+template<typename T, class A = cache_aligned_allocator<T>>
+ + + + +
typedef std::ptrdiff_t tbb::concurrent_bounded_queue< T, A >::size_type
+
+
+ +

+Integral type for representing size of the queue. +

+Note that the size_type is a signed integral type. This is because the size can be negative if there are pending pops without corresponding pushes. +

+

+


Member Function Documentation

+ +
+
+
+template<typename T, class A = cache_aligned_allocator<T>>
+ + + + + + + + + +
void tbb::concurrent_bounded_queue< T, A >::pop (T &  destination  )  [inline]
+
+
+ +

+Dequeue item from head of queue. +

+Block until an item becomes available, and then dequeue it. +

+

+ +

+
+
+template<typename T, class A = cache_aligned_allocator<T>>
+ + + + + + + + + +
void tbb::concurrent_bounded_queue< T, A >::set_capacity (size_type  new_capacity  )  [inline]
+
+
+ +

+Set the capacity. +

+Setting the capacity to 0 causes subsequent try_push operations to always fail, and subsequent push operations to block forever. +

+

+ +

+
+
+template<typename T, class A = cache_aligned_allocator<T>>
+ + + + + + + + +
size_type tbb::concurrent_bounded_queue< T, A >::size (  )  const [inline]
+
+
+ +

+Return number of pushes minus number of pops. +

+Note that the result can be negative if there are pops waiting for the corresponding pushes. The result can also exceed capacity() if there are push operations in flight. +

+

+ +

+
+
+template<typename T, class A = cache_aligned_allocator<T>>
+ + + + + + + + + +
bool tbb::concurrent_bounded_queue< T, A >::try_pop (T &  destination  )  [inline]
+
+
+ +

+Attempt to dequeue an item from head of queue. +

+Does not wait for item to become available. Returns true if successful; false otherwise. +

+

+ +

+
+
+template<typename T, class A = cache_aligned_allocator<T>>
+ + + + + + + + + +
bool tbb::concurrent_bounded_queue< T, A >::try_push (const T &  source  )  [inline]
+
+
+ +

+Enqueue an item at tail of queue if queue is not already full. +

+Does not wait for queue to become not full. Returns true if item is pushed; false if queue was already full. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00268.png b/src/tbb/doc/html/a00268.png new file mode 100644 index 0000000000000000000000000000000000000000..e9d90a27b371941b6c15fd6fb250f226cdb65bc4 GIT binary patch literal 731 zcmV<10wn#3P)u2340000OP)t-s|Ns90 z00960z@MLBkN^MxkN^Mxkifved&2+Z00001bW%=J06^y0W&i*JaY;l$RCt{2mTPV! zAq;@wPk&=>04J!r7pk;U?tg^(1;cBmNvF;1s&r?9yx>AuaImur9pfh=)yQFRZ=fdm#) z;~tdydb%i z^DUG*@PjIK(AoPsP=dJ*N-ub+-_itB^O^%SwY@-R@kI~4&=|U22u%(qg71{wEmw{& z5b$sMp>NOaSH|b&;AsR8i4hoq5M2CceZRBsmiO~%_}>X$Zbopsz5jZG>nqU+jKBzt zzzB@M2#ml8jKBzt;0Fo*oRq&O*T1^Ae61LP5mbVdBYmjERb1-SfgD8uK%CBaDnWIo zCW;9lMnEeconpj!MnjG<0XZ`&kTI`RYg9$AhPW{t!(rM?d=k`k5|N=LU`v*-TyKG6#aUKGnXt7F$#ws%aj7-Ycp!j069~eR z06_P}%1NAd`ugw*0l-M0OHe_73#B3nVV#3qbC6T9>A43v$a4-fF!wn~I%;#Eb-?+q zbr4r|&|MU(w7LaIrHo*%10`tdp!5Q5+4MrLy?{>bg_vqDWR9c-M4+amy}-37OS)c2 zO%AqRSjh6B@PO<-7AD8{6JSNc0l~EK({nJ%Kl00D1V(WB-}+g3{Qy%s(JzHZ_W}R_ N002ovPDHLkV1lt)KZ^hW literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/a00269.html b/src/tbb/doc/html/a00269.html new file mode 100644 index 0000000..e0f8d9e --- /dev/null +++ b/src/tbb/doc/html/a00269.html @@ -0,0 +1,646 @@ + + +tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > Class Template Reference + + + + + + + +

tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator > Class Template Reference
+ +[Containers] +

Unordered map from Key to T. +More... +

+#include <concurrent_hash_map.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef Key key_type
+typedef T mapped_type
+typedef std::pair< const Key,
+ T > 
value_type
+typedef hash_map_base::size_type size_type
+typedef ptrdiff_t difference_type
+typedef value_type * pointer
+typedef const value_type * const_pointer
+typedef value_type & reference
+typedef const value_type & const_reference
+typedef internal::hash_map_iterator<
+ concurrent_hash_map, value_type > 
iterator
+typedef internal::hash_map_iterator<
+ concurrent_hash_map, const
+value_type > 
const_iterator
+typedef internal::hash_map_range<
+ iterator > 
range_type
+typedef internal::hash_map_range<
+ const_iterator > 
const_range_type
+typedef Allocator allocator_type

Public Member Functions

concurrent_hash_map (const allocator_type &a=allocator_type())
 Construct empty table.
concurrent_hash_map (size_type n, const allocator_type &a=allocator_type())
 Construct empty table with n preallocated buckets. This number serves also as initial concurrency level.
concurrent_hash_map (const concurrent_hash_map &table, const allocator_type &a=allocator_type())
 Copy constructor.
+template<typename I>
 concurrent_hash_map (I first, I last, const allocator_type &a=allocator_type())
 Construction with copying iteration range and given allocator instance.
+concurrent_hash_mapoperator= (const concurrent_hash_map &table)
 Assignment.
void rehash (size_type n=0)
 Rehashes and optionally resizes the whole table.
+void clear ()
 Clear table.
~concurrent_hash_map ()
 Clear table and destroy it.
+range_type range (size_type grainsize=1)
+const_range_type range (size_type grainsize=1) const
+iterator begin ()
+iterator end ()
+const_iterator begin () const
+const_iterator end () const
+std::pair< iterator, iterator > equal_range (const Key &key)
+std::pair< const_iterator,
+ const_iterator > 
equal_range (const Key &key) const
+size_type size () const
 Number of items in table.
+bool empty () const
 True if size()==0.
+size_type max_size () const
 Upper bound on size.
+size_type bucket_count () const
 Returns the current number of buckets.
+allocator_type get_allocator () const
 return allocator object
+void swap (concurrent_hash_map &table)
 swap two instances. Iterators are invalidated
+size_type count (const Key &key) const
 Return count of items (0 or 1).
bool find (const_accessor &result, const Key &key) const
 Find item and acquire a read lock on the item.
bool find (accessor &result, const Key &key)
 Find item and acquire a write lock on the item.
bool insert (const_accessor &result, const Key &key)
 Insert item (if not already present) and acquire a read lock on the item.
bool insert (accessor &result, const Key &key)
 Insert item (if not already present) and acquire a write lock on the item.
bool insert (const_accessor &result, const value_type &value)
 Insert item by copying if there is no such key present already and acquire a read lock on the item.
bool insert (accessor &result, const value_type &value)
 Insert item by copying if there is no such key present already and acquire a write lock on the item.
bool insert (const value_type &value)
 Insert item by copying if there is no such key present already.
+template<typename I>
void insert (I first, I last)
 Insert range [first, last).
bool erase (const Key &key)
 Erase item.
bool erase (const_accessor &item_accessor)
 Erase item by const_accessor.
bool erase (accessor &item_accessor)
 Erase item by accessor.

Protected Types

+typedef Allocator::template
+rebind< node >::other 
node_allocator_type

Protected Member Functions

+void delete_node (node_base *n)
+node * search_bucket (const key_type &key, bucket *b) const
+void rehash_bucket (bucket *b_new, const hashcode_t h)
+bool lookup (bool op_insert, const Key &key, const T *t, const_accessor *result, bool write)
 Insert or find item and optionally acquire a lock on the item.
+bool exclude (const_accessor &item_accessor)
 delete item by accessor
+template<typename I>
std::pair< I, I > internal_equal_range (const Key &key, I end) const
 Returns an iterator for an item defined by the key, or for the next item after it (if upper==true).
+void internal_copy (const concurrent_hash_map &source)
 Copy "source" to *this, where *this must start out empty.
+template<typename I>
void internal_copy (I first, I last)
const_pointer internal_fast_find (const Key &key) const
 Fast find when no concurrent erasure is used. For internal use inside TBB only!

Protected Attributes

+node_allocator_type my_allocator
+HashCompare my_hash_compare

Friends

+class internal::hash_map_iterator
+class internal::hash_map_range
+class const_accessor

Classes

class  accessor
 Allows write access to elements and combines data access, locking, and garbage collection. More...
class  bucket_accessor
 bucket accessor is to find, rehash, acquire a lock, and access a bucket More...
class  const_accessor
 Combines data access, locking, and garbage collection. More...
struct  node
+


Detailed Description

+

template<typename Key, typename T, typename HashCompare, typename Allocator>
+ class tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >

+ +Unordered map from Key to T. +

+concurrent_hash_map is associative container with concurrent access.

+

Compatibility
The class meets all Container Requirements from C++ Standard (See ISO/IEC 14882:2003(E), clause 23.1).
+
Exception Safety
    +
  • Hash function is not permitted to throw an exception. User-defined types Key and T are forbidden from throwing an exception in destructors.
  • If exception happens during insert() operations, it has no effect (unless exception raised by HashCompare::hash() function during grow_segment).
  • If exception happens during operator=() operation, the container can have a part of source items, and methods size() and empty() can return wrong results.
+
+
Changes since TBB 2.1
    +
  • Replaced internal algorithm and data structure. Patent is pending.
  • Added buckets number argument for constructor
+
+
Changes since TBB 2.0
    +
  • Fixed exception-safety
  • Added template argument for allocator
  • Added allocator argument in constructors
  • Added constructor from a range of iterators
  • Added several new overloaded insert() methods
  • Added get_allocator()
  • Added swap()
  • Added count()
  • Added overloaded erase(accessor &) and erase(const_accessor&)
  • Added equal_range() [const]
  • Added [const_]pointer, [const_]reference, and allocator_type types
  • Added global functions: operator==(), operator!=(), and swap()
+
+ +

+


Member Function Documentation

+ +
+
+
+template<typename Key, typename T, typename HashCompare, typename Allocator>
+ + + + + + + + + +
bool tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::erase (accessor item_accessor  )  [inline]
+
+
+ +

+Erase item by accessor. +

+Return true if item was erased by particularly this call. +

+

+ +

+
+
+template<typename Key, typename T, typename HashCompare, typename Allocator>
+ + + + + + + + + +
bool tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::erase (const_accessor item_accessor  )  [inline]
+
+
+ +

+Erase item by const_accessor. +

+Return true if item was erased by particularly this call. +

+

+ +

+
+
+template<typename Key, typename T, typename HashCompare, typename A>
+ + + + + + + + + +
bool tbb::interface5::concurrent_hash_map< Key, T, HashCompare, A >::erase (const Key &  key  ) 
+
+
+ +

+Erase item. +

+Return true if item was erased by particularly this call. +

+

+ +

+
+
+template<typename Key, typename T, typename HashCompare, typename Allocator>
+ + + + + + + + + + + + + + + + + + +
bool tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::find (accessor result,
const Key &  key 
) [inline]
+
+
+ +

+Find item and acquire a write lock on the item. +

+Return true if item is found, false otherwise. +

+

+ +

+
+
+template<typename Key, typename T, typename HashCompare, typename Allocator>
+ + + + + + + + + + + + + + + + + + +
bool tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::find (const_accessor result,
const Key &  key 
) const [inline]
+
+
+ +

+Find item and acquire a read lock on the item. +

+Return true if item is found, false otherwise. +

+

+ +

+
+
+template<typename Key, typename T, typename HashCompare, typename Allocator>
+ + + + + + + + + +
bool tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::insert (const value_type &  value  )  [inline]
+
+
+ +

+Insert item by copying if there is no such key present already. +

+Returns true if item is inserted. +

+

+ +

+
+
+template<typename Key, typename T, typename HashCompare, typename Allocator>
+ + + + + + + + + + + + + + + + + + +
bool tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::insert (accessor result,
const value_type &  value 
) [inline]
+
+
+ +

+Insert item by copying if there is no such key present already and acquire a write lock on the item. +

+Returns true if item is new. +

+

+ +

+
+
+template<typename Key, typename T, typename HashCompare, typename Allocator>
+ + + + + + + + + + + + + + + + + + +
bool tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::insert (const_accessor result,
const value_type &  value 
) [inline]
+
+
+ +

+Insert item by copying if there is no such key present already and acquire a read lock on the item. +

+Returns true if item is new. +

+

+ +

+
+
+template<typename Key, typename T, typename HashCompare, typename Allocator>
+ + + + + + + + + + + + + + + + + + +
bool tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::insert (accessor result,
const Key &  key 
) [inline]
+
+
+ +

+Insert item (if not already present) and acquire a write lock on the item. +

+Returns true if item is new. +

+

+ +

+
+
+template<typename Key, typename T, typename HashCompare, typename Allocator>
+ + + + + + + + + + + + + + + + + + +
bool tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::insert (const_accessor result,
const Key &  key 
) [inline]
+
+
+ +

+Insert item (if not already present) and acquire a read lock on the item. +

+Returns true if item is new. +

+

+ +

+
+
+template<typename Key, typename T, typename HashCompare, typename Allocator>
+ + + + + + + + + +
const_pointer tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::internal_fast_find (const Key &  key  )  const [inline, protected]
+
+
+ +

+Fast find when no concurrent erasure is used. For internal use inside TBB only! +

+Return pointer to item with given key, or NULL if no such item exists. Must not be called concurrently with erasure operations. +

+

+ +

+
+
+template<typename Key, typename T, typename HashCompare, typename A>
+ + + + + + + + + +
void tbb::interface5::concurrent_hash_map< Key, T, HashCompare, A >::rehash (size_type  n = 0  ) 
+
+
+ +

+Rehashes and optionally resizes the whole table. +

+Useful to optimize performance before or after concurrent operations. Also enables using of find() and count() concurrent methods in serial context. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00270.html b/src/tbb/doc/html/a00270.html new file mode 100644 index 0000000..adfa37b --- /dev/null +++ b/src/tbb/doc/html/a00270.html @@ -0,0 +1,68 @@ + + +tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::accessor Class Reference + + + + + + + +

tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::accessor Class Reference

Allows write access to elements and combines data access, locking, and garbage collection. +More... +

+#include <concurrent_hash_map.h> +

+

Inheritance diagram for tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::accessor: +

+ +tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor + +List of all members. + + + + + + + + + + + + +

Public Types

+typedef concurrent_hash_map::value_type value_type
 Type of value.

Public Member Functions

+reference operator * () const
 Return reference to associated value in hash table.
+pointer operator-> () const
 Return pointer to associated value in hash table.
+

Detailed Description

+

template<typename Key, typename T, typename HashCompare, typename Allocator>
+ class tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::accessor

+ +Allows write access to elements and combines data access, locking, and garbage collection. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00270.png b/src/tbb/doc/html/a00270.png new file mode 100644 index 0000000000000000000000000000000000000000..9fd6a575f54e83ee34adbee35f196e21dc6fa486 GIT binary patch literal 1371 zcmai!X;hL46o$#A!rf0zb4%?L%q637Nz6pX1=Prurkv4Cv&HQ=CK`+>Mj4F}jbo`Z z3aMj-B3cZ#m>OEQ$xK)M>GpBRkhUByrZ0)ePw zF`hvXhyozj0ZNMUUT;k1%ZEXLe~6b%CX-8W&Zp4i&C#8%%ICg2~Rjv7AP|1nVl&ZZ?Oll*Kop5P%40yYv<*ZraDF6k7S< zKHuOP=nUkpawS8_8Sk&hi>bq5UQA-0uv~kp;)qSFH5u=C0a9&Y+e>bKH|j8;6a0P9 zO7zudD3f9k{N$*e6MKZHN-(J#I8As7RQJWH2|G@UY6~7~Cnm5W2_Z8vc|(^j8|JMi zd1po2p%25!7PYU=`0zQ$w;Pq;73751Yo+P#;$Y|+>88-oAub7cLb<4v%29=4qn9o; zB>OT%?XxI>B6KCXqN4KU1<%p~N{IpJ^hc~!%cJ($G|%HksmD-tMmj?Ol3laZ=4$R$ zVGj+}Jwu6gvv*QPU7f}iKb%ec zg^(r?9ggRv4#NguzIDHQHSFfhf}*_5@9>?$z{6Uhw5eu8U zQWpFDOUAa{T+*a7gYKLhLVk7$)?7ikiwhnoBTr=-Em0%f4)+G!2n*w;CkD>q??*~F zgcPic);{QhbslyqWdCWLft5FZjCx|@NAJkja6eZ0TUZOCmtjvd$4(IE?cMIFAJ8V* zY}LKCw(NlJXgi9eO&PI_vSe*RxXa-lwONE`J?bIzeF0kSWA_gQ0k_hef|XIuK*~w4sY8 zz?LO#xgyALhV}WQOU}W_=FBLC*K?HScaPvTIa_0=)!SS1t@`uDrq?jTNW}FQI#ABe zIfb#sI6`!)ORm8T^QfILSDDmaPS_Y9xJ_@83amTOh4vi80>Zr0QM%*9| z5ox|xu`k}))wf`kRz`yGICRe%4N{PB;fYTqa_mQ81GC_CHbJB+V~ Rn#eyP1nY(KtU@2l`UjZqhjIV_ literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/a00271.html b/src/tbb/doc/html/a00271.html new file mode 100644 index 0000000..05c048d --- /dev/null +++ b/src/tbb/doc/html/a00271.html @@ -0,0 +1,65 @@ + + +tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::bucket_accessor Class Reference + + + + + + + +

tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::bucket_accessor Class Reference

bucket accessor is to find, rehash, acquire a lock, and access a bucket +More... +

+#include <concurrent_hash_map.h> +

+List of all members. + + + + + + + + + + + + + +

Public Member Functions

bucket_accessor (concurrent_hash_map *base, const hashcode_t h, bool writer=false)
+void acquire (concurrent_hash_map *base, const hashcode_t h, bool writer=false)
 find a bucket by masked hashcode, optionally rehash, and acquire the lock
+bool is_writer ()
 check whether bucket is locked for write
+bucket * operator() ()
 get bucket pointer
+


Detailed Description

+

template<typename Key, typename T, typename HashCompare, typename Allocator>
+ class tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::bucket_accessor

+ +bucket accessor is to find, rehash, acquire a lock, and access a bucket +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00272.html b/src/tbb/doc/html/a00272.html new file mode 100644 index 0000000..1f6148c --- /dev/null +++ b/src/tbb/doc/html/a00272.html @@ -0,0 +1,102 @@ + + +tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor Class Reference + + + + + + + +

tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor Class Reference

Combines data access, locking, and garbage collection. +More... +

+#include <concurrent_hash_map.h> +

+

Inheritance diagram for tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor: +

+ +tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::accessor + +List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef const concurrent_hash_map::value_type value_type
 Type of value.

Public Member Functions

+bool empty () const
 True if result is empty.
+void release ()
 Set to null.
+const_reference operator * () const
 Return reference to associated value in hash table.
+const_pointer operator-> () const
 Return pointer to associated value in hash table.
const_accessor ()
 Create empty result.
~const_accessor ()
 Destroy result after releasing the underlying reference.

Protected Member Functions

+bool is_writer ()

Protected Attributes

+node * my_node
+hashcode_t my_hash

Friends

+class concurrent_hash_map< Key, T, HashCompare, Allocator >
+class accessor
+

Detailed Description

+

template<typename Key, typename T, typename HashCompare, typename Allocator>
+ class tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessor

+ +Combines data access, locking, and garbage collection. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00272.png b/src/tbb/doc/html/a00272.png new file mode 100644 index 0000000000000000000000000000000000000000..f3e6df6c0af453e83b17800b4ff1b19ea5a553b8 GIT binary patch literal 1376 zcma*neKga190%~x3Nh6vJ&>s%5*6hZZh2~BE3qWiS*@CNb!o0VKb&Y%8LrJ!vQ2h` zLuN>mHpxY5u}Yb+%UHE$HRf*f5ZT>P=XC$Pe|*26_xE$o=Y0Nooi7RP?+aPEaU}=@ zf}oJ_KoCe5s?BKdGVR@JPHfkf^=Q8!ghr#$MvbPewDcTBo0d*nTU&Cw=7aXB6BFov z4CE;p_zeUCPov;oK?!vEZB*1&S0e=PNUg!h)l>VVnN>>Fiy04ZlMX!|9pH9b?@-9m zhgKV;w0xk%l~J}An&Ljf&aZ@`DOc0L0PqD7v`~>%c?(W1-cj<_`a?@fVdDFy=?pWH zDCc>tlB)KZ5mlN%CqhK?#gCNEq>?&uQ8D}xyHvT4!U(Ji?RWe7%du5z&(tyd%Z3Sk zpnVcUjmi{p@Kgk$clt4+0mHw+^Z3fB_S2`Q$FH5tb6FceHL=Oeb&SUqi;9SrU30i$ zAJ?efv#6}`*OvB4R;U#9P^zksptwGO@nR&j2rJi!dzpp!LeHI4FVM*~x1^r982&~X z$!=?P()}(R!zcinw?NhJVmmxu&Nar$9=JJznRr@9Ka3{2G~u(KTb(T+wgmsa;hOYi z$ISa|Fb|u~^4CRFj)nQQ`!-~6=p+`UbBcxkSZyVth?18xC)?X3VyY*j>z5hlU6N`^`&0jwcHabmF zlyyZ_4!$MAv8Zhs-*O_wBQplJ#Kw>W3FLV2O}e3rQ{Ys5Q@D^`zj{t49geHHTQL3w znY5x{d}LOpU=8~68`AUtwI;p9?>0$iY9RG* zJTMvRJ;>WXR@VYU!E=b9Z(5!{@Yv+?3gtq?am=EV+t#f(*j-`y-DF1DW#uTxa%MD&;~j+@uqp#D8{PoA6=_K*t6 zPj&t$FA5e39XY-|zZ0V_Cv?D_pb~!v<-D7MT<1_ty+bqq1XhJV}e+c->#aZaRy$NN4Nqb~$-ZF>)&L`KG2 z2JJtz1!K8TeC+G)v%z|t&B!WS;h771mcT|nV0yiC@9aClR3cQ^yiD-<3C%?4=Uqmy zA=)vbb(Qk}X#C8hSG}bxHj|M9?oPQEO$_Qngv*=X56Ui1MAS!yZ;g(%J588~Yc1D)haeQfAI|bVm-a8|Zk}BL literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/a00273.html b/src/tbb/doc/html/a00273.html new file mode 100644 index 0000000..2b9bf6b --- /dev/null +++ b/src/tbb/doc/html/a00273.html @@ -0,0 +1,348 @@ + + +tbb::interface5::concurrent_priority_queue< T, Compare, A > Class Template Reference + + + + + + + +

tbb::interface5::concurrent_priority_queue< T, Compare, A > Class Template Reference

Concurrent priority queue. +More... +

+#include <concurrent_priority_queue.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef T value_type
 Element type in the queue.
+typedef T & reference
 Reference type.
+typedef const T & const_reference
 Const reference type.
+typedef size_t size_type
 Integral type for representing size of the queue.
+typedef ptrdiff_t difference_type
 Difference type for iterator.
+typedef A allocator_type
 Allocator type.

Public Member Functions

concurrent_priority_queue (const allocator_type &a=allocator_type())
 Constructs a new concurrent_priority_queue with default capacity.
concurrent_priority_queue (size_type init_capacity, const allocator_type &a=allocator_type())
 Constructs a new concurrent_priority_queue with init_sz capacity.
+template<typename InputIterator>
 concurrent_priority_queue (InputIterator begin, InputIterator end, const allocator_type &a=allocator_type())
 [begin,end) constructor
 concurrent_priority_queue (const concurrent_priority_queue &src)
 Copy constructor.
 concurrent_priority_queue (const concurrent_priority_queue &src, const allocator_type &a)
 Copy constructor with specific allocator.
concurrent_priority_queueoperator= (const concurrent_priority_queue &src)
 Assignment operator.
bool empty () const
 Returns true if empty, false otherwise.
size_type size () const
 Returns the current number of elements contained in the queue.
void push (const_reference elem)
 Pushes elem onto the queue, increasing capacity of queue if necessary.
bool try_pop (reference elem)
 Gets a reference to and removes highest priority element.
void clear ()
 Clear the queue; not thread-safe.
void swap (concurrent_priority_queue &q)
 Swap this queue with another; not thread-safe.
+allocator_type get_allocator () const
 Return allocator object.

Classes

class  cpq_operation
class  my_functor_t
+


Detailed Description

+

template<typename T, typename Compare = std::less<T>, typename A = cache_aligned_allocator<T>>
+ class tbb::interface5::concurrent_priority_queue< T, Compare, A >

+ +Concurrent priority queue. +

+


Constructor & Destructor Documentation

+ +
+
+
+template<typename T, typename Compare = std::less<T>, typename A = cache_aligned_allocator<T>>
+ + + + + + + + + +
tbb::interface5::concurrent_priority_queue< T, Compare, A >::concurrent_priority_queue (const concurrent_priority_queue< T, Compare, A > &  src  )  [inline, explicit]
+
+
+ +

+Copy constructor. +

+This operation is unsafe if there are pending concurrent operations on the src queue. +

+

+ +

+
+
+template<typename T, typename Compare = std::less<T>, typename A = cache_aligned_allocator<T>>
+ + + + + + + + + + + + + + + + + + +
tbb::interface5::concurrent_priority_queue< T, Compare, A >::concurrent_priority_queue (const concurrent_priority_queue< T, Compare, A > &  src,
const allocator_type a 
) [inline]
+
+
+ +

+Copy constructor with specific allocator. +

+This operation is unsafe if there are pending concurrent operations on the src queue. +

+

+


Member Function Documentation

+ +
+
+
+template<typename T, typename Compare = std::less<T>, typename A = cache_aligned_allocator<T>>
+ + + + + + + + +
void tbb::interface5::concurrent_priority_queue< T, Compare, A >::clear (  )  [inline]
+
+
+ +

+Clear the queue; not thread-safe. +

+This operation is unsafe if there are pending concurrent operations on the queue. Resets size, effectively emptying queue; does not free space. May not clear elements added in pending operations. +

+

+ +

+
+
+template<typename T, typename Compare = std::less<T>, typename A = cache_aligned_allocator<T>>
+ + + + + + + + +
bool tbb::interface5::concurrent_priority_queue< T, Compare, A >::empty (  )  const [inline]
+
+
+ +

+Returns true if empty, false otherwise. +

+Returned value may not reflect results of pending operations. This operation reads shared data and will trigger a race condition. +

+

+ +

+
+
+template<typename T, typename Compare = std::less<T>, typename A = cache_aligned_allocator<T>>
+ + + + + + + + + +
concurrent_priority_queue& tbb::interface5::concurrent_priority_queue< T, Compare, A >::operator= (const concurrent_priority_queue< T, Compare, A > &  src  )  [inline]
+
+
+ +

+Assignment operator. +

+This operation is unsafe if there are pending concurrent operations on the src queue. +

+

+ +

+
+
+template<typename T, typename Compare = std::less<T>, typename A = cache_aligned_allocator<T>>
+ + + + + + + + + +
void tbb::interface5::concurrent_priority_queue< T, Compare, A >::push (const_reference  elem  )  [inline]
+
+
+ +

+Pushes elem onto the queue, increasing capacity of queue if necessary. +

+This operation can be safely used concurrently with other push, try_pop or reserve operations. +

+

+ +

+
+
+template<typename T, typename Compare = std::less<T>, typename A = cache_aligned_allocator<T>>
+ + + + + + + + +
size_type tbb::interface5::concurrent_priority_queue< T, Compare, A >::size (  )  const [inline]
+
+
+ +

+Returns the current number of elements contained in the queue. +

+Returned value may not reflect results of pending operations. This operation reads shared data and will trigger a race condition. +

+

+ +

+
+
+template<typename T, typename Compare = std::less<T>, typename A = cache_aligned_allocator<T>>
+ + + + + + + + + +
void tbb::interface5::concurrent_priority_queue< T, Compare, A >::swap (concurrent_priority_queue< T, Compare, A > &  q  )  [inline]
+
+
+ +

+Swap this queue with another; not thread-safe. +

+This operation is unsafe if there are pending concurrent operations on the queue. +

+

+ +

+
+
+template<typename T, typename Compare = std::less<T>, typename A = cache_aligned_allocator<T>>
+ + + + + + + + + +
bool tbb::interface5::concurrent_priority_queue< T, Compare, A >::try_pop (reference  elem  )  [inline]
+
+
+ +

+Gets a reference to and removes highest priority element. +

+If a highest priority element was found, sets elem and returns true, otherwise returns false. This operation can be safely used concurrently with other push, try_pop or reserve operations. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00274.html b/src/tbb/doc/html/a00274.html new file mode 100644 index 0000000..ddc0616 --- /dev/null +++ b/src/tbb/doc/html/a00274.html @@ -0,0 +1,169 @@ + + +tbb::strict_ppl::concurrent_queue< T, A > Class Template Reference + + + + + + + +

tbb::strict_ppl::concurrent_queue< T, A > Class Template Reference
+ +[Containers] +

A high-performance thread-safe non-blocking concurrent queue. +More... +

+#include <concurrent_queue.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef T value_type
 Element type in the queue.
+typedef T & reference
 Reference type.
+typedef const T & const_reference
 Const reference type.
+typedef size_t size_type
 Integral type for representing size of the queue.
+typedef ptrdiff_t difference_type
 Difference type for iterator.
+typedef A allocator_type
 Allocator type.
+typedef internal::concurrent_queue_iterator<
+ concurrent_queue, T > 
iterator
+typedef internal::concurrent_queue_iterator<
+ concurrent_queue, const T > 
const_iterator

Public Member Functions

concurrent_queue (const allocator_type &a=allocator_type())
 Construct empty queue.
+template<typename InputIterator>
 concurrent_queue (InputIterator begin, InputIterator end, const allocator_type &a=allocator_type())
 [begin,end) constructor
concurrent_queue (const concurrent_queue &src, const allocator_type &a=allocator_type())
 Copy constructor.
~concurrent_queue ()
 Destroy queue.
+void push (const T &source)
 Enqueue an item at tail of queue.
bool try_pop (T &result)
 Attempt to dequeue an item from head of queue.
+size_type unsafe_size () const
 Return the number of items in the queue; thread unsafe.
+bool empty () const
 Equivalent to size()==0.
+void clear ()
 Clear the queue. not thread-safe.
+allocator_type get_allocator () const
 Return allocator object.
+iterator unsafe_begin ()
+iterator unsafe_end ()
+const_iterator unsafe_begin () const
+const_iterator unsafe_end () const

Friends

+class internal::concurrent_queue_iterator
+


Detailed Description

+

template<typename T, typename A = cache_aligned_allocator<T>>
+ class tbb::strict_ppl::concurrent_queue< T, A >

+ +A high-performance thread-safe non-blocking concurrent queue. +

+Multiple threads may each push and pop concurrently. Assignment construction is not allowed. +

+


Member Function Documentation

+ +
+
+
+template<typename T, typename A = cache_aligned_allocator<T>>
+ + + + + + + + + +
bool tbb::strict_ppl::concurrent_queue< T, A >::try_pop (T &  result  )  [inline]
+
+
+ +

+Attempt to dequeue an item from head of queue. +

+Does not wait for item to become available. Returns true if successful; false otherwise. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00275.html b/src/tbb/doc/html/a00275.html new file mode 100644 index 0000000..4917221 --- /dev/null +++ b/src/tbb/doc/html/a00275.html @@ -0,0 +1,154 @@ + + +tbb::deprecated::concurrent_queue< T, A > Class Template Reference + + + + + + + +

tbb::deprecated::concurrent_queue< T, A > Class Template Reference
+ +[Containers] +

A high-performance thread-safe blocking concurrent bounded queue. +More... +

+#include <concurrent_queue.h> +

+

Inheritance diagram for tbb::deprecated::concurrent_queue< T, A >: +

+ +tbb::concurrent_bounded_queue< T, A > + +List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef concurrent_bounded_queue<
+ T, A >::iterator 
iterator
+typedef concurrent_bounded_queue<
+ T, A >::const_iterator 
const_iterator

Public Member Functions

concurrent_queue (const A &a=A())
 Construct empty queue.
concurrent_queue (const concurrent_queue &src, const A &a=A())
 Copy constructor.
+template<typename InputIterator>
 concurrent_queue (InputIterator b, InputIterator e, const A &a=A())
 [begin,end) constructor
bool push_if_not_full (const T &source)
 Enqueue an item at tail of queue if queue is not already full.
bool pop_if_present (T &destination)
 Attempt to dequeue an item from head of queue.
+iterator begin ()
+iterator end ()
+const_iterator begin () const
+const_iterator end () const

Friends

+class internal::concurrent_queue_iterator
+

Detailed Description

+

template<typename T, class A = cache_aligned_allocator<T>>
+ class tbb::deprecated::concurrent_queue< T, A >

+ +A high-performance thread-safe blocking concurrent bounded queue. +

+This is the pre-PPL TBB concurrent queue which support boundedness and blocking semantics. Note that method names agree with the PPL-style concurrent queue. Multiple threads may each push and pop concurrently. Assignment construction is not allowed. +

+


Member Function Documentation

+ +
+
+
+template<typename T, class A = cache_aligned_allocator<T>>
+ + + + + + + + + +
bool tbb::deprecated::concurrent_queue< T, A >::pop_if_present (T &  destination  )  [inline]
+
+
+ +

+Attempt to dequeue an item from head of queue. +

+Does not wait for item to become available. Returns true if successful; false otherwise.

Deprecated:
Use try_pop()
+ +
+

+ +

+
+
+template<typename T, class A = cache_aligned_allocator<T>>
+ + + + + + + + + +
bool tbb::deprecated::concurrent_queue< T, A >::push_if_not_full (const T &  source  )  [inline]
+
+
+ +

+Enqueue an item at tail of queue if queue is not already full. +

+Does not wait for queue to become not full. Returns true if item is pushed; false if queue was already full. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00275.png b/src/tbb/doc/html/a00275.png new file mode 100644 index 0000000000000000000000000000000000000000..6aac5a0687354f6cde28fbe1275fb68e0506eb1b GIT binary patch literal 720 zcmV;>0x$iEP)u2340000OP)t-s|Ns90 z00960z@MLBkN^MxkN^Mxkifved&2+Z00001bW%=J06^y0W&i*JW=TXrRCt{2mR)k( zAPj)fOP>)pfD?4u3*~9=e}w7}3>bTpI9az-;faMMAwCPq+3@@3@iY7?_YNm;f`K4q zzP)2bYPVT=x;`VK&2A#tjA`_$1Q~NqB`GE*dM>PB!B?hrs>U)9rl7pUlp;HXKkh&b~2)=S0eil}S zPY}?@?QjdV9hvh=`Pv-3jNn7V37kL)?*FxZb-Z1U@Xr(ccsRl1@%G;n++T@K-~>+K z1Ww=tPT&Mi-~>+K1m8%2H;)+N^)y@>PT&NM0QA;Wivfc;8D}0+`STtxC1^(Iyo3N_ zMAFLE5M$sTMY2UeHU<)?b6IKHXo9auF;%5+iS!KYXyO?Gtqu_)r2JhP|FDSbzlU29n@ankX%o#E>Vs3P%%U>Er1IauuUSNvyk0w=it*ZLoM3D5y2vm + +tbb::concurrent_vector< T, A > Class Template Reference + + + + + + + +

tbb::concurrent_vector< T, A > Class Template Reference
+ +[Containers] +

Concurrent vector container. +More... +

+#include <concurrent_vector.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef internal::concurrent_vector_base_v3::size_type size_type
+typedef internal::allocator_base<
+ T, A >::allocator_type 
allocator_type
+typedef T value_type
+typedef ptrdiff_t difference_type
+typedef T & reference
+typedef const T & const_reference
+typedef T * pointer
+typedef const T * const_pointer
+typedef internal::vector_iterator<
+ concurrent_vector, T > 
iterator
+typedef internal::vector_iterator<
+ concurrent_vector, const
+T > 
const_iterator
+typedef std::reverse_iterator<
+ iterator > 
reverse_iterator
+typedef std::reverse_iterator<
+ const_iterator > 
const_reverse_iterator
+typedef std::reverse_iterator<
+ iterator, T, T &, T * > 
reverse_iterator
+typedef std::reverse_iterator<
+ const_iterator, T, const
+T &, const T * > 
const_reverse_iterator
+typedef generic_range_type<
+ iterator > 
range_type
+typedef generic_range_type<
+ const_iterator > 
const_range_type

Public Member Functions

concurrent_vector (const allocator_type &a=allocator_type())
 Construct empty vector.
concurrent_vector (const concurrent_vector &vector, const allocator_type &a=allocator_type())
 Copying constructor.
+template<class M>
 concurrent_vector (const concurrent_vector< T, M > &vector, const allocator_type &a=allocator_type())
 Copying constructor for vector with different allocator type.
concurrent_vector (size_type n)
 Construction with initial size specified by argument n.
concurrent_vector (size_type n, const_reference t, const allocator_type &a=allocator_type())
 Construction with initial size specified by argument n, initialization by copying of t, and given allocator instance.
+template<class I>
 concurrent_vector (I first, I last, const allocator_type &a=allocator_type())
 Construction with copying iteration range and given allocator instance.
+concurrent_vectoroperator= (const concurrent_vector &vector)
 Assignment.
+template<class M>
concurrent_vectoroperator= (const concurrent_vector< T, M > &vector)
 Assignment for vector with different allocator type.
size_type grow_by (size_type delta)
 Grow by "delta" elements.
iterator grow_by (size_type delta)
size_type grow_by (size_type delta, const_reference t)
 Grow by "delta" elements using copying constructor.
iterator grow_by (size_type delta, const_reference t)
void grow_to_at_least (size_type n)
 Append minimal sequence of elements such that size()>=n.
iterator grow_to_at_least (size_type n)
size_type push_back (const_reference item) iterator push_back(const _reference item)
 Push item.
reference operator[] (size_type index)
 Get reference to element at given index.
+const_reference operator[] (size_type index) const
 Get const reference to element at given index.
+reference at (size_type index)
 Get reference to element at given index. Throws exceptions on errors.
+const_reference at (size_type index) const
 Get const reference to element at given index. Throws exceptions on errors.
+range_type range (size_t grainsize=1)
 Get range for iterating with parallel algorithms.
+const_range_type range (size_t grainsize=1) const
 Get const range for iterating with parallel algorithms.
+size_type size () const
 Return size of vector. It may include elements under construction.
+bool empty () const
 Return false if vector is not empty or has elements under construction at least.
+size_type capacity () const
 Maximum size to which array can grow without allocating more memory. Concurrent allocations are not included in the value.
void reserve (size_type n)
 Allocate enough space to grow to size n without having to allocate more memory later.
+void resize (size_type n)
 Resize the vector. Not thread-safe.
+void resize (size_type n, const_reference t)
 Resize the vector, copy t for new elements. Not thread-safe.
+void compact ()
 An alias for shrink_to_fit().
+void shrink_to_fit ()
 Optimize memory usage and fragmentation.
+size_type max_size () const
 Upper bound on argument to reserve.
+iterator begin ()
 start iterator
+iterator end ()
 end iterator
+const_iterator begin () const
 start const iterator
+const_iterator end () const
 end const iterator
+const_iterator cbegin () const
 start const iterator
+const_iterator cend () const
 end const iterator
+reverse_iterator rbegin ()
 reverse start iterator
+reverse_iterator rend ()
 reverse end iterator
+const_reverse_iterator rbegin () const
 reverse start const iterator
+const_reverse_iterator rend () const
 reverse end const iterator
+const_reverse_iterator crbegin () const
 reverse start const iterator
+const_reverse_iterator crend () const
 reverse end const iterator
+reference front ()
 the first item
+const_reference front () const
 the first item const
+reference back ()
 the last item
+const_reference back () const
 the last item const
+allocator_type get_allocator () const
 return allocator object
+void assign (size_type n, const_reference t)
 assign n items by copying t item
+template<class I>
void assign (I first, I last)
 assign range [first, last)
+void swap (concurrent_vector &vector)
 swap two instances
void clear ()
 Clear container while keeping memory allocated.
~concurrent_vector ()
 Clear and destroy vector.
+const internal::concurrent_vector_base_v3 & internal_vector_base () const

Friends

+class internal::vector_iterator

Classes

class  generic_range_type
class  internal_loop_guide
 Exception-aware helper class for filling a segment by exception-danger operators of user class.
+


Detailed Description

+

template<typename T, class A>
+ class tbb::concurrent_vector< T, A >

+ +Concurrent vector container. +

+concurrent_vector is a container having the following main properties:

    +
  • It provides random indexed access to its elements. The index of the first element is 0.
  • It ensures safe concurrent growing its size (different threads can safely append new elements).
  • Adding new elements does not invalidate existing iterators and does not change indices of existing items.
+

+

Compatibility
The class meets all Container Requirements and Reversible Container Requirements from C++ Standard (See ISO/IEC 14882:2003(E), clause 23.1). But it doesn't meet Sequence Requirements due to absence of insert() and erase() methods.
+
Exception Safety
Methods working with memory allocation and/or new elements construction can throw an exception if allocator fails to allocate memory or element's default constructor throws one. Concurrent vector's element of type T must conform to the following requirements:
    +
  • Throwing an exception is forbidden for destructor of T.
  • Default constructor of T must not throw an exception OR its non-virtual destructor must safely work when its object memory is zero-initialized.
+Otherwise, the program's behavior is undefined.
+
If an exception happens inside growth or assignment operation, an instance of the vector becomes invalid unless it is stated otherwise in the method documentation. Invalid state means:
    +
  • There are no guarantees that all items were initialized by a constructor. The rest of items is zero-filled, including item where exception happens.
  • An invalid vector instance cannot be repaired; it is unable to grow anymore.
  • Size and capacity reported by the vector are incorrect, and calculated as if the failed operation were successful.
  • Attempt to access not allocated elements using operator[] or iterators results in access violation or segmentation fault exception, and in case of using at() method a C++ exception is thrown.
+If a concurrent grow operation successfully completes, all the elements it has added to the vector will remain valid and accessible even if one of subsequent grow operations fails.
+
Fragmentation
Unlike an STL vector, a concurrent_vector does not move existing elements if it needs to allocate more memory. The container is divided into a series of contiguous arrays of elements. The first reservation, growth, or assignment operation determines the size of the first array. Using small number of elements as initial size incurs fragmentation that may increase element access time. Internal layout can be optimized by method compact() that merges several smaller arrays into one solid.
+
Changes since TBB 2.1
    +
  • Fixed guarantees of concurrent_vector::size() and grow_to_at_least() methods to assure elements are allocated.
  • Methods end()/rbegin()/back() are partly thread-safe since they use size() to get the end of vector
  • Added resize() methods (not thread-safe)
  • Added cbegin/cend/crbegin/crend methods
  • Changed return type of methods grow* and push_back to iterator
+
+
Changes since TBB 2.0
    +
  • Implemented exception-safety guarantees
  • Added template argument for allocator
  • Added allocator argument in constructors
  • Faster index calculation
  • First growth call specifies a number of segments to be merged in the first allocation.
  • Fixed memory blow up for swarm of vector's instances of small size
  • Added grow_by(size_type n, const_reference t) growth using copying constructor to init new items.
  • Added STL-like constructors.
  • Added operators ==, < and derivatives
  • Added at() method, approved for using after an exception was thrown inside the vector
  • Added get_allocator() method.
  • Added assign() methods
  • Added compact() method to defragment first segments
  • Added swap() method
  • range() defaults on grainsize = 1 supporting auto grainsize algorithms.
+
+ +

+


Member Function Documentation

+ +
+
+
+template<typename T, class A>
+ + + + + + + + +
void tbb::concurrent_vector< T, A >::clear (  )  [inline]
+
+
+ +

+Clear container while keeping memory allocated. +

+To free up the memory, use in conjunction with method compact(). Not thread safe +

+

+ +

+
+
+template<typename T, class A>
+ + + + + + + + + + + + + + + + + + +
iterator tbb::concurrent_vector< T, A >::grow_by (size_type  delta,
const_reference  t 
) [inline]
+
+
+ +

+Returns iterator pointing to the first new element. +

+

+ +

+
+
+template<typename T, class A>
+ + + + + + + + + + + + + + + + + + +
size_type tbb::concurrent_vector< T, A >::grow_by (size_type  delta,
const_reference  t 
) [inline]
+
+
+ +

+Grow by "delta" elements using copying constructor. +

+Returns old size. +

+

+ +

+
+
+template<typename T, class A>
+ + + + + + + + + +
iterator tbb::concurrent_vector< T, A >::grow_by (size_type  delta  )  [inline]
+
+
+ +

+Returns iterator pointing to the first new element. +

+

+ +

+
+
+template<typename T, class A>
+ + + + + + + + + +
size_type tbb::concurrent_vector< T, A >::grow_by (size_type  delta  )  [inline]
+
+
+ +

+Grow by "delta" elements. +

+Returns old size. +

+

+ +

+
+
+template<typename T, class A>
+ + + + + + + + + +
iterator tbb::concurrent_vector< T, A >::grow_to_at_least (size_type  n  )  [inline]
+
+
+ +

+The new elements are default constructed. Blocks until all elements in range [0..n) are allocated. May return while other elements are being constructed by other threads. Returns iterator that points to beginning of appended sequence. If no elements were appended, returns iterator pointing to nth element. +

+

+ +

+
+
+template<typename T, class A>
+ + + + + + + + + +
void tbb::concurrent_vector< T, A >::grow_to_at_least (size_type  n  )  [inline]
+
+
+ +

+Append minimal sequence of elements such that size()>=n. +

+The new elements are default constructed. Blocks until all elements in range [0..n) are allocated. May return while other elements are being constructed by other threads. +

+

+ +

+
+
+template<typename T, class A>
+ + + + + + + + + +
reference tbb::concurrent_vector< T, A >::operator[] (size_type  index  )  [inline]
+
+
+ +

+Get reference to element at given index. +

+This method is thread-safe for concurrent reads, and also while growing the vector, as long as the calling thread has checked that index<size(). +

+

+ +

+
+
+template<typename T, class A>
+ + + + + + + + + +
size_type tbb::concurrent_vector< T, A >::push_back (const_reference  item  )  const [inline]
+
+
+ +

+Push item. +

+Returns iterator pointing to the new element. +

+

+ +

+
+
+template<typename T, class A>
+ + + + + + + + + +
void tbb::concurrent_vector< T, A >::reserve (size_type  n  )  [inline]
+
+
+ +

+Allocate enough space to grow to size n without having to allocate more memory later. +

+Like most of the methods provided for STL compatibility, this method is *not* thread safe. The capacity afterwards may be bigger than the requested reservation. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00277.html b/src/tbb/doc/html/a00277.html new file mode 100644 index 0000000..49751ec --- /dev/null +++ b/src/tbb/doc/html/a00277.html @@ -0,0 +1,46 @@ + + +tbb::flow::interface6::continue_msg Class Reference + + + + + + + +

tbb::flow::interface6::continue_msg Class Reference

An empty class used for messages that mean "I'm done". +More... +

+#include <flow_graph.h> +

+ + +
+


Detailed Description

+An empty class used for messages that mean "I'm done". +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00278.html b/src/tbb/doc/html/a00278.html new file mode 100644 index 0000000..a9d32b0 --- /dev/null +++ b/src/tbb/doc/html/a00278.html @@ -0,0 +1,94 @@ + + +tbb::flow::interface6::continue_node< Output > Class Template Reference + + + + + + + +

tbb::flow::interface6::continue_node< Output > Class Template Reference

Implements an executable node that supports continue_msg -> Output. +More... +

+#include <flow_graph.h> +

+

Inheritance diagram for tbb::flow::interface6::continue_node< Output >: +

+ +tbb::flow::interface6::graph_node + +List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef continue_msg input_type
+typedef Output output_type
+typedef sender< input_typepredecessor_type
+typedef receiver< output_type > successor_type
+typedef internal::function_output<
+ output_type > 
fOutput_type

Public Member Functions

+template<typename Body>
 continue_node (graph &g, Body body)
 Constructor for executable node with continue_msg -> Output.
+template<typename Body>
 continue_node (graph &g, int number_of_predecessors, Body body)
 Constructor for executable node with continue_msg -> Output.
continue_node (const continue_node &src)
 Copy constructor.
+bool try_put (const input_type &i)

Protected Member Functions

+internal::broadcast_cache<
+ output_type > & 
successors ()
+

Detailed Description

+

template<typename Output>
+ class tbb::flow::interface6::continue_node< Output >

+ +Implements an executable node that supports continue_msg -> Output. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00278.png b/src/tbb/doc/html/a00278.png new file mode 100644 index 0000000000000000000000000000000000000000..97eb6dbf0cc935c9de948c38c3636ec430beb03d GIT binary patch literal 777 zcmeAS@N?(olHy`uVBq!ia0y~yVB`m~16Y`WxfF2H_=X zdM2yy{O4$vOAshqZe3Wu=Yc<$w918chm~GGs(J4onqR}IE3lsRQ7Ox$q9<?%)Z)|e zDaPmZ)(PF8lXS=X_HqTy=^s|QJl8k(bXekVc0xaGiu`YwtYFShnV~Z0FY%GAE47mxTH5oqjRk&8MuZCnQx?OVt%D$T+Ndl<&#S zRh6z{uRe&>ajIAeELyDc$G~G%>c@9IHY-^lZFSg__weq2WuNT@O?KxZp76x7J^A0mtnAob9q6&!heK$okHWPkuRbHtSpA60KKGvyw9W40Nu1Es)v+zP6JGV;qqRbRspJGtaELuj{pa_GT_xoayX8XNE?~N4@O1TaS?83{ F1OS1`T8#hz literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/a00279.html b/src/tbb/doc/html/a00279.html new file mode 100644 index 0000000..ca025d5 --- /dev/null +++ b/src/tbb/doc/html/a00279.html @@ -0,0 +1,168 @@ + + +tbb::flow::interface6::continue_receiver Class Reference + + + + + + + +

tbb::flow::interface6::continue_receiver Class Reference

Base class for receivers of completion messages. +More... +

+#include <flow_graph.h> +

+

Inheritance diagram for tbb::flow::interface6::continue_receiver: +

+ +tbb::flow::interface6::receiver< T > + +List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef continue_msg input_type
 The input type.
+typedef sender< continue_msgpredecessor_type
 The predecessor type for this node.

Public Member Functions

continue_receiver (int number_of_predecessors=0)
 Constructor.
continue_receiver (const continue_receiver &src)
 Copy constructor.
+virtual ~continue_receiver ()
 Destructor.
+bool register_predecessor (predecessor_type &)
 Increments the trigger threshold.
bool remove_predecessor (predecessor_type &)
 Decrements the trigger threshold.
bool try_put (const input_type &)
 Puts a continue_msg to the receiver.

Protected Member Functions

virtual void execute ()=0
 Does whatever should happen when the threshold is reached.

Protected Attributes

+spin_mutex my_mutex
+int my_predecessor_count
+int my_current_count
+int my_initial_predecessor_count
+

Detailed Description

+Base class for receivers of completion messages. +

+These receivers automatically reset, but cannot be explicitly waited on +

+


Member Function Documentation

+ +
+
+ + + + + + + + +
virtual void tbb::flow::interface6::continue_receiver::execute (  )  [protected, pure virtual]
+
+
+ +

+Does whatever should happen when the threshold is reached. +

+This should be very fast or else spawn a task. This is called while the sender is blocked in the try_put(). +

+

+ +

+
+ + + + + + + + + +
bool tbb::flow::interface6::continue_receiver::remove_predecessor (predecessor_type  )  [inline]
+
+
+ +

+Decrements the trigger threshold. +

+Does not check to see if the removal of the predecessor now makes the current count exceed the new threshold. So removing a predecessor while the graph is active can cause unexpected results. +

+

+ +

+
+ + + + + + + + + +
bool tbb::flow::interface6::continue_receiver::try_put (const input_type  )  [inline]
+
+
+ +

+Puts a continue_msg to the receiver. +

+If the message causes the message count to reach the predecessor count, execute() is called and the message count is reset to 0. Otherwise the message count is incremented. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00279.png b/src/tbb/doc/html/a00279.png new file mode 100644 index 0000000000000000000000000000000000000000..b14a696a13841c0a25d2531150ab622314a39f9b GIT binary patch literal 668 zcmV;N0%QG&P)1RCt{2mRph= zAq+*)&wT5$1IP}N4du)GU&07I8fbewU7np>i9vrQA2m zrQ0Y0$`Dy8zHWngHEI5wDURYGF72zX>aA<|W}CQChhp<>UCU+@slS7E_<-qNDhvPI zE!jV{EliV3q}X3(VCHyw>+uj1@S~t8Ak;0FP^J!&RFy`x`GAAWoToTz#AcQ<@ZZ4-!7MzV7^SnrN@5l7cHkc=K+ALxkEZE)k{^e<2?3jG*8xHej=(gxUQyiF)NW-A^;{lT&DrU4L zgebqOHcEgpL{@A=Mchtcb+;?>D0c(V7NU?yK&&=u7VX$9=AgaarVYeh?IP+MtzneM zoOsA>NJD4u(;YnNOs-*9r+z9;2gMcB%uGj_fH4Vr2+-9xnDPi_!zh<8aG%LM#hD^j z>ZA|j9ICO)BgXxEb|%HoWXdh?6F9w?w^6rIE@Ag~u)5XUk{6;@D{ZqT z@*3%NJC`}zJeVi9zr!SW9i7O$-xhN*zs`KZf6aG=@RpESZF1BA0000 + +tbb::empty_task Class Reference + + + + + + + +

tbb::empty_task Class Reference
+ +[Task Scheduling] +

task that does nothing. Useful for synchronization. +More... +

+#include <task.h> +

+

Inheritance diagram for tbb::empty_task: +

+ +tbb::task + +List of all members. + +
+

Detailed Description

+task that does nothing. Useful for synchronization. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00280.png b/src/tbb/doc/html/a00280.png new file mode 100644 index 0000000000000000000000000000000000000000..2fa6419d1f5dfa4998aba972087dbec76e15f778 GIT binary patch literal 387 zcmeAS@N?(olHy`uVBq!ia0vp^i9j5{!VDyT^RdkUQW60^A+G=b{|7Sv|35H)e!>JG z3ycpOI8c4){}UjWu_VYZn8D%MjWi%z($mE;q+-t7Dban06?j}f`tPs3$+#xLWb?wh z)c@WR_6s-zy7JTv?qp!9SF|K=IDzXq}-x%hc@3#Cjy z+PkuzZHZIXpXb?cgfD8x_I4gQYnR3p5X#)Lc6;blJFSO*zjRowUa`iY2kGm$%p(`aZwgnSSP#0^cJbddk5g#V%*_dojnSA4y9oAea6MrfArSI~c~#cz z54pV}hli+WYs2{*gNd3^4{zS3j3^P6 + +tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > Class Template Reference + + + + + + + +

tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type > Class Template Reference
+ +[Containers] +

The enumerable_thread_specific container. +More... +

+#include <enumerable_thread_specific.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef Allocator allocator_type
 Basic types.
+typedef T value_type
+typedef T & reference
+typedef const T & const_reference
+typedef T * pointer
+typedef const T * const_pointer
+typedef internal_collection_type::size_type size_type
+typedef internal_collection_type::difference_type difference_type
+typedef internal::enumerable_thread_specific_iterator<
+ internal_collection_type,
+ value_type > 
iterator
+typedef internal::enumerable_thread_specific_iterator<
+ internal_collection_type,
+ const value_type > 
const_iterator
+typedef generic_range_type<
+ iterator > 
range_type
+typedef generic_range_type<
+ const_iterator > 
const_range_type

Public Member Functions

enumerable_thread_specific ()
 Default constructor. Each local instance of T is default constructed.
+template<typename Finit>
 enumerable_thread_specific (Finit finit)
 Constructor with initializer functor. Each local instance of T is constructed by T(finit()).
enumerable_thread_specific (const T &exemplar)
 Constuctor with exemplar. Each local instance of T is copied-constructed from the exemplar.
~enumerable_thread_specific ()
 Destructor.
+reference local ()
 returns reference to local, discarding exists
+reference local (bool &exists)
 Returns reference to calling thread's local copy, creating one if necessary.
+size_type size () const
 Get the number of local copies.
+bool empty () const
 true if there have been no local copies created
+iterator begin ()
 begin iterator
+iterator end ()
 end iterator
+const_iterator begin () const
 begin const iterator
+const_iterator end () const
 end const iterator
+range_type range (size_t grainsize=1)
 Get range for parallel algorithms.
+const_range_type range (size_t grainsize=1) const
 Get const range for parallel algorithms.
+void clear ()
 Destroys local copies.
+template<typename U, typename Alloc, ets_key_usage_type Cachetype>
 enumerable_thread_specific (const enumerable_thread_specific< U, Alloc, Cachetype > &other)
enumerable_thread_specific (const enumerable_thread_specific &other)
+enumerable_thread_specificoperator= (const enumerable_thread_specific &other)
+template<typename U, typename Alloc, ets_key_usage_type Cachetype>
enumerable_thread_specificoperator= (const enumerable_thread_specific< U, Alloc, Cachetype > &other)
+template<typename combine_func_t>
combine (combine_func_t f_combine)
+template<typename combine_func_t>
void combine_each (combine_func_t f_combine)

Friends

+class enumerable_thread_specific

Classes

class  generic_range_type
 A generic range, used to create range objects from the iterators.
+


Detailed Description

+

template<typename T, typename Allocator = cache_aligned_allocator<T>, ets_key_usage_type ETS_key_type = ets_no_key>
+ class tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >

+ +The enumerable_thread_specific container. +

+enumerable_thread_specific has the following properties:

    +
  • thread-local copies are lazily created, with default, exemplar or function initialization.
  • thread-local copies do not move (during lifetime, and excepting clear()) so the address of a copy is invariant.
  • the contained objects need not have operator=() defined if combine is not used.
  • enumerable_thread_specific containers may be copy-constructed or assigned.
  • thread-local copies can be managed by hash-table, or can be accessed via TLS storage for speed.
  • outside of parallel contexts, the contents of all thread-local copies are accessible by iterator or using combine or combine_each methods
+

+

Segmented iterator
When the thread-local objects are containers with input_iterators defined, a segmented iterator may be used to iterate over all the elements of all thread-local copies.
+
combine and combine_each
    +
  • Both methods are defined for enumerable_thread_specific.
  • combine() requires the the type T have operator=() defined.
  • neither method modifies the contents of the object (though there is no guarantee that the applied methods do not modify the object.)
  • Both are evaluated in serial context (the methods are assumed to be non-benign.)
+
+ +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00282.html b/src/tbb/doc/html/a00282.html new file mode 100644 index 0000000..f2cc50d --- /dev/null +++ b/src/tbb/doc/html/a00282.html @@ -0,0 +1,236 @@ + + +tbb::filter Class Reference + + + + + + + +

tbb::filter Class Reference
+ +[Algorithms] +

A stage in a pipeline. +More... +

+#include <pipeline.h> +

+

Inheritance diagram for tbb::filter: +

+ +tbb::thread_bound_filter + +List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Member Functions

+bool is_serial () const
 True if filter is serial.
+bool is_ordered () const
 True if filter must receive stream in order.
+bool is_bound () const
 True if filter is thread-bound.
+bool object_may_be_null ()
 true if an input filter can emit null
virtual void * operator() (void *item)=0
 Operate on an item from the input stream, and return item for output stream.
virtual __TBB_EXPORTED_METHOD ~filter ()
 Destroy filter.
virtual void finalize (void *)
 Destroys item if pipeline was cancelled.

Protected Member Functions

x1 ((is_serial_?serial:parallel)|exact_exception_propagation))
prev_filter_in_pipeline (not_in_pipeline())
my_pipeline (NULL)
next_segment (NULL)
filter (mode filter_mode)
+void __TBB_EXPORTED_METHOD set_end_of_input ()

Static Protected Attributes

+static const unsigned char filter_is_serial = 0x1
 The lowest bit 0 is for parallel vs. serial.
static const unsigned char filter_is_out_of_order = 0x1<<4
 4th bit distinguishes ordered vs unordered filters.
+static const unsigned char filter_is_bound = 0x1<<5
 5th bit distinguishes thread-bound and regular filters.
+static const unsigned char filter_may_emit_null = 0x1<<6
 6th bit marks input filters emitting small objects
static const unsigned char exact_exception_propagation
 7th bit defines exception propagation mode expected by the application.

Friends

+class internal::stage_task
+class internal::pipeline_root_task
+class pipeline
+class thread_bound_filter
+

Detailed Description

+A stage in a pipeline. +

+


Constructor & Destructor Documentation

+ +
+
+ + + + + + + + +
virtual __TBB_EXPORTED_METHOD tbb::filter::~filter (  )  [virtual]
+
+
+ +

+Destroy filter. +

+If the filter was added to a pipeline, the pipeline must be destroyed first. +

+

+


Member Function Documentation

+ +
+
+ + + + + + + + + +
virtual void tbb::filter::finalize (void *   )  [inline, virtual]
+
+
+ +

+Destroys item if pipeline was cancelled. +

+Required to prevent memory leaks. Note it can be called concurrently even for serial filters. +

+

+ +

+
+ + + + + + + + + +
virtual void* tbb::filter::operator() (void *  item  )  [pure virtual]
+
+
+ +

+Operate on an item from the input stream, and return item for output stream. +

+Returns NULL if filter is a sink. +

+

+


Member Data Documentation

+ +
+
+ + + + +
const unsigned char tbb::filter::exact_exception_propagation [static, protected]
+
+
+ +

+Initial value:

+#if TBB_USE_CAPTURED_EXCEPTION
+            0x0
+
7th bit defines exception propagation mode expected by the application. +

+ +

+

+ +

+
+ + + + +
const unsigned char tbb::filter::filter_is_out_of_order = 0x1<<4 [static, protected]
+
+
+ +

+4th bit distinguishes ordered vs unordered filters. +

+The bit was not set for parallel filters in TBB 2.1 and earlier, but is_ordered() function always treats parallel filters as out of order. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00282.png b/src/tbb/doc/html/a00282.png new file mode 100644 index 0000000000000000000000000000000000000000..e668b177ced5ac5f9611b3a1342a1524ab4a655a GIT binary patch literal 433 zcmV;i0Z#sjP)q3eF0000OP)t-s|Ns90 z00960z@MLBkN^MxkN^Mxkifved&2+Z00001bW%=J06^y0W&i*IM@d9MRCt{2m06C% zAPhj^XTGs-U`|j?FH~uy-2Vt;8%SZ)#Ys?=k!%zeV;)`-CBP&}A%!{Oq@$!LJF(7F zitnzpky2gmBSA_KVwCL&Aw}-^or!UePjX(O5_ihT?Wt$4qtnC1s*#?7wvhm4kwVx> zs(A{BqieNm885ZlLE0)#a*~kd{iQ5&o8=Eeoa7`YImt;*`uC)( zL4FK2m++nEh?6#uD5G>LNTUI*-Ctz}>a7ouXtY)mAVMZW*#;SjSjTg{SG1%nk~>!= zpsY}=5Lcgo>8Q@?s1G}evLhs{t72J|xg6jIeROJ8{B13-O1hiis4OIWMFI{6EF^$8 zB$*n0$~~#(X^ieco}gDgimug8jH*XkI~r@JZ;&Lo^QqJ>fA(wP+=E4V+Ar8i29o73 bWs%D-pS=nQvleeV00000NkvXXu0mjfQ6sy> literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/a00283.html b/src/tbb/doc/html/a00283.html new file mode 100644 index 0000000..a7e2944 --- /dev/null +++ b/src/tbb/doc/html/a00283.html @@ -0,0 +1,76 @@ + + +tbb::interface6::filter_t< T, U > Class Template Reference + + + + + + + +

tbb::interface6::filter_t< T, U > Class Template Reference

Class representing a chain of type-safe pipeline filters. +More... +

+#include <pipeline.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + +

Public Member Functions

filter_t (const filter_t< T, U > &rhs)
+template<typename Body>
 filter_t (tbb::filter::mode mode, const Body &body)
+void operator= (const filter_t< T, U > &rhs)
+void clear ()

Friends

+class internal::pipeline_proxy
+template<typename T_, typename U_, typename Body>
filter_t< T_, U_ > make_filter (tbb::filter::mode, const Body &)
 Create a filter to participate in parallel_pipeline.
+template<typename T_, typename V_, typename U_>
filter_t< T_, U_ > operator & (const filter_t< T_, V_ > &, const filter_t< V_, U_ > &)
+


Detailed Description

+

template<typename T, typename U>
+ class tbb::interface6::filter_t< T, U >

+ +Class representing a chain of type-safe pipeline filters. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00284.html b/src/tbb/doc/html/a00284.html new file mode 100644 index 0000000..7d3edb6 --- /dev/null +++ b/src/tbb/doc/html/a00284.html @@ -0,0 +1,53 @@ + + +tbb::final_scan_tag Struct Reference + + + + + + + +

tbb::final_scan_tag Struct Reference
+ +[Algorithms] +

Used to indicate that the final scan is being performed. +More... +

+#include <parallel_scan.h> +

+List of all members. + + + + +

Static Public Member Functions

+static bool is_final_scan ()
+


Detailed Description

+Used to indicate that the final scan is being performed. +

+


The documentation for this struct was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00285.html b/src/tbb/doc/html/a00285.html new file mode 100644 index 0000000..e7c54d5 --- /dev/null +++ b/src/tbb/doc/html/a00285.html @@ -0,0 +1,54 @@ + + +tbb::interface6::flow_control Class Reference + + + + + + + +

tbb::interface6::flow_control Class Reference

input_filter control to signal end-of-input for parallel_pipeline +More... +

+#include <pipeline.h> +

+List of all members. + + + + + + + +

Public Member Functions

+void stop ()

Friends

+class internal::concrete_filter
+


Detailed Description

+input_filter control to signal end-of-input for parallel_pipeline +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00286.html b/src/tbb/doc/html/a00286.html new file mode 100644 index 0000000..3b12c8b --- /dev/null +++ b/src/tbb/doc/html/a00286.html @@ -0,0 +1,94 @@ + + +tbb::flow::interface6::function_node< Input, Output,, Allocator > Class Template Reference + + + + + + + +

tbb::flow::interface6::function_node< Input, Output,, Allocator > Class Template Reference

Implements a function node that supports Input -> Output. +More... +

+#include <flow_graph.h> +

+

Inheritance diagram for tbb::flow::interface6::function_node< Input, Output,, Allocator >: +

+ +tbb::flow::interface6::graph_node + +List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef Input input_type
+typedef Output output_type
+typedef sender< input_type > predecessor_type
+typedef receiver< output_type > successor_type
+typedef internal::function_input<
+ input_type, output_type,
+ Allocator > 
fInput_type
+typedef internal::function_output<
+ output_type > 
fOutput_type

Public Member Functions

+template<typename Body>
 function_node (graph &g, size_t concurrency, Body body)
 Constructor.
function_node (const function_node &src)
 Copy constructor.
+bool try_put (const input_type &i)

Protected Member Functions

+internal::broadcast_cache<
+ output_type > & 
successors ()
+

Detailed Description

+

template<typename Input, typename Output = continue_msg, graph_buffer_policy = queueing, typename Allocator = cache_aligned_allocator<Input>>
+ class tbb::flow::interface6::function_node< Input, Output,, Allocator >

+ +Implements a function node that supports Input -> Output. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00286.png b/src/tbb/doc/html/a00286.png new file mode 100644 index 0000000000000000000000000000000000000000..75bb777b867b6114d8c5d8f981d091fc3b23e6bc GIT binary patch literal 942 zcmeAS@N?(olHy`uVBq!ia0y~yU@QQ#16Y`WEaktG3V_J?@5mpc-j(;vybo=+)sGs zw5I64GLO(CMtiH=(wwQQ|18%&HpwAA#c|i8e|JOPy)W^uwS6G|nsI-W`@zd1AJ_IJ z%h+6gqq*)J^IzYqmp1iPEWh7yywr|S-aas@O|rqc$3RspqiGUSQv74$>Dl9dQtv&uJ@Pmoyosf)={P%?#FWYVqWPh{7dr{%cP}!AjL6R04 zM}bNb3)E&Uo7sEI-DYCE@I4=oXyNP-U(hY~SA#y2fDzq_@rf%(y@1rj*0#9NqMKfniUCX%T)HQ~v z)NF>eKuuxfNk26fZ=Zdt)p&K$yg$r!8|6N%c75e3`T1>C5Xch5BT;KYZZbFnELVO_GK@tYZ&dm zSuCH_8{j|n+OG|~a&8~i9e)}!u~s6g|7z*M!qq>vonO8E%+iPn%u5>c=V*PMQFP&( zK|qy~Kyk(c-RKp|yJWPg?@Os`tzq;2+~48H$lmZb^!Cn;$@hLLMW5L4$lmDvt9$=b o?gsMzxVp=5$Jg^bQGeNwoS)v-Z}`6yn7J4{UHx3vIVCg!07>h!+W-In literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/a00287.html b/src/tbb/doc/html/a00287.html new file mode 100644 index 0000000..44f643a --- /dev/null +++ b/src/tbb/doc/html/a00287.html @@ -0,0 +1,98 @@ + + +tbb::flow::interface6::function_node< Input, Output, queueing, Allocator > Class Template Reference + + + + + + + +

tbb::flow::interface6::function_node< Input, Output, queueing, Allocator > Class Template Reference

Implements a function node that supports Input -> Output. +More... +

+#include <flow_graph.h> +

+

Inheritance diagram for tbb::flow::interface6::function_node< Input, Output, queueing, Allocator >: +

+ +tbb::flow::interface6::graph_node + +List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef Input input_type
+typedef Output output_type
+typedef sender< input_type > predecessor_type
+typedef receiver< output_type > successor_type
+typedef internal::function_input<
+ input_type, output_type,
+ Allocator > 
fInput_type
+typedef internal::function_input_queue<
+ input_type, Allocator > 
queue_type
+typedef internal::function_output<
+ output_type > 
fOutput_type

Public Member Functions

+template<typename Body>
 function_node (graph &g, size_t concurrency, Body body)
 Constructor.
function_node (const function_node &src)
 Copy constructor.
+bool try_put (const input_type &i)

Protected Member Functions

+internal::broadcast_cache<
+ output_type > & 
successors ()
+

Detailed Description

+

template<typename Input, typename Output, typename Allocator>
+ class tbb::flow::interface6::function_node< Input, Output, queueing, Allocator >

+ +Implements a function node that supports Input -> Output. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00287.png b/src/tbb/doc/html/a00287.png new file mode 100644 index 0000000000000000000000000000000000000000..349b919a04af911c14ecd9f87d13df19b88d3407 GIT binary patch literal 1016 zcmeAS@N?(olHy`uVBq!ia0y~yU|a!Y2e2>$$$eUXjDeIyfKQ0)|NsAi%>Vxn%%7hy z0muU50|yRNANv0U$Ym@E@(X5gcy=R=fq}Wt)5S5QV$RzL$D$_+JT0f^sn#`oZobQ3 zcy|Hi!?#OQq^Y~b8ldd+v8 zS68BVsqw5~o7)v@pZ(znw#2{LqPfPU)luY8_R*IKs#>Qib_XpD0eYPq~NjS29#r)WXi~^lFcOLagD`f z!WzyDg-GEG4x7{#G^Y4EFq5yqN>4OSfUmE*-u>YHMSe}uS0V#kKDwJSl;mx%+O+zk zLeDbx_w38OBcFR-T~_g>t9rBiWZvCnixU3FoV>C6YxQMgyK1?4;^$p>`&;S-S{Yu{ zRKA{VKyyFU42Jc;R{olFnG%eH>`L|i)iQ9*WEed8A&$}vCX&(6QqG+|VWYG(SoQIE| zy*sS$!dNo3C`ea7WM81>_x)3gvX6y{?AUsJ=E*%lH_WD#XP>!HSL>hCdt=^8$B_DE z7E@*RSpD6$SS`&ec;8+9*LyWyxSFPWEt`La<;JgV&s>hbeZGBW@ZKr&k^}J%gTfL%}^UBNTEXV)5GVVTl#wOkLr_fwSR}m$Xf_ zra!w`XBU4yF=D0u+07dN((3wN|8uN1y|d_CQ+L-UP)hp8G-Ko6U7r_sx&yN*gQu&X J%Q~loCIB-c+S&jB literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/a00288.html b/src/tbb/doc/html/a00288.html new file mode 100644 index 0000000..39862a8 --- /dev/null +++ b/src/tbb/doc/html/a00288.html @@ -0,0 +1,276 @@ + + +tbb::flow::interface6::graph Class Reference + + + + + + + +

tbb::flow::interface6::graph Class Reference

The graph class. +More... +

+#include <flow_graph.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef graph_iterator< graph,
+ graph_node
iterator
+typedef graph_iterator< const
+graph, const graph_node
const_iterator

Public Member Functions

graph ()
 Constructs a graph with isolated task_group_context.
graph (task_group_context &use_this_context)
 Constructs a graph with use_this_context as context.
 ~graph ()
 Destroys the graph.
void increment_wait_count ()
 Used to register that an external entity may still interact with the graph.
void decrement_wait_count ()
 Deregisters an external entity that may have interacted with the graph.
template<typename Receiver, typename Body>
void run (Receiver &r, Body body)
 Spawns a task that runs a body and puts its output to a specific receiver.
template<typename Body>
void run (Body body)
 Spawns a task that runs a function object.
void wait_for_all ()
 Wait until graph is idle and decrement_wait_count calls equals increment_wait_count calls.
+taskroot_task ()
 Returns the root task of the graph.
+iterator begin ()
 start iterator
+iterator end ()
 end iterator
+const_iterator begin () const
 start const iterator
+const_iterator end () const
 end const iterator
+const_iterator cbegin () const
 start const iterator
+const_iterator cend () const
 end const iterator
+bool is_cancelled ()
 return status of graph execution
+bool exception_thrown ()

Friends

+class graph_node
+class graph_iterator

Classes

class  run_and_put_task
class  run_task
+


Detailed Description

+The graph class. +

+This class serves as a handle to the graph +

+


Constructor & Destructor Documentation

+ +
+
+ + + + + + + + +
tbb::flow::interface6::graph::~graph (  )  [inline]
+
+
+ +

+Destroys the graph. +

+Calls wait_for_all, then destroys the root task and context. +

+

+


Member Function Documentation

+ +
+
+ + + + + + + + +
void tbb::flow::interface6::graph::decrement_wait_count (  )  [inline]
+
+
+ +

+Deregisters an external entity that may have interacted with the graph. +

+The graph will not return from wait_for_all until all the number of decrement_wait_count calls matches the number of increment_wait_count calls. +

+

+ +

+
+ + + + + + + + +
void tbb::flow::interface6::graph::increment_wait_count (  )  [inline]
+
+
+ +

+Used to register that an external entity may still interact with the graph. +

+The graph will not return from wait_for_all until a matching number of decrement_wait_count calls is made. +

+

+ +

+
+
+template<typename Body>
+ + + + + + + + + +
void tbb::flow::interface6::graph::run (Body  body  )  [inline]
+
+
+ +

+Spawns a task that runs a function object. +

+The task is spawned as a child of the graph. This is useful for running tasks that need to block a wait_for_all() on the graph. For example a one-off source. +

+

+ +

+
+
+template<typename Receiver, typename Body>
+ + + + + + + + + + + + + + + + + + +
void tbb::flow::interface6::graph::run (Receiver &  r,
Body  body 
) [inline]
+
+
+ +

+Spawns a task that runs a body and puts its output to a specific receiver. +

+The task is spawned as a child of the graph. This is useful for running tasks that need to block a wait_for_all() on the graph. For example a one-off source. +

+

+ +

+
+ + + + + + + + +
void tbb::flow::interface6::graph::wait_for_all (  )  [inline]
+
+
+ +

+Wait until graph is idle and decrement_wait_count calls equals increment_wait_count calls. +

+The waiting thread will go off and steal work while it is block in the wait_for_all. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00289.html b/src/tbb/doc/html/a00289.html new file mode 100644 index 0000000..8fa3c46 --- /dev/null +++ b/src/tbb/doc/html/a00289.html @@ -0,0 +1,80 @@ + + +tbb::flow::interface6::graph_node Class Reference + + + + + + + +

tbb::flow::interface6::graph_node Class Reference

The base of all graph nodes. +More... +

+#include <flow_graph.h> +

+

Inheritance diagram for tbb::flow::interface6::graph_node: +

+ +tbb::flow::interface6::broadcast_node< T > +tbb::flow::interface6::buffer_node< T, A > +tbb::flow::interface6::continue_node< Output > +tbb::flow::interface6::function_node< Input, Output,, Allocator > +tbb::flow::interface6::function_node< Input, Output, queueing, Allocator > +tbb::flow::interface6::limiter_node< T > +tbb::flow::interface6::multifunction_node< Input, Output,, Allocator > +tbb::flow::interface6::multifunction_node< TupleType, TupleType, rejecting, Allocator > +tbb::flow::interface6::source_node< Output > + +List of all members. + + + + + + + + + + + + + + + + +

Public Member Functions

graph_node (graph &g)

Protected Attributes

+graphmy_graph
+graph_nodenext
+graph_nodeprev

Friends

+class graph
+class graph_iterator
+

Detailed Description

+The base of all graph nodes. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00289.png b/src/tbb/doc/html/a00289.png new file mode 100644 index 0000000000000000000000000000000000000000..9d49991d79a9b65847274ea1fa807e3ba14d3cc1 GIT binary patch literal 5357 zcmdT|X;f2Ly2XLEq!66J5=@~_aX>&pW{3?^;J{4697F_}5{fBdN}`1l5g}D20*a6l zgaBa>83Ke5m8mp_XhE1l5`_ZfVhGbE5KPjsdcAsG-POI;TdVr5en0NI=bpRnIp4b9 z-rwHe$#8Xc*rM`1~2~ zRl8UQ2g%yONzIw;PS|G@`8o@ir$-(*U%5MNrZz=?TLd7YvJ5<8iW+nWSo6a5}*!(YL*q*#`}BJZ6j7 zmg~fRgwdm*owqpLLGuN*<9nS~$R8?30<82ScTbZWB ztO913%5UB2wV>d%X!BvrN>{9RHV{joj=m!st&yOsYVw>WXXcIGD@7h7m(|+oDQ|;oHG7-e$+O@|L;sgnQ#=%e(E^kpxA3n3maA)xb zO_ew6RByajO1F(yveU7+`f%%CzxqR7tIAj9#2bZ)bseNt_EN>i5M9KFxin7jO>Nxc zWYxM3bvRK6z48n=(WwTFcY}7XG8eEn3r_X5hN`e`-v9F&pT5Sd*3c))i5P z?=2{MlY6SCPBI?n{j*bFglWLW${+J4<8tj>x zdnnnuo1wFZsAKFmCBIRL<0rPcLu^d~MY`%e=^T05qM*a0nJjzNddQhF5z|sY^9(#_ zK>98b+wY=)Qs2BU6b5>jN15t=%o=Y1n|)Ffsv+2FxwA#N!EbQ1LuQtnvJx`0ss?3b z&uGhhz%evGQ#8leA~#XD{V>@*yosz%(!V~MmDTT2b65VS&$ zxPSfHn1}Zq53FOg@Urg038)e<0510n-I^F(Z{qcc%KrAo7k)?T_7ht3FDB||F$tQ!uEzTyG$LKRD zoJ5CM-749SAC3#r=ij_=_qo$g9@H^-U>k1t;)dgRYr>HpKaC45TXjW2HZSc;+J~3N zEG~h8lXIIHniQmci>zF;#yT&lVDy_Np*^=;kb8i$z-_cWLV>>LE5ha5fjW9Xu;UY3 zZz|sn@?;Wxv^BT2e=k66!LWJPUT|U1?1B>9Q3qU&RXe%;LxVY>3jqaRks_s@oWc6# z$?H%=5r?Z>;7j`o8&^%rZE8rq@-7m)DZ4^J;E8OMo_+d>z`?i)-fC}KbzOGkLoh#O zcEFeBes_@n&Ojaj6+QACS15!bLr6`MTCl6yxt_~!Q_12V8u|g+JOY3OgS-_auoeV1 ztW%|sw_NnLMk;mumEVfmzsYj`62VmK-(1`O1-s`;b{$q!^p$HzKk>F|pWW{i{dZ@< z(&v{BMeTF7a-O+gfh|wK5?bMg=Xg+)TUIXI z9?V>Bu9bx{0&c_c-(KmTLbt?kBq)|T{^T4?Bd((>^{R=Jh6m4r9yi-|UgRG!k7^jc z>z?I)8AB83QvyFgB0;7z1*goM7#&6X_Qj zg4uJ}(MoZn%)H1waCRHx0KF8g(lv7{fdTee%TULpiQiDo$JKQf*qtKja zuh}E9`6qq#N|RlJK{lJi-dfw<;y+rk^b%NmHJ;bZ4ILcq5O}Ay4V?@Ev6FQW)9h)S z6s=4V*_1Mr{|;-Pv_#@kY(A8sVcGWXk2DVd0$jgmS|HV@Kk0_L=d)kc;vZ0F%3%c8 z^QsGfu4edRL&3Ghg>)8LoLCC>0%G!l@V>CufIL!M=NWY!yuNg9rjR3IGij%|T}v6m zp1kW5%OocV1|Tq;9>?bO z0dGQS$^EqlOn|@$`l1{Dyfoz$w=@zP#t#%Hl*)z`s|iSX;)te#h3_Y&Nw+stW8nB` zG%me|g&sUMm|)-)#f5vSB2G^+W<3El!Jc|^j}hB2L&5dgJrlr<6Sd()5ZB; z=Adr0rX3py!9Z%HDsVygem`)$v8x!jcJF3^y_f?%Y_ekUX}ZHK_bZy`EsgH7?UdzS zR>)bWD_>ng4S3%d<}S1~=tUc6v*Os*?FQ0piLck4V_{=I!93R%+@B2(E%$Z)RK9(z zId_VcLa|OdALH!L^;|1ls&4N))1>TxoOTPSH__$5D@Tgp@<7Rj5n1s<%#RLOQw62N z_d_aOVDWJzm}7TbFt5Q4^1M;9^<{NXxYumXkTs_8P^^p843#aZ&{}Ody6P)67HWZa zh!WAmwMJa!Sj3Cr$?FX3JQuOcO8Wr*0IxsK@?)%nY3}+?_uzcW!esJHnXGlbh`AX0 za$hPzp0z?v+N!7nd^hZ84o6=V^#J%wxq|J#!^2-Z9ez9OnRDCFyDfx&lcE17iT>MW z;$xWdC$E6}LFMoK+utxUvAo?F{_1+Ok5P4`iL!D`AN;Yg*6jji+6E!ckD#_n&nxI; zYTL+NkrW0Lnk6yon&H4s)1v%BO%Y98p?bp_QagEd(pPHcE2WHjLF|q;IrjJiM^v1m zVG&J^ocN%q%;UM3$(MJ`MEi44^-Jju^H113TiOX?OS~Y26plH64-wE-SzAI4NrK}^ z1P83Jf|+&d?0e0~3SO!O8>X97@VH^%x_h#R&BpQ8FNH?fBJ?@bzzOC$>l(U`a4cNt z?c-1@3?ur+R>{7TguoY#H4+k7zR^3+XTT2cx{?Pl53y`8p9@VCqCmv-yY$@;Oa8zI z)GJ*$@h5mUvnt}6QBoM#_C+AyspH*#3D;{C(Y8kRmyXjC(E^^5vKwq*7j6gWO1IjsftH-VqqR?s>Z;hQc3|Y_f8N0KDas zO2v z^>U#~W+Ret+xB*)v&KrY!r=I?*QP6gyF|_lwyAttFUdGk@5dlg`SXdHTk>Wgu(v+eo}s44 zg?r9N2b62;GP$JDF{{+Wr@jb()ex&?3Pi)-`bax-hC}Kew#8LbD|B-Rew~fN(5OoE zz~UfJ#fn18KS_(d5O}k&re838i5sgSsvfOS>~y6cZ+9=?n2DZ~y^j;UFs0evzqnIt z##UOQVkI6GQsm1gX~GlqQR3h>bhdegCkX7luypuGFU_+OLx9I2p!A9U_)eVsDmqm|{QITRC855kzRGxRsLp}pY z56bZn*)i=ArLI5uc*bi)FdczfM`7$#^z;6vEB|!~w=FIpppBP7-N}96m397LcOToDk;#D+ zFiHuidnZ5?to5|z>w4ZAc>Gtm}rl!iXqy~EG&VdVWC30zP(LwZOR^pWA)Ds&vbIV@cs0Z z*=&}eND?!ur8rSoh=c@;wl^wrwa zTFSOyR;(B^)T97enoTgMt-E+w-D3U_MfB3L0)Lx>`599o%J`pyhhKXasqPys`38*; Y-K$%6e||%8HmP*h-uX<8?Zt2Y0@2NAE&u=k literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/a00290.html b/src/tbb/doc/html/a00290.html new file mode 100644 index 0000000..4e99ce7 --- /dev/null +++ b/src/tbb/doc/html/a00290.html @@ -0,0 +1,50 @@ + + +tbb::improper_lock Class Reference + + + + + + + +

tbb::improper_lock Class Reference

Exception for PPL locks. +More... +

+#include <tbb_exception.h> +

+List of all members. + + + + +

Public Member Functions

+const char * what () const throw ()
+


Detailed Description

+Exception for PPL locks. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00291.html b/src/tbb/doc/html/a00291.html new file mode 100644 index 0000000..9bd2357 --- /dev/null +++ b/src/tbb/doc/html/a00291.html @@ -0,0 +1,50 @@ + + +tbb::invalid_multiple_scheduling Class Reference + + + + + + + +

tbb::invalid_multiple_scheduling Class Reference

Exception for repeated scheduling of the same task_handle. +More... +

+#include <tbb_exception.h> +

+List of all members. + + + + +

Public Member Functions

+const char * what () const throw ()
+


Detailed Description

+Exception for repeated scheduling of the same task_handle. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00292.html b/src/tbb/doc/html/a00292.html new file mode 100644 index 0000000..ec23c70 --- /dev/null +++ b/src/tbb/doc/html/a00292.html @@ -0,0 +1,143 @@ + + +tbb::flow::interface6::limiter_node< T > Class Template Reference + + + + + + + +

tbb::flow::interface6::limiter_node< T > Class Template Reference

Forwards messages only if the threshold has not been reached. +More... +

+#include <flow_graph.h> +

+

Inheritance diagram for tbb::flow::interface6::limiter_node< T >: +

+ +tbb::flow::interface6::graph_node +tbb::flow::interface6::receiver< T > +tbb::flow::interface6::sender< T > + +List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef T input_type
 The input type of this receiver.
+typedef T output_type
 The output type of this sender.
+typedef sender< input_typepredecessor_type
 The predecessor type for this node.
+typedef receiver< output_typesuccessor_type
 The successor type for this node.

Public Member Functions

limiter_node (graph &g, size_t threshold, int num_decrement_predecessors=0)
 Constructor.
limiter_node (const limiter_node &src)
 Copy constructor.
+bool register_successor (receiver< output_type > &r)
 Replace the current successor with this new successor.
bool remove_successor (receiver< output_type > &r)
 Removes a successor from this node.
+bool try_put (const T &t)
 Puts an item to this receiver.
+bool register_predecessor (predecessor_type &src)
 Removes src from the list of cached predecessors.
+bool remove_predecessor (predecessor_type &src)
 Removes src from the list of cached predecessors.

Public Attributes

+internal::decrementer< limiter_node<
+ T > > 
decrement
 The internal receiver< continue_msg > that decrements the count.

Friends

+class internal::forward_task< limiter_node< T > >
+class internal::decrementer< limiter_node< T > >
+

Detailed Description

+

template<typename T>
+ class tbb::flow::interface6::limiter_node< T >

+ +Forwards messages only if the threshold has not been reached. +

+This node forwards items until its threshold is reached. It contains no buffering. If the downstream node rejects, the message is dropped. +

+


Member Function Documentation

+ +
+
+
+template<typename T>
+ + + + + + + + + +
bool tbb::flow::interface6::limiter_node< T >::remove_successor (receiver< output_type > &  r  )  [inline, virtual]
+
+
+ +

+Removes a successor from this node. +

+r.remove_predecessor(*this) is also called. +

+Implements tbb::flow::interface6::sender< T >. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00292.png b/src/tbb/doc/html/a00292.png new file mode 100644 index 0000000000000000000000000000000000000000..4eedec5953bcf974590db48116409db60f1f632b GIT binary patch literal 1209 zcmeAS@N?(olHy`uVBq!ia0y~yVA=&_2e2>$NtVf{p93k00G|-o|Ns93ng9PEm_I*Z z0+0p92M!#lKJ@IDt)TgY;^rq# zkzfDz3kV1`-(9@haO$)vQ|_kyTFNh3u=nZto7+?_FZxw&d%Z4jPE^R&Bbg=p{X@Oy zxPAW}B7L;s<)nJ%ZD$WfWrt;GZK!>)==b^BIWydzib)*WHv7xbZEUyNkL^FF`$G2i zrN2FS;R34LdGjtFm0eu%JhSjh>2BIk`)Njc4YaEHw+Ta!=2Tik5j-DT0$AwdhTwLJU#&}?B({2dJ=$3v&X zcdYx>mlrX6gGE6E_g%jC*(H}}J1rIrVabT{{wTWZZqa|GScW#XC!7w(bS_^Mh& zZtAEl%@6G+rH%|&%7Aa!}R!Q z>G#yT0j{b1Re5)(8aFqzgtk4G)qXp{BwTSzb>@O*Mp5>R;@2N%GN!(t)~mu{cGKoY zXT^e>^8|M-=3e(^eafj@H~Zcd#_~y>p1JVcjcaya*Ot9)sJMHjZndo0oeOtswMx6( zzPoC-Go8L02TdpNL{l7c{=asKk?$(^H_r>sm-}?Dnr88QMclu6dMiDEYJ)@S^`=i2 zHC>t2Sv+agw7;o+V0j>qAmiA1XWKHXyOw6^cPXEJ(Py&Q`ce(ojp-}q<`?cRTDWQ%+lzzNd1bkMSu?Zy zxK_RVWvdY$ZI-%Ddzb%q<=PvU|6i;*<;>r`_)3WY_W|o;;yazIdS*UP{p{)GhZQdw z@}9gn)*7>U#gfxEUQE0xAh7P^pMLSE`4^ua|1_UHWBCGs=XY9`SIMFPTpGoiI1pb>!G@y>juB@#?WR literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/a00293.html b/src/tbb/doc/html/a00293.html new file mode 100644 index 0000000..68f7f6b --- /dev/null +++ b/src/tbb/doc/html/a00293.html @@ -0,0 +1,53 @@ + + +tbb::internal::machine_load_store_relaxed< T, S > Struct Template Reference + + + + + + + +

tbb::internal::machine_load_store_relaxed< T, S > Struct Template Reference

#include <tbb_machine.h> +

+List of all members. + + + + + + +

Static Public Member Functions

+static T load (const volatile T &location)
+static void store (volatile T &location, T value)
+


Detailed Description

+

template<typename T, size_t S>
+ struct tbb::internal::machine_load_store_relaxed< T, S >

+ +Volatile should not incur any additional cost on IA32, Intel64, and Sparc TSO architectures. However on architectures with weak memory ordering compiler may generate code with acquire/release semantics for operations on volatile data. +

+


The documentation for this struct was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00294.html b/src/tbb/doc/html/a00294.html new file mode 100644 index 0000000..90ce8b2 --- /dev/null +++ b/src/tbb/doc/html/a00294.html @@ -0,0 +1,53 @@ + + +tbb::internal::machine_load_store_seq_cst< T, 8 > Struct Template Reference + + + + + + + +

tbb::internal::machine_load_store_seq_cst< T, 8 > Struct Template Reference

#include <tbb_machine.h> +

+List of all members. + + + + + + +

Static Public Member Functions

+static T load (const volatile T &location)
+static void store (volatile T &location, T value)
+


Detailed Description

+

template<typename T>
+ struct tbb::internal::machine_load_store_seq_cst< T, 8 >

+ +The implementation does not use functions __TBB_machine_load8/store8 as they are not required to be sequentially consistent. +

+


The documentation for this struct was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00295.html b/src/tbb/doc/html/a00295.html new file mode 100644 index 0000000..c405804 --- /dev/null +++ b/src/tbb/doc/html/a00295.html @@ -0,0 +1,58 @@ + + +tbb::interface6::memory_pool< Alloc > Class Template Reference + + + + + + + +

tbb::interface6::memory_pool< Alloc > Class Template Reference

Thread-safe growable pool allocator for variable-size requests. +More... +

+#include <memory_pool.h> +

+List of all members. + + + + + + + + +

Public Member Functions

memory_pool (const Alloc &src=Alloc())
 construct pool with underlying allocator
~memory_pool ()
 destroy pool
+


Detailed Description

+

template<typename Alloc>
+ class tbb::interface6::memory_pool< Alloc >

+ +Thread-safe growable pool allocator for variable-size requests. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00296.html b/src/tbb/doc/html/a00296.html new file mode 100644 index 0000000..2edbf1f --- /dev/null +++ b/src/tbb/doc/html/a00296.html @@ -0,0 +1,132 @@ + + +tbb::interface6::memory_pool_allocator< T, P > Class Template Reference + + + + + + + +

tbb::interface6::memory_pool_allocator< T, P > Class Template Reference
+ +[Memory Allocation] +

Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5. +More... +

+#include <memory_pool.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef tbb::internal::allocator_type<
+ T >::value_type 
value_type
+typedef value_type * pointer
+typedef const value_type * const_pointer
+typedef value_type & reference
+typedef const value_type & const_reference
+typedef size_t size_type
+typedef ptrdiff_t difference_type

Public Member Functions

memory_pool_allocator (pool_type &pool) throw ()
memory_pool_allocator (const memory_pool_allocator &src) throw ()
+template<typename U>
 memory_pool_allocator (const memory_pool_allocator< U, P > &src) throw ()
+pointer address (reference x) const
+const_pointer address (const_reference x) const
+pointer allocate (size_type n, const void *=0)
 Allocate space for n objects.
+void deallocate (pointer p, size_type)
 Free previously allocated block of memory.
+size_type max_size () const throw ()
 Largest value for which method allocate might succeed.
+template<typename... Args>
void construct (pointer p, Args &&...args)
 Copy-construct value at location pointed to by p.

Protected Types

+typedef P pool_type

Protected Attributes

+pool_type * my_pool

Friends

+class memory_pool_allocator
+template<typename V, typename U, typename R>
bool operator== (const memory_pool_allocator< V, R > &a, const memory_pool_allocator< U, R > &b)
+template<typename V, typename U, typename R>
bool operator!= (const memory_pool_allocator< V, R > &a, const memory_pool_allocator< U, R > &b)

Classes

struct  rebind
+


Detailed Description

+

template<typename T, typename P = internal::pool_base>
+ class tbb::interface6::memory_pool_allocator< T, P >

+ +Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00297.html b/src/tbb/doc/html/a00297.html new file mode 100644 index 0000000..afd1246 --- /dev/null +++ b/src/tbb/doc/html/a00297.html @@ -0,0 +1,95 @@ + + +tbb::interface6::memory_pool_allocator< void, P > Class Template Reference + + + + + + + +

tbb::interface6::memory_pool_allocator< void, P > Class Template Reference
+ +[Memory Allocation] +

Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1. +More... +

+#include <memory_pool.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef P pool_type
+typedef void * pointer
+typedef const void * const_pointer
+typedef void value_type

Public Member Functions

memory_pool_allocator (pool_type &pool) throw ()
memory_pool_allocator (const memory_pool_allocator &src) throw ()
+template<typename U>
 memory_pool_allocator (const memory_pool_allocator< U, P > &src) throw ()

Protected Attributes

+pool_type * my_pool

Friends

+class memory_pool_allocator
+template<typename V, typename U, typename R>
bool operator== (const memory_pool_allocator< V, R > &a, const memory_pool_allocator< U, R > &b)
+template<typename V, typename U, typename R>
bool operator!= (const memory_pool_allocator< V, R > &a, const memory_pool_allocator< U, R > &b)

Classes

struct  rebind
+


Detailed Description

+

template<typename P>
+ class tbb::interface6::memory_pool_allocator< void, P >

+ +Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00298.html b/src/tbb/doc/html/a00298.html new file mode 100644 index 0000000..d8e0333 --- /dev/null +++ b/src/tbb/doc/html/a00298.html @@ -0,0 +1,50 @@ + + +tbb::missing_wait Class Reference + + + + + + + +

tbb::missing_wait Class Reference

Exception for missing wait on structured_task_group. +More... +

+#include <tbb_exception.h> +

+List of all members. + + + + +

Public Member Functions

+const char * what () const throw ()
+


Detailed Description

+Exception for missing wait on structured_task_group. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00299.html b/src/tbb/doc/html/a00299.html new file mode 100644 index 0000000..b081baf --- /dev/null +++ b/src/tbb/doc/html/a00299.html @@ -0,0 +1,171 @@ + + +tbb::movable_exception< ExceptionData > Class Template Reference + + + + + + + +

tbb::movable_exception< ExceptionData > Class Template Reference

Template that can be used to implement exception that transfers arbitrary ExceptionData to the root thread. +More... +

+#include <tbb_exception.h> +

+

Inheritance diagram for tbb::movable_exception< ExceptionData >: +

+ +tbb::tbb_exception + +List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Member Functions

movable_exception (const ExceptionData &data_)
movable_exception (const movable_exception &src) throw ()
+const movable_exceptionoperator= (const movable_exception &src)
+ExceptionData & data () throw ()
+const ExceptionData & data () const throw ()
+const char * name () const throw ()
 Returns RTTI name of the originally intercepted exception.
+const char * what () const throw ()
 Returns the result of originally intercepted exception's what() method.
movable_exceptionmove () throw ()
 Creates and returns pointer to the deep copy of this exception object.
void destroy () throw ()
 Destroys objects created by the move() method.
void throw_self ()
 Throws this exception object.

Protected Attributes

+ExceptionData my_exception_data
 User data.
+

Detailed Description

+

template<typename ExceptionData>
+ class tbb::movable_exception< ExceptionData >

+ +Template that can be used to implement exception that transfers arbitrary ExceptionData to the root thread. +

+Code using TBB can instantiate this template with an arbitrary ExceptionData type and throw this exception object. Such exceptions are intercepted by the TBB scheduler and delivered to the root thread ().

See also:
tbb::tbb_exception
+ +

+


Member Function Documentation

+ +
+
+
+template<typename ExceptionData>
+ + + + + + + + +
void tbb::movable_exception< ExceptionData >::destroy (  )  throw () [inline, virtual]
+
+
+ +

+Destroys objects created by the move() method. +

+Frees memory and calls destructor for this exception object. Can and must be used only on objects created by the move method. +

+Implements tbb::tbb_exception. +

+

+ +

+
+
+template<typename ExceptionData>
+ + + + + + + + +
movable_exception* tbb::movable_exception< ExceptionData >::move (  )  throw () [inline, virtual]
+
+
+ +

+Creates and returns pointer to the deep copy of this exception object. +

+Move semantics is allowed. +

+Implements tbb::tbb_exception. +

+

+ +

+
+
+template<typename ExceptionData>
+ + + + + + + + +
void tbb::movable_exception< ExceptionData >::throw_self (  )  [inline, virtual]
+
+
+ +

+Throws this exception object. +

+Make sure that if you have several levels of derivation from this interface you implement or override this method on the most derived level. The implementation is as simple as "throw *this;". Failure to do this will result in exception of a base class type being thrown. +

+Implements tbb::tbb_exception. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00299.png b/src/tbb/doc/html/a00299.png new file mode 100644 index 0000000000000000000000000000000000000000..a85d170678622f3e2d67467a8d06144107bee69d GIT binary patch literal 604 zcmV-i0;BzjP)NO zAPhj!rfb9vNN>v;xWktvWqyd7 zdCV*8vMuTa-y@H~Gv=Hw30cQPBfsiP=A9vHY$u~>$H6H+QIHd0qojfkDietxqg}K^ z;garj(X`8}!E@3&*nG9}-EhPLNBlTkP1b?$gQrr-NzJ+8W;H(+Ub>xwZ*_aNZa)!44bseDs#5@ll7VmS!K&dkRG0E4(14xy=ulIl{ literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/a00300.html b/src/tbb/doc/html/a00300.html new file mode 100644 index 0000000..38a6f25 --- /dev/null +++ b/src/tbb/doc/html/a00300.html @@ -0,0 +1,71 @@ + + +tbb::flow::interface6::multifunction_node< Input, Output,, Allocator > Class Template Reference + + + + + + + +

tbb::flow::interface6::multifunction_node< Input, Output,, Allocator > Class Template Reference

implements a function node that supports Input -> (set of outputs) +More... +

+#include <flow_graph.h> +

+

Inheritance diagram for tbb::flow::interface6::multifunction_node< Input, Output,, Allocator >: +

+ +tbb::flow::interface6::graph_node + +List of all members. + + + + + + + + + + + + +

Public Types

+typedef Input input_type
+typedef internal::wrap_tuple_elements<
+ N, internal::function_output,
+ Output >::type 
output_ports_type

Public Member Functions

+template<typename Body>
 multifunction_node (graph &g, size_t concurrency, Body body)
multifunction_node (const multifunction_node &other)
+

Detailed Description

+

template<typename Input, typename Output, graph_buffer_policy = queueing, typename Allocator = cache_aligned_allocator<Input>>
+ class tbb::flow::interface6::multifunction_node< Input, Output,, Allocator >

+ +implements a function node that supports Input -> (set of outputs) +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00300.png b/src/tbb/doc/html/a00300.png new file mode 100644 index 0000000000000000000000000000000000000000..cdab3e3540dfac46cbb9d2efe720d6357cb40a04 GIT binary patch literal 982 zcmeAS@N?(olHy`uVBq!ia0y~yVC)3416Y`Wq}Vxn%%7hy z0muU50|yRNANv0U$Ym@E@(X5gcy=R=fq^;4)5S5QV$RzczC}+Icv=&Uvrn2IQ1>_+ zj_Bz(@Z zDW6*3pP0Mr)KZoA7R5s6rg<&j629TF#-{6UWOu5ZIl$ng_}+BJms5p1AL{T%NCoUR zIvQg2Fzz7V(tzsEdn7`=Z!P*a*~I@Ad-Qv$d8d-z1fF+oTu~NyM*YaTa^Cj=3Rb}> zr6OkwRvxtpSaN)8g{S=;@$U9r630ZhM(S+Rf5jCYyr(+;it#Ebx4+j)lV3}!dZ*7i zB{_A;b{Q9;c?It@V$Q9QU-3_4&yI?+uX$Zt7M=M0Z|iyc7jL&_v|q?ychqo~=DEeQ zAKCokxc9$x;{|t%xG!y%ed3kU8!pWE&u16g#dh?$dS$f11yhZ68+Ye-33u+{ozX!H ze9wSA&OzV-Z~Uu_yCTmo`WDJ@x?btlaOxMm?K*3hn9PgD;0F>n0`Ju31W%u{;U&}R zme)_DyXHPRa&3D*@63um!wu{oSy`vF^Sbt&4^Uuuw$8>%sXnCRXxcO9y0h~o1$IvD zo{(Sq=#sDn>xt48!rv20`y&z_^y|MoEVQKRZY7G~Eo-Hb}>xz=^1 za1}A;PK?tCFP)ViIL}b4y{}g_IAi7)?qjpWPlt2=o%7W=yeo9ajGSw?HZN=JTU2tv zp;+*j;jSwxUmvaC6|ZsX&4uSZ3%4)$oo=#q5l6qKllMApe}j38FWj%tTlT~;XYYRR ziS0>0^jdxHJ0&d&5Ty4@;l>w(nX5NpGhvt6&$ z-)U?Jd=PM&_vi-w1@De#iQhUVbx7G&M)Ox~;Q1B1au*bAvF%#8W<`WwXF!+EeqkeZ z|E}B`%f(_{bB(>ubI3*VG1^V3Xw#Fi?kaOT`f9~}i@L7a?WGmpj~6dKteN!h^Z&xf zNsk?WSeC1=JR1D)_^u1_&HLlbk5-n5a=rh5D1zf3bN}*_2lSN%gn^lm!PC{xWt~$( F69CG4)A0ZR literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/a00301.html b/src/tbb/doc/html/a00301.html new file mode 100644 index 0000000..06efb66 --- /dev/null +++ b/src/tbb/doc/html/a00301.html @@ -0,0 +1,136 @@ + + +tbb::mutex Class Reference + + + + + + + +

tbb::mutex Class Reference
+ +[Synchronization] +

Wrapper around the platform's native reader-writer lock. +More... +

+#include <mutex.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef LPCRITICAL_SECTION native_handle_type
 Return native_handle.
+typedef pthread_mutex_t * native_handle_type
INITIALIZED = 0x1234
DESTROYED = 0x789A
HELD = 0x56CD
enum  state_t { INITIALIZED = 0x1234, +DESTROYED = 0x789A, +HELD = 0x56CD + }

Public Member Functions

mutex ()
 Construct unacquired mutex.
+void lock ()
 Acquire lock.
bool try_lock ()
 Try acquiring lock (non-blocking).
+void unlock ()
 Release lock.
+native_handle_type native_handle ()
+void set_state (state_t to)
 Set the internal state.

Static Public Attributes

+static const bool is_rw_mutex = false
+static const bool is_recursive_mutex = false
+static const bool is_fair_mutex = false

Friends

+class scoped_lock

Classes

class  scoped_lock
 The scoped locking pattern. More...
+


Detailed Description

+Wrapper around the platform's native reader-writer lock. +

+For testing purposes only. +

+


Member Function Documentation

+ +
+
+ + + + + + + + +
bool tbb::mutex::try_lock (  )  [inline]
+
+
+ +

+Try acquiring lock (non-blocking). +

+Return true if lock acquired; false otherwise. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00302.html b/src/tbb/doc/html/a00302.html new file mode 100644 index 0000000..b3cc37f --- /dev/null +++ b/src/tbb/doc/html/a00302.html @@ -0,0 +1,77 @@ + + +tbb::mutex::scoped_lock Class Reference + + + + + + + +

tbb::mutex::scoped_lock Class Reference

The scoped locking pattern. +More... +

+#include <mutex.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + +

Public Member Functions

scoped_lock ()
 Construct lock that has not acquired a mutex.
scoped_lock (mutex &mutex)
 Acquire lock on given mutex.
~scoped_lock ()
 Release lock (if lock is held).
+void acquire (mutex &mutex)
 Acquire lock on given mutex.
+bool try_acquire (mutex &mutex)
 Try acquire lock on given mutex.
+void release ()
 Release lock.

Friends

+class mutex
+


Detailed Description

+The scoped locking pattern. +

+It helps to avoid the common problem of forgetting to release lock. It also nicely provides the "node" for queuing locks. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00303.html b/src/tbb/doc/html/a00303.html new file mode 100644 index 0000000..03fde40 --- /dev/null +++ b/src/tbb/doc/html/a00303.html @@ -0,0 +1,65 @@ + + +tbb::null_mutex Class Reference + + + + + + + +

tbb::null_mutex Class Reference
+ +[Synchronization] +

A mutex which does nothing. +More... +

+#include <null_mutex.h> +

+List of all members. + + + + + + + + + + + + +

Static Public Attributes

+static const bool is_rw_mutex = false
+static const bool is_recursive_mutex = true
+static const bool is_fair_mutex = true

Classes

class  scoped_lock
 Represents acquisition of a mutex. More...
+


Detailed Description

+A mutex which does nothing. +

+A null_mutex does no operation and simulates success. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00304.html b/src/tbb/doc/html/a00304.html new file mode 100644 index 0000000..3b24d67 --- /dev/null +++ b/src/tbb/doc/html/a00304.html @@ -0,0 +1,59 @@ + + +tbb::null_mutex::scoped_lock Class Reference + + + + + + + +

tbb::null_mutex::scoped_lock Class Reference

Represents acquisition of a mutex. +More... +

+#include <null_mutex.h> +

+List of all members. + + + + + + + + + + +

Public Member Functions

scoped_lock (null_mutex &)
+void acquire (null_mutex &)
+bool try_acquire (null_mutex &)
+void release ()
+


Detailed Description

+Represents acquisition of a mutex. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00305.html b/src/tbb/doc/html/a00305.html new file mode 100644 index 0000000..696e0f3 --- /dev/null +++ b/src/tbb/doc/html/a00305.html @@ -0,0 +1,65 @@ + + +tbb::null_rw_mutex Class Reference + + + + + + + +

tbb::null_rw_mutex Class Reference
+ +[Synchronization] +

A rw mutex which does nothing. +More... +

+#include <null_rw_mutex.h> +

+List of all members. + + + + + + + + + + + + +

Static Public Attributes

+static const bool is_rw_mutex = true
+static const bool is_recursive_mutex = true
+static const bool is_fair_mutex = true

Classes

class  scoped_lock
 Represents acquisition of a mutex. More...
+


Detailed Description

+A rw mutex which does nothing. +

+A null_rw_mutex is a rw mutex that does nothing and simulates successful operation. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00306.html b/src/tbb/doc/html/a00306.html new file mode 100644 index 0000000..a7a346e --- /dev/null +++ b/src/tbb/doc/html/a00306.html @@ -0,0 +1,65 @@ + + +tbb::null_rw_mutex::scoped_lock Class Reference + + + + + + + +

tbb::null_rw_mutex::scoped_lock Class Reference

Represents acquisition of a mutex. +More... +

+#include <null_rw_mutex.h> +

+List of all members. + + + + + + + + + + + + + + +

Public Member Functions

scoped_lock (null_rw_mutex &, bool=true)
+void acquire (null_rw_mutex &, bool=true)
+bool upgrade_to_writer ()
+bool downgrade_to_reader ()
+bool try_acquire (null_rw_mutex &, bool=true)
+void release ()
+


Detailed Description

+Represents acquisition of a mutex. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00307.html b/src/tbb/doc/html/a00307.html new file mode 100644 index 0000000..6e27b82 --- /dev/null +++ b/src/tbb/doc/html/a00307.html @@ -0,0 +1,65 @@ + + +tbb::parallel_do_feeder< Item > Class Template Reference + + + + + + + +

tbb::parallel_do_feeder< Item > Class Template Reference

Class the user supplied algorithm body uses to add new tasks. +More... +

+#include <parallel_do.h> +

+List of all members. + + + + + + + + +

Public Member Functions

+void add (const Item &item)
 Add a work item to a running parallel_do.

Friends

+class internal::parallel_do_feeder_impl
+


Detailed Description

+

template<typename Item>
+ class tbb::parallel_do_feeder< Item >

+ +Class the user supplied algorithm body uses to add new tasks. +

+

Parameters:
+ + +
Item Work item type
+
+ +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00308.html b/src/tbb/doc/html/a00308.html new file mode 100644 index 0000000..bcf4c07 --- /dev/null +++ b/src/tbb/doc/html/a00308.html @@ -0,0 +1,140 @@ + + +tbb::parallel_while< Body > Class Template Reference + + + + + + + +

tbb::parallel_while< Body > Class Template Reference
+ +[Algorithms] +

Parallel iteration over a stream, with optional addition of more work. +More... +

+#include <parallel_while.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef Body::argument_type value_type
 Type of items.

Public Member Functions

parallel_while ()
 Construct empty non-running parallel while.
~parallel_while ()
 Destructor cleans up data members before returning.
template<typename Stream>
void run (Stream &stream, const Body &body)
 Apply body.apply to each item in the stream.
void add (const value_type &item)
 Add a work item while running.
+


Detailed Description

+

template<typename Body>
+ class tbb::parallel_while< Body >

+ +Parallel iteration over a stream, with optional addition of more work. +

+The Body b has the requirement:
+ "b(v)"
+ "b.argument_type"
+ where v is an argument_type +

+


Member Function Documentation

+ +
+
+
+template<typename Body>
+ + + + + + + + + +
void tbb::parallel_while< Body >::add (const value_type item  ) 
+
+
+ +

+Add a work item while running. +

+Should be executed only by body.apply or a thread spawned therefrom. +

+

+ +

+
+
+template<typename Body>
+
+template<typename Stream>
+ + + + + + + + + + + + + + + + + + +
void tbb::parallel_while< Body >::run (Stream &  stream,
const Body &  body 
)
+
+
+ +

+Apply body.apply to each item in the stream. +

+A Stream s has the requirements
+ "S::value_type"
+ "s.pop_if_present(value) is convertible to bool +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00309.html b/src/tbb/doc/html/a00309.html new file mode 100644 index 0000000..a1b9bda --- /dev/null +++ b/src/tbb/doc/html/a00309.html @@ -0,0 +1,62 @@ + + +tbb::internal::partition_type_base Class Reference + + + + + + + +

tbb::internal::partition_type_base Class Reference

Provides backward-compatible methods for partition objects without affinity. +More... +

+#include <partitioner.h> +

+List of all members. + + + + + + + + + + + + +

Public Member Functions

+void set_affinity (task &)
+void note_affinity (task::affinity_id)
+taskcontinue_after_execute_range ()
+bool decide_whether_to_delay ()
+void spawn_or_delay (bool, task &b)
+


Detailed Description

+Provides backward-compatible methods for partition objects without affinity. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00310.html b/src/tbb/doc/html/a00310.html new file mode 100644 index 0000000..b04898f --- /dev/null +++ b/src/tbb/doc/html/a00310.html @@ -0,0 +1,111 @@ + + +tbb::pipeline Class Reference + + + + + + + +

tbb::pipeline Class Reference
+ +[Algorithms] +

A processing pipeline that applies filters to items. +More... +

+#include <pipeline.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Member Functions

+__TBB_EXPORTED_METHOD pipeline ()
 Construct empty pipeline.
virtual __TBB_EXPORTED_METHOD ~pipeline ()
+void __TBB_EXPORTED_METHOD add_filter (filter &filter_)
 Add filter to end of pipeline.
+void __TBB_EXPORTED_METHOD run (size_t max_number_of_live_tokens)
 Run the pipeline to completion.
+void __TBB_EXPORTED_METHOD run (size_t max_number_of_live_tokens, tbb::task_group_context &context)
 Run the pipeline to completion with user-supplied context.
+void __TBB_EXPORTED_METHOD clear ()
 Remove all filters from the pipeline.

Friends

+class internal::stage_task
+class internal::pipeline_root_task
+class filter
+class thread_bound_filter
+class internal::pipeline_cleaner
+class tbb::interface6::internal::pipeline_proxy
+


Detailed Description

+A processing pipeline that applies filters to items. +

+


Constructor & Destructor Documentation

+ +
+
+ + + + + + + + +
virtual __TBB_EXPORTED_METHOD tbb::pipeline::~pipeline (  )  [virtual]
+
+
+ +

+Though the current implementation declares the destructor virtual, do not rely on this detail. The virtualness is deprecated and may disappear in future versions of TBB. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00311.html b/src/tbb/doc/html/a00311.html new file mode 100644 index 0000000..9ac5444 --- /dev/null +++ b/src/tbb/doc/html/a00311.html @@ -0,0 +1,53 @@ + + +tbb::pre_scan_tag Struct Reference + + + + + + + +

tbb::pre_scan_tag Struct Reference
+ +[Algorithms] +

Used to indicate that the initial scan is being performed. +More... +

+#include <parallel_scan.h> +

+List of all members. + + + + +

Static Public Member Functions

+static bool is_final_scan ()
+


Detailed Description

+Used to indicate that the initial scan is being performed. +

+


The documentation for this struct was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00312.html b/src/tbb/doc/html/a00312.html new file mode 100644 index 0000000..14f3f9d --- /dev/null +++ b/src/tbb/doc/html/a00312.html @@ -0,0 +1,133 @@ + + +tbb::flow::interface6::priority_queue_node< T, Compare, A > Class Template Reference + + + + + + + +

tbb::flow::interface6::priority_queue_node< T, Compare, A > Class Template Reference

Forwards messages in priority order. +More... +

+#include <flow_graph.h> +

+

Inheritance diagram for tbb::flow::interface6::priority_queue_node< T, Compare, A >: +

+ +tbb::flow::interface6::buffer_node< T, A > +tbb::flow::interface6::graph_node +tbb::flow::interface6::receiver< T > +tbb::flow::interface6::sender< T > + +List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef T input_type
 The input type of this receiver.
+typedef T output_type
 The output type of this sender.
+typedef sender< input_typepredecessor_type
 The predecessor type for this node.
+typedef receiver< output_typesuccessor_type
 The successor type for this node.

Public Member Functions

priority_queue_node (graph &g)
 Constructor.
priority_queue_node (const priority_queue_node &src)
 Copy constructor.

Protected Types

+typedef buffer_node< T, A
+>::size_type 
size_type
+typedef buffer_node< T, A
+>::item_type 
item_type
+typedef buffer_node< T, A
+>::buffer_operation 
prio_operation
WAIT = 0
SUCCEEDED
FAILED
enum  op_stat { WAIT = 0, +SUCCEEDED, +FAILED + }

Protected Member Functions

+void handle_operations (prio_operation *op_list)
+void internal_forward (prio_operation *op)
 Tries to forward valid items to successors.
+void internal_push (prio_operation *op)
+void internal_pop (prio_operation *op)
+void internal_reserve (prio_operation *op)
+void internal_consume (prio_operation *op)
+void internal_release (prio_operation *op)
+

Detailed Description

+

template<typename T, typename Compare = std::less<T>, typename A = cache_aligned_allocator<T>>
+ class tbb::flow::interface6::priority_queue_node< T, Compare, A >

+ +Forwards messages in priority order. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00312.png b/src/tbb/doc/html/a00312.png new file mode 100644 index 0000000000000000000000000000000000000000..1e0df079570a66587a7c15d747c2d17abca5985c GIT binary patch literal 2103 zcmcgtX;hO*7X5$#-K?Pr2tlMd2!>`ANP~zY%D#436bQ&NECB)nwq{tAVUa|UZ3cvi z!@em^*b_EowIOssLLz)ZSRxW^)<9@uBZBFuedf%}=|A&lepJ=1ck8}aRqxfQyC`=D zSt+;_006R1j<%iv05KEdI}kBpzd@+?77i*XS8qFkKp=zy!C*y2aDfngYJ-D=DZ>Je za4K@$)7=ZOemxrj0Fuv~Y%h2xmTs3_DXv98vsS~)WpQbJnMBzUubsbssWnjDP+UNS zl=cSkoxCpeNtla`aSiJQ5~1ym_YmQ(41u8yk7}n{JwUJELF83eHSOe2C5|EFb(1ZI zZ0wU98Bf1FVM4RXPBom>XZ7#@ir#T9_HI`W*Dl&g%yS6DE_f)1$9Ad}%-!d7)sqG} zXP2jV0OP0c7g5o<`D06En9D!q$L%yw@Tsv3MEDM|q}ADP#h#|QFAwPp+$c6Dc^JKq z5A^#-i3zpC1nw<`)^&sgdJP#~X z{4}RL6Va$HU*T61cKb~Tc9u)0bW1mBvN#?eU=h4ay7=L^6Ui$pV0V#Q0(CBH;h|~3 z^SE-t!4+&|-#DBho^YJffe$n!@qCB&M6fCy@AnN{4!^*keyd}|HLBVSIN333Gv`-- zZ=0cmMJ?II_-)TtJ$a)9_FCeMC9!6zSbg2m^|y~FZjKF)UrUryTi$Iopu$Jm-RjTe zUh&UCzLL?-vj}~15wnFsH2-Y;Zgy^8HCruFt&I9%-n2+tjvs2FOG#2`&cd{Iw5;TW znbVmcZb^-NKeSrS{+s$kJzf9E&pLa4 zWt5nU^rQ4Tao8R`C`w$(`noh;F(!RY`S56*`4vqFWKPYBGTefrM3AlIG`LWxD-=q6 z79z6h#HRjQhWu5|6F3ojtR!KS@=1dc@V5lJXS`0I+G&!LsopBoV{zE_=R7 zgU~!(y#%y^y+|fbXA+<5}b=$K-Z)ar(4GqqiDr9&Rr=` z2G{OawA*i+G`#CA)6qxcd<#HMndg|%d4nhkEO~`0SBE1`_aP5waQ9@m;Ca^@sk;&+ zMxJ?70>w4@sz|jD7OH;P&CO+cDMbv7bZA4C8x;1A!^fRKUpYUU^Zq9l!ANRH+bB5u zU5V37lq-)_Rho;;KpKNx)el75b28N`{!C)-A1M zU`kKl0C*$J9?&Pu?Ek~GYiOpz>eFhyx7rf8}{t3)>d0>=j7pEhPZA5YhP9X;7s z&Ag{ab4JV)Lsv21&PO+xt#nr;J$l~ta{M^y^gw3|D>{NY$$B&mCpKQCKid-CNNA^O zaJ^GcZDr&+>kg^dfd}|4?g6p+ezBuP=9^{1cVN0=gdH(W0l@xt~HtVl+2ZMdtcM|)< zmLHuv;WO#P<0dG^ZML*6Ufb-8%s`^|euUfhm%+|BK*K5WV0^ABNnt}lz3D>jUO8t5 zPFplCjdW=2hY!IGdRj-VcG~SgGc}@epbI7 ztM}j{p?X+m#O+j3MO6%@mMHx$9pRQ>8q3c!g;hX1T@F;U9}HV*H-@DnSv;_-s)U^m zBfsRqf2f4rETp4D<=F8j&;@szxxX;MjU?UuZ!{?Q_pYr=}Zxs4r hKy1X3+L$d6$ + +tbb::flow::interface6::queue_node< T, A > Class Template Reference + + + + + + + +

tbb::flow::interface6::queue_node< T, A > Class Template Reference

Forwards messages in FIFO order. +More... +

+#include <flow_graph.h> +

+

Inheritance diagram for tbb::flow::interface6::queue_node< T, A >: +

+ +tbb::flow::interface6::buffer_node< T, A > +tbb::flow::interface6::graph_node +tbb::flow::interface6::receiver< T > +tbb::flow::interface6::sender< T > +tbb::flow::interface6::sequencer_node< T, A > + +List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef T input_type
 The input type of this receiver.
+typedef T output_type
 The output type of this sender.
+typedef sender< input_typepredecessor_type
 The predecessor type for this node.
+typedef receiver< output_typesuccessor_type
 The successor type for this node.

Public Member Functions

queue_node (graph &g)
 Constructor.
queue_node (const queue_node &src)
 Copy constructor.

Protected Types

+typedef buffer_node< T, A
+>::size_type 
size_type
+typedef buffer_node< T, A
+>::buffer_operation 
queue_operation
WAIT = 0
SUCCEEDED
FAILED
enum  op_stat { WAIT = 0, +SUCCEEDED, +FAILED + }

Protected Member Functions

+void internal_forward (queue_operation *op)
 Tries to forward valid items to successors.
+void internal_pop (queue_operation *op)
+void internal_reserve (queue_operation *op)
+void internal_consume (queue_operation *op)
+

Detailed Description

+

template<typename T, typename A = cache_aligned_allocator<T>>
+ class tbb::flow::interface6::queue_node< T, A >

+ +Forwards messages in FIFO order. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00313.png b/src/tbb/doc/html/a00313.png new file mode 100644 index 0000000000000000000000000000000000000000..09b37ae3b93a67437fdfeb9cf34920cf3020a3ee GIT binary patch literal 2251 zcmbVOdo=Wc-UQrg^Xf7rvz3vY8VM*NAJ&1f3c z;-3B?N`b`r1in3q=rz$ht$Fi>i@vOgXYGObp}&dT(48+*^D49-5L%pEDZ+DB;!GC8 zQd;4{n7=-$htBNH`FNy1nU?4^B)=CExzrBBpR0$iURwc!-cGG#D(VF2K#mw?`rTCs zn>?kPs%RhQ0KR1HtM7A0|Mt;p0b{VW_%V}=!`~Ao9C*;UN5=qJp~x`FUU-6P%RAUq zq4;b1l3o+9@nA}E>r4aoPRPuYMr$@%*K`DW=EO)CyeoEI4UD)@nd>?m3+jsubdRa^ zVELubuN{hup{UUTV(+vh&Wi9Tn@M#DzK2=;GtlU5!@JJWvEaHeHrQ#kcA(p{W}cWx z;MNe3z;g!WMfuYx4Og;9lAcmD?zYfEo>Oo$9;8Zf(e2SrduaT!o6UYiaBH7Yg{CW& ziPNPZH7TFwP&OtDcbN)hDg=M8H%&4jtH)AKWbPiiW%$2mL0~v z8^(r=LY*Og582~h5!B!tgVzWp^|KeZmQuKkIhL1+i>~KtlPiQAT)q1AW#CwSiJm2z z^s-@Xdn}HIP-SKFg0@ zBd%d(Ik<}_%a$fw1tFtx=U11ba53>8ul-W^Hg?QA(BdA77G2m#Z$??F+GiVzDB;}! znhb0L`Y3DwPH*MKUPYJdM2&6H`gpXJV|lqIkmIq z*0;AF++Bp%e4Ql!#gKJ;X`6Fhodec~L#q>Vu+jJl`=dDZTr;hVV%A(U@xYLezUARC z8)X=kIygA+qoOiQ_MDnrhmpjjx$-|-Uzk3Oyxpy8PQfd=Z_of$NhSQbvX$eayHPT# zs!-$lwDdlH>;HxXjfvS!nPRU$zISunaQIQ>C&*BbtSJYxOLW;;*a+@^Rs(u0w^Uw8 zU-c<%5KSXHdVtGsUSq;aV10J&$o1C7r4H(2g34=PZu~s!=Y20@-lsIEXEobH0OtXK zIDQ^xnfsI`2VUwJ!wqA1=g&^Fj@b)VXU%At8c2KZ=S}LSlxMf{H2L?#MuABD%rJ(7 zYOB97G-IT-W{`@ys>U}z(H-dwVHBW-eM)InO(a4N2OuoG4=eFUcXJjPAJ-qFctZ2` zMb>0k31YEyGRQ@g!4GLFCuE}3SMD`Ke$SABLyS=^KrfF$JI3u)Mr|gGi~Fk12(BzK zmq=SSY#-C{74wN10p}0($eL)ValTjOOQwjVzSYEUc3FIYB`qgIhD+(s4M=L^h*F8a z{i{w1&z(t{3UCh$g2h7f%R%g+;Jo!7d(R~Ui=lKA84+nkrk1JBic)!JIO4-Gemvnx zcR4-9WNZ06C#CP$Hl=NlEUO#HE0QlQ+|zcYviA7?P#V;WLW-pxw2!pQ?*jtL`P(nz zG!JfM8p7B)I9t~am66{M!5(<~MYz!eB7Q-3+I`UWZX@4cOe$BLL7t&Cx!(Ydz~EOd zUE%^DgNd6L84YVShW?eY#R%iUq0hqL*A5IPg6=*`y%0~`ubtPW<#A*(!N;x|c7;T! zx}c=vw_8LCbcUQD7J5M_bnO08BypBSrvtu-({#X(&jKoVx-tz?VTH3d3l=86+r5MqO>36kt|# z?xz+IR3IOb=Dan0=cL%6-ekgdjxlBo`&r9>y!_u9hbH)oMODqJ%-AJLY~PUl+wor| z{2y=yBisO^M?NyY%5b4wk17r`~k+Y3( zsJ`#`@xz>mTeTtZ8vh+m`AARv#(QSlRju%n=)%{dQ!s(63aEQgsBO(L9?#IYGf#!} zY5B&d++zLqf<#2je#b%CkT5HYsMV=g`gqQ8G6R6%4U61CDM`m#& zY(&EM3fH*3wIM-)dHE;fH{RUzr1MlP(fzUnNJ>HpaH?+3A0b(qjJM?Y)5OoxCJ2rn z6NHqdXy)G-XRGuBRhv`g{6fNkQMRZxM + +tbb::queuing_mutex Class Reference + + + + + + + +

tbb::queuing_mutex Class Reference
+ +[Synchronization] +

Queuing mutex with local-only spinning. +More... +

+#include <queuing_mutex.h> +

+List of all members. + + + + + + + + + + + + + + + + + + +

Public Member Functions

queuing_mutex ()
 Construct unacquired mutex.
+void __TBB_EXPORTED_METHOD internal_construct ()

Static Public Attributes

+static const bool is_rw_mutex = false
+static const bool is_recursive_mutex = false
+static const bool is_fair_mutex = true

Classes

class  scoped_lock
 The scoped locking pattern. More...
+


Detailed Description

+Queuing mutex with local-only spinning. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00315.html b/src/tbb/doc/html/a00315.html new file mode 100644 index 0000000..82298ac --- /dev/null +++ b/src/tbb/doc/html/a00315.html @@ -0,0 +1,94 @@ + + +tbb::queuing_mutex::scoped_lock Class Reference + + + + + + + +

tbb::queuing_mutex::scoped_lock Class Reference

The scoped locking pattern. +More... +

+#include <queuing_mutex.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + +

Public Member Functions

 scoped_lock ()
 Construct lock that has not acquired a mutex.
scoped_lock (queuing_mutex &m)
 Acquire lock on given mutex.
~scoped_lock ()
 Release lock (if lock is held).
+void __TBB_EXPORTED_METHOD acquire (queuing_mutex &m)
 Acquire lock on given mutex.
+bool __TBB_EXPORTED_METHOD try_acquire (queuing_mutex &m)
 Acquire lock on given mutex if free (i.e. non-blocking).
+void __TBB_EXPORTED_METHOD release ()
 Release lock.
+


Detailed Description

+The scoped locking pattern. +

+It helps to avoid the common problem of forgetting to release lock. It also nicely provides the "node" for queuing locks. +

+


Constructor & Destructor Documentation

+ +
+
+ + + + + + + + +
tbb::queuing_mutex::scoped_lock::scoped_lock (  )  [inline]
+
+
+ +

+Construct lock that has not acquired a mutex. +

+Equivalent to zero-initialization of *this. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00316.html b/src/tbb/doc/html/a00316.html new file mode 100644 index 0000000..0c5953b --- /dev/null +++ b/src/tbb/doc/html/a00316.html @@ -0,0 +1,77 @@ + + +tbb::queuing_rw_mutex Class Reference + + + + + + + +

tbb::queuing_rw_mutex Class Reference
+ +[Synchronization] +

Queuing reader-writer mutex with local-only spinning. +More... +

+#include <queuing_rw_mutex.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + +

Public Member Functions

queuing_rw_mutex ()
 Construct unacquired mutex.
~queuing_rw_mutex ()
 Destructor asserts if the mutex is acquired, i.e. q_tail is non-NULL.
+void __TBB_EXPORTED_METHOD internal_construct ()

Static Public Attributes

+static const bool is_rw_mutex = true
+static const bool is_recursive_mutex = false
+static const bool is_fair_mutex = true

Classes

class  scoped_lock
 The scoped locking pattern. More...
+


Detailed Description

+Queuing reader-writer mutex with local-only spinning. +

+Adapted from Krieger, Stumm, et al. pseudocode at http://www.eecg.toronto.edu/parallel/pubs_abs.html#Krieger_etal_ICPP93 +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00317.html b/src/tbb/doc/html/a00317.html new file mode 100644 index 0000000..53e1ba5 --- /dev/null +++ b/src/tbb/doc/html/a00317.html @@ -0,0 +1,123 @@ + + +tbb::queuing_rw_mutex::scoped_lock Class Reference + + + + + + + +

tbb::queuing_rw_mutex::scoped_lock Class Reference

The scoped locking pattern. +More... +

+#include <queuing_rw_mutex.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Member Functions

 scoped_lock ()
 Construct lock that has not acquired a mutex.
scoped_lock (queuing_rw_mutex &m, bool write=true)
 Acquire lock on given mutex.
~scoped_lock ()
 Release lock (if lock is held).
+void acquire (queuing_rw_mutex &m, bool write=true)
 Acquire lock on given mutex.
+bool try_acquire (queuing_rw_mutex &m, bool write=true)
 Acquire lock on given mutex if free (i.e. non-blocking).
+void release ()
 Release lock.
bool upgrade_to_writer ()
 Upgrade reader to become a writer.
+bool downgrade_to_reader ()
 Downgrade writer to become a reader.
+


Detailed Description

+The scoped locking pattern. +

+It helps to avoid the common problem of forgetting to release lock. It also nicely provides the "node" for queuing locks. +

+


Constructor & Destructor Documentation

+ +
+
+ + + + + + + + +
tbb::queuing_rw_mutex::scoped_lock::scoped_lock (  )  [inline]
+
+
+ +

+Construct lock that has not acquired a mutex. +

+Equivalent to zero-initialization of *this. +

+

+


Member Function Documentation

+ +
+
+ + + + + + + + +
bool tbb::queuing_rw_mutex::scoped_lock::upgrade_to_writer (  ) 
+
+
+ +

+Upgrade reader to become a writer. +

+Returns whether the upgrade happened without releasing and re-acquiring the lock +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00318.html b/src/tbb/doc/html/a00318.html new file mode 100644 index 0000000..4036939 --- /dev/null +++ b/src/tbb/doc/html/a00318.html @@ -0,0 +1,221 @@ + + +tbb::interface5::reader_writer_lock Class Reference + + + + + + + +

tbb::interface5::reader_writer_lock Class Reference
+ +[Synchronization] +

Writer-preference reader-writer lock with local-only spinning on readers. +More... +

+#include <reader_writer_lock.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

waiting_nonblocking
waiting
active
invalid
enum  status_t { waiting_nonblocking, +waiting, +active, +invalid + }
 Status type for nodes associated with lock instances. More...

Public Member Functions

reader_writer_lock ()
 Constructs a new reader_writer_lock.
~reader_writer_lock ()
 Destructs a reader_writer_lock object.
void __TBB_EXPORTED_METHOD lock ()
 Acquires the reader_writer_lock for write.
bool __TBB_EXPORTED_METHOD try_lock ()
 Tries to acquire the reader_writer_lock for write.
void __TBB_EXPORTED_METHOD lock_read ()
 Acquires the reader_writer_lock for read.
bool __TBB_EXPORTED_METHOD try_lock_read ()
 Tries to acquire the reader_writer_lock for read.
+void __TBB_EXPORTED_METHOD unlock ()
 Releases the reader_writer_lock.

Friends

+class scoped_lock
+class scoped_lock_read

Classes

class  scoped_lock
 The scoped lock pattern for write locks. More...
class  scoped_lock_read
 The scoped lock pattern for read locks. More...
+


Detailed Description

+Writer-preference reader-writer lock with local-only spinning on readers. +

+Loosely adapted from Mellor-Crummey and Scott pseudocode at http://www.cs.rochester.edu/research/synchronization/pseudocode/rw.html#s_wp +

+


Member Enumeration Documentation

+ +
+ +
+ +

+Status type for nodes associated with lock instances. +

+waiting_nonblocking: the wait state for nonblocking lock instances; for writes, these transition straight to active states; for reads, these are unused.

+waiting: the start and spin state for all lock instances; these will transition to active state when appropriate. Non-blocking write locks transition from this state to waiting_nonblocking immediately.

+active: the active state means that the lock instance holds the lock; it will transition to invalid state during node deletion

+invalid: the end state for all nodes; this is set in the destructor so if we encounter this state, we are looking at memory that has already been freed

+The state diagrams below describe the status transitions. Single arrows indicate that the thread that owns the node is responsible for the transition; double arrows indicate that any thread could make the transition.

+State diagram for scoped_lock status:

+waiting ----------> waiting_nonblocking | _____________/ | V V V active -----------------> invalid

+State diagram for scoped_lock_read status:

+waiting | V active ----------------->invalid +

+

+


Member Function Documentation

+ +
+
+ + + + + + + + +
void __TBB_EXPORTED_METHOD tbb::interface5::reader_writer_lock::lock (  ) 
+
+
+ +

+Acquires the reader_writer_lock for write. +

+If the lock is currently held in write mode by another context, the writer will block by spinning on a local variable. Exceptions thrown: improper_lock The context tries to acquire a reader_writer_lock that it already has write ownership of. +

+

+ +

+
+ + + + + + + + +
void __TBB_EXPORTED_METHOD tbb::interface5::reader_writer_lock::lock_read (  ) 
+
+
+ +

+Acquires the reader_writer_lock for read. +

+If the lock is currently held by a writer, this reader will block and wait until the writers are done. Exceptions thrown: improper_lock The context tries to acquire a reader_writer_lock that it already has write ownership of. +

+

+ +

+
+ + + + + + + + +
bool __TBB_EXPORTED_METHOD tbb::interface5::reader_writer_lock::try_lock (  ) 
+
+
+ +

+Tries to acquire the reader_writer_lock for write. +

+This function does not block. Return Value: True or false, depending on whether the lock is acquired or not. If the lock is already held by this acquiring context, try_lock() returns false. +

+

+ +

+
+ + + + + + + + +
bool __TBB_EXPORTED_METHOD tbb::interface5::reader_writer_lock::try_lock_read (  ) 
+
+
+ +

+Tries to acquire the reader_writer_lock for read. +

+This function does not block. Return Value: True or false, depending on whether the lock is acquired or not. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00319.html b/src/tbb/doc/html/a00319.html new file mode 100644 index 0000000..c4a8de5 --- /dev/null +++ b/src/tbb/doc/html/a00319.html @@ -0,0 +1,67 @@ + + +tbb::interface5::reader_writer_lock::scoped_lock Class Reference + + + + + + + +

tbb::interface5::reader_writer_lock::scoped_lock Class Reference

The scoped lock pattern for write locks. +More... +

+#include <reader_writer_lock.h> +

+List of all members. + + + + + + + + + + + + + + + +

Public Member Functions

scoped_lock (reader_writer_lock &lock)
 Construct with blocking attempt to acquire write lock on the passed-in lock.
~scoped_lock ()
 Destructor, releases the write lock.
+void * operator new (size_t s)
+void operator delete (void *p)

Friends

+class reader_writer_lock
+


Detailed Description

+The scoped lock pattern for write locks. +

+Scoped locks help avoid the common problem of forgetting to release the lock. This type also serves as the node for queuing locks. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00320.html b/src/tbb/doc/html/a00320.html new file mode 100644 index 0000000..6692689 --- /dev/null +++ b/src/tbb/doc/html/a00320.html @@ -0,0 +1,65 @@ + + +tbb::interface5::reader_writer_lock::scoped_lock_read Class Reference + + + + + + + +

tbb::interface5::reader_writer_lock::scoped_lock_read Class Reference

The scoped lock pattern for read locks. +More... +

+#include <reader_writer_lock.h> +

+List of all members. + + + + + + + + + + + + + + + +

Public Member Functions

scoped_lock_read (reader_writer_lock &lock)
 Construct with blocking attempt to acquire read lock on the passed-in lock.
~scoped_lock_read ()
 Destructor, releases the read lock.
+void * operator new (size_t s)
+void operator delete (void *p)

Friends

+class reader_writer_lock
+


Detailed Description

+The scoped lock pattern for read locks. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00321.html b/src/tbb/doc/html/a00321.html new file mode 100644 index 0000000..052c3af --- /dev/null +++ b/src/tbb/doc/html/a00321.html @@ -0,0 +1,86 @@ + + +tbb::flow::interface6::receiver< T > Class Template Reference + + + + + + + +

tbb::flow::interface6::receiver< T > Class Template Reference

Pure virtual template class that defines a receiver of messages of type T. +More... +

+#include <flow_graph.h> +

+

Inheritance diagram for tbb::flow::interface6::receiver< T >: +

+ +tbb::flow::interface6::broadcast_node< T > +tbb::flow::interface6::buffer_node< T, A > +tbb::flow::interface6::continue_receiver +tbb::flow::interface6::limiter_node< T > +tbb::flow::interface6::priority_queue_node< T, Compare, A > +tbb::flow::interface6::queue_node< T, A > +tbb::flow::interface6::sequencer_node< T, A > + +List of all members. + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef T input_type
 The input type of this receiver.
+typedef sender< T > predecessor_type
 The predecessor type for this node.

Public Member Functions

+virtual ~receiver ()
 Destructor.
+virtual bool try_put (const T &t)=0
 Put an item to the receiver.
+virtual bool register_predecessor (predecessor_type &)
 Add a predecessor to the node.
+virtual bool remove_predecessor (predecessor_type &)
 Remove a predecessor from the node.
+

Detailed Description

+

template<typename T>
+ class tbb::flow::interface6::receiver< T >

+ +Pure virtual template class that defines a receiver of messages of type T. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00321.png b/src/tbb/doc/html/a00321.png new file mode 100644 index 0000000000000000000000000000000000000000..73ffc7362ff73d4477270cba81a58e4f3701c61a GIT binary patch literal 3242 zcmds)XHb*b8pneu7D~iWgitIiC@i2N{qiDWp}0s3U?H%gL;(S5krql+6a*D3NQiU< zLNN#e0Rl)7FrkZ55{Mym0|63}5N_Prow;{+=9ZcJ>3%rx`~SZ)&pBtFbDnd4?|nPl zGm<+LcYr`3Nh`~f4j|B$4521&78O22Z}}t%U%TzjI-T0s*bvH%4I&on@kpqCYeXV3 zqG{us(24{**gAraPY!v3KoZBTPMSO2N}tF0Bxl#iorb(~YQVE4=5%ATBXV_BY|a#} zfycQ?A4SV72%Z%G5Y6pFM0wXQyL;V2s$)_#lUjZWkB=>#)KGrCiz87PL-tUk>b~60 zk?`6Cpi>QJSOcjtChq=KFq`r;pD#<_ygsZeAtUG>aSTn+>zo$Ga5n6^o=?xiVuFL6 zFy3%RchoPqn!6Nnz(;np#NO4%xZ3I>!oPB;266G_ykp_yXT$l7CWjKAT@U~bF@j@p zEiOgbyxDilUfk;mx}%9hQ`nO6kc|3EL9gZ&+tdW(oR^{iTFbi?T4fmLIzrIWs^Tyv z)J|Y8DqV2zyOzsbdw%!p_+nW%Q^EIU8hN4UTIr#%r27v32K9TscRPj9T-v zPc$RST1)_nUlBLbO3%2T(K!*6R=*i*;nI%?00w9bn^hxTjiSE{jnU~%kVd#aS>0`h zW*N-|)igZTUiY)=_fgX9JCJOkvVeHn=XW$Xi7F5?l#Vpp_FJm{l(|1FpRftEy7pKK zM7&Q#9ELQUHWmRfM6it~`Fw%(84&fDFxxvWf#XvD2>3nof3awmIML@p1@_(UX^_@G zwEt`W@*IxSpgKVTFlE?qBG1b!1A}+>mGDR#gI*pPr-={l|8{a z)FANA8hH}{9|#`Tdjm^^UpOW!*>SFzTcRE|@b>JXeZ93xUpoEs)z*Lhh%cD2YN+f+ ziQ^i-e_jk1uT?l2ABFNnvfjo;B!q?ftA2_aL9BcmT5Qf6{aZaYq>JHcQrpYO>nF>F zOFsk8Pl;h?;~Fg2$fykW8wJF>iNeGp?!kpllqnGt~a}yDqC#7f|DIq8%>|g zJ{@}*C>d61jYI9Nx|Oz^SVCE|rHJ@aEywNk&vGc4ihr&8bFAKhs)h2i>&rVNXt&Xf)3Mc8E?n8Pp&Xrv{RzA6n8 z{!mqGkVLN4#+6zw?#^=z@yrYh`ljy)JE}5!GQ7gT))$vhLRSFxzZi9F7Ic?n z0S5V%$_K5b_tPzQ0TMIque*T2Vt2VZf(KC5< z%=dNq;ADfZjxT^&OhGkyyK0jGTE__X*zjuCXi#&#k{&H-us?m{`SnEpq6|a@yluUN zEMt2kw0$9amuwwPwF9Un@u|A@JJLv);n;J`FwGD^y)T;#wujYdM{ZbfyqM}hThT#T zUhcviG@Q#f4p}uiqahWGsj8m=_5|0Ft#LqjVof@-NIQyTe4Cx4GK*iZ!#>O>tr*R> zCKap&v#Pm~$2fi5x%=uLM-EBdKsFO-te*Z;QG@4Z@IV8=8m%_O$PebH)Z%ZGXt{xh zpRy~pLj}#Rmp?29IeI&v;)V9lvA)n4Tx!dM6^ zgFKxs^`gWt=tKH~$L+C%W?$r5?FgmJ-}I+t&us80<(94<-nwVS*$JLO+P3b@;8DIA=uk_QICP1(6f%iPDGb@yqAN*>8jIT@Y4> zyq!mmC@5gxX=4zGvB=WIfMQrbjvF!lyIv4sGk|_`xK{*ZD7{}96azW(A4~qmBFki7 zZ-iu|rdhAZh22MwO*KC9mQYY!_OR5uDuEkBsl9#@DNx5OF?!&=;VI@}!ZfYik4LJC^Khqi>c9%=8bM&ig z5Z*>e8VQlBn)@xDHa%%-lrjM5sNVT>71rZA&3cmFsoxpK`+}uAw~ZZ*TxeBwQF?}h z&1q_%uevc$Ke%aF&g6R0)$o%s<6|d5@Xq7!mHbCA z;UPu^aGq~lriL~zU#v~ zrjrgNY9v3SL7j3sF6tK=vo#bV1!7~|!g+d~cb!YQ{$S%PoT>oDOd5d_8Gh-rcxws< zS6BAJIhdli=&{qkGIXU{gDu9ahBCNaV4WGGfFde%CP-5F!9viN@$YISUog9o&zT}? za%7kamN8g$(cf@{qu09~WC-R+s7-8bAVSY>judl@oi#rUVJdV9wXP6B&i(+B|EaZP zzQG~{p`@>NNy?$E?N zaU#%al^(-PQe@r5;Y{MQchE|oHwfymw`%~ILqFr&sC?p=WjXqiR5!H8wlc~zzS;zuq6`CGTW)o^SYT^87us;09l=~Jy~+X GBku2MJwdVn literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/a00322.html b/src/tbb/doc/html/a00322.html new file mode 100644 index 0000000..f0829d9 --- /dev/null +++ b/src/tbb/doc/html/a00322.html @@ -0,0 +1,118 @@ + + +tbb::recursive_mutex Class Reference + + + + + + + +

tbb::recursive_mutex Class Reference
+ +[Synchronization] +

Mutex that allows recursive mutex acquisition. +More... +

+#include <recursive_mutex.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef LPCRITICAL_SECTION native_handle_type
 Return native_handle.
+typedef pthread_mutex_t * native_handle_type

Public Member Functions

recursive_mutex ()
 Construct unacquired recursive_mutex.
+void lock ()
 Acquire lock.
bool try_lock ()
 Try acquiring lock (non-blocking).
+void unlock ()
 Release lock.
+native_handle_type native_handle ()

Static Public Attributes

+static const bool is_rw_mutex = false
+static const bool is_recursive_mutex = true
+static const bool is_fair_mutex = false

Friends

+class scoped_lock

Classes

class  scoped_lock
 The scoped locking pattern. More...
+


Detailed Description

+Mutex that allows recursive mutex acquisition. +

+Mutex that allows recursive mutex acquisition. +

+


Member Function Documentation

+ +
+
+ + + + + + + + +
bool tbb::recursive_mutex::try_lock (  )  [inline]
+
+
+ +

+Try acquiring lock (non-blocking). +

+Return true if lock acquired; false otherwise. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00323.html b/src/tbb/doc/html/a00323.html new file mode 100644 index 0000000..6a62752 --- /dev/null +++ b/src/tbb/doc/html/a00323.html @@ -0,0 +1,77 @@ + + +tbb::recursive_mutex::scoped_lock Class Reference + + + + + + + +

tbb::recursive_mutex::scoped_lock Class Reference

The scoped locking pattern. +More... +

+#include <recursive_mutex.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + +

Public Member Functions

scoped_lock ()
 Construct lock that has not acquired a recursive_mutex.
scoped_lock (recursive_mutex &mutex)
 Acquire lock on given mutex.
~scoped_lock ()
 Release lock (if lock is held).
+void acquire (recursive_mutex &mutex)
 Acquire lock on given mutex.
+bool try_acquire (recursive_mutex &mutex)
 Try acquire lock on given recursive_mutex.
+void release ()
 Release lock.

Friends

+class recursive_mutex
+


Detailed Description

+The scoped locking pattern. +

+It helps to avoid the common problem of forgetting to release lock. It also nicely provides the "node" for queuing locks. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00324.html b/src/tbb/doc/html/a00324.html new file mode 100644 index 0000000..46f100a --- /dev/null +++ b/src/tbb/doc/html/a00324.html @@ -0,0 +1,325 @@ + + +tbb::interface6::runtime_loader Class Reference + + + + + + + +

tbb::interface6::runtime_loader Class Reference

Load TBB at runtime. +More... +

+#include <runtime_loader.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

 em_status
 Save status of operation and continue.
 em_throw
 Throw an exception of tbb::runtime_loader::error_code type.
 em_abort
 Print message to stderr and call abort().
 ec_ok
 No errors.
 ec_bad_call
 Invalid function call (e. g. load() called when TBB is already loaded).
 ec_bad_arg
 Invalid argument passed.
 ec_bad_lib
 Invalid library found (e. g. TBB_runtime_version symbol not found).
 ec_bad_ver
 TBB found but version is not suitable.
 ec_no_lib
 No suitable TBB library found.
enum  error_mode { em_status, +em_throw, +em_abort + }
 Error mode constants. More...
enum  error_code {
+  ec_ok, +ec_bad_call, +ec_bad_arg, +ec_bad_lib, +
+  ec_bad_ver, +ec_no_lib +
+ }
 Error codes. More...

Public Member Functions

runtime_loader (error_mode mode=em_abort)
 Initialize object but do not load TBB.
 runtime_loader (char const *path[], int min_ver=TBB_INTERFACE_VERSION, int max_ver=INT_MAX, error_mode mode=em_abort)
 Initialize object and load TBB.
~runtime_loader ()
 Destroy object.
error_code load (char const *path[], int min_ver=TBB_INTERFACE_VERSION, int max_ver=INT_MAX)
 Load TBB.
error_code status ()
 Report status.
+


Detailed Description

+Load TBB at runtime. +

+Usage:

+In source code:

+

#include "tbb/runtime_loader.h"
+
+char const * path[] = { "<install dir>/lib/ia32", NULL };
+tbb::runtime_loader loader( path );
+
+// Now use TBB.
+

+Link with tbbproxy.lib (or libtbbproxy.a) instead of tbb.lib (libtbb.dylib, libtbb.so).

+TBB library will be loaded at runtime from <install dir>="">/lib/ia32 directory.

+Attention:

+All runtime_loader objects (in the same module, i.e. exe or dll) share some global state. The most noticeable piece of global state is loaded TBB library. There are some implications:

+

    +
  • Only one TBB library can be loaded per module.
+

+

    +
  • If one object has already loaded TBB library, another object will not load TBB. If the loaded TBB library is suitable for the second object, both will use TBB cooperatively, otherwise the second object will report an error.
+

+

    +
  • runtime_loader objects will not work (correctly) in parallel due to absence of syncronization.
+ +

+


Member Enumeration Documentation

+ +
+ +
+ +

+Error codes. +

+

Enumerator:
+ + + + + + + +
ec_ok  +No errors.
ec_bad_call  +Invalid function call (e. g. load() called when TBB is already loaded).
ec_bad_arg  +Invalid argument passed.
ec_bad_lib  +Invalid library found (e. g. TBB_runtime_version symbol not found).
ec_bad_ver  +TBB found but version is not suitable.
ec_no_lib  +No suitable TBB library found.
+
+ +
+

+ +

+ +
+ +

+Error mode constants. +

+

Enumerator:
+ + + + +
em_status  +Save status of operation and continue.
em_throw  +Throw an exception of tbb::runtime_loader::error_code type.
em_abort  +Print message to stderr and call abort().
+
+ +
+

+


Constructor & Destructor Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
tbb::interface6::runtime_loader::runtime_loader (char const *  path[],
int  min_ver = TBB_INTERFACE_VERSION,
int  max_ver = INT_MAX,
error_mode  mode = em_abort 
)
+
+
+ +

+Initialize object and load TBB. +

+See load() for details.

+If error mode is em_status, call status() to check whether TBB was loaded or not.

Parameters:
+ + + + + +
path  +List of directories to search TBB in.
min_ver  +Minimal suitable version of TBB.
max_ver  +Maximal suitable version of TBB.
mode  +Error mode for this object.
+
+
+

+


Member Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
error_code tbb::interface6::runtime_loader::load (char const *  path[],
int  min_ver = TBB_INTERFACE_VERSION,
int  max_ver = INT_MAX 
)
+
+
+ +

+Load TBB. +

+The method searches the directories specified in path[] array for the TBB library. When the library is found, it is loaded and its version is checked. If the version is not suitable, the library is unloaded, and the search continues.

+Note:

+For security reasons, avoid using relative directory names. For example, never load TBB from current ("."), parent ("..") or any other relative directory (like "lib" ). Use only absolute directory names (e. g. "/usr/local/lib").

+For the same security reasons, avoid using system default directories ("") on Windows. (See http://www.microsoft.com/technet/security/advisory/2269637.mspx for details.)

+Neglecting these rules may cause your program to execute 3-rd party malicious code.

+Errors:

    +
  • ec_bad_call - TBB already loaded by this object.
  • ec_bad_arg - min_ver and/or max_ver negative or zero, or min_ver > max_ver.
  • ec_bad_ver - TBB of unsuitable version already loaded by another object.
  • ec_no_lib - No suitable library found.
+
Parameters:
+ + + + +
path  +List of directories to search TBB in.
min_ver  +Minimal suitable version of TBB.
max_ver  +Maximal suitable version of TBB.
+
+
+

+ +

+
+ + + + + + + + +
error_code tbb::interface6::runtime_loader::status (  ) 
+
+
+ +

+Report status. +

+If error mode is em_status, the function returns status of the last operation. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00325.html b/src/tbb/doc/html/a00325.html new file mode 100644 index 0000000..97c2c3f --- /dev/null +++ b/src/tbb/doc/html/a00325.html @@ -0,0 +1,110 @@ + + +tbb::scalable_allocator< T > Class Template Reference + + + + + + + +

tbb::scalable_allocator< T > Class Template Reference
+ +[Memory Allocation] +

Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5. +More... +

+#include <scalable_allocator.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef internal::allocator_type<
+ T >::value_type 
value_type
+typedef value_type * pointer
+typedef const value_type * const_pointer
+typedef value_type & reference
+typedef const value_type & const_reference
+typedef size_t size_type
+typedef ptrdiff_t difference_type

Public Member Functions

scalable_allocator (const scalable_allocator &) throw ()
+template<typename U>
 scalable_allocator (const scalable_allocator< U > &) throw ()
+pointer address (reference x) const
+const_pointer address (const_reference x) const
+pointer allocate (size_type n, const void *=0)
 Allocate space for n objects.
+void deallocate (pointer p, size_type)
 Free previously allocated block of memory.
+size_type max_size () const throw ()
 Largest value for which method allocate might succeed.
+template<typename... Args>
void construct (pointer p, Args &&...args)

Classes

struct  rebind
+


Detailed Description

+

template<typename T>
+ class tbb::scalable_allocator< T >

+ +Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5. +

+The members are ordered the same way they are in section 20.4.1 of the ISO C++ standard. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00326.html b/src/tbb/doc/html/a00326.html new file mode 100644 index 0000000..bb877d6 --- /dev/null +++ b/src/tbb/doc/html/a00326.html @@ -0,0 +1,65 @@ + + +tbb::scalable_allocator< void > Class Template Reference + + + + + + + +

tbb::scalable_allocator< void > Class Template Reference
+ +[Memory Allocation] +

Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1. +More... +

+#include <scalable_allocator.h> +

+List of all members. + + + + + + + + + + + +

Public Types

+typedef void * pointer
+typedef const void * const_pointer
+typedef void value_type

Classes

struct  rebind
+


Detailed Description

+

template<>
+ class tbb::scalable_allocator< void >

+ +Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00327.html b/src/tbb/doc/html/a00327.html new file mode 100644 index 0000000..f5078f7 --- /dev/null +++ b/src/tbb/doc/html/a00327.html @@ -0,0 +1,93 @@ + + +tbb::flow::interface6::sender< T > Class Template Reference + + + + + + + +

tbb::flow::interface6::sender< T > Class Template Reference

Pure virtual template class that defines a sender of messages of type T. +More... +

+#include <flow_graph.h> +

+

Inheritance diagram for tbb::flow::interface6::sender< T >: +

+ +tbb::flow::interface6::broadcast_node< T > +tbb::flow::interface6::buffer_node< T, A > +tbb::flow::interface6::limiter_node< T > +tbb::flow::interface6::priority_queue_node< T, Compare, A > +tbb::flow::interface6::queue_node< T, A > +tbb::flow::interface6::sequencer_node< T, A > + +List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef T output_type
 The output type of this sender.
+typedef receiver< T > successor_type
 The successor type for this node.

Public Member Functions

+virtual bool register_successor (successor_type &r)=0
 Add a new successor to this node.
+virtual bool remove_successor (successor_type &r)=0
 Removes a successor from this node.
+virtual bool try_get (T &)
 Request an item from the sender.
+virtual bool try_reserve (T &)
 Reserves an item in the sender.
+virtual bool try_release ()
 Releases the reserved item.
+virtual bool try_consume ()
 Consumes the reserved item.
+

Detailed Description

+

template<typename T>
+ class tbb::flow::interface6::sender< T >

+ +Pure virtual template class that defines a sender of messages of type T. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00327.png b/src/tbb/doc/html/a00327.png new file mode 100644 index 0000000000000000000000000000000000000000..64fee8f22d6db4f58ed6b4471b72deaeb7c5ba87 GIT binary patch literal 2681 zcmb_ec|25mA0EWqi0YE%NRhX!L#2@-jJ0H$v1Ay9RAi_o*~&U%kV)2LsTf(uG%@zd z5Th(*oxwF@nTjk~$9nOO?)}_9?x*{H-aqai=RDtYp6~OV-}#;2bIyr@Tbc?B0)ikA zNch}YBWn<7#|dst-NDD*?~GHkjP|7#M< z&D!$&-_%Q!X~99+(ByeK{NvsTYYZuS6kGP-O~np(RgzW;6U%`YMAQ-h81DnYaGkl@=Y zpxyj*5WlWo42n142zRPsgS=FmzgldgQJ?_jMhHk}->5j~sUSuOWEEM(AC_Xv9@a1n|tIkTrS>_9Y1U!@W99L#-!d>A1QZu6r4An#q-8$2a{(!04d*KL~~53k~< zaILoKZS@7NdYj%>bFZ~cZ>t^uUGo~x<}IhjP>E@Y9EQ`8wHbt1-Nh8SwYwp$qN=4W zhm0Tm3}yuBG~E?O%M}QF@OY7N1V+eVCPt7$>%o1+g zo-`&ybRcHjpTr+P^`PE)CBy1u21wnLcD{6ErB}BHUac1;y)Sp7$Y2>sC}V-?1&gIu zhX4~P4Vi&eYl~6^+{ANZD@ga~XP8?ac%A5#ze0=iK3ikgPoG(;f?_SMtR4T8%hl3DnZ zeOk^M7EIjiIQDYaqkSTu)!pZeGT;aNTc*#a+-=SyC-o^MUr=XVdNgrxdD1Bm_Ranc zg%%(S<*f4RJ+mWq50N9<^g7jGH}NMwIvOge+ntIuDKws$H9d^(`?%H)m>FkdHp|sl zgov;5PdidMrxHC!?<~H4_DR`_4xeBG-8DfhrxCm#S~96Rz%P8M`65c*j$Ws*pz9fT zG7jJrbry;QCxkwaH^o zZ}I7M>m=ygAW|nOXa;-xgOmKnG=lP%i-5aP2yIG0tAu?fddAzm*|opTU$GmtEXZt{ z$kYatW7_8w)&OqT>Zai#wSYdKqmAyTB4!9$J-D!`7vq9}Gh5WD?W zl$~7;j<^>F)!+H^Z2pn*pF}u+rAdZ3!0+E1vZIchFj;GgmeB==Tn|h%vGi=`=pKiw z2{}!2KcZlGCB-;a9QR)Nffz*O$AI@ADpvjf1i@0F7Z+7vn{PboLK|bno1F*iZWkoz zT{eF3kFH)RzBg}O50KGjeEG$TKRtazGSb*B5^C+25S;Y_n*L?3OffxH64x$EuUW+1 zbQLa35KZWsF7=f*zFt9_Dq?!K=e+6!q)(5zsWD{GLtWkztWqR8Q#e)_X5gqIV?&^b zyfPV4T7oq4uUeG>hJq84^C-4yStpRR>x;GEcNA7fe6Xk686 z0=!|bJ^)9`Omv{^qQ*)6?vv;%ZZwb7Z>d@Ij?>amn!~&#xKNjASDleqf;q0Z)DCER zX$W0n3Z0PIkTIh~IUcx$;T;$Q%Ako+Q`mXGIgj2frS(+0mXugVMRYh@Ez0gC*8Y5W z-pKbW36Vgl6uf) z;I!sHtw?s!R%PhE$D8DOyZ00UWY|FjFTaa0926e9{n4vfjdZpasR-wW!rTzXgX9zA z=Hp)mL!I}5{QR>*8GkblPlT$O1+=HteyRqW@<@_t-aSaex_q(4Bd@QG;~8tzOWae* zM9h&9sL|obj@;z$MTQjTq_b$gehSpTeGGFVIBZIt$JUF;UWBjRg!I+*=&N& z)ptZjWQe1C4!_QWT|VYCF4kHFKxw@Nd&|Ba^_=z5Vx)b#>f3-$M;CCKa0B)?89IN8(`KP`C`h|7^62oUQ(`3^;ChI~Ls&HaKNq_xv$JIgs6Lt)Sx sY#700ANSUVpE3S6BRrp9AK3)|9_2T&{&A|F`=1CpXKZOiGH}8E7grVM82|tP literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/a00328.html b/src/tbb/doc/html/a00328.html new file mode 100644 index 0000000..b48bfa4 --- /dev/null +++ b/src/tbb/doc/html/a00328.html @@ -0,0 +1,112 @@ + + +tbb::flow::interface6::sequencer_node< T, A > Class Template Reference + + + + + + + +

tbb::flow::interface6::sequencer_node< T, A > Class Template Reference

Forwards messages in sequence order. +More... +

+#include <flow_graph.h> +

+

Inheritance diagram for tbb::flow::interface6::sequencer_node< T, A >: +

+ +tbb::flow::interface6::queue_node< T, A > +tbb::flow::interface6::buffer_node< T, A > +tbb::flow::interface6::graph_node +tbb::flow::interface6::receiver< T > +tbb::flow::interface6::sender< T > + +List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef T input_type
 The input type of this receiver.
+typedef T output_type
 The output type of this sender.
+typedef sender< input_typepredecessor_type
 The predecessor type for this node.
+typedef receiver< output_typesuccessor_type
 The successor type for this node.

Public Member Functions

+template<typename Sequencer>
 sequencer_node (graph &g, const Sequencer &s)
 Constructor.
sequencer_node (const sequencer_node &src)
 Copy constructor.
~sequencer_node ()
 Destructor.

Protected Types

+typedef buffer_node< T, A
+>::size_type 
size_type
+typedef buffer_node< T, A
+>::buffer_operation 
sequencer_operation
WAIT = 0
SUCCEEDED
FAILED
enum  op_stat { WAIT = 0, +SUCCEEDED, +FAILED + }
+

Detailed Description

+

template<typename T, typename A = cache_aligned_allocator<T>>
+ class tbb::flow::interface6::sequencer_node< T, A >

+ +Forwards messages in sequence order. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00328.png b/src/tbb/doc/html/a00328.png new file mode 100644 index 0000000000000000000000000000000000000000..30266e57e96cc306547a03fbfa406b2847f1ec09 GIT binary patch literal 2045 zcmbW2X;9Ni8pgvS;vmsMoZ*xp3W!8z6eJ*E40kxKAOS`Y80Ef{OU^`y5(JrmU=RX^ zJ0i#-hY&!J2m(TIfDLDeDCZzigm5JJC!29=s@yNLTl=BAfA9Nt_gnSUQ{8tjI#_|F z6s15Q5EyA~jsk(i&x^QgkGN=tJ*a|+7Ws>Imn?)rp$LV-E;89GQ$$}!S65ejw{Tt* zibbLvoIn>ACwxI5$!w%K;!;e(T7k#?Qq{wEIOXKlk03uuU8Q`=tniTKyW|sIhs=7N zJeEk6#|7q&J9}0xZ5Il>evV}yD8Asc+oAedyYagQYce-Mj9_kh_nnc3j~``?P%4=?n@iu*J+;%gXVyGoBKSF2nl58CZsHy3qA#5{LW- z-qNDpJ93@7lK4fvT{|?hC8)2$2)SBf6qcP(5GgI^@Wd}oo718d(9(!%Z~VoRCo>sh z7P%2&~UFmmO3ey>SI5IR|k>Ut*&uDfqBy2P>=SNO)wQ_B92*?SsljLYT%3k-e|{=he*u*YPEaxEKUE9aPfEBrDt8;E{3Z%eTVunN7*_g zIY&ZW5=Bz=LG&k$X;{0l1rloNjs47{hg+awU(UW)#d#4GbCgwlD|ZF)Hm5Ba1 zZ(>^Qr%!Fiu01T@tB%LJDHhF0nhc_F_h~ff*%OAw|1)~B%KDkVf)K5~NG0ye6ii() zBzRf!Z}5B{6DwUl!<4Qo;@ck$FoRFLJ*dBl0|Q>!fP1ZO$S4ur(^fJzg^s395ioIj zfS!%cqp>`C#_UP*f?}#bQ67(POvxgtbYL|k*vB+zXvvBW*wi?BUccC@KtK!^x?UycGCuq>C<=>K2VVepLihpHz#h46<+#MkfY; znp3;Rpp5+PDvaAF{)Z=zM;JZek`Y#o1yn?#q{%v1f0!jIN}Iia$MCNP7C)BwQy0-$ zl|C#Req@;<*$L_SMw&&oXEll)nnISw!e##S59dLBF~r~1Q$dLVKdk-ph^epRIQ3z+N$;b93S^yTkCX zSGcmmZXHXxds=bIK>LN|b5##wAG{ax@DnrMZjt5KVkO$B@)Ziq`j|(-&s_dCghS&EYiaNYWhqwzPI`@HB4LSn zkqM+I!6JFEeTda9jnF9U?K$?Ul(fhn3U(CZuAH9d;c`jaF=+0}x*=SR`IEvEV1@G9 v1n}Dt!$A3%!{0m$q&955O>3KijX-Q)o2IT4TAMHWt3gN$2lE + +tbb::simple_partitioner Class Reference + + + + + + + +

tbb::simple_partitioner Class Reference
+ +[Algorithms] +

A simple partitioner. +More... +

+#include <partitioner.h> +

+List of all members. + + + + + + + + + + + + + +

Friends

+class serial::interface6::start_for
+class interface6::internal::start_for
+class interface6::internal::start_reduce
+class internal::start_scan

Classes

class  partition_type
+


Detailed Description

+A simple partitioner. +

+Divides the range until the range is not divisible. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00330.html b/src/tbb/doc/html/a00330.html new file mode 100644 index 0000000..cea9942 --- /dev/null +++ b/src/tbb/doc/html/a00330.html @@ -0,0 +1,135 @@ + + +tbb::flow::interface6::source_node< Output > Class Template Reference + + + + + + + +

tbb::flow::interface6::source_node< Output > Class Template Reference

An executable node that acts as a source, i.e. it has no predecessors. +More... +

+#include <flow_graph.h> +

+

Inheritance diagram for tbb::flow::interface6::source_node< Output >: +

+ +tbb::flow::interface6::graph_node +tbb::flow::interface6::sender< Output > + +List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef Output output_type
 The type of the output message, which is complete.
+typedef receiver< Output > successor_type
 The type of successors of this node.

Public Member Functions

+template<typename Body>
 source_node (graph &g, Body body, bool is_active=true)
 Constructor for a node with a successor.
source_node (const source_node &src)
 Copy constructor.
~source_node ()
 The destructor.
+bool register_successor (receiver< output_type > &r)
 Add a new successor to this node.
+bool remove_successor (receiver< output_type > &r)
 Removes a successor from this node.
+bool try_get (output_type &v)
 Request an item from the node.
+bool try_reserve (output_type &v)
 Reserves an item.
bool try_release ()
 Release a reserved item.
+bool try_consume ()
 Consumes a reserved item.
+void activate ()
 Activates a node that was created in the inactive state.

Friends

+class internal::source_task< source_node< output_type > >
+

Detailed Description

+

template<typename Output>
+ class tbb::flow::interface6::source_node< Output >

+ +An executable node that acts as a source, i.e. it has no predecessors. +

+


Member Function Documentation

+ +
+
+
+template<typename Output>
+ + + + + + + + +
bool tbb::flow::interface6::source_node< Output >::try_release (  )  [inline, virtual]
+
+
+ +

+Release a reserved item. +

+true = item has been released and so remains in sender, dest must request or reserve future items +

+Reimplemented from tbb::flow::interface6::sender< Output >. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00330.png b/src/tbb/doc/html/a00330.png new file mode 100644 index 0000000000000000000000000000000000000000..14df9ee97edc00aa4aef409b4256c2df0e13d94c GIT binary patch literal 1084 zcmeAS@N?(olHy`uVBq!ia0y~yU=jne16Y`WVxn%%7hy z0muU50|yRNANv0U$Ym@E@(X5gcy=R=fr0swr;B4q#hkY@W6K^Z@U%W$dcH&Uz?+0! z3oB3kn{MF2(b8G`=$M_WZ)tU3a9xky{M3mvcb)%QwBo8-*PZ)&qUt+Z+2o~cB)C5& z=p1R@D8N4}@<_|{U)D>`dQ6+hbJ#&j`p(xSx^ih^(~rzQ#F$f^Jn!oi*IPH8?r@5| z7vJA<^!3Nfce-ZZYt|835^_y#LO_k^vx&_|je=$g6ni~wn%^+FZTSqLt%{G8c0@h$ z%+#;^#Mf>7(U?8|VbYsu{~c^DC2i&M$$?5@><#_wa~}vjX}z`9_^S4|%j|9ocE4h{ zvU11f6O$A4E5Aj|>Ac@uY~jGn%q{2hghfrB|K7wS$EtVi+GrINyCmlNd6{|X+uxmd zX)9%S=F!t1#XBMbd2|+SxN)drBCEq!rW8d+p3TwU`M4XpBW$|*Gc^wy#;nnh+i>H6 z#hFDJHF~+X|HOQ1JG$YwjqM6s*`z|9I{n?YcUUV0kFV+9TjFb3HT_?Re$=^hI{V`E z<2vM*7fgKZx~k<-fKT7m?y%$05i9O2HA(!tOs03@>xxA;L-ww;E)x69{O6Kok(!;n z*2ekDwZ5ws0Yloz{rp7XtmohVz22}o|KGiz7j7QaxpZWa$fmm?Gi>&#cHiOWI^8{e z$?yAV_un3j=wMG)l*n?GWl`g z0prpG$B)0=c8kfgnV(lKK&vKWMWhC=ok@iQR4GVQswU$@!=(q#&FoV^alQbe@nAa} zKTK)hzCW)nWC@6S9yY$Jl&okZhL5OH7TXZFTCk+`D%+g++y$p2I(k}9fC!BRGcU;g zG&uC}uaom(4w?){hj-a*UkTIZFG(M{(apCiynqt>n`itVkCL%n$2(a zv;Y7A literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/a00331.html b/src/tbb/doc/html/a00331.html new file mode 100644 index 0000000..63d8419 --- /dev/null +++ b/src/tbb/doc/html/a00331.html @@ -0,0 +1,131 @@ + + +tbb::spin_mutex Class Reference + + + + + + + +

tbb::spin_mutex Class Reference
+ +[Synchronization] +

A lock that occupies a single byte. +More... +

+#include <spin_mutex.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Member Functions

 spin_mutex ()
 Construct unacquired lock.
+void __TBB_EXPORTED_METHOD internal_construct ()
+void lock ()
 Acquire lock.
bool try_lock ()
 Try acquiring lock (non-blocking).
+void unlock ()
 Release lock.

Static Public Attributes

+static const bool is_rw_mutex = false
+static const bool is_recursive_mutex = false
+static const bool is_fair_mutex = false

Friends

+class scoped_lock

Classes

class  scoped_lock
 Represents acquisition of a mutex. More...
+


Detailed Description

+A lock that occupies a single byte. +

+A spin_mutex is a spin mutex that fits in a single byte. It should be used only for locking short critical sections (typically less than 20 instructions) when fairness is not an issue. If zero-initialized, the mutex is considered unheld. +

+


Constructor & Destructor Documentation

+ +
+
+ + + + + + + + +
tbb::spin_mutex::spin_mutex (  )  [inline]
+
+
+ +

+Construct unacquired lock. +

+Equivalent to zero-initialization of *this. +

+

+


Member Function Documentation

+ +
+
+ + + + + + + + +
bool tbb::spin_mutex::try_lock (  )  [inline]
+
+
+ +

+Try acquiring lock (non-blocking). +

+Return true if lock acquired; false otherwise. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00332.html b/src/tbb/doc/html/a00332.html new file mode 100644 index 0000000..a9b527d --- /dev/null +++ b/src/tbb/doc/html/a00332.html @@ -0,0 +1,97 @@ + + +tbb::spin_mutex::scoped_lock Class Reference + + + + + + + +

tbb::spin_mutex::scoped_lock Class Reference

Represents acquisition of a mutex. +More... +

+#include <spin_mutex.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + +

Public Member Functions

scoped_lock ()
 Construct without acquiring a mutex.
scoped_lock (spin_mutex &m)
 Construct and acquire lock on a mutex.
+void acquire (spin_mutex &m)
 Acquire lock.
bool try_acquire (spin_mutex &m)
 Try acquiring lock (non-blocking).
+void release ()
 Release lock.
~scoped_lock ()
 Destroy lock. If holding a lock, releases the lock first.

Friends

+class spin_mutex
+


Detailed Description

+Represents acquisition of a mutex. +

+


Member Function Documentation

+ +
+
+ + + + + + + + + +
bool tbb::spin_mutex::scoped_lock::try_acquire (spin_mutex m  )  [inline]
+
+
+ +

+Try acquiring lock (non-blocking). +

+Return true if lock acquired; false otherwise. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00333.html b/src/tbb/doc/html/a00333.html new file mode 100644 index 0000000..1b1dbd6 --- /dev/null +++ b/src/tbb/doc/html/a00333.html @@ -0,0 +1,133 @@ + + +tbb::spin_rw_mutex_v3 Class Reference + + + + + + + +

tbb::spin_rw_mutex_v3 Class Reference
+ +[Synchronization] +

Fast, unfair, spinning reader-writer lock with backoff and writer-preference. +More... +

+#include <spin_rw_mutex.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Member Functions

spin_rw_mutex_v3 ()
 Construct unacquired mutex.
~spin_rw_mutex_v3 ()
 Destructor asserts if the mutex is acquired, i.e. state is zero.
+void lock ()
 Acquire writer lock.
bool try_lock ()
 Try acquiring writer lock (non-blocking).
+void unlock ()
 Release lock.
+void lock_read ()
 Acquire reader lock.
bool try_lock_read ()
 Try acquiring reader lock (non-blocking).

Static Public Attributes

+static const bool is_rw_mutex = true
+static const bool is_recursive_mutex = false
+static const bool is_fair_mutex = false

Classes

class  scoped_lock
 The scoped locking pattern. More...
+


Detailed Description

+Fast, unfair, spinning reader-writer lock with backoff and writer-preference. +

+


Member Function Documentation

+ +
+
+ + + + + + + + +
bool tbb::spin_rw_mutex_v3::try_lock (  )  [inline]
+
+
+ +

+Try acquiring writer lock (non-blocking). +

+Return true if lock acquired; false otherwise. +

+

+ +

+
+ + + + + + + + +
bool tbb::spin_rw_mutex_v3::try_lock_read (  )  [inline]
+
+
+ +

+Try acquiring reader lock (non-blocking). +

+Return true if reader lock acquired; false otherwise. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00334.html b/src/tbb/doc/html/a00334.html new file mode 100644 index 0000000..09c4189 --- /dev/null +++ b/src/tbb/doc/html/a00334.html @@ -0,0 +1,149 @@ + + +tbb::spin_rw_mutex_v3::scoped_lock Class Reference + + + + + + + +

tbb::spin_rw_mutex_v3::scoped_lock Class Reference

The scoped locking pattern. +More... +

+#include <spin_rw_mutex.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Member Functions

 scoped_lock ()
 Construct lock that has not acquired a mutex.
scoped_lock (spin_rw_mutex &m, bool write=true)
 Acquire lock on given mutex.
~scoped_lock ()
 Release lock (if lock is held).
+void acquire (spin_rw_mutex &m, bool write=true)
 Acquire lock on given mutex.
bool upgrade_to_writer ()
 Upgrade reader to become a writer.
+void release ()
 Release lock.
+bool downgrade_to_reader ()
 Downgrade writer to become a reader.
+bool try_acquire (spin_rw_mutex &m, bool write=true)
 Try acquire lock on given mutex.

Protected Attributes

+spin_rw_mutexmutex
 The pointer to the current mutex that is held, or NULL if no mutex is held.
bool is_writer
 If mutex!=NULL, then is_writer is true if holding a writer lock, false if holding a reader lock.
+


Detailed Description

+The scoped locking pattern. +

+It helps to avoid the common problem of forgetting to release lock. It also nicely provides the "node" for queuing locks. +

+


Constructor & Destructor Documentation

+ +
+
+ + + + + + + + +
tbb::spin_rw_mutex_v3::scoped_lock::scoped_lock (  )  [inline]
+
+
+ +

+Construct lock that has not acquired a mutex. +

+Equivalent to zero-initialization of *this. +

+

+


Member Function Documentation

+ +
+
+ + + + + + + + +
bool tbb::spin_rw_mutex_v3::scoped_lock::upgrade_to_writer (  )  [inline]
+
+
+ +

+Upgrade reader to become a writer. +

+Returns whether the upgrade happened without releasing and re-acquiring the lock +

+

+


Member Data Documentation

+ +
+
+ + + + +
bool tbb::spin_rw_mutex_v3::scoped_lock::is_writer [protected]
+
+
+ +

+If mutex!=NULL, then is_writer is true if holding a writer lock, false if holding a reader lock. +

+Not defined if not holding a lock. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00335.html b/src/tbb/doc/html/a00335.html new file mode 100644 index 0000000..c157ee6 --- /dev/null +++ b/src/tbb/doc/html/a00335.html @@ -0,0 +1,51 @@ + + +tbb::split Class Reference + + + + + + + +

tbb::split Class Reference
+ +[Algorithms] +

Dummy type that distinguishes splitting constructor from copy constructor. +More... +

+#include <tbb_stddef.h> +

+ + +
+


Detailed Description

+Dummy type that distinguishes splitting constructor from copy constructor. +

+See description of parallel_for and parallel_reduce for example usages. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00336.html b/src/tbb/doc/html/a00336.html new file mode 100644 index 0000000..8958aba --- /dev/null +++ b/src/tbb/doc/html/a00336.html @@ -0,0 +1,75 @@ + + +tbb::flow::interface6::split_node< TupleType, Allocator > Class Template Reference + + + + + + + +

tbb::flow::interface6::split_node< TupleType, Allocator > Class Template Reference

split_node: accepts a tuple as input, forwards each element of the tuple to its +More... +

+#include <flow_graph.h> +

+

Inheritance diagram for tbb::flow::interface6::split_node< TupleType, Allocator >: +

+ +tbb::flow::interface6::multifunction_node< TupleType, TupleType, rejecting, Allocator > +tbb::flow::interface6::graph_node + +List of all members. + + + + + + + + + + + + + + + + +

Public Types

+typedef base_type::output_ports_type output_ports_type
+typedef TupleType input_type
+typedef Allocator allocator_type

Public Member Functions

split_node (graph &g)
split_node (const split_node &other)

Classes

struct  splitting_body
+

Detailed Description

+

template<typename TupleType, typename Allocator = cache_aligned_allocator<TupleType>>
+ class tbb::flow::interface6::split_node< TupleType, Allocator >

+ +split_node: accepts a tuple as input, forwards each element of the tuple to its +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00336.png b/src/tbb/doc/html/a00336.png new file mode 100644 index 0000000000000000000000000000000000000000..b0f2ab0a1df44ab1de9341bf91df5cd6ec4baa02 GIT binary patch literal 3005 zcmbVOc{J2*8~#~(C5D<5#+Gb(QDP#52`SrTDcPmOn6ivzYV5=ylwFo-EKMW{DG4() zQC>^KG-fC}V;LmMuKA|k&i9@7zxRCS{FeK9?&rSFeLv^Aujfg!hMxuPf$RYQ0AzN~ z#1;Vf1UYshFAwLt`!shR=O<=udEpG3&E}YFb_*VVIgMledRtmr!rrhaIYX{sTeuwn zV=}w|K)}w-w`9um*}-=oz-Ym29IQJLd)``86Iv;WU;vbAbdd)Sj64{F1p%Pz zd=M>IHso$U>HYBmRd1(2MRScCp(SSiJt`ih#d&z98OBIs^wUIMVxP!Oq&@ZR+uR{6 z+Lro;)xTU}y1xtVXTM@ncox_7$&au=X4Uz%h0DeI>OE&?9(29<#MQX*>OJJEkj1b!}Hx)IGvXd=Oyfo$fdj8+A$xy?qdC)Q8!l#?_4fGT82TKYWscKSQ0u4L+08Q z-ld(WGAO+NwI~}-w5~-vbxuP!OvA6+3k)Ia0}X5-QYuN?J4t%z158J%w_ge?kAR`qe}ta*#eHKWy!%4T)A^>_ z9q63Z)`F>0z5~J~t%%1Sez01zSUHqIvJ7-(f|71o_LSI6T|?mykM`?$>sd9#vR zYS;TI9n48N(veX9=9o%Ze1eI}GXvZRVqCCKFr!4MO4d=&g1M6f=~F!n`7seSBfkH0 za<86d##On_M~;f3J{{@}-z=diPmg8~Sqgm5U|QKa5Jo5VO8Z3jy^ypM)NL=qocEo% zP&gkSKDkspQE@=UCe+c*Rmt~|=OYL)^>WAtb4uergRUxb=g)rY?fge=P?UL~39NIV zG^^M_SN>k8VZm#s7g!G`HL8VWr}w1BzV+^hq=`$JtURPxS&tngqXSYl_;TX~RuPxr zwNE9dYnvZa{4NM(JA?XOOf_FFz0&*|-q4kY^_O#SC0dfbx39_8*gS`TllP zJ~!N(Hk0df(qAceB=|lag)6c&E-Bh|4boFrT0HNyt}SjyL6)6jyR4}d7AJb3_W0uS( zc{2~NmL5U70{lM4Dbgx-yvf(3E7As@7fbdr2Lk#H;B98T;S2J-=|^7BmS%K)cphE~ z>0R>WU12WkuiV2U9lkvGU?_vy(<{*)H%-yz8;e1bA!Q!}eTIdmCet68khRd}J7W9K zOB;rnd2yizEk9Tqlajr2cFg748urfaSrv4SP(&PQ3|lr{(a09W&zY*O5gYAvS&fO1 z9OYq68&Rs*gDpM6vGEilMmzCLT64!_uCPAY>hW>pMr+7;{txh1Eu_fT3%uK3pLedM z$hf1;LGkbFY*Qg_hqk9K$9E2M8EzcxZYn@7XJU?RT*%z&#*bTiD;i?xpW+d@w4Z9)`{B-4r6!5AC-^Uf5e9D{;sNw;sOnxYSwa_eR*=RCCJM4kZ7wG%g=j6bV4;C?RBF~1sTP^3T6K8Fs;;^IsOX46k$NG%arqwj}{zSEv=jdRa z#g9*of6HxJzquK!;E>MvVQ8R-Pv%JYMY9X0_QTgu32r5X%?@x?m{7bCzEB4#TH%qR z6Mpxeiyapy*LU{DN-`T~P?JetysM*XGRR5xZUb?L5;_&E#BZlfWVHBhu9~sVNrbNb znPF4@IAeAoxFU|`RmLc5I>*fNZvSw6s-Di4r&RMB+_Zx*(HewY$tOWhUkpTBV<`FCUosw`r|4Twn4cBcaK)Hh)w6<< zWNero!9{t1@4MQJ!OX3SI9wmDkFr%>&{Q&3Yo|Lmy?%(Z9fRzH-S_bf-{nu>0+Ntq zy;*!T)`}91O>mFgXCF1~Khe7Ze!~3D|Lq`*tcZY-wJV8J%X5uTK81e%RXgEGrJu`* zSYIAc0RZU-L2qy)9JD#OMIJ+(fM{&UPY0*(rm`NufF?e+i~8RjpJv(Uas!e2l)ce? z+Z&sIN^t`uDGui`)n|DAJ@NmKUin8zc{JxP!^v#apOVYzZte*>uUPx**7Xxy*cw0e zNULa%N{JNr{g=g9e{fuD6758ZD-JvAo;pL|06deDmIGN9&Mw^7mhq!`6}N*&@`2f zY}nPug8al+zWAYn{80|*l>9Mj4)IanJtpmNVj(X3oV}-lrJ)O8~e~(+E?4hMbBl3 zZzOIjRc4)wQ%O0DenvbLljU5Q)_8H%>c!mTO&S=7-ATrF$+H9&alL-bj+$$dg={Nn(>@zh$ ztd>?Spi)waMI}Enq)_M#M-X9ouX7)FM9Ek*hx;7VtKnMnB^n+tI{nS5@3fV1h7#?x zpzk*r-XE}Tq>i`pp>oMW&+?)IJX!1wJ6BU!7j^9DLnJwGdF z`}S9j3@L{!l<5&vOZ}43$yiibov_q!=C5*7K@&R8o3xJVOc(wW?SfiRt(4Q{bhfP9 zYH@-Ct4d{91tLKjF~3S)-=S3-y0UVhT9Kp!f>(zwZ|4JK2W>HuVvBk|sQnqgdP>Oc juh+SMyMFUpW|SQotIYuSw)=AK+JM;^xJi}K<=FoKxk;^{ literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/a00337.html b/src/tbb/doc/html/a00337.html new file mode 100644 index 0000000..9c2e5d6 --- /dev/null +++ b/src/tbb/doc/html/a00337.html @@ -0,0 +1,625 @@ + + +tbb::task Class Reference + + + + + + + +

tbb::task Class Reference
+ +[Task Scheduling] +

Base class for user-defined tasks. +More... +

+#include <task.h> +

+

Inheritance diagram for tbb::task: +

+ +tbb::empty_task + +List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

typedef internal::affinity_id affinity_id
 An id as used for specifying affinity.
 executing
 task is running, and will be destroyed after method execute() completes.
 reexecute
 task to be rescheduled.
 ready
 task is in ready pool, or is going to be put there, or was just taken off.
 allocated
 task object is freshly allocated or recycled.
 freed
 task object is on free list, or is going to be put there, or was just taken off.
 recycle
 task to be recycled as continuation
enum  state_type {
+  executing, +reexecute, +ready, +allocated, +
+  freed, +recycle +
+ }
 Enumeration of task states that the scheduler considers. More...

Public Member Functions

+virtual ~task ()
 Destructor.
+virtual taskexecute ()=0
 Should be overridden by derived classes.
internal::allocate_continuation_proxy & allocate_continuation ()
 Returns proxy for overloaded new that allocates a continuation task of *this.
+internal::allocate_child_proxy & allocate_child ()
 Returns proxy for overloaded new that allocates a child task of *this.
void __TBB_EXPORTED_METHOD destroy (task &t)
 Destroy a task.
void recycle_as_continuation ()
 Change this to be a continuation of its former self.
void recycle_as_safe_continuation ()
 Recommended to use, safe variant of recycle_as_continuation.
+void recycle_as_child_of (task &new_parent)
 Change this to be a child of new_parent.
void recycle_to_reexecute ()
 Schedule this for reexecution after current execute() returns.
+intptr_t depth () const
+void set_depth (intptr_t)
+void add_to_depth (int)
+void set_ref_count (int count)
 Set reference count.
void increment_ref_count ()
 Atomically increment reference count and returns its old value.
int decrement_ref_count ()
 Atomically decrement reference count and returns its new value.
+void spawn_and_wait_for_all (task &child)
 Similar to spawn followed by wait_for_all, but more efficient.
+void __TBB_EXPORTED_METHOD spawn_and_wait_for_all (task_list &list)
 Similar to spawn followed by wait_for_all, but more efficient.
void wait_for_all ()
 Wait for reference count to become one, and set reference count to zero.
+taskparent () const
 task on whose behalf this task is working, or NULL if this is a root.
+void set_parent (task *p)
 sets parent task pointer to specified value
task_group_contextcontext ()
 This method is deprecated and will be removed in the future.
+task_group_contextgroup ()
 Pointer to the task group descriptor.
+bool is_stolen_task () const
 True if task was stolen from the task pool of another thread.
+state_type state () const
 Current execution state.
+int ref_count () const
 The internal reference count.
+bool __TBB_EXPORTED_METHOD is_owned_by_current_thread () const
 Obsolete, and only retained for the sake of backward compatibility. Always returns true.
+void set_affinity (affinity_id id)
 Set affinity for this task.
+affinity_id affinity () const
 Current affinity of this task.
virtual void __TBB_EXPORTED_METHOD note_affinity (affinity_id id)
 Invoked by scheduler to notify task that it ran on unexpected thread.
void __TBB_EXPORTED_METHOD change_group (task_group_context &ctx)
 Moves this task from its current group into another one.
bool cancel_group_execution ()
 Initiates cancellation of all tasks in this cancellation group and its subordinate groups.
+bool is_cancelled () const
 Returns true if the context has received cancellation request.
+void set_group_priority (priority_t p)
 Changes priority of the task group this task belongs to.
+priority_t group_priority () const
 Retrieves current priority of the task group this task belongs to.

Static Public Member Functions

+static internal::allocate_root_proxy allocate_root ()
 Returns proxy for overloaded new that allocates a root task.
+static internal::allocate_root_with_context_proxy allocate_root (task_group_context &ctx)
 Returns proxy for overloaded new that allocates a root task associated with user supplied context.
+static void spawn_root_and_wait (task &root)
 Spawn task allocated by allocate_root, wait for it to complete, and deallocate it.
static void spawn_root_and_wait (task_list &root_list)
 Spawn root tasks on list and wait for all of them to finish.
static void enqueue (task &t)
 Enqueue task for starvation-resistant execution.
+static void enqueue (task &t, priority_t p)
 Enqueue task for starvation-resistant execution on the specified priority level.
+static task &__TBB_EXPORTED_FUNC self ()
 The innermost task being executed or destroyed by the current thread at the moment.

Protected Member Functions

task ()
 Default constructor.

Friends

+class interface5::internal::task_base
+class task_list
+class internal::scheduler
+class internal::allocate_root_proxy
+class internal::allocate_root_with_context_proxy
+class internal::allocate_continuation_proxy
+class internal::allocate_child_proxy
+class internal::allocate_additional_child_of_proxy
+

Detailed Description

+Base class for user-defined tasks. +

+


Member Typedef Documentation

+ +
+
+ + + + +
typedef internal::affinity_id tbb::task::affinity_id
+
+
+ +

+An id as used for specifying affinity. +

+Guaranteed to be integral type. Value of 0 means no affinity. +

+

+


Member Enumeration Documentation

+ +
+
+ + + + +
enum tbb::task::state_type
+
+
+ +

+Enumeration of task states that the scheduler considers. +

+

Enumerator:
+ + + + + + + +
executing  +task is running, and will be destroyed after method execute() completes.
reexecute  +task to be rescheduled.
ready  +task is in ready pool, or is going to be put there, or was just taken off.
allocated  +task object is freshly allocated or recycled.
freed  +task object is on free list, or is going to be put there, or was just taken off.
recycle  +task to be recycled as continuation
+
+ +
+

+


Member Function Documentation

+ +
+
+ + + + + + + + +
internal::allocate_continuation_proxy& tbb::task::allocate_continuation (  )  [inline]
+
+
+ +

+Returns proxy for overloaded new that allocates a continuation task of *this. +

+The continuation's parent becomes the parent of *this. +

+

+ +

+
+ + + + + + + + +
bool tbb::task::cancel_group_execution (  )  [inline]
+
+
+ +

+Initiates cancellation of all tasks in this cancellation group and its subordinate groups. +

+

Returns:
false if cancellation has already been requested, true otherwise.
+ +
+

+ +

+
+ + + + + + + + + +
void __TBB_EXPORTED_METHOD tbb::task::change_group (task_group_context ctx  ) 
+
+
+ +

+Moves this task from its current group into another one. +

+Argument ctx specifies the new group.

+The primary purpose of this method is to associate unique task group context with a task allocated for subsequent enqueuing. In contrast to spawned tasks enqueued ones normally outlive the scope where they were created. This makes traditional usage model where task group context are allocated locally on the stack inapplicable. Dynamic allocation of context objects is performance inefficient. Method change_group() allows to make task group context object a member of the task class, and then associate it with its containing task object in the latter's constructor. +

+

+ +

+
+ + + + + + + + +
task_group_context* tbb::task::context (  )  [inline]
+
+
+ +

+This method is deprecated and will be removed in the future. +

+Use method group() instead. +

+

+ +

+
+ + + + + + + + +
int tbb::task::decrement_ref_count (  )  [inline]
+
+
+ +

+Atomically decrement reference count and returns its new value. +

+Has release semantics. +

+

+ +

+
+ + + + + + + + + +
void __TBB_EXPORTED_METHOD tbb::task::destroy (task t  ) 
+
+
+ +

+Destroy a task. +

+Usually, calling this method is unnecessary, because a task is implicitly deleted after its execute() method runs. However, sometimes a task needs to be explicitly deallocated, such as when a root task is used as the parent in spawn_and_wait_for_all. +

+

+ +

+
+ + + + + + + + + +
static void tbb::task::enqueue (task t  )  [inline, static]
+
+
+ +

+Enqueue task for starvation-resistant execution. +

+The task will be enqueued on the normal priority level disregarding the priority of its task group.

+The rationale of such semantics is that priority of an enqueued task is statically fixed at the moment of its enqueuing, while task group priority is dynamic. Thus automatic priority inheritance would be generally a subject to the race, which may result in unexpected behavior.

+Use enqueue() overload with explicit priority value and task::group_priority() method to implement such priority inheritance when it is really necessary. +

+

+ +

+
+ + + + + + + + +
void tbb::task::increment_ref_count (  )  [inline]
+
+
+ +

+Atomically increment reference count and returns its old value. +

+Has acquire semantics +

+

+ +

+
+ + + + + + + + + +
virtual void __TBB_EXPORTED_METHOD tbb::task::note_affinity (affinity_id  id  )  [virtual]
+
+
+ +

+Invoked by scheduler to notify task that it ran on unexpected thread. +

+Invoked before method execute() runs, if task is stolen, or task has affinity but will be executed on another thread.

+The default action does nothing. +

+

+ +

+
+ + + + + + + + +
void tbb::task::recycle_as_continuation (  )  [inline]
+
+
+ +

+Change this to be a continuation of its former self. +

+The caller must guarantee that the task's refcount does not become zero until after the method execute() returns. Typically, this is done by having method execute() return a pointer to a child of the task. If the guarantee cannot be made, use method recycle_as_safe_continuation instead.

+Because of the hazard, this method may be deprecated in the future. +

+

+ +

+
+ + + + + + + + +
void tbb::task::recycle_as_safe_continuation (  )  [inline]
+
+
+ +

+Recommended to use, safe variant of recycle_as_continuation. +

+For safety, it requires additional increment of ref_count. With no descendants and ref_count of 1, it has the semantics of recycle_to_reexecute. +

+

+ +

+
+ + + + + + + + +
void tbb::task::recycle_to_reexecute (  )  [inline]
+
+
+ +

+Schedule this for reexecution after current execute() returns. +

+Made obsolete by recycle_as_safe_continuation; may become deprecated. +

+

+ +

+
+ + + + + + + + + +
void tbb::task::spawn_root_and_wait (task_list root_list  )  [inline, static]
+
+
+ +

+Spawn root tasks on list and wait for all of them to finish. +

+If there are more tasks than worker threads, the tasks are spawned in order of front to back. +

+

+ +

+
+ + + + + + + + +
void tbb::task::wait_for_all (  )  [inline]
+
+
+ +

+Wait for reference count to become one, and set reference count to zero. +

+Works on tasks while waiting. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00337.png b/src/tbb/doc/html/a00337.png new file mode 100644 index 0000000000000000000000000000000000000000..497b6ad719841006fa4b1047595a4ae2679c81fc GIT binary patch literal 393 zcmV;40e1e0P)BNeHv3=r;6UAZDf(vfWK9umX^(ED= zuObivoc9v*;GJVP_;C+#1=rYRYZw#3Dou@w#KUu}1R$y=2wfkm%I7GAoo7UpSp{Kv za^kinf8x9PSH%3^r)QVR-cJx;%l^c&Ty`gZV^#-o5C?G(Z%3RvcJ0JZ?mNxdM-efR z-0tlbp?ZCi01;A*8i?X?jw2k_q9|_SG{v7*; zMF2GsvwlESZ4>sq63K+-T2=WRl`7m5rKJ&NR+2)_st%j0j!kzoc<0o-iOR-Alu4k) n#>7U8cmCRUCwhOMo}GRGLm;@;u~!e;00000NkvXXu0mjfwtB1} literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/a00338.html b/src/tbb/doc/html/a00338.html new file mode 100644 index 0000000..5c918ce --- /dev/null +++ b/src/tbb/doc/html/a00338.html @@ -0,0 +1,48 @@ + + +tbb::interface5::internal::task_base Class Reference + + + + + + + +

tbb::interface5::internal::task_base Class Reference

Base class for methods that became static in TBB 3.0. +More... +

+#include <task.h> +

+List of all members. + +
+


Detailed Description

+Base class for methods that became static in TBB 3.0. +

+TBB's evolution caused the "this" argument for several methods to become obsolete. However, for backwards binary compatibility, the new methods need distinct names, otherwise the One Definition Rule would be broken. Hence the new methods are defined in this private base class, and then exposed in class task via using declarations. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00339.html b/src/tbb/doc/html/a00339.html new file mode 100644 index 0000000..d7a08fe --- /dev/null +++ b/src/tbb/doc/html/a00339.html @@ -0,0 +1,43 @@ + + +tbb::task_group_context Struct Reference + + + + + + + +

tbb::task_group_context Struct Reference

#include <parallel_invoke.h> +

+ + +
+


Detailed Description

+Dummy to avoid cluttering the bulk of the header with enormous amount of ifdefs. +

+


The documentation for this struct was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00341.html b/src/tbb/doc/html/a00341.html new file mode 100644 index 0000000..eb061d6 --- /dev/null +++ b/src/tbb/doc/html/a00341.html @@ -0,0 +1,83 @@ + + +tbb::task_list Class Reference + + + + + + + +

tbb::task_list Class Reference
+ +[Task Scheduling] +

A list of children. +More... +

+#include <task.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Member Functions

task_list ()
 Construct empty list.
~task_list ()
 Destroys the list, but does not destroy the task objects.
+bool empty () const
 True if list if empty; false otherwise.
+void push_back (task &task)
 Push task onto back of list.
+taskpop_front ()
 Pop the front task from the list.
+void clear ()
 Clear the list.

Friends

+class task
+class interface5::internal::task_base
+


Detailed Description

+A list of children. +

+Used for method task::spawn_children +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00342.html b/src/tbb/doc/html/a00342.html new file mode 100644 index 0000000..d4ca23f --- /dev/null +++ b/src/tbb/doc/html/a00342.html @@ -0,0 +1,168 @@ + + +tbb::task_scheduler_init Class Reference + + + + + + + +

tbb::task_scheduler_init Class Reference
+ +[Task Scheduling] +

Class delimiting the scope of task scheduler activity. +More... +

+#include <task_scheduler_init.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Member Functions

void __TBB_EXPORTED_METHOD initialize (int number_of_threads=automatic)
 Ensure that scheduler exists for this thread.
void __TBB_EXPORTED_METHOD initialize (int number_of_threads, stack_size_type thread_stack_size)
 The overloaded method with stack size parameter.
+void __TBB_EXPORTED_METHOD terminate ()
 Inverse of method initialize.
task_scheduler_init (int number_of_threads=automatic, stack_size_type thread_stack_size=0)
 Shorthand for default constructor followed by call to initialize(number_of_threads).
~task_scheduler_init ()
 Destroy scheduler for this thread if thread has no other live task_scheduler_inits.
+bool is_active () const
 Returns true if scheduler is active (initialized); false otherwise.

Static Public Member Functions

static int __TBB_EXPORTED_FUNC default_num_threads ()
 Returns the number of threads TBB scheduler would create if initialized by default.

Static Public Attributes

+static const int automatic = -1
 Typedef for number of threads that is automatic.
+static const int deferred = -2
 Argument to initialize() or constructor that causes initialization to be deferred.
+


Detailed Description

+Class delimiting the scope of task scheduler activity. +

+A thread can construct a task_scheduler_init object and keep it alive while it uses TBB's tasking subsystem (including parallel algorithms).

+This class allows to customize properties of the TBB task pool to some extent. For example it can limit concurrency level of parallel work initiated by the given thread. It also can be used to specify stack size of the TBB worker threads, though this setting is not effective if the thread pool has already been created.

+If a parallel construct is used without task_scheduler_init object previously created, the scheduler will be initialized automatically with default settings, and will persist until this thread exits. Default concurrency level is defined as described in task_scheduler_init::initialize(). +

+


Member Function Documentation

+ +
+
+ + + + + + + + +
static int __TBB_EXPORTED_FUNC tbb::task_scheduler_init::default_num_threads (  )  [static]
+
+
+ +

+Returns the number of threads TBB scheduler would create if initialized by default. +

+Result returned by this method does not depend on whether the scheduler has already been initialized.

+Because tbb 2.0 does not support blocking tasks yet, you may use this method to boost the number of threads in the tbb's internal pool, if your tasks are doing I/O operations. The optimal number of additional threads depends on how much time your tasks spend in the blocked state.

+Before TBB 3.0 U4 this method returned the number of logical CPU in the system. Currently on Windows, Linux and FreeBSD it returns the number of logical CPUs available to the current process in accordance with its affinity mask.

+NOTE: The return value of this method never changes after its first invocation. This means that changes in the process affinity mask that took place after this method was first invoked will not affect the number of worker threads in the TBB worker threads pool. +

+

+ +

+
+ + + + + + + + + + + + + + + + + + +
void __TBB_EXPORTED_METHOD tbb::task_scheduler_init::initialize (int  number_of_threads,
stack_size_type  thread_stack_size 
)
+
+
+ +

+The overloaded method with stack size parameter. +

+Overloading is necessary to preserve ABI compatibility +

+

+ +

+
+ + + + + + + + + +
void __TBB_EXPORTED_METHOD tbb::task_scheduler_init::initialize (int  number_of_threads = automatic  ) 
+
+
+ +

+Ensure that scheduler exists for this thread. +

+A value of -1 lets TBB decide on the number of threads, which is usually maximal hardware concurrency for this process, that is the number of logical CPUs on the machine (possibly limited by the processor affinity mask of this process (Windows) or of this thread (Linux, FreeBSD). It is preferable option for production code because it helps to avoid nasty surprises when several TBB based components run side-by-side or in a nested fashion inside the same process.

+The number_of_threads is ignored if any other task_scheduler_inits currently exist. A thread may construct multiple task_scheduler_inits. Doing so does no harm because the underlying scheduler is reference counted. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00343.html b/src/tbb/doc/html/a00343.html new file mode 100644 index 0000000..880528b --- /dev/null +++ b/src/tbb/doc/html/a00343.html @@ -0,0 +1,122 @@ + + +tbb::tbb_allocator< T > Class Template Reference + + + + + + + +

tbb::tbb_allocator< T > Class Template Reference
+ +[Memory Allocation] +

Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5. +More... +

+#include <tbb_allocator.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef internal::allocator_type<
+ T >::value_type 
value_type
+typedef value_type * pointer
+typedef const value_type * const_pointer
+typedef value_type & reference
+typedef const value_type & const_reference
+typedef size_t size_type
+typedef ptrdiff_t difference_type
scalable
standard
enum  malloc_type { scalable, +standard + }
 Specifies current allocator.

Public Member Functions

tbb_allocator (const tbb_allocator &) throw ()
+template<typename U>
 tbb_allocator (const tbb_allocator< U > &) throw ()
+pointer address (reference x) const
+const_pointer address (const_reference x) const
+pointer allocate (size_type n, const void *=0)
 Allocate space for n objects.
+void deallocate (pointer p, size_type)
 Free previously allocated block of memory.
+size_type max_size () const throw ()
 Largest value for which method allocate might succeed.
+template<typename... Args>
void construct (pointer p, Args &&...args)
 Copy-construct value at location pointed to by p.

Classes

struct  rebind
+


Detailed Description

+

template<typename T>
+ class tbb::tbb_allocator< T >

+ +Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5. +

+The class selects the best memory allocation mechanism available from scalable_malloc and standard malloc. The members are ordered the same way they are in section 20.4.1 of the ISO C++ standard. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00344.html b/src/tbb/doc/html/a00344.html new file mode 100644 index 0000000..e070fb6 --- /dev/null +++ b/src/tbb/doc/html/a00344.html @@ -0,0 +1,65 @@ + + +tbb::tbb_allocator< void > Class Template Reference + + + + + + + +

tbb::tbb_allocator< void > Class Template Reference
+ +[Memory Allocation] +

Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1. +More... +

+#include <tbb_allocator.h> +

+List of all members. + + + + + + + + + + + +

Public Types

+typedef void * pointer
+typedef const void * const_pointer
+typedef void value_type

Classes

struct  rebind
+


Detailed Description

+

template<>
+ class tbb::tbb_allocator< void >

+ +Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00345.html b/src/tbb/doc/html/a00345.html new file mode 100644 index 0000000..00bdd33 --- /dev/null +++ b/src/tbb/doc/html/a00345.html @@ -0,0 +1,168 @@ + + +tbb::tbb_exception Class Reference + + + + + + + +

tbb::tbb_exception Class Reference

Interface to be implemented by all exceptions TBB recognizes and propagates across the threads. +More... +

+#include <tbb_exception.h> +

+

Inheritance diagram for tbb::tbb_exception: +

+ +tbb::captured_exception +tbb::movable_exception< ExceptionData > + +List of all members. + + + + + + + + + + + + + + + + + + + +

Public Member Functions

virtual tbb_exceptionmove ()=0 throw ()
 Creates and returns pointer to the deep copy of this exception object.
virtual void destroy ()=0 throw ()
 Destroys objects created by the move() method.
virtual void throw_self ()=0
 Throws this exception object.
+virtual const char * name () const =0 throw ()
 Returns RTTI name of the originally intercepted exception.
+virtual const char * what () const =0 throw ()
 Returns the result of originally intercepted exception's what() method.
void operator delete (void *p)
+

Detailed Description

+Interface to be implemented by all exceptions TBB recognizes and propagates across the threads. +

+If an unhandled exception of the type derived from tbb::tbb_exception is intercepted by the TBB scheduler in one of the worker threads, it is delivered to and re-thrown in the root thread. The root thread is the thread that has started the outermost algorithm or root task sharing the same task_group_context with the guilty algorithm/task (the one that threw the exception first).

+Note: when documentation mentions workers with respect to exception handling, masters are implied as well, because they are completely equivalent in this context. Consequently a root thread can be master or worker thread.

+NOTE: In case of nested algorithms or complex task hierarchies when the nested levels share (explicitly or by means of implicit inheritance) the task group context of the outermost level, the exception may be (re-)thrown multiple times (ultimately - in each worker on each nesting level) before reaching the root thread at the outermost level. IMPORTANT: if you intercept an exception derived from this class on a nested level, you must re-throw it in the catch block by means of the "throw;" operator.

+TBB provides two implementations of this interface: tbb::captured_exception and template class tbb::movable_exception. See their declarations for more info. +

+


Member Function Documentation

+ +
+
+ + + + + + + + +
virtual void tbb::tbb_exception::destroy (  )  throw () [pure virtual]
+
+
+ +

+Destroys objects created by the move() method. +

+Frees memory and calls destructor for this exception object. Can and must be used only on objects created by the move method. +

+Implemented in tbb::captured_exception, and tbb::movable_exception< ExceptionData >. +

+

+ +

+
+ + + + + + + + +
virtual tbb_exception* tbb::tbb_exception::move (  )  throw () [pure virtual]
+
+
+ +

+Creates and returns pointer to the deep copy of this exception object. +

+Move semantics is allowed. +

+Implemented in tbb::captured_exception, and tbb::movable_exception< ExceptionData >. +

+

+ +

+
+ + + + + + + + + +
void tbb::tbb_exception::operator delete (void *  p  )  [inline]
+
+
+ +

+Operator delete is provided only to allow using existing smart pointers with TBB exception objects obtained as the result of applying move() operation on an exception thrown out of TBB scheduler.

+When overriding method move() make sure to override operator delete as well if memory is allocated not by TBB's scalable allocator. +

+

+ +

+
+ + + + + + + + +
virtual void tbb::tbb_exception::throw_self (  )  [pure virtual]
+
+
+ +

+Throws this exception object. +

+Make sure that if you have several levels of derivation from this interface you implement or override this method on the most derived level. The implementation is as simple as "throw *this;". Failure to do this will result in exception of a base class type being thrown. +

+Implemented in tbb::captured_exception, and tbb::movable_exception< ExceptionData >. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00345.png b/src/tbb/doc/html/a00345.png new file mode 100644 index 0000000000000000000000000000000000000000..496da7edeccbf773f1ad2e1993e03ad771d4c64a GIT binary patch literal 894 zcmV-^1A+XBP)PkftVf4Y^bZID*Io;AO!do+c-FV#{u<=V9>qCfZ|Tq6-H0E7)s3-M-S9) z^w?i_eq=r73hN%ZHV z(PN|0qoUDcqwY_%%i;@d02+1EKfcipkWn@L*W-b<0F1inE3bNuzTRl`^+uzwHyVAt zac}wuI=+$gP;s~cs5smJR2*&qDh@XQ6^9#uio*>+#o-2^;&1~{akv4fINShK9Bu$A z4mSW5hZ}&3!wo>iFEH?@DE=1B#vAx;Ve!k;Lk%=~n0TXa^e_Xv;)dnds(16neB!Zq zpl8YQe8%R5XDUQA@8D#Q!=>4bx6$uq9mPxOk5qZuGV>mLM9;)*tkJth#=W+#!}Yo( z%)ZBHPI9?4p63@L%T%CKRH)qd%tof`3Sl$CzcAu~MJ2l^i zYMe_SYknk>&1w95!CuW@skn1LulXEmzVuOe50iI_WZ>kZR>o6I&V$aJ{*^dZIezB2 zfSy84+8MGbo=^XR%8$^$G9-%MZSAj&|NXz5cZ)arMh`PkH+|U$%4KoEC)#E44^WSK U>8FX~UH||907*qoM6N<$g1#)r-2eap literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/a00346.html b/src/tbb/doc/html/a00346.html new file mode 100644 index 0000000..0834f10 --- /dev/null +++ b/src/tbb/doc/html/a00346.html @@ -0,0 +1,89 @@ + + +tbb::internal::tbb_exception_ptr Class Reference + + + + + + + +

tbb::internal::tbb_exception_ptr Class Reference

Exception container that preserves the exact copy of the original exception. +More... +

+#include <tbb_exception.h> +

+List of all members. + + + + + + + + + + + + + + + + +

Public Member Functions

void destroy () throw ()
 Destroys this objects.
+void throw_self ()
 Throws the contained exception .

Static Public Member Functions

+static tbb_exception_ptrallocate ()
+static tbb_exception_ptrallocate (const tbb_exception &tag)
+static tbb_exception_ptrallocate (captured_exception &src)
 This overload uses move semantics (i.e. it empties src).
+


Detailed Description

+Exception container that preserves the exact copy of the original exception. +

+This class can be used only when the appropriate runtime support (mandated by C++0x) is present +

+


Member Function Documentation

+ +
+
+ + + + + + + + +
void tbb::internal::tbb_exception_ptr::destroy (  )  throw ()
+
+
+ +

+Destroys this objects. +

+Note that objects of this type can be created only by the allocate() method. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00347.html b/src/tbb/doc/html/a00347.html new file mode 100644 index 0000000..ff67c30 --- /dev/null +++ b/src/tbb/doc/html/a00347.html @@ -0,0 +1,56 @@ + + +tbb::tbb_hash_compare< Key > Struct Template Reference + + + + + + + +

tbb::tbb_hash_compare< Key > Struct Template Reference

hash_compare that is default argument for concurrent_hash_map +More... +

+#include <concurrent_hash_map.h> +

+List of all members. + + + + + + +

Static Public Member Functions

+static size_t hash (const Key &a)
+static bool equal (const Key &a, const Key &b)
+


Detailed Description

+

template<typename Key>
+ struct tbb::tbb_hash_compare< Key >

+ +hash_compare that is default argument for concurrent_hash_map +

+


The documentation for this struct was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00348.html b/src/tbb/doc/html/a00348.html new file mode 100644 index 0000000..16f0a1b --- /dev/null +++ b/src/tbb/doc/html/a00348.html @@ -0,0 +1,123 @@ + + +tbb::thread_bound_filter Class Reference + + + + + + + +

tbb::thread_bound_filter Class Reference
+ +[Algorithms] +

A stage in a pipeline served by a user thread. +More... +

+#include <pipeline.h> +

+

Inheritance diagram for tbb::thread_bound_filter: +

+ +tbb::filter + +List of all members. + + + + + + + + + + + + + + + + + + + + +

Public Types

success
item_not_available
end_of_stream
enum  result_type { success, +item_not_available, +end_of_stream + }

Public Member Functions

result_type __TBB_EXPORTED_METHOD try_process_item ()
 If a data item is available, invoke operator() on that item.
result_type __TBB_EXPORTED_METHOD process_item ()
 Wait until a data item becomes available, and invoke operator() on that item.

Protected Member Functions

thread_bound_filter (mode filter_mode)
+

Detailed Description

+A stage in a pipeline served by a user thread. +

+


Member Function Documentation

+ +
+
+ + + + + + + + +
result_type __TBB_EXPORTED_METHOD tbb::thread_bound_filter::process_item (  ) 
+
+
+ +

+Wait until a data item becomes available, and invoke operator() on that item. +

+This interface is blocking. Returns 'success' if an item was processed. Returns 'end_of_stream' if there are no more items to process. Never returns 'item_not_available', as it blocks until another return condition applies. +

+

+ +

+
+ + + + + + + + +
result_type __TBB_EXPORTED_METHOD tbb::thread_bound_filter::try_process_item (  ) 
+
+
+ +

+If a data item is available, invoke operator() on that item. +

+This interface is non-blocking. Returns 'success' if an item was processed. Returns 'item_not_available' if no item can be processed now but more may arrive in the future, or if token limit is reached. Returns 'end_of_stream' if there are no more items to process. +

+

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00348.png b/src/tbb/doc/html/a00348.png new file mode 100644 index 0000000000000000000000000000000000000000..3327bd5cc26121de629295b781aa5808d1dd8acf GIT binary patch literal 426 zcmV;b0agBqP)q3eF0000OP)t-s|Ns90 z00960z@MLBkN^MxkN^Mxkifved&2+Z00001bW%=J06^y0W&i*IKuJVFRCt{2l|hcf zAPhzA&8%&104EqtFVt1;e}us{q);^#Nl=wa1_gp+UcT+1z-?0dg}*eXIq57ZrXYje zhoH;zq)?W}NE`yE7-fIt6k;AYWWy0nvR|SSIX36MsqB4px;dqmv<2EnVxC1x=^&}( zDV>h4)~;sUYIlINw>im4LYnuN8fo_-uaA;`mg|w0<$gKR6>H}tCppPUPIA)MlXy}i zph>!&w1b2;m;rkST!&{PFt*+&NZ5NTiHR5xB~E0S5wk7d>wCqDxDLGkGE;Dl79WMz9UJa~qwyncmuAHR8jCdZUr(9f@-=JVL7HWLpzFZ`#xZ zEve+GkM2dDxHZ0tuGUVRiXyEY_O;V5ND|y=vf9CCPfN}{j~Fj|f}J!#n)a9a2YhN2 UXmkT|V*mgE07*qoM6N<$f`*m33;+NC literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/a00349.html b/src/tbb/doc/html/a00349.html new file mode 100644 index 0000000..e18a148 --- /dev/null +++ b/src/tbb/doc/html/a00349.html @@ -0,0 +1,68 @@ + + +tbb::tick_count Class Reference + + + + + + + +

tbb::tick_count Class Reference
+ +[Timing] +

Absolute timestamp. +More... +

+#include <tick_count.h> +

+List of all members. + + + + + + + + + + + + + + + + + +

Public Member Functions

tick_count ()
 Construct an absolute timestamp initialized to zero.

Static Public Member Functions

+static tick_count now ()
 Return current time.

Friends

+interval_t operator- (const tick_count &t1, const tick_count &t0)
 Subtract two timestamps to get the time interval between.

Classes

class  interval_t
 Relative time interval. More...
+


Detailed Description

+Absolute timestamp. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00350.html b/src/tbb/doc/html/a00350.html new file mode 100644 index 0000000..2832a20 --- /dev/null +++ b/src/tbb/doc/html/a00350.html @@ -0,0 +1,83 @@ + + +tbb::tick_count::interval_t Class Reference + + + + + + + +

tbb::tick_count::interval_t Class Reference

Relative time interval. +More... +

+#include <tick_count.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Member Functions

interval_t ()
 Construct a time interval representing zero time duration.
interval_t (double sec)
 Construct a time interval representing sec seconds time duration.
+double seconds () const
 Return the length of a time interval in seconds.
+interval_toperator+= (const interval_t &i)
 Accumulation operator.
+interval_toperator-= (const interval_t &i)
 Subtraction operator.

Friends

+class tbb::tick_count
+interval_t operator- (const tick_count &t1, const tick_count &t0)
 Extract the intervals from the tick_counts and subtract them.
+interval_t operator+ (const interval_t &i, const interval_t &j)
 Add two intervals.
+interval_t operator- (const interval_t &i, const interval_t &j)
 Subtract two intervals.
+


Detailed Description

+Relative time interval. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00351.html b/src/tbb/doc/html/a00351.html new file mode 100644 index 0000000..88e1c1b --- /dev/null +++ b/src/tbb/doc/html/a00351.html @@ -0,0 +1,50 @@ + + +tbb::user_abort Class Reference + + + + + + + +

tbb::user_abort Class Reference

Exception for user-initiated abort. +More... +

+#include <tbb_exception.h> +

+List of all members. + + + + +

Public Member Functions

+const char * what () const throw ()
+


Detailed Description

+Exception for user-initiated abort. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00352.html b/src/tbb/doc/html/a00352.html new file mode 100644 index 0000000..8b990af --- /dev/null +++ b/src/tbb/doc/html/a00352.html @@ -0,0 +1,55 @@ + + +tbb::internal::work_around_alignment_bug< Size, T > Struct Template Reference + + + + + + + +

tbb::internal::work_around_alignment_bug< Size, T > Struct Template Reference

Work around for bug in GNU 3.2 and MSVC compilers. +More... +

+#include <tbb_machine.h> +

+List of all members. + + + + +

Static Public Attributes

+static const size_t alignment = __TBB_alignof(T)
+


Detailed Description

+

template<size_t Size, typename T>
+ struct tbb::internal::work_around_alignment_bug< Size, T >

+ +Work around for bug in GNU 3.2 and MSVC compilers. +

+Bug is that compiler sometimes returns 0 for __alignof(T) when T has not yet been instantiated. The work-around forces instantiation by forcing computation of sizeof(T) before __alignof(T). +

+


The documentation for this struct was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00353.html b/src/tbb/doc/html/a00353.html new file mode 100644 index 0000000..4374787 --- /dev/null +++ b/src/tbb/doc/html/a00353.html @@ -0,0 +1,93 @@ + + +tbb::zero_allocator< T, Allocator > Class Template Reference + + + + + + + +

tbb::zero_allocator< T, Allocator > Class Template Reference
+ +[Memory Allocation] +

Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5. +More... +

+#include <tbb_allocator.h> +

+List of all members. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Types

+typedef Allocator< T > base_allocator_type
+typedef base_allocator_type::value_type value_type
+typedef base_allocator_type::pointer pointer
+typedef base_allocator_type::const_pointer const_pointer
+typedef base_allocator_type::reference reference
+typedef base_allocator_type::const_reference const_reference
+typedef base_allocator_type::size_type size_type
+typedef base_allocator_type::difference_type difference_type

Public Member Functions

zero_allocator (const zero_allocator &a) throw ()
+template<typename U>
 zero_allocator (const zero_allocator< U > &a) throw ()
+pointer allocate (const size_type n, const void *hint=0)

Classes

struct  rebind
+


Detailed Description

+

template<typename T, template< typename X > class Allocator = tbb_allocator>
+ class tbb::zero_allocator< T, Allocator >

+ +Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5. +

+The class is an adapter over an actual allocator that fills the allocation using memset function with template argument C as the value. The members are ordered the same way they are in section 20.4.1 of the ISO C++ standard. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00354.html b/src/tbb/doc/html/a00354.html new file mode 100644 index 0000000..787fc5f --- /dev/null +++ b/src/tbb/doc/html/a00354.html @@ -0,0 +1,68 @@ + + +tbb::zero_allocator< void, Allocator > Class Template Reference + + + + + + + +

tbb::zero_allocator< void, Allocator > Class Template Reference
+ +[Memory Allocation] +

Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1. +More... +

+#include <tbb_allocator.h> +

+List of all members. + + + + + + + + + + + + + +

Public Types

+typedef Allocator< void > base_allocator_type
+typedef base_allocator_type::value_type value_type
+typedef base_allocator_type::pointer pointer
+typedef base_allocator_type::const_pointer const_pointer

Classes

struct  rebind
+


Detailed Description

+

template<template< typename T > class Allocator>
+ class tbb::zero_allocator< void, Allocator >

+ +Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1. +

+


The documentation for this class was generated from the following file: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00372.html b/src/tbb/doc/html/a00372.html new file mode 100644 index 0000000..d818ad2 --- /dev/null +++ b/src/tbb/doc/html/a00372.html @@ -0,0 +1,152 @@ + + +flow_graph.h File Reference + + + + + + +

flow_graph.h File Reference

The graph related classes and functions. More... +

+ +

+Go to the source code of this file. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Namespaces

namespace  tbb
namespace  tbb::flow
namespace  tbb::flow::interface6
namespace  internal::graph_policy_namespace
namespace  interface6::internal::graph_policy_namespace

Classes

class  tbb::flow::interface6::continue_msg
 An empty class used for messages that mean "I'm done". More...
class  tbb::flow::interface6::sender< T >
 Pure virtual template class that defines a sender of messages of type T. More...
class  tbb::flow::interface6::receiver< T >
 Pure virtual template class that defines a receiver of messages of type T. More...
class  tbb::flow::interface6::continue_receiver
 Base class for receivers of completion messages. More...
class  tbb::flow::interface6::graph_iterator< GraphContainerType, GraphNodeType >
class  tbb::flow::interface6::graph
 The graph class. More...
class  tbb::flow::interface6::graph::run_task< Body >
class  tbb::flow::interface6::graph::run_and_put_task< Receiver, Body >
class  tbb::flow::interface6::graph_node
 The base of all graph nodes. More...
class  tbb::flow::interface6::source_node< Output >
 An executable node that acts as a source, i.e. it has no predecessors. More...
class  tbb::flow::interface6::function_node< Input, Output,, Allocator >
 Implements a function node that supports Input -> Output. More...
class  tbb::flow::interface6::function_node< Input, Output, queueing, Allocator >
 Implements a function node that supports Input -> Output. More...
class  tbb::flow::interface6::multifunction_node< Input, Output,, Allocator >
 implements a function node that supports Input -> (set of outputs) More...
class  tbb::flow::interface6::multifunction_node< Input, Output, queueing, Allocator >
class  tbb::flow::interface6::split_node< TupleType, Allocator >
 split_node: accepts a tuple as input, forwards each element of the tuple to its More...
struct  tbb::flow::interface6::split_node< TupleType, Allocator >::splitting_body
class  tbb::flow::interface6::continue_node< Output >
 Implements an executable node that supports continue_msg -> Output. More...
class  tbb::flow::interface6::overwrite_node< T >
class  tbb::flow::interface6::write_once_node< T >
class  tbb::flow::interface6::broadcast_node< T >
 Forwards messages of type T to all successors. More...
class  tbb::flow::interface6::buffer_node< T, A >
 Forwards messages in arbitrary order. More...
class  tbb::flow::interface6::buffer_node< T, A >::buffer_operation
class  tbb::flow::interface6::queue_node< T, A >
 Forwards messages in FIFO order. More...
class  tbb::flow::interface6::sequencer_node< T, A >
 Forwards messages in sequence order. More...
class  tbb::flow::interface6::priority_queue_node< T, Compare, A >
 Forwards messages in priority order. More...
class  tbb::flow::interface6::limiter_node< T >
 Forwards messages only if the threshold has not been reached. More...
class  tbb::flow::interface6::join_node< OutputTuple, reserving >
class  tbb::flow::interface6::join_node< OutputTuple, queueing >
class  tbb::flow::interface6::join_node< OutputTuple, tag_matching >
class  tbb::flow::interface6::or_node< InputTuple >

Enumerations

enum  concurrency { unlimited = 0, +serial = 1 + }
 An enumeration the provides the two most common concurrency levels: unlimited and serial.

Functions

+template<typename T>
void tbb::flow::interface6::make_edge (sender< T > &p, receiver< T > &s)
 Makes an edge between a single predecessor and a single successor.
+template<typename T>
void tbb::flow::interface6::remove_edge (sender< T > &p, receiver< T > &s)
 Makes an edge between a single predecessor and a single successor.
+template<typename Body, typename Node>
Body tbb::flow::interface6::copy_body (Node &n)
 Returns a copy of the body from a function or continue node.
+


Detailed Description

+The graph related classes and functions. +

+There are some applications that best express dependencies as messages passed between nodes in a graph. These messages may contain data or simply act as signals that a predecessors has completed. The graph class and its associated node classes can be used to express such applcations.


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00373.html b/src/tbb/doc/html/a00373.html new file mode 100644 index 0000000..66fd77b --- /dev/null +++ b/src/tbb/doc/html/a00373.html @@ -0,0 +1,66 @@ + + +memory_pool.h File Reference + + + + + + +

memory_pool.h File Reference

+

+Go to the source code of this file. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Namespaces

namespace  tbb
namespace  tbb::interface6

Classes

class  tbb::interface6::memory_pool_allocator< T, P >
 Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5. More...
struct  tbb::interface6::memory_pool_allocator< T, P >::rebind< U >
class  tbb::interface6::memory_pool_allocator< void, P >
 Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1. More...
struct  tbb::interface6::memory_pool_allocator< void, P >::rebind< U >
class  tbb::interface6::memory_pool< Alloc >
 Thread-safe growable pool allocator for variable-size requests. More...
class  tbb::interface6::fixed_pool

Functions

+template<typename T, typename U, typename P>
bool tbb::interface6::operator== (const memory_pool_allocator< T, P > &a, const memory_pool_allocator< U, P > &b)
+template<typename T, typename U, typename P>
bool tbb::interface6::operator!= (const memory_pool_allocator< T, P > &a, const memory_pool_allocator< U, P > &b)
+


Detailed Description

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00392.html b/src/tbb/doc/html/a00392.html new file mode 100644 index 0000000..caf2a9b --- /dev/null +++ b/src/tbb/doc/html/a00392.html @@ -0,0 +1,119 @@ + + +scalable_allocator.h File Reference + + + + + + +

scalable_allocator.h File Reference

+

+Go to the source code of this file. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Namespaces

namespace  rml
namespace  tbb

Classes

struct  rml::MemPoolPolicy
class  tbb::scalable_allocator< T >
 Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5. More...
struct  tbb::scalable_allocator< T >::rebind< U >
class  tbb::scalable_allocator< void >
 Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1. More...
struct  tbb::scalable_allocator< void >::rebind< U >

Typedefs

+typedef void *(*) rml::rawAllocType (intptr_t pool_id, size_t &bytes)
+typedef int(*) rml::rawFreeType (intptr_t pool_id, void *raw_ptr, size_t raw_bytes)

Enumerations

enum  MemPoolError { POOL_OK, +INVALID_POLICY, +UNSUPPORTED_POLICY, +NO_MEMORY + }

Functions

void *__TBB_EXPORTED_FUNC scalable_malloc (size_t size)
void __TBB_EXPORTED_FUNC scalable_free (void *ptr)
void *__TBB_EXPORTED_FUNC scalable_realloc (void *ptr, size_t size)
void *__TBB_EXPORTED_FUNC scalable_calloc (size_t nobj, size_t size)
int __TBB_EXPORTED_FUNC scalable_posix_memalign (void **memptr, size_t alignment, size_t size)
void *__TBB_EXPORTED_FUNC scalable_aligned_malloc (size_t size, size_t alignment)
void *__TBB_EXPORTED_FUNC scalable_aligned_realloc (void *ptr, size_t size, size_t alignment)
void __TBB_EXPORTED_FUNC scalable_aligned_free (void *ptr)
size_t __TBB_EXPORTED_FUNC scalable_msize (void *ptr)
+MemPoolError rml::pool_create_v1 (intptr_t pool_id, const MemPoolPolicy *policy, rml::MemoryPool **pool)
+bool rml::pool_destroy (MemoryPool *memPool)
+void * rml::pool_malloc (MemoryPool *memPool, size_t size)
+void * rml::pool_realloc (MemoryPool *memPool, void *object, size_t size)
+void * rml::pool_aligned_malloc (MemoryPool *mPool, size_t size, size_t alignment)
+void * rml::pool_aligned_realloc (MemoryPool *mPool, void *ptr, size_t size, size_t alignment)
+bool rml::pool_reset (MemoryPool *memPool)
+bool rml::pool_free (MemoryPool *memPool, void *object)
+template<typename T, typename U>
bool tbb::operator== (const scalable_allocator< T > &, const scalable_allocator< U > &)
+template<typename T, typename U>
bool tbb::operator!= (const scalable_allocator< T > &, const scalable_allocator< U > &)
+


Detailed Description

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00411.html b/src/tbb/doc/html/a00411.html new file mode 100644 index 0000000..4d62363 --- /dev/null +++ b/src/tbb/doc/html/a00411.html @@ -0,0 +1,83 @@ + + +rml Namespace Reference + + + + + + +

rml Namespace Reference

Assert that x is true. +More... +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Classes

struct  MemPoolPolicy

Typedefs

+typedef void *(*) rawAllocType (intptr_t pool_id, size_t &bytes)
+typedef int(*) rawFreeType (intptr_t pool_id, void *raw_ptr, size_t raw_bytes)

Enumerations

enum  MemPoolError { POOL_OK, +INVALID_POLICY, +UNSUPPORTED_POLICY, +NO_MEMORY + }

Functions

+MemPoolError pool_create_v1 (intptr_t pool_id, const MemPoolPolicy *policy, rml::MemoryPool **pool)
+bool pool_destroy (MemoryPool *memPool)
+void * pool_malloc (MemoryPool *memPool, size_t size)
+void * pool_realloc (MemoryPool *memPool, void *object, size_t size)
+void * pool_aligned_malloc (MemoryPool *mPool, size_t size, size_t alignment)
+void * pool_aligned_realloc (MemoryPool *mPool, void *ptr, size_t size, size_t alignment)
+bool pool_reset (MemoryPool *memPool)
+bool pool_free (MemoryPool *memPool, void *object)
+


Detailed Description

+Assert that x is true. +

+If x is false, print assertion failure message. If the comment argument is not NULL, it is printed as part of the failure message. The comment argument has no other effect. +

+


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00414.html b/src/tbb/doc/html/a00414.html new file mode 100644 index 0000000..16b5c0d --- /dev/null +++ b/src/tbb/doc/html/a00414.html @@ -0,0 +1,667 @@ + + +tbb Namespace Reference + + + + + + +

tbb Namespace Reference

The namespace tbb contains all components of the library. +More... +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Classes

class  aligned_space
 Block of space aligned sufficiently to construct an array T with N elements. More...
struct  atomic
 Primary template for atomic. More...
struct  atomic< void * >
 Specialization for atomic<void*>, for sake of not allowing arithmetic or operator->. More...
class  blocked_range
 A range over which to iterate. More...
class  blocked_range2d
 A 2-dimensional range that models the Range concept. More...
class  blocked_range3d
 A 3-dimensional range that models the Range concept. More...
class  cache_aligned_allocator
 Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5. More...
class  cache_aligned_allocator< void >
 Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1. More...
class  combinable
 Thread-local storage with optional reduction. More...
struct  tbb_hash_compare
 hash_compare that is default argument for concurrent_hash_map More...
class  concurrent_bounded_queue
 A high-performance thread-safe blocking concurrent bounded queue. More...
class  concurrent_vector
 Concurrent vector container. More...
class  mutex
 Wrapper around the platform's native reader-writer lock. More...
class  null_mutex
 A mutex which does nothing. More...
class  null_rw_mutex
 A rw mutex which does nothing. More...
class  parallel_do_feeder
 Class the user supplied algorithm body uses to add new tasks. More...
struct  task_group_context
struct  pre_scan_tag
 Used to indicate that the initial scan is being performed. More...
struct  final_scan_tag
 Used to indicate that the final scan is being performed. More...
class  parallel_while
 Parallel iteration over a stream, with optional addition of more work. More...
class  simple_partitioner
 A simple partitioner. More...
class  auto_partitioner
 An auto partitioner. More...
class  affinity_partitioner
 An affinity partitioner. More...
class  filter
 A stage in a pipeline. More...
class  thread_bound_filter
 A stage in a pipeline served by a user thread. More...
class  pipeline
 A processing pipeline that applies filters to items. More...
class  queuing_mutex
 Queuing mutex with local-only spinning. More...
class  queuing_rw_mutex
 Queuing reader-writer mutex with local-only spinning. More...
class  recursive_mutex
 Mutex that allows recursive mutex acquisition. More...
class  scalable_allocator
 Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5. More...
class  scalable_allocator< void >
 Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1. More...
class  spin_mutex
 A lock that occupies a single byte. More...
class  spin_rw_mutex_v3
 Fast, unfair, spinning reader-writer lock with backoff and writer-preference. More...
class  task
 Base class for user-defined tasks. More...
class  empty_task
 task that does nothing. Useful for synchronization. More...
class  task_list
 A list of children. More...
class  task_handle
class  task_group
class  structured_task_group
class  task_scheduler_init
 Class delimiting the scope of task scheduler activity. More...
class  tbb_allocator
 Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5. More...
class  tbb_allocator< void >
 Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1. More...
class  zero_allocator
 Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5. More...
class  zero_allocator< void, Allocator >
 Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1. More...
class  bad_last_alloc
 Exception for concurrent containers. More...
class  improper_lock
 Exception for PPL locks. More...
class  user_abort
 Exception for user-initiated abort. More...
class  missing_wait
 Exception for missing wait on structured_task_group. More...
class  invalid_multiple_scheduling
 Exception for repeated scheduling of the same task_handle. More...
class  tbb_exception
 Interface to be implemented by all exceptions TBB recognizes and propagates across the threads. More...
class  captured_exception
 This class is used by TBB to propagate information about unhandled exceptions into the root thread. More...
class  movable_exception
 Template that can be used to implement exception that transfers arbitrary ExceptionData to the root thread. More...
class  split
 Dummy type that distinguishes splitting constructor from copy constructor. More...
class  tick_count
 Absolute timestamp. More...

parallel_do

See also requirements on parallel_do Body.

+template<typename Iterator, typename Body>
void parallel_do (Iterator first, Iterator last, const Body &body)
 Parallel iteration over a range, with optional addition of more work.
+template<typename Iterator, typename Body>
void parallel_do (Iterator first, Iterator last, const Body &body, task_group_context &context)
 Parallel iteration over a range, with optional addition of more work and user-supplied context.

parallel_for

See also requirements on Range and parallel_for Body.

+template<typename Range, typename Body>
void parallel_for (const Range &range, const Body &body)
 Parallel iteration over range with default partitioner.
+template<typename Range, typename Body>
void parallel_for (const Range &range, const Body &body, const simple_partitioner &partitioner)
 Parallel iteration over range with simple partitioner.
+template<typename Range, typename Body>
void parallel_for (const Range &range, const Body &body, const auto_partitioner &partitioner)
 Parallel iteration over range with auto_partitioner.
+template<typename Range, typename Body>
void parallel_for (const Range &range, const Body &body, affinity_partitioner &partitioner)
 Parallel iteration over range with affinity_partitioner.
+template<typename Range, typename Body>
void parallel_for (const Range &range, const Body &body, const simple_partitioner &partitioner, task_group_context &context)
 Parallel iteration over range with simple partitioner and user-supplied context.
+template<typename Range, typename Body>
void parallel_for (const Range &range, const Body &body, const auto_partitioner &partitioner, task_group_context &context)
 Parallel iteration over range with auto_partitioner and user-supplied context.
+template<typename Range, typename Body>
void parallel_for (const Range &range, const Body &body, affinity_partitioner &partitioner, task_group_context &context)
 Parallel iteration over range with affinity_partitioner and user-supplied context.

parallel_for_each

+template<typename InputIterator, typename Function>
void parallel_for_each (InputIterator first, InputIterator last, const Function &f, task_group_context &context)
 Calls function f for all items from [first, last) interval using user-supplied context.
+template<typename InputIterator, typename Function>
void parallel_for_each (InputIterator first, InputIterator last, const Function &f)
 Uses default context.

parallel_invoke

+template<typename F0, typename F1>
void parallel_invoke (const F0 &f0, const F1 &f1, tbb::task_group_context &context)
 Executes a list of tasks in parallel and waits for all tasks to complete.
+template<typename F0, typename F1, typename F2>
void parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, tbb::task_group_context &context)
+template<typename F0, typename F1, typename F2, typename F3>
void parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, tbb::task_group_context &context)
+template<typename F0, typename F1, typename F2, typename F3, typename F4>
void parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, tbb::task_group_context &context)
+template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5>
void parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, const F5 &f5, tbb::task_group_context &context)
+template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6>
void parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, const F5 &f5, const F6 &f6, tbb::task_group_context &context)
+template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6, typename F7>
void parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, const F5 &f5, const F6 &f6, const F7 &f7, tbb::task_group_context &context)
+template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6, typename F7, typename F8>
void parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, const F5 &f5, const F6 &f6, const F7 &f7, const F8 &f8, tbb::task_group_context &context)
+template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6, typename F7, typename F8, typename F9>
void parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, const F5 &f5, const F6 &f6, const F7 &f7, const F8 &f8, const F9 &f9, tbb::task_group_context &context)
+template<typename F0, typename F1>
void parallel_invoke (const F0 &f0, const F1 &f1)
+template<typename F0, typename F1, typename F2>
void parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2)
+template<typename F0, typename F1, typename F2, typename F3>
void parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3)
+template<typename F0, typename F1, typename F2, typename F3, typename F4>
void parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4)
+template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5>
void parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, const F5 &f5)
+template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6>
void parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, const F5 &f5, const F6 &f6)
+template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6, typename F7>
void parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, const F5 &f5, const F6 &f6, const F7 &f7)
+template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6, typename F7, typename F8>
void parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, const F5 &f5, const F6 &f6, const F7 &f7, const F8 &f8)
+template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6, typename F7, typename F8, typename F9>
void parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, const F5 &f5, const F6 &f6, const F7 &f7, const F8 &f8, const F9 &f9)

parallel_reduce

See also requirements on Range and parallel_reduce Body.

+template<typename Range, typename Body>
void parallel_reduce (const Range &range, Body &body)
 Parallel iteration with reduction and default partitioner.
+template<typename Range, typename Body>
void parallel_reduce (const Range &range, Body &body, const simple_partitioner &partitioner)
 Parallel iteration with reduction and simple_partitioner.
+template<typename Range, typename Body>
void parallel_reduce (const Range &range, Body &body, const auto_partitioner &partitioner)
 Parallel iteration with reduction and auto_partitioner.
+template<typename Range, typename Body>
void parallel_reduce (const Range &range, Body &body, affinity_partitioner &partitioner)
 Parallel iteration with reduction and affinity_partitioner.
+template<typename Range, typename Body>
void parallel_reduce (const Range &range, Body &body, const simple_partitioner &partitioner, task_group_context &context)
 Parallel iteration with reduction, simple partitioner and user-supplied context.
+template<typename Range, typename Body>
void parallel_reduce (const Range &range, Body &body, const auto_partitioner &partitioner, task_group_context &context)
 Parallel iteration with reduction, auto_partitioner and user-supplied context.
+template<typename Range, typename Body>
void parallel_reduce (const Range &range, Body &body, affinity_partitioner &partitioner, task_group_context &context)
 Parallel iteration with reduction, affinity_partitioner and user-supplied context.
+template<typename Range, typename Value, typename RealBody, typename Reduction>
Value parallel_reduce (const Range &range, const Value &identity, const RealBody &real_body, const Reduction &reduction)
 Parallel iteration with reduction and default partitioner.
+template<typename Range, typename Value, typename RealBody, typename Reduction>
Value parallel_reduce (const Range &range, const Value &identity, const RealBody &real_body, const Reduction &reduction, const simple_partitioner &partitioner)
 Parallel iteration with reduction and simple_partitioner.
+template<typename Range, typename Value, typename RealBody, typename Reduction>
Value parallel_reduce (const Range &range, const Value &identity, const RealBody &real_body, const Reduction &reduction, const auto_partitioner &partitioner)
 Parallel iteration with reduction and auto_partitioner.
+template<typename Range, typename Value, typename RealBody, typename Reduction>
Value parallel_reduce (const Range &range, const Value &identity, const RealBody &real_body, const Reduction &reduction, affinity_partitioner &partitioner)
 Parallel iteration with reduction and affinity_partitioner.
+template<typename Range, typename Value, typename RealBody, typename Reduction>
Value parallel_reduce (const Range &range, const Value &identity, const RealBody &real_body, const Reduction &reduction, const simple_partitioner &partitioner, task_group_context &context)
 Parallel iteration with reduction, simple partitioner and user-supplied context.
+template<typename Range, typename Value, typename RealBody, typename Reduction>
Value parallel_reduce (const Range &range, const Value &identity, const RealBody &real_body, const Reduction &reduction, const auto_partitioner &partitioner, task_group_context &context)
 Parallel iteration with reduction, auto_partitioner and user-supplied context.
+template<typename Range, typename Value, typename RealBody, typename Reduction>
Value parallel_reduce (const Range &range, const Value &identity, const RealBody &real_body, const Reduction &reduction, affinity_partitioner &partitioner, task_group_context &context)
 Parallel iteration with reduction, affinity_partitioner and user-supplied context.
+template<typename Range, typename Body>
void parallel_deterministic_reduce (const Range &range, Body &body)
 Parallel iteration with deterministic reduction and default partitioner.
+template<typename Range, typename Body>
void parallel_deterministic_reduce (const Range &range, Body &body, task_group_context &context)
 Parallel iteration with deterministic reduction, simple partitioner and user-supplied context.
+template<typename Range, typename Value, typename RealBody, typename Reduction>
Value parallel_deterministic_reduce (const Range &range, const Value &identity, const RealBody &real_body, const Reduction &reduction)
 Parallel iteration with deterministic reduction and default partitioner.
+template<typename Range, typename Value, typename RealBody, typename Reduction>
Value parallel_deterministic_reduce (const Range &range, const Value &identity, const RealBody &real_body, const Reduction &reduction, task_group_context &context)
 Parallel iteration with deterministic reduction, simple partitioner and user-supplied context.

parallel_scan

See also requirements on Range and parallel_scan Body.

+template<typename Range, typename Body>
void parallel_scan (const Range &range, Body &body)
 Parallel prefix with default partitioner.
+template<typename Range, typename Body>
void parallel_scan (const Range &range, Body &body, const simple_partitioner &partitioner)
 Parallel prefix with simple_partitioner.
+template<typename Range, typename Body>
void parallel_scan (const Range &range, Body &body, const auto_partitioner &partitioner)
 Parallel prefix with auto_partitioner.

parallel_sort

See also requirements on iterators for parallel_sort.

template<typename RandomAccessIterator, typename Compare>
void parallel_sort (RandomAccessIterator begin, RandomAccessIterator end, const Compare &comp)
 Sorts the data in [begin,end) using the given comparator.
+template<typename RandomAccessIterator>
void parallel_sort (RandomAccessIterator begin, RandomAccessIterator end)
 Sorts the data in [begin,end) with a default comparator std::less<RandomAccessIterator>.
+template<typename T>
void parallel_sort (T *begin, T *end)
 Sorts the data in the range [begin,end) with a default comparator std::less<T>.

Typedefs

+typedef internal::critical_section_v4 critical_section
+typedef spin_rw_mutex_v3 spin_rw_mutex
+typedef std::size_t stack_size_type
+typedef internal::task_scheduler_observer_v3 task_scheduler_observer

Enumerations

enum  memory_semantics { full_fence, +acquire, +release, +relaxed + }
 Specifies memory semantics. More...
enum  ets_key_usage_type { ets_key_per_instance, +ets_no_key + }
 enum for selecting between single key and key-per-instance versions
enum  priority_t { priority_normal = internal::priority_stride_v4 * 2, +priority_low = priority_normal - internal::priority_stride_v4, +priority_high = priority_normal + internal::priority_stride_v4 + }
enum  task_group_status { not_complete, +complete, +canceled + }

Functions

__TBB_DECL_ATOMIC (__TBB_LONG_LONG) __TBB_DECL_ATOMIC(unsigned __TBB_LONG_LONG) __TBB_DECL_ATOMIC(long) __TBB_DECL_ATOMIC(unsigned long) __TBB_DECL_ATOMIC_ALT(unsigned
+size_t __TBB_DECL_ATOMIC_ALT (int, ptrdiff_t) __TBB_DECL_ATOMIC(unsigned) __TBB_DECL_ATOMIC(int) __TBB_DECL_ATOMIC(unsigned short) __TBB_DECL_ATOMIC(short) __TBB_DECL_ATOMIC(char) __TBB_DECL_ATOMIC(signed char) __TBB_DECL_ATOMIC(unsigned char) __TBB_DECL_ATOMIC(wchar_t) template< typename T > struct atomic< T * >
 Specialization for atomic<T*> with arithmetic and operator->.
+template<memory_semantics M, typename T>
load (const atomic< T > &a)
+template<memory_semantics M, typename T>
void store (atomic< T > &a, T value)
+template<typename T, typename U>
bool operator== (const cache_aligned_allocator< T > &, const cache_aligned_allocator< U > &)
+template<typename T, typename U>
bool operator!= (const cache_aligned_allocator< T > &, const cache_aligned_allocator< U > &)
+template<typename Key, typename T, typename HashCompare, typename A1, typename A2>
bool operator== (const concurrent_hash_map< Key, T, HashCompare, A1 > &a, const concurrent_hash_map< Key, T, HashCompare, A2 > &b)
+template<typename Key, typename T, typename HashCompare, typename A1, typename A2>
bool operator!= (const concurrent_hash_map< Key, T, HashCompare, A1 > &a, const concurrent_hash_map< Key, T, HashCompare, A2 > &b)
+template<typename Key, typename T, typename HashCompare, typename A>
void swap (concurrent_hash_map< Key, T, HashCompare, A > &a, concurrent_hash_map< Key, T, HashCompare, A > &b)
+template<typename T, class A1, class A2>
bool operator== (const concurrent_vector< T, A1 > &a, const concurrent_vector< T, A2 > &b)
+template<typename T, class A1, class A2>
bool operator!= (const concurrent_vector< T, A1 > &a, const concurrent_vector< T, A2 > &b)
+template<typename T, class A1, class A2>
bool operator< (const concurrent_vector< T, A1 > &a, const concurrent_vector< T, A2 > &b)
+template<typename T, class A1, class A2>
bool operator> (const concurrent_vector< T, A1 > &a, const concurrent_vector< T, A2 > &b)
+template<typename T, class A1, class A2>
bool operator<= (const concurrent_vector< T, A1 > &a, const concurrent_vector< T, A2 > &b)
+template<typename T, class A1, class A2>
bool operator>= (const concurrent_vector< T, A1 > &a, const concurrent_vector< T, A2 > &b)
+template<typename T, class A>
void swap (concurrent_vector< T, A > &a, concurrent_vector< T, A > &b)
+template<typename T, typename U>
bool operator== (const scalable_allocator< T > &, const scalable_allocator< U > &)
+template<typename T, typename U>
bool operator!= (const scalable_allocator< T > &, const scalable_allocator< U > &)
+bool is_current_task_group_canceling ()
+template<class F>
task_handle< F > make_task (const F &f)
+template<typename T, typename U>
bool operator== (const tbb_allocator< T > &, const tbb_allocator< U > &)
+template<typename T, typename U>
bool operator!= (const tbb_allocator< T > &, const tbb_allocator< U > &)
+template<typename T1, template< typename X1 > class B1, typename T2, template< typename X2 > class B2>
bool operator== (const zero_allocator< T1, B1 > &a, const zero_allocator< T2, B2 > &b)
+template<typename T1, template< typename X1 > class B1, typename T2, template< typename X2 > class B2>
bool operator!= (const zero_allocator< T1, B1 > &a, const zero_allocator< T2, B2 > &b)
+void atomic_fence ()
 Sequentially consistent full memory fence.
int __TBB_EXPORTED_FUNC TBB_runtime_interface_version ()
 The function returns the interface version of the TBB shared library being used.
+tick_count::interval_t operator- (const tick_count &t1, const tick_count &t0)
+


Detailed Description

+The namespace tbb contains all components of the library. +

+This header provides basic platform abstraction layer by hooking up appropriate architecture/OS/compiler specific headers from the /include/tbb/machine directory. If a plug-in header does not implement all the required APIs, it must specify the missing ones by setting one or more of the following macros:

+__TBB_USE_GENERIC_PART_WORD_CAS __TBB_USE_GENERIC_PART_WORD_FETCH_ADD __TBB_USE_GENERIC_PART_WORD_FETCH_STORE __TBB_USE_GENERIC_FETCH_ADD __TBB_USE_GENERIC_FETCH_STORE __TBB_USE_GENERIC_DWORD_FETCH_ADD __TBB_USE_GENERIC_DWORD_FETCH_STORE __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE __TBB_USE_GENERIC_FULL_FENCED_LOAD_STORE __TBB_USE_GENERIC_RELAXED_LOAD_STORE __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE

+In this case tbb_machine.h will add missing functionality based on a minimal set of APIs that are required to be implemented by all plug-n headers as described further. Note that these generic implementations may be sub-optimal for a particular architecture, and thus should be relied upon only after careful evaluation or as the last resort.

+Additionally __TBB_64BIT_ATOMICS can be set to 0 on a 32-bit architecture to indicate that the port is not going to support double word atomics. It may also be set to 1 explicitly, though normally this is not necessary as tbb_machine.h will set it automatically.

+__TBB_BIG_ENDIAN macro can be defined by the implementation as well. It is used only if the __TBB_USE_GENERIC_PART_WORD_CAS is set. Possible values are:

    +
  • 1 if the system is big endian,
  • 0 if it is little endian,
  • or -1 to explicitly state that __TBB_USE_GENERIC_PART_WORD_CAS can not be used. -1 should be used when it is known in advance that endianness can change in run time or it is not simple big or little but something more complex. The system will try to detect it in run time if it is not set(in assumption that it is either a big or little one).
+

+Prerequisites for each architecture port ---------------------------------------- The following functions and macros have no generic implementation. Therefore they must be implemented in each machine architecture specific header either as a conventional function or as a functional macro.

+__TBB_WORDSIZE This is the size of machine word in bytes, i.e. for 32 bit systems it should be defined to 4.

+__TBB_Yield() Signals OS that the current thread is willing to relinquish the remainder of its time quantum.

+__TBB_full_memory_fence() Must prevent all memory operations from being reordered across it (both by hardware and compiler). All such fences must be totally ordered (or sequentially consistent).

+__TBB_machine_cmpswp4( volatile void *ptr, int32_t value, int32_t comparand ) Must be provided if __TBB_USE_FENCED_ATOMICS is not set.

+__TBB_machine_cmpswp8( volatile void *ptr, int32_t value, int64_t comparand ) Must be provided for 64-bit architectures if __TBB_USE_FENCED_ATOMICS is not set, and for 32-bit architectures if __TBB_64BIT_ATOMICS is set

+__TBB_machine_<op><S><fence>(...), where <op> = {cmpswp, fetchadd, fetchstore} <S> = {1, 2, 4, 8} <fence> = {full_fence, acquire, release, relaxed} Must be provided if __TBB_USE_FENCED_ATOMICS is set.

+__TBB_control_consistency_helper() Bridges the memory-semantics gap between architectures providing only implicit C++0x "consume" semantics (like Power Architecture) and those also implicitly obeying control dependencies (like IA-64). It must be used only in conditional code where the condition is itself data-dependent, and will then make subsequent code behave as if the original data dependency were acquired. It needs only a compiler fence where implied by the architecture either specifically (like IA-64) or because generally stronger "acquire" semantics are enforced (like x86). It is always valid, though potentially suboptimal, to replace control with acquire on the load and then remove the helper.

+__TBB_acquire_consistency_helper(), __TBB_release_consistency_helper() Must be provided if __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE is set. Enforce acquire and release semantics in generic implementations of fenced store and load operations. Depending on the particular architecture/compiler combination they may be a hardware fence, a compiler fence, both or nothing. +

+


Enumeration Type Documentation

+ +
+
+ + + + +
enum tbb::memory_semantics
+
+
+ +

+Specifies memory semantics. +

+

Enumerator:
+ + + + + +
full_fence  +Sequential consistency.
acquire  +Acquire.
release  +Release.
relaxed  +No ordering.
+
+ +
+

+


Function Documentation

+ +
+
+ + + + + + + + +
int __TBB_EXPORTED_FUNC tbb::TBB_runtime_interface_version (  ) 
+
+
+ +

+The function returns the interface version of the TBB shared library being used. +

+The version it returns is determined at runtime, not at compile/link time. So it can be different than the value of TBB_INTERFACE_VERSION obtained at compile time. +

+

+


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00426.html b/src/tbb/doc/html/a00426.html new file mode 100644 index 0000000..cd9895b --- /dev/null +++ b/src/tbb/doc/html/a00426.html @@ -0,0 +1,364 @@ + + +Algorithms + + + + + +

Algorithms

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Classes

class  tbb::blocked_range< Value >
 A range over which to iterate. More...
class  tbb::blocked_range2d< RowValue, ColValue >
 A 2-dimensional range that models the Range concept. More...
class  tbb::blocked_range3d< PageValue, RowValue, ColValue >
 A 3-dimensional range that models the Range concept. More...
struct  tbb::pre_scan_tag
 Used to indicate that the initial scan is being performed. More...
struct  tbb::final_scan_tag
 Used to indicate that the final scan is being performed. More...
class  tbb::parallel_while< Body >
 Parallel iteration over a stream, with optional addition of more work. More...
class  tbb::simple_partitioner
 A simple partitioner. More...
class  tbb::auto_partitioner
 An auto partitioner. More...
class  tbb::filter
 A stage in a pipeline. More...
class  tbb::thread_bound_filter
 A stage in a pipeline served by a user thread. More...
class  tbb::pipeline
 A processing pipeline that applies filters to items. More...
class  tbb::split
 Dummy type that distinguishes splitting constructor from copy constructor. More...

parallel_do

See also requirements on parallel_do Body.

+template<typename Iterator, typename Body>
void tbb::parallel_do (Iterator first, Iterator last, const Body &body)
 Parallel iteration over a range, with optional addition of more work.
+template<typename Iterator, typename Body>
void tbb::parallel_do (Iterator first, Iterator last, const Body &body, task_group_context &context)
 Parallel iteration over a range, with optional addition of more work and user-supplied context.

parallel_for

See also requirements on Range and parallel_for Body.

+template<typename Range, typename Body>
void tbb::parallel_for (const Range &range, const Body &body)
 Parallel iteration over range with default partitioner.
+template<typename Range, typename Body>
void tbb::parallel_for (const Range &range, const Body &body, const simple_partitioner &partitioner)
 Parallel iteration over range with simple partitioner.
+template<typename Range, typename Body>
void tbb::parallel_for (const Range &range, const Body &body, const auto_partitioner &partitioner)
 Parallel iteration over range with auto_partitioner.
+template<typename Range, typename Body>
void tbb::parallel_for (const Range &range, const Body &body, affinity_partitioner &partitioner)
 Parallel iteration over range with affinity_partitioner.
+template<typename Range, typename Body>
void tbb::parallel_for (const Range &range, const Body &body, const simple_partitioner &partitioner, task_group_context &context)
 Parallel iteration over range with simple partitioner and user-supplied context.
+template<typename Range, typename Body>
void tbb::parallel_for (const Range &range, const Body &body, const auto_partitioner &partitioner, task_group_context &context)
 Parallel iteration over range with auto_partitioner and user-supplied context.
+template<typename Range, typename Body>
void tbb::parallel_for (const Range &range, const Body &body, affinity_partitioner &partitioner, task_group_context &context)
 Parallel iteration over range with affinity_partitioner and user-supplied context.

parallel_for_each

+template<typename InputIterator, typename Function>
void tbb::parallel_for_each (InputIterator first, InputIterator last, const Function &f, task_group_context &context)
 Calls function f for all items from [first, last) interval using user-supplied context.
+template<typename InputIterator, typename Function>
void tbb::parallel_for_each (InputIterator first, InputIterator last, const Function &f)
 Uses default context.

parallel_invoke

+template<typename F0, typename F1>
void tbb::parallel_invoke (const F0 &f0, const F1 &f1, tbb::task_group_context &context)
 Executes a list of tasks in parallel and waits for all tasks to complete.
+template<typename F0, typename F1, typename F2>
void tbb::parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, tbb::task_group_context &context)
+template<typename F0, typename F1, typename F2, typename F3>
void tbb::parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, tbb::task_group_context &context)
+template<typename F0, typename F1, typename F2, typename F3, typename F4>
void tbb::parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, tbb::task_group_context &context)
+template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5>
void tbb::parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, const F5 &f5, tbb::task_group_context &context)
+template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6>
void tbb::parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, const F5 &f5, const F6 &f6, tbb::task_group_context &context)
+template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6, typename F7>
void tbb::parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, const F5 &f5, const F6 &f6, const F7 &f7, tbb::task_group_context &context)
+template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6, typename F7, typename F8>
void tbb::parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, const F5 &f5, const F6 &f6, const F7 &f7, const F8 &f8, tbb::task_group_context &context)
+template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6, typename F7, typename F8, typename F9>
void tbb::parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, const F5 &f5, const F6 &f6, const F7 &f7, const F8 &f8, const F9 &f9, tbb::task_group_context &context)
+template<typename F0, typename F1>
void tbb::parallel_invoke (const F0 &f0, const F1 &f1)
+template<typename F0, typename F1, typename F2>
void tbb::parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2)
+template<typename F0, typename F1, typename F2, typename F3>
void tbb::parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3)
+template<typename F0, typename F1, typename F2, typename F3, typename F4>
void tbb::parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4)
+template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5>
void tbb::parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, const F5 &f5)
+template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6>
void tbb::parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, const F5 &f5, const F6 &f6)
+template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6, typename F7>
void tbb::parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, const F5 &f5, const F6 &f6, const F7 &f7)
+template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6, typename F7, typename F8>
void tbb::parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, const F5 &f5, const F6 &f6, const F7 &f7, const F8 &f8)
+template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6, typename F7, typename F8, typename F9>
void tbb::parallel_invoke (const F0 &f0, const F1 &f1, const F2 &f2, const F3 &f3, const F4 &f4, const F5 &f5, const F6 &f6, const F7 &f7, const F8 &f8, const F9 &f9)

parallel_reduce

See also requirements on Range and parallel_reduce Body.

+template<typename Range, typename Body>
void tbb::parallel_reduce (const Range &range, Body &body)
 Parallel iteration with reduction and default partitioner.
+template<typename Range, typename Body>
void tbb::parallel_reduce (const Range &range, Body &body, const simple_partitioner &partitioner)
 Parallel iteration with reduction and simple_partitioner.
+template<typename Range, typename Body>
void tbb::parallel_reduce (const Range &range, Body &body, const auto_partitioner &partitioner)
 Parallel iteration with reduction and auto_partitioner.
+template<typename Range, typename Body>
void tbb::parallel_reduce (const Range &range, Body &body, affinity_partitioner &partitioner)
 Parallel iteration with reduction and affinity_partitioner.
+template<typename Range, typename Body>
void tbb::parallel_reduce (const Range &range, Body &body, const simple_partitioner &partitioner, task_group_context &context)
 Parallel iteration with reduction, simple partitioner and user-supplied context.
+template<typename Range, typename Body>
void tbb::parallel_reduce (const Range &range, Body &body, const auto_partitioner &partitioner, task_group_context &context)
 Parallel iteration with reduction, auto_partitioner and user-supplied context.
+template<typename Range, typename Body>
void tbb::parallel_reduce (const Range &range, Body &body, affinity_partitioner &partitioner, task_group_context &context)
 Parallel iteration with reduction, affinity_partitioner and user-supplied context.
+template<typename Range, typename Value, typename RealBody, typename Reduction>
Value tbb::parallel_reduce (const Range &range, const Value &identity, const RealBody &real_body, const Reduction &reduction)
 Parallel iteration with reduction and default partitioner.
+template<typename Range, typename Value, typename RealBody, typename Reduction>
Value tbb::parallel_reduce (const Range &range, const Value &identity, const RealBody &real_body, const Reduction &reduction, const simple_partitioner &partitioner)
 Parallel iteration with reduction and simple_partitioner.
+template<typename Range, typename Value, typename RealBody, typename Reduction>
Value tbb::parallel_reduce (const Range &range, const Value &identity, const RealBody &real_body, const Reduction &reduction, const auto_partitioner &partitioner)
 Parallel iteration with reduction and auto_partitioner.
+template<typename Range, typename Value, typename RealBody, typename Reduction>
Value tbb::parallel_reduce (const Range &range, const Value &identity, const RealBody &real_body, const Reduction &reduction, affinity_partitioner &partitioner)
 Parallel iteration with reduction and affinity_partitioner.
+template<typename Range, typename Value, typename RealBody, typename Reduction>
Value tbb::parallel_reduce (const Range &range, const Value &identity, const RealBody &real_body, const Reduction &reduction, const simple_partitioner &partitioner, task_group_context &context)
 Parallel iteration with reduction, simple partitioner and user-supplied context.
+template<typename Range, typename Value, typename RealBody, typename Reduction>
Value tbb::parallel_reduce (const Range &range, const Value &identity, const RealBody &real_body, const Reduction &reduction, const auto_partitioner &partitioner, task_group_context &context)
 Parallel iteration with reduction, auto_partitioner and user-supplied context.
+template<typename Range, typename Value, typename RealBody, typename Reduction>
Value tbb::parallel_reduce (const Range &range, const Value &identity, const RealBody &real_body, const Reduction &reduction, affinity_partitioner &partitioner, task_group_context &context)
 Parallel iteration with reduction, affinity_partitioner and user-supplied context.
+template<typename Range, typename Body>
void tbb::parallel_deterministic_reduce (const Range &range, Body &body)
 Parallel iteration with deterministic reduction and default partitioner.
+template<typename Range, typename Body>
void tbb::parallel_deterministic_reduce (const Range &range, Body &body, task_group_context &context)
 Parallel iteration with deterministic reduction, simple partitioner and user-supplied context.
+template<typename Range, typename Value, typename RealBody, typename Reduction>
Value tbb::parallel_deterministic_reduce (const Range &range, const Value &identity, const RealBody &real_body, const Reduction &reduction)
 Parallel iteration with deterministic reduction and default partitioner.
+template<typename Range, typename Value, typename RealBody, typename Reduction>
Value tbb::parallel_deterministic_reduce (const Range &range, const Value &identity, const RealBody &real_body, const Reduction &reduction, task_group_context &context)
 Parallel iteration with deterministic reduction, simple partitioner and user-supplied context.

parallel_scan

See also requirements on Range and parallel_scan Body.

+template<typename Range, typename Body>
void tbb::parallel_scan (const Range &range, Body &body)
 Parallel prefix with default partitioner.
+template<typename Range, typename Body>
void tbb::parallel_scan (const Range &range, Body &body, const simple_partitioner &partitioner)
 Parallel prefix with simple_partitioner.
+template<typename Range, typename Body>
void tbb::parallel_scan (const Range &range, Body &body, const auto_partitioner &partitioner)
 Parallel prefix with auto_partitioner.

parallel_sort

See also requirements on iterators for parallel_sort.

template<typename RandomAccessIterator, typename Compare>
void tbb::parallel_sort (RandomAccessIterator begin, RandomAccessIterator end, const Compare &comp)
 Sorts the data in [begin,end) using the given comparator.
+template<typename RandomAccessIterator>
void tbb::parallel_sort (RandomAccessIterator begin, RandomAccessIterator end)
 Sorts the data in [begin,end) with a default comparator std::less<RandomAccessIterator>.
+template<typename T>
void tbb::parallel_sort (T *begin, T *end)
 Sorts the data in the range [begin,end) with a default comparator std::less<T>.
+

Function Documentation

+ +
+
+
+template<typename RandomAccessIterator, typename Compare>
+ + + + + + + + + + + + + + + + + + + + + + + + +
void tbb::parallel_sort (RandomAccessIterator  begin,
RandomAccessIterator  end,
const Compare &  comp 
)
+
+
+ +

+Sorts the data in [begin,end) using the given comparator. +

+The compare function object is used for all comparisons between elements during sorting. The compare object must define a bool operator() function. +

+

+


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00427.html b/src/tbb/doc/html/a00427.html new file mode 100644 index 0000000..3e458d9 --- /dev/null +++ b/src/tbb/doc/html/a00427.html @@ -0,0 +1,50 @@ + + +Containers + + + + + +

Containers

+ + + + + + + + + + + + + + + + + + + + + + + +

Classes

class  tbb::combinable< T >
 Thread-local storage with optional reduction. More...
class  tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >
 Unordered map from Key to T. More...
class  tbb::strict_ppl::concurrent_queue< T, A >
 A high-performance thread-safe non-blocking concurrent queue. More...
class  tbb::concurrent_bounded_queue< T, A >
 A high-performance thread-safe blocking concurrent bounded queue. More...
class  tbb::deprecated::concurrent_queue< T, A >
 A high-performance thread-safe blocking concurrent bounded queue. More...
class  tbb::concurrent_vector< T, A >
 Concurrent vector container. More...
class  tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >
 The enumerable_thread_specific container. More...
+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00428.html b/src/tbb/doc/html/a00428.html new file mode 100644 index 0000000..1910530 --- /dev/null +++ b/src/tbb/doc/html/a00428.html @@ -0,0 +1,319 @@ + + +Memory Allocation + + + + + +

Memory Allocation

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Classes

class  tbb::aligned_space< T, N >
 Block of space aligned sufficiently to construct an array T with N elements. More...
class  tbb::cache_aligned_allocator< T >
 Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5. More...
class  tbb::cache_aligned_allocator< void >
 Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1. More...
class  tbb::interface6::memory_pool_allocator< T, P >
 Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5. More...
class  tbb::interface6::memory_pool_allocator< void, P >
 Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1. More...
class  tbb::scalable_allocator< T >
 Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5. More...
class  tbb::scalable_allocator< void >
 Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1. More...
class  tbb::tbb_allocator< T >
 Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5. More...
class  tbb::tbb_allocator< void >
 Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1. More...
class  tbb::zero_allocator< T, Allocator >
 Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5. More...
class  tbb::zero_allocator< void, Allocator >
 Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1. More...

Functions

void *__TBB_EXPORTED_FUNC scalable_malloc (size_t size)
void __TBB_EXPORTED_FUNC scalable_free (void *ptr)
void *__TBB_EXPORTED_FUNC scalable_realloc (void *ptr, size_t size)
void *__TBB_EXPORTED_FUNC scalable_calloc (size_t nobj, size_t size)
int __TBB_EXPORTED_FUNC scalable_posix_memalign (void **memptr, size_t alignment, size_t size)
void *__TBB_EXPORTED_FUNC scalable_aligned_malloc (size_t size, size_t alignment)
void *__TBB_EXPORTED_FUNC scalable_aligned_realloc (void *ptr, size_t size, size_t alignment)
void __TBB_EXPORTED_FUNC scalable_aligned_free (void *ptr)
size_t __TBB_EXPORTED_FUNC scalable_msize (void *ptr)
+

Function Documentation

+ +
+
+ + + + + + + + + +
void __TBB_EXPORTED_FUNC scalable_aligned_free (void *  ptr  ) 
+
+
+ +

+The "_aligned_free" analogue. +

+

+ +

+
+ + + + + + + + + + + + + + + + + + +
void* __TBB_EXPORTED_FUNC scalable_aligned_malloc (size_t  size,
size_t  alignment 
)
+
+
+ +

+The "_aligned_malloc" analogue. +

+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
void* __TBB_EXPORTED_FUNC scalable_aligned_realloc (void *  ptr,
size_t  size,
size_t  alignment 
)
+
+
+ +

+The "_aligned_realloc" analogue. +

+

+ +

+
+ + + + + + + + + + + + + + + + + + +
void* __TBB_EXPORTED_FUNC scalable_calloc (size_t  nobj,
size_t  size 
)
+
+
+ +

+The "calloc" analogue complementing scalable_malloc. +

+

+ +

+
+ + + + + + + + + +
void __TBB_EXPORTED_FUNC scalable_free (void *  ptr  ) 
+
+
+ +

+The "free" analogue to discard a previously allocated piece of memory. +

+

+ +

+
+ + + + + + + + + +
void* __TBB_EXPORTED_FUNC scalable_malloc (size_t  size  ) 
+
+
+ +

+The "malloc" analogue to allocate block of memory of size bytes. +

+

+ +

+
+ + + + + + + + + +
size_t __TBB_EXPORTED_FUNC scalable_msize (void *  ptr  ) 
+
+
+ +

+The analogue of _msize/malloc_size/malloc_usable_size. Returns the usable size of a memory block previously allocated by scalable_*, or 0 (zero) if ptr does not point to such a block. +

+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
int __TBB_EXPORTED_FUNC scalable_posix_memalign (void **  memptr,
size_t  alignment,
size_t  size 
)
+
+
+ +

+The "posix_memalign" analogue. +

+

+ +

+
+ + + + + + + + + + + + + + + + + + +
void* __TBB_EXPORTED_FUNC scalable_realloc (void *  ptr,
size_t  size 
)
+
+
+ +

+The "realloc" analogue complementing scalable_malloc. +

+

+


+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00429.html b/src/tbb/doc/html/a00429.html new file mode 100644 index 0000000..18ce518 --- /dev/null +++ b/src/tbb/doc/html/a00429.html @@ -0,0 +1,59 @@ + + +Synchronization + + + + + +

Synchronization

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Classes

struct  tbb::atomic< T >
 Primary template for atomic. More...
class  tbb::mutex
 Wrapper around the platform's native reader-writer lock. More...
class  tbb::null_mutex
 A mutex which does nothing. More...
class  tbb::null_rw_mutex
 A rw mutex which does nothing. More...
class  tbb::queuing_mutex
 Queuing mutex with local-only spinning. More...
class  tbb::queuing_rw_mutex
 Queuing reader-writer mutex with local-only spinning. More...
class  tbb::interface5::reader_writer_lock
 Writer-preference reader-writer lock with local-only spinning on readers. More...
class  tbb::recursive_mutex
 Mutex that allows recursive mutex acquisition. More...
class  tbb::spin_mutex
 A lock that occupies a single byte. More...
class  tbb::spin_rw_mutex_v3
 Fast, unfair, spinning reader-writer lock with backoff and writer-preference. More...
+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00430.html b/src/tbb/doc/html/a00430.html new file mode 100644 index 0000000..ec37257 --- /dev/null +++ b/src/tbb/doc/html/a00430.html @@ -0,0 +1,32 @@ + + +Timing + + + + + +

Timing

+ + + + + +

Classes

class  tbb::tick_count
 Absolute timestamp. More...
+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00431.html b/src/tbb/doc/html/a00431.html new file mode 100644 index 0000000..2b72f6d --- /dev/null +++ b/src/tbb/doc/html/a00431.html @@ -0,0 +1,44 @@ + + +Task Scheduling + + + + + +

Task Scheduling

+ + + + + + + + + + + + + + + + + +

Classes

class  tbb::task_group_context
 Used to form groups of tasks. More...
class  tbb::task
 Base class for user-defined tasks. More...
class  tbb::empty_task
 task that does nothing. Useful for synchronization. More...
class  tbb::task_list
 A list of children. More...
class  tbb::task_scheduler_init
 Class delimiting the scope of task scheduler activity. More...
+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00432.html b/src/tbb/doc/html/a00432.html new file mode 100644 index 0000000..1eb992a --- /dev/null +++ b/src/tbb/doc/html/a00432.html @@ -0,0 +1,219 @@ + + +aggregator.h Source File + + + + + + +

aggregator.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB__aggregator_H
+00022 #define __TBB__aggregator_H
+00023 
+00024 #if !TBB_PREVIEW_AGGREGATOR
+00025 #error Set TBB_PREVIEW_AGGREGATOR before including aggregator.h
+00026 #endif
+00027 
+00028 #include "atomic.h"
+00029 #include "tbb_profiling.h"
+00030 
+00031 namespace tbb {
+00032 namespace interface6 {
+00033 
+00034 using namespace tbb::internal;
+00035 
+00036 class aggregator_operation {
+00037     template<typename handler_type> friend class aggregator_ext;
+00038     uintptr_t status;
+00039     aggregator_operation* my_next;
+00040 public:
+00041     enum aggregator_operation_status { agg_waiting=0, agg_finished };
+00042     aggregator_operation() : status(agg_waiting), my_next(NULL) {}
+00044     void start() { call_itt_notify(acquired, &status); }
+00046 
+00047     void finish() { itt_store_word_with_release(status, uintptr_t(agg_finished)); }
+00048     aggregator_operation* next() { return itt_hide_load_word(my_next);}
+00049     void set_next(aggregator_operation* n) { itt_hide_store_word(my_next, n); }
+00050 };
+00051 
+00052 namespace internal {
+00053 
+00054 class basic_operation_base : public aggregator_operation {
+00055     friend class basic_handler;
+00056     virtual void apply_body() = 0;
+00057 public:
+00058     basic_operation_base() : aggregator_operation() {}
+00059     virtual ~basic_operation_base() {}
+00060 };
+00061 
+00062 template<typename Body>
+00063 class basic_operation : public basic_operation_base, no_assign {
+00064     const Body& my_body;
+00065     /*override*/ void apply_body() { my_body(); }
+00066 public:
+00067     basic_operation(const Body& b) : basic_operation_base(), my_body(b) {}
+00068 };
+00069 
+00070 class basic_handler {
+00071 public:
+00072     basic_handler() {}
+00073     void operator()(aggregator_operation* op_list) const { 
+00074         while (op_list) {
+00075             // ITT note: &(op_list->status) tag is used to cover accesses to the operation data.
+00076             // The executing thread "acquires" the tag (see start()) and then performs
+00077             // the associated operation w/o triggering a race condition diagnostics.
+00078             // A thread that created the operation is waiting for its status (see execute_impl()),
+00079             // so when this thread is done with the operation, it will "release" the tag 
+00080             // and update the status (see finish()) to give control back to the waiting thread.
+00081             basic_operation_base& request = static_cast<basic_operation_base&>(*op_list);
+00082             // IMPORTANT: need to advance op_list to op_list->next() before calling request.finish()
+00083             op_list = op_list->next();
+00084             request.start();
+00085             request.apply_body();
+00086             request.finish();
+00087         }
+00088     }
+00089 };
+00090 
+00091 } // namespace internal
+00092 
+00094 
+00096 template <typename handler_type>
+00097 class aggregator_ext : tbb::internal::no_copy {
+00098 public:
+00099     aggregator_ext(const handler_type& h) : handler_busy(0), handle_operations(h) { mailbox = NULL; }
+00100 
+00102 
+00103     void process(aggregator_operation *op) { execute_impl(*op); }
+00104 
+00105  protected:
+00108     void execute_impl(aggregator_operation& op) {
+00109         aggregator_operation* res;
+00110 
+00111         // ITT note: &(op.status) tag is used to cover accesses to this operation. This
+00112         // thread has created the operation, and now releases it so that the handler
+00113         // thread may handle the associated operation w/o triggering a race condition;
+00114         // thus this tag will be acquired just before the operation is handled in the
+00115         // handle_operations functor.
+00116         call_itt_notify(releasing, &(op.status));
+00117         // insert the operation in the queue
+00118         do {
+00119             // ITT may flag the following line as a race; it is a false positive:
+00120             // This is an atomic read; we don't provide itt_hide_load_word for atomics
+00121             op.my_next = res = mailbox; // NOT A RACE 
+00122         } while (mailbox.compare_and_swap(&op, res) != res);
+00123         if (!res) { // first in the list; handle the operations
+00124             // ITT note: &mailbox tag covers access to the handler_busy flag, which this
+00125             // waiting handler thread will try to set before entering handle_operations.
+00126             call_itt_notify(acquired, &mailbox);
+00127             start_handle_operations();
+00128             __TBB_ASSERT(op.status, NULL);
+00129         }
+00130         else { // not first; wait for op to be ready
+00131             call_itt_notify(prepare, &(op.status));
+00132             spin_wait_while_eq(op.status, uintptr_t(aggregator_operation::agg_waiting));
+00133             itt_load_word_with_acquire(op.status);
+00134         }
+00135     }
+00136 
+00137 
+00138  private:
+00140     atomic<aggregator_operation *> mailbox;
+00141 
+00143 
+00144     uintptr_t handler_busy;
+00145 
+00146     handler_type handle_operations;
+00147 
+00149     void start_handle_operations() {
+00150         aggregator_operation *pending_operations;
+00151 
+00152         // ITT note: &handler_busy tag covers access to mailbox as it is passed
+00153         // between active and waiting handlers.  Below, the waiting handler waits until
+00154         // the active handler releases, and the waiting handler acquires &handler_busy as
+00155         // it becomes the active_handler. The release point is at the end of this
+00156         // function, when all operations in mailbox have been handled by the
+00157         // owner of this aggregator.
+00158         call_itt_notify(prepare, &handler_busy);
+00159         // get handler_busy: only one thread can possibly spin here at a time
+00160         spin_wait_until_eq(handler_busy, uintptr_t(0));
+00161         call_itt_notify(acquired, &handler_busy);
+00162         // acquire fence not necessary here due to causality rule and surrounding atomics
+00163         __TBB_store_with_release(handler_busy, uintptr_t(1));
+00164 
+00165         // ITT note: &mailbox tag covers access to the handler_busy flag itself. 
+00166         // Capturing the state of the mailbox signifies that handler_busy has been 
+00167         // set and a new active handler will now process that list's operations.
+00168         call_itt_notify(releasing, &mailbox);
+00169         // grab pending_operations
+00170         pending_operations = mailbox.fetch_and_store(NULL);
+00171 
+00172         // handle all the operations
+00173         handle_operations(pending_operations);
+00174 
+00175         // release the handler
+00176         itt_store_word_with_release(handler_busy, uintptr_t(0));
+00177     }
+00178 };
+00179 
+00181 class aggregator : private aggregator_ext<internal::basic_handler> {
+00182 public:
+00183     aggregator() : aggregator_ext<internal::basic_handler>(internal::basic_handler()) {}
+00185 
+00187     template<typename Body>
+00188     void execute(const Body& b) {
+00189         internal::basic_operation<Body> op(b);
+00190         this->execute_impl(op);
+00191     }
+00192 };
+00193 
+00194 } // namespace interface6
+00195 
+00196 using interface6::aggregator;
+00197 using interface6::aggregator_ext;
+00198 using interface6::aggregator_operation;
+00199 
+00200 } // namespace tbb
+00201 
+00202 #endif  // __TBB__aggregator_H
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00440.html b/src/tbb/doc/html/a00440.html new file mode 100644 index 0000000..e394dd2 --- /dev/null +++ b/src/tbb/doc/html/a00440.html @@ -0,0 +1,73 @@ + + +aligned_space.h Source File + + + + + + +

aligned_space.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_aligned_space_H
+00022 #define __TBB_aligned_space_H
+00023 
+00024 #include "tbb_stddef.h"
+00025 #include "tbb_machine.h"
+00026 
+00027 namespace tbb {
+00028 
+00030 
+00032 template<typename T,size_t N>
+00033 class aligned_space {
+00034 private:
+00035     typedef __TBB_TypeWithAlignmentAtLeastAsStrict(T) element_type;
+00036     element_type array[(sizeof(T)*N+sizeof(element_type)-1)/sizeof(element_type)];
+00037 public:
+00039     T* begin() {return internal::punned_cast<T*>(this);}
+00040 
+00042     T* end() {return begin()+N;}
+00043 };
+00044 
+00045 } // namespace tbb 
+00046 
+00047 #endif /* __TBB_aligned_space_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00441.html b/src/tbb/doc/html/a00441.html new file mode 100644 index 0000000..0d06971 --- /dev/null +++ b/src/tbb/doc/html/a00441.html @@ -0,0 +1,452 @@ + + +atomic.h Source File + + + + + + +

atomic.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_atomic_H
+00022 #define __TBB_atomic_H
+00023 
+00024 #include <cstddef>
+00025 #include "tbb_stddef.h"
+00026 
+00027 #if _MSC_VER
+00028 #define __TBB_LONG_LONG __int64
+00029 #else
+00030 #define __TBB_LONG_LONG long long
+00031 #endif /* _MSC_VER */
+00032 
+00033 #include "tbb_machine.h"
+00034 
+00035 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
+00036     // Workaround for overzealous compiler warnings
+00037     #pragma warning (push)
+00038     #pragma warning (disable: 4244 4267)
+00039 #endif
+00040 
+00041 namespace tbb {
+00042 
+00044 enum memory_semantics {
+00046     full_fence,
+00048     acquire,
+00050     release,
+00052     relaxed
+00053 };
+00054 
+00056 namespace internal {
+00057 
+00058 #if __TBB_ATTRIBUTE_ALIGNED_PRESENT
+00059     #define __TBB_DECL_ATOMIC_FIELD(t,f,a) t f  __attribute__ ((aligned(a)));
+00060 #elif __TBB_DECLSPEC_ALIGN_PRESENT
+00061     #define __TBB_DECL_ATOMIC_FIELD(t,f,a) __declspec(align(a)) t f;
+00062 #else
+00063     #error Do not know syntax for forcing alignment.
+00064 #endif
+00065 
+00066 template<size_t S>
+00067 struct atomic_rep;           // Primary template declared, but never defined.
+00068 
+00069 template<>
+00070 struct atomic_rep<1> {       // Specialization
+00071     typedef int8_t word;
+00072     int8_t value;
+00073 };
+00074 template<>
+00075 struct atomic_rep<2> {       // Specialization
+00076     typedef int16_t word;
+00077     __TBB_DECL_ATOMIC_FIELD(int16_t,value,2)
+00078 };
+00079 template<>
+00080 struct atomic_rep<4> {       // Specialization
+00081 #if _MSC_VER && !_WIN64
+00082     // Work-around that avoids spurious /Wp64 warnings
+00083     typedef intptr_t word;
+00084 #else
+00085     typedef int32_t word;
+00086 #endif
+00087     __TBB_DECL_ATOMIC_FIELD(int32_t,value,4)
+00088 };
+00089 #if __TBB_64BIT_ATOMICS
+00090 template<>
+00091 struct atomic_rep<8> {       // Specialization
+00092     typedef int64_t word;
+00093     __TBB_DECL_ATOMIC_FIELD(int64_t,value,8)
+00094 };
+00095 #endif
+00096 
+00097 template<size_t Size, memory_semantics M>
+00098 struct atomic_traits;        // Primary template declared, but not defined.
+00099 
+00100 #define __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(S,M)                                                         \
+00101     template<> struct atomic_traits<S,M> {                                                               \
+00102         typedef atomic_rep<S>::word word;                                                                \
+00103         inline static word compare_and_swap( volatile void* location, word new_value, word comparand ) { \
+00104             return __TBB_machine_cmpswp##S##M(location,new_value,comparand);                             \
+00105         }                                                                                                \
+00106         inline static word fetch_and_add( volatile void* location, word addend ) {                       \
+00107             return __TBB_machine_fetchadd##S##M(location,addend);                                        \
+00108         }                                                                                                \
+00109         inline static word fetch_and_store( volatile void* location, word value ) {                      \
+00110             return __TBB_machine_fetchstore##S##M(location,value);                                       \
+00111         }                                                                                                \
+00112     };
+00113 
+00114 #define __TBB_DECL_ATOMIC_PRIMITIVES(S)                                                                  \
+00115     template<memory_semantics M>                                                                         \
+00116     struct atomic_traits<S,M> {                                                                          \
+00117         typedef atomic_rep<S>::word word;                                                                \
+00118         inline static word compare_and_swap( volatile void* location, word new_value, word comparand ) { \
+00119             return __TBB_machine_cmpswp##S(location,new_value,comparand);                                \
+00120         }                                                                                                \
+00121         inline static word fetch_and_add( volatile void* location, word addend ) {                       \
+00122             return __TBB_machine_fetchadd##S(location,addend);                                           \
+00123         }                                                                                                \
+00124         inline static word fetch_and_store( volatile void* location, word value ) {                      \
+00125             return __TBB_machine_fetchstore##S(location,value);                                          \
+00126         }                                                                                                \
+00127     };
+00128 
+00129 template<memory_semantics M>
+00130 struct atomic_load_store_traits;    // Primary template declaration
+00131 
+00132 #define __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(M)                      \
+00133     template<> struct atomic_load_store_traits<M> {                     \
+00134         template <typename T>                                           \
+00135         inline static T load( const volatile T& location ) {            \
+00136             return __TBB_load_##M( location );                          \
+00137         }                                                               \
+00138         template <typename T>                                           \
+00139         inline static void store( volatile T& location, T value ) {     \
+00140             __TBB_store_##M( location, value );                         \
+00141         }                                                               \
+00142     }
+00143 
+00144 #if __TBB_USE_FENCED_ATOMICS
+00145 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,full_fence)
+00146 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,full_fence)
+00147 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,full_fence)
+00148 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,acquire)
+00149 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,acquire)
+00150 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,acquire)
+00151 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,release)
+00152 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,release)
+00153 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,release)
+00154 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,relaxed)
+00155 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,relaxed)
+00156 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,relaxed)
+00157 #if __TBB_64BIT_ATOMICS
+00158 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,full_fence)
+00159 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,acquire)
+00160 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,release)
+00161 __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,relaxed)
+00162 #endif
+00163 #else /* !__TBB_USE_FENCED_ATOMICS */
+00164 __TBB_DECL_ATOMIC_PRIMITIVES(1)
+00165 __TBB_DECL_ATOMIC_PRIMITIVES(2)
+00166 __TBB_DECL_ATOMIC_PRIMITIVES(4)
+00167 #if __TBB_64BIT_ATOMICS
+00168 __TBB_DECL_ATOMIC_PRIMITIVES(8)
+00169 #endif
+00170 #endif /* !__TBB_USE_FENCED_ATOMICS */
+00171 
+00172 __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(full_fence);
+00173 __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(acquire);
+00174 __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(release);
+00175 __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(relaxed);
+00176 
+00178 
+00180 #define __TBB_MINUS_ONE(T) (T(T(0)-T(1)))
+00181 
+00183 
+00185 template<typename T>
+00186 struct atomic_impl {
+00187 protected:
+00188     atomic_rep<sizeof(T)> rep;
+00189 private:
+00191     union converter {
+00192         T value;
+00193         typename atomic_rep<sizeof(T)>::word bits;
+00194     };
+00195 public:
+00196     typedef T value_type;
+00197 
+00198     template<memory_semantics M>
+00199     value_type fetch_and_store( value_type value ) {
+00200         converter u, w;
+00201         u.value = value;
+00202         w.bits = internal::atomic_traits<sizeof(value_type),M>::fetch_and_store(&rep.value,u.bits);
+00203         return w.value;
+00204     }
+00205 
+00206     value_type fetch_and_store( value_type value ) {
+00207         return fetch_and_store<full_fence>(value);
+00208     }
+00209 
+00210     template<memory_semantics M>
+00211     value_type compare_and_swap( value_type value, value_type comparand ) {
+00212         converter u, v, w;
+00213         u.value = value;
+00214         v.value = comparand;
+00215         w.bits = internal::atomic_traits<sizeof(value_type),M>::compare_and_swap(&rep.value,u.bits,v.bits);
+00216         return w.value;
+00217     }
+00218 
+00219     value_type compare_and_swap( value_type value, value_type comparand ) {
+00220         return compare_and_swap<full_fence>(value,comparand);
+00221     }
+00222 
+00223     operator value_type() const volatile {                // volatile qualifier here for backwards compatibility
+00224         converter w;
+00225         w.bits = __TBB_load_with_acquire( rep.value );
+00226         return w.value;
+00227     }
+00228 
+00229     template<memory_semantics M>
+00230     value_type load () const {
+00231         converter u;
+00232         u.bits = internal::atomic_load_store_traits<M>::load( rep.value );
+00233         return u.value;
+00234     }
+00235 
+00236     value_type load () const {
+00237         return load<acquire>();
+00238     }
+00239 
+00240     template<memory_semantics M>
+00241     void store ( value_type value ) {
+00242         converter u;
+00243         u.value = value;
+00244         internal::atomic_load_store_traits<M>::store( rep.value, u.bits );
+00245     }
+00246 
+00247     void store ( value_type value ) {
+00248         store<release>( value );
+00249     }
+00250 
+00251 protected:
+00252     value_type store_with_release( value_type rhs ) {
+00253         converter u;
+00254         u.value = rhs;
+00255         __TBB_store_with_release(rep.value,u.bits);
+00256         return rhs;
+00257     }
+00258 };
+00259 
+00261 
+00264 template<typename I, typename D, typename StepType>
+00265 struct atomic_impl_with_arithmetic: atomic_impl<I> {
+00266 public:
+00267     typedef I value_type;
+00268 
+00269     template<memory_semantics M>
+00270     value_type fetch_and_add( D addend ) {
+00271         return value_type(internal::atomic_traits<sizeof(value_type),M>::fetch_and_add( &this->rep.value, addend*sizeof(StepType) ));
+00272     }
+00273 
+00274     value_type fetch_and_add( D addend ) {
+00275         return fetch_and_add<full_fence>(addend);
+00276     }
+00277 
+00278     template<memory_semantics M>
+00279     value_type fetch_and_increment() {
+00280         return fetch_and_add<M>(1);
+00281     }
+00282 
+00283     value_type fetch_and_increment() {
+00284         return fetch_and_add(1);
+00285     }
+00286 
+00287     template<memory_semantics M>
+00288     value_type fetch_and_decrement() {
+00289         return fetch_and_add<M>(__TBB_MINUS_ONE(D));
+00290     }
+00291 
+00292     value_type fetch_and_decrement() {
+00293         return fetch_and_add(__TBB_MINUS_ONE(D));
+00294     }
+00295 
+00296 public:
+00297     value_type operator+=( D value ) {
+00298         return fetch_and_add(value)+value;
+00299     }
+00300 
+00301     value_type operator-=( D value ) {
+00302         // Additive inverse of value computed using binary minus,
+00303         // instead of unary minus, for sake of avoiding compiler warnings.
+00304         return operator+=(D(0)-value);
+00305     }
+00306 
+00307     value_type operator++() {
+00308         return fetch_and_add(1)+1;
+00309     }
+00310 
+00311     value_type operator--() {
+00312         return fetch_and_add(__TBB_MINUS_ONE(D))-1;
+00313     }
+00314 
+00315     value_type operator++(int) {
+00316         return fetch_and_add(1);
+00317     }
+00318 
+00319     value_type operator--(int) {
+00320         return fetch_and_add(__TBB_MINUS_ONE(D));
+00321     }
+00322 };
+00323 
+00324 } /* Internal */
+00326 
+00328 
+00330 template<typename T>
+00331 struct atomic: internal::atomic_impl<T> {
+00332     T operator=( T rhs ) {
+00333         // "this" required here in strict ISO C++ because store_with_release is a dependent name
+00334         return this->store_with_release(rhs);
+00335     }
+00336     atomic<T>& operator=( const atomic<T>& rhs ) {this->store_with_release(rhs); return *this;}
+00337 };
+00338 
+00339 #define __TBB_DECL_ATOMIC(T) \
+00340     template<> struct atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {  \
+00341         T operator=( T rhs ) {return store_with_release(rhs);}  \
+00342         atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rhs); return *this;}  \
+00343     };
+00344 
+00345 #if __TBB_64BIT_ATOMICS
+00346 __TBB_DECL_ATOMIC(__TBB_LONG_LONG)
+00347 __TBB_DECL_ATOMIC(unsigned __TBB_LONG_LONG)
+00348 #else
+00349 // test_atomic will verify that sizeof(long long)==8
+00350 #endif
+00351 __TBB_DECL_ATOMIC(long)
+00352 __TBB_DECL_ATOMIC(unsigned long)
+00353 
+00354 #if _MSC_VER && !_WIN64
+00355 /* Special version of __TBB_DECL_ATOMIC that avoids gratuitous warnings from cl /Wp64 option.
+00356    It is identical to __TBB_DECL_ATOMIC(unsigned) except that it replaces operator=(T)
+00357    with an operator=(U) that explicitly converts the U to a T.  Types T and U should be
+00358    type synonyms on the platform.  Type U should be the wider variant of T from the
+00359    perspective of /Wp64. */
+00360 #define __TBB_DECL_ATOMIC_ALT(T,U) \
+00361     template<> struct atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {  \
+00362         T operator=( U rhs ) {return store_with_release(T(rhs));}  \
+00363         atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rhs); return *this;}  \
+00364     };
+00365 __TBB_DECL_ATOMIC_ALT(unsigned,size_t)
+00366 __TBB_DECL_ATOMIC_ALT(int,ptrdiff_t)
+00367 #else
+00368 __TBB_DECL_ATOMIC(unsigned)
+00369 __TBB_DECL_ATOMIC(int)
+00370 #endif /* _MSC_VER && !_WIN64 */
+00371 
+00372 __TBB_DECL_ATOMIC(unsigned short)
+00373 __TBB_DECL_ATOMIC(short)
+00374 __TBB_DECL_ATOMIC(char)
+00375 __TBB_DECL_ATOMIC(signed char)
+00376 __TBB_DECL_ATOMIC(unsigned char)
+00377 
+00378 #if !_MSC_VER || defined(_NATIVE_WCHAR_T_DEFINED)
+00379 __TBB_DECL_ATOMIC(wchar_t)
+00380 #endif /* _MSC_VER||!defined(_NATIVE_WCHAR_T_DEFINED) */
+00381 
+00383 template<typename T> struct atomic<T*>: internal::atomic_impl_with_arithmetic<T*,ptrdiff_t,T> {
+00384     T* operator=( T* rhs ) {
+00385         // "this" required here in strict ISO C++ because store_with_release is a dependent name
+00386         return this->store_with_release(rhs);
+00387     }
+00388     atomic<T*>& operator=( const atomic<T*>& rhs ) {
+00389         this->store_with_release(rhs); return *this;
+00390     }
+00391     T* operator->() const {
+00392         return (*this);
+00393     }
+00394 };
+00395 
+00397 template<> struct atomic<void*>: internal::atomic_impl<void*> {
+00398     void* operator=( void* rhs ) {
+00399         // "this" required here in strict ISO C++ because store_with_release is a dependent name
+00400         return this->store_with_release(rhs);
+00401     }
+00402     atomic<void*>& operator=( const atomic<void*>& rhs ) {
+00403         this->store_with_release(rhs); return *this;
+00404     }
+00405 };
+00406 
+00407 // Helpers to workaround ugly syntax of calling template member function of a
+00408 // template class with template argument dependent on template parameters.
+00409 
+00410 template <memory_semantics M, typename T>
+00411 T load ( const atomic<T>& a ) { return a.template load<M>(); }
+00412 
+00413 template <memory_semantics M, typename T>
+00414 void store ( atomic<T>& a, T value ) { return a.template store<M>(value); }
+00415 
+00416 namespace interface6{
+00418 template<typename T>
+00419 atomic<T> make_atomic(T t) {
+00420     atomic<T> a;
+00421     store<relaxed>(a,t);
+00422     return a;
+00423 }
+00424 }
+00425 using interface6::make_atomic;
+00426 
+00427 namespace internal {
+00428 
+00429 // only to aid in the gradual conversion of ordinary variables to proper atomics
+00430 template<typename T>
+00431 inline atomic<T>& as_atomic( T& t ) {
+00432     return (atomic<T>&)t;
+00433 }
+00434 } // namespace tbb::internal
+00435 
+00436 } // namespace tbb
+00437 
+00438 #if _MSC_VER && !__INTEL_COMPILER
+00439     #pragma warning (pop)
+00440 #endif // warnings 4244, 4267 are back
+00441 
+00442 #endif /* __TBB_atomic_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00449.html b/src/tbb/doc/html/a00449.html new file mode 100644 index 0000000..a59568e --- /dev/null +++ b/src/tbb/doc/html/a00449.html @@ -0,0 +1,127 @@ + + +blocked_range.h Source File + + + + + + +

blocked_range.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_blocked_range_H
+00022 #define __TBB_blocked_range_H
+00023 
+00024 #include "tbb_stddef.h"
+00025 
+00026 namespace tbb {
+00027 
+00037 
+00038 
+00039 template<typename Value>
+00040 class blocked_range {
+00041 public:
+00043 
+00045     typedef Value const_iterator;
+00046 
+00048     typedef std::size_t size_type;
+00049 
+00051 
+00052     blocked_range() : my_end(), my_begin() {}
+00053 
+00055     blocked_range( Value begin_, Value end_, size_type grainsize_=1 ) : 
+00056         my_end(end_), my_begin(begin_), my_grainsize(grainsize_) 
+00057     {
+00058         __TBB_ASSERT( my_grainsize>0, "grainsize must be positive" );
+00059     }
+00060 
+00062     const_iterator begin() const {return my_begin;}
+00063 
+00065     const_iterator end() const {return my_end;}
+00066 
+00068 
+00069     size_type size() const {
+00070         __TBB_ASSERT( !(end()<begin()), "size() unspecified if end()<begin()" );
+00071         return size_type(my_end-my_begin);
+00072     }
+00073 
+00075     size_type grainsize() const {return my_grainsize;}
+00076 
+00077     //------------------------------------------------------------------------
+00078     // Methods that implement Range concept
+00079     //------------------------------------------------------------------------
+00080 
+00082     bool empty() const {return !(my_begin<my_end);}
+00083 
+00085 
+00086     bool is_divisible() const {return my_grainsize<size();}
+00087 
+00089 
+00091     blocked_range( blocked_range& r, split ) : 
+00092         my_end(r.my_end),
+00093         my_begin(do_split(r)),
+00094         my_grainsize(r.my_grainsize)
+00095     {}
+00096 
+00097 private:
+00099     Value my_end;
+00100     Value my_begin;
+00101     size_type my_grainsize;
+00102 
+00104 
+00105     static Value do_split( blocked_range& r ) {
+00106         __TBB_ASSERT( r.is_divisible(), "cannot split blocked_range that is not divisible" );
+00107         Value middle = r.my_begin + (r.my_end-r.my_begin)/2u;
+00108         r.my_end = middle;
+00109         return middle;
+00110     }
+00111 
+00112     template<typename RowValue, typename ColValue>
+00113     friend class blocked_range2d;
+00114 
+00115     template<typename RowValue, typename ColValue, typename PageValue>
+00116     friend class blocked_range3d;
+00117 };
+00118 
+00119 } // namespace tbb 
+00120 
+00121 #endif /* __TBB_blocked_range_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00450.html b/src/tbb/doc/html/a00450.html new file mode 100644 index 0000000..fe4847d --- /dev/null +++ b/src/tbb/doc/html/a00450.html @@ -0,0 +1,113 @@ + + +blocked_range2d.h Source File + + + + + + +

blocked_range2d.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_blocked_range2d_H
+00022 #define __TBB_blocked_range2d_H
+00023 
+00024 #include "tbb_stddef.h"
+00025 #include "blocked_range.h"
+00026 
+00027 namespace tbb {
+00028 
+00030 
+00031 template<typename RowValue, typename ColValue=RowValue>
+00032 class blocked_range2d {
+00033 public:
+00035     typedef blocked_range<RowValue> row_range_type;
+00036     typedef blocked_range<ColValue> col_range_type;
+00037  
+00038 private:
+00039     row_range_type my_rows;
+00040     col_range_type my_cols;
+00041 
+00042 public:
+00043 
+00044     blocked_range2d( RowValue row_begin, RowValue row_end, typename row_range_type::size_type row_grainsize,
+00045                      ColValue col_begin, ColValue col_end, typename col_range_type::size_type col_grainsize ) : 
+00046         my_rows(row_begin,row_end,row_grainsize),
+00047         my_cols(col_begin,col_end,col_grainsize)
+00048     {
+00049     }
+00050 
+00051     blocked_range2d( RowValue row_begin, RowValue row_end,
+00052                      ColValue col_begin, ColValue col_end ) : 
+00053         my_rows(row_begin,row_end),
+00054         my_cols(col_begin,col_end)
+00055     {
+00056     }
+00057 
+00059     bool empty() const {
+00060         // Yes, it is a logical OR here, not AND.
+00061         return my_rows.empty() || my_cols.empty();
+00062     }
+00063 
+00065     bool is_divisible() const {
+00066         return my_rows.is_divisible() || my_cols.is_divisible();
+00067     }
+00068 
+00069     blocked_range2d( blocked_range2d& r, split ) : 
+00070         my_rows(r.my_rows),
+00071         my_cols(r.my_cols)
+00072     {
+00073         if( my_rows.size()*double(my_cols.grainsize()) < my_cols.size()*double(my_rows.grainsize()) ) {
+00074             my_cols.my_begin = col_range_type::do_split(r.my_cols);
+00075         } else {
+00076             my_rows.my_begin = row_range_type::do_split(r.my_rows);
+00077         }
+00078     }
+00079 
+00081     const row_range_type& rows() const {return my_rows;}
+00082 
+00084     const col_range_type& cols() const {return my_cols;}
+00085 };
+00086 
+00087 } // namespace tbb 
+00088 
+00089 #endif /* __TBB_blocked_range2d_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00451.html b/src/tbb/doc/html/a00451.html new file mode 100644 index 0000000..3f8bee2 --- /dev/null +++ b/src/tbb/doc/html/a00451.html @@ -0,0 +1,131 @@ + + +blocked_range3d.h Source File + + + + + + +

blocked_range3d.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_blocked_range3d_H
+00022 #define __TBB_blocked_range3d_H
+00023 
+00024 #include "tbb_stddef.h"
+00025 #include "blocked_range.h"
+00026 
+00027 namespace tbb {
+00028 
+00030 
+00031 template<typename PageValue, typename RowValue=PageValue, typename ColValue=RowValue>
+00032 class blocked_range3d {
+00033 public:
+00035     typedef blocked_range<PageValue> page_range_type;
+00036     typedef blocked_range<RowValue>  row_range_type;
+00037     typedef blocked_range<ColValue>  col_range_type;
+00038  
+00039 private:
+00040     page_range_type my_pages;
+00041     row_range_type  my_rows;
+00042     col_range_type  my_cols;
+00043 
+00044 public:
+00045 
+00046     blocked_range3d( PageValue page_begin, PageValue page_end,
+00047                      RowValue  row_begin,  RowValue row_end,
+00048                      ColValue  col_begin,  ColValue col_end ) : 
+00049         my_pages(page_begin,page_end),
+00050         my_rows(row_begin,row_end),
+00051         my_cols(col_begin,col_end)
+00052     {
+00053     }
+00054 
+00055     blocked_range3d( PageValue page_begin, PageValue page_end, typename page_range_type::size_type page_grainsize, 
+00056                      RowValue  row_begin,  RowValue row_end,   typename row_range_type::size_type row_grainsize,
+00057                      ColValue  col_begin,  ColValue col_end,   typename col_range_type::size_type col_grainsize ) :  
+00058         my_pages(page_begin,page_end,page_grainsize),
+00059         my_rows(row_begin,row_end,row_grainsize),
+00060         my_cols(col_begin,col_end,col_grainsize)
+00061     {
+00062     }
+00063 
+00065     bool empty() const {
+00066         // Yes, it is a logical OR here, not AND.
+00067         return my_pages.empty() || my_rows.empty() || my_cols.empty();
+00068     }
+00069 
+00071     bool is_divisible() const {
+00072         return  my_pages.is_divisible() || my_rows.is_divisible() || my_cols.is_divisible();
+00073     }
+00074 
+00075     blocked_range3d( blocked_range3d& r, split ) : 
+00076         my_pages(r.my_pages),
+00077         my_rows(r.my_rows),
+00078         my_cols(r.my_cols)
+00079     {
+00080         if( my_pages.size()*double(my_rows.grainsize()) < my_rows.size()*double(my_pages.grainsize()) ) {
+00081             if ( my_rows.size()*double(my_cols.grainsize()) < my_cols.size()*double(my_rows.grainsize()) ) {
+00082                 my_cols.my_begin = col_range_type::do_split(r.my_cols);
+00083             } else {
+00084                 my_rows.my_begin = row_range_type::do_split(r.my_rows);
+00085             }
+00086         } else {
+00087             if ( my_pages.size()*double(my_cols.grainsize()) < my_cols.size()*double(my_pages.grainsize()) ) {
+00088                 my_cols.my_begin = col_range_type::do_split(r.my_cols);
+00089             } else {
+00090                     my_pages.my_begin = page_range_type::do_split(r.my_pages);
+00091             }
+00092         }
+00093     }
+00094 
+00096     const page_range_type& pages() const {return my_pages;}
+00097 
+00099     const row_range_type& rows() const {return my_rows;}
+00100 
+00102     const col_range_type& cols() const {return my_cols;}
+00103 
+00104 };
+00105 
+00106 } // namespace tbb 
+00107 
+00108 #endif /* __TBB_blocked_range3d_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00452.html b/src/tbb/doc/html/a00452.html new file mode 100644 index 0000000..f2a69b1 --- /dev/null +++ b/src/tbb/doc/html/a00452.html @@ -0,0 +1,153 @@ + + +cache_aligned_allocator.h Source File + + + + + + +

cache_aligned_allocator.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_cache_aligned_allocator_H
+00022 #define __TBB_cache_aligned_allocator_H
+00023 
+00024 #include <new>
+00025 #include "tbb_stddef.h"
+00026 #if __TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_CPP11_STD_FORWARD_BROKEN
+00027  #include <utility> // std::forward
+00028 #endif
+00029 
+00030 namespace tbb {
+00031 
+00033 namespace internal {
+00035 
+00036     size_t __TBB_EXPORTED_FUNC NFS_GetLineSize();
+00037 
+00039 
+00040     void* __TBB_EXPORTED_FUNC NFS_Allocate( size_t n_element, size_t element_size, void* hint );
+00041 
+00043 
+00045     void __TBB_EXPORTED_FUNC NFS_Free( void* );
+00046 }
+00048 
+00049 #if _MSC_VER && !defined(__INTEL_COMPILER)
+00050     // Workaround for erroneous "unreferenced parameter" warning in method destroy.
+00051     #pragma warning (push)
+00052     #pragma warning (disable: 4100)
+00053 #endif
+00054 
+00056 
+00059 template<typename T>
+00060 class cache_aligned_allocator {
+00061 public:
+00062     typedef typename internal::allocator_type<T>::value_type value_type;
+00063     typedef value_type* pointer;
+00064     typedef const value_type* const_pointer;
+00065     typedef value_type& reference;
+00066     typedef const value_type& const_reference;
+00067     typedef size_t size_type;
+00068     typedef ptrdiff_t difference_type;
+00069     template<typename U> struct rebind {
+00070         typedef cache_aligned_allocator<U> other;
+00071     };
+00072 
+00073     cache_aligned_allocator() throw() {}
+00074     cache_aligned_allocator( const cache_aligned_allocator& ) throw() {}
+00075     template<typename U> cache_aligned_allocator(const cache_aligned_allocator<U>&) throw() {}
+00076 
+00077     pointer address(reference x) const {return &x;}
+00078     const_pointer address(const_reference x) const {return &x;}
+00079     
+00081     pointer allocate( size_type n, const void* hint=0 ) {
+00082         // The "hint" argument is always ignored in NFS_Allocate thus const_cast shouldn't hurt
+00083         return pointer(internal::NFS_Allocate( n, sizeof(value_type), const_cast<void*>(hint) ));
+00084     }
+00085 
+00087     void deallocate( pointer p, size_type ) {
+00088         internal::NFS_Free(p);
+00089     }
+00090 
+00092     size_type max_size() const throw() {
+00093         return (~size_t(0)-internal::NFS_MaxLineSize)/sizeof(value_type);
+00094     }
+00095 
+00097 #if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT
+00098     template<typename... Args>
+00099     void construct(pointer p, Args&&... args)
+00100  #if __TBB_CPP11_STD_FORWARD_BROKEN
+00101         { ::new((void *)p) T((args)...); }
+00102  #else
+00103         { ::new((void *)p) T(std::forward<Args>(args)...); }
+00104  #endif
+00105 #else // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT
+00106     void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);}
+00107 #endif // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT
+00108 
+00110     void destroy( pointer p ) {p->~value_type();}
+00111 };
+00112 
+00113 #if _MSC_VER && !defined(__INTEL_COMPILER)
+00114     #pragma warning (pop)
+00115 #endif // warning 4100 is back
+00116 
+00118 
+00119 template<> 
+00120 class cache_aligned_allocator<void> {
+00121 public:
+00122     typedef void* pointer;
+00123     typedef const void* const_pointer;
+00124     typedef void value_type;
+00125     template<typename U> struct rebind {
+00126         typedef cache_aligned_allocator<U> other;
+00127     };
+00128 };
+00129 
+00130 template<typename T, typename U>
+00131 inline bool operator==( const cache_aligned_allocator<T>&, const cache_aligned_allocator<U>& ) {return true;}
+00132 
+00133 template<typename T, typename U>
+00134 inline bool operator!=( const cache_aligned_allocator<T>&, const cache_aligned_allocator<U>& ) {return false;}
+00135 
+00136 } // namespace tbb
+00137 
+00138 #endif /* __TBB_cache_aligned_allocator_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00454.html b/src/tbb/doc/html/a00454.html new file mode 100644 index 0000000..315bfc1 --- /dev/null +++ b/src/tbb/doc/html/a00454.html @@ -0,0 +1,98 @@ + + +combinable.h Source File + + + + + + +

combinable.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_combinable_H
+00022 #define __TBB_combinable_H
+00023 
+00024 #include "enumerable_thread_specific.h"
+00025 #include "cache_aligned_allocator.h"
+00026 
+00027 namespace tbb {
+00031 
+00032 
+00033     template <typename T>
+00034         class combinable {
+00035     private:
+00036         typedef typename tbb::cache_aligned_allocator<T> my_alloc;
+00037 
+00038         typedef typename tbb::enumerable_thread_specific<T, my_alloc, ets_no_key> my_ets_type;
+00039         my_ets_type my_ets; 
+00040  
+00041     public:
+00042 
+00043         combinable() { }
+00044 
+00045         template <typename finit>
+00046         combinable( finit _finit) : my_ets(_finit) { }
+00047 
+00049         ~combinable() { 
+00050         }
+00051 
+00052         combinable(const combinable& other) : my_ets(other.my_ets) { }
+00053 
+00054         combinable & operator=( const combinable & other) { my_ets = other.my_ets; return *this; }
+00055 
+00056         void clear() { my_ets.clear(); }
+00057 
+00058         T& local() { return my_ets.local(); }
+00059 
+00060         T& local(bool & exists) { return my_ets.local(exists); }
+00061 
+00062         // combine_func_t has signature T(T,T) or T(const T&, const T&)
+00063         template <typename combine_func_t>
+00064         T combine(combine_func_t f_combine) { return my_ets.combine(f_combine); }
+00065 
+00066         // combine_func_t has signature void(T) or void(const T&)
+00067         template <typename combine_func_t>
+00068         void combine_each(combine_func_t f_combine) { my_ets.combine_each(f_combine); }
+00069 
+00070     };
+00071 } // namespace tbb
+00072 #endif /* __TBB_combinable_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00455.html b/src/tbb/doc/html/a00455.html new file mode 100644 index 0000000..8c7af05 --- /dev/null +++ b/src/tbb/doc/html/a00455.html @@ -0,0 +1,1219 @@ + + +concurrent_hash_map.h Source File + + + + + + +

concurrent_hash_map.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_concurrent_hash_map_H
+00022 #define __TBB_concurrent_hash_map_H
+00023 
+00024 #include "tbb_stddef.h"
+00025 
+00026 #if !TBB_USE_EXCEPTIONS && _MSC_VER
+00027     // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers
+00028     #pragma warning (push)
+00029     #pragma warning (disable: 4530)
+00030 #endif
+00031 
+00032 #include <iterator>
+00033 #include <utility>      // Need std::pair
+00034 #include <cstring>      // Need std::memset
+00035 
+00036 #if !TBB_USE_EXCEPTIONS && _MSC_VER
+00037     #pragma warning (pop)
+00038 #endif
+00039 
+00040 #include "cache_aligned_allocator.h"
+00041 #include "tbb_allocator.h"
+00042 #include "spin_rw_mutex.h"
+00043 #include "atomic.h"
+00044 #include "aligned_space.h"
+00045 #include "tbb_exception.h"
+00046 #include "tbb_profiling.h"
+00047 #include "internal/_concurrent_unordered_impl.h" // Need tbb_hasher
+00048 #if TBB_USE_PERFORMANCE_WARNINGS || __TBB_STATISTICS
+00049 #include <typeinfo>
+00050 #endif
+00051 #if __TBB_STATISTICS
+00052 #include <stdio.h>
+00053 #endif
+00054 
+00055 namespace tbb {
+00056 
+00058 template<typename Key>
+00059 struct tbb_hash_compare {
+00060     static size_t hash( const Key& a ) { return tbb_hasher(a); }
+00061     static bool equal( const Key& a, const Key& b ) { return a == b; }
+00062 };
+00063 
+00064 namespace interface5 {
+00065 
+00066     template<typename Key, typename T, typename HashCompare = tbb_hash_compare<Key>, typename A = tbb_allocator<std::pair<Key, T> > >
+00067     class concurrent_hash_map;
+00068 
+00070     namespace internal {
+00071 
+00072 
+00074     typedef size_t hashcode_t;
+00076     struct hash_map_node_base : tbb::internal::no_copy {
+00078         typedef spin_rw_mutex mutex_t;
+00080         typedef mutex_t::scoped_lock scoped_t;
+00082         hash_map_node_base *next;
+00083         mutex_t mutex;
+00084     };
+00086     static hash_map_node_base *const rehash_req = reinterpret_cast<hash_map_node_base*>(size_t(3));
+00088     static hash_map_node_base *const empty_rehashed = reinterpret_cast<hash_map_node_base*>(size_t(0));
+00090     class hash_map_base {
+00091     public:
+00093         typedef size_t size_type;
+00095         typedef size_t hashcode_t;
+00097         typedef size_t segment_index_t;
+00099         typedef hash_map_node_base node_base;
+00101         struct bucket : tbb::internal::no_copy {
+00103             typedef spin_rw_mutex mutex_t;
+00105             typedef mutex_t::scoped_lock scoped_t;
+00106             mutex_t mutex;
+00107             node_base *node_list;
+00108         };
+00110         static size_type const embedded_block = 1;
+00112         static size_type const embedded_buckets = 1<<embedded_block;
+00114         static size_type const first_block = 8; //including embedded_block. perfect with bucket size 16, so the allocations are power of 4096
+00116         static size_type const pointers_per_table = sizeof(segment_index_t) * 8; // one segment per bit
+00118         typedef bucket *segment_ptr_t;
+00120         typedef segment_ptr_t segments_table_t[pointers_per_table];
+00122         atomic<hashcode_t> my_mask;
+00124         segments_table_t my_table;
+00126         atomic<size_type> my_size; // It must be in separate cache line from my_mask due to performance effects
+00128         bucket my_embedded_segment[embedded_buckets];
+00129 #if __TBB_STATISTICS
+00130         atomic<unsigned> my_info_resizes; // concurrent ones
+00131         mutable atomic<unsigned> my_info_restarts; // race collisions
+00132         atomic<unsigned> my_info_rehashes;  // invocations of rehash_bucket
+00133 #endif
+00135         hash_map_base() {
+00136             std::memset( this, 0, pointers_per_table*sizeof(segment_ptr_t) // 32*4=128   or 64*8=512
+00137                 + sizeof(my_size) + sizeof(my_mask)  // 4+4 or 8+8
+00138                 + embedded_buckets*sizeof(bucket) ); // n*8 or n*16
+00139             for( size_type i = 0; i < embedded_block; i++ ) // fill the table
+00140                 my_table[i] = my_embedded_segment + segment_base(i);
+00141             my_mask = embedded_buckets - 1;
+00142             __TBB_ASSERT( embedded_block <= first_block, "The first block number must include embedded blocks");
+00143 #if __TBB_STATISTICS
+00144             my_info_resizes = 0; // concurrent ones
+00145             my_info_restarts = 0; // race collisions
+00146             my_info_rehashes = 0;  // invocations of rehash_bucket
+00147 #endif
+00148         }
+00149 
+00151         static segment_index_t segment_index_of( size_type index ) {
+00152             return segment_index_t( __TBB_Log2( index|1 ) );
+00153         }
+00154 
+00156         static segment_index_t segment_base( segment_index_t k ) {
+00157             return (segment_index_t(1)<<k & ~segment_index_t(1));
+00158         }
+00159 
+00161         static size_type segment_size( segment_index_t k ) {
+00162             return size_type(1)<<k; // fake value for k==0
+00163         }
+00164 
+00166         static bool is_valid( void *ptr ) {
+00167             return reinterpret_cast<uintptr_t>(ptr) > uintptr_t(63);
+00168         }
+00169 
+00171         static void init_buckets( segment_ptr_t ptr, size_type sz, bool is_initial ) {
+00172             if( is_initial ) std::memset(ptr, 0, sz*sizeof(bucket) );
+00173             else for(size_type i = 0; i < sz; i++, ptr++) {
+00174                 *reinterpret_cast<intptr_t*>(&ptr->mutex) = 0;
+00175                 ptr->node_list = rehash_req;
+00176             }
+00177         }
+00178 
+00180         static void add_to_bucket( bucket *b, node_base *n ) {
+00181             __TBB_ASSERT(b->node_list != rehash_req, NULL);
+00182             n->next = b->node_list;
+00183             b->node_list = n; // its under lock and flag is set
+00184         }
+00185 
+00187         struct enable_segment_failsafe : tbb::internal::no_copy {
+00188             segment_ptr_t *my_segment_ptr;
+00189             enable_segment_failsafe(segments_table_t &table, segment_index_t k) : my_segment_ptr(&table[k]) {}
+00190             ~enable_segment_failsafe() {
+00191                 if( my_segment_ptr ) *my_segment_ptr = 0; // indicate no allocation in progress
+00192             }
+00193         };
+00194 
+00196         void enable_segment( segment_index_t k, bool is_initial = false ) {
+00197             __TBB_ASSERT( k, "Zero segment must be embedded" );
+00198             enable_segment_failsafe watchdog( my_table, k );
+00199             cache_aligned_allocator<bucket> alloc;
+00200             size_type sz;
+00201             __TBB_ASSERT( !is_valid(my_table[k]), "Wrong concurrent assignment");
+00202             if( k >= first_block ) {
+00203                 sz = segment_size( k );
+00204                 segment_ptr_t ptr = alloc.allocate( sz );
+00205                 init_buckets( ptr, sz, is_initial );
+00206                 itt_hide_store_word( my_table[k], ptr );
+00207                 sz <<= 1;// double it to get entire capacity of the container
+00208             } else { // the first block
+00209                 __TBB_ASSERT( k == embedded_block, "Wrong segment index" );
+00210                 sz = segment_size( first_block );
+00211                 segment_ptr_t ptr = alloc.allocate( sz - embedded_buckets );
+00212                 init_buckets( ptr, sz - embedded_buckets, is_initial );
+00213                 ptr -= segment_base(embedded_block);
+00214                 for(segment_index_t i = embedded_block; i < first_block; i++) // calc the offsets
+00215                     itt_hide_store_word( my_table[i], ptr + segment_base(i) );
+00216             }
+00217             itt_store_word_with_release( my_mask, sz-1 );
+00218             watchdog.my_segment_ptr = 0;
+00219         }
+00220 
+00222         bucket *get_bucket( hashcode_t h ) const throw() { // TODO: add throw() everywhere?
+00223             segment_index_t s = segment_index_of( h );
+00224             h -= segment_base(s);
+00225             segment_ptr_t seg = my_table[s];
+00226             __TBB_ASSERT( is_valid(seg), "hashcode must be cut by valid mask for allocated segments" );
+00227             return &seg[h];
+00228         }
+00229 
+00230         // internal serial rehashing helper
+00231         void mark_rehashed_levels( hashcode_t h ) throw () {
+00232             segment_index_t s = segment_index_of( h );
+00233             while( segment_ptr_t seg = my_table[++s] )
+00234                 if( seg[h].node_list == rehash_req ) {
+00235                     seg[h].node_list = empty_rehashed;
+00236                     mark_rehashed_levels( h + ((hashcode_t)1<<s) ); // optimized segment_base(s)
+00237                 }
+00238         }
+00239 
+00241         // Splitting into two functions should help inlining
+00242         inline bool check_mask_race( const hashcode_t h, hashcode_t &m ) const {
+00243             hashcode_t m_now, m_old = m;
+00244             m_now = (hashcode_t) itt_load_word_with_acquire( my_mask );
+00245             if( m_old != m_now )
+00246                 return check_rehashing_collision( h, m_old, m = m_now );
+00247             return false;
+00248         }
+00249 
+00251         bool check_rehashing_collision( const hashcode_t h, hashcode_t m_old, hashcode_t m ) const {
+00252             __TBB_ASSERT(m_old != m, NULL); // TODO?: m arg could be optimized out by passing h = h&m
+00253             if( (h & m_old) != (h & m) ) { // mask changed for this hashcode, rare event
+00254                 // condition above proves that 'h' has some other bits set beside 'm_old'
+00255                 // find next applicable mask after m_old    //TODO: look at bsl instruction
+00256                 for( ++m_old; !(h & m_old); m_old <<= 1 ) // at maximum few rounds depending on the first block size
+00257                     ;
+00258                 m_old = (m_old<<1) - 1; // get full mask from a bit
+00259                 __TBB_ASSERT((m_old&(m_old+1))==0 && m_old <= m, NULL);
+00260                 // check whether it is rehashing/ed
+00261                 if( itt_load_word_with_acquire(get_bucket(h & m_old)->node_list) != rehash_req )
+00262                 {
+00263 #if __TBB_STATISTICS
+00264                     my_info_restarts++; // race collisions
+00265 #endif
+00266                     return true;
+00267                 }
+00268             }
+00269             return false;
+00270         }
+00271 
+00273         segment_index_t insert_new_node( bucket *b, node_base *n, hashcode_t mask ) {
+00274             size_type sz = ++my_size; // prefix form is to enforce allocation after the first item inserted
+00275             add_to_bucket( b, n );
+00276             // check load factor
+00277             if( sz >= mask ) { // TODO: add custom load_factor
+00278                 segment_index_t new_seg = __TBB_Log2( mask+1 ); //optimized segment_index_of
+00279                 __TBB_ASSERT( is_valid(my_table[new_seg-1]), "new allocations must not publish new mask until segment has allocated");
+00280                 if( !itt_hide_load_word(my_table[new_seg])
+00281                   && __TBB_CompareAndSwapW(&my_table[new_seg], 2, 0) == 0 )
+00282                     return new_seg; // The value must be processed
+00283             }
+00284             return 0;
+00285         }
+00286 
+00288         void reserve(size_type buckets) {
+00289             if( !buckets-- ) return;
+00290             bool is_initial = !my_size;
+00291             for( size_type m = my_mask; buckets > m; m = my_mask )
+00292                 enable_segment( segment_index_of( m+1 ), is_initial );
+00293         }
+00295         void internal_swap(hash_map_base &table) {
+00296             std::swap(this->my_mask, table.my_mask);
+00297             std::swap(this->my_size, table.my_size);
+00298             for(size_type i = 0; i < embedded_buckets; i++)
+00299                 std::swap(this->my_embedded_segment[i].node_list, table.my_embedded_segment[i].node_list);
+00300             for(size_type i = embedded_block; i < pointers_per_table; i++)
+00301                 std::swap(this->my_table[i], table.my_table[i]);
+00302         }
+00303     };
+00304 
+00305     template<typename Iterator>
+00306     class hash_map_range;
+00307 
+00309 
+00311     template<typename Container, typename Value>
+00312     class hash_map_iterator
+00313         : public std::iterator<std::forward_iterator_tag,Value>
+00314     {
+00315         typedef Container map_type;
+00316         typedef typename Container::node node;
+00317         typedef hash_map_base::node_base node_base;
+00318         typedef hash_map_base::bucket bucket;
+00319 
+00320         template<typename C, typename T, typename U>
+00321         friend bool operator==( const hash_map_iterator<C,T>& i, const hash_map_iterator<C,U>& j );
+00322 
+00323         template<typename C, typename T, typename U>
+00324         friend bool operator!=( const hash_map_iterator<C,T>& i, const hash_map_iterator<C,U>& j );
+00325 
+00326         template<typename C, typename T, typename U>
+00327         friend ptrdiff_t operator-( const hash_map_iterator<C,T>& i, const hash_map_iterator<C,U>& j );
+00328 
+00329         template<typename C, typename U>
+00330         friend class hash_map_iterator;
+00331 
+00332         template<typename I>
+00333         friend class hash_map_range;
+00334 
+00335         void advance_to_next_bucket() { // TODO?: refactor to iterator_base class
+00336             size_t k = my_index+1;
+00337             while( my_bucket && k <= my_map->my_mask ) {
+00338                 // Following test uses 2's-complement wizardry
+00339                 if( k& (k-2) ) // not the beginning of a segment
+00340                     ++my_bucket;
+00341                 else my_bucket = my_map->get_bucket( k );
+00342                 my_node = static_cast<node*>( my_bucket->node_list );
+00343                 if( hash_map_base::is_valid(my_node) ) {
+00344                     my_index = k; return;
+00345                 }
+00346                 ++k;
+00347             }
+00348             my_bucket = 0; my_node = 0; my_index = k; // the end
+00349         }
+00350 #if !defined(_MSC_VER) || defined(__INTEL_COMPILER)
+00351         template<typename Key, typename T, typename HashCompare, typename A>
+00352         friend class interface5::concurrent_hash_map;
+00353 #else
+00354     public: // workaround
+00355 #endif
+00357         const Container *my_map;
+00358 
+00360         size_t my_index;
+00361 
+00363         const bucket *my_bucket;
+00364 
+00366         node *my_node;
+00367 
+00368         hash_map_iterator( const Container &map, size_t index, const bucket *b, node_base *n );
+00369 
+00370     public:
+00372         hash_map_iterator() {}
+00373         hash_map_iterator( const hash_map_iterator<Container,typename Container::value_type> &other ) :
+00374             my_map(other.my_map),
+00375             my_index(other.my_index),
+00376             my_bucket(other.my_bucket),
+00377             my_node(other.my_node)
+00378         {}
+00379         Value& operator*() const {
+00380             __TBB_ASSERT( hash_map_base::is_valid(my_node), "iterator uninitialized or at end of container?" );
+00381             return my_node->item;
+00382         }
+00383         Value* operator->() const {return &operator*();}
+00384         hash_map_iterator& operator++();
+00385 
+00387         hash_map_iterator operator++(int) {
+00388             hash_map_iterator old(*this);
+00389             operator++();
+00390             return old;
+00391         }
+00392     };
+00393 
+00394     template<typename Container, typename Value>
+00395     hash_map_iterator<Container,Value>::hash_map_iterator( const Container &map, size_t index, const bucket *b, node_base *n ) :
+00396         my_map(&map),
+00397         my_index(index),
+00398         my_bucket(b),
+00399         my_node( static_cast<node*>(n) )
+00400     {
+00401         if( b && !hash_map_base::is_valid(n) )
+00402             advance_to_next_bucket();
+00403     }
+00404 
+00405     template<typename Container, typename Value>
+00406     hash_map_iterator<Container,Value>& hash_map_iterator<Container,Value>::operator++() {
+00407         my_node = static_cast<node*>( my_node->next );
+00408         if( !my_node ) advance_to_next_bucket();
+00409         return *this;
+00410     }
+00411 
+00412     template<typename Container, typename T, typename U>
+00413     bool operator==( const hash_map_iterator<Container,T>& i, const hash_map_iterator<Container,U>& j ) {
+00414         return i.my_node == j.my_node && i.my_map == j.my_map;
+00415     }
+00416 
+00417     template<typename Container, typename T, typename U>
+00418     bool operator!=( const hash_map_iterator<Container,T>& i, const hash_map_iterator<Container,U>& j ) {
+00419         return i.my_node != j.my_node || i.my_map != j.my_map;
+00420     }
+00421 
+00423 
+00424     template<typename Iterator>
+00425     class hash_map_range {
+00426         typedef typename Iterator::map_type map_type;
+00427         Iterator my_begin;
+00428         Iterator my_end;
+00429         mutable Iterator my_midpoint;
+00430         size_t my_grainsize;
+00432         void set_midpoint() const;
+00433         template<typename U> friend class hash_map_range;
+00434     public:
+00436         typedef std::size_t size_type;
+00437         typedef typename Iterator::value_type value_type;
+00438         typedef typename Iterator::reference reference;
+00439         typedef typename Iterator::difference_type difference_type;
+00440         typedef Iterator iterator;
+00441 
+00443         bool empty() const {return my_begin==my_end;}
+00444 
+00446         bool is_divisible() const {
+00447             return my_midpoint!=my_end;
+00448         }
+00450         hash_map_range( hash_map_range& r, split ) :
+00451             my_end(r.my_end),
+00452             my_grainsize(r.my_grainsize)
+00453         {
+00454             r.my_end = my_begin = r.my_midpoint;
+00455             __TBB_ASSERT( !empty(), "Splitting despite the range is not divisible" );
+00456             __TBB_ASSERT( !r.empty(), "Splitting despite the range is not divisible" );
+00457             set_midpoint();
+00458             r.set_midpoint();
+00459         }
+00461         template<typename U>
+00462         hash_map_range( hash_map_range<U>& r) :
+00463             my_begin(r.my_begin),
+00464             my_end(r.my_end),
+00465             my_midpoint(r.my_midpoint),
+00466             my_grainsize(r.my_grainsize)
+00467         {}
+00468 #if TBB_DEPRECATED
+00470         hash_map_range( const Iterator& begin_, const Iterator& end_, size_type grainsize_ = 1 ) :
+00471             my_begin(begin_),
+00472             my_end(end_),
+00473             my_grainsize(grainsize_)
+00474         {
+00475             if(!my_end.my_index && !my_end.my_bucket) // end
+00476                 my_end.my_index = my_end.my_map->my_mask + 1;
+00477             set_midpoint();
+00478             __TBB_ASSERT( grainsize_>0, "grainsize must be positive" );
+00479         }
+00480 #endif
+00482         hash_map_range( const map_type &map, size_type grainsize_ = 1 ) :
+00483             my_begin( Iterator( map, 0, map.my_embedded_segment, map.my_embedded_segment->node_list ) ),
+00484             my_end( Iterator( map, map.my_mask + 1, 0, 0 ) ),
+00485             my_grainsize( grainsize_ )
+00486         {
+00487             __TBB_ASSERT( grainsize_>0, "grainsize must be positive" );
+00488             set_midpoint();
+00489         }
+00490         const Iterator& begin() const {return my_begin;}
+00491         const Iterator& end() const {return my_end;}
+00493         size_type grainsize() const {return my_grainsize;}
+00494     };
+00495 
+00496     template<typename Iterator>
+00497     void hash_map_range<Iterator>::set_midpoint() const {
+00498         // Split by groups of nodes
+00499         size_t m = my_end.my_index-my_begin.my_index;
+00500         if( m > my_grainsize ) {
+00501             m = my_begin.my_index + m/2u;
+00502             hash_map_base::bucket *b = my_begin.my_map->get_bucket(m);
+00503             my_midpoint = Iterator(*my_begin.my_map,m,b,b->node_list);
+00504         } else {
+00505             my_midpoint = my_end;
+00506         }
+00507         __TBB_ASSERT( my_begin.my_index <= my_midpoint.my_index,
+00508             "my_begin is after my_midpoint" );
+00509         __TBB_ASSERT( my_midpoint.my_index <= my_end.my_index,
+00510             "my_midpoint is after my_end" );
+00511         __TBB_ASSERT( my_begin != my_midpoint || my_begin == my_end,
+00512             "[my_begin, my_midpoint) range should not be empty" );
+00513     }
+00514 
+00515     } // internal
+00517 
+00519 
+00548 template<typename Key, typename T, typename HashCompare, typename Allocator>
+00549 class concurrent_hash_map : protected internal::hash_map_base {
+00550     template<typename Container, typename Value>
+00551     friend class internal::hash_map_iterator;
+00552 
+00553     template<typename I>
+00554     friend class internal::hash_map_range;
+00555 
+00556 public:
+00557     typedef Key key_type;
+00558     typedef T mapped_type;
+00559     typedef std::pair<const Key,T> value_type;
+00560     typedef hash_map_base::size_type size_type;
+00561     typedef ptrdiff_t difference_type;
+00562     typedef value_type *pointer;
+00563     typedef const value_type *const_pointer;
+00564     typedef value_type &reference;
+00565     typedef const value_type &const_reference;
+00566     typedef internal::hash_map_iterator<concurrent_hash_map,value_type> iterator;
+00567     typedef internal::hash_map_iterator<concurrent_hash_map,const value_type> const_iterator;
+00568     typedef internal::hash_map_range<iterator> range_type;
+00569     typedef internal::hash_map_range<const_iterator> const_range_type;
+00570     typedef Allocator allocator_type;
+00571 
+00572 protected:
+00573     friend class const_accessor;
+00574     struct node;
+00575     typedef typename Allocator::template rebind<node>::other node_allocator_type;
+00576     node_allocator_type my_allocator;
+00577     HashCompare my_hash_compare;
+00578 
+00579     struct node : public node_base {
+00580         value_type item;
+00581         node( const Key &key ) : item(key, T()) {}
+00582         node( const Key &key, const T &t ) : item(key, t) {}
+00583         // exception-safe allocation, see C++ Standard 2003, clause 5.3.4p17
+00584         void *operator new( size_t /*size*/, node_allocator_type &a ) {
+00585             void *ptr = a.allocate(1);
+00586             if(!ptr)
+00587                 tbb::internal::throw_exception(tbb::internal::eid_bad_alloc);
+00588             return ptr;
+00589         }
+00590         // match placement-new form above to be called if exception thrown in constructor
+00591         void operator delete( void *ptr, node_allocator_type &a ) {return a.deallocate(static_cast<node*>(ptr),1); }
+00592     };
+00593 
+00594     void delete_node( node_base *n ) {
+00595         my_allocator.destroy( static_cast<node*>(n) );
+00596         my_allocator.deallocate( static_cast<node*>(n), 1);
+00597     }
+00598 
+00599     node *search_bucket( const key_type &key, bucket *b ) const {
+00600         node *n = static_cast<node*>( b->node_list );
+00601         while( is_valid(n) && !my_hash_compare.equal(key, n->item.first) )
+00602             n = static_cast<node*>( n->next );
+00603         __TBB_ASSERT(n != internal::rehash_req, "Search can be executed only for rehashed bucket");
+00604         return n;
+00605     }
+00606 
+00608     class bucket_accessor : public bucket::scoped_t {
+00609         bucket *my_b;
+00610     public:
+00611         bucket_accessor( concurrent_hash_map *base, const hashcode_t h, bool writer = false ) { acquire( base, h, writer ); }
+00613         inline void acquire( concurrent_hash_map *base, const hashcode_t h, bool writer = false ) {
+00614             my_b = base->get_bucket( h );
+00615             // TODO: actually, notification is unnecessary here, just hiding double-check
+00616             if( itt_load_word_with_acquire(my_b->node_list) == internal::rehash_req
+00617                 && try_acquire( my_b->mutex, /*write=*/true ) )
+00618             {
+00619                 if( my_b->node_list == internal::rehash_req ) base->rehash_bucket( my_b, h ); //recursive rehashing
+00620             }
+00621             else bucket::scoped_t::acquire( my_b->mutex, writer );
+00622             __TBB_ASSERT( my_b->node_list != internal::rehash_req, NULL);
+00623         }
+00625         bool is_writer() { return bucket::scoped_t::is_writer; }
+00627         bucket *operator() () { return my_b; }
+00628     };
+00629 
+00630     // TODO refactor to hash_base
+00631     void rehash_bucket( bucket *b_new, const hashcode_t h ) {
+00632         __TBB_ASSERT( *(intptr_t*)(&b_new->mutex), "b_new must be locked (for write)");
+00633         __TBB_ASSERT( h > 1, "The lowermost buckets can't be rehashed" );
+00634         __TBB_store_with_release(b_new->node_list, internal::empty_rehashed); // mark rehashed
+00635         hashcode_t mask = ( 1u<<__TBB_Log2( h ) ) - 1; // get parent mask from the topmost bit
+00636 #if __TBB_STATISTICS
+00637         my_info_rehashes++; // invocations of rehash_bucket
+00638 #endif
+00639 
+00640         bucket_accessor b_old( this, h & mask );
+00641 
+00642         mask = (mask<<1) | 1; // get full mask for new bucket
+00643         __TBB_ASSERT( (mask&(mask+1))==0 && (h & mask) == h, NULL );
+00644     restart:
+00645         for( node_base **p = &b_old()->node_list, *n = __TBB_load_with_acquire(*p); is_valid(n); n = *p ) {
+00646             hashcode_t c = my_hash_compare.hash( static_cast<node*>(n)->item.first );
+00647 #if TBB_USE_ASSERT
+00648             hashcode_t bmask = h & (mask>>1);
+00649             bmask = bmask==0? 1 : ( 1u<<(__TBB_Log2( bmask )+1 ) ) - 1; // minimal mask of parent bucket
+00650             __TBB_ASSERT( (c & bmask) == (h & bmask), "hash() function changed for key in table" );
+00651 #endif
+00652             if( (c & mask) == h ) {
+00653                 if( !b_old.is_writer() )
+00654                     if( !b_old.upgrade_to_writer() ) {
+00655                         goto restart; // node ptr can be invalid due to concurrent erase
+00656                     }
+00657                 *p = n->next; // exclude from b_old
+00658                 add_to_bucket( b_new, n );
+00659             } else p = &n->next; // iterate to next item
+00660         }
+00661     }
+00662 
+00663 public:
+00664 
+00665     class accessor;
+00667     class const_accessor : private node::scoped_t /*which derived from no_copy*/ {
+00668         friend class concurrent_hash_map<Key,T,HashCompare,Allocator>;
+00669         friend class accessor;
+00670     public:
+00672         typedef const typename concurrent_hash_map::value_type value_type;
+00673 
+00675         bool empty() const {return !my_node;}
+00676 
+00678         void release() {
+00679             if( my_node ) {
+00680                 node::scoped_t::release();
+00681                 my_node = 0;
+00682             }
+00683         }
+00684 
+00686         const_reference operator*() const {
+00687             __TBB_ASSERT( my_node, "attempt to dereference empty accessor" );
+00688             return my_node->item;
+00689         }
+00690 
+00692         const_pointer operator->() const {
+00693             return &operator*();
+00694         }
+00695 
+00697         const_accessor() : my_node(NULL) {}
+00698 
+00700         ~const_accessor() {
+00701             my_node = NULL; // scoped lock's release() is called in its destructor
+00702         }
+00703     protected:
+00704         bool is_writer() { return node::scoped_t::is_writer; }
+00705         node *my_node;
+00706         hashcode_t my_hash;
+00707     };
+00708 
+00710     class accessor: public const_accessor {
+00711     public:
+00713         typedef typename concurrent_hash_map::value_type value_type;
+00714 
+00716         reference operator*() const {
+00717             __TBB_ASSERT( this->my_node, "attempt to dereference empty accessor" );
+00718             return this->my_node->item;
+00719         }
+00720 
+00722         pointer operator->() const {
+00723             return &operator*();
+00724         }
+00725     };
+00726 
+00728     concurrent_hash_map(const allocator_type &a = allocator_type())
+00729         : internal::hash_map_base(), my_allocator(a)
+00730     {}
+00731 
+00733     concurrent_hash_map(size_type n, const allocator_type &a = allocator_type())
+00734         : my_allocator(a)
+00735     {
+00736         reserve( n );
+00737     }
+00738 
+00740     concurrent_hash_map( const concurrent_hash_map& table, const allocator_type &a = allocator_type())
+00741         : internal::hash_map_base(), my_allocator(a)
+00742     {
+00743         internal_copy(table);
+00744     }
+00745 
+00747     template<typename I>
+00748     concurrent_hash_map(I first, I last, const allocator_type &a = allocator_type())
+00749         : my_allocator(a)
+00750     {
+00751         reserve( std::distance(first, last) ); // TODO: load_factor?
+00752         internal_copy(first, last);
+00753     }
+00754 
+00756     concurrent_hash_map& operator=( const concurrent_hash_map& table ) {
+00757         if( this!=&table ) {
+00758             clear();
+00759             internal_copy(table);
+00760         }
+00761         return *this;
+00762     }
+00763 
+00764 
+00766 
+00768     void rehash(size_type n = 0);
+00769 
+00771     void clear();
+00772 
+00774     ~concurrent_hash_map() { clear(); }
+00775 
+00776     //------------------------------------------------------------------------
+00777     // Parallel algorithm support
+00778     //------------------------------------------------------------------------
+00779     range_type range( size_type grainsize=1 ) {
+00780         return range_type( *this, grainsize );
+00781     }
+00782     const_range_type range( size_type grainsize=1 ) const {
+00783         return const_range_type( *this, grainsize );
+00784     }
+00785 
+00786     //------------------------------------------------------------------------
+00787     // STL support - not thread-safe methods
+00788     //------------------------------------------------------------------------
+00789     iterator begin() {return iterator(*this,0,my_embedded_segment,my_embedded_segment->node_list);}
+00790     iterator end() {return iterator(*this,0,0,0);}
+00791     const_iterator begin() const {return const_iterator(*this,0,my_embedded_segment,my_embedded_segment->node_list);}
+00792     const_iterator end() const {return const_iterator(*this,0,0,0);}
+00793     std::pair<iterator, iterator> equal_range( const Key& key ) { return internal_equal_range(key, end()); }
+00794     std::pair<const_iterator, const_iterator> equal_range( const Key& key ) const { return internal_equal_range(key, end()); }
+00795 
+00797     size_type size() const { return my_size; }
+00798 
+00800     bool empty() const { return my_size == 0; }
+00801 
+00803     size_type max_size() const {return (~size_type(0))/sizeof(node);}
+00804 
+00806     size_type bucket_count() const { return my_mask+1; }
+00807 
+00809     allocator_type get_allocator() const { return this->my_allocator; }
+00810 
+00812     void swap(concurrent_hash_map &table);
+00813 
+00814     //------------------------------------------------------------------------
+00815     // concurrent map operations
+00816     //------------------------------------------------------------------------
+00817 
+00819     size_type count( const Key &key ) const {
+00820         return const_cast<concurrent_hash_map*>(this)->lookup(/*insert*/false, key, NULL, NULL, /*write=*/false );
+00821     }
+00822 
+00824 
+00825     bool find( const_accessor &result, const Key &key ) const {
+00826         result.release();
+00827         return const_cast<concurrent_hash_map*>(this)->lookup(/*insert*/false, key, NULL, &result, /*write=*/false );
+00828     }
+00829 
+00831 
+00832     bool find( accessor &result, const Key &key ) {
+00833         result.release();
+00834         return lookup(/*insert*/false, key, NULL, &result, /*write=*/true );
+00835     }
+00836 
+00838 
+00839     bool insert( const_accessor &result, const Key &key ) {
+00840         result.release();
+00841         return lookup(/*insert*/true, key, NULL, &result, /*write=*/false );
+00842     }
+00843 
+00845 
+00846     bool insert( accessor &result, const Key &key ) {
+00847         result.release();
+00848         return lookup(/*insert*/true, key, NULL, &result, /*write=*/true );
+00849     }
+00850 
+00852 
+00853     bool insert( const_accessor &result, const value_type &value ) {
+00854         result.release();
+00855         return lookup(/*insert*/true, value.first, &value.second, &result, /*write=*/false );
+00856     }
+00857 
+00859 
+00860     bool insert( accessor &result, const value_type &value ) {
+00861         result.release();
+00862         return lookup(/*insert*/true, value.first, &value.second, &result, /*write=*/true );
+00863     }
+00864 
+00866 
+00867     bool insert( const value_type &value ) {
+00868         return lookup(/*insert*/true, value.first, &value.second, NULL, /*write=*/false );
+00869     }
+00870 
+00872     template<typename I>
+00873     void insert(I first, I last) {
+00874         for(; first != last; ++first)
+00875             insert( *first );
+00876     }
+00877 
+00879 
+00880     bool erase( const Key& key );
+00881 
+00883 
+00884     bool erase( const_accessor& item_accessor ) {
+00885         return exclude( item_accessor );
+00886     }
+00887 
+00889 
+00890     bool erase( accessor& item_accessor ) {
+00891         return exclude( item_accessor );
+00892     }
+00893 
+00894 protected:
+00896     bool lookup( bool op_insert, const Key &key, const T *t, const_accessor *result, bool write );
+00897 
+00899     bool exclude( const_accessor &item_accessor );
+00900 
+00902     template<typename I>
+00903     std::pair<I, I> internal_equal_range( const Key& key, I end ) const;
+00904 
+00906     void internal_copy( const concurrent_hash_map& source );
+00907 
+00908     template<typename I>
+00909     void internal_copy(I first, I last);
+00910 
+00912 
+00914     const_pointer internal_fast_find( const Key& key ) const {
+00915         hashcode_t h = my_hash_compare.hash( key );
+00916         hashcode_t m = (hashcode_t) itt_load_word_with_acquire( my_mask );
+00917         node *n;
+00918     restart:
+00919         __TBB_ASSERT((m&(m+1))==0, NULL);
+00920         bucket *b = get_bucket( h & m );
+00921         // TODO: actually, notification is unnecessary here, just hiding double-check
+00922         if( itt_load_word_with_acquire(b->node_list) == internal::rehash_req )
+00923         {
+00924             bucket::scoped_t lock;
+00925             if( lock.try_acquire( b->mutex, /*write=*/true ) ) {
+00926                 if( b->node_list == internal::rehash_req)
+00927                     const_cast<concurrent_hash_map*>(this)->rehash_bucket( b, h & m ); //recursive rehashing
+00928             }
+00929             else lock.acquire( b->mutex, /*write=*/false );
+00930             __TBB_ASSERT(b->node_list!=internal::rehash_req,NULL);
+00931         }
+00932         n = search_bucket( key, b );
+00933         if( n )
+00934             return &n->item;
+00935         else if( check_mask_race( h, m ) )
+00936             goto restart;
+00937         return 0;
+00938     }
+00939 };
+00940 
+00941 #if _MSC_VER && !defined(__INTEL_COMPILER)
+00942     // Suppress "conditional expression is constant" warning.
+00943     #pragma warning( push )
+00944     #pragma warning( disable: 4127 )
+00945 #endif
+00946 
+00947 template<typename Key, typename T, typename HashCompare, typename A>
+00948 bool concurrent_hash_map<Key,T,HashCompare,A>::lookup( bool op_insert, const Key &key, const T *t, const_accessor *result, bool write ) {
+00949     __TBB_ASSERT( !result || !result->my_node, NULL );
+00950     bool return_value;
+00951     hashcode_t const h = my_hash_compare.hash( key );
+00952     hashcode_t m = (hashcode_t) itt_load_word_with_acquire( my_mask );
+00953     segment_index_t grow_segment = 0;
+00954     node *n, *tmp_n = 0;
+00955     restart:
+00956     {//lock scope
+00957         __TBB_ASSERT((m&(m+1))==0, NULL);
+00958         return_value = false;
+00959         // get bucket
+00960         bucket_accessor b( this, h & m );
+00961 
+00962         // find a node
+00963         n = search_bucket( key, b() );
+00964         if( op_insert ) {
+00965             // [opt] insert a key
+00966             if( !n ) {
+00967                 if( !tmp_n ) {
+00968                     if(t) tmp_n = new( my_allocator ) node(key, *t);
+00969                     else  tmp_n = new( my_allocator ) node(key);
+00970                 }
+00971                 if( !b.is_writer() && !b.upgrade_to_writer() ) { // TODO: improved insertion
+00972                     // Rerun search_list, in case another thread inserted the item during the upgrade.
+00973                     n = search_bucket( key, b() );
+00974                     if( is_valid(n) ) { // unfortunately, it did
+00975                         b.downgrade_to_reader();
+00976                         goto exists;
+00977                     }
+00978                 }
+00979                 if( check_mask_race(h, m) )
+00980                     goto restart; // b.release() is done in ~b().
+00981                 // insert and set flag to grow the container
+00982                 grow_segment = insert_new_node( b(), n = tmp_n, m );
+00983                 tmp_n = 0;
+00984                 return_value = true;
+00985             }
+00986         } else { // find or count
+00987             if( !n ) {
+00988                 if( check_mask_race( h, m ) )
+00989                     goto restart; // b.release() is done in ~b(). TODO: replace by continue
+00990                 return false;
+00991             }
+00992             return_value = true;
+00993         }
+00994     exists:
+00995         if( !result ) goto check_growth;
+00996         // TODO: the following seems as generic/regular operation
+00997         // acquire the item
+00998         if( !result->try_acquire( n->mutex, write ) ) {
+00999             // we are unlucky, prepare for longer wait
+01000             tbb::internal::atomic_backoff trials;
+01001             do {
+01002                 if( !trials.bounded_pause() ) {
+01003                     // the wait takes really long, restart the operation
+01004                     b.release();
+01005                     __TBB_ASSERT( !op_insert || !return_value, "Can't acquire new item in locked bucket?" );
+01006                     __TBB_Yield();
+01007                     m = (hashcode_t) itt_load_word_with_acquire( my_mask );
+01008                     goto restart;
+01009                 }
+01010             } while( !result->try_acquire( n->mutex, write ) );
+01011         }
+01012     }//lock scope
+01013     result->my_node = n;
+01014     result->my_hash = h;
+01015 check_growth:
+01016     // [opt] grow the container
+01017     if( grow_segment ) {
+01018 #if __TBB_STATISTICS
+01019         my_info_resizes++; // concurrent ones
+01020 #endif
+01021         enable_segment( grow_segment );
+01022     }
+01023     if( tmp_n ) // if op_insert only
+01024         delete_node( tmp_n );
+01025     return return_value;
+01026 }
+01027 
+01028 template<typename Key, typename T, typename HashCompare, typename A>
+01029 template<typename I>
+01030 std::pair<I, I> concurrent_hash_map<Key,T,HashCompare,A>::internal_equal_range( const Key& key, I end_ ) const {
+01031     hashcode_t h = my_hash_compare.hash( key );
+01032     hashcode_t m = my_mask;
+01033     __TBB_ASSERT((m&(m+1))==0, NULL);
+01034     h &= m;
+01035     bucket *b = get_bucket( h );
+01036     while( b->node_list == internal::rehash_req ) {
+01037         m = ( 1u<<__TBB_Log2( h ) ) - 1; // get parent mask from the topmost bit
+01038         b = get_bucket( h &= m );
+01039     }
+01040     node *n = search_bucket( key, b );
+01041     if( !n )
+01042         return std::make_pair(end_, end_);
+01043     iterator lower(*this, h, b, n), upper(lower);
+01044     return std::make_pair(lower, ++upper);
+01045 }
+01046 
+01047 template<typename Key, typename T, typename HashCompare, typename A>
+01048 bool concurrent_hash_map<Key,T,HashCompare,A>::exclude( const_accessor &item_accessor ) {
+01049     __TBB_ASSERT( item_accessor.my_node, NULL );
+01050     node_base *const n = item_accessor.my_node;
+01051     hashcode_t const h = item_accessor.my_hash;
+01052     hashcode_t m = (hashcode_t) itt_load_word_with_acquire( my_mask );
+01053     do {
+01054         // get bucket
+01055         bucket_accessor b( this, h & m, /*writer=*/true );
+01056         node_base **p = &b()->node_list;
+01057         while( *p && *p != n )
+01058             p = &(*p)->next;
+01059         if( !*p ) { // someone else was first
+01060             if( check_mask_race( h, m ) )
+01061                 continue;
+01062             item_accessor.release();
+01063             return false;
+01064         }
+01065         __TBB_ASSERT( *p == n, NULL );
+01066         *p = n->next; // remove from container
+01067         my_size--;
+01068         break;
+01069     } while(true);
+01070     if( !item_accessor.is_writer() ) // need to get exclusive lock
+01071         item_accessor.upgrade_to_writer(); // return value means nothing here
+01072     item_accessor.release();
+01073     delete_node( n ); // Only one thread can delete it
+01074     return true;
+01075 }
+01076 
+01077 template<typename Key, typename T, typename HashCompare, typename A>
+01078 bool concurrent_hash_map<Key,T,HashCompare,A>::erase( const Key &key ) {
+01079     node_base *n;
+01080     hashcode_t const h = my_hash_compare.hash( key );
+01081     hashcode_t m = (hashcode_t) itt_load_word_with_acquire( my_mask );
+01082 restart:
+01083     {//lock scope
+01084         // get bucket
+01085         bucket_accessor b( this, h & m );
+01086     search:
+01087         node_base **p = &b()->node_list;
+01088         n = *p;
+01089         while( is_valid(n) && !my_hash_compare.equal(key, static_cast<node*>(n)->item.first ) ) {
+01090             p = &n->next;
+01091             n = *p;
+01092         }
+01093         if( !n ) { // not found, but mask could be changed
+01094             if( check_mask_race( h, m ) )
+01095                 goto restart;
+01096             return false;
+01097         }
+01098         else if( !b.is_writer() && !b.upgrade_to_writer() ) {
+01099             if( check_mask_race( h, m ) ) // contended upgrade, check mask
+01100                 goto restart;
+01101             goto search;
+01102         }
+01103         *p = n->next;
+01104         my_size--;
+01105     }
+01106     {
+01107         typename node::scoped_t item_locker( n->mutex, /*write=*/true );
+01108     }
+01109     // note: there should be no threads pretending to acquire this mutex again, do not try to upgrade const_accessor!
+01110     delete_node( n ); // Only one thread can delete it due to write lock on the bucket
+01111     return true;
+01112 }
+01113 
+01114 template<typename Key, typename T, typename HashCompare, typename A>
+01115 void concurrent_hash_map<Key,T,HashCompare,A>::swap(concurrent_hash_map<Key,T,HashCompare,A> &table) {
+01116     std::swap(this->my_allocator, table.my_allocator);
+01117     std::swap(this->my_hash_compare, table.my_hash_compare);
+01118     internal_swap(table);
+01119 }
+01120 
+01121 template<typename Key, typename T, typename HashCompare, typename A>
+01122 void concurrent_hash_map<Key,T,HashCompare,A>::rehash(size_type sz) {
+01123     reserve( sz ); // TODO: add reduction of number of buckets as well
+01124     hashcode_t mask = my_mask;
+01125     hashcode_t b = (mask+1)>>1; // size or first index of the last segment
+01126     __TBB_ASSERT((b&(b-1))==0, NULL); // zero or power of 2
+01127     bucket *bp = get_bucket( b ); // only the last segment should be scanned for rehashing
+01128     for(; b <= mask; b++, bp++ ) {
+01129         node_base *n = bp->node_list;
+01130         __TBB_ASSERT( is_valid(n) || n == internal::empty_rehashed || n == internal::rehash_req, "Broken internal structure" );
+01131         __TBB_ASSERT( *reinterpret_cast<intptr_t*>(&bp->mutex) == 0, "concurrent or unexpectedly terminated operation during rehash() execution" );
+01132         if( n == internal::rehash_req ) { // rehash bucket, conditional because rehashing of a previous bucket may affect this one
+01133             hashcode_t h = b; bucket *b_old = bp;
+01134             do {
+01135                 __TBB_ASSERT( h > 1, "The lowermost buckets can't be rehashed" );
+01136                 hashcode_t m = ( 1u<<__TBB_Log2( h ) ) - 1; // get parent mask from the topmost bit
+01137                 b_old = get_bucket( h &= m );
+01138             } while( b_old->node_list == internal::rehash_req );
+01139             // now h - is index of the root rehashed bucket b_old
+01140             mark_rehashed_levels( h ); // mark all non-rehashed children recursively across all segments
+01141             for( node_base **p = &b_old->node_list, *q = *p; is_valid(q); q = *p ) {
+01142                 hashcode_t c = my_hash_compare.hash( static_cast<node*>(q)->item.first );
+01143                 if( (c & mask) != h ) { // should be rehashed
+01144                     *p = q->next; // exclude from b_old
+01145                     bucket *b_new = get_bucket( c & mask );
+01146                     __TBB_ASSERT( b_new->node_list != internal::rehash_req, "hash() function changed for key in table or internal error" );
+01147                     add_to_bucket( b_new, q );
+01148                 } else p = &q->next; // iterate to next item
+01149             }
+01150         }
+01151     }
+01152 #if TBB_USE_PERFORMANCE_WARNINGS
+01153     int current_size = int(my_size), buckets = int(mask)+1, empty_buckets = 0, overpopulated_buckets = 0; // usage statistics
+01154     static bool reported = false;
+01155 #endif
+01156 #if TBB_USE_ASSERT || TBB_USE_PERFORMANCE_WARNINGS
+01157     for( b = 0; b <= mask; b++ ) {// only last segment should be scanned for rehashing
+01158         if( b & (b-2) ) ++bp; // not the beginning of a segment
+01159         else bp = get_bucket( b );
+01160         node_base *n = bp->node_list;
+01161         __TBB_ASSERT( *reinterpret_cast<intptr_t*>(&bp->mutex) == 0, "concurrent or unexpectedly terminated operation during rehash() execution" );
+01162         __TBB_ASSERT( is_valid(n) || n == internal::empty_rehashed, "Broken internal structure" );
+01163 #if TBB_USE_PERFORMANCE_WARNINGS
+01164         if( n == internal::empty_rehashed ) empty_buckets++;
+01165         else if( n->next ) overpopulated_buckets++;
+01166 #endif
+01167 #if TBB_USE_ASSERT
+01168         for( ; is_valid(n); n = n->next ) {
+01169             hashcode_t h = my_hash_compare.hash( static_cast<node*>(n)->item.first ) & mask;
+01170             __TBB_ASSERT( h == b, "hash() function changed for key in table or internal error" );
+01171         }
+01172 #endif
+01173     }
+01174 #endif // TBB_USE_ASSERT || TBB_USE_PERFORMANCE_WARNINGS
+01175 #if TBB_USE_PERFORMANCE_WARNINGS
+01176     if( buckets > current_size) empty_buckets -= buckets - current_size;
+01177     else overpopulated_buckets -= current_size - buckets; // TODO: load_factor?
+01178     if( !reported && buckets >= 512 && ( 2*empty_buckets > current_size || 2*overpopulated_buckets > current_size ) ) {
+01179         tbb::internal::runtime_warning(
+01180             "Performance is not optimal because the hash function produces bad randomness in lower bits in %s.\nSize: %d  Empties: %d  Overlaps: %d",
+01181             typeid(*this).name(), current_size, empty_buckets, overpopulated_buckets );
+01182         reported = true;
+01183     }
+01184 #endif
+01185 }
+01186 
+01187 template<typename Key, typename T, typename HashCompare, typename A>
+01188 void concurrent_hash_map<Key,T,HashCompare,A>::clear() {
+01189     hashcode_t m = my_mask;
+01190     __TBB_ASSERT((m&(m+1))==0, NULL);
+01191 #if TBB_USE_ASSERT || TBB_USE_PERFORMANCE_WARNINGS || __TBB_STATISTICS
+01192 #if TBB_USE_PERFORMANCE_WARNINGS || __TBB_STATISTICS
+01193     int current_size = int(my_size), buckets = int(m)+1, empty_buckets = 0, overpopulated_buckets = 0; // usage statistics
+01194     static bool reported = false;
+01195 #endif
+01196     bucket *bp = 0;
+01197     // check consistency
+01198     for( segment_index_t b = 0; b <= m; b++ ) {
+01199         if( b & (b-2) ) ++bp; // not the beginning of a segment
+01200         else bp = get_bucket( b );
+01201         node_base *n = bp->node_list;
+01202         __TBB_ASSERT( is_valid(n) || n == internal::empty_rehashed || n == internal::rehash_req, "Broken internal structure" );
+01203         __TBB_ASSERT( *reinterpret_cast<intptr_t*>(&bp->mutex) == 0, "concurrent or unexpectedly terminated operation during clear() execution" );
+01204 #if TBB_USE_PERFORMANCE_WARNINGS || __TBB_STATISTICS
+01205         if( n == internal::empty_rehashed ) empty_buckets++;
+01206         else if( n == internal::rehash_req ) buckets--;
+01207         else if( n->next ) overpopulated_buckets++;
+01208 #endif
+01209 #if __TBB_EXTRA_DEBUG
+01210         for(; is_valid(n); n = n->next ) {
+01211             hashcode_t h = my_hash_compare.hash( static_cast<node*>(n)->item.first );
+01212             h &= m;
+01213             __TBB_ASSERT( h == b || get_bucket(h)->node_list == internal::rehash_req, "hash() function changed for key in table or internal error" );
+01214         }
+01215 #endif
+01216     }
+01217 #if TBB_USE_PERFORMANCE_WARNINGS || __TBB_STATISTICS
+01218 #if __TBB_STATISTICS
+01219     printf( "items=%d buckets: capacity=%d rehashed=%d empty=%d overpopulated=%d"
+01220         " concurrent: resizes=%u rehashes=%u restarts=%u\n",
+01221         current_size, int(m+1), buckets, empty_buckets, overpopulated_buckets,
+01222         unsigned(my_info_resizes), unsigned(my_info_rehashes), unsigned(my_info_restarts) );
+01223     my_info_resizes = 0; // concurrent ones
+01224     my_info_restarts = 0; // race collisions
+01225     my_info_rehashes = 0;  // invocations of rehash_bucket
+01226 #endif
+01227     if( buckets > current_size) empty_buckets -= buckets - current_size;
+01228     else overpopulated_buckets -= current_size - buckets; // TODO: load_factor?
+01229     if( !reported && buckets >= 512 && ( 2*empty_buckets > current_size || 2*overpopulated_buckets > current_size ) ) {
+01230         tbb::internal::runtime_warning(
+01231             "Performance is not optimal because the hash function produces bad randomness in lower bits in %s.\nSize: %d  Empties: %d  Overlaps: %d",
+01232             typeid(*this).name(), current_size, empty_buckets, overpopulated_buckets );
+01233         reported = true;
+01234     }
+01235 #endif
+01236 #endif//TBB_USE_ASSERT || TBB_USE_PERFORMANCE_WARNINGS || __TBB_STATISTICS
+01237     my_size = 0;
+01238     segment_index_t s = segment_index_of( m );
+01239     __TBB_ASSERT( s+1 == pointers_per_table || !my_table[s+1], "wrong mask or concurrent grow" );
+01240     cache_aligned_allocator<bucket> alloc;
+01241     do {
+01242         __TBB_ASSERT( is_valid( my_table[s] ), "wrong mask or concurrent grow" );
+01243         segment_ptr_t buckets_ptr = my_table[s];
+01244         size_type sz = segment_size( s ? s : 1 );
+01245         for( segment_index_t i = 0; i < sz; i++ )
+01246             for( node_base *n = buckets_ptr[i].node_list; is_valid(n); n = buckets_ptr[i].node_list ) {
+01247                 buckets_ptr[i].node_list = n->next;
+01248                 delete_node( n );
+01249             }
+01250         if( s >= first_block) // the first segment or the next
+01251             alloc.deallocate( buckets_ptr, sz );
+01252         else if( s == embedded_block && embedded_block != first_block )
+01253             alloc.deallocate( buckets_ptr, segment_size(first_block)-embedded_buckets );
+01254         if( s >= embedded_block ) my_table[s] = 0;
+01255     } while(s-- > 0);
+01256     my_mask = embedded_buckets - 1;
+01257 }
+01258 
+01259 template<typename Key, typename T, typename HashCompare, typename A>
+01260 void concurrent_hash_map<Key,T,HashCompare,A>::internal_copy( const concurrent_hash_map& source ) {
+01261     reserve( source.my_size ); // TODO: load_factor?
+01262     hashcode_t mask = source.my_mask;
+01263     if( my_mask == mask ) { // optimized version
+01264         bucket *dst = 0, *src = 0;
+01265         bool rehash_required = false;
+01266         for( hashcode_t k = 0; k <= mask; k++ ) {
+01267             if( k & (k-2) ) ++dst,src++; // not the beginning of a segment
+01268             else { dst = get_bucket( k ); src = source.get_bucket( k ); }
+01269             __TBB_ASSERT( dst->node_list != internal::rehash_req, "Invalid bucket in destination table");
+01270             node *n = static_cast<node*>( src->node_list );
+01271             if( n == internal::rehash_req ) { // source is not rehashed, items are in previous buckets
+01272                 rehash_required = true;
+01273                 dst->node_list = internal::rehash_req;
+01274             } else for(; n; n = static_cast<node*>( n->next ) ) {
+01275                 add_to_bucket( dst, new( my_allocator ) node(n->item.first, n->item.second) );
+01276                 ++my_size; // TODO: replace by non-atomic op
+01277             }
+01278         }
+01279         if( rehash_required ) rehash();
+01280     } else internal_copy( source.begin(), source.end() );
+01281 }
+01282 
+01283 template<typename Key, typename T, typename HashCompare, typename A>
+01284 template<typename I>
+01285 void concurrent_hash_map<Key,T,HashCompare,A>::internal_copy(I first, I last) {
+01286     hashcode_t m = my_mask;
+01287     for(; first != last; ++first) {
+01288         hashcode_t h = my_hash_compare.hash( first->first );
+01289         bucket *b = get_bucket( h & m );
+01290         __TBB_ASSERT( b->node_list != internal::rehash_req, "Invalid bucket in destination table");
+01291         node *n = new( my_allocator ) node(first->first, first->second);
+01292         add_to_bucket( b, n );
+01293         ++my_size; // TODO: replace by non-atomic op
+01294     }
+01295 }
+01296 
+01297 } // namespace interface5
+01298 
+01299 using interface5::concurrent_hash_map;
+01300 
+01301 
+01302 template<typename Key, typename T, typename HashCompare, typename A1, typename A2>
+01303 inline bool operator==(const concurrent_hash_map<Key, T, HashCompare, A1> &a, const concurrent_hash_map<Key, T, HashCompare, A2> &b) {
+01304     if(a.size() != b.size()) return false;
+01305     typename concurrent_hash_map<Key, T, HashCompare, A1>::const_iterator i(a.begin()), i_end(a.end());
+01306     typename concurrent_hash_map<Key, T, HashCompare, A2>::const_iterator j, j_end(b.end());
+01307     for(; i != i_end; ++i) {
+01308         j = b.equal_range(i->first).first;
+01309         if( j == j_end || !(i->second == j->second) ) return false;
+01310     }
+01311     return true;
+01312 }
+01313 
+01314 template<typename Key, typename T, typename HashCompare, typename A1, typename A2>
+01315 inline bool operator!=(const concurrent_hash_map<Key, T, HashCompare, A1> &a, const concurrent_hash_map<Key, T, HashCompare, A2> &b)
+01316 {    return !(a == b); }
+01317 
+01318 template<typename Key, typename T, typename HashCompare, typename A>
+01319 inline void swap(concurrent_hash_map<Key, T, HashCompare, A> &a, concurrent_hash_map<Key, T, HashCompare, A> &b)
+01320 {    a.swap( b ); }
+01321 
+01322 #if _MSC_VER && !defined(__INTEL_COMPILER)
+01323     #pragma warning( pop )
+01324 #endif // warning 4127 is back
+01325 
+01326 } // namespace tbb
+01327 
+01328 #endif /* __TBB_concurrent_hash_map_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00466.html b/src/tbb/doc/html/a00466.html new file mode 100644 index 0000000..96b7814 --- /dev/null +++ b/src/tbb/doc/html/a00466.html @@ -0,0 +1,260 @@ + + +concurrent_lru_cache.h Source File + + + + + + +

concurrent_lru_cache.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_concurrent_lru_cache_H
+00022 #define __TBB_concurrent_lru_cache_H
+00023 
+00024 #if ! TBB_PREVIEW_CONCURRENT_LRU_CACHE
+00025     #error Set TBB_PREVIEW_CONCURRENT_LRU_CACHE to include concurrent_lru_cache.h
+00026 #endif
+00027 
+00028 #include <map>
+00029 #include <list>
+00030 
+00031 #include "tbb_stddef.h"
+00032 #include "atomic.h"
+00033 #include "internal/_aggregator_impl.h"
+00034 
+00035 namespace tbb{
+00036 namespace interface6 {
+00037 
+00038 
+00039 template <typename key_type, typename value_type, typename value_functor_type = value_type (*)(key_type) >
+00040 class concurrent_lru_cache : internal::no_assign{
+00041 private:
+00042     typedef concurrent_lru_cache self_type;
+00043     typedef value_functor_type value_function_type;
+00044     typedef std::size_t ref_counter_type;
+00045     struct map_value_type;
+00046     typedef std::map<key_type, map_value_type> map_storage_type;
+00047     typedef std::list<typename map_storage_type::iterator> lru_list_type;
+00048     struct map_value_type {
+00049         value_type my_value;
+00050         ref_counter_type my_ref_counter;
+00051         typename lru_list_type::iterator my_lru_list_iterator;
+00052         bool my_is_ready;
+00053 
+00054         map_value_type (value_type const& a_value,  ref_counter_type a_ref_counter,    typename lru_list_type::iterator a_lru_list_iterator, bool a_is_ready)
+00055             : my_value(a_value), my_ref_counter(a_ref_counter), my_lru_list_iterator (a_lru_list_iterator), my_is_ready(a_is_ready)
+00056         {}
+00057     };
+00058 
+00059     class handle_object;
+00060 
+00061     struct aggregator_operation;
+00062     typedef aggregator_operation aggregated_operation_type;
+00063     typedef tbb::internal::aggregating_functor<self_type,aggregated_operation_type> aggregator_function_type;
+00064     friend class tbb::internal::aggregating_functor<self_type,aggregated_operation_type>;
+00065     typedef tbb::internal::aggregator<aggregator_function_type, aggregated_operation_type> aggregator_type;
+00066 
+00067 private:
+00068     value_function_type my_value_function;
+00069     std::size_t const my_number_of_lru_history_items;
+00070     map_storage_type my_map_storage;
+00071     lru_list_type my_lru_list;
+00072     aggregator_type my_aggregator;
+00073 
+00074 public:
+00075     typedef handle_object handle;
+00076 
+00077 public:
+00078     concurrent_lru_cache(value_function_type f, std::size_t number_of_lru_history_items)
+00079         : my_value_function(f),my_number_of_lru_history_items(number_of_lru_history_items)
+00080     {
+00081         my_aggregator.initialize_handler(aggregator_function_type(this));
+00082     }
+00083 
+00084     handle_object operator[](key_type k){
+00085         retrieve_aggregator_operation op(k);
+00086         my_aggregator.execute(&op);
+00087         if (op.is_new_value_needed()){
+00088              op.result().second.my_value = my_value_function(k);
+00089              __TBB_store_with_release(op.result().second.my_is_ready, true);
+00090         }else{
+00091             tbb::internal::spin_wait_while_eq(op.result().second.my_is_ready,false);
+00092         }
+00093         return handle_object(*this,op.result());
+00094     }
+00095 private:
+00096     void signal_end_of_usage(typename map_storage_type::reference value_ref){
+00097         signal_end_of_usage_aggregator_operation op(value_ref);
+00098         my_aggregator.execute(&op);
+00099     }
+00100 
+00101 private:
+00102     struct handle_move_t:no_assign{
+00103         concurrent_lru_cache & my_cache_ref;
+00104         typename map_storage_type::reference my_map_record_ref;
+00105         handle_move_t(concurrent_lru_cache & cache_ref, typename map_storage_type::reference value_ref):my_cache_ref(cache_ref),my_map_record_ref(value_ref) {};
+00106     };
+00107     class handle_object {
+00108         concurrent_lru_cache * my_cache_pointer;
+00109         typename map_storage_type::reference my_map_record_ref;
+00110     public:
+00111         handle_object(concurrent_lru_cache & cache_ref, typename map_storage_type::reference value_ref):my_cache_pointer(&cache_ref), my_map_record_ref(value_ref) {}
+00112         handle_object(handle_move_t m):my_cache_pointer(&m.my_cache_ref), my_map_record_ref(m.my_map_record_ref){}
+00113         operator handle_move_t(){ return move(*this);}
+00114         value_type& value(){
+00115             __TBB_ASSERT(my_cache_pointer,"get value from moved from object?");
+00116             return my_map_record_ref.second.my_value;
+00117         }
+00118         ~handle_object(){
+00119             if (my_cache_pointer){
+00120                 my_cache_pointer->signal_end_of_usage(my_map_record_ref);
+00121             }
+00122         }
+00123     private:
+00124         friend handle_move_t move(handle_object& h){
+00125             return handle_object::move(h);
+00126         }
+00127         static handle_move_t move(handle_object& h){
+00128             __TBB_ASSERT(h.my_cache_pointer,"move from the same object twice ?");
+00129             concurrent_lru_cache * cache_pointer = NULL;
+00130             std::swap(cache_pointer,h.my_cache_pointer);
+00131             return handle_move_t(*cache_pointer,h.my_map_record_ref);
+00132         }
+00133     private:
+00134         void operator=(handle_object&);
+00135         handle_object(handle_object &);
+00136     };
+00137 private:
+00138     //TODO: looks like aggregator_operation is a perfect match for statically typed variant type
+00139     struct aggregator_operation : tbb::internal::aggregated_operation<aggregator_operation>{
+00140         enum e_op_type {op_retive, op_signal_end_of_usage};
+00141         //TODO: try to use pointer to function apply_visitor here
+00142         //TODO: try virtual functions and measure the difference
+00143         e_op_type my_operation_type;
+00144         aggregator_operation(e_op_type operation_type): my_operation_type(operation_type) {}
+00145         void cast_and_handle(self_type& container ){
+00146             if (my_operation_type==op_retive){
+00147                 static_cast<retrieve_aggregator_operation*>(this)->handle(container);
+00148             }else{
+00149                 static_cast<signal_end_of_usage_aggregator_operation*>(this)->handle(container);
+00150             }
+00151         }
+00152     };
+00153     struct retrieve_aggregator_operation : aggregator_operation, private internal::no_assign {
+00154         key_type my_key;
+00155         typename map_storage_type::pointer my_result_map_record_pointer;
+00156         bool my_is_new_value_needed;
+00157         retrieve_aggregator_operation(key_type key):aggregator_operation(aggregator_operation::op_retive),my_key(key),my_is_new_value_needed(false){}
+00158         void handle(self_type& container ){
+00159             my_result_map_record_pointer = & container.retrieve_serial(my_key,my_is_new_value_needed);
+00160         }
+00161         typename map_storage_type::reference result(){ return * my_result_map_record_pointer; }
+00162         bool is_new_value_needed(){return my_is_new_value_needed;}
+00163     };
+00164     struct signal_end_of_usage_aggregator_operation : aggregator_operation, private internal::no_assign {
+00165         typename map_storage_type::reference my_map_record_ref;
+00166         signal_end_of_usage_aggregator_operation(typename map_storage_type::reference map_record_ref):aggregator_operation(aggregator_operation::op_signal_end_of_usage),my_map_record_ref(map_record_ref){}
+00167         void handle(self_type& container ){
+00168             container.signal_end_of_usage_serial(my_map_record_ref);
+00169         }
+00170     };
+00171 
+00172 private:
+00173    void handle_operations(aggregator_operation* op_list){
+00174        while(op_list){
+00175            op_list->cast_and_handle(*this);
+00176            aggregator_operation* tmp = op_list;
+00177            op_list=op_list->next;
+00178            tbb::internal::itt_store_word_with_release(tmp->status, uintptr_t(1));
+00179        }
+00180    }
+00181 
+00182 private:
+00183    typename map_storage_type::reference retrieve_serial(key_type k, bool& is_new_value_needed){
+00184         typename map_storage_type::iterator it = my_map_storage.find(k);
+00185         if (it == my_map_storage.end()){
+00186             it = my_map_storage.insert(it,std::make_pair(k,map_value_type(value_type(),0,my_lru_list.end(),false)));
+00187             is_new_value_needed = true;
+00188         }else {
+00189             typename lru_list_type::iterator list_it = it->second.my_lru_list_iterator;
+00190             if (list_it!=my_lru_list.end()) {
+00191                 __TBB_ASSERT(!it->second.my_ref_counter,"item to be evicted should not have a live references");
+00192                 //item is going to be used. Therefore it is not a subject for eviction
+00193                 //so - remove it from LRU history.
+00194                 my_lru_list.erase(list_it);
+00195                 it->second.my_lru_list_iterator= my_lru_list.end();
+00196             }
+00197         }
+00198         ++(it->second.my_ref_counter);
+00199         return *it;
+00200     }
+00201 
+00202     void signal_end_of_usage_serial(typename map_storage_type::reference map_record_ref){
+00203         typename map_storage_type::iterator it = my_map_storage.find(map_record_ref.first);
+00204         __TBB_ASSERT(it!=my_map_storage.end(),"cache should not return past-end iterators to outer world");
+00205         __TBB_ASSERT(&(*it) == &map_record_ref,"dangling reference has been returned to outside world? data race ?");
+00206         __TBB_ASSERT( my_lru_list.end()== std::find(my_lru_list.begin(),my_lru_list.end(),it),
+00207                 "object in use should not be in list of unused objects ");
+00208         if (! --(it->second.my_ref_counter)){
+00209             //it was the last reference so put it to the LRU history
+00210             if (my_lru_list.size()>=my_number_of_lru_history_items){
+00211                 //evict items in order to get a space
+00212                 size_t number_of_elements_to_evict = 1 + my_lru_list.size() - my_number_of_lru_history_items;
+00213                 for (size_t i=0; i<number_of_elements_to_evict; ++i){
+00214                     typename map_storage_type::iterator it_to_evict = my_lru_list.back();
+00215                     __TBB_ASSERT(!it_to_evict->second.my_ref_counter,"item to be evicted should not have a live references");
+00216                     my_lru_list.pop_back();
+00217                     my_map_storage.erase(it_to_evict);
+00218                 }
+00219             }
+00220             my_lru_list.push_front(it);
+00221             it->second.my_lru_list_iterator = my_lru_list.begin();
+00222         }
+00223     }
+00224 };
+00225 } // namespace interface6
+00226 
+00227 using interface6::concurrent_lru_cache;
+00228 
+00229 } // namespace tbb
+00230 #endif //__TBB_concurrent_lru_cache_H
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00473.html b/src/tbb/doc/html/a00473.html new file mode 100644 index 0000000..f639f2c --- /dev/null +++ b/src/tbb/doc/html/a00473.html @@ -0,0 +1,327 @@ + + +concurrent_priority_queue.h Source File + + + + + + +

concurrent_priority_queue.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_concurrent_priority_queue_H
+00022 #define __TBB_concurrent_priority_queue_H
+00023 
+00024 #include "atomic.h"
+00025 #include "cache_aligned_allocator.h"
+00026 #include "tbb_exception.h"
+00027 #include "tbb_stddef.h"
+00028 #include "tbb_profiling.h"
+00029 #include "internal/_aggregator_impl.h"
+00030 #include <vector>
+00031 #include <iterator>
+00032 #include <functional>
+00033 
+00034 namespace tbb {
+00035 namespace interface5 {
+00036 
+00037 using namespace tbb::internal;
+00038 
+00040 template <typename T, typename Compare=std::less<T>, typename A=cache_aligned_allocator<T> >
+00041 class concurrent_priority_queue {
+00042  public:
+00044     typedef T value_type;
+00045 
+00047     typedef T& reference;
+00048 
+00050     typedef const T& const_reference;
+00051 
+00053     typedef size_t size_type;
+00054 
+00056     typedef ptrdiff_t difference_type;
+00057 
+00059     typedef A allocator_type;
+00060 
+00062     explicit concurrent_priority_queue(const allocator_type& a = allocator_type()) : mark(0), my_size(0), data(a)
+00063     {
+00064         my_aggregator.initialize_handler(my_functor_t(this));
+00065     }
+00066 
+00068     explicit concurrent_priority_queue(size_type init_capacity, const allocator_type& a = allocator_type()) :
+00069         mark(0), my_size(0), data(a)
+00070     {
+00071         data.reserve(init_capacity);
+00072         my_aggregator.initialize_handler(my_functor_t(this));
+00073     }
+00074 
+00076     template<typename InputIterator>
+00077     concurrent_priority_queue(InputIterator begin, InputIterator end, const allocator_type& a = allocator_type()) :
+00078         data(begin, end, a)
+00079     {
+00080         mark = 0;
+00081         my_aggregator.initialize_handler(my_functor_t(this));
+00082         heapify();
+00083         my_size = data.size();
+00084     }
+00085 
+00087 
+00088     explicit concurrent_priority_queue(const concurrent_priority_queue& src) : mark(src.mark),
+00089         my_size(src.my_size), data(src.data.begin(), src.data.end(), src.data.get_allocator())
+00090     {
+00091         my_aggregator.initialize_handler(my_functor_t(this));
+00092         heapify();
+00093     }
+00094 
+00096 
+00097     concurrent_priority_queue(const concurrent_priority_queue& src, const allocator_type& a) : mark(src.mark),
+00098         my_size(src.my_size), data(src.data.begin(), src.data.end(), a)
+00099     {
+00100         my_aggregator.initialize_handler(my_functor_t(this));
+00101         heapify();
+00102     }
+00103 
+00105 
+00106     concurrent_priority_queue& operator=(const concurrent_priority_queue& src) {
+00107         if (this != &src) {
+00108             std::vector<value_type, allocator_type>(src.data.begin(), src.data.end(), src.data.get_allocator()).swap(data);
+00109             mark = src.mark;
+00110             my_size = src.my_size;
+00111         }
+00112         return *this;
+00113     }
+00114 
+00116 
+00118     bool empty() const { return size()==0; }
+00119 
+00121 
+00123     size_type size() const { return __TBB_load_with_acquire(my_size); }
+00124 
+00126 
+00127     void push(const_reference elem) {
+00128         cpq_operation op_data(elem, PUSH_OP);
+00129         my_aggregator.execute(&op_data);
+00130         if (op_data.status == FAILED) // exception thrown
+00131             throw_exception(eid_bad_alloc);
+00132     }
+00133 
+00135 
+00138     bool try_pop(reference elem) {
+00139         cpq_operation op_data(POP_OP);
+00140         op_data.elem = &elem;
+00141         my_aggregator.execute(&op_data);
+00142         return op_data.status==SUCCEEDED;
+00143     }
+00144 
+00146 
+00149     void clear() {
+00150         data.clear();
+00151         mark = 0;
+00152         my_size = 0;
+00153     }
+00154 
+00156 
+00157     void swap(concurrent_priority_queue& q) {
+00158         data.swap(q.data);
+00159         std::swap(mark, q.mark);
+00160         std::swap(my_size, q.my_size);
+00161     }
+00162 
+00164     allocator_type get_allocator() const { return data.get_allocator(); }
+00165 
+00166  private:
+00167     enum operation_type {INVALID_OP, PUSH_OP, POP_OP};
+00168     enum operation_status { WAIT=0, SUCCEEDED, FAILED };
+00169 
+00170     class cpq_operation : public aggregated_operation<cpq_operation> {
+00171      public:
+00172         operation_type type;
+00173         union {
+00174             value_type *elem;
+00175             size_type sz;
+00176         };
+00177         cpq_operation(const_reference e, operation_type t) :
+00178             type(t), elem(const_cast<value_type*>(&e)) {}
+00179         cpq_operation(operation_type t) : type(t) {}
+00180     };
+00181 
+00182     class my_functor_t {
+00183         concurrent_priority_queue<T, Compare, A> *cpq;
+00184      public:
+00185         my_functor_t() {}
+00186         my_functor_t(concurrent_priority_queue<T, Compare, A> *cpq_) : cpq(cpq_) {}
+00187         void operator()(cpq_operation* op_list) {
+00188             cpq->handle_operations(op_list);
+00189         }
+00190     };
+00191 
+00192     aggregator< my_functor_t, cpq_operation> my_aggregator;
+00194     char padding1[NFS_MaxLineSize - sizeof(aggregator< my_functor_t, cpq_operation >)];
+00196     size_type mark;
+00197     __TBB_atomic size_type my_size;
+00198     Compare compare;
+00200     char padding2[NFS_MaxLineSize - (2*sizeof(size_type)) - sizeof(Compare)];
+00202 
+00219     std::vector<value_type, allocator_type> data;
+00220 
+00221     void handle_operations(cpq_operation *op_list) {
+00222         cpq_operation *tmp, *pop_list=NULL;
+00223 
+00224         __TBB_ASSERT(mark == data.size(), NULL);
+00225 
+00226         // First pass processes all constant (amortized; reallocation may happen) time pushes and pops.
+00227         while (op_list) {
+00228             // ITT note: &(op_list->status) tag is used to cover accesses to op_list
+00229             // node. This thread is going to handle the operation, and so will acquire it
+00230             // and perform the associated operation w/o triggering a race condition; the
+00231             // thread that created the operation is waiting on the status field, so when
+00232             // this thread is done with the operation, it will perform a
+00233             // store_with_release to give control back to the waiting thread in
+00234             // aggregator::insert_operation.
+00235             call_itt_notify(acquired, &(op_list->status));
+00236             __TBB_ASSERT(op_list->type != INVALID_OP, NULL);
+00237             tmp = op_list;
+00238             op_list = itt_hide_load_word(op_list->next);
+00239             if (tmp->type == PUSH_OP) {
+00240                 __TBB_TRY {
+00241                     data.push_back(*(tmp->elem));
+00242                     __TBB_store_with_release(my_size, my_size+1);
+00243                     itt_store_word_with_release(tmp->status, uintptr_t(SUCCEEDED));
+00244                 } __TBB_CATCH(...) {
+00245                     itt_store_word_with_release(tmp->status, uintptr_t(FAILED));
+00246                 }
+00247             }
+00248             else { // tmp->type == POP_OP
+00249                 __TBB_ASSERT(tmp->type == POP_OP, NULL);
+00250                 if (mark < data.size() &&
+00251                     compare(data[0], data[data.size()-1])) {
+00252                     // there are newly pushed elems and the last one
+00253                     // is higher than top
+00254                     *(tmp->elem) = data[data.size()-1]; // copy the data
+00255                     __TBB_store_with_release(my_size, my_size-1);
+00256                     itt_store_word_with_release(tmp->status, uintptr_t(SUCCEEDED));
+00257                     data.pop_back();
+00258                     __TBB_ASSERT(mark<=data.size(), NULL);
+00259                 }
+00260                 else { // no convenient item to pop; postpone
+00261                     itt_hide_store_word(tmp->next, pop_list);
+00262                     pop_list = tmp;
+00263                 }
+00264             }
+00265         }
+00266 
+00267         // second pass processes pop operations
+00268         while (pop_list) {
+00269             tmp = pop_list;
+00270             pop_list = itt_hide_load_word(pop_list->next);
+00271             __TBB_ASSERT(tmp->type == POP_OP, NULL);
+00272             if (data.empty()) {
+00273                 itt_store_word_with_release(tmp->status, uintptr_t(FAILED));
+00274             }
+00275             else {
+00276                 __TBB_ASSERT(mark<=data.size(), NULL);
+00277                 if (mark < data.size() &&
+00278                     compare(data[0], data[data.size()-1])) {
+00279                     // there are newly pushed elems and the last one is
+00280                     // higher than top
+00281                     *(tmp->elem) = data[data.size()-1]; // copy the data
+00282                     __TBB_store_with_release(my_size, my_size-1);
+00283                     itt_store_word_with_release(tmp->status, uintptr_t(SUCCEEDED));
+00284                     data.pop_back();
+00285                 }
+00286                 else { // extract top and push last element down heap
+00287                     *(tmp->elem) = data[0]; // copy the data
+00288                     __TBB_store_with_release(my_size, my_size-1);
+00289                     itt_store_word_with_release(tmp->status, uintptr_t(SUCCEEDED));
+00290                     reheap();
+00291                 }
+00292             }
+00293         }
+00294 
+00295         // heapify any leftover pushed elements before doing the next
+00296         // batch of operations
+00297         if (mark<data.size()) heapify();
+00298         __TBB_ASSERT(mark == data.size(), NULL);
+00299     }
+00300 
+00302     void heapify() {
+00303         if (!mark && data.size()>0) mark = 1;
+00304         for (; mark<data.size(); ++mark) {
+00305             // for each unheapified element under size
+00306             size_type cur_pos = mark;
+00307             value_type to_place = data[mark];
+00308             do { // push to_place up the heap
+00309                 size_type parent = (cur_pos-1)>>1;
+00310                 if (!compare(data[parent], to_place)) break;
+00311                 data[cur_pos] = data[parent];
+00312                 cur_pos = parent;
+00313             } while( cur_pos );
+00314             data[cur_pos] = to_place;
+00315         }
+00316     }
+00317 
+00319 
+00320     void reheap() {
+00321         size_type cur_pos=0, child=1;
+00322 
+00323         while (child < mark) {
+00324             size_type target = child;
+00325             if (child+1 < mark && compare(data[child], data[child+1]))
+00326                 ++target;
+00327             // target now has the higher priority child
+00328             if (compare(data[target], data[data.size()-1])) break;
+00329             data[cur_pos] = data[target];
+00330             cur_pos = target;
+00331             child = (cur_pos<<1)+1;
+00332         }
+00333         data[cur_pos] = data[data.size()-1];
+00334         data.pop_back();
+00335         if (mark > data.size()) mark = data.size();
+00336     }
+00337 };
+00338 
+00339 } // namespace interface5
+00340 
+00341 using interface5::concurrent_priority_queue;
+00342 
+00343 } // namespace tbb
+00344 
+00345 #endif /* __TBB_concurrent_priority_queue_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00476.html b/src/tbb/doc/html/a00476.html new file mode 100644 index 0000000..1b9d6f5 --- /dev/null +++ b/src/tbb/doc/html/a00476.html @@ -0,0 +1,371 @@ + + +concurrent_queue.h Source File + + + + + + +

concurrent_queue.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_concurrent_queue_H
+00022 #define __TBB_concurrent_queue_H
+00023 
+00024 #include "internal/_concurrent_queue_impl.h"
+00025 
+00026 namespace tbb {
+00027 
+00028 namespace strict_ppl {
+00029 
+00031 
+00034 template<typename T, typename A = cache_aligned_allocator<T> > 
+00035 class concurrent_queue: public internal::concurrent_queue_base_v3<T> {
+00036     template<typename Container, typename Value> friend class internal::concurrent_queue_iterator;
+00037 
+00039     typedef typename A::template rebind<char>::other page_allocator_type;
+00040     page_allocator_type my_allocator;
+00041 
+00043     /*override*/ virtual void *allocate_block( size_t n ) {
+00044         void *b = reinterpret_cast<void*>(my_allocator.allocate( n ));
+00045         if( !b )
+00046             internal::throw_exception(internal::eid_bad_alloc); 
+00047         return b;
+00048     }
+00049 
+00051     /*override*/ virtual void deallocate_block( void *b, size_t n ) {
+00052         my_allocator.deallocate( reinterpret_cast<char*>(b), n );
+00053     }
+00054 
+00055 public:
+00057     typedef T value_type;
+00058 
+00060     typedef T& reference;
+00061 
+00063     typedef const T& const_reference;
+00064 
+00066     typedef size_t size_type;
+00067 
+00069     typedef ptrdiff_t difference_type;
+00070 
+00072     typedef A allocator_type;
+00073 
+00075     explicit concurrent_queue(const allocator_type& a = allocator_type()) : 
+00076         my_allocator( a )
+00077     {
+00078     }
+00079 
+00081     template<typename InputIterator>
+00082     concurrent_queue( InputIterator begin, InputIterator end, const allocator_type& a = allocator_type()) :
+00083         my_allocator( a )
+00084     {
+00085         for( ; begin != end; ++begin )
+00086             this->internal_push(&*begin);
+00087     }
+00088     
+00090     concurrent_queue( const concurrent_queue& src, const allocator_type& a = allocator_type()) : 
+00091         internal::concurrent_queue_base_v3<T>(), my_allocator( a )
+00092     {
+00093         this->assign( src );
+00094     }
+00095     
+00097     ~concurrent_queue();
+00098 
+00100     void push( const T& source ) {
+00101         this->internal_push( &source );
+00102     }
+00103 
+00105 
+00107     bool try_pop( T& result ) {
+00108         return this->internal_try_pop( &result );
+00109     }
+00110 
+00112     size_type unsafe_size() const {return this->internal_size();}
+00113 
+00115     bool empty() const {return this->internal_empty();}
+00116 
+00118     void clear() ;
+00119 
+00121     allocator_type get_allocator() const { return this->my_allocator; }
+00122 
+00123     typedef internal::concurrent_queue_iterator<concurrent_queue,T> iterator;
+00124     typedef internal::concurrent_queue_iterator<concurrent_queue,const T> const_iterator;
+00125 
+00126     //------------------------------------------------------------------------
+00127     // The iterators are intended only for debugging.  They are slow and not thread safe.
+00128     //------------------------------------------------------------------------
+00129     iterator unsafe_begin() {return iterator(*this);}
+00130     iterator unsafe_end() {return iterator();}
+00131     const_iterator unsafe_begin() const {return const_iterator(*this);}
+00132     const_iterator unsafe_end() const {return const_iterator();}
+00133 } ;
+00134 
+00135 template<typename T, class A>
+00136 concurrent_queue<T,A>::~concurrent_queue() {
+00137     clear();
+00138     this->internal_finish_clear();
+00139 }
+00140 
+00141 template<typename T, class A>
+00142 void concurrent_queue<T,A>::clear() {
+00143     while( !empty() ) {
+00144         T value;
+00145         this->internal_try_pop(&value);
+00146     }
+00147 }
+00148 
+00149 } // namespace strict_ppl
+00150     
+00152 
+00157 template<typename T, class A = cache_aligned_allocator<T> >
+00158 class concurrent_bounded_queue: public internal::concurrent_queue_base_v3 {
+00159     template<typename Container, typename Value> friend class internal::concurrent_queue_iterator;
+00160 
+00162     typedef typename A::template rebind<char>::other page_allocator_type;
+00163     page_allocator_type my_allocator;
+00164 
+00165     typedef typename concurrent_queue_base_v3::padded_page<T> padded_page;
+00166  
+00168     class destroyer: internal::no_copy {
+00169         T& my_value;
+00170     public:
+00171         destroyer( T& value ) : my_value(value) {}
+00172         ~destroyer() {my_value.~T();}          
+00173     };
+00174 
+00175     T& get_ref( page& p, size_t index ) {
+00176         __TBB_ASSERT( index<items_per_page, NULL );
+00177         return (&static_cast<padded_page*>(static_cast<void*>(&p))->last)[index];
+00178     }
+00179 
+00180     /*override*/ virtual void copy_item( page& dst, size_t index, const void* src ) {
+00181         new( &get_ref(dst,index) ) T(*static_cast<const T*>(src)); 
+00182     }
+00183 
+00184     /*override*/ virtual void copy_page_item( page& dst, size_t dindex, const page& src, size_t sindex ) {
+00185         new( &get_ref(dst,dindex) ) T( get_ref( const_cast<page&>(src), sindex ) );
+00186     }
+00187 
+00188     /*override*/ virtual void assign_and_destroy_item( void* dst, page& src, size_t index ) {
+00189         T& from = get_ref(src,index);
+00190         destroyer d(from);
+00191         *static_cast<T*>(dst) = from;
+00192     }
+00193 
+00194     /*override*/ virtual page *allocate_page() {
+00195         size_t n = sizeof(padded_page) + (items_per_page-1)*sizeof(T);
+00196         page *p = reinterpret_cast<page*>(my_allocator.allocate( n ));
+00197         if( !p )
+00198             internal::throw_exception(internal::eid_bad_alloc); 
+00199         return p;
+00200     }
+00201 
+00202     /*override*/ virtual void deallocate_page( page *p ) {
+00203         size_t n = sizeof(padded_page) + (items_per_page-1)*sizeof(T);
+00204         my_allocator.deallocate( reinterpret_cast<char*>(p), n );
+00205     }
+00206 
+00207 public:
+00209     typedef T value_type;
+00210 
+00212     typedef A allocator_type;
+00213 
+00215     typedef T& reference;
+00216 
+00218     typedef const T& const_reference;
+00219 
+00221 
+00223     typedef std::ptrdiff_t size_type;
+00224 
+00226     typedef std::ptrdiff_t difference_type;
+00227 
+00229     explicit concurrent_bounded_queue(const allocator_type& a = allocator_type()) : 
+00230         concurrent_queue_base_v3( sizeof(T) ), my_allocator( a )
+00231     {
+00232     }
+00233 
+00235     concurrent_bounded_queue( const concurrent_bounded_queue& src, const allocator_type& a = allocator_type()) : 
+00236         concurrent_queue_base_v3( sizeof(T) ), my_allocator( a )
+00237     {
+00238         assign( src );
+00239     }
+00240 
+00242     template<typename InputIterator>
+00243     concurrent_bounded_queue( InputIterator begin, InputIterator end, const allocator_type& a = allocator_type()) :
+00244         concurrent_queue_base_v3( sizeof(T) ), my_allocator( a )
+00245     {
+00246         for( ; begin != end; ++begin )
+00247             internal_push_if_not_full(&*begin);
+00248     }
+00249 
+00251     ~concurrent_bounded_queue();
+00252 
+00254     void push( const T& source ) {
+00255         internal_push( &source );
+00256     }
+00257 
+00259 
+00260     void pop( T& destination ) {
+00261         internal_pop( &destination );
+00262     }
+00263 
+00264 #if TBB_USE_EXCEPTIONS
+00266     void abort() {
+00267         internal_abort();
+00268     }
+00269 #endif
+00270 
+00272 
+00274     bool try_push( const T& source ) {
+00275         return internal_push_if_not_full( &source );
+00276     }
+00277 
+00279 
+00281     bool try_pop( T& destination ) {
+00282         return internal_pop_if_present( &destination );
+00283     }
+00284 
+00286 
+00289     size_type size() const {return internal_size();}
+00290 
+00292     bool empty() const {return internal_empty();}
+00293 
+00295     size_type capacity() const {
+00296         return my_capacity;
+00297     }
+00298 
+00300 
+00302     void set_capacity( size_type new_capacity ) {
+00303         internal_set_capacity( new_capacity, sizeof(T) );
+00304     }
+00305 
+00307     allocator_type get_allocator() const { return this->my_allocator; }
+00308 
+00310     void clear() ;
+00311 
+00312     typedef internal::concurrent_queue_iterator<concurrent_bounded_queue,T> iterator;
+00313     typedef internal::concurrent_queue_iterator<concurrent_bounded_queue,const T> const_iterator;
+00314 
+00315     //------------------------------------------------------------------------
+00316     // The iterators are intended only for debugging.  They are slow and not thread safe.
+00317     //------------------------------------------------------------------------
+00318     iterator unsafe_begin() {return iterator(*this);}
+00319     iterator unsafe_end() {return iterator();}
+00320     const_iterator unsafe_begin() const {return const_iterator(*this);}
+00321     const_iterator unsafe_end() const {return const_iterator();}
+00322 
+00323 }; 
+00324 
+00325 template<typename T, class A>
+00326 concurrent_bounded_queue<T,A>::~concurrent_bounded_queue() {
+00327     clear();
+00328     internal_finish_clear();
+00329 }
+00330 
+00331 template<typename T, class A>
+00332 void concurrent_bounded_queue<T,A>::clear() {
+00333     while( !empty() ) {
+00334         T value;
+00335         internal_pop_if_present(&value);
+00336     }
+00337 }
+00338 
+00339 namespace deprecated {
+00340 
+00342 
+00347 template<typename T, class A = cache_aligned_allocator<T> > 
+00348 class concurrent_queue: public concurrent_bounded_queue<T,A> {
+00349 #if !__TBB_TEMPLATE_FRIENDS_BROKEN
+00350     template<typename Container, typename Value> friend class internal::concurrent_queue_iterator;
+00351 #endif 
+00352 
+00353 public:
+00355     explicit concurrent_queue(const A& a = A()) : 
+00356         concurrent_bounded_queue<T,A>( a )
+00357     {
+00358     }
+00359 
+00361     concurrent_queue( const concurrent_queue& src, const A& a = A()) : 
+00362         concurrent_bounded_queue<T,A>( src, a )
+00363     {
+00364     }
+00365 
+00367     template<typename InputIterator>
+00368     concurrent_queue( InputIterator b /*begin*/, InputIterator e /*end*/, const A& a = A()) :
+00369         concurrent_bounded_queue<T,A>( b, e, a )
+00370     {
+00371     }
+00372 
+00374 
+00376     bool push_if_not_full( const T& source ) {
+00377         return this->try_push( source );
+00378     }
+00379 
+00381 
+00385     bool pop_if_present( T& destination ) {
+00386         return this->try_pop( destination );
+00387     }
+00388 
+00389     typedef typename concurrent_bounded_queue<T,A>::iterator iterator;
+00390     typedef typename concurrent_bounded_queue<T,A>::const_iterator const_iterator;
+00391     //
+00392     //------------------------------------------------------------------------
+00393     // The iterators are intended only for debugging.  They are slow and not thread safe.
+00394     //------------------------------------------------------------------------
+00395     iterator begin() {return this->unsafe_begin();}
+00396     iterator end() {return this->unsafe_end();}
+00397     const_iterator begin() const {return this->unsafe_begin();}
+00398     const_iterator end() const {return this->unsafe_end();}
+00399 }; 
+00400 
+00401 }
+00402     
+00403 
+00404 #if TBB_DEPRECATED
+00405 using deprecated::concurrent_queue;
+00406 #else
+00407 using strict_ppl::concurrent_queue;    
+00408 #endif
+00409 
+00410 } // namespace tbb
+00411 
+00412 #endif /* __TBB_concurrent_queue_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00480.html b/src/tbb/doc/html/a00480.html new file mode 100644 index 0000000..6fb956c --- /dev/null +++ b/src/tbb/doc/html/a00480.html @@ -0,0 +1,250 @@ + + +concurrent_unordered_map.h Source File + + + + + + +

concurrent_unordered_map.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 /* Container implementations in this header are based on PPL implementations
+00022    provided by Microsoft. */
+00023 
+00024 #ifndef __TBB_concurrent_unordered_map_H
+00025 #define __TBB_concurrent_unordered_map_H
+00026 
+00027 #include "internal/_concurrent_unordered_impl.h"
+00028 
+00029 namespace tbb
+00030 {
+00031 
+00032 namespace interface5 {
+00033 
+00034 // Template class for hash map traits
+00035 template<typename Key, typename T, typename Hash_compare, typename Allocator, bool Allow_multimapping>
+00036 class concurrent_unordered_map_traits
+00037 {
+00038 protected:
+00039     typedef std::pair<const Key, T> value_type;
+00040     typedef Key key_type;
+00041     typedef Hash_compare hash_compare;
+00042     typedef typename Allocator::template rebind<value_type>::other allocator_type;
+00043     enum { allow_multimapping = Allow_multimapping };
+00044 
+00045     concurrent_unordered_map_traits() : my_hash_compare() {}
+00046     concurrent_unordered_map_traits(const hash_compare& hc) : my_hash_compare(hc) {}
+00047 
+00048     class value_compare : public std::binary_function<value_type, value_type, bool>
+00049     {
+00050         friend class concurrent_unordered_map_traits<Key, T, Hash_compare, Allocator, Allow_multimapping>;
+00051 
+00052     public:
+00053         bool operator()(const value_type& left, const value_type& right) const
+00054         {
+00055             return (my_hash_compare(left.first, right.first));
+00056         }
+00057 
+00058         value_compare(const hash_compare& comparator) : my_hash_compare(comparator) {}
+00059 
+00060     protected:
+00061         hash_compare my_hash_compare;    // the comparator predicate for keys
+00062     };
+00063 
+00064     template<class Type1, class Type2>
+00065     static const Key& get_key(const std::pair<Type1, Type2>& value) {
+00066         return (value.first);
+00067     }
+00068 
+00069     hash_compare my_hash_compare; // the comparator predicate for keys
+00070 };
+00071 
+00072 template <typename Key, typename T, typename Hasher = tbb::tbb_hash<Key>, typename Key_equality = std::equal_to<Key>, typename Allocator = tbb::tbb_allocator<std::pair<const Key, T> > >
+00073 class concurrent_unordered_map : public internal::concurrent_unordered_base< concurrent_unordered_map_traits<Key, T, internal::hash_compare<Key, Hasher, Key_equality>, Allocator, false> >
+00074 {
+00075     // Base type definitions
+00076     typedef internal::hash_compare<Key, Hasher, Key_equality> hash_compare;
+00077     typedef internal::concurrent_unordered_base< concurrent_unordered_map_traits<Key, T, hash_compare, Allocator, false> > base_type;
+00078     typedef concurrent_unordered_map_traits<Key, T, internal::hash_compare<Key, Hasher, Key_equality>, Allocator, false> traits_type;
+00079     using traits_type::my_hash_compare;
+00080 #if __TBB_EXTRA_DEBUG
+00081 public:
+00082 #endif
+00083     using traits_type::allow_multimapping;
+00084 public:
+00085     using base_type::end;
+00086     using base_type::find;
+00087     using base_type::insert;
+00088 
+00089     // Type definitions
+00090     typedef Key key_type;
+00091     typedef typename base_type::value_type value_type;
+00092     typedef T mapped_type;
+00093     typedef Hasher hasher;
+00094     typedef Key_equality key_equal;
+00095     typedef hash_compare key_compare;
+00096 
+00097     typedef typename base_type::allocator_type allocator_type;
+00098     typedef typename base_type::pointer pointer;
+00099     typedef typename base_type::const_pointer const_pointer;
+00100     typedef typename base_type::reference reference;
+00101     typedef typename base_type::const_reference const_reference;
+00102 
+00103     typedef typename base_type::size_type size_type;
+00104     typedef typename base_type::difference_type difference_type;
+00105 
+00106     typedef typename base_type::iterator iterator;
+00107     typedef typename base_type::const_iterator const_iterator;
+00108     typedef typename base_type::iterator local_iterator;
+00109     typedef typename base_type::const_iterator const_local_iterator;
+00110 
+00111     // Construction/destruction/copying
+00112     explicit concurrent_unordered_map(size_type n_of_buckets = 8, const hasher& a_hasher = hasher(),
+00113         const key_equal& a_keyeq = key_equal(), const allocator_type& a = allocator_type())
+00114         : base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a)
+00115     {
+00116     }
+00117 
+00118     concurrent_unordered_map(const Allocator& a) : base_type(8, key_compare(), a)
+00119     {
+00120     }
+00121 
+00122     template <typename Iterator>
+00123     concurrent_unordered_map(Iterator first, Iterator last, size_type n_of_buckets = 8, const hasher& a_hasher = hasher(),
+00124         const key_equal& a_keyeq = key_equal(), const allocator_type& a = allocator_type())
+00125         : base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a)
+00126     {
+00127         for (; first != last; ++first)
+00128             base_type::insert(*first);
+00129     }
+00130 
+00131     concurrent_unordered_map(const concurrent_unordered_map& table) : base_type(table)
+00132     {
+00133     }
+00134 
+00135     concurrent_unordered_map(const concurrent_unordered_map& table, const Allocator& a)
+00136         : base_type(table, a)
+00137     {
+00138     }
+00139 
+00140     concurrent_unordered_map& operator=(const concurrent_unordered_map& table)
+00141     {
+00142         base_type::operator=(table);
+00143         return (*this);
+00144     }
+00145 
+00146     iterator unsafe_erase(const_iterator where)
+00147     {
+00148         return base_type::unsafe_erase(where);
+00149     }
+00150 
+00151     size_type unsafe_erase(const key_type& key)
+00152     {
+00153         return base_type::unsafe_erase(key);
+00154     }
+00155 
+00156     iterator unsafe_erase(const_iterator first, const_iterator last)
+00157     {
+00158         return base_type::unsafe_erase(first, last);
+00159     }
+00160 
+00161     void swap(concurrent_unordered_map& table)
+00162     {
+00163         base_type::swap(table);
+00164     }
+00165 
+00166     // Observers
+00167     hasher hash_function() const
+00168     {
+00169         return my_hash_compare.my_hash_object;
+00170     }
+00171 
+00172     key_equal key_eq() const
+00173     {
+00174         return my_hash_compare.my_key_compare_object;
+00175     }
+00176 
+00177     mapped_type& operator[](const key_type& key)
+00178     {
+00179         iterator where = find(key);
+00180 
+00181         if (where == end())
+00182         {
+00183             where = insert(std::pair<key_type, mapped_type>(key, mapped_type())).first;
+00184         }
+00185 
+00186         return ((*where).second);
+00187     }
+00188 
+00189     mapped_type& at(const key_type& key)
+00190     {
+00191         iterator where = find(key);
+00192 
+00193         if (where == end())
+00194         {
+00195             tbb::internal::throw_exception(tbb::internal::eid_invalid_key);
+00196         }
+00197 
+00198         return ((*where).second);
+00199     }
+00200 
+00201     const mapped_type& at(const key_type& key) const
+00202     {
+00203         const_iterator where = find(key);
+00204 
+00205         if (where == end())
+00206         {
+00207             tbb::internal::throw_exception(tbb::internal::eid_invalid_key);
+00208         }
+00209 
+00210         return ((*where).second);
+00211     }
+00212 };
+00213 
+00214 } // namespace interface5
+00215 
+00216 using interface5::concurrent_unordered_map;
+00217 
+00218 } // namespace tbb
+00219 
+00220 #endif// __TBB_concurrent_unordered_map_H
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00484.html b/src/tbb/doc/html/a00484.html new file mode 100644 index 0000000..7226c70 --- /dev/null +++ b/src/tbb/doc/html/a00484.html @@ -0,0 +1,199 @@ + + +concurrent_unordered_set.h Source File + + + + + + +

concurrent_unordered_set.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 /* Container implementations in this header are based on PPL implementations
+00022    provided by Microsoft. */
+00023 
+00024 #ifndef __TBB_concurrent_unordered_set_H
+00025 #define __TBB_concurrent_unordered_set_H
+00026 
+00027 #include "internal/_concurrent_unordered_impl.h"
+00028 
+00029 namespace tbb
+00030 {
+00031 
+00032 namespace interface5 {
+00033 
+00034 // Template class for hash set traits
+00035 template<typename Key, typename Hash_compare, typename Allocator, bool Allow_multimapping>
+00036 class concurrent_unordered_set_traits
+00037 {
+00038 protected:
+00039     typedef Key value_type;
+00040     typedef Key key_type;
+00041     typedef Hash_compare hash_compare;
+00042     typedef typename Allocator::template rebind<value_type>::other allocator_type;
+00043     enum { allow_multimapping = Allow_multimapping };
+00044 
+00045     concurrent_unordered_set_traits() : my_hash_compare() {}
+00046     concurrent_unordered_set_traits(const hash_compare& hc) : my_hash_compare(hc) {}
+00047 
+00048     typedef hash_compare value_compare;
+00049 
+00050     static const Key& get_key(const value_type& value) {
+00051         return value;
+00052     }
+00053 
+00054     hash_compare my_hash_compare; // the comparator predicate for keys
+00055 };
+00056 
+00057 template <typename Key, typename Hasher = tbb::tbb_hash<Key>, typename Key_equality = std::equal_to<Key>, typename Allocator = tbb::tbb_allocator<Key> >
+00058 class concurrent_unordered_set : public internal::concurrent_unordered_base< concurrent_unordered_set_traits<Key, internal::hash_compare<Key, Hasher, Key_equality>, Allocator, false> >
+00059 {
+00060     // Base type definitions
+00061     typedef internal::hash_compare<Key, Hasher, Key_equality> hash_compare;
+00062     typedef internal::concurrent_unordered_base< concurrent_unordered_set_traits<Key, hash_compare, Allocator, false> > base_type;
+00063     typedef concurrent_unordered_set_traits<Key, internal::hash_compare<Key, Hasher, Key_equality>, Allocator, false> traits_type;
+00064     using traits_type::my_hash_compare;
+00065 #if __TBB_EXTRA_DEBUG
+00066 public:
+00067 #endif
+00068     using traits_type::allow_multimapping;
+00069 public:
+00070     using base_type::end;
+00071     using base_type::find;
+00072     using base_type::insert;
+00073 
+00074     // Type definitions
+00075     typedef Key key_type;
+00076     typedef typename base_type::value_type value_type;
+00077     typedef Key mapped_type;
+00078     typedef Hasher hasher;
+00079     typedef Key_equality key_equal;
+00080     typedef hash_compare key_compare;
+00081 
+00082     typedef typename base_type::allocator_type allocator_type;
+00083     typedef typename base_type::pointer pointer;
+00084     typedef typename base_type::const_pointer const_pointer;
+00085     typedef typename base_type::reference reference;
+00086     typedef typename base_type::const_reference const_reference;
+00087 
+00088     typedef typename base_type::size_type size_type;
+00089     typedef typename base_type::difference_type difference_type;
+00090 
+00091     typedef typename base_type::iterator iterator;
+00092     typedef typename base_type::const_iterator const_iterator;
+00093     typedef typename base_type::iterator local_iterator;
+00094     typedef typename base_type::const_iterator const_local_iterator;
+00095 
+00096     // Construction/destruction/copying
+00097     explicit concurrent_unordered_set(size_type n_of_buckets = 8, const hasher& a_hasher = hasher(),
+00098         const key_equal& a_keyeq = key_equal(), const allocator_type& a = allocator_type())
+00099         : base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a)
+00100     {
+00101     }
+00102 
+00103     concurrent_unordered_set(const Allocator& a) : base_type(8, key_compare(), a)
+00104     {
+00105     }
+00106 
+00107     template <typename Iterator>
+00108     concurrent_unordered_set(Iterator first, Iterator last, size_type n_of_buckets = 8, const hasher& a_hasher = hasher(),
+00109         const key_equal& a_keyeq = key_equal(), const allocator_type& a = allocator_type())
+00110         : base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a)
+00111     {
+00112         for (; first != last; ++first)
+00113             base_type::insert(*first);
+00114     }
+00115 
+00116     concurrent_unordered_set(const concurrent_unordered_set& table) : base_type(table)
+00117     {
+00118     }
+00119 
+00120     concurrent_unordered_set(const concurrent_unordered_set& table, const Allocator& a)
+00121         : base_type(table, a)
+00122     {
+00123     }
+00124 
+00125     concurrent_unordered_set& operator=(const concurrent_unordered_set& table)
+00126     {
+00127         base_type::operator=(table);
+00128         return (*this);
+00129     }
+00130 
+00131     iterator unsafe_erase(const_iterator where)
+00132     {
+00133         return base_type::unsafe_erase(where);
+00134     }
+00135 
+00136     size_type unsafe_erase(const key_type& key)
+00137     {
+00138         return base_type::unsafe_erase(key);
+00139     }
+00140 
+00141     iterator unsafe_erase(const_iterator first, const_iterator last)
+00142     {
+00143         return base_type::unsafe_erase(first, last);
+00144     }
+00145 
+00146     void swap(concurrent_unordered_set& table)
+00147     {
+00148         base_type::swap(table);
+00149     }
+00150 
+00151     // Observers
+00152     hasher hash_function() const
+00153     {
+00154         return my_hash_compare.my_hash_object;
+00155     }
+00156 
+00157     key_equal key_eq() const
+00158     {
+00159         return my_hash_compare.my_key_compare_object;
+00160     }
+00161 };
+00162 
+00163 } // namespace interface5
+00164 
+00165 using interface5::concurrent_unordered_set;
+00166 
+00167 } // namespace tbb
+00168 
+00169 #endif// __TBB_concurrent_unordered_set_H
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00487.html b/src/tbb/doc/html/a00487.html new file mode 100644 index 0000000..2c739ce --- /dev/null +++ b/src/tbb/doc/html/a00487.html @@ -0,0 +1,928 @@ + + +concurrent_vector.h Source File + + + + + + +

concurrent_vector.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_concurrent_vector_H
+00022 #define __TBB_concurrent_vector_H
+00023 
+00024 #include "tbb_stddef.h"
+00025 #include "tbb_exception.h"
+00026 #include "atomic.h"
+00027 #include "cache_aligned_allocator.h"
+00028 #include "blocked_range.h"
+00029 #include "tbb_machine.h"
+00030 #include "tbb_profiling.h"
+00031 #include <new>
+00032 #include <cstring>   // for memset()
+00033 
+00034 #if !TBB_USE_EXCEPTIONS && _MSC_VER
+00035     // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers
+00036     #pragma warning (push)
+00037     #pragma warning (disable: 4530)
+00038 #endif
+00039 
+00040 #include <algorithm>
+00041 #include <iterator>
+00042 
+00043 #if !TBB_USE_EXCEPTIONS && _MSC_VER
+00044     #pragma warning (pop)
+00045 #endif
+00046 
+00047 #if _MSC_VER==1500 && !__INTEL_COMPILER
+00048     // VS2008/VC9 seems to have an issue; limits pull in math.h
+00049     #pragma warning( push )
+00050     #pragma warning( disable: 4985 )
+00051 #endif
+00052 #include <limits> /* std::numeric_limits */
+00053 #if _MSC_VER==1500 && !__INTEL_COMPILER
+00054     #pragma warning( pop )
+00055 #endif
+00056 
+00057 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_Wp64)
+00058     // Workaround for overzealous compiler warnings in /Wp64 mode
+00059     #pragma warning (push)
+00060     #pragma warning (disable: 4267)
+00061 #endif
+00062 
+00063 namespace tbb {
+00064 
+00065 template<typename T, class A = cache_aligned_allocator<T> >
+00066 class concurrent_vector;
+00067 
+00069 namespace internal {
+00070 
+00072     static void *const vector_allocation_error_flag = reinterpret_cast<void*>(size_t(63));
+00073 
+00075 
+00076     class concurrent_vector_base_v3 {
+00077     protected:
+00078 
+00079         // Basic types declarations
+00080         typedef size_t segment_index_t;
+00081         typedef size_t size_type;
+00082 
+00083         // Using enumerations due to Mac linking problems of static const variables
+00084         enum {
+00085             // Size constants
+00086             default_initial_segments = 1, // 2 initial items
+00088             pointers_per_short_table = 3, // to fit into 8 words of entire structure
+00089             pointers_per_long_table = sizeof(segment_index_t) * 8 // one segment per bit
+00090         };
+00091 
+00092         // Segment pointer. Can be zero-initialized
+00093         struct segment_t {
+00094             void* array;
+00095 #if TBB_USE_ASSERT
+00096             ~segment_t() {
+00097                 __TBB_ASSERT( array <= internal::vector_allocation_error_flag, "should have been freed by clear" );
+00098             }
+00099 #endif /* TBB_USE_ASSERT */
+00100         };
+00101 
+00102         // Data fields
+00103 
+00105         void* (*vector_allocator_ptr)(concurrent_vector_base_v3 &, size_t);
+00106 
+00108         atomic<size_type> my_first_block;
+00109 
+00111         atomic<size_type> my_early_size;
+00112 
+00114         atomic<segment_t*> my_segment;
+00115 
+00117         segment_t my_storage[pointers_per_short_table];
+00118 
+00119         // Methods
+00120 
+00121         concurrent_vector_base_v3() {
+00122             my_early_size = 0;
+00123             my_first_block = 0; // here is not default_initial_segments
+00124             for( segment_index_t i = 0; i < pointers_per_short_table; i++)
+00125                 my_storage[i].array = NULL;
+00126             my_segment = my_storage;
+00127         }
+00128         __TBB_EXPORTED_METHOD ~concurrent_vector_base_v3();
+00129 
+00130         static segment_index_t segment_index_of( size_type index ) {
+00131             return segment_index_t( __TBB_Log2( index|1 ) );
+00132         }
+00133 
+00134         static segment_index_t segment_base( segment_index_t k ) {
+00135             return (segment_index_t(1)<<k & ~segment_index_t(1));
+00136         }
+00137 
+00138         static inline segment_index_t segment_base_index_of( segment_index_t &index ) {
+00139             segment_index_t k = segment_index_of( index );
+00140             index -= segment_base(k);
+00141             return k;
+00142         }
+00143 
+00144         static size_type segment_size( segment_index_t k ) {
+00145             return segment_index_t(1)<<k; // fake value for k==0
+00146         }
+00147 
+00149         typedef void (__TBB_EXPORTED_FUNC *internal_array_op1)(void* begin, size_type n );
+00150 
+00152         typedef void (__TBB_EXPORTED_FUNC *internal_array_op2)(void* dst, const void* src, size_type n );
+00153 
+00155         struct internal_segments_table {
+00156             segment_index_t first_block;
+00157             void* table[pointers_per_long_table];
+00158         };
+00159 
+00160         void __TBB_EXPORTED_METHOD internal_reserve( size_type n, size_type element_size, size_type max_size );
+00161         size_type __TBB_EXPORTED_METHOD internal_capacity() const;
+00162         void internal_grow( size_type start, size_type finish, size_type element_size, internal_array_op2 init, const void *src );
+00163         size_type __TBB_EXPORTED_METHOD internal_grow_by( size_type delta, size_type element_size, internal_array_op2 init, const void *src );
+00164         void* __TBB_EXPORTED_METHOD internal_push_back( size_type element_size, size_type& index );
+00165         segment_index_t __TBB_EXPORTED_METHOD internal_clear( internal_array_op1 destroy );
+00166         void* __TBB_EXPORTED_METHOD internal_compact( size_type element_size, void *table, internal_array_op1 destroy, internal_array_op2 copy );
+00167         void __TBB_EXPORTED_METHOD internal_copy( const concurrent_vector_base_v3& src, size_type element_size, internal_array_op2 copy );
+00168         void __TBB_EXPORTED_METHOD internal_assign( const concurrent_vector_base_v3& src, size_type element_size,
+00169                               internal_array_op1 destroy, internal_array_op2 assign, internal_array_op2 copy );
+00171         void __TBB_EXPORTED_METHOD internal_throw_exception(size_type) const;
+00172         void __TBB_EXPORTED_METHOD internal_swap(concurrent_vector_base_v3& v);
+00173 
+00174         void __TBB_EXPORTED_METHOD internal_resize( size_type n, size_type element_size, size_type max_size, const void *src,
+00175                                                     internal_array_op1 destroy, internal_array_op2 init );
+00176         size_type __TBB_EXPORTED_METHOD internal_grow_to_at_least_with_result( size_type new_size, size_type element_size, internal_array_op2 init, const void *src );
+00177 
+00179         void __TBB_EXPORTED_METHOD internal_grow_to_at_least( size_type new_size, size_type element_size, internal_array_op2 init, const void *src );
+00180 private:
+00182         class helper;
+00183         friend class helper;
+00184     };
+00185 
+00186     typedef concurrent_vector_base_v3 concurrent_vector_base;
+00187 
+00189 
+00191     template<typename Container, typename Value>
+00192     class vector_iterator
+00193     {
+00195         Container* my_vector;
+00196 
+00198         size_t my_index;
+00199 
+00201 
+00202         mutable Value* my_item;
+00203 
+00204         template<typename C, typename T>
+00205         friend vector_iterator<C,T> operator+( ptrdiff_t offset, const vector_iterator<C,T>& v );
+00206 
+00207         template<typename C, typename T, typename U>
+00208         friend bool operator==( const vector_iterator<C,T>& i, const vector_iterator<C,U>& j );
+00209 
+00210         template<typename C, typename T, typename U>
+00211         friend bool operator<( const vector_iterator<C,T>& i, const vector_iterator<C,U>& j );
+00212 
+00213         template<typename C, typename T, typename U>
+00214         friend ptrdiff_t operator-( const vector_iterator<C,T>& i, const vector_iterator<C,U>& j );
+00215 
+00216         template<typename C, typename U>
+00217         friend class internal::vector_iterator;
+00218 
+00219 #if !defined(_MSC_VER) || defined(__INTEL_COMPILER)
+00220         template<typename T, class A>
+00221         friend class tbb::concurrent_vector;
+00222 #else
+00223 public: // workaround for MSVC
+00224 #endif
+00225 
+00226         vector_iterator( const Container& vector, size_t index, void *ptr = 0 ) :
+00227             my_vector(const_cast<Container*>(&vector)),
+00228             my_index(index),
+00229             my_item(static_cast<Value*>(ptr))
+00230         {}
+00231 
+00232     public:
+00234         vector_iterator() : my_vector(NULL), my_index(~size_t(0)), my_item(NULL) {}
+00235 
+00236         vector_iterator( const vector_iterator<Container,typename Container::value_type>& other ) :
+00237             my_vector(other.my_vector),
+00238             my_index(other.my_index),
+00239             my_item(other.my_item)
+00240         {}
+00241 
+00242         vector_iterator operator+( ptrdiff_t offset ) const {
+00243             return vector_iterator( *my_vector, my_index+offset );
+00244         }
+00245         vector_iterator &operator+=( ptrdiff_t offset ) {
+00246             my_index+=offset;
+00247             my_item = NULL;
+00248             return *this;
+00249         }
+00250         vector_iterator operator-( ptrdiff_t offset ) const {
+00251             return vector_iterator( *my_vector, my_index-offset );
+00252         }
+00253         vector_iterator &operator-=( ptrdiff_t offset ) {
+00254             my_index-=offset;
+00255             my_item = NULL;
+00256             return *this;
+00257         }
+00258         Value& operator*() const {
+00259             Value* item = my_item;
+00260             if( !item ) {
+00261                 item = my_item = &my_vector->internal_subscript(my_index);
+00262             }
+00263             __TBB_ASSERT( item==&my_vector->internal_subscript(my_index), "corrupt cache" );
+00264             return *item;
+00265         }
+00266         Value& operator[]( ptrdiff_t k ) const {
+00267             return my_vector->internal_subscript(my_index+k);
+00268         }
+00269         Value* operator->() const {return &operator*();}
+00270 
+00272         vector_iterator& operator++() {
+00273             size_t k = ++my_index;
+00274             if( my_item ) {
+00275                 // Following test uses 2's-complement wizardry
+00276                 if( (k& (k-2))==0 ) {
+00277                     // k is a power of two that is at least k-2
+00278                     my_item= NULL;
+00279                 } else {
+00280                     ++my_item;
+00281                 }
+00282             }
+00283             return *this;
+00284         }
+00285 
+00287         vector_iterator& operator--() {
+00288             __TBB_ASSERT( my_index>0, "operator--() applied to iterator already at beginning of concurrent_vector" );
+00289             size_t k = my_index--;
+00290             if( my_item ) {
+00291                 // Following test uses 2's-complement wizardry
+00292                 if( (k& (k-2))==0 ) {
+00293                     // k is a power of two that is at least k-2  
+00294                     my_item= NULL;
+00295                 } else {
+00296                     --my_item;
+00297                 }
+00298             }
+00299             return *this;
+00300         }
+00301 
+00303         vector_iterator operator++(int) {
+00304             vector_iterator result = *this;
+00305             operator++();
+00306             return result;
+00307         }
+00308 
+00310         vector_iterator operator--(int) {
+00311             vector_iterator result = *this;
+00312             operator--();
+00313             return result;
+00314         }
+00315 
+00316         // STL support
+00317 
+00318         typedef ptrdiff_t difference_type;
+00319         typedef Value value_type;
+00320         typedef Value* pointer;
+00321         typedef Value& reference;
+00322         typedef std::random_access_iterator_tag iterator_category;
+00323     };
+00324 
+00325     template<typename Container, typename T>
+00326     vector_iterator<Container,T> operator+( ptrdiff_t offset, const vector_iterator<Container,T>& v ) {
+00327         return vector_iterator<Container,T>( *v.my_vector, v.my_index+offset );
+00328     }
+00329 
+00330     template<typename Container, typename T, typename U>
+00331     bool operator==( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) {
+00332         return i.my_index==j.my_index && i.my_vector == j.my_vector;
+00333     }
+00334 
+00335     template<typename Container, typename T, typename U>
+00336     bool operator!=( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) {
+00337         return !(i==j);
+00338     }
+00339 
+00340     template<typename Container, typename T, typename U>
+00341     bool operator<( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) {
+00342         return i.my_index<j.my_index;
+00343     }
+00344 
+00345     template<typename Container, typename T, typename U>
+00346     bool operator>( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) {
+00347         return j<i;
+00348     }
+00349 
+00350     template<typename Container, typename T, typename U>
+00351     bool operator>=( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) {
+00352         return !(i<j);
+00353     }
+00354 
+00355     template<typename Container, typename T, typename U>
+00356     bool operator<=( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) {
+00357         return !(j<i);
+00358     }
+00359 
+00360     template<typename Container, typename T, typename U>
+00361     ptrdiff_t operator-( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) {
+00362         return ptrdiff_t(i.my_index)-ptrdiff_t(j.my_index);
+00363     }
+00364 
+00365     template<typename T, class A>
+00366     class allocator_base {
+00367     public:
+00368         typedef typename A::template
+00369             rebind<T>::other allocator_type;
+00370         allocator_type my_allocator;
+00371 
+00372         allocator_base(const allocator_type &a = allocator_type() ) : my_allocator(a) {}
+00373     };
+00374 
+00375 } // namespace internal
+00377 
+00379 
+00440 template<typename T, class A>
+00441 class concurrent_vector: protected internal::allocator_base<T, A>,
+00442                          private internal::concurrent_vector_base {
+00443 private:
+00444     template<typename I>
+00445     class generic_range_type: public blocked_range<I> {
+00446     public:
+00447         typedef T value_type;
+00448         typedef T& reference;
+00449         typedef const T& const_reference;
+00450         typedef I iterator;
+00451         typedef ptrdiff_t difference_type;
+00452         generic_range_type( I begin_, I end_, size_t grainsize_ = 1) : blocked_range<I>(begin_,end_,grainsize_) {}
+00453         template<typename U>
+00454         generic_range_type( const generic_range_type<U>& r) : blocked_range<I>(r.begin(),r.end(),r.grainsize()) {}
+00455         generic_range_type( generic_range_type& r, split ) : blocked_range<I>(r,split()) {}
+00456     };
+00457 
+00458     template<typename C, typename U>
+00459     friend class internal::vector_iterator;
+00460 public:
+00461     //------------------------------------------------------------------------
+00462     // STL compatible types
+00463     //------------------------------------------------------------------------
+00464     typedef internal::concurrent_vector_base_v3::size_type size_type;
+00465     typedef typename internal::allocator_base<T, A>::allocator_type allocator_type;
+00466 
+00467     typedef T value_type;
+00468     typedef ptrdiff_t difference_type;
+00469     typedef T& reference;
+00470     typedef const T& const_reference;
+00471     typedef T *pointer;
+00472     typedef const T *const_pointer;
+00473 
+00474     typedef internal::vector_iterator<concurrent_vector,T> iterator;
+00475     typedef internal::vector_iterator<concurrent_vector,const T> const_iterator;
+00476 
+00477 #if !defined(_MSC_VER) || _CPPLIB_VER>=300
+00478     // Assume ISO standard definition of std::reverse_iterator
+00479     typedef std::reverse_iterator<iterator> reverse_iterator;
+00480     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+00481 #else
+00482     // Use non-standard std::reverse_iterator
+00483     typedef std::reverse_iterator<iterator,T,T&,T*> reverse_iterator;
+00484     typedef std::reverse_iterator<const_iterator,T,const T&,const T*> const_reverse_iterator;
+00485 #endif /* defined(_MSC_VER) && (_MSC_VER<1300) */
+00486 
+00487     //------------------------------------------------------------------------
+00488     // Parallel algorithm support
+00489     //------------------------------------------------------------------------
+00490     typedef generic_range_type<iterator> range_type;
+00491     typedef generic_range_type<const_iterator> const_range_type;
+00492 
+00493     //------------------------------------------------------------------------
+00494     // STL compatible constructors & destructors
+00495     //------------------------------------------------------------------------
+00496 
+00498     explicit concurrent_vector(const allocator_type &a = allocator_type())
+00499         : internal::allocator_base<T, A>(a), internal::concurrent_vector_base()
+00500     {
+00501         vector_allocator_ptr = &internal_allocator;
+00502     }
+00503 
+00505     concurrent_vector( const concurrent_vector& vector, const allocator_type& a = allocator_type() )
+00506         : internal::allocator_base<T, A>(a), internal::concurrent_vector_base()
+00507     {
+00508         vector_allocator_ptr = &internal_allocator;
+00509         __TBB_TRY {
+00510             internal_copy(vector, sizeof(T), &copy_array);
+00511         } __TBB_CATCH(...) {
+00512             segment_t *table = my_segment;
+00513             internal_free_segments( reinterpret_cast<void**>(table), internal_clear(&destroy_array), my_first_block );
+00514             __TBB_RETHROW();
+00515         }
+00516     }
+00517 
+00519     template<class M>
+00520     concurrent_vector( const concurrent_vector<T, M>& vector, const allocator_type& a = allocator_type() )
+00521         : internal::allocator_base<T, A>(a), internal::concurrent_vector_base()
+00522     {
+00523         vector_allocator_ptr = &internal_allocator;
+00524         __TBB_TRY {
+00525             internal_copy(vector.internal_vector_base(), sizeof(T), &copy_array);
+00526         } __TBB_CATCH(...) {
+00527             segment_t *table = my_segment;
+00528             internal_free_segments( reinterpret_cast<void**>(table), internal_clear(&destroy_array), my_first_block );
+00529             __TBB_RETHROW();
+00530         }
+00531     }
+00532 
+00534     explicit concurrent_vector(size_type n)
+00535     {
+00536         vector_allocator_ptr = &internal_allocator;
+00537         __TBB_TRY {
+00538             internal_resize( n, sizeof(T), max_size(), NULL, &destroy_array, &initialize_array );
+00539         } __TBB_CATCH(...) {
+00540             segment_t *table = my_segment;
+00541             internal_free_segments( reinterpret_cast<void**>(table), internal_clear(&destroy_array), my_first_block );
+00542             __TBB_RETHROW();
+00543         }
+00544     }
+00545 
+00547     concurrent_vector(size_type n, const_reference t, const allocator_type& a = allocator_type())
+00548         : internal::allocator_base<T, A>(a)
+00549     {
+00550         vector_allocator_ptr = &internal_allocator;
+00551         __TBB_TRY {
+00552             internal_resize( n, sizeof(T), max_size(), static_cast<const void*>(&t), &destroy_array, &initialize_array_by );
+00553         } __TBB_CATCH(...) {
+00554             segment_t *table = my_segment;
+00555             internal_free_segments( reinterpret_cast<void**>(table), internal_clear(&destroy_array), my_first_block );
+00556             __TBB_RETHROW();
+00557         }
+00558     }
+00559 
+00561     template<class I>
+00562     concurrent_vector(I first, I last, const allocator_type &a = allocator_type())
+00563         : internal::allocator_base<T, A>(a)
+00564     {
+00565         vector_allocator_ptr = &internal_allocator;
+00566         __TBB_TRY {
+00567             internal_assign_range(first, last, static_cast<is_integer_tag<std::numeric_limits<I>::is_integer> *>(0) );
+00568         } __TBB_CATCH(...) {
+00569             segment_t *table = my_segment;
+00570             internal_free_segments( reinterpret_cast<void**>(table), internal_clear(&destroy_array), my_first_block );
+00571             __TBB_RETHROW();
+00572         }
+00573     }
+00574 
+00576     concurrent_vector& operator=( const concurrent_vector& vector ) {
+00577         if( this != &vector )
+00578             internal_assign(vector, sizeof(T), &destroy_array, &assign_array, &copy_array);
+00579         return *this;
+00580     }
+00581 
+00583     template<class M>
+00584     concurrent_vector& operator=( const concurrent_vector<T, M>& vector ) {
+00585         if( static_cast<void*>( this ) != static_cast<const void*>( &vector ) )
+00586             internal_assign(vector.internal_vector_base(),
+00587                 sizeof(T), &destroy_array, &assign_array, &copy_array);
+00588         return *this;
+00589     }
+00590 
+00591     //------------------------------------------------------------------------
+00592     // Concurrent operations
+00593     //------------------------------------------------------------------------
+00595 #if TBB_DEPRECATED
+00596 
+00597     size_type grow_by( size_type delta ) {
+00598         return delta ? internal_grow_by( delta, sizeof(T), &initialize_array, NULL ) : my_early_size;
+00599     }
+00600 #else
+00601 
+00602     iterator grow_by( size_type delta ) {
+00603         return iterator(*this, delta ? internal_grow_by( delta, sizeof(T), &initialize_array, NULL ) : my_early_size);
+00604     }
+00605 #endif
+00606 
+00608 #if TBB_DEPRECATED
+00609 
+00610     size_type grow_by( size_type delta, const_reference t ) {
+00611         return delta ? internal_grow_by( delta, sizeof(T), &initialize_array_by, static_cast<const void*>(&t) ) : my_early_size;
+00612     }
+00613 #else
+00614 
+00615     iterator grow_by( size_type delta, const_reference t ) {
+00616         return iterator(*this, delta ? internal_grow_by( delta, sizeof(T), &initialize_array_by, static_cast<const void*>(&t) ) : my_early_size);
+00617     }
+00618 #endif
+00619 
+00621 #if TBB_DEPRECATED
+00622 
+00624     void grow_to_at_least( size_type n ) {
+00625         if( n ) internal_grow_to_at_least_with_result( n, sizeof(T), &initialize_array, NULL );
+00626     };
+00627 #else
+00628 
+00632     iterator grow_to_at_least( size_type n ) {
+00633         size_type m=0;
+00634         if( n ) {
+00635             m = internal_grow_to_at_least_with_result( n, sizeof(T), &initialize_array, NULL );
+00636             if( m>n ) m=n;
+00637         }
+00638         return iterator(*this, m);
+00639     };
+00640 #endif
+00641 
+00643 #if TBB_DEPRECATED
+00644     size_type push_back( const_reference item )
+00645 #else
+00646 
+00647     iterator push_back( const_reference item )
+00648 #endif
+00649     {
+00650         size_type k;
+00651         void *ptr = internal_push_back(sizeof(T),k);
+00652         internal_loop_guide loop(1, ptr);
+00653         loop.init(&item);
+00654 #if TBB_DEPRECATED
+00655         return k;
+00656 #else
+00657         return iterator(*this, k, ptr);
+00658 #endif
+00659     }
+00660 
+00662 
+00664     reference operator[]( size_type index ) {
+00665         return internal_subscript(index);
+00666     }
+00667 
+00669     const_reference operator[]( size_type index ) const {
+00670         return internal_subscript(index);
+00671     }
+00672 
+00674     reference at( size_type index ) {
+00675         return internal_subscript_with_exceptions(index);
+00676     }
+00677 
+00679     const_reference at( size_type index ) const {
+00680         return internal_subscript_with_exceptions(index);
+00681     }
+00682 
+00684     range_type range( size_t grainsize = 1 ) {
+00685         return range_type( begin(), end(), grainsize );
+00686     }
+00687 
+00689     const_range_type range( size_t grainsize = 1 ) const {
+00690         return const_range_type( begin(), end(), grainsize );
+00691     }
+00692 
+00693     //------------------------------------------------------------------------
+00694     // Capacity
+00695     //------------------------------------------------------------------------
+00697     size_type size() const {
+00698         size_type sz = my_early_size, cp = internal_capacity();
+00699         return cp < sz ? cp : sz;
+00700     }
+00701 
+00703     bool empty() const {return !my_early_size;}
+00704 
+00706     size_type capacity() const {return internal_capacity();}
+00707 
+00709 
+00711     void reserve( size_type n ) {
+00712         if( n )
+00713             internal_reserve(n, sizeof(T), max_size());
+00714     }
+00715 
+00717     void resize( size_type n ) {
+00718         internal_resize( n, sizeof(T), max_size(), NULL, &destroy_array, &initialize_array );
+00719     }
+00720 
+00722     void resize( size_type n, const_reference t ) {
+00723         internal_resize( n, sizeof(T), max_size(), static_cast<const void*>(&t), &destroy_array, &initialize_array_by );
+00724     }
+00725 
+00726 #if TBB_DEPRECATED
+00728     void compact() {shrink_to_fit();}
+00729 #endif /* TBB_DEPRECATED */
+00730 
+00732     void shrink_to_fit();
+00733 
+00735     size_type max_size() const {return (~size_type(0))/sizeof(T);}
+00736 
+00737     //------------------------------------------------------------------------
+00738     // STL support
+00739     //------------------------------------------------------------------------
+00740 
+00742     iterator begin() {return iterator(*this,0);}
+00744     iterator end() {return iterator(*this,size());}
+00746     const_iterator begin() const {return const_iterator(*this,0);}
+00748     const_iterator end() const {return const_iterator(*this,size());}
+00750     const_iterator cbegin() const {return const_iterator(*this,0);}
+00752     const_iterator cend() const {return const_iterator(*this,size());}
+00754     reverse_iterator rbegin() {return reverse_iterator(end());}
+00756     reverse_iterator rend() {return reverse_iterator(begin());}
+00758     const_reverse_iterator rbegin() const {return const_reverse_iterator(end());}
+00760     const_reverse_iterator rend() const {return const_reverse_iterator(begin());}
+00762     const_reverse_iterator crbegin() const {return const_reverse_iterator(end());}
+00764     const_reverse_iterator crend() const {return const_reverse_iterator(begin());}
+00766     reference front() {
+00767         __TBB_ASSERT( size()>0, NULL);
+00768         return static_cast<T*>(my_segment[0].array)[0];
+00769     }
+00771     const_reference front() const {
+00772         __TBB_ASSERT( size()>0, NULL);
+00773         return static_cast<const T*>(my_segment[0].array)[0];
+00774     }
+00776     reference back() {
+00777         __TBB_ASSERT( size()>0, NULL);
+00778         return internal_subscript( size()-1 );
+00779     }
+00781     const_reference back() const {
+00782         __TBB_ASSERT( size()>0, NULL);
+00783         return internal_subscript( size()-1 );
+00784     }
+00786     allocator_type get_allocator() const { return this->my_allocator; }
+00787 
+00789     void assign(size_type n, const_reference t) {
+00790         clear();
+00791         internal_resize( n, sizeof(T), max_size(), static_cast<const void*>(&t), &destroy_array, &initialize_array_by );
+00792     }
+00793 
+00795     template<class I>
+00796     void assign(I first, I last) {
+00797         clear(); internal_assign_range( first, last, static_cast<is_integer_tag<std::numeric_limits<I>::is_integer> *>(0) );
+00798     }
+00799 
+00801     void swap(concurrent_vector &vector) {
+00802         if( this != &vector ) {
+00803             concurrent_vector_base_v3::internal_swap(static_cast<concurrent_vector_base_v3&>(vector));
+00804             std::swap(this->my_allocator, vector.my_allocator);
+00805         }
+00806     }
+00807 
+00809 
+00810     void clear() {
+00811         internal_clear(&destroy_array);
+00812     }
+00813 
+00815     ~concurrent_vector() {
+00816         segment_t *table = my_segment;
+00817         internal_free_segments( reinterpret_cast<void**>(table), internal_clear(&destroy_array), my_first_block );
+00818         // base class destructor call should be then
+00819     }
+00820 
+00821     const internal::concurrent_vector_base_v3 &internal_vector_base() const { return *this; }
+00822 private:
+00824     static void *internal_allocator(internal::concurrent_vector_base_v3 &vb, size_t k) {
+00825         return static_cast<concurrent_vector<T, A>&>(vb).my_allocator.allocate(k);
+00826     }
+00828     void internal_free_segments(void *table[], segment_index_t k, segment_index_t first_block);
+00829 
+00831     T& internal_subscript( size_type index ) const;
+00832 
+00834     T& internal_subscript_with_exceptions( size_type index ) const;
+00835 
+00837     void internal_assign_n(size_type n, const_pointer p) {
+00838         internal_resize( n, sizeof(T), max_size(), static_cast<const void*>(p), &destroy_array, p? &initialize_array_by : &initialize_array );
+00839     }
+00840 
+00842     template<bool B> class is_integer_tag;
+00843 
+00845     template<class I>
+00846     void internal_assign_range(I first, I last, is_integer_tag<true> *) {
+00847         internal_assign_n(static_cast<size_type>(first), &static_cast<T&>(last));
+00848     }
+00850     template<class I>
+00851     void internal_assign_range(I first, I last, is_integer_tag<false> *) {
+00852         internal_assign_iterators(first, last);
+00853     }
+00855     template<class I>
+00856     void internal_assign_iterators(I first, I last);
+00857 
+00859     static void __TBB_EXPORTED_FUNC initialize_array( void* begin, const void*, size_type n );
+00860 
+00862     static void __TBB_EXPORTED_FUNC initialize_array_by( void* begin, const void* src, size_type n );
+00863 
+00865     static void __TBB_EXPORTED_FUNC copy_array( void* dst, const void* src, size_type n );
+00866 
+00868     static void __TBB_EXPORTED_FUNC assign_array( void* dst, const void* src, size_type n );
+00869 
+00871     static void __TBB_EXPORTED_FUNC destroy_array( void* begin, size_type n );
+00872 
+00874     class internal_loop_guide : internal::no_copy {
+00875     public:
+00876         const pointer array;
+00877         const size_type n;
+00878         size_type i;
+00879         internal_loop_guide(size_type ntrials, void *ptr)
+00880             : array(static_cast<pointer>(ptr)), n(ntrials), i(0) {}
+00881         void init() {   for(; i < n; ++i) new( &array[i] ) T(); }
+00882         void init(const void *src) { for(; i < n; ++i) new( &array[i] ) T(*static_cast<const T*>(src)); }
+00883         void copy(const void *src) { for(; i < n; ++i) new( &array[i] ) T(static_cast<const T*>(src)[i]); }
+00884         void assign(const void *src) { for(; i < n; ++i) array[i] = static_cast<const T*>(src)[i]; }
+00885         template<class I> void iterate(I &src) { for(; i < n; ++i, ++src) new( &array[i] ) T( *src ); }
+00886         ~internal_loop_guide() {
+00887             if(i < n) // if exception raised, do zeroing on the rest of items
+00888                 std::memset(array+i, 0, (n-i)*sizeof(value_type));
+00889         }
+00890     };
+00891 };
+00892 
+00893 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
+00894 #pragma warning (push)
+00895 #pragma warning (disable: 4701) // potentially uninitialized local variable "old"
+00896 #endif
+00897 template<typename T, class A>
+00898 void concurrent_vector<T, A>::shrink_to_fit() {
+00899     internal_segments_table old;
+00900     __TBB_TRY {
+00901         if( internal_compact( sizeof(T), &old, &destroy_array, &copy_array ) )
+00902             internal_free_segments( old.table, pointers_per_long_table, old.first_block ); // free joined and unnecessary segments
+00903     } __TBB_CATCH(...) {
+00904         if( old.first_block ) // free segment allocated for compacting. Only for support of exceptions in ctor of user T[ype]
+00905             internal_free_segments( old.table, 1, old.first_block );
+00906         __TBB_RETHROW();
+00907     }
+00908 }
+00909 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
+00910 #pragma warning (pop)
+00911 #endif // warning 4701 is back
+00912 
+00913 template<typename T, class A>
+00914 void concurrent_vector<T, A>::internal_free_segments(void *table[], segment_index_t k, segment_index_t first_block) {
+00915     // Free the arrays
+00916     while( k > first_block ) {
+00917         --k;
+00918         T* array = static_cast<T*>(table[k]);
+00919         table[k] = NULL;
+00920         if( array > internal::vector_allocation_error_flag ) // check for correct segment pointer
+00921             this->my_allocator.deallocate( array, segment_size(k) );
+00922     }
+00923     T* array = static_cast<T*>(table[0]);
+00924     if( array > internal::vector_allocation_error_flag ) {
+00925         __TBB_ASSERT( first_block > 0, NULL );
+00926         while(k > 0) table[--k] = NULL;
+00927         this->my_allocator.deallocate( array, segment_size(first_block) );
+00928     }
+00929 }
+00930 
+00931 template<typename T, class A>
+00932 T& concurrent_vector<T, A>::internal_subscript( size_type index ) const {
+00933     __TBB_ASSERT( index < my_early_size, "index out of bounds" );
+00934     size_type j = index;
+00935     segment_index_t k = segment_base_index_of( j );
+00936     __TBB_ASSERT( (segment_t*)my_segment != my_storage || k < pointers_per_short_table, "index is being allocated" );
+00937     // no need in __TBB_load_with_acquire since thread works in own space or gets 
+00938     T* array = static_cast<T*>( tbb::internal::itt_hide_load_word(my_segment[k].array));
+00939     __TBB_ASSERT( array != internal::vector_allocation_error_flag, "the instance is broken by bad allocation. Use at() instead" );
+00940     __TBB_ASSERT( array, "index is being allocated" );
+00941     return array[j];
+00942 }
+00943 
+00944 template<typename T, class A>
+00945 T& concurrent_vector<T, A>::internal_subscript_with_exceptions( size_type index ) const {
+00946     if( index >= my_early_size )
+00947         internal::throw_exception(internal::eid_out_of_range); // throw std::out_of_range
+00948     size_type j = index;
+00949     segment_index_t k = segment_base_index_of( j );
+00950     if( (segment_t*)my_segment == my_storage && k >= pointers_per_short_table )
+00951         internal::throw_exception(internal::eid_segment_range_error); // throw std::range_error
+00952     void *array = my_segment[k].array; // no need in __TBB_load_with_acquire
+00953     if( array <= internal::vector_allocation_error_flag ) // check for correct segment pointer
+00954         internal::throw_exception(internal::eid_index_range_error); // throw std::range_error
+00955     return static_cast<T*>(array)[j];
+00956 }
+00957 
+00958 template<typename T, class A> template<class I>
+00959 void concurrent_vector<T, A>::internal_assign_iterators(I first, I last) {
+00960     __TBB_ASSERT(my_early_size == 0, NULL);
+00961     size_type n = std::distance(first, last);
+00962     if( !n ) return;
+00963     internal_reserve(n, sizeof(T), max_size());
+00964     my_early_size = n;
+00965     segment_index_t k = 0;
+00966     size_type sz = segment_size( my_first_block );
+00967     while( sz < n ) {
+00968         internal_loop_guide loop(sz, my_segment[k].array);
+00969         loop.iterate(first);
+00970         n -= sz;
+00971         if( !k ) k = my_first_block;
+00972         else { ++k; sz <<= 1; }
+00973     }
+00974     internal_loop_guide loop(n, my_segment[k].array);
+00975     loop.iterate(first);
+00976 }
+00977 
+00978 template<typename T, class A>
+00979 void concurrent_vector<T, A>::initialize_array( void* begin, const void *, size_type n ) {
+00980     internal_loop_guide loop(n, begin); loop.init();
+00981 }
+00982 
+00983 template<typename T, class A>
+00984 void concurrent_vector<T, A>::initialize_array_by( void* begin, const void *src, size_type n ) {
+00985     internal_loop_guide loop(n, begin); loop.init(src);
+00986 }
+00987 
+00988 template<typename T, class A>
+00989 void concurrent_vector<T, A>::copy_array( void* dst, const void* src, size_type n ) {
+00990     internal_loop_guide loop(n, dst); loop.copy(src);
+00991 }
+00992 
+00993 template<typename T, class A>
+00994 void concurrent_vector<T, A>::assign_array( void* dst, const void* src, size_type n ) {
+00995     internal_loop_guide loop(n, dst); loop.assign(src);
+00996 }
+00997 
+00998 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
+00999     // Workaround for overzealous compiler warning
+01000     #pragma warning (push)
+01001     #pragma warning (disable: 4189)
+01002 #endif
+01003 template<typename T, class A>
+01004 void concurrent_vector<T, A>::destroy_array( void* begin, size_type n ) {
+01005     T* array = static_cast<T*>(begin);
+01006     for( size_type j=n; j>0; --j )
+01007         array[j-1].~T(); // destructors are supposed to not throw any exceptions
+01008 }
+01009 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
+01010     #pragma warning (pop)
+01011 #endif // warning 4189 is back
+01012 
+01013 // concurrent_vector's template functions
+01014 template<typename T, class A1, class A2>
+01015 inline bool operator==(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b) {
+01016     // Simply:    return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin());
+01017     if(a.size() != b.size()) return false;
+01018     typename concurrent_vector<T, A1>::const_iterator i(a.begin());
+01019     typename concurrent_vector<T, A2>::const_iterator j(b.begin());
+01020     for(; i != a.end(); ++i, ++j)
+01021         if( !(*i == *j) ) return false;
+01022     return true;
+01023 }
+01024 
+01025 template<typename T, class A1, class A2>
+01026 inline bool operator!=(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b)
+01027 {    return !(a == b); }
+01028 
+01029 template<typename T, class A1, class A2>
+01030 inline bool operator<(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b)
+01031 {    return (std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end())); }
+01032 
+01033 template<typename T, class A1, class A2>
+01034 inline bool operator>(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b)
+01035 {    return b < a; }
+01036 
+01037 template<typename T, class A1, class A2>
+01038 inline bool operator<=(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b)
+01039 {    return !(b < a); }
+01040 
+01041 template<typename T, class A1, class A2>
+01042 inline bool operator>=(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b)
+01043 {    return !(a < b); }
+01044 
+01045 template<typename T, class A>
+01046 inline void swap(concurrent_vector<T, A> &a, concurrent_vector<T, A> &b)
+01047 {    a.swap( b ); }
+01048 
+01049 } // namespace tbb
+01050 
+01051 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_Wp64)
+01052     #pragma warning (pop)
+01053 #endif // warning 4267 is back
+01054 
+01055 #endif /* __TBB_concurrent_vector_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00496.html b/src/tbb/doc/html/a00496.html new file mode 100644 index 0000000..1fd5d87 --- /dev/null +++ b/src/tbb/doc/html/a00496.html @@ -0,0 +1,163 @@ + + +critical_section.h Source File + + + + + + +

critical_section.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef _TBB_CRITICAL_SECTION_H_
+00022 #define _TBB_CRITICAL_SECTION_H_
+00023 
+00024 #if _WIN32||_WIN64
+00025 #include "machine/windows_api.h"
+00026 #else
+00027 #include <pthread.h>
+00028 #include <errno.h>
+00029 #endif  // _WIN32||WIN64
+00030 
+00031 #include "tbb_stddef.h"
+00032 #include "tbb_thread.h"
+00033 #include "tbb_exception.h"
+00034 
+00035 #include "tbb_profiling.h"
+00036 
+00037 namespace tbb {
+00038 
+00039     namespace internal {
+00040 class critical_section_v4 : internal::no_copy {
+00041 #if _WIN32||_WIN64
+00042     CRITICAL_SECTION my_impl;
+00043 #else
+00044     pthread_mutex_t my_impl;
+00045 #endif
+00046     tbb_thread::id my_tid;
+00047 public:
+00048 
+00049     void __TBB_EXPORTED_METHOD internal_construct();
+00050 
+00051     critical_section_v4() { 
+00052 #if _WIN32||_WIN64
+00053         InitializeCriticalSection(&my_impl);
+00054 #else
+00055         pthread_mutex_init(&my_impl, NULL);
+00056 #endif
+00057         internal_construct();
+00058     }
+00059 
+00060     ~critical_section_v4() {
+00061         __TBB_ASSERT(my_tid == tbb_thread::id(), "Destroying a still-held critical section");
+00062 #if _WIN32||_WIN64
+00063         DeleteCriticalSection(&my_impl); 
+00064 #else
+00065         pthread_mutex_destroy(&my_impl);
+00066 #endif
+00067     }
+00068 
+00069     class scoped_lock : internal::no_copy {
+00070     private:
+00071         critical_section_v4 &my_crit;
+00072     public:
+00073         scoped_lock( critical_section_v4& lock_me) :my_crit(lock_me) {
+00074             my_crit.lock();
+00075         }
+00076 
+00077         ~scoped_lock() {
+00078             my_crit.unlock();
+00079         }
+00080     };
+00081 
+00082     void lock() { 
+00083         tbb_thread::id local_tid = this_tbb_thread::get_id();
+00084         if(local_tid == my_tid) throw_exception( eid_improper_lock );
+00085 #if _WIN32||_WIN64
+00086         EnterCriticalSection( &my_impl );
+00087 #else
+00088         int rval = pthread_mutex_lock(&my_impl);
+00089         __TBB_ASSERT_EX(!rval, "critical_section::lock: pthread_mutex_lock failed");
+00090 #endif
+00091         __TBB_ASSERT(my_tid == tbb_thread::id(), NULL);
+00092         my_tid = local_tid;
+00093     }
+00094 
+00095     bool try_lock() {
+00096         bool gotlock;
+00097         tbb_thread::id local_tid = this_tbb_thread::get_id();
+00098         if(local_tid == my_tid) return false;
+00099 #if _WIN32||_WIN64
+00100         gotlock = TryEnterCriticalSection( &my_impl ) != 0;
+00101 #else
+00102         int rval = pthread_mutex_trylock(&my_impl);
+00103         // valid returns are 0 (locked) and [EBUSY]
+00104         __TBB_ASSERT(rval == 0 || rval == EBUSY, "critical_section::trylock: pthread_mutex_trylock failed");
+00105         gotlock = rval == 0;
+00106 #endif
+00107         if(gotlock)  {
+00108             my_tid = local_tid;
+00109         }
+00110         return gotlock;
+00111     }
+00112 
+00113     void unlock() {
+00114         __TBB_ASSERT(this_tbb_thread::get_id() == my_tid, "thread unlocking critical_section is not thread that locked it");
+00115         my_tid = tbb_thread::id();
+00116 #if _WIN32||_WIN64
+00117         LeaveCriticalSection( &my_impl );
+00118 #else
+00119         int rval = pthread_mutex_unlock(&my_impl);
+00120         __TBB_ASSERT_EX(!rval, "critical_section::unlock: pthread_mutex_unlock failed");
+00121 #endif
+00122     }
+00123 
+00124     static const bool is_rw_mutex = false;
+00125     static const bool is_recursive_mutex = false;
+00126     static const bool is_fair_mutex = true;
+00127 }; // critical_section_v4
+00128 } // namespace internal
+00129 typedef internal::critical_section_v4 critical_section;
+00130 
+00131 __TBB_DEFINE_PROFILING_SET_NAME(critical_section)
+00132 } // namespace tbb
+00133 #endif  // _TBB_CRITICAL_SECTION_H_
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00499.html b/src/tbb/doc/html/a00499.html new file mode 100644 index 0000000..a5f13ac --- /dev/null +++ b/src/tbb/doc/html/a00499.html @@ -0,0 +1,964 @@ + + +enumerable_thread_specific.h Source File + + + + + + +

enumerable_thread_specific.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_enumerable_thread_specific_H
+00022 #define __TBB_enumerable_thread_specific_H
+00023 
+00024 #include "concurrent_vector.h"
+00025 #include "tbb_thread.h"
+00026 #include "tbb_allocator.h"
+00027 #include "cache_aligned_allocator.h"
+00028 #include "aligned_space.h"
+00029 #include <string.h>  // for memcpy
+00030 
+00031 #if _WIN32||_WIN64
+00032 #include "machine/windows_api.h"
+00033 #else
+00034 #include <pthread.h>
+00035 #endif
+00036 
+00037 namespace tbb {
+00038 
+00040 enum ets_key_usage_type { ets_key_per_instance, ets_no_key };
+00041 
+00042 namespace interface6 {
+00043  
+00045     namespace internal { 
+00046 
+00047         template<ets_key_usage_type ETS_key_type>
+00048         class ets_base: tbb::internal::no_copy {
+00049         protected:
+00050 #if _WIN32||_WIN64
+00051             typedef DWORD key_type;
+00052 #else
+00053             typedef pthread_t key_type;
+00054 #endif
+00055 #if __TBB_PROTECTED_NESTED_CLASS_BROKEN
+00056         public:
+00057 #endif
+00058             struct slot;
+00059 
+00060             struct array {
+00061                 array* next;
+00062                 size_t lg_size;
+00063                 slot& at( size_t k ) {
+00064                     return ((slot*)(void*)(this+1))[k];
+00065                 }
+00066                 size_t size() const {return (size_t)1<<lg_size;}
+00067                 size_t mask() const {return size()-1;}
+00068                 size_t start( size_t h ) const {
+00069                     return h>>(8*sizeof(size_t)-lg_size);
+00070                 }
+00071             };
+00072             struct slot {
+00073                 key_type key;
+00074                 void* ptr;
+00075                 bool empty() const {return !key;}
+00076                 bool match( key_type k ) const {return key==k;}
+00077                 bool claim( key_type k ) {
+00078                     __TBB_ASSERT(sizeof(tbb::atomic<key_type>)==sizeof(key_type), NULL);
+00079                     return tbb::internal::punned_cast<tbb::atomic<key_type>*>(&key)->compare_and_swap(k,0)==0;
+00080                 }
+00081             };
+00082 #if __TBB_PROTECTED_NESTED_CLASS_BROKEN
+00083         protected:
+00084 #endif
+00085         
+00086             static key_type key_of_current_thread() {
+00087                tbb::tbb_thread::id id = tbb::this_tbb_thread::get_id();
+00088                key_type k;
+00089                memcpy( &k, &id, sizeof(k) );
+00090                return k;
+00091             }
+00092 
+00094 
+00096             atomic<array*> my_root;
+00097             atomic<size_t> my_count;
+00098             virtual void* create_local() = 0;
+00099             virtual void* create_array(size_t _size) = 0;  // _size in bytes
+00100             virtual void free_array(void* ptr, size_t _size) = 0; // _size in bytes
+00101             array* allocate( size_t lg_size ) {
+00102                 size_t n = 1<<lg_size;  
+00103                 array* a = static_cast<array*>(create_array( sizeof(array)+n*sizeof(slot) ));
+00104                 a->lg_size = lg_size;
+00105                 std::memset( a+1, 0, n*sizeof(slot) );
+00106                 return a;
+00107             }
+00108             void free(array* a) {
+00109                 size_t n = 1<<(a->lg_size);  
+00110                 free_array( (void *)a, size_t(sizeof(array)+n*sizeof(slot)) );
+00111             }
+00112             static size_t hash( key_type k ) {
+00113                 // Multiplicative hashing.  Client should use *upper* bits.
+00114                 // casts required for Mac gcc4.* compiler
+00115                 return uintptr_t(k)*tbb::internal::size_t_select(0x9E3779B9,0x9E3779B97F4A7C15ULL);
+00116             } 
+00117         
+00118             ets_base() {my_root=NULL; my_count=0;}
+00119             virtual ~ets_base();  // g++ complains if this is not virtual...
+00120             void* table_lookup( bool& exists );
+00121             void table_clear();
+00122             slot& table_find( key_type k ) {
+00123                 size_t h = hash(k);
+00124                 array* r = my_root;
+00125                 size_t mask = r->mask();
+00126                 for(size_t i = r->start(h);;i=(i+1)&mask) {
+00127                     slot& s = r->at(i);
+00128                     if( s.empty() || s.match(k) )
+00129                         return s;
+00130                 }
+00131             }
+00132             void table_reserve_for_copy( const ets_base& other ) {
+00133                 __TBB_ASSERT(!my_root,NULL);
+00134                 __TBB_ASSERT(!my_count,NULL);
+00135                 if( other.my_root ) {
+00136                     array* a = allocate(other.my_root->lg_size);
+00137                     a->next = NULL;
+00138                     my_root = a;
+00139                     my_count = other.my_count;
+00140                 }
+00141             }
+00142         };
+00143 
+00144         template<ets_key_usage_type ETS_key_type>
+00145         ets_base<ETS_key_type>::~ets_base() {
+00146             __TBB_ASSERT(!my_root, NULL);
+00147         }
+00148 
+00149         template<ets_key_usage_type ETS_key_type>
+00150         void ets_base<ETS_key_type>::table_clear() {
+00151             while( array* r = my_root ) {
+00152                 my_root = r->next;
+00153                 free(r);
+00154             }
+00155             my_count = 0;
+00156         }
+00157                 
+00158         template<ets_key_usage_type ETS_key_type>
+00159         void* ets_base<ETS_key_type>::table_lookup( bool& exists ) {
+00160             const key_type k = key_of_current_thread(); 
+00161 
+00162             __TBB_ASSERT(k!=0,NULL);
+00163             void* found;
+00164             size_t h = hash(k);
+00165             for( array* r=my_root; r; r=r->next ) {
+00166                 size_t mask=r->mask();
+00167                 for(size_t i = r->start(h); ;i=(i+1)&mask) {
+00168                     slot& s = r->at(i);
+00169                     if( s.empty() ) break;
+00170                     if( s.match(k) ) {
+00171                         if( r==my_root ) {
+00172                             // Success at top level
+00173                             exists = true;
+00174                             return s.ptr;
+00175                         } else {
+00176                             // Success at some other level.  Need to insert at top level.
+00177                             exists = true;
+00178                             found = s.ptr;
+00179                             goto insert;
+00180                         }
+00181                     }
+00182                 }
+00183             }
+00184             // Key does not yet exist
+00185             exists = false;
+00186             found = create_local();
+00187             {
+00188                 size_t c = ++my_count;
+00189                 array* r = my_root;
+00190                 if( !r || c>r->size()/2 ) {
+00191                     size_t s = r ? r->lg_size : 2;
+00192                     while( c>size_t(1)<<(s-1) ) ++s;
+00193                     array* a = allocate(s);
+00194                     for(;;) {
+00195                         a->next = my_root;
+00196                         array* new_r = my_root.compare_and_swap(a,r);
+00197                         if( new_r==r ) break;
+00198                         if( new_r->lg_size>=s ) {
+00199                             // Another thread inserted an equal or  bigger array, so our array is superfluous.
+00200                             free(a);
+00201                             break;
+00202                         }
+00203                         r = new_r;
+00204                     }
+00205                 }
+00206             }
+00207         insert:
+00208             // Guaranteed to be room for it, and it is not present, so search for empty slot and grab it.
+00209             array* ir = my_root;
+00210             size_t mask = ir->mask();
+00211             for(size_t i = ir->start(h);;i=(i+1)&mask) {
+00212                 slot& s = ir->at(i);
+00213                 if( s.empty() ) {
+00214                     if( s.claim(k) ) {
+00215                         s.ptr = found;
+00216                         return found;
+00217                     }
+00218                 }
+00219             }
+00220         }
+00221 
+00223         template <>
+00224         class ets_base<ets_key_per_instance>: protected ets_base<ets_no_key> {
+00225             typedef ets_base<ets_no_key> super;
+00226 #if _WIN32||_WIN64
+00227             typedef DWORD tls_key_t;
+00228             void create_key() { my_key = TlsAlloc(); }
+00229             void destroy_key() { TlsFree(my_key); }
+00230             void set_tls(void * value) { TlsSetValue(my_key, (LPVOID)value); }
+00231             void* get_tls() { return (void *)TlsGetValue(my_key); }
+00232 #else
+00233             typedef pthread_key_t tls_key_t;
+00234             void create_key() { pthread_key_create(&my_key, NULL); }
+00235             void destroy_key() { pthread_key_delete(my_key); }
+00236             void set_tls( void * value ) const { pthread_setspecific(my_key, value); }
+00237             void* get_tls() const { return pthread_getspecific(my_key); }
+00238 #endif
+00239             tls_key_t my_key;
+00240             virtual void* create_local() = 0;
+00241             virtual void* create_array(size_t _size) = 0;  // _size in bytes
+00242             virtual void free_array(void* ptr, size_t _size) = 0; // size in bytes
+00243         public:
+00244             ets_base() {create_key();}
+00245             ~ets_base() {destroy_key();}
+00246             void* table_lookup( bool& exists ) {
+00247                 void* found = get_tls();
+00248                 if( found ) {
+00249                     exists=true;
+00250                 } else {
+00251                     found = super::table_lookup(exists);
+00252                     set_tls(found);
+00253                 }
+00254                 return found; 
+00255             }
+00256             void table_clear() {
+00257                 destroy_key();
+00258                 create_key(); 
+00259                 super::table_clear();
+00260             }
+00261         };
+00262 
+00264         template< typename Container, typename Value >
+00265         class enumerable_thread_specific_iterator 
+00266 #if defined(_WIN64) && defined(_MSC_VER) 
+00267             // Ensure that Microsoft's internal template function _Val_type works correctly.
+00268             : public std::iterator<std::random_access_iterator_tag,Value>
+00269 #endif /* defined(_WIN64) && defined(_MSC_VER) */
+00270         {
+00272         
+00273             Container *my_container;
+00274             typename Container::size_type my_index;
+00275             mutable Value *my_value;
+00276         
+00277             template<typename C, typename T>
+00278             friend enumerable_thread_specific_iterator<C,T> operator+( ptrdiff_t offset, 
+00279                                                                        const enumerable_thread_specific_iterator<C,T>& v );
+00280         
+00281             template<typename C, typename T, typename U>
+00282             friend bool operator==( const enumerable_thread_specific_iterator<C,T>& i, 
+00283                                     const enumerable_thread_specific_iterator<C,U>& j );
+00284         
+00285             template<typename C, typename T, typename U>
+00286             friend bool operator<( const enumerable_thread_specific_iterator<C,T>& i, 
+00287                                    const enumerable_thread_specific_iterator<C,U>& j );
+00288         
+00289             template<typename C, typename T, typename U>
+00290             friend ptrdiff_t operator-( const enumerable_thread_specific_iterator<C,T>& i, const enumerable_thread_specific_iterator<C,U>& j );
+00291             
+00292             template<typename C, typename U> 
+00293             friend class enumerable_thread_specific_iterator;
+00294         
+00295             public:
+00296         
+00297             enumerable_thread_specific_iterator( const Container &container, typename Container::size_type index ) : 
+00298                 my_container(&const_cast<Container &>(container)), my_index(index), my_value(NULL) {}
+00299         
+00301             enumerable_thread_specific_iterator() : my_container(NULL), my_index(0), my_value(NULL) {}
+00302         
+00303             template<typename U>
+00304             enumerable_thread_specific_iterator( const enumerable_thread_specific_iterator<Container, U>& other ) :
+00305                     my_container( other.my_container ), my_index( other.my_index), my_value( const_cast<Value *>(other.my_value) ) {}
+00306         
+00307             enumerable_thread_specific_iterator operator+( ptrdiff_t offset ) const {
+00308                 return enumerable_thread_specific_iterator(*my_container, my_index + offset);
+00309             }
+00310         
+00311             enumerable_thread_specific_iterator &operator+=( ptrdiff_t offset ) {
+00312                 my_index += offset;
+00313                 my_value = NULL;
+00314                 return *this;
+00315             }
+00316         
+00317             enumerable_thread_specific_iterator operator-( ptrdiff_t offset ) const {
+00318                 return enumerable_thread_specific_iterator( *my_container, my_index-offset );
+00319             }
+00320         
+00321             enumerable_thread_specific_iterator &operator-=( ptrdiff_t offset ) {
+00322                 my_index -= offset;
+00323                 my_value = NULL;
+00324                 return *this;
+00325             }
+00326         
+00327             Value& operator*() const {
+00328                 Value* value = my_value;
+00329                 if( !value ) {
+00330                     value = my_value = reinterpret_cast<Value *>(&(*my_container)[my_index].value);
+00331                 }
+00332                 __TBB_ASSERT( value==reinterpret_cast<Value *>(&(*my_container)[my_index].value), "corrupt cache" );
+00333                 return *value;
+00334             }
+00335         
+00336             Value& operator[]( ptrdiff_t k ) const {
+00337                return (*my_container)[my_index + k].value;
+00338             }
+00339         
+00340             Value* operator->() const {return &operator*();}
+00341         
+00342             enumerable_thread_specific_iterator& operator++() {
+00343                 ++my_index;
+00344                 my_value = NULL;
+00345                 return *this;
+00346             }
+00347         
+00348             enumerable_thread_specific_iterator& operator--() {
+00349                 --my_index;
+00350                 my_value = NULL;
+00351                 return *this;
+00352             }
+00353         
+00355             enumerable_thread_specific_iterator operator++(int) {
+00356                 enumerable_thread_specific_iterator result = *this;
+00357                 ++my_index;
+00358                 my_value = NULL;
+00359                 return result;
+00360             }
+00361         
+00363             enumerable_thread_specific_iterator operator--(int) {
+00364                 enumerable_thread_specific_iterator result = *this;
+00365                 --my_index;
+00366                 my_value = NULL;
+00367                 return result;
+00368             }
+00369         
+00370             // STL support
+00371             typedef ptrdiff_t difference_type;
+00372             typedef Value value_type;
+00373             typedef Value* pointer;
+00374             typedef Value& reference;
+00375             typedef std::random_access_iterator_tag iterator_category;
+00376         };
+00377         
+00378         template<typename Container, typename T>
+00379         enumerable_thread_specific_iterator<Container,T> operator+( ptrdiff_t offset, 
+00380                                                                     const enumerable_thread_specific_iterator<Container,T>& v ) {
+00381             return enumerable_thread_specific_iterator<Container,T>( v.my_container, v.my_index + offset );
+00382         }
+00383         
+00384         template<typename Container, typename T, typename U>
+00385         bool operator==( const enumerable_thread_specific_iterator<Container,T>& i, 
+00386                          const enumerable_thread_specific_iterator<Container,U>& j ) {
+00387             return i.my_index==j.my_index && i.my_container == j.my_container;
+00388         }
+00389         
+00390         template<typename Container, typename T, typename U>
+00391         bool operator!=( const enumerable_thread_specific_iterator<Container,T>& i, 
+00392                          const enumerable_thread_specific_iterator<Container,U>& j ) {
+00393             return !(i==j);
+00394         }
+00395         
+00396         template<typename Container, typename T, typename U>
+00397         bool operator<( const enumerable_thread_specific_iterator<Container,T>& i, 
+00398                         const enumerable_thread_specific_iterator<Container,U>& j ) {
+00399             return i.my_index<j.my_index;
+00400         }
+00401         
+00402         template<typename Container, typename T, typename U>
+00403         bool operator>( const enumerable_thread_specific_iterator<Container,T>& i, 
+00404                         const enumerable_thread_specific_iterator<Container,U>& j ) {
+00405             return j<i;
+00406         }
+00407         
+00408         template<typename Container, typename T, typename U>
+00409         bool operator>=( const enumerable_thread_specific_iterator<Container,T>& i, 
+00410                          const enumerable_thread_specific_iterator<Container,U>& j ) {
+00411             return !(i<j);
+00412         }
+00413         
+00414         template<typename Container, typename T, typename U>
+00415         bool operator<=( const enumerable_thread_specific_iterator<Container,T>& i, 
+00416                          const enumerable_thread_specific_iterator<Container,U>& j ) {
+00417             return !(j<i);
+00418         }
+00419         
+00420         template<typename Container, typename T, typename U>
+00421         ptrdiff_t operator-( const enumerable_thread_specific_iterator<Container,T>& i, 
+00422                              const enumerable_thread_specific_iterator<Container,U>& j ) {
+00423             return i.my_index-j.my_index;
+00424         }
+00425 
+00426     template<typename SegmentedContainer, typename Value >
+00427         class segmented_iterator
+00428 #if defined(_WIN64) && defined(_MSC_VER)
+00429         : public std::iterator<std::input_iterator_tag, Value>
+00430 #endif
+00431         {
+00432             template<typename C, typename T, typename U>
+00433             friend bool operator==(const segmented_iterator<C,T>& i, const segmented_iterator<C,U>& j);
+00434 
+00435             template<typename C, typename T, typename U>
+00436             friend bool operator!=(const segmented_iterator<C,T>& i, const segmented_iterator<C,U>& j);
+00437             
+00438             template<typename C, typename U> 
+00439             friend class segmented_iterator;
+00440 
+00441             public:
+00442 
+00443                 segmented_iterator() {my_segcont = NULL;}
+00444 
+00445                 segmented_iterator( const SegmentedContainer& _segmented_container ) : 
+00446                     my_segcont(const_cast<SegmentedContainer*>(&_segmented_container)),
+00447                     outer_iter(my_segcont->end()) { }
+00448 
+00449                 ~segmented_iterator() {}
+00450 
+00451                 typedef typename SegmentedContainer::iterator outer_iterator;
+00452                 typedef typename SegmentedContainer::value_type InnerContainer;
+00453                 typedef typename InnerContainer::iterator inner_iterator;
+00454 
+00455                 // STL support
+00456                 typedef ptrdiff_t difference_type;
+00457                 typedef Value value_type;
+00458                 typedef typename SegmentedContainer::size_type size_type;
+00459                 typedef Value* pointer;
+00460                 typedef Value& reference;
+00461                 typedef std::input_iterator_tag iterator_category;
+00462 
+00463                 // Copy Constructor
+00464                 template<typename U>
+00465                 segmented_iterator(const segmented_iterator<SegmentedContainer, U>& other) :
+00466                     my_segcont(other.my_segcont),
+00467                     outer_iter(other.outer_iter),
+00468                     // can we assign a default-constructed iterator to inner if we're at the end?
+00469                     inner_iter(other.inner_iter)
+00470                 {}
+00471 
+00472                 // assignment
+00473                 template<typename U>
+00474                 segmented_iterator& operator=( const segmented_iterator<SegmentedContainer, U>& other) {
+00475                     if(this != &other) {
+00476                         my_segcont = other.my_segcont;
+00477                         outer_iter = other.outer_iter;
+00478                         if(outer_iter != my_segcont->end()) inner_iter = other.inner_iter;
+00479                     }
+00480                     return *this;
+00481                 }
+00482 
+00483                 // allow assignment of outer iterator to segmented iterator.  Once it is
+00484                 // assigned, move forward until a non-empty inner container is found or
+00485                 // the end of the outer container is reached.
+00486                 segmented_iterator& operator=(const outer_iterator& new_outer_iter) {
+00487                     __TBB_ASSERT(my_segcont != NULL, NULL);
+00488                     // check that this iterator points to something inside the segmented container
+00489                     for(outer_iter = new_outer_iter ;outer_iter!=my_segcont->end(); ++outer_iter) {
+00490                         if( !outer_iter->empty() ) {
+00491                             inner_iter = outer_iter->begin();
+00492                             break;
+00493                         }
+00494                     }
+00495                     return *this;
+00496                 }
+00497 
+00498                 // pre-increment
+00499                 segmented_iterator& operator++() {
+00500                     advance_me();
+00501                     return *this;
+00502                 }
+00503 
+00504                 // post-increment
+00505                 segmented_iterator operator++(int) {
+00506                     segmented_iterator tmp = *this;
+00507                     operator++();
+00508                     return tmp;
+00509                 }
+00510 
+00511                 bool operator==(const outer_iterator& other_outer) const {
+00512                     __TBB_ASSERT(my_segcont != NULL, NULL);
+00513                     return (outer_iter == other_outer &&
+00514                             (outer_iter == my_segcont->end() || inner_iter == outer_iter->begin()));
+00515                 }
+00516 
+00517                 bool operator!=(const outer_iterator& other_outer) const {
+00518                     return !operator==(other_outer);
+00519 
+00520                 }
+00521 
+00522                 // (i)* RHS
+00523                 reference operator*() const {
+00524                     __TBB_ASSERT(my_segcont != NULL, NULL);
+00525                     __TBB_ASSERT(outer_iter != my_segcont->end(), "Dereferencing a pointer at end of container");
+00526                     __TBB_ASSERT(inner_iter != outer_iter->end(), NULL); // should never happen
+00527                     return *inner_iter;
+00528                 }
+00529 
+00530                 // i->
+00531                 pointer operator->() const { return &operator*();}
+00532 
+00533             private:
+00534                 SegmentedContainer*             my_segcont;
+00535                 outer_iterator outer_iter;
+00536                 inner_iterator inner_iter;
+00537 
+00538                 void advance_me() {
+00539                     __TBB_ASSERT(my_segcont != NULL, NULL);
+00540                     __TBB_ASSERT(outer_iter != my_segcont->end(), NULL); // not true if there are no inner containers
+00541                     __TBB_ASSERT(inner_iter != outer_iter->end(), NULL); // not true if the inner containers are all empty.
+00542                     ++inner_iter;
+00543                     while(inner_iter == outer_iter->end() && ++outer_iter != my_segcont->end()) {
+00544                         inner_iter = outer_iter->begin();
+00545                     }
+00546                 }
+00547         };    // segmented_iterator
+00548 
+00549         template<typename SegmentedContainer, typename T, typename U>
+00550         bool operator==( const segmented_iterator<SegmentedContainer,T>& i, 
+00551                          const segmented_iterator<SegmentedContainer,U>& j ) {
+00552             if(i.my_segcont != j.my_segcont) return false;
+00553             if(i.my_segcont == NULL) return true;
+00554             if(i.outer_iter != j.outer_iter) return false;
+00555             if(i.outer_iter == i.my_segcont->end()) return true;
+00556             return i.inner_iter == j.inner_iter;
+00557         }
+00558 
+00559         // !=
+00560         template<typename SegmentedContainer, typename T, typename U>
+00561         bool operator!=( const segmented_iterator<SegmentedContainer,T>& i, 
+00562                          const segmented_iterator<SegmentedContainer,U>& j ) {
+00563             return !(i==j);
+00564         }
+00565 
+00566         template<typename T>
+00567         struct destruct_only: tbb::internal::no_copy {
+00568             tbb::aligned_space<T,1> value;
+00569             ~destruct_only() {value.begin()[0].~T();}
+00570         };
+00571 
+00572         template<typename T>
+00573         struct construct_by_default: tbb::internal::no_assign {
+00574             void construct(void*where) {new(where) T();} // C++ note: the () in T() ensure zero initialization.
+00575             construct_by_default( int ) {}
+00576         };
+00577 
+00578         template<typename T>
+00579         struct construct_by_exemplar: tbb::internal::no_assign {
+00580             const T exemplar;
+00581             void construct(void*where) {new(where) T(exemplar);}
+00582             construct_by_exemplar( const T& t ) : exemplar(t) {}
+00583         };
+00584 
+00585         template<typename T, typename Finit>
+00586         struct construct_by_finit: tbb::internal::no_assign {
+00587             Finit f;
+00588             void construct(void* where) {new(where) T(f());}
+00589             construct_by_finit( const Finit& f_ ) : f(f_) {}
+00590         };
+00591 
+00592         // storage for initialization function pointer
+00593         template<typename T>
+00594         class callback_base {
+00595         public:
+00596             // Clone *this
+00597             virtual callback_base* clone() = 0;
+00598             // Destruct and free *this
+00599             virtual void destroy() = 0;
+00600             // Need virtual destructor to satisfy GCC compiler warning
+00601             virtual ~callback_base() { }
+00602             // Construct T at where
+00603             virtual void construct(void* where) = 0;
+00604         };
+00605 
+00606         template <typename T, typename Constructor>
+00607         class callback_leaf: public callback_base<T>, Constructor {
+00608             template<typename X> callback_leaf( const X& x ) : Constructor(x) {}
+00609 
+00610             typedef typename tbb::tbb_allocator<callback_leaf> my_allocator_type;
+00611 
+00612             /*override*/ callback_base<T>* clone() {
+00613                 void* where = my_allocator_type().allocate(1);
+00614                 return new(where) callback_leaf(*this);
+00615             }
+00616 
+00617             /*override*/ void destroy() {
+00618                 my_allocator_type().destroy(this);
+00619                 my_allocator_type().deallocate(this,1);
+00620             }
+00621 
+00622             /*override*/ void construct(void* where) {
+00623                 Constructor::construct(where);
+00624             }  
+00625         public:
+00626             template<typename X>
+00627             static callback_base<T>* make( const X& x ) {
+00628                 void* where = my_allocator_type().allocate(1);
+00629                 return new(where) callback_leaf(x);
+00630             }
+00631         };
+00632 
+00634 
+00639         template<typename U, size_t ModularSize>
+00640         struct ets_element {
+00641             char value[ModularSize==0 ? sizeof(U) : sizeof(U)+(tbb::internal::NFS_MaxLineSize-ModularSize)];
+00642             void unconstruct() {
+00643                 tbb::internal::punned_cast<U*>(&value)->~U();
+00644             }
+00645         };
+00646 
+00647     } // namespace internal
+00649 
+00651 
+00670     template <typename T, 
+00671               typename Allocator=cache_aligned_allocator<T>, 
+00672               ets_key_usage_type ETS_key_type=ets_no_key > 
+00673     class enumerable_thread_specific: internal::ets_base<ETS_key_type> { 
+00674 
+00675         template<typename U, typename A, ets_key_usage_type C> friend class enumerable_thread_specific;
+00676     
+00677         typedef internal::ets_element<T,sizeof(T)%tbb::internal::NFS_MaxLineSize> padded_element;
+00678 
+00680         template<typename I>
+00681         class generic_range_type: public blocked_range<I> {
+00682         public:
+00683             typedef T value_type;
+00684             typedef T& reference;
+00685             typedef const T& const_reference;
+00686             typedef I iterator;
+00687             typedef ptrdiff_t difference_type;
+00688             generic_range_type( I begin_, I end_, size_t grainsize_ = 1) : blocked_range<I>(begin_,end_,grainsize_) {} 
+00689             template<typename U>
+00690             generic_range_type( const generic_range_type<U>& r) : blocked_range<I>(r.begin(),r.end(),r.grainsize()) {} 
+00691             generic_range_type( generic_range_type& r, split ) : blocked_range<I>(r,split()) {}
+00692         };
+00693     
+00694         typedef typename Allocator::template rebind< padded_element >::other padded_allocator_type;
+00695         typedef tbb::concurrent_vector< padded_element, padded_allocator_type > internal_collection_type;
+00696         
+00697         internal::callback_base<T> *my_construct_callback;
+00698 
+00699         internal_collection_type my_locals;
+00700    
+00701         /*override*/ void* create_local() {
+00702 #if TBB_DEPRECATED
+00703             void* lref = &my_locals[my_locals.push_back(padded_element())];
+00704 #else
+00705             void* lref = &*my_locals.push_back(padded_element());
+00706 #endif
+00707             my_construct_callback->construct(lref);
+00708             return lref;
+00709         } 
+00710 
+00711         void unconstruct_locals() {
+00712             for(typename internal_collection_type::iterator cvi = my_locals.begin(); cvi != my_locals.end(); ++cvi) {
+00713                 cvi->unconstruct();
+00714             }
+00715         }
+00716 
+00717         typedef typename Allocator::template rebind< uintptr_t >::other array_allocator_type;
+00718 
+00719         // _size is in bytes
+00720         /*override*/ void* create_array(size_t _size) {
+00721             size_t nelements = (_size + sizeof(uintptr_t) -1) / sizeof(uintptr_t);
+00722             return array_allocator_type().allocate(nelements);
+00723         }
+00724 
+00725         /*override*/ void free_array( void* _ptr, size_t _size) {
+00726             size_t nelements = (_size + sizeof(uintptr_t) -1) / sizeof(uintptr_t);
+00727             array_allocator_type().deallocate( reinterpret_cast<uintptr_t *>(_ptr),nelements);
+00728         }
+00729    
+00730     public:
+00731     
+00733         typedef Allocator allocator_type;
+00734         typedef T value_type;
+00735         typedef T& reference;
+00736         typedef const T& const_reference;
+00737         typedef T* pointer;
+00738         typedef const T* const_pointer;
+00739         typedef typename internal_collection_type::size_type size_type;
+00740         typedef typename internal_collection_type::difference_type difference_type;
+00741     
+00742         // Iterator types
+00743         typedef typename internal::enumerable_thread_specific_iterator< internal_collection_type, value_type > iterator;
+00744         typedef typename internal::enumerable_thread_specific_iterator< internal_collection_type, const value_type > const_iterator;
+00745 
+00746         // Parallel range types
+00747         typedef generic_range_type< iterator > range_type;
+00748         typedef generic_range_type< const_iterator > const_range_type;
+00749     
+00751         enumerable_thread_specific() : 
+00752             my_construct_callback( internal::callback_leaf<T,internal::construct_by_default<T> >::make(/*dummy argument*/0) ) 
+00753         {}
+00754 
+00756         template <typename Finit>
+00757         enumerable_thread_specific( Finit finit ) : 
+00758             my_construct_callback( internal::callback_leaf<T,internal::construct_by_finit<T,Finit> >::make( finit ) ) 
+00759         {}
+00760     
+00762         enumerable_thread_specific(const T& exemplar) : 
+00763             my_construct_callback( internal::callback_leaf<T,internal::construct_by_exemplar<T> >::make( exemplar ) )
+00764         {}
+00765     
+00767         ~enumerable_thread_specific() { 
+00768             my_construct_callback->destroy();
+00769             this->clear();  // deallocation before the derived class is finished destructing
+00770             // So free(array *) is still accessible
+00771         }
+00772       
+00774         reference local() {
+00775             bool exists;
+00776             return local(exists);
+00777         }
+00778 
+00780         reference local(bool& exists)  {
+00781             void* ptr = this->table_lookup(exists);
+00782             return *(T*)ptr;
+00783         }
+00784 
+00786         size_type size() const { return my_locals.size(); }
+00787     
+00789         bool empty() const { return my_locals.empty(); }
+00790     
+00792         iterator begin() { return iterator( my_locals, 0 ); }
+00794         iterator end() { return iterator(my_locals, my_locals.size() ); }
+00795     
+00797         const_iterator begin() const { return const_iterator(my_locals, 0); }
+00798     
+00800         const_iterator end() const { return const_iterator(my_locals, my_locals.size()); }
+00801 
+00803         range_type range( size_t grainsize=1 ) { return range_type( begin(), end(), grainsize ); } 
+00804         
+00806         const_range_type range( size_t grainsize=1 ) const { return const_range_type( begin(), end(), grainsize ); }
+00807 
+00809         void clear() {
+00810             unconstruct_locals();
+00811             my_locals.clear();
+00812             this->table_clear();
+00813             // callback is not destroyed
+00814             // exemplar is not destroyed
+00815         }
+00816 
+00817     private:
+00818 
+00819         template<typename U, typename A2, ets_key_usage_type C2>
+00820         void internal_copy( const enumerable_thread_specific<U, A2, C2>& other);
+00821 
+00822     public:
+00823 
+00824         template<typename U, typename Alloc, ets_key_usage_type Cachetype>
+00825         enumerable_thread_specific( const enumerable_thread_specific<U, Alloc, Cachetype>& other ) : internal::ets_base<ETS_key_type> ()
+00826         {
+00827             internal_copy(other);
+00828         }
+00829 
+00830         enumerable_thread_specific( const enumerable_thread_specific& other ) : internal::ets_base<ETS_key_type> ()
+00831         {
+00832             internal_copy(other);
+00833         }
+00834 
+00835     private:
+00836 
+00837         template<typename U, typename A2, ets_key_usage_type C2>
+00838         enumerable_thread_specific &
+00839         internal_assign(const enumerable_thread_specific<U, A2, C2>& other) {
+00840             if(static_cast<void *>( this ) != static_cast<const void *>( &other )) {
+00841                 this->clear(); 
+00842                 my_construct_callback->destroy();
+00843                 my_construct_callback = 0;
+00844                 internal_copy( other );
+00845             }
+00846             return *this;
+00847         }
+00848 
+00849     public:
+00850 
+00851         // assignment
+00852         enumerable_thread_specific& operator=(const enumerable_thread_specific& other) {
+00853             return internal_assign(other);
+00854         }
+00855 
+00856         template<typename U, typename Alloc, ets_key_usage_type Cachetype>
+00857         enumerable_thread_specific& operator=(const enumerable_thread_specific<U, Alloc, Cachetype>& other)
+00858         {
+00859             return internal_assign(other);
+00860         }
+00861 
+00862         // combine_func_t has signature T(T,T) or T(const T&, const T&)
+00863         template <typename combine_func_t>
+00864         T combine(combine_func_t f_combine) {
+00865             if(begin() == end()) {
+00866                 internal::destruct_only<T> location;
+00867                 my_construct_callback->construct(location.value.begin());
+00868                 return *location.value.begin();
+00869             }
+00870             const_iterator ci = begin();
+00871             T my_result = *ci;
+00872             while(++ci != end()) 
+00873                 my_result = f_combine( my_result, *ci );
+00874             return my_result;
+00875         }
+00876 
+00877         // combine_func_t has signature void(T) or void(const T&)
+00878         template <typename combine_func_t>
+00879         void combine_each(combine_func_t f_combine) {
+00880             for(const_iterator ci = begin(); ci != end(); ++ci) {
+00881                 f_combine( *ci );
+00882             }
+00883         }
+00884 
+00885     }; // enumerable_thread_specific
+00886 
+00887     template <typename T, typename Allocator, ets_key_usage_type ETS_key_type> 
+00888     template<typename U, typename A2, ets_key_usage_type C2>
+00889     void enumerable_thread_specific<T,Allocator,ETS_key_type>::internal_copy( const enumerable_thread_specific<U, A2, C2>& other) {
+00890         // Initialize my_construct_callback first, so that it is valid even if rest of this routine throws an exception.
+00891         my_construct_callback = other.my_construct_callback->clone();
+00892 
+00893         typedef internal::ets_base<ets_no_key> base;
+00894         __TBB_ASSERT(my_locals.size()==0,NULL);
+00895         this->table_reserve_for_copy( other );
+00896         for( base::array* r=other.my_root; r; r=r->next ) {
+00897             for( size_t i=0; i<r->size(); ++i ) {
+00898                 base::slot& s1 = r->at(i);
+00899                 if( !s1.empty() ) {
+00900                     base::slot& s2 = this->table_find(s1.key);
+00901                     if( s2.empty() ) { 
+00902 #if TBB_DEPRECATED
+00903                         void* lref = &my_locals[my_locals.push_back(padded_element())];
+00904 #else
+00905                         void* lref = &*my_locals.push_back(padded_element());
+00906 #endif
+00907                         s2.ptr = new(lref) T(*(U*)s1.ptr);
+00908                         s2.key = s1.key;
+00909                     } else {
+00910                         // Skip the duplicate
+00911                     } 
+00912                 }
+00913             }
+00914         }
+00915     }
+00916 
+00917     template< typename Container >
+00918     class flattened2d {
+00919 
+00920         // This intermediate typedef is to address issues with VC7.1 compilers
+00921         typedef typename Container::value_type conval_type;
+00922 
+00923     public:
+00924 
+00926         typedef typename conval_type::size_type size_type;
+00927         typedef typename conval_type::difference_type difference_type;
+00928         typedef typename conval_type::allocator_type allocator_type;
+00929         typedef typename conval_type::value_type value_type;
+00930         typedef typename conval_type::reference reference;
+00931         typedef typename conval_type::const_reference const_reference;
+00932         typedef typename conval_type::pointer pointer;
+00933         typedef typename conval_type::const_pointer const_pointer;
+00934 
+00935         typedef typename internal::segmented_iterator<Container, value_type> iterator;
+00936         typedef typename internal::segmented_iterator<Container, const value_type> const_iterator;
+00937 
+00938         flattened2d( const Container &c, typename Container::const_iterator b, typename Container::const_iterator e ) : 
+00939             my_container(const_cast<Container*>(&c)), my_begin(b), my_end(e) { }
+00940 
+00941         flattened2d( const Container &c ) : 
+00942             my_container(const_cast<Container*>(&c)), my_begin(c.begin()), my_end(c.end()) { }
+00943 
+00944         iterator begin() { return iterator(*my_container) = my_begin; }
+00945         iterator end() { return iterator(*my_container) = my_end; }
+00946         const_iterator begin() const { return const_iterator(*my_container) = my_begin; }
+00947         const_iterator end() const { return const_iterator(*my_container) = my_end; }
+00948 
+00949         size_type size() const {
+00950             size_type tot_size = 0;
+00951             for(typename Container::const_iterator i = my_begin; i != my_end; ++i) {
+00952                 tot_size += i->size();
+00953             }
+00954             return tot_size;
+00955         }
+00956 
+00957     private:
+00958 
+00959         Container *my_container;
+00960         typename Container::const_iterator my_begin;
+00961         typename Container::const_iterator my_end;
+00962 
+00963     };
+00964 
+00965     template <typename Container>
+00966     flattened2d<Container> flatten2d(const Container &c, const typename Container::const_iterator b, const typename Container::const_iterator e) {
+00967         return flattened2d<Container>(c, b, e);
+00968     }
+00969 
+00970     template <typename Container>
+00971     flattened2d<Container> flatten2d(const Container &c) {
+00972         return flattened2d<Container>(c);
+00973     }
+00974 
+00975 } // interface6
+00976 
+00977 namespace internal {
+00978 using interface6::internal::segmented_iterator;
+00979 }
+00980 
+00981 using interface6::enumerable_thread_specific;
+00982 using interface6::flattened2d;
+00983 using interface6::flatten2d;
+00984 
+00985 } // namespace tbb
+00986 
+00987 #endif
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00511.html b/src/tbb/doc/html/a00511.html new file mode 100644 index 0000000..a918e30 --- /dev/null +++ b/src/tbb/doc/html/a00511.html @@ -0,0 +1,1655 @@ + + +flow_graph.h Source File + + + + + + +

flow_graph.h

Go to the documentation of this file.
00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_flow_graph_H
+00022 #define __TBB_flow_graph_H
+00023 
+00024 #include "tbb_stddef.h"
+00025 #include "atomic.h"
+00026 #include "spin_mutex.h"
+00027 #include "null_mutex.h"
+00028 #include "spin_rw_mutex.h"
+00029 #include "null_rw_mutex.h"
+00030 #include "task.h"
+00031 #include "concurrent_vector.h"
+00032 #include "internal/_aggregator_impl.h"
+00033 
+00034 // use the VC10 or gcc version of tuple if it is available.
+00035 #if TBB_IMPLEMENT_CPP0X && (!defined(_MSC_VER) || _MSC_VER < 1600)
+00036 #define TBB_PREVIEW_TUPLE 1
+00037 #include "compat/tuple"
+00038 #else
+00039 #include <tuple>
+00040 #endif
+00041 
+00042 #include<list>
+00043 #include<queue>
+00044 
+00055 namespace tbb {
+00056 namespace flow {
+00057 
+00059 enum concurrency { unlimited = 0, serial = 1 };
+00060 
+00061 namespace interface6 {
+00062 
+00064 class continue_msg {};
+00065 
+00066 template< typename T > class sender;
+00067 template< typename T > class receiver;
+00068 class continue_receiver;
+00069 
+00071 template< typename T >
+00072 class sender {
+00073 public:
+00075     typedef T output_type;
+00076 
+00078     typedef receiver<T> successor_type;
+00079 
+00080     virtual ~sender() {}
+00081 
+00083     virtual bool register_successor( successor_type &r ) = 0;
+00084 
+00086     virtual bool remove_successor( successor_type &r ) = 0;
+00087 
+00089     virtual bool try_get( T & ) { return false; }
+00090 
+00092     virtual bool try_reserve( T & ) { return false; }
+00093 
+00095     virtual bool try_release( ) { return false; }
+00096 
+00098     virtual bool try_consume( ) { return false; }
+00099 };
+00100 
+00102 template< typename T >
+00103 class receiver {
+00104 public:
+00106     typedef T input_type;
+00107 
+00109     typedef sender<T> predecessor_type;
+00110 
+00112     virtual ~receiver() {}
+00113 
+00115     virtual bool try_put( const T& t ) = 0;
+00116 
+00118     virtual bool register_predecessor( predecessor_type & ) { return false; }
+00119 
+00121     virtual bool remove_predecessor( predecessor_type & ) { return false; }
+00122 };
+00123 
+00125 
+00126 class continue_receiver : public receiver< continue_msg > {
+00127 public:
+00128 
+00130     typedef continue_msg input_type;
+00131 
+00133     typedef sender< continue_msg > predecessor_type;
+00134 
+00136     continue_receiver( int number_of_predecessors = 0 ) {
+00137         my_predecessor_count = my_initial_predecessor_count = number_of_predecessors;
+00138         my_current_count = 0;
+00139     }
+00140 
+00142     continue_receiver( const continue_receiver& src ) : receiver<continue_msg>() {
+00143         my_predecessor_count = my_initial_predecessor_count = src.my_initial_predecessor_count;
+00144         my_current_count = 0;
+00145     }
+00146 
+00148     virtual ~continue_receiver() { }
+00149 
+00151     /* override */ bool register_predecessor( predecessor_type & ) {
+00152         spin_mutex::scoped_lock l(my_mutex);
+00153         ++my_predecessor_count;
+00154         return true;
+00155     }
+00156 
+00158 
+00161     /* override */ bool remove_predecessor( predecessor_type & ) {
+00162         spin_mutex::scoped_lock l(my_mutex);
+00163         --my_predecessor_count;
+00164         return true;
+00165     }
+00166 
+00168 
+00170     /* override */ bool try_put( const input_type & ) {
+00171         {
+00172             spin_mutex::scoped_lock l(my_mutex);
+00173             if ( ++my_current_count < my_predecessor_count )
+00174                 return true;
+00175             else
+00176                 my_current_count = 0;
+00177         }
+00178         execute();
+00179         return true;
+00180     }
+00181 
+00182 protected:
+00183     spin_mutex my_mutex;
+00184     int my_predecessor_count;
+00185     int my_current_count;
+00186     int my_initial_predecessor_count;
+00187 
+00189 
+00191     virtual void execute() = 0;
+00192 };
+00193 
+00194 #include "internal/_flow_graph_impl.h"
+00195 using namespace internal::graph_policy_namespace;
+00196 
+00197 class graph;
+00198 class graph_node;
+00199 
+00200 template <typename GraphContainerType, typename GraphNodeType>
+00201 class graph_iterator {
+00202     friend class graph;
+00203     friend class graph_node;
+00204 public:
+00205     typedef size_t size_type;
+00206     typedef GraphNodeType value_type;
+00207     typedef GraphNodeType* pointer;
+00208     typedef GraphNodeType& reference;
+00209     typedef const GraphNodeType& const_reference;
+00210     typedef std::forward_iterator_tag iterator_category;
+00211 
+00213     graph_iterator() : my_graph(NULL), current_node(NULL) {}
+00214 
+00216     graph_iterator(const graph_iterator& other) :
+00217         my_graph(other.my_graph), current_node(other.current_node)
+00218     {}
+00219 
+00221     graph_iterator& operator=(const graph_iterator& other) {
+00222         if (this != &other) {
+00223             my_graph = other.my_graph;
+00224             current_node = other.current_node;
+00225         }
+00226         return *this;
+00227     }
+00228 
+00230     reference operator*() const;
+00231 
+00233     pointer operator->() const;
+00234 
+00236     bool operator==(const graph_iterator& other) const {
+00237         return ((my_graph == other.my_graph) && (current_node == other.current_node));
+00238     }
+00239 
+00241     bool operator!=(const graph_iterator& other) const { return !(operator==(other)); }
+00242 
+00244     graph_iterator& operator++() {
+00245         internal_forward();
+00246         return *this;
+00247     }
+00248 
+00250     graph_iterator operator++(int) {
+00251         graph_iterator result = *this;
+00252         operator++();
+00253         return result;
+00254     }
+00255 
+00256 private:
+00257     // the graph over which we are iterating
+00258     GraphContainerType *my_graph;
+00259     // pointer into my_graph's my_nodes list
+00260     pointer current_node;
+00261 
+00263     graph_iterator(GraphContainerType *g, bool begin);
+00264     void internal_forward();
+00265 };
+00266 
+00268 
+00269 class graph : tbb::internal::no_copy {
+00270     friend class graph_node;
+00271 
+00272     template< typename Body >
+00273     class run_task : public task {
+00274     public:
+00275         run_task( Body& body ) : my_body(body) {}
+00276         task *execute() {
+00277             my_body();
+00278             return NULL;
+00279         }
+00280     private:
+00281         Body my_body;
+00282     };
+00283 
+00284     template< typename Receiver, typename Body >
+00285     class run_and_put_task : public task {
+00286     public:
+00287         run_and_put_task( Receiver &r, Body& body ) : my_receiver(r), my_body(body) {}
+00288         task *execute() {
+00289             my_receiver.try_put( my_body() );
+00290             return NULL;
+00291         }
+00292     private:
+00293         Receiver &my_receiver;
+00294         Body my_body;
+00295     };
+00296 
+00297 public:
+00299     explicit graph() : my_nodes(NULL), my_nodes_last(NULL)
+00300     {
+00301         own_context = true;
+00302         cancelled = false;
+00303         caught_exception = false;
+00304         my_context = new task_group_context();
+00305         my_root_task = ( new ( task::allocate_root(*my_context) ) empty_task );
+00306         my_root_task->set_ref_count(1);
+00307     }
+00308 
+00310     explicit graph(task_group_context& use_this_context) :
+00311     my_context(&use_this_context), my_nodes(NULL), my_nodes_last(NULL)
+00312     {
+00313         own_context = false;
+00314         my_root_task = ( new ( task::allocate_root(*my_context) ) empty_task );
+00315         my_root_task->set_ref_count(1);
+00316     }
+00317 
+00319 
+00320     ~graph() {
+00321         wait_for_all();
+00322         my_root_task->set_ref_count(0);
+00323         task::destroy( *my_root_task );
+00324         if (own_context) delete my_context;
+00325     }
+00326 
+00328 
+00330     void increment_wait_count() {
+00331         if (my_root_task)
+00332             my_root_task->increment_ref_count();
+00333     }
+00334 
+00336 
+00338     void decrement_wait_count() {
+00339         if (my_root_task)
+00340             my_root_task->decrement_ref_count();
+00341     }
+00342 
+00344 
+00346     template< typename Receiver, typename Body >
+00347         void run( Receiver &r, Body body ) {
+00348        task::enqueue( * new ( task::allocate_additional_child_of( *my_root_task ) )
+00349            run_and_put_task< Receiver, Body >( r, body ) );
+00350     }
+00351 
+00353 
+00355     template< typename Body >
+00356     void run( Body body ) {
+00357        task::enqueue( * new ( task::allocate_additional_child_of( *my_root_task ) )
+00358            run_task< Body >( body ) );
+00359     }
+00360 
+00362 
+00363     void wait_for_all() {
+00364         cancelled = false;
+00365         caught_exception = false;
+00366         if (my_root_task) {
+00367 #if TBB_USE_EXCEPTIONS
+00368             try {
+00369 #endif
+00370                 my_root_task->wait_for_all();
+00371                 cancelled = my_context->is_group_execution_cancelled();
+00372 #if TBB_USE_EXCEPTIONS
+00373             }
+00374             catch(...) {
+00375                 my_root_task->set_ref_count(1);
+00376                 my_context->reset();
+00377                 caught_exception = true;
+00378                 cancelled = true;
+00379                 throw;
+00380             }
+00381 #endif
+00382             my_root_task->set_ref_count(1);
+00383         }
+00384     }
+00385 
+00387     task * root_task() {
+00388         return my_root_task;
+00389     }
+00390 
+00391     // ITERATORS
+00392     template<typename C, typename N>
+00393     friend class graph_iterator;
+00394 
+00395     // Graph iterator typedefs
+00396     typedef graph_iterator<graph,graph_node> iterator;
+00397     typedef graph_iterator<const graph,const graph_node> const_iterator;
+00398 
+00399     // Graph iterator constructors
+00401     iterator begin() { return iterator(this, true); }
+00403     iterator end() { return iterator(this, false); }
+00405     const_iterator begin() const { return const_iterator(this, true); }
+00407     const_iterator end() const { return const_iterator(this, false); }
+00409     const_iterator cbegin() const { return const_iterator(this, true); }
+00411     const_iterator cend() const { return const_iterator(this, false); }
+00412 
+00414     bool is_cancelled() { return cancelled; }
+00415     bool exception_thrown() { return caught_exception; }
+00416 
+00417 private:
+00418     task *my_root_task;
+00419     task_group_context *my_context;
+00420     bool own_context;
+00421     bool cancelled;
+00422     bool caught_exception;
+00423 
+00424     graph_node *my_nodes, *my_nodes_last;
+00425 
+00426     spin_mutex nodelist_mutex;
+00427     void register_node(graph_node *n); 
+00428     void remove_node(graph_node *n);
+00429 
+00430 };
+00431 
+00432 template <typename C, typename N>
+00433 graph_iterator<C,N>::graph_iterator(C *g, bool begin) : my_graph(g), current_node(NULL)
+00434 {
+00435     if (begin) current_node = my_graph->my_nodes;
+00436     //else it is an end iterator by default
+00437 }
+00438 
+00439 template <typename C, typename N>
+00440 typename graph_iterator<C,N>::reference graph_iterator<C,N>::operator*() const {
+00441     __TBB_ASSERT(current_node, "graph_iterator at end");
+00442     return *operator->();
+00443 }
+00444 
+00445 template <typename C, typename N>
+00446 typename graph_iterator<C,N>::pointer graph_iterator<C,N>::operator->() const { 
+00447     return current_node;
+00448 }
+00449 
+00450 
+00451 template <typename C, typename N>
+00452 void graph_iterator<C,N>::internal_forward() {
+00453     if (current_node) current_node = current_node->next;
+00454 }
+00455 
+00457 class graph_node : tbb::internal::no_assign {
+00458     friend class graph;
+00459     template<typename C, typename N>
+00460     friend class graph_iterator;
+00461 protected:
+00462     graph& my_graph;
+00463     graph_node *next, *prev;
+00464 public:
+00465     graph_node(graph& g) : my_graph(g) {
+00466         my_graph.register_node(this);
+00467     }
+00468     virtual ~graph_node() {
+00469         my_graph.remove_node(this);
+00470     }
+00471 };
+00472 
+00473 inline void graph::register_node(graph_node *n) {
+00474     n->next = NULL;
+00475     {
+00476         spin_mutex::scoped_lock lock(nodelist_mutex);
+00477         n->prev = my_nodes_last;
+00478         if (my_nodes_last) my_nodes_last->next = n;
+00479         my_nodes_last = n;
+00480         if (!my_nodes) my_nodes = n;
+00481     }
+00482 }
+00483 
+00484 inline void graph::remove_node(graph_node *n) {
+00485     {
+00486         spin_mutex::scoped_lock lock(nodelist_mutex);
+00487         __TBB_ASSERT(my_nodes && my_nodes_last, "graph::remove_node: Error: no registered nodes");
+00488         if (n->prev) n->prev->next = n->next;
+00489         if (n->next) n->next->prev = n->prev;
+00490         if (my_nodes_last == n) my_nodes_last = n->prev;
+00491         if (my_nodes == n) my_nodes = n->next;
+00492     }
+00493     n->prev = n->next = NULL;
+00494 }
+00495 
+00496 #include "internal/_flow_graph_node_impl.h"
+00497 
+00499 template < typename Output >
+00500 class source_node : public graph_node, public sender< Output > {
+00501     using graph_node::my_graph;
+00502 public:
+00504     typedef Output output_type;
+00505 
+00507     typedef receiver< Output > successor_type;
+00508 
+00510     template< typename Body >
+00511     source_node( graph &g, Body body, bool is_active = true )
+00512         : graph_node(g), my_root_task(g.root_task()), my_active(is_active), init_my_active(is_active),
+00513         my_body( new internal::source_body_leaf< output_type, Body>(body) ),
+00514         my_reserved(false), my_has_cached_item(false)
+00515     {
+00516         my_successors.set_owner(this);
+00517     }
+00518 
+00520     source_node( const source_node& src ) :
+00521         graph_node(src.my_graph), sender<Output>(),
+00522         my_root_task( src.my_root_task), my_active(src.init_my_active),
+00523         init_my_active(src.init_my_active), my_body( src.my_body->clone() ),
+00524         my_reserved(false), my_has_cached_item(false)
+00525     {
+00526         my_successors.set_owner(this);
+00527     }
+00528 
+00530     ~source_node() { delete my_body; }
+00531 
+00533     /* override */ bool register_successor( receiver<output_type> &r ) {
+00534         spin_mutex::scoped_lock lock(my_mutex);
+00535         my_successors.register_successor(r);
+00536         if ( my_active )
+00537             spawn_put();
+00538         return true;
+00539     }
+00540 
+00542     /* override */ bool remove_successor( receiver<output_type> &r ) {
+00543         spin_mutex::scoped_lock lock(my_mutex);
+00544         my_successors.remove_successor(r);
+00545         return true;
+00546     }
+00547 
+00549     /*override */ bool try_get( output_type &v ) {
+00550         spin_mutex::scoped_lock lock(my_mutex);
+00551         if ( my_reserved )
+00552             return false;
+00553 
+00554         if ( my_has_cached_item ) {
+00555             v = my_cached_item;
+00556             my_has_cached_item = false;
+00557         } else if ( (*my_body)(v) == false ) {
+00558             return false;
+00559         }
+00560         return true;
+00561     }
+00562 
+00564     /* override */ bool try_reserve( output_type &v ) {
+00565         spin_mutex::scoped_lock lock(my_mutex);
+00566         if ( my_reserved ) {
+00567             return false;
+00568         }
+00569 
+00570         if ( !my_has_cached_item && (*my_body)(my_cached_item) )
+00571             my_has_cached_item = true;
+00572 
+00573         if ( my_has_cached_item ) {
+00574             v = my_cached_item;
+00575             my_reserved = true;
+00576             return true;
+00577         } else {
+00578             return false;
+00579         }
+00580     }
+00581 
+00583 
+00584     /* override */ bool try_release( ) {
+00585         spin_mutex::scoped_lock lock(my_mutex);
+00586         __TBB_ASSERT( my_reserved && my_has_cached_item, "releasing non-existent reservation" );
+00587         my_reserved = false;
+00588         if(!my_successors.empty())
+00589             spawn_put();
+00590         return true;
+00591     }
+00592 
+00594     /* override */ bool try_consume( ) {
+00595         spin_mutex::scoped_lock lock(my_mutex);
+00596         __TBB_ASSERT( my_reserved && my_has_cached_item, "consuming non-existent reservation" );
+00597         my_reserved = false;
+00598         my_has_cached_item = false;
+00599         if ( !my_successors.empty() ) {
+00600             spawn_put();
+00601         }
+00602         return true;
+00603     }
+00604 
+00606     void activate() {
+00607         spin_mutex::scoped_lock lock(my_mutex);
+00608         my_active = true;
+00609         if ( !my_successors.empty() )
+00610             spawn_put();
+00611     }
+00612 
+00613 private:
+00614     task *my_root_task;
+00615     spin_mutex my_mutex;
+00616     bool my_active;
+00617     bool init_my_active;
+00618     internal::source_body<output_type> *my_body;
+00619     internal::broadcast_cache< output_type > my_successors;
+00620     bool my_reserved;
+00621     bool my_has_cached_item;
+00622     output_type my_cached_item;
+00623 
+00624     friend class internal::source_task< source_node< output_type > >;
+00625 
+00627     /* override */ void apply_body( ) {
+00628         output_type v;
+00629         if ( try_reserve(v) == false )
+00630             return;
+00631 
+00632         if ( my_successors.try_put( v ) )
+00633             try_consume();
+00634         else
+00635             try_release();
+00636     }
+00637 
+00639     /* override */ void spawn_put( ) {
+00640         task::enqueue( * new ( task::allocate_additional_child_of( *my_root_task ) )
+00641            internal::source_task< source_node< output_type > >( *this ) );
+00642     }
+00643 };
+00644 
+00646 template < typename Input, typename Output = continue_msg, graph_buffer_policy = queueing, typename Allocator=cache_aligned_allocator<Input> >
+00647 class function_node : public graph_node, public internal::function_input<Input,Output,Allocator>, public internal::function_output<Output> {
+00648     using graph_node::my_graph;
+00649 public:
+00650     typedef Input input_type;
+00651     typedef Output output_type;
+00652     typedef sender< input_type > predecessor_type;
+00653     typedef receiver< output_type > successor_type;
+00654     typedef internal::function_input<input_type,output_type,Allocator> fInput_type;
+00655     typedef internal::function_output<output_type> fOutput_type;
+00656 
+00658     template< typename Body >
+00659     function_node( graph &g, size_t concurrency, Body body ) :
+00660         graph_node(g), internal::function_input<input_type,output_type,Allocator>(g, concurrency, body)
+00661     {}
+00662 
+00664     function_node( const function_node& src ) :
+00665         graph_node(src.my_graph), internal::function_input<input_type,output_type,Allocator>( src ),
+00666         fOutput_type()
+00667     {}
+00668 
+00669     bool try_put(const input_type &i) { return fInput_type::try_put(i); }
+00670 
+00671 protected:
+00672     /* override */ internal::broadcast_cache<output_type> &successors () { return fOutput_type::my_successors; }
+00673 };
+00674 
+00676 template < typename Input, typename Output, typename Allocator >
+00677 class function_node<Input,Output,queueing,Allocator> : public graph_node, public internal::function_input<Input,Output,Allocator>, public internal::function_output<Output> {
+00678     using graph_node::my_graph;
+00679 public:
+00680     typedef Input input_type;
+00681     typedef Output output_type;
+00682     typedef sender< input_type > predecessor_type;
+00683     typedef receiver< output_type > successor_type;
+00684     typedef internal::function_input<input_type,output_type,Allocator> fInput_type;
+00685     typedef internal::function_input_queue<input_type, Allocator> queue_type;
+00686     typedef internal::function_output<output_type> fOutput_type;
+00687 
+00689     template< typename Body >
+00690     function_node( graph &g, size_t concurrency, Body body ) :
+00691         graph_node(g), fInput_type( g, concurrency, body, new queue_type() )
+00692     {}
+00693 
+00695     function_node( const function_node& src ) :
+00696         graph_node(src.my_graph), fInput_type( src, new queue_type() ), fOutput_type()
+00697     {}
+00698 
+00699     bool try_put(const input_type &i) { return fInput_type::try_put(i); }
+00700 
+00701 protected:
+00702     /* override */ internal::broadcast_cache<output_type> &successors () { return fOutput_type::my_successors; }
+00703 };
+00704 
+00705 #include "tbb/internal/_flow_graph_types_impl.h"
+00706 
+00708 // Output is a tuple of output types.
+00709 template < typename Input, typename Output, graph_buffer_policy = queueing, typename Allocator=cache_aligned_allocator<Input> >
+00710 class multifunction_node :
+00711     public graph_node,
+00712     public internal::multifunction_input
+00713     <
+00714         Input,
+00715         typename internal::wrap_tuple_elements<
+00716             std::tuple_size<Output>::value,  // #elements in tuple
+00717             internal::function_output,  // wrap this around each element
+00718             Output // the tuple providing the types
+00719         >::type,
+00720         Allocator
+00721     > {
+00722     using graph_node::my_graph;
+00723 private:
+00724     static const int N = std::tuple_size<Output>::value;
+00725 public:
+00726     typedef Input input_type;
+00727     typedef typename internal::wrap_tuple_elements<N,internal::function_output, Output>::type output_ports_type;
+00728 private:
+00729     typedef typename internal::multifunction_input<input_type, output_ports_type, Allocator> base_type;
+00730     typedef typename internal::function_input_queue<input_type,Allocator> queue_type;
+00731 public:
+00732     template<typename Body>
+00733     multifunction_node( graph &g, size_t concurrency, Body body ) :
+00734         graph_node(g), base_type(g,concurrency, body)
+00735     {}
+00736     multifunction_node( const multifunction_node &other) :
+00737         graph_node(other.my_graph), base_type(other)
+00738     {}
+00739     // all the guts are in multifunction_input...
+00740 };  // multifunction_node
+00741 
+00742 template < typename Input, typename Output, typename Allocator >
+00743 class multifunction_node<Input,Output,queueing,Allocator> : public graph_node, public internal::multifunction_input<Input,
+00744     typename internal::wrap_tuple_elements<std::tuple_size<Output>::value, internal::function_output, Output>::type, Allocator> {
+00745     using graph_node::my_graph;
+00746     static const int N = std::tuple_size<Output>::value;
+00747 public:
+00748     typedef Input input_type;
+00749     typedef typename internal::wrap_tuple_elements<N, internal::function_output, Output>::type output_ports_type;
+00750 private:
+00751     typedef typename internal::multifunction_input<input_type, output_ports_type, Allocator> base_type;
+00752     typedef typename internal::function_input_queue<input_type,Allocator> queue_type;
+00753 public:
+00754     template<typename Body>
+00755     multifunction_node( graph &g, size_t concurrency, Body body) :
+00756         graph_node(g), base_type(g,concurrency, body, new queue_type())
+00757     {}
+00758     multifunction_node( const multifunction_node &other) :
+00759         graph_node(other.my_graph), base_type(other, new queue_type())
+00760     {}
+00761 };  // multifunction_node
+00762 
+00764 //  successors.  The node has unlimited concurrency, so though it is marked as
+00765 //  "rejecting" it does not reject inputs.
+00766 template<typename TupleType, typename Allocator=cache_aligned_allocator<TupleType> >
+00767 class split_node : public multifunction_node<TupleType, TupleType, rejecting, Allocator> {
+00768     static const int N = std::tuple_size<TupleType>::value;
+00769     typedef multifunction_node<TupleType,TupleType,rejecting,Allocator> base_type;
+00770 public:
+00771     typedef typename base_type::output_ports_type output_ports_type;
+00772 private:
+00773     struct splitting_body {
+00774         void operator()(const TupleType& t, output_ports_type &p) {
+00775             internal::emit_element<N>::emit_this(t, p);
+00776         }
+00777     };
+00778 public:
+00779     typedef TupleType input_type;
+00780     typedef Allocator allocator_type;
+00781     split_node(graph &g) : base_type(g, unlimited, splitting_body()) {}
+00782     split_node( const split_node & other) : base_type(other) {}
+00783 };
+00784 
+00786 template <typename Output>
+00787 class continue_node : public graph_node, public internal::continue_input<Output>, public internal::function_output<Output> {
+00788     using graph_node::my_graph;
+00789 public:
+00790     typedef continue_msg input_type;
+00791     typedef Output output_type;
+00792     typedef sender< input_type > predecessor_type;
+00793     typedef receiver< output_type > successor_type;
+00794     typedef internal::function_output<output_type> fOutput_type;
+00795 
+00797     template <typename Body >
+00798     continue_node( graph &g, Body body ) :
+00799         graph_node(g), internal::continue_input<output_type>( g, body )
+00800     {}
+00801 
+00803     template <typename Body >
+00804     continue_node( graph &g, int number_of_predecessors, Body body ) :
+00805         graph_node(g), internal::continue_input<output_type>( g, number_of_predecessors, body )
+00806     {}
+00807 
+00809     continue_node( const continue_node& src ) :
+00810         graph_node(src.my_graph), internal::continue_input<output_type>(src),
+00811         internal::function_output<Output>()
+00812     {}
+00813 
+00814     bool try_put(const input_type &i) { return internal::continue_input<Output>::try_put(i); }
+00815 
+00816 protected:
+00817     /* override */ internal::broadcast_cache<output_type> &successors () { return fOutput_type::my_successors; }
+00818 };
+00819 
+00820 template< typename T >
+00821 class overwrite_node : public graph_node, public receiver<T>, public sender<T> {
+00822     using graph_node::my_graph;
+00823 public:
+00824     typedef T input_type;
+00825     typedef T output_type;
+00826     typedef sender< input_type > predecessor_type;
+00827     typedef receiver< output_type > successor_type;
+00828 
+00829     overwrite_node(graph &g) : graph_node(g), my_buffer_is_valid(false) {
+00830         my_successors.set_owner( this );
+00831     }
+00832 
+00833     // Copy constructor; doesn't take anything from src; default won't work
+00834     overwrite_node( const overwrite_node& src ) :
+00835         graph_node(src.my_graph), receiver<T>(), sender<T>(), my_buffer_is_valid(false)
+00836     {
+00837         my_successors.set_owner( this );
+00838     }
+00839 
+00840     ~overwrite_node() {}
+00841 
+00842     /* override */ bool register_successor( successor_type &s ) {
+00843         spin_mutex::scoped_lock l( my_mutex );
+00844         if ( my_buffer_is_valid ) {
+00845             // We have a valid value that must be forwarded immediately.
+00846             if ( s.try_put( my_buffer ) || !s.register_predecessor( *this  ) ) {
+00847                 // We add the successor: it accepted our put or it rejected it but won't let use become a predecessor
+00848                 my_successors.register_successor( s );
+00849                 return true;
+00850             } else {
+00851                 // We don't add the successor: it rejected our put and we became its predecessor instead
+00852                 return false;
+00853             }
+00854         } else {
+00855             // No valid value yet, just add as successor
+00856             my_successors.register_successor( s );
+00857             return true;
+00858         }
+00859     }
+00860 
+00861     /* override */ bool remove_successor( successor_type &s ) {
+00862         spin_mutex::scoped_lock l( my_mutex );
+00863         my_successors.remove_successor(s);
+00864         return true;
+00865     }
+00866 
+00867     /* override */ bool try_put( const T &v ) {
+00868         spin_mutex::scoped_lock l( my_mutex );
+00869         my_buffer = v;
+00870         my_buffer_is_valid = true;
+00871         my_successors.try_put(v);
+00872         return true;
+00873     }
+00874 
+00875     /* override */ bool try_get( T &v ) {
+00876         spin_mutex::scoped_lock l( my_mutex );
+00877         if ( my_buffer_is_valid ) {
+00878             v = my_buffer;
+00879             return true;
+00880         } else {
+00881             return false;
+00882         }
+00883     }
+00884 
+00885     bool is_valid() {
+00886        spin_mutex::scoped_lock l( my_mutex );
+00887        return my_buffer_is_valid;
+00888     }
+00889 
+00890     void clear() {
+00891        spin_mutex::scoped_lock l( my_mutex );
+00892        my_buffer_is_valid = false;
+00893     }
+00894 
+00895 protected:
+00896     spin_mutex my_mutex;
+00897     internal::broadcast_cache< T, null_rw_mutex > my_successors;
+00898     T my_buffer;
+00899     bool my_buffer_is_valid;
+00900 };
+00901 
+00902 template< typename T >
+00903 class write_once_node : public overwrite_node<T> {
+00904 public:
+00905     typedef T input_type;
+00906     typedef T output_type;
+00907     typedef sender< input_type > predecessor_type;
+00908     typedef receiver< output_type > successor_type;
+00909 
+00911     write_once_node(graph& g) : overwrite_node<T>(g) {}
+00912 
+00914     write_once_node( const write_once_node& src ) : overwrite_node<T>(src) {}
+00915 
+00916     /* override */ bool try_put( const T &v ) {
+00917         spin_mutex::scoped_lock l( this->my_mutex );
+00918         if ( this->my_buffer_is_valid ) {
+00919             return false;
+00920         } else {
+00921             this->my_buffer = v;
+00922             this->my_buffer_is_valid = true;
+00923             this->my_successors.try_put(v);
+00924             return true;
+00925         }
+00926     }
+00927 };
+00928 
+00930 template <typename T>
+00931 class broadcast_node : public graph_node, public receiver<T>, public sender<T> {
+00932     using graph_node::my_graph;
+00933     internal::broadcast_cache<T> my_successors;
+00934 public:
+00935     typedef T input_type;
+00936     typedef T output_type;
+00937     typedef sender< input_type > predecessor_type;
+00938     typedef receiver< output_type > successor_type;
+00939 
+00940     broadcast_node(graph& g) : graph_node(g) {
+00941         my_successors.set_owner( this );
+00942     }
+00943 
+00944     // Copy constructor
+00945     broadcast_node( const broadcast_node& src ) :
+00946         graph_node(src.my_graph), receiver<T>(), sender<T>()
+00947     {
+00948         my_successors.set_owner( this );
+00949     }
+00950 
+00952     virtual bool register_successor( receiver<T> &r ) {
+00953         my_successors.register_successor( r );
+00954         return true;
+00955     }
+00956 
+00958     virtual bool remove_successor( receiver<T> &r ) {
+00959         my_successors.remove_successor( r );
+00960         return true;
+00961     }
+00962 
+00963     /* override */ bool try_put( const T &t ) {
+00964         my_successors.try_put(t);
+00965         return true;
+00966     }
+00967 };
+00968 
+00969 #include "internal/_flow_graph_item_buffer_impl.h"
+00970 
+00972 template <typename T, typename A=cache_aligned_allocator<T> >
+00973 class buffer_node : public graph_node, public reservable_item_buffer<T, A>, public receiver<T>, public sender<T> {
+00974     using graph_node::my_graph;
+00975 public:
+00976     typedef T input_type;
+00977     typedef T output_type;
+00978     typedef sender< input_type > predecessor_type;
+00979     typedef receiver< output_type > successor_type;
+00980     typedef buffer_node<T, A> my_class;
+00981 protected:
+00982     typedef size_t size_type;
+00983     internal::round_robin_cache< T, null_rw_mutex > my_successors;
+00984 
+00985     task *my_parent;
+00986 
+00987     friend class internal::forward_task< buffer_node< T, A > >;
+00988 
+00989     enum op_type {reg_succ, rem_succ, req_item, res_item, rel_res, con_res, put_item, try_fwd};
+00990     enum op_stat {WAIT=0, SUCCEEDED, FAILED};
+00991 
+00992     // implements the aggregator_operation concept
+00993     class buffer_operation : public internal::aggregated_operation< buffer_operation > {
+00994     public:
+00995         char type;
+00996         T *elem;
+00997         successor_type *r;
+00998         buffer_operation(const T& e, op_type t) :
+00999             type(char(t)), elem(const_cast<T*>(&e)), r(NULL) {}
+01000         buffer_operation(op_type t) : type(char(t)), r(NULL) {}
+01001     };
+01002 
+01003     bool forwarder_busy;
+01004     typedef internal::aggregating_functor<my_class, buffer_operation> my_handler;
+01005     friend class internal::aggregating_functor<my_class, buffer_operation>;
+01006     internal::aggregator< my_handler, buffer_operation> my_aggregator;
+01007 
+01008     virtual void handle_operations(buffer_operation *op_list) {
+01009         buffer_operation *tmp;
+01010         bool try_forwarding=false;
+01011         while (op_list) {
+01012             tmp = op_list;
+01013             op_list = op_list->next;
+01014             switch (tmp->type) {
+01015             case reg_succ: internal_reg_succ(tmp);  try_forwarding = true; break;
+01016             case rem_succ: internal_rem_succ(tmp); break;
+01017             case req_item: internal_pop(tmp); break;
+01018             case res_item: internal_reserve(tmp); break;
+01019             case rel_res:  internal_release(tmp);  try_forwarding = true; break;
+01020             case con_res:  internal_consume(tmp);  try_forwarding = true; break;
+01021             case put_item: internal_push(tmp);  try_forwarding = true; break;
+01022             case try_fwd:  internal_forward(tmp); break;
+01023             }
+01024         }
+01025         if (try_forwarding && !forwarder_busy) {
+01026             forwarder_busy = true;
+01027             task::enqueue(*new(task::allocate_additional_child_of(*my_parent)) internal::forward_task< buffer_node<input_type, A> >(*this));
+01028         }
+01029     }
+01030 
+01032     virtual void forward() {
+01033         buffer_operation op_data(try_fwd);
+01034         do {
+01035             op_data.status = WAIT;
+01036             my_aggregator.execute(&op_data);
+01037         } while (op_data.status == SUCCEEDED);
+01038     }
+01039 
+01041     virtual void internal_reg_succ(buffer_operation *op) {
+01042         my_successors.register_successor(*(op->r));
+01043         __TBB_store_with_release(op->status, SUCCEEDED);
+01044     }
+01045 
+01047     virtual void internal_rem_succ(buffer_operation *op) {
+01048         my_successors.remove_successor(*(op->r));
+01049         __TBB_store_with_release(op->status, SUCCEEDED);
+01050     }
+01051 
+01053     virtual void internal_forward(buffer_operation *op) {
+01054         T i_copy;
+01055         bool success = false; // flagged when a successor accepts
+01056         size_type counter = my_successors.size();
+01057         // Try forwarding, giving each successor a chance
+01058         while (counter>0 && !this->buffer_empty() && this->item_valid(this->my_tail-1)) {
+01059             this->fetch_back(i_copy);
+01060             if( my_successors.try_put(i_copy) ) {
+01061                 this->invalidate_back();
+01062                 --(this->my_tail);
+01063                 success = true; // found an accepting successor
+01064             }
+01065             --counter;
+01066         }
+01067         if (success && !counter)
+01068             __TBB_store_with_release(op->status, SUCCEEDED);
+01069         else {
+01070             __TBB_store_with_release(op->status, FAILED);
+01071             forwarder_busy = false;
+01072         }
+01073     }
+01074 
+01075     virtual void internal_push(buffer_operation *op) {
+01076         this->push_back(*(op->elem));
+01077         __TBB_store_with_release(op->status, SUCCEEDED);
+01078     }
+01079 
+01080     virtual void internal_pop(buffer_operation *op) {
+01081         if(this->pop_back(*(op->elem))) {
+01082             __TBB_store_with_release(op->status, SUCCEEDED);
+01083         }
+01084         else {
+01085             __TBB_store_with_release(op->status, FAILED);
+01086         }
+01087     }
+01088 
+01089     virtual void internal_reserve(buffer_operation *op) {
+01090         if(this->reserve_front(*(op->elem))) {
+01091             __TBB_store_with_release(op->status, SUCCEEDED);
+01092         }
+01093         else {
+01094             __TBB_store_with_release(op->status, FAILED);
+01095         }
+01096     }
+01097 
+01098     virtual void internal_consume(buffer_operation *op) {
+01099         this->consume_front();
+01100         __TBB_store_with_release(op->status, SUCCEEDED);
+01101     }
+01102 
+01103     virtual void internal_release(buffer_operation *op) {
+01104         this->release_front();
+01105         __TBB_store_with_release(op->status, SUCCEEDED);
+01106     }
+01107 
+01108 public:
+01110     buffer_node( graph &g ) : graph_node(g), reservable_item_buffer<T>(),
+01111         my_parent( g.root_task() ), forwarder_busy(false) {
+01112         my_successors.set_owner(this);
+01113         my_aggregator.initialize_handler(my_handler(this));
+01114     }
+01115 
+01117     buffer_node( const buffer_node& src ) : graph_node(src.my_graph),
+01118         reservable_item_buffer<T>(), receiver<T>(), sender<T>(),
+01119         my_parent( src.my_parent ) {
+01120         forwarder_busy = false;
+01121         my_successors.set_owner(this);
+01122         my_aggregator.initialize_handler(my_handler(this));
+01123     }
+01124 
+01125     virtual ~buffer_node() {}
+01126 
+01127     //
+01128     // message sender implementation
+01129     //
+01130 
+01132 
+01133     /* override */ bool register_successor( receiver<output_type> &r ) {
+01134         buffer_operation op_data(reg_succ);
+01135         op_data.r = &r;
+01136         my_aggregator.execute(&op_data);
+01137         return true;
+01138     }
+01139 
+01141 
+01143     /* override */ bool remove_successor( receiver<output_type> &r ) {
+01144         r.remove_predecessor(*this);
+01145         buffer_operation op_data(rem_succ);
+01146         op_data.r = &r;
+01147         my_aggregator.execute(&op_data);
+01148         return true;
+01149     }
+01150 
+01152 
+01154     /* override */ bool try_get( T &v ) {
+01155         buffer_operation op_data(req_item);
+01156         op_data.elem = &v;
+01157         my_aggregator.execute(&op_data);
+01158         return (op_data.status==SUCCEEDED);
+01159     }
+01160 
+01162 
+01164     /* override */ bool try_reserve( T &v ) {
+01165         buffer_operation op_data(res_item);
+01166         op_data.elem = &v;
+01167         my_aggregator.execute(&op_data);
+01168         return (op_data.status==SUCCEEDED);
+01169     }
+01170 
+01172 
+01173     /* override */ bool try_release() {
+01174         buffer_operation op_data(rel_res);
+01175         my_aggregator.execute(&op_data);
+01176         return true;
+01177     }
+01178 
+01180 
+01181     /* override */ bool try_consume() {
+01182         buffer_operation op_data(con_res);
+01183         my_aggregator.execute(&op_data);
+01184         return true;
+01185     }
+01186 
+01188 
+01189     /* override */ bool try_put(const T &t) {
+01190         buffer_operation op_data(t, put_item);
+01191         my_aggregator.execute(&op_data);
+01192         return true;
+01193     }
+01194 };
+01195 
+01197 template <typename T, typename A=cache_aligned_allocator<T> >
+01198 class queue_node : public buffer_node<T, A> {
+01199 protected:
+01200     typedef typename buffer_node<T, A>::size_type size_type;
+01201     typedef typename buffer_node<T, A>::buffer_operation queue_operation;
+01202 
+01203     enum op_stat {WAIT=0, SUCCEEDED, FAILED};
+01204 
+01206     /* override */ void internal_forward(queue_operation *op) {
+01207         T i_copy;
+01208         bool success = false; // flagged when a successor accepts
+01209         size_type counter = this->my_successors.size();
+01210         if (this->my_reserved || !this->item_valid(this->my_head)) {
+01211             __TBB_store_with_release(op->status, FAILED);
+01212             this->forwarder_busy = false;
+01213             return;
+01214         }
+01215         // Keep trying to send items while there is at least one accepting successor
+01216         while (counter>0 && this->item_valid(this->my_head)) {
+01217             this->fetch_front(i_copy);
+01218             if(this->my_successors.try_put(i_copy)) {
+01219                  this->invalidate_front();
+01220                  ++(this->my_head);
+01221                 success = true; // found an accepting successor
+01222             }
+01223             --counter;
+01224         }
+01225         if (success && !counter)
+01226             __TBB_store_with_release(op->status, SUCCEEDED);
+01227         else {
+01228             __TBB_store_with_release(op->status, FAILED);
+01229             this->forwarder_busy = false;
+01230         }
+01231     }
+01232 
+01233     /* override */ void internal_pop(queue_operation *op) {
+01234         if ( this->my_reserved || !this->item_valid(this->my_head)){
+01235             __TBB_store_with_release(op->status, FAILED);
+01236         }
+01237         else {
+01238             this->pop_front(*(op->elem));
+01239             __TBB_store_with_release(op->status, SUCCEEDED);
+01240         }
+01241     }
+01242     /* override */ void internal_reserve(queue_operation *op) {
+01243         if (this->my_reserved || !this->item_valid(this->my_head)) {
+01244             __TBB_store_with_release(op->status, FAILED);
+01245         }
+01246         else {
+01247             this->my_reserved = true;
+01248             this->fetch_front(*(op->elem));
+01249             this->invalidate_front();
+01250             __TBB_store_with_release(op->status, SUCCEEDED);
+01251         }
+01252     }
+01253     /* override */ void internal_consume(queue_operation *op) {
+01254         this->consume_front();
+01255         __TBB_store_with_release(op->status, SUCCEEDED);
+01256     }
+01257 
+01258 public:
+01259     typedef T input_type;
+01260     typedef T output_type;
+01261     typedef sender< input_type > predecessor_type;
+01262     typedef receiver< output_type > successor_type;
+01263 
+01265     queue_node( graph &g ) : buffer_node<T, A>(g) {}
+01266 
+01268     queue_node( const queue_node& src) : buffer_node<T, A>(src) {}
+01269 };
+01270 
+01272 template< typename T, typename A=cache_aligned_allocator<T> >
+01273 class sequencer_node : public queue_node<T, A> {
+01274     internal::function_body< T, size_t > *my_sequencer;
+01275 public:
+01276     typedef T input_type;
+01277     typedef T output_type;
+01278     typedef sender< input_type > predecessor_type;
+01279     typedef receiver< output_type > successor_type;
+01280 
+01282     template< typename Sequencer >
+01283     sequencer_node( graph &g, const Sequencer& s ) : queue_node<T, A>(g),
+01284         my_sequencer(new internal::function_body_leaf< T, size_t, Sequencer>(s) ) {}
+01285 
+01287     sequencer_node( const sequencer_node& src ) : queue_node<T, A>(src),
+01288         my_sequencer( src.my_sequencer->clone() ) {}
+01289 
+01291     ~sequencer_node() { delete my_sequencer; }
+01292 protected:
+01293     typedef typename buffer_node<T, A>::size_type size_type;
+01294     typedef typename buffer_node<T, A>::buffer_operation sequencer_operation;
+01295 
+01296     enum op_stat {WAIT=0, SUCCEEDED, FAILED};
+01297 
+01298 private:
+01299     /* override */ void internal_push(sequencer_operation *op) {
+01300         size_type tag = (*my_sequencer)(*(op->elem));
+01301 
+01302         this->my_tail = (tag+1 > this->my_tail) ? tag+1 : this->my_tail;
+01303 
+01304         if(this->size() > this->capacity())
+01305             this->grow_my_array(this->size());  // tail already has 1 added to it
+01306         this->item(tag) = std::make_pair( *(op->elem), true );
+01307         __TBB_store_with_release(op->status, SUCCEEDED);
+01308     }
+01309 };
+01310 
+01312 template< typename T, typename Compare = std::less<T>, typename A=cache_aligned_allocator<T> >
+01313 class priority_queue_node : public buffer_node<T, A> {
+01314 public:
+01315     typedef T input_type;
+01316     typedef T output_type;
+01317     typedef sender< input_type > predecessor_type;
+01318     typedef receiver< output_type > successor_type;
+01319 
+01321     priority_queue_node( graph &g ) : buffer_node<T, A>(g), mark(0) {}
+01322 
+01324     priority_queue_node( const priority_queue_node &src ) : buffer_node<T, A>(src), mark(0) {}
+01325 
+01326 protected:
+01327     typedef typename buffer_node<T, A>::size_type size_type;
+01328     typedef typename buffer_node<T, A>::item_type item_type;
+01329     typedef typename buffer_node<T, A>::buffer_operation prio_operation;
+01330 
+01331     enum op_stat {WAIT=0, SUCCEEDED, FAILED};
+01332 
+01333     /* override */ void handle_operations(prio_operation *op_list) {
+01334         prio_operation *tmp /*, *pop_list*/ ;
+01335         bool try_forwarding=false;
+01336         while (op_list) {
+01337             tmp = op_list;
+01338             op_list = op_list->next;
+01339             switch (tmp->type) {
+01340             case buffer_node<T, A>::reg_succ: this->internal_reg_succ(tmp); try_forwarding = true; break;
+01341             case buffer_node<T, A>::rem_succ: this->internal_rem_succ(tmp); break;
+01342             case buffer_node<T, A>::put_item: internal_push(tmp); try_forwarding = true; break;
+01343             case buffer_node<T, A>::try_fwd: internal_forward(tmp); break;
+01344             case buffer_node<T, A>::rel_res: internal_release(tmp); try_forwarding = true; break;
+01345             case buffer_node<T, A>::con_res: internal_consume(tmp); try_forwarding = true; break;
+01346             case buffer_node<T, A>::req_item: internal_pop(tmp); break;
+01347             case buffer_node<T, A>::res_item: internal_reserve(tmp); break;
+01348             }
+01349         }
+01350         // process pops!  for now, no special pop processing
+01351         if (mark<this->my_tail) heapify();
+01352         if (try_forwarding && !this->forwarder_busy) {
+01353             this->forwarder_busy = true;
+01354             task::enqueue(*new(task::allocate_additional_child_of(*(this->my_parent))) internal::forward_task< buffer_node<input_type, A> >(*this));
+01355         }
+01356     }
+01357 
+01359     /* override */ void internal_forward(prio_operation *op) {
+01360         T i_copy;
+01361         bool success = false; // flagged when a successor accepts
+01362         size_type counter = this->my_successors.size();
+01363 
+01364         if (this->my_reserved || this->my_tail == 0) {
+01365             __TBB_store_with_release(op->status, FAILED);
+01366             this->forwarder_busy = false;
+01367             return;
+01368         }
+01369         // Keep trying to send while there exists an accepting successor
+01370         while (counter>0 && this->my_tail > 0) {
+01371             i_copy = this->my_array[0].first;
+01372             bool msg = this->my_successors.try_put(i_copy);
+01373             if ( msg == true ) {
+01374                  if (mark == this->my_tail) --mark;
+01375                 --(this->my_tail);
+01376                 this->my_array[0].first=this->my_array[this->my_tail].first;
+01377                 if (this->my_tail > 1) // don't reheap for heap of size 1
+01378                     reheap();
+01379                 success = true; // found an accepting successor
+01380             }
+01381             --counter;
+01382         }
+01383         if (success && !counter)
+01384             __TBB_store_with_release(op->status, SUCCEEDED);
+01385         else {
+01386             __TBB_store_with_release(op->status, FAILED);
+01387             this->forwarder_busy = false;
+01388         }
+01389     }
+01390 
+01391     /* override */ void internal_push(prio_operation *op) {
+01392         if ( this->my_tail >= this->my_array_size )
+01393             this->grow_my_array( this->my_tail + 1 );
+01394         this->my_array[this->my_tail] = std::make_pair( *(op->elem), true );
+01395         ++(this->my_tail);
+01396         __TBB_store_with_release(op->status, SUCCEEDED);
+01397     }
+01398     /* override */ void internal_pop(prio_operation *op) {
+01399         if ( this->my_reserved == true || this->my_tail == 0 ) {
+01400             __TBB_store_with_release(op->status, FAILED);
+01401         }
+01402         else {
+01403             if (mark<this->my_tail &&
+01404                 compare(this->my_array[0].first,
+01405                         this->my_array[this->my_tail-1].first)) {
+01406                 // there are newly pushed elems; last one higher than top
+01407                 // copy the data
+01408                 *(op->elem) = this->my_array[this->my_tail-1].first;
+01409                 --(this->my_tail);
+01410                 __TBB_store_with_release(op->status, SUCCEEDED);
+01411             }
+01412             else { // extract and push the last element down heap
+01413                 *(op->elem) = this->my_array[0].first; // copy the data
+01414                 if (mark == this->my_tail) --mark;
+01415                 --(this->my_tail);
+01416                 __TBB_store_with_release(op->status, SUCCEEDED);
+01417                 this->my_array[0].first=this->my_array[this->my_tail].first;
+01418                 if (this->my_tail > 1) // don't reheap for heap of size 1
+01419                     reheap();
+01420             }
+01421         }
+01422     }
+01423     /* override */ void internal_reserve(prio_operation *op) {
+01424         if (this->my_reserved == true || this->my_tail == 0) {
+01425             __TBB_store_with_release(op->status, FAILED);
+01426         }
+01427         else {
+01428             this->my_reserved = true;
+01429             *(op->elem) = reserved_item = this->my_array[0].first;
+01430             if (mark == this->my_tail) --mark;
+01431             --(this->my_tail);
+01432             __TBB_store_with_release(op->status, SUCCEEDED);
+01433             this->my_array[0].first = this->my_array[this->my_tail].first;
+01434             if (this->my_tail > 1) // don't reheap for heap of size 1
+01435                 reheap();
+01436         }
+01437     }
+01438     /* override */ void internal_consume(prio_operation *op) {
+01439         this->my_reserved = false;
+01440         __TBB_store_with_release(op->status, SUCCEEDED);
+01441     }
+01442     /* override */ void internal_release(prio_operation *op) {
+01443         if (this->my_tail >= this->my_array_size)
+01444             this->grow_my_array( this->my_tail + 1 );
+01445         this->my_array[this->my_tail] = std::make_pair(reserved_item, true);
+01446         ++(this->my_tail);
+01447         this->my_reserved = false;
+01448         __TBB_store_with_release(op->status, SUCCEEDED);
+01449         heapify();
+01450     }
+01451 private:
+01452     Compare compare;
+01453     size_type mark;
+01454     input_type reserved_item;
+01455 
+01456     void heapify() {
+01457         if (!mark) mark = 1;
+01458         for (; mark<this->my_tail; ++mark) { // for each unheaped element
+01459             size_type cur_pos = mark;
+01460             input_type to_place = this->my_array[mark].first;
+01461             do { // push to_place up the heap
+01462                 size_type parent = (cur_pos-1)>>1;
+01463                 if (!compare(this->my_array[parent].first, to_place))
+01464                     break;
+01465                 this->my_array[cur_pos].first = this->my_array[parent].first;
+01466                 cur_pos = parent;
+01467             } while( cur_pos );
+01468             this->my_array[cur_pos].first = to_place;
+01469         }
+01470     }
+01471 
+01472     void reheap() {
+01473         size_type cur_pos=0, child=1;
+01474         while (child < mark) {
+01475             size_type target = child;
+01476             if (child+1<mark &&
+01477                 compare(this->my_array[child].first,
+01478                         this->my_array[child+1].first))
+01479                 ++target;
+01480             // target now has the higher priority child
+01481             if (compare(this->my_array[target].first,
+01482                         this->my_array[this->my_tail].first))
+01483                 break;
+01484             this->my_array[cur_pos].first = this->my_array[target].first;
+01485             cur_pos = target;
+01486             child = (cur_pos<<1)+1;
+01487         }
+01488         this->my_array[cur_pos].first = this->my_array[this->my_tail].first;
+01489     }
+01490 };
+01491 
+01493 
+01496 template< typename T >
+01497 class limiter_node : public graph_node, public receiver< T >, public sender< T > {
+01498     using graph_node::my_graph;
+01499 public:
+01500     typedef T input_type;
+01501     typedef T output_type;
+01502     typedef sender< input_type > predecessor_type;
+01503     typedef receiver< output_type > successor_type;
+01504 
+01505 private:
+01506     task *my_root_task;
+01507     size_t my_threshold;
+01508     size_t my_count;
+01509     internal::predecessor_cache< T > my_predecessors;
+01510     spin_mutex my_mutex;
+01511     internal::broadcast_cache< T > my_successors;
+01512     int init_decrement_predecessors;
+01513 
+01514     friend class internal::forward_task< limiter_node<T> >;
+01515 
+01516     // Let decrementer call decrement_counter()
+01517     friend class internal::decrementer< limiter_node<T> >;
+01518 
+01519     void decrement_counter() {
+01520         input_type v;
+01521 
+01522         // If we can't get / put an item immediately then drop the count
+01523         if ( my_predecessors.get_item( v ) == false
+01524              || my_successors.try_put(v) == false ) {
+01525             spin_mutex::scoped_lock lock(my_mutex);
+01526             --my_count;
+01527             if ( !my_predecessors.empty() )
+01528                 task::enqueue( * new ( task::allocate_additional_child_of( *my_root_task ) )
+01529                             internal::forward_task< limiter_node<T> >( *this ) );
+01530         }
+01531     }
+01532 
+01533     void forward() {
+01534         {
+01535             spin_mutex::scoped_lock lock(my_mutex);
+01536             if ( my_count < my_threshold )
+01537                 ++my_count;
+01538             else
+01539                 return;
+01540         }
+01541         decrement_counter();
+01542     }
+01543 
+01544 public:
+01546     internal::decrementer< limiter_node<T> > decrement;
+01547 
+01549     limiter_node(graph &g, size_t threshold, int num_decrement_predecessors=0) :
+01550         graph_node(g), my_root_task(g.root_task()), my_threshold(threshold), my_count(0),
+01551         init_decrement_predecessors(num_decrement_predecessors),
+01552         decrement(num_decrement_predecessors)
+01553     {
+01554         my_predecessors.set_owner(this);
+01555         my_successors.set_owner(this);
+01556         decrement.set_owner(this);
+01557     }
+01558 
+01560     limiter_node( const limiter_node& src ) :
+01561         graph_node(src.my_graph), receiver<T>(), sender<T>(),
+01562         my_root_task(src.my_root_task), my_threshold(src.my_threshold), my_count(0),
+01563         init_decrement_predecessors(src.init_decrement_predecessors),
+01564         decrement(src.init_decrement_predecessors)
+01565     {
+01566         my_predecessors.set_owner(this);
+01567         my_successors.set_owner(this);
+01568         decrement.set_owner(this);
+01569     }
+01570 
+01572     /* override */ bool register_successor( receiver<output_type> &r ) {
+01573         my_successors.register_successor(r);
+01574         return true;
+01575     }
+01576 
+01578 
+01579     /* override */ bool remove_successor( receiver<output_type> &r ) {
+01580         r.remove_predecessor(*this);
+01581         my_successors.remove_successor(r);
+01582         return true;
+01583     }
+01584 
+01586     /* override */ bool try_put( const T &t ) {
+01587         {
+01588             spin_mutex::scoped_lock lock(my_mutex);
+01589             if ( my_count >= my_threshold )
+01590                 return false;
+01591             else
+01592                 ++my_count;
+01593         }
+01594 
+01595         bool msg = my_successors.try_put(t);
+01596 
+01597         if ( msg != true ) {
+01598             spin_mutex::scoped_lock lock(my_mutex);
+01599             --my_count;
+01600             if ( !my_predecessors.empty() )
+01601                 task::enqueue( * new ( task::allocate_additional_child_of( *my_root_task ) )
+01602                             internal::forward_task< limiter_node<T> >( *this ) );
+01603         }
+01604 
+01605         return msg;
+01606     }
+01607 
+01609     /* override */ bool register_predecessor( predecessor_type &src ) {
+01610         spin_mutex::scoped_lock lock(my_mutex);
+01611         my_predecessors.add( src );
+01612         if ( my_count < my_threshold && !my_successors.empty() )
+01613             task::enqueue( * new ( task::allocate_additional_child_of( *my_root_task ) )
+01614                            internal::forward_task< limiter_node<T> >( *this ) );
+01615         return true;
+01616     }
+01617 
+01619     /* override */ bool remove_predecessor( predecessor_type &src ) {
+01620         my_predecessors.remove( src );
+01621         return true;
+01622     }
+01623 };
+01624 
+01625 #include "internal/_flow_graph_join_impl.h"
+01626 
+01627 using internal::reserving_port;
+01628 using internal::queueing_port;
+01629 using internal::tag_matching_port;
+01630 using internal::input_port;
+01631 using internal::tag_value;
+01632 using internal::NO_TAG;
+01633 
+01634 template<typename OutputTuple, graph_buffer_policy JP=queueing> class join_node;
+01635 
+01636 template<typename OutputTuple>
+01637 class join_node<OutputTuple,reserving>: public internal::unfolded_join_node<std::tuple_size<OutputTuple>::value, reserving_port, OutputTuple, reserving> {
+01638 private:
+01639     static const int N = std::tuple_size<OutputTuple>::value;
+01640     typedef typename internal::unfolded_join_node<N, reserving_port, OutputTuple, reserving> unfolded_type;
+01641 public:
+01642     typedef OutputTuple output_type;
+01643     typedef typename unfolded_type::input_ports_type input_ports_type;
+01644     join_node(graph &g) : unfolded_type(g) { }
+01645     join_node(const join_node &other) : unfolded_type(other) {}
+01646 };
+01647 
+01648 template<typename OutputTuple>
+01649 class join_node<OutputTuple,queueing>: public internal::unfolded_join_node<std::tuple_size<OutputTuple>::value, queueing_port, OutputTuple, queueing> {
+01650 private:
+01651     static const int N = std::tuple_size<OutputTuple>::value;
+01652     typedef typename internal::unfolded_join_node<N, queueing_port, OutputTuple, queueing> unfolded_type;
+01653 public:
+01654     typedef OutputTuple output_type;
+01655     typedef typename unfolded_type::input_ports_type input_ports_type;
+01656     join_node(graph &g) : unfolded_type(g) { }
+01657     join_node(const join_node &other) : unfolded_type(other) {}
+01658 };
+01659 
+01660 // template for tag_matching join_node
+01661 template<typename OutputTuple>
+01662 class join_node<OutputTuple, tag_matching> : public internal::unfolded_join_node<std::tuple_size<OutputTuple>::value,
+01663       tag_matching_port, OutputTuple, tag_matching> {
+01664 private:
+01665     static const int N = std::tuple_size<OutputTuple>::value;
+01666     typedef typename internal::unfolded_join_node<N, tag_matching_port, OutputTuple, tag_matching> unfolded_type;
+01667 public:
+01668     typedef OutputTuple output_type;
+01669     typedef typename unfolded_type::input_ports_type input_ports_type;
+01670     template<typename B0, typename B1>
+01671     join_node(graph &g, B0 b0, B1 b1) : unfolded_type(g, b0, b1) { }
+01672     template<typename B0, typename B1, typename B2>
+01673     join_node(graph &g, B0 b0, B1 b1, B2 b2) : unfolded_type(g, b0, b1, b2) { }
+01674     template<typename B0, typename B1, typename B2, typename B3>
+01675     join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3) : unfolded_type(g, b0, b1, b2, b3) { }
+01676     template<typename B0, typename B1, typename B2, typename B3, typename B4>
+01677     join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4) : unfolded_type(g, b0, b1, b2, b3, b4) { }
+01678 #if __TBB_VARIADIC_MAX >= 6
+01679     template<typename B0, typename B1, typename B2, typename B3, typename B4, typename B5>
+01680     join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5) : unfolded_type(g, b0, b1, b2, b3, b4, b5) { }
+01681 #endif
+01682 #if __TBB_VARIADIC_MAX >= 7
+01683     template<typename B0, typename B1, typename B2, typename B3, typename B4, typename B5, typename B6>
+01684     join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5, B6 b6) : unfolded_type(g, b0, b1, b2, b3, b4, b5, b6) { }
+01685 #endif
+01686 #if __TBB_VARIADIC_MAX >= 8
+01687     template<typename B0, typename B1, typename B2, typename B3, typename B4, typename B5, typename B6, typename B7>
+01688     join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5, B6 b6, B7 b7) : unfolded_type(g, b0, b1, b2, b3, b4, b5, b6, b7) { }
+01689 #endif
+01690 #if __TBB_VARIADIC_MAX >= 9
+01691     template<typename B0, typename B1, typename B2, typename B3, typename B4, typename B5, typename B6, typename B7, typename B8>
+01692     join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5, B6 b6, B7 b7, B8 b8) : unfolded_type(g, b0, b1, b2, b3, b4, b5, b6, b7, b8) { }
+01693 #endif
+01694 #if __TBB_VARIADIC_MAX >= 10
+01695     template<typename B0, typename B1, typename B2, typename B3, typename B4, typename B5, typename B6, typename B7, typename B8, typename B9>
+01696     join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5, B6 b6, B7 b7, B8 b8, B9 b9) : unfolded_type(g, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9) { }
+01697 #endif
+01698     join_node(const join_node &other) : unfolded_type(other) {}
+01699 };
+01700 
+01701 #if TBB_PREVIEW_GRAPH_NODES
+01702 // or node
+01703 #include "internal/_flow_graph_or_impl.h"
+01704 
+01705 template<typename InputTuple>
+01706 class or_node : public internal::unfolded_or_node<InputTuple> {
+01707 private:
+01708     static const int N = std::tuple_size<InputTuple>::value;
+01709 public:
+01710     typedef typename internal::or_output_type<InputTuple>::type output_type;
+01711     typedef typename internal::unfolded_or_node<InputTuple> unfolded_type;
+01712     or_node(graph& g) : unfolded_type(g) { }
+01713     // Copy constructor
+01714     or_node( const or_node& other ) : unfolded_type(other) { }
+01715 };
+01716 #endif  // TBB_PREVIEW_GRAPH_NODES
+01717 
+01719 template< typename T >
+01720 inline void make_edge( sender<T> &p, receiver<T> &s ) {
+01721     p.register_successor( s );
+01722 }
+01723 
+01725 template< typename T >
+01726 inline void remove_edge( sender<T> &p, receiver<T> &s ) {
+01727     p.remove_successor( s );
+01728 }
+01729 
+01731 template< typename Body, typename Node >
+01732 Body copy_body( Node &n ) {
+01733     return n.template copy_function_object<Body>();
+01734 }
+01735 
+01736 } // interface6
+01737 
+01738     using interface6::graph;
+01739     using interface6::graph_node;
+01740     using interface6::continue_msg;
+01741     using interface6::sender;
+01742     using interface6::receiver;
+01743     using interface6::continue_receiver;
+01744 
+01745     using interface6::source_node;
+01746     using interface6::function_node;
+01747     using interface6::multifunction_node;
+01748     using interface6::split_node;
+01749     using interface6::internal::output_port;
+01750 #if TBB_PREVIEW_GRAPH_NODES
+01751     using interface6::or_node;
+01752 #endif
+01753     using interface6::continue_node;
+01754     using interface6::overwrite_node;
+01755     using interface6::write_once_node;
+01756     using interface6::broadcast_node;
+01757     using interface6::buffer_node;
+01758     using interface6::queue_node;
+01759     using interface6::sequencer_node;
+01760     using interface6::priority_queue_node;
+01761     using interface6::limiter_node;
+01762     using namespace interface6::internal::graph_policy_namespace;
+01763     using interface6::join_node;
+01764     using interface6::input_port;
+01765     using interface6::copy_body; 
+01766     using interface6::make_edge; 
+01767     using interface6::remove_edge; 
+01768     using interface6::internal::NO_TAG;
+01769     using interface6::internal::tag_value;
+01770 
+01771 } // flow
+01772 } // tbb
+01773 
+01774 #endif // __TBB_flow_graph_H
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00524.html b/src/tbb/doc/html/a00524.html new file mode 100644 index 0000000..f47438a --- /dev/null +++ b/src/tbb/doc/html/a00524.html @@ -0,0 +1,269 @@ + + +memory_pool.h Source File + + + + + + +

memory_pool.h

Go to the documentation of this file.
00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_memory_pool_H
+00022 #define __TBB_memory_pool_H
+00023 
+00024 #if !TBB_PREVIEW_MEMORY_POOL
+00025 #error Set TBB_PREVIEW_MEMORY_POOL to include memory_pool.h
+00026 #endif
+00027 
+00029 #include "scalable_allocator.h"
+00030 #include "tbb_stddef.h"
+00031 #include "tbb_machine.h" // TODO: avoid linkage with libtbb on IA-64
+00032 #include <new> // std::bad_alloc
+00033 #if __TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_CPP11_STD_FORWARD_BROKEN
+00034 #include <utility> // std::forward
+00035 #endif
+00036 
+00037 #if __TBB_EXTRA_DEBUG
+00038 #define __TBBMALLOC_ASSERT ASSERT
+00039 #else
+00040 #define __TBBMALLOC_ASSERT(a,b) ((void)0)
+00041 #endif
+00042 
+00043 namespace tbb {
+00044 namespace interface6 {
+00046 namespace internal {
+00047 
+00049 class pool_base : tbb::internal::no_copy {
+00050     // Pool interface is separate from standard allocator classes because it has
+00051     // to maintain internal state, no copy or assignment. Move and swap are possible.
+00052 public:
+00054     void recycle() { rml::pool_reset(my_pool); }
+00055 
+00057     void *malloc(size_t size) { return rml::pool_malloc(my_pool, size); }
+00058 
+00060     void free(void* ptr) { rml::pool_free(my_pool, ptr); }
+00061 
+00063     // Enables some low-level optimization possibilities
+00064     void *realloc(void* ptr, size_t size) {
+00065         return rml::pool_realloc(my_pool, ptr, size);
+00066     }
+00067 
+00068 protected:
+00070     void destroy() { rml::pool_destroy(my_pool); }
+00071 
+00072     rml::MemoryPool *my_pool;
+00073 };
+00074 
+00075 } // namespace internal
+00077 
+00078 #if _MSC_VER && !defined(__INTEL_COMPILER)
+00079     // Workaround for erroneous "unreferenced parameter" warning in method destroy.
+00080     #pragma warning (push)
+00081     #pragma warning (disable: 4100)
+00082 #endif
+00083 
+00085 
+00086 template<typename T, typename P = internal::pool_base>
+00087 class memory_pool_allocator {
+00088 protected:
+00089     typedef P pool_type;
+00090     pool_type *my_pool;
+00091     template<typename U, typename R>
+00092     friend class memory_pool_allocator;
+00093     template<typename V, typename U, typename R>
+00094     friend bool operator==( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
+00095     template<typename V, typename U, typename R>
+00096     friend bool operator!=( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
+00097 public:
+00098     typedef typename tbb::internal::allocator_type<T>::value_type value_type;
+00099     typedef value_type* pointer;
+00100     typedef const value_type* const_pointer;
+00101     typedef value_type& reference;
+00102     typedef const value_type& const_reference;
+00103     typedef size_t size_type;
+00104     typedef ptrdiff_t difference_type;
+00105     template<typename U> struct rebind {
+00106         typedef memory_pool_allocator<U, P> other;
+00107     };
+00108 
+00109     memory_pool_allocator(pool_type &pool) throw() : my_pool(&pool) {}
+00110     memory_pool_allocator(const memory_pool_allocator& src) throw() : my_pool(src.my_pool) {}
+00111     template<typename U>
+00112     memory_pool_allocator(const memory_pool_allocator<U,P>& src) throw() : my_pool(src.my_pool) {}
+00113 
+00114     pointer address(reference x) const { return &x; }
+00115     const_pointer address(const_reference x) const { return &x; }
+00116     
+00118     pointer allocate( size_type n, const void* /*hint*/ = 0) {
+00119         return static_cast<pointer>( my_pool->malloc( n*sizeof(value_type) ) );
+00120     }
+00122     void deallocate( pointer p, size_type ) {
+00123         my_pool->free(p);
+00124     }
+00126     size_type max_size() const throw() {
+00127         size_type max = static_cast<size_type>(-1) / sizeof (value_type);
+00128         return (max > 0 ? max : 1);
+00129     }
+00131 #if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT
+00132     template<typename... Args>
+00133     void construct(pointer p, Args&&... args)
+00134  #if __TBB_CPP11_STD_FORWARD_BROKEN
+00135         { ::new((void *)p) T((args)...); }
+00136  #else
+00137         { ::new((void *)p) T(std::forward<Args>(args)...); }
+00138  #endif
+00139 #else // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT
+00140     void construct( pointer p, const value_type& value ) { ::new((void*)(p)) value_type(value); }
+00141 #endif // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT
+00142 
+00144     void destroy( pointer p ) { p->~value_type(); }
+00145 
+00146 };
+00147 
+00148 #if _MSC_VER && !defined(__INTEL_COMPILER)
+00149     #pragma warning (pop)
+00150 #endif // warning 4100 is back
+00151 
+00153 
+00154 template<typename P> 
+00155 class memory_pool_allocator<void, P> {
+00156 public:
+00157     typedef P pool_type;
+00158     typedef void* pointer;
+00159     typedef const void* const_pointer;
+00160     typedef void value_type;
+00161     template<typename U> struct rebind {
+00162         typedef memory_pool_allocator<U, P> other;
+00163     };
+00164 
+00165     memory_pool_allocator( pool_type &pool) throw() : my_pool(&pool) {}
+00166     memory_pool_allocator( const memory_pool_allocator& src) throw() : my_pool(src.my_pool) {}
+00167     template<typename U>
+00168     memory_pool_allocator(const memory_pool_allocator<U,P>& src) throw() : my_pool(src.my_pool) {}
+00169 
+00170 protected:
+00171     pool_type *my_pool;
+00172     template<typename U, typename R>
+00173     friend class memory_pool_allocator;
+00174     template<typename V, typename U, typename R>
+00175     friend bool operator==( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
+00176     template<typename V, typename U, typename R>
+00177     friend bool operator!=( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
+00178 };
+00179 
+00180 template<typename T, typename U, typename P>
+00181 inline bool operator==( const memory_pool_allocator<T,P>& a, const memory_pool_allocator<U,P>& b) {return a.my_pool==b.my_pool;}
+00182 
+00183 template<typename T, typename U, typename P>
+00184 inline bool operator!=( const memory_pool_allocator<T,P>& a, const memory_pool_allocator<U,P>& b) {return a.my_pool!=b.my_pool;}
+00185 
+00186 
+00188 template <typename Alloc>
+00189 class memory_pool : public internal::pool_base {
+00190     Alloc my_alloc; // TODO: base-class optimization
+00191     static void *allocate_request(intptr_t pool_id, size_t & bytes);
+00192     static int deallocate_request(intptr_t pool_id, void*, size_t raw_bytes);
+00193 
+00194 public:
+00196     memory_pool(const Alloc &src = Alloc());
+00197 
+00199     ~memory_pool() { destroy(); } // call the callbacks first and destroy my_alloc latter
+00200 
+00201 };
+00202 
+00203 class fixed_pool : public internal::pool_base {
+00204     void *my_buffer;
+00205     size_t my_size;
+00206     inline static void *allocate_request(intptr_t pool_id, size_t & bytes);
+00207 
+00208 public:
+00210     inline fixed_pool(void *buf, size_t size);
+00212     ~fixed_pool() { destroy(); }
+00213 };
+00214 
+00216 
+00217 template <typename Alloc>
+00218 memory_pool<Alloc>::memory_pool(const Alloc &src) : my_alloc(src) {
+00219     rml::MemPoolPolicy args(allocate_request, deallocate_request,
+00220                             sizeof(typename Alloc::value_type));
+00221     rml::MemPoolError res = rml::pool_create_v1(intptr_t(this), &args, &my_pool);
+00222     if( res!=rml::POOL_OK ) __TBB_THROW(std::bad_alloc());
+00223 }
+00224 template <typename Alloc>
+00225 void *memory_pool<Alloc>::allocate_request(intptr_t pool_id, size_t & bytes) {
+00226     memory_pool<Alloc> &self = *reinterpret_cast<memory_pool<Alloc>*>(pool_id);
+00227     const size_t unit_size = sizeof(typename Alloc::value_type);
+00228     __TBBMALLOC_ASSERT( 0 == bytes%unit_size, NULL);
+00229     void *ptr;
+00230     __TBB_TRY { ptr = self.my_alloc.allocate( bytes/unit_size ); }
+00231     __TBB_CATCH(...) { return 0; }
+00232     return ptr;
+00233 }
+00234 template <typename Alloc>
+00235 int memory_pool<Alloc>::deallocate_request(intptr_t pool_id, void* raw_ptr, size_t raw_bytes) {
+00236     memory_pool<Alloc> &self = *reinterpret_cast<memory_pool<Alloc>*>(pool_id);
+00237     const size_t unit_size = sizeof(typename Alloc::value_type);
+00238     __TBBMALLOC_ASSERT( 0 == raw_bytes%unit_size, NULL);
+00239     self.my_alloc.deallocate( static_cast<typename Alloc::value_type*>(raw_ptr), raw_bytes/unit_size );
+00240     return 0;
+00241 }
+00242 inline fixed_pool::fixed_pool(void *buf, size_t size) : my_buffer(buf), my_size(size) {
+00243     rml::MemPoolPolicy args(allocate_request, 0, size, /*fixedPool=*/true);
+00244     rml::MemPoolError res = rml::pool_create_v1(intptr_t(this), &args, &my_pool);
+00245     if( res!=rml::POOL_OK ) __TBB_THROW(std::bad_alloc());
+00246 }
+00247 inline void *fixed_pool::allocate_request(intptr_t pool_id, size_t & bytes) {
+00248     fixed_pool &self = *reinterpret_cast<fixed_pool*>(pool_id);
+00249     if( !__TBB_CompareAndSwapW(&self.my_size, 0, (bytes=self.my_size)) )
+00250         return 0; // all the memory was given already
+00251     return self.my_buffer;
+00252 }
+00253 
+00254 } //namespace interface6
+00255 using interface6::memory_pool_allocator;
+00256 using interface6::memory_pool;
+00257 using interface6::fixed_pool;
+00258 } //namespace tbb
+00259 
+00260 #undef __TBBMALLOC_ASSERT
+00261 #endif// __TBB_memory_pool_H
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00531.html b/src/tbb/doc/html/a00531.html new file mode 100644 index 0000000..b2f9e79 --- /dev/null +++ b/src/tbb/doc/html/a00531.html @@ -0,0 +1,240 @@ + + +mutex.h Source File + + + + + + +

mutex.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_mutex_H
+00022 #define __TBB_mutex_H
+00023 
+00024 #if _WIN32||_WIN64
+00025 #include "machine/windows_api.h"
+00026 #else
+00027 #include <pthread.h>
+00028 #endif /* _WIN32||_WIN64 */
+00029 
+00030 #include <new>
+00031 #include "aligned_space.h"
+00032 #include "tbb_stddef.h"
+00033 #include "tbb_profiling.h"
+00034 
+00035 namespace tbb {
+00036 
+00038 
+00040 class mutex {
+00041 public:
+00043     mutex() {
+00044 #if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS
+00045     internal_construct();
+00046 #else
+00047   #if _WIN32||_WIN64
+00048         InitializeCriticalSection(&impl);
+00049   #else
+00050         int error_code = pthread_mutex_init(&impl,NULL);
+00051         if( error_code )
+00052             tbb::internal::handle_perror(error_code,"mutex: pthread_mutex_init failed");
+00053   #endif /* _WIN32||_WIN64*/
+00054 #endif /* TBB_USE_ASSERT */
+00055     };
+00056 
+00057     ~mutex() {
+00058 #if TBB_USE_ASSERT
+00059         internal_destroy();
+00060 #else
+00061   #if _WIN32||_WIN64
+00062         DeleteCriticalSection(&impl);
+00063   #else
+00064         pthread_mutex_destroy(&impl); 
+00065 
+00066   #endif /* _WIN32||_WIN64 */
+00067 #endif /* TBB_USE_ASSERT */
+00068     };
+00069 
+00070     class scoped_lock;
+00071     friend class scoped_lock;
+00072 
+00074 
+00076     class scoped_lock : internal::no_copy {
+00077     public:
+00079         scoped_lock() : my_mutex(NULL) {};
+00080 
+00082         scoped_lock( mutex& mutex ) {
+00083             acquire( mutex );
+00084         }
+00085 
+00087         ~scoped_lock() {
+00088             if( my_mutex ) 
+00089                 release();
+00090         }
+00091 
+00093         void acquire( mutex& mutex ) {
+00094 #if TBB_USE_ASSERT
+00095             internal_acquire(mutex);
+00096 #else
+00097             mutex.lock();
+00098             my_mutex = &mutex;
+00099 #endif /* TBB_USE_ASSERT */
+00100         }
+00101 
+00103         bool try_acquire( mutex& mutex ) {
+00104 #if TBB_USE_ASSERT
+00105             return internal_try_acquire (mutex);
+00106 #else
+00107             bool result = mutex.try_lock();
+00108             if( result )
+00109                 my_mutex = &mutex;
+00110             return result;
+00111 #endif /* TBB_USE_ASSERT */
+00112         }
+00113 
+00115         void release() {
+00116 #if TBB_USE_ASSERT
+00117             internal_release ();
+00118 #else
+00119             my_mutex->unlock();
+00120             my_mutex = NULL;
+00121 #endif /* TBB_USE_ASSERT */
+00122         }
+00123 
+00124     private:
+00126         mutex* my_mutex;
+00127 
+00129         void __TBB_EXPORTED_METHOD internal_acquire( mutex& m );
+00130 
+00132         bool __TBB_EXPORTED_METHOD internal_try_acquire( mutex& m );
+00133 
+00135         void __TBB_EXPORTED_METHOD internal_release();
+00136 
+00137         friend class mutex;
+00138     };
+00139 
+00140     // Mutex traits
+00141     static const bool is_rw_mutex = false;
+00142     static const bool is_recursive_mutex = false;
+00143     static const bool is_fair_mutex = false;
+00144 
+00145     // ISO C++0x compatibility methods
+00146 
+00148     void lock() {
+00149 #if TBB_USE_ASSERT
+00150         aligned_space<scoped_lock,1> tmp;
+00151         new(tmp.begin()) scoped_lock(*this);
+00152 #else
+00153   #if _WIN32||_WIN64
+00154         EnterCriticalSection(&impl);
+00155   #else
+00156         pthread_mutex_lock(&impl);
+00157   #endif /* _WIN32||_WIN64 */
+00158 #endif /* TBB_USE_ASSERT */
+00159     }
+00160 
+00162 
+00163     bool try_lock() {
+00164 #if TBB_USE_ASSERT
+00165         aligned_space<scoped_lock,1> tmp;
+00166         scoped_lock& s = *tmp.begin();
+00167         s.my_mutex = NULL;
+00168         return s.internal_try_acquire(*this);
+00169 #else
+00170   #if _WIN32||_WIN64
+00171         return TryEnterCriticalSection(&impl)!=0;
+00172   #else
+00173         return pthread_mutex_trylock(&impl)==0;
+00174   #endif /* _WIN32||_WIN64 */
+00175 #endif /* TBB_USE_ASSERT */
+00176     }
+00177 
+00179     void unlock() {
+00180 #if TBB_USE_ASSERT
+00181         aligned_space<scoped_lock,1> tmp;
+00182         scoped_lock& s = *tmp.begin();
+00183         s.my_mutex = this;
+00184         s.internal_release();
+00185 #else
+00186   #if _WIN32||_WIN64
+00187         LeaveCriticalSection(&impl);
+00188   #else
+00189         pthread_mutex_unlock(&impl);
+00190   #endif /* _WIN32||_WIN64 */
+00191 #endif /* TBB_USE_ASSERT */
+00192     }
+00193 
+00195   #if _WIN32||_WIN64
+00196     typedef LPCRITICAL_SECTION native_handle_type;
+00197   #else
+00198     typedef pthread_mutex_t* native_handle_type;
+00199   #endif
+00200     native_handle_type native_handle() { return (native_handle_type) &impl; }
+00201 
+00202     enum state_t {
+00203         INITIALIZED=0x1234,
+00204         DESTROYED=0x789A,
+00205         HELD=0x56CD
+00206     };
+00207 private:
+00208 #if _WIN32||_WIN64
+00209     CRITICAL_SECTION impl;    
+00210     enum state_t state;
+00211 #else
+00212     pthread_mutex_t impl;
+00213 #endif /* _WIN32||_WIN64 */
+00214 
+00216     void __TBB_EXPORTED_METHOD internal_construct();
+00217 
+00219     void __TBB_EXPORTED_METHOD internal_destroy();
+00220 
+00221 #if _WIN32||_WIN64
+00222 public:
+00224     void set_state( state_t to ) { state = to; }
+00225 #endif
+00226 };
+00227 
+00228 __TBB_DEFINE_PROFILING_SET_NAME(mutex)
+00229 
+00230 } // namespace tbb 
+00231 
+00232 #endif /* __TBB_mutex_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00533.html b/src/tbb/doc/html/a00533.html new file mode 100644 index 0000000..1743080 --- /dev/null +++ b/src/tbb/doc/html/a00533.html @@ -0,0 +1,81 @@ + + +null_mutex.h Source File + + + + + + +

null_mutex.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_null_mutex_H
+00022 #define __TBB_null_mutex_H
+00023 
+00024 namespace tbb {
+00025     
+00027 
+00029 class null_mutex {   
+00031     null_mutex( const null_mutex& );   
+00032     void operator=( const null_mutex& );   
+00033 public:   
+00035     class scoped_lock {   
+00036     public:   
+00037         scoped_lock() {}
+00038         scoped_lock( null_mutex& ) {}   
+00039         ~scoped_lock() {}
+00040         void acquire( null_mutex& ) {}
+00041         bool try_acquire( null_mutex& ) { return true; }
+00042         void release() {}
+00043     };
+00044   
+00045     null_mutex() {}
+00046     
+00047     // Mutex traits   
+00048     static const bool is_rw_mutex = false;   
+00049     static const bool is_recursive_mutex = true;
+00050     static const bool is_fair_mutex = true;
+00051 };  
+00052 
+00053 }
+00054 
+00055 #endif /* __TBB_null_mutex_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00534.html b/src/tbb/doc/html/a00534.html new file mode 100644 index 0000000..9981ca0 --- /dev/null +++ b/src/tbb/doc/html/a00534.html @@ -0,0 +1,83 @@ + + +null_rw_mutex.h Source File + + + + + + +

null_rw_mutex.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_null_rw_mutex_H
+00022 #define __TBB_null_rw_mutex_H
+00023 
+00024 namespace tbb {
+00025     
+00027 
+00029 class null_rw_mutex {
+00031     null_rw_mutex( const null_rw_mutex& );   
+00032     void operator=( const null_rw_mutex& );   
+00033 public:   
+00035     class scoped_lock {   
+00036     public:   
+00037         scoped_lock() {}
+00038         scoped_lock( null_rw_mutex& , bool = true ) {}
+00039         ~scoped_lock() {}
+00040         void acquire( null_rw_mutex& , bool = true ) {}
+00041         bool upgrade_to_writer() { return true; }
+00042         bool downgrade_to_reader() { return true; }
+00043         bool try_acquire( null_rw_mutex& , bool = true ) { return true; }
+00044         void release() {}
+00045     };
+00046   
+00047     null_rw_mutex() {}
+00048     
+00049     // Mutex traits   
+00050     static const bool is_rw_mutex = true;   
+00051     static const bool is_recursive_mutex = true;
+00052     static const bool is_fair_mutex = true;
+00053 };  
+00054 
+00055 }
+00056 
+00057 #endif /* __TBB_null_rw_mutex_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00535.html b/src/tbb/doc/html/a00535.html new file mode 100644 index 0000000..f1a33ff --- /dev/null +++ b/src/tbb/doc/html/a00535.html @@ -0,0 +1,480 @@ + + +parallel_do.h Source File + + + + + + +

parallel_do.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_parallel_do_H
+00022 #define __TBB_parallel_do_H
+00023 
+00024 #include "task.h"
+00025 #include "aligned_space.h"
+00026 #include <iterator>
+00027 
+00028 namespace tbb {
+00029 
+00031 namespace internal {
+00032     template<typename Body, typename Item> class parallel_do_feeder_impl;
+00033     template<typename Body> class do_group_task;
+00034 
+00036     template<typename T>
+00037     struct strip { typedef T type; };
+00038     template<typename T>
+00039     struct strip<T&> { typedef T type; };
+00040     template<typename T>
+00041     struct strip<const T&> { typedef T type; };
+00042     template<typename T>
+00043     struct strip<volatile T&> { typedef T type; };
+00044     template<typename T>
+00045     struct strip<const volatile T&> { typedef T type; };
+00046     // Most of the compilers remove cv-qualifiers from non-reference function argument types. 
+00047     // But unfortunately there are those that don't.
+00048     template<typename T>
+00049     struct strip<const T> { typedef T type; };
+00050     template<typename T>
+00051     struct strip<volatile T> { typedef T type; };
+00052     template<typename T>
+00053     struct strip<const volatile T> { typedef T type; };
+00054 } // namespace internal
+00056 
+00058 
+00059 template<typename Item>
+00060 class parallel_do_feeder: internal::no_copy
+00061 {
+00062     parallel_do_feeder() {}
+00063     virtual ~parallel_do_feeder () {}
+00064     virtual void internal_add( const Item& item ) = 0;
+00065     template<typename Body_, typename Item_> friend class internal::parallel_do_feeder_impl;
+00066 public:
+00068     void add( const Item& item ) {internal_add(item);}
+00069 };
+00070 
+00072 namespace internal {
+00074 
+00076     template<class Body, typename Item>
+00077     class parallel_do_operator_selector
+00078     {
+00079         typedef parallel_do_feeder<Item> Feeder;
+00080         template<typename A1, typename A2, typename CvItem >
+00081         static void internal_call( const Body& obj, A1& arg1, A2&, void (Body::*)(CvItem) const ) {
+00082             obj(arg1);
+00083         }
+00084         template<typename A1, typename A2, typename CvItem >
+00085         static void internal_call( const Body& obj, A1& arg1, A2& arg2, void (Body::*)(CvItem, parallel_do_feeder<Item>&) const ) {
+00086             obj(arg1, arg2);
+00087         }
+00088 
+00089     public:
+00090         template<typename A1, typename A2 >
+00091         static void call( const Body& obj, A1& arg1, A2& arg2 )
+00092         {
+00093             internal_call( obj, arg1, arg2, &Body::operator() );
+00094         }
+00095     };
+00096 
+00098 
+00100     template<typename Body, typename Item>
+00101     class do_iteration_task: public task
+00102     {
+00103         typedef parallel_do_feeder_impl<Body, Item> feeder_type;
+00104 
+00105         Item my_value;
+00106         feeder_type& my_feeder;
+00107 
+00108         do_iteration_task( const Item& value, feeder_type& feeder ) : 
+00109             my_value(value), my_feeder(feeder)
+00110         {}
+00111 
+00112         /*override*/ 
+00113         task* execute()
+00114         {
+00115             parallel_do_operator_selector<Body, Item>::call(*my_feeder.my_body, my_value, my_feeder);
+00116             return NULL;
+00117         }
+00118 
+00119         template<typename Body_, typename Item_> friend class parallel_do_feeder_impl;
+00120     }; // class do_iteration_task
+00121 
+00122     template<typename Iterator, typename Body, typename Item>
+00123     class do_iteration_task_iter: public task
+00124     {
+00125         typedef parallel_do_feeder_impl<Body, Item> feeder_type;
+00126 
+00127         Iterator my_iter;
+00128         feeder_type& my_feeder;
+00129 
+00130         do_iteration_task_iter( const Iterator& iter, feeder_type& feeder ) : 
+00131             my_iter(iter), my_feeder(feeder)
+00132         {}
+00133 
+00134         /*override*/ 
+00135         task* execute()
+00136         {
+00137             parallel_do_operator_selector<Body, Item>::call(*my_feeder.my_body, *my_iter, my_feeder);
+00138             return NULL;
+00139         }
+00140 
+00141         template<typename Iterator_, typename Body_, typename Item_> friend class do_group_task_forward;    
+00142         template<typename Body_, typename Item_> friend class do_group_task_input;    
+00143         template<typename Iterator_, typename Body_, typename Item_> friend class do_task_iter;    
+00144     }; // class do_iteration_task_iter
+00145 
+00147 
+00149     template<class Body, typename Item>
+00150     class parallel_do_feeder_impl : public parallel_do_feeder<Item>
+00151     {
+00152         /*override*/ 
+00153         void internal_add( const Item& item )
+00154         {
+00155             typedef do_iteration_task<Body, Item> iteration_type;
+00156 
+00157             iteration_type& t = *new (task::allocate_additional_child_of(*my_barrier)) iteration_type(item, *this);
+00158 
+00159             t.spawn( t );
+00160         }
+00161     public:
+00162         const Body* my_body;
+00163         empty_task* my_barrier;
+00164 
+00165         parallel_do_feeder_impl()
+00166         {
+00167             my_barrier = new( task::allocate_root() ) empty_task();
+00168             __TBB_ASSERT(my_barrier, "root task allocation failed");
+00169         }
+00170 
+00171 #if __TBB_TASK_GROUP_CONTEXT
+00172         parallel_do_feeder_impl(tbb::task_group_context &context)
+00173         {
+00174             my_barrier = new( task::allocate_root(context) ) empty_task();
+00175             __TBB_ASSERT(my_barrier, "root task allocation failed");
+00176         }
+00177 #endif
+00178 
+00179         ~parallel_do_feeder_impl()
+00180         {
+00181             my_barrier->destroy(*my_barrier);
+00182         }
+00183     }; // class parallel_do_feeder_impl
+00184 
+00185 
+00187 
+00190     template<typename Iterator, typename Body, typename Item>
+00191     class do_group_task_forward: public task
+00192     {
+00193         static const size_t max_arg_size = 4;         
+00194 
+00195         typedef parallel_do_feeder_impl<Body, Item> feeder_type;
+00196 
+00197         feeder_type& my_feeder;
+00198         Iterator my_first;
+00199         size_t my_size;
+00200         
+00201         do_group_task_forward( Iterator first, size_t size, feeder_type& feeder ) 
+00202             : my_feeder(feeder), my_first(first), my_size(size)
+00203         {}
+00204 
+00205         /*override*/ task* execute()
+00206         {
+00207             typedef do_iteration_task_iter<Iterator, Body, Item> iteration_type;
+00208             __TBB_ASSERT( my_size>0, NULL );
+00209             task_list list;
+00210             task* t; 
+00211             size_t k=0; 
+00212             for(;;) {
+00213                 t = new( allocate_child() ) iteration_type( my_first, my_feeder );
+00214                 ++my_first;
+00215                 if( ++k==my_size ) break;
+00216                 list.push_back(*t);
+00217             }
+00218             set_ref_count(int(k+1));
+00219             spawn(list);
+00220             spawn_and_wait_for_all(*t);
+00221             return NULL;
+00222         }
+00223 
+00224         template<typename Iterator_, typename Body_, typename _Item> friend class do_task_iter;
+00225     }; // class do_group_task_forward
+00226 
+00227     template<typename Body, typename Item>
+00228     class do_group_task_input: public task
+00229     {
+00230         static const size_t max_arg_size = 4;         
+00231         
+00232         typedef parallel_do_feeder_impl<Body, Item> feeder_type;
+00233 
+00234         feeder_type& my_feeder;
+00235         size_t my_size;
+00236         aligned_space<Item, max_arg_size> my_arg;
+00237 
+00238         do_group_task_input( feeder_type& feeder ) 
+00239             : my_feeder(feeder), my_size(0)
+00240         {}
+00241 
+00242         /*override*/ task* execute()
+00243         {
+00244             typedef do_iteration_task_iter<Item*, Body, Item> iteration_type;
+00245             __TBB_ASSERT( my_size>0, NULL );
+00246             task_list list;
+00247             task* t; 
+00248             size_t k=0; 
+00249             for(;;) {
+00250                 t = new( allocate_child() ) iteration_type( my_arg.begin() + k, my_feeder );
+00251                 if( ++k==my_size ) break;
+00252                 list.push_back(*t);
+00253             }
+00254             set_ref_count(int(k+1));
+00255             spawn(list);
+00256             spawn_and_wait_for_all(*t);
+00257             return NULL;
+00258         }
+00259 
+00260         ~do_group_task_input(){
+00261             for( size_t k=0; k<my_size; ++k)
+00262                 (my_arg.begin() + k)->~Item();
+00263         }
+00264 
+00265         template<typename Iterator_, typename Body_, typename Item_> friend class do_task_iter;
+00266     }; // class do_group_task_input
+00267     
+00269 
+00271     template<typename Iterator, typename Body, typename Item>
+00272     class do_task_iter: public task
+00273     {
+00274         typedef parallel_do_feeder_impl<Body, Item> feeder_type;
+00275 
+00276     public:
+00277         do_task_iter( Iterator first, Iterator last , feeder_type& feeder ) : 
+00278             my_first(first), my_last(last), my_feeder(feeder)
+00279         {}
+00280 
+00281     private:
+00282         Iterator my_first;
+00283         Iterator my_last;
+00284         feeder_type& my_feeder;
+00285 
+00286         /* Do not merge run(xxx) and run_xxx() methods. They are separated in order
+00287             to make sure that compilers will eliminate unused argument of type xxx
+00288             (that is will not put it on stack). The sole purpose of this argument 
+00289             is overload resolution.
+00290             
+00291             An alternative could be using template functions, but explicit specialization 
+00292             of member function templates is not supported for non specialized class 
+00293             templates. Besides template functions would always fall back to the least 
+00294             efficient variant (the one for input iterators) in case of iterators having 
+00295             custom tags derived from basic ones. */
+00296         /*override*/ task* execute()
+00297         {
+00298             typedef typename std::iterator_traits<Iterator>::iterator_category iterator_tag;
+00299             return run( (iterator_tag*)NULL );
+00300         }
+00301 
+00304         inline task* run( void* ) { return run_for_input_iterator(); }
+00305         
+00306         task* run_for_input_iterator() {
+00307             typedef do_group_task_input<Body, Item> block_type;
+00308 
+00309             block_type& t = *new( allocate_additional_child_of(*my_feeder.my_barrier) ) block_type(my_feeder);
+00310             size_t k=0; 
+00311             while( !(my_first == my_last) ) {
+00312                 new (t.my_arg.begin() + k) Item(*my_first);
+00313                 ++my_first;
+00314                 if( ++k==block_type::max_arg_size ) {
+00315                     if ( !(my_first == my_last) )
+00316                         recycle_to_reexecute();
+00317                     break;
+00318                 }
+00319             }
+00320             if( k==0 ) {
+00321                 destroy(t);
+00322                 return NULL;
+00323             } else {
+00324                 t.my_size = k;
+00325                 return &t;
+00326             }
+00327         }
+00328 
+00329         inline task* run( std::forward_iterator_tag* ) { return run_for_forward_iterator(); }
+00330 
+00331         task* run_for_forward_iterator() {
+00332             typedef do_group_task_forward<Iterator, Body, Item> block_type;
+00333 
+00334             Iterator first = my_first;
+00335             size_t k=0; 
+00336             while( !(my_first==my_last) ) {
+00337                 ++my_first;
+00338                 if( ++k==block_type::max_arg_size ) {
+00339                     if ( !(my_first==my_last) )
+00340                         recycle_to_reexecute();
+00341                     break;
+00342                 }
+00343             }
+00344             return k==0 ? NULL : new( allocate_additional_child_of(*my_feeder.my_barrier) ) block_type(first, k, my_feeder);
+00345         }
+00346         
+00347         inline task* run( std::random_access_iterator_tag* ) { return run_for_random_access_iterator(); }
+00348 
+00349         task* run_for_random_access_iterator() {
+00350             typedef do_group_task_forward<Iterator, Body, Item> block_type;
+00351             typedef do_iteration_task_iter<Iterator, Body, Item> iteration_type;
+00352             
+00353             size_t k = static_cast<size_t>(my_last-my_first); 
+00354             if( k > block_type::max_arg_size ) {
+00355                 Iterator middle = my_first + k/2;
+00356 
+00357                 empty_task& c = *new( allocate_continuation() ) empty_task;
+00358                 do_task_iter& b = *new( c.allocate_child() ) do_task_iter(middle, my_last, my_feeder);
+00359                 recycle_as_child_of(c);
+00360 
+00361                 my_last = middle;
+00362                 c.set_ref_count(2);
+00363                 c.spawn(b);
+00364                 return this;
+00365             }else if( k != 0 ) {
+00366                 task_list list;
+00367                 task* t; 
+00368                 size_t k1=0; 
+00369                 for(;;) {
+00370                     t = new( allocate_child() ) iteration_type(my_first, my_feeder);
+00371                     ++my_first;
+00372                     if( ++k1==k ) break;
+00373                     list.push_back(*t);
+00374                 }
+00375                 set_ref_count(int(k+1));
+00376                 spawn(list);
+00377                 spawn_and_wait_for_all(*t);
+00378             }
+00379             return NULL;
+00380         }
+00381     }; // class do_task_iter
+00382 
+00384 
+00386     template<typename Iterator, typename Body, typename Item> 
+00387     void run_parallel_do( Iterator first, Iterator last, const Body& body
+00388 #if __TBB_TASK_GROUP_CONTEXT
+00389         , task_group_context& context
+00390 #endif
+00391         )
+00392     {
+00393         typedef do_task_iter<Iterator, Body, Item> root_iteration_task;
+00394 #if __TBB_TASK_GROUP_CONTEXT
+00395         parallel_do_feeder_impl<Body, Item> feeder(context);
+00396 #else
+00397         parallel_do_feeder_impl<Body, Item> feeder;
+00398 #endif
+00399         feeder.my_body = &body;
+00400 
+00401         root_iteration_task &t = *new( feeder.my_barrier->allocate_child() ) root_iteration_task(first, last, feeder);
+00402 
+00403         feeder.my_barrier->set_ref_count(2);
+00404         feeder.my_barrier->spawn_and_wait_for_all(t);
+00405     }
+00406 
+00408 
+00410     template<typename Iterator, typename Body, typename Item> 
+00411     void select_parallel_do( Iterator first, Iterator last, const Body& body, void (Body::*)(Item) const
+00412 #if __TBB_TASK_GROUP_CONTEXT
+00413         , task_group_context& context 
+00414 #endif // __TBB_TASK_GROUP_CONTEXT 
+00415         )
+00416     {
+00417         run_parallel_do<Iterator, Body, typename strip<Item>::type>( first, last, body
+00418 #if __TBB_TASK_GROUP_CONTEXT
+00419             , context
+00420 #endif // __TBB_TASK_GROUP_CONTEXT 
+00421             );
+00422     }
+00423 
+00425 
+00427     template<typename Iterator, typename Body, typename Item, typename _Item> 
+00428     void select_parallel_do( Iterator first, Iterator last, const Body& body, void (Body::*)(Item, parallel_do_feeder<_Item>&) const
+00429 #if __TBB_TASK_GROUP_CONTEXT
+00430         , task_group_context& context 
+00431 #endif // __TBB_TASK_GROUP_CONTEXT
+00432         )
+00433     {
+00434         run_parallel_do<Iterator, Body, typename strip<Item>::type>( first, last, body
+00435 #if __TBB_TASK_GROUP_CONTEXT
+00436             , context
+00437 #endif // __TBB_TASK_GROUP_CONTEXT
+00438             );
+00439     }
+00440 
+00441 } // namespace internal
+00443 
+00444 
+00467 
+00468 
+00469 template<typename Iterator, typename Body> 
+00470 void parallel_do( Iterator first, Iterator last, const Body& body )
+00471 {
+00472     if ( first == last )
+00473         return;
+00474 #if __TBB_TASK_GROUP_CONTEXT
+00475     task_group_context context;
+00476 #endif // __TBB_TASK_GROUP_CONTEXT
+00477     internal::select_parallel_do( first, last, body, &Body::operator()
+00478 #if __TBB_TASK_GROUP_CONTEXT
+00479         , context
+00480 #endif // __TBB_TASK_GROUP_CONTEXT
+00481         );
+00482 }
+00483 
+00484 #if __TBB_TASK_GROUP_CONTEXT
+00486 
+00487 template<typename Iterator, typename Body> 
+00488 void parallel_do( Iterator first, Iterator last, const Body& body, task_group_context& context  )
+00489 {
+00490     if ( first == last )
+00491         return;
+00492     internal::select_parallel_do( first, last, body, &Body::operator(), context );
+00493 }
+00494 #endif // __TBB_TASK_GROUP_CONTEXT
+00495 
+00497 
+00498 } // namespace 
+00499 
+00500 #endif /* __TBB_parallel_do_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00544.html b/src/tbb/doc/html/a00544.html new file mode 100644 index 0000000..4e3d497 --- /dev/null +++ b/src/tbb/doc/html/a00544.html @@ -0,0 +1,256 @@ + + +parallel_for.h Source File + + + + + + +

parallel_for.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_parallel_for_H
+00022 #define __TBB_parallel_for_H
+00023 
+00024 #include <new>
+00025 #include "task.h"
+00026 #include "partitioner.h"
+00027 #include "blocked_range.h"
+00028 #include "tbb_exception.h"
+00029 
+00030 namespace tbb {
+00031 
+00032 namespace interface6 {
+00034 namespace internal {
+00035 
+00037 
+00038     template<typename Range, typename Body, typename Partitioner>
+00039     class start_for: public task {
+00040         Range my_range;
+00041         const Body my_body;
+00042         typename Partitioner::task_partition_type my_partition;
+00043         /*override*/ task* execute();
+00044 
+00045     public:
+00047         start_for( const Range& range, const Body& body, Partitioner& partitioner ) :
+00048             my_range(range),    
+00049             my_body(body),
+00050             my_partition(partitioner)
+00051         {
+00052         }
+00054 
+00055         start_for( start_for& parent_, split ) :
+00056             my_range(parent_.my_range,split()),
+00057             my_body(parent_.my_body),
+00058             my_partition(parent_.my_partition, split())
+00059         {
+00060             my_partition.set_affinity(*this);
+00061         }
+00063 
+00064         start_for( start_for& parent_, const Range& r, depth_t d ) :
+00065             my_range(r),
+00066             my_body(parent_.my_body),
+00067             my_partition(parent_.my_partition,split())
+00068         {
+00069             my_partition.set_affinity(*this);
+00070             my_partition.align_depth( d );
+00071         }
+00073         /*override*/ void note_affinity( affinity_id id ) {
+00074             my_partition.note_affinity( id );
+00075         }
+00076         static void run(  const Range& range, const Body& body, const Partitioner& partitioner ) {
+00077             if( !range.empty() ) {
+00078 #if !__TBB_TASK_GROUP_CONTEXT || TBB_JOIN_OUTER_TASK_GROUP
+00079                 start_for& a = *new(task::allocate_root()) start_for(range,body,const_cast<Partitioner&>(partitioner));
+00080 #else
+00081                 // Bound context prevents exceptions from body to affect nesting or sibling algorithms,
+00082                 // and allows users to handle exceptions safely by wrapping parallel_for in the try-block.
+00083                 task_group_context context;
+00084                 start_for& a = *new(task::allocate_root(context)) start_for(range,body,const_cast<Partitioner&>(partitioner));
+00085 #endif /* __TBB_TASK_GROUP_CONTEXT && !TBB_JOIN_OUTER_TASK_GROUP */
+00086                 task::spawn_root_and_wait(a);
+00087             }
+00088         }
+00089 #if __TBB_TASK_GROUP_CONTEXT
+00090         static void run(  const Range& range, const Body& body, const Partitioner& partitioner, task_group_context& context ) {
+00091             if( !range.empty() ) {
+00092                 start_for& a = *new(task::allocate_root(context)) start_for(range,body,const_cast<Partitioner&>(partitioner));
+00093                 task::spawn_root_and_wait(a);
+00094             }
+00095         }
+00096 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00098         flag_task *create_continuation() {
+00099             return new( allocate_continuation() ) flag_task();
+00100         }
+00102         void run_body( Range &r ) { my_body( r ); }
+00103     };
+00104 
+00105     template<typename Range, typename Body, typename Partitioner>
+00106     task* start_for<Range,Body,Partitioner>::execute() {
+00107         my_partition.check_being_stolen( *this );
+00108         my_partition.execute(*this, my_range);
+00109         return NULL;
+00110     } 
+00111 } // namespace internal
+00113 } // namespace interfaceX
+00114 
+00116 namespace internal {
+00117     using interface6::internal::start_for;
+00118     
+00120     template<typename Function, typename Index>
+00121     class parallel_for_body : internal::no_assign {
+00122         const Function &my_func;
+00123         const Index my_begin;
+00124         const Index my_step; 
+00125     public:
+00126         parallel_for_body( const Function& _func, Index& _begin, Index& _step) 
+00127             : my_func(_func), my_begin(_begin), my_step(_step) {}
+00128         
+00129         void operator()( tbb::blocked_range<Index>& r ) const {
+00130             for( Index i = r.begin(),  k = my_begin + i * my_step; i < r.end(); i++, k = k + my_step)
+00131                 my_func( k );
+00132         }
+00133     };
+00134 } // namespace internal
+00136 
+00137 // Requirements on Range concept are documented in blocked_range.h
+00138 
+00149 
+00151 
+00152 template<typename Range, typename Body>
+00153 void parallel_for( const Range& range, const Body& body ) {
+00154     internal::start_for<Range,Body,__TBB_DEFAULT_PARTITIONER>::run(range,body,__TBB_DEFAULT_PARTITIONER());
+00155 }
+00156 
+00158 
+00159 template<typename Range, typename Body>
+00160 void parallel_for( const Range& range, const Body& body, const simple_partitioner& partitioner ) {
+00161     internal::start_for<Range,Body,simple_partitioner>::run(range,body,partitioner);
+00162 }
+00163 
+00165 
+00166 template<typename Range, typename Body>
+00167 void parallel_for( const Range& range, const Body& body, const auto_partitioner& partitioner ) {
+00168     internal::start_for<Range,Body,auto_partitioner>::run(range,body,partitioner);
+00169 }
+00170 
+00172 
+00173 template<typename Range, typename Body>
+00174 void parallel_for( const Range& range, const Body& body, affinity_partitioner& partitioner ) {
+00175     internal::start_for<Range,Body,affinity_partitioner>::run(range,body,partitioner);
+00176 }
+00177 
+00178 #if __TBB_TASK_GROUP_CONTEXT
+00180 
+00181 template<typename Range, typename Body>
+00182 void parallel_for( const Range& range, const Body& body, const simple_partitioner& partitioner, task_group_context& context ) {
+00183     internal::start_for<Range,Body,simple_partitioner>::run(range, body, partitioner, context);
+00184 }
+00185 
+00187 
+00188 template<typename Range, typename Body>
+00189 void parallel_for( const Range& range, const Body& body, const auto_partitioner& partitioner, task_group_context& context ) {
+00190     internal::start_for<Range,Body,auto_partitioner>::run(range, body, partitioner, context);
+00191 }
+00192 
+00194 
+00195 template<typename Range, typename Body>
+00196 void parallel_for( const Range& range, const Body& body, affinity_partitioner& partitioner, task_group_context& context ) {
+00197     internal::start_for<Range,Body,affinity_partitioner>::run(range,body,partitioner, context);
+00198 }
+00199 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00200 
+00201 
+00202 namespace strict_ppl {
+00203 
+00205 
+00206 template <typename Index, typename Function>
+00207 void parallel_for(Index first, Index last, Index step, const Function& f) {
+00208     if (step <= 0 )
+00209         internal::throw_exception(internal::eid_nonpositive_step); // throws std::invalid_argument
+00210     else if (last > first) {
+00211         // Above "else" avoids "potential divide by zero" warning on some platforms
+00212         Index end = (last - first - Index(1)) / step + Index(1);
+00213         tbb::blocked_range<Index> range(static_cast<Index>(0), end);
+00214         internal::parallel_for_body<Function, Index> body(f, first, step);
+00215         tbb::parallel_for(range, body, tbb::auto_partitioner());
+00216     }
+00217 }
+00219 template <typename Index, typename Function>
+00220 void parallel_for(Index first, Index last, const Function& f) {
+00221     parallel_for(first, last, static_cast<Index>(1), f);
+00222 }
+00223 
+00224 #if __TBB_TASK_GROUP_CONTEXT
+00226 template <typename Index, typename Function>
+00227 void parallel_for(Index first, Index last, Index step, const Function& f, tbb::task_group_context &context) {
+00228     if (step <= 0 )
+00229         internal::throw_exception(internal::eid_nonpositive_step); // throws std::invalid_argument
+00230     else if (last > first) {
+00231         // Above "else" avoids "potential divide by zero" warning on some platforms
+00232         Index end = (last - first - Index(1)) / step + Index(1);
+00233         tbb::blocked_range<Index> range(static_cast<Index>(0), end);
+00234         internal::parallel_for_body<Function, Index> body(f, first, step);
+00235         tbb::parallel_for(range, body, tbb::auto_partitioner(), context);
+00236     }
+00237 }
+00239 template <typename Index, typename Function>
+00240 void parallel_for(Index first, Index last, const Function& f, tbb::task_group_context &context) {
+00241     parallel_for(first, last, static_cast<Index>(1), f, context);
+00242 }
+00243 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00244 
+00245 
+00246 } // namespace strict_ppl
+00247 
+00248 using strict_ppl::parallel_for;
+00249 
+00250 } // namespace tbb
+00251 
+00252 #if TBB_PREVIEW_SERIAL_SUBSET
+00253 #define __TBB_NORMAL_EXECUTION
+00254 #include "../serial/tbb/parallel_for.h"
+00255 #undef __TBB_NORMAL_EXECUTION
+00256 #endif
+00257 
+00258 #endif /* __TBB_parallel_for_H */
+00259 
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00548.html b/src/tbb/doc/html/a00548.html new file mode 100644 index 0000000..d89d71a --- /dev/null +++ b/src/tbb/doc/html/a00548.html @@ -0,0 +1,92 @@ + + +parallel_for_each.h Source File + + + + + + +

parallel_for_each.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_parallel_for_each_H
+00022 #define __TBB_parallel_for_each_H
+00023 
+00024 #include "parallel_do.h"
+00025 
+00026 namespace tbb {
+00027 
+00029 namespace internal {
+00030     // The class calls user function in operator()
+00031     template <typename Function, typename Iterator>
+00032     class parallel_for_each_body : internal::no_assign {
+00033         const Function &my_func;
+00034     public:
+00035         parallel_for_each_body(const Function &_func) : my_func(_func) {}
+00036         parallel_for_each_body(const parallel_for_each_body<Function, Iterator> &_caller) : my_func(_caller.my_func) {}
+00037 
+00038         void operator() ( typename std::iterator_traits<Iterator>::reference value ) const {
+00039             my_func(value);
+00040         }
+00041     };
+00042 } // namespace internal
+00044 
+00048 
+00049 
+00050 #if __TBB_TASK_GROUP_CONTEXT
+00051 template<typename InputIterator, typename Function>
+00052 void parallel_for_each(InputIterator first, InputIterator last, const Function& f, task_group_context &context) {
+00053     internal::parallel_for_each_body<Function, InputIterator> body(f);
+00054     tbb::parallel_do (first, last, body, context);
+00055 }
+00056 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00057 
+00059 template<typename InputIterator, typename Function>
+00060 void parallel_for_each(InputIterator first, InputIterator last, const Function& f) {
+00061     internal::parallel_for_each_body<Function, InputIterator> body(f);
+00062     tbb::parallel_do (first, last, body);
+00063 }
+00064 
+00066 
+00067 } // namespace
+00068 
+00069 #endif /* __TBB_parallel_for_each_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00550.html b/src/tbb/doc/html/a00550.html new file mode 100644 index 0000000..e4c96d7 --- /dev/null +++ b/src/tbb/doc/html/a00550.html @@ -0,0 +1,386 @@ + + +parallel_invoke.h Source File + + + + + + +

parallel_invoke.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_parallel_invoke_H
+00022 #define __TBB_parallel_invoke_H
+00023 
+00024 #include "task.h"
+00025 
+00026 namespace tbb {
+00027 
+00028 #if !__TBB_TASK_GROUP_CONTEXT
+00029 
+00030     struct task_group_context {};
+00031 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00032 
+00034 namespace internal {
+00035     // Simple task object, executing user method
+00036     template<typename function>
+00037     class function_invoker : public task{
+00038     public:
+00039         function_invoker(const function& _function) : my_function(_function) {}
+00040     private:
+00041         const function &my_function;
+00042         /*override*/
+00043         task* execute()
+00044         {
+00045             my_function();
+00046             return NULL;
+00047         }
+00048     };
+00049 
+00050     // The class spawns two or three child tasks
+00051     template <size_t N, typename function1, typename function2, typename function3>
+00052     class spawner : public task {
+00053     private:
+00054         const function1& my_func1;
+00055         const function2& my_func2;
+00056         const function3& my_func3;
+00057         bool is_recycled;
+00058 
+00059         task* execute (){
+00060             if(is_recycled){
+00061                 return NULL;
+00062             }else{
+00063                 __TBB_ASSERT(N==2 || N==3, "Number of arguments passed to spawner is wrong");
+00064                 set_ref_count(N);
+00065                 recycle_as_safe_continuation();
+00066                 internal::function_invoker<function2>* invoker2 = new (allocate_child()) internal::function_invoker<function2>(my_func2);
+00067                 __TBB_ASSERT(invoker2, "Child task allocation failed");
+00068                 spawn(*invoker2);
+00069                 size_t n = N; // To prevent compiler warnings
+00070                 if (n>2) {
+00071                     internal::function_invoker<function3>* invoker3 = new (allocate_child()) internal::function_invoker<function3>(my_func3);
+00072                     __TBB_ASSERT(invoker3, "Child task allocation failed");
+00073                     spawn(*invoker3);
+00074                 }
+00075                 my_func1();
+00076                 is_recycled = true;
+00077                 return NULL;
+00078             }
+00079         } // execute
+00080 
+00081     public:
+00082         spawner(const function1& _func1, const function2& _func2, const function3& _func3) : my_func1(_func1), my_func2(_func2), my_func3(_func3), is_recycled(false) {}
+00083     };
+00084 
+00085     // Creates and spawns child tasks
+00086     class parallel_invoke_helper : public empty_task {
+00087     public:
+00088         // Dummy functor class
+00089         class parallel_invoke_noop {
+00090         public:
+00091             void operator() () const {}
+00092         };
+00093         // Creates a helper object with user-defined number of children expected
+00094         parallel_invoke_helper(int number_of_children)
+00095         {
+00096             set_ref_count(number_of_children + 1);
+00097         }
+00098         // Adds child task and spawns it
+00099         template <typename function>
+00100         void add_child (const function &_func)
+00101         {
+00102             internal::function_invoker<function>* invoker = new (allocate_child()) internal::function_invoker<function>(_func);
+00103             __TBB_ASSERT(invoker, "Child task allocation failed");
+00104             spawn(*invoker);
+00105         }
+00106 
+00107         // Adds a task with multiple child tasks and spawns it
+00108         // two arguments
+00109         template <typename function1, typename function2>
+00110         void add_children (const function1& _func1, const function2& _func2)
+00111         {
+00112             // The third argument is dummy, it is ignored actually.
+00113             parallel_invoke_noop noop;
+00114             internal::spawner<2, function1, function2, parallel_invoke_noop>& sub_root = *new(allocate_child())internal::spawner<2, function1, function2, parallel_invoke_noop>(_func1, _func2, noop);
+00115             spawn(sub_root);
+00116         }
+00117         // three arguments
+00118         template <typename function1, typename function2, typename function3>
+00119         void add_children (const function1& _func1, const function2& _func2, const function3& _func3)
+00120         {
+00121             internal::spawner<3, function1, function2, function3>& sub_root = *new(allocate_child())internal::spawner<3, function1, function2, function3>(_func1, _func2, _func3);
+00122             spawn(sub_root);
+00123         }
+00124 
+00125         // Waits for all child tasks
+00126         template <typename F0>
+00127         void run_and_finish(const F0& f0)
+00128         {
+00129             internal::function_invoker<F0>* invoker = new (allocate_child()) internal::function_invoker<F0>(f0);
+00130             __TBB_ASSERT(invoker, "Child task allocation failed");
+00131             spawn_and_wait_for_all(*invoker);
+00132         }
+00133     };
+00134     // The class destroys root if exception occurred as well as in normal case
+00135     class parallel_invoke_cleaner: internal::no_copy {
+00136     public:
+00137 #if __TBB_TASK_GROUP_CONTEXT
+00138         parallel_invoke_cleaner(int number_of_children, tbb::task_group_context& context)
+00139             : root(*new(task::allocate_root(context)) internal::parallel_invoke_helper(number_of_children))
+00140 #else
+00141         parallel_invoke_cleaner(int number_of_children, tbb::task_group_context&)
+00142             : root(*new(task::allocate_root()) internal::parallel_invoke_helper(number_of_children))
+00143 #endif /* !__TBB_TASK_GROUP_CONTEXT */
+00144         {}
+00145 
+00146         ~parallel_invoke_cleaner(){
+00147             root.destroy(root);
+00148         }
+00149         internal::parallel_invoke_helper& root;
+00150     };
+00151 } // namespace internal
+00153 
+00157 
+00158 
+00160 // parallel_invoke with user-defined context
+00161 // two arguments
+00162 template<typename F0, typename F1 >
+00163 void parallel_invoke(const F0& f0, const F1& f1, tbb::task_group_context& context) {
+00164     internal::parallel_invoke_cleaner cleaner(2, context);
+00165     internal::parallel_invoke_helper& root = cleaner.root;
+00166 
+00167     root.add_child(f1);
+00168 
+00169     root.run_and_finish(f0);
+00170 }
+00171 
+00172 // three arguments
+00173 template<typename F0, typename F1, typename F2 >
+00174 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, tbb::task_group_context& context) {
+00175     internal::parallel_invoke_cleaner cleaner(3, context);
+00176     internal::parallel_invoke_helper& root = cleaner.root;
+00177 
+00178     root.add_child(f2);
+00179     root.add_child(f1);
+00180 
+00181     root.run_and_finish(f0);
+00182 }
+00183 
+00184 // four arguments
+00185 template<typename F0, typename F1, typename F2, typename F3>
+00186 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3,
+00187                      tbb::task_group_context& context)
+00188 {
+00189     internal::parallel_invoke_cleaner cleaner(4, context);
+00190     internal::parallel_invoke_helper& root = cleaner.root;
+00191 
+00192     root.add_child(f3);
+00193     root.add_child(f2);
+00194     root.add_child(f1);
+00195 
+00196     root.run_and_finish(f0);
+00197 }
+00198 
+00199 // five arguments
+00200 template<typename F0, typename F1, typename F2, typename F3, typename F4 >
+00201 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4,
+00202                      tbb::task_group_context& context)
+00203 {
+00204     internal::parallel_invoke_cleaner cleaner(3, context);
+00205     internal::parallel_invoke_helper& root = cleaner.root;
+00206 
+00207     root.add_children(f4, f3);
+00208     root.add_children(f2, f1);
+00209 
+00210     root.run_and_finish(f0);
+00211 }
+00212 
+00213 // six arguments
+00214 template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5>
+00215 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, const F5& f5,
+00216                      tbb::task_group_context& context)
+00217 {
+00218     internal::parallel_invoke_cleaner cleaner(3, context);
+00219     internal::parallel_invoke_helper& root = cleaner.root;
+00220 
+00221     root.add_children(f5, f4, f3);
+00222     root.add_children(f2, f1);
+00223 
+00224     root.run_and_finish(f0);
+00225 }
+00226 
+00227 // seven arguments
+00228 template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6>
+00229 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4,
+00230                      const F5& f5, const F6& f6,
+00231                      tbb::task_group_context& context)
+00232 {
+00233     internal::parallel_invoke_cleaner cleaner(3, context);
+00234     internal::parallel_invoke_helper& root = cleaner.root;
+00235 
+00236     root.add_children(f6, f5, f4);
+00237     root.add_children(f3, f2, f1);
+00238 
+00239     root.run_and_finish(f0);
+00240 }
+00241 
+00242 // eight arguments
+00243 template<typename F0, typename F1, typename F2, typename F3, typename F4,
+00244          typename F5, typename F6, typename F7>
+00245 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4,
+00246                      const F5& f5, const F6& f6, const F7& f7,
+00247                      tbb::task_group_context& context)
+00248 {
+00249     internal::parallel_invoke_cleaner cleaner(4, context);
+00250     internal::parallel_invoke_helper& root = cleaner.root;
+00251 
+00252     root.add_children(f7, f6, f5);
+00253     root.add_children(f4, f3);
+00254     root.add_children(f2, f1);
+00255 
+00256     root.run_and_finish(f0);
+00257 }
+00258 
+00259 // nine arguments
+00260 template<typename F0, typename F1, typename F2, typename F3, typename F4,
+00261          typename F5, typename F6, typename F7, typename F8>
+00262 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4,
+00263                      const F5& f5, const F6& f6, const F7& f7, const F8& f8,
+00264                      tbb::task_group_context& context)
+00265 {
+00266     internal::parallel_invoke_cleaner cleaner(4, context);
+00267     internal::parallel_invoke_helper& root = cleaner.root;
+00268 
+00269     root.add_children(f8, f7, f6);
+00270     root.add_children(f5, f4, f3);
+00271     root.add_children(f2, f1);
+00272 
+00273     root.run_and_finish(f0);
+00274 }
+00275 
+00276 // ten arguments
+00277 template<typename F0, typename F1, typename F2, typename F3, typename F4,
+00278          typename F5, typename F6, typename F7, typename F8, typename F9>
+00279 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4,
+00280                      const F5& f5, const F6& f6, const F7& f7, const F8& f8, const F9& f9,
+00281                      tbb::task_group_context& context)
+00282 {
+00283     internal::parallel_invoke_cleaner cleaner(4, context);
+00284     internal::parallel_invoke_helper& root = cleaner.root;
+00285 
+00286     root.add_children(f9, f8, f7);
+00287     root.add_children(f6, f5, f4);
+00288     root.add_children(f3, f2, f1);
+00289 
+00290     root.run_and_finish(f0);
+00291 }
+00292 
+00293 // two arguments
+00294 template<typename F0, typename F1>
+00295 void parallel_invoke(const F0& f0, const F1& f1) {
+00296     task_group_context context;
+00297     parallel_invoke<F0, F1>(f0, f1, context);
+00298 }
+00299 // three arguments
+00300 template<typename F0, typename F1, typename F2>
+00301 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2) {
+00302     task_group_context context;
+00303     parallel_invoke<F0, F1, F2>(f0, f1, f2, context);
+00304 }
+00305 // four arguments
+00306 template<typename F0, typename F1, typename F2, typename F3 >
+00307 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3) {
+00308     task_group_context context;
+00309     parallel_invoke<F0, F1, F2, F3>(f0, f1, f2, f3, context);
+00310 }
+00311 // five arguments
+00312 template<typename F0, typename F1, typename F2, typename F3, typename F4>
+00313 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4) {
+00314     task_group_context context;
+00315     parallel_invoke<F0, F1, F2, F3, F4>(f0, f1, f2, f3, f4, context);
+00316 }
+00317 // six arguments
+00318 template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5>
+00319 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, const F5& f5) {
+00320     task_group_context context;
+00321     parallel_invoke<F0, F1, F2, F3, F4, F5>(f0, f1, f2, f3, f4, f5, context);
+00322 }
+00323 // seven arguments
+00324 template<typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, typename F6>
+00325 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4,
+00326                      const F5& f5, const F6& f6)
+00327 {
+00328     task_group_context context;
+00329     parallel_invoke<F0, F1, F2, F3, F4, F5, F6>(f0, f1, f2, f3, f4, f5, f6, context);
+00330 }
+00331 // eigth arguments
+00332 template<typename F0, typename F1, typename F2, typename F3, typename F4,
+00333          typename F5, typename F6, typename F7>
+00334 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4,
+00335                      const F5& f5, const F6& f6, const F7& f7)
+00336 {
+00337     task_group_context context;
+00338     parallel_invoke<F0, F1, F2, F3, F4, F5, F6, F7>(f0, f1, f2, f3, f4, f5, f6, f7, context);
+00339 }
+00340 // nine arguments
+00341 template<typename F0, typename F1, typename F2, typename F3, typename F4,
+00342          typename F5, typename F6, typename F7, typename F8>
+00343 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4,
+00344                      const F5& f5, const F6& f6, const F7& f7, const F8& f8)
+00345 {
+00346     task_group_context context;
+00347     parallel_invoke<F0, F1, F2, F3, F4, F5, F6, F7, F8>(f0, f1, f2, f3, f4, f5, f6, f7, f8, context);
+00348 }
+00349 // ten arguments
+00350 template<typename F0, typename F1, typename F2, typename F3, typename F4,
+00351          typename F5, typename F6, typename F7, typename F8, typename F9>
+00352 void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4,
+00353                      const F5& f5, const F6& f6, const F7& f7, const F8& f8, const F9& f9)
+00354 {
+00355     task_group_context context;
+00356     parallel_invoke<F0, F1, F2, F3, F4, F5, F6, F7, F8, F9>(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, context);
+00357 }
+00358 
+00360 
+00361 } // namespace
+00362 
+00363 #endif /* __TBB_parallel_invoke_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00556.html b/src/tbb/doc/html/a00556.html new file mode 100644 index 0000000..0aa7595 --- /dev/null +++ b/src/tbb/doc/html/a00556.html @@ -0,0 +1,476 @@ + + +parallel_reduce.h Source File + + + + + + +

parallel_reduce.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_parallel_reduce_H
+00022 #define __TBB_parallel_reduce_H
+00023 
+00024 #include <new>
+00025 #include "task.h"
+00026 #include "aligned_space.h"
+00027 #include "partitioner.h"
+00028 #include "tbb_profiling.h"
+00029 
+00030 namespace tbb {
+00031 
+00032 namespace interface6 {
+00034 namespace internal {
+00035 
+00036     using namespace tbb::internal;
+00037 
+00039     enum {
+00040         root_task, left_child, right_child
+00041     };
+00042 
+00044     typedef char reduction_context;
+00045 
+00047 
+00048     template<typename Body>
+00049     class finish_reduce: public flag_task {
+00051         bool has_right_zombie;
+00052         const reduction_context my_context;
+00053         Body* my_body;
+00054         aligned_space<Body,1> zombie_space;
+00055         finish_reduce( reduction_context context_ ) :
+00056             has_right_zombie(false), // TODO: substitute by flag_task::child_stolen?
+00057             my_context(context_),
+00058             my_body(NULL)
+00059         {
+00060         }
+00061         task* execute() {
+00062             if( has_right_zombie ) {
+00063                 // Right child was stolen.
+00064                 Body* s = zombie_space.begin();
+00065                 my_body->join( *s );
+00066                 s->~Body();
+00067             }
+00068             if( my_context==left_child )
+00069                 itt_store_word_with_release( static_cast<finish_reduce*>(parent())->my_body, my_body );
+00070             return NULL;
+00071         }
+00072         template<typename Range,typename Body_, typename Partitioner>
+00073         friend class start_reduce;
+00074     };
+00075 
+00077 
+00078     template<typename Range, typename Body, typename Partitioner>
+00079     class start_reduce: public task {
+00080         typedef finish_reduce<Body> finish_type;
+00081         Body* my_body;
+00082         Range my_range;
+00083         typename Partitioner::task_partition_type my_partition;
+00084         reduction_context my_context; // TODO: factor out into start_reduce_base
+00085         /*override*/ task* execute();
+00086         template<typename Body_>
+00087         friend class finish_reduce;
+00088 
+00089 public:
+00091         start_reduce( const Range& range, Body* body, Partitioner& partitioner ) :
+00092             my_body(body),
+00093             my_range(range),
+00094             my_partition(partitioner),
+00095             my_context(root_task)
+00096         {
+00097         }
+00099 
+00100         start_reduce( start_reduce& parent_, split ) :
+00101             my_body(parent_.my_body),
+00102             my_range(parent_.my_range,split()),
+00103             my_partition(parent_.my_partition,split()),
+00104             my_context(right_child)
+00105         {
+00106             my_partition.set_affinity(*this);
+00107             parent_.my_context = left_child;
+00108         }
+00110 
+00111         start_reduce( start_reduce& parent_, const Range& r, depth_t d ) :
+00112             my_body(parent_.my_body),
+00113             my_range(r),
+00114             my_partition(parent_.my_partition,split()),
+00115             my_context(right_child)
+00116         {
+00117             my_partition.set_affinity(*this);
+00118             my_partition.align_depth( d );
+00119             parent_.my_context = left_child;
+00120         }
+00122         /*override*/ void note_affinity( affinity_id id ) {
+00123             my_partition.note_affinity( id );
+00124         }
+00125         static void run( const Range& range, Body& body, Partitioner& partitioner ) {
+00126             if( !range.empty() ) {
+00127 #if !__TBB_TASK_GROUP_CONTEXT || TBB_JOIN_OUTER_TASK_GROUP
+00128                 task::spawn_root_and_wait( *new(task::allocate_root()) start_reduce(range,&body,partitioner) );
+00129 #else
+00130                 // Bound context prevents exceptions from body to affect nesting or sibling algorithms,
+00131                 // and allows users to handle exceptions safely by wrapping parallel_for in the try-block.
+00132                 task_group_context context;
+00133                 task::spawn_root_and_wait( *new(task::allocate_root(context)) start_reduce(range,&body,partitioner) );
+00134 #endif /* __TBB_TASK_GROUP_CONTEXT && !TBB_JOIN_OUTER_TASK_GROUP */
+00135             }
+00136         }
+00137 #if __TBB_TASK_GROUP_CONTEXT
+00138         static void run( const Range& range, Body& body, Partitioner& partitioner, task_group_context& context ) {
+00139             if( !range.empty() )
+00140                 task::spawn_root_and_wait( *new(task::allocate_root(context)) start_reduce(range,&body,partitioner) );
+00141         }
+00142 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00144         finish_type *create_continuation() {
+00145             return new( allocate_continuation() ) finish_type(my_context);
+00146         }
+00148         void run_body( Range &r ) { (*my_body)( r ); }
+00149     };
+00150     template<typename Range, typename Body, typename Partitioner>
+00151     task* start_reduce<Range,Body,Partitioner>::execute() {
+00152         my_partition.check_being_stolen( *this );
+00153         if( my_context==right_child ) {
+00154             finish_type* parent_ptr = static_cast<finish_type*>(parent());
+00155             if( !itt_load_word_with_acquire(parent_ptr->my_body) ) { // TODO: replace by is_stolen_task() or by parent_ptr->ref_count() == 2???
+00156                 my_body = new( parent_ptr->zombie_space.begin() ) Body(*my_body,split());
+00157                 parent_ptr->has_right_zombie = true;
+00158             }
+00159         } else __TBB_ASSERT(my_context==root_task,NULL);// because left leaf spawns right leafs without recycling
+00160         my_partition.execute(*this, my_range);
+00161         if( my_context==left_child ) {
+00162             finish_type* parent_ptr = static_cast<finish_type*>(parent());
+00163             __TBB_ASSERT(my_body!=parent_ptr->zombie_space.begin(),NULL);
+00164             itt_store_word_with_release(parent_ptr->my_body, my_body );
+00165         }
+00166         return NULL;
+00167     }
+00168 
+00169 #if TBB_PREVIEW_DETERMINISTIC_REDUCE
+00171 
+00172     template<typename Body>
+00173     class finish_deterministic_reduce: public task {
+00174         Body &my_left_body;
+00175         Body my_right_body;
+00176 
+00177         finish_deterministic_reduce( Body &body ) :
+00178             my_left_body( body ),
+00179             my_right_body( body, split() )
+00180         {
+00181         }
+00182         task* execute() {
+00183             my_left_body.join( my_right_body );
+00184             return NULL;
+00185         }
+00186         template<typename Range,typename Body_>
+00187         friend class start_deterministic_reduce;
+00188     };
+00189 
+00191 
+00192     template<typename Range, typename Body>
+00193     class start_deterministic_reduce: public task {
+00194         typedef finish_deterministic_reduce<Body> finish_type;
+00195         Body &my_body;
+00196         Range my_range;
+00197         /*override*/ task* execute();
+00198 
+00200         start_deterministic_reduce( const Range& range, Body& body ) :
+00201             my_body( body ),
+00202             my_range( range )
+00203         {
+00204         }
+00206 
+00207         start_deterministic_reduce( start_deterministic_reduce& parent_, finish_type& c ) :
+00208             my_body( c.my_right_body ),
+00209             my_range( parent_.my_range, split() )
+00210         {
+00211         }
+00212 
+00213 public:
+00214         static void run( const Range& range, Body& body ) {
+00215             if( !range.empty() ) {
+00216 #if !__TBB_TASK_GROUP_CONTEXT || TBB_JOIN_OUTER_TASK_GROUP
+00217                 task::spawn_root_and_wait( *new(task::allocate_root()) start_deterministic_reduce(range,&body) );
+00218 #else
+00219                 // Bound context prevents exceptions from body to affect nesting or sibling algorithms,
+00220                 // and allows users to handle exceptions safely by wrapping parallel_for in the try-block.
+00221                 task_group_context context;
+00222                 task::spawn_root_and_wait( *new(task::allocate_root(context)) start_deterministic_reduce(range,body) );
+00223 #endif /* __TBB_TASK_GROUP_CONTEXT && !TBB_JOIN_OUTER_TASK_GROUP */
+00224             }
+00225         }
+00226 #if __TBB_TASK_GROUP_CONTEXT
+00227         static void run( const Range& range, Body& body, task_group_context& context ) {
+00228             if( !range.empty() )
+00229                 task::spawn_root_and_wait( *new(task::allocate_root(context)) start_deterministic_reduce(range,body) );
+00230         }
+00231 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00232     };
+00233 
+00234     template<typename Range, typename Body>
+00235     task* start_deterministic_reduce<Range,Body>::execute() {
+00236         if( !my_range.is_divisible() ) {
+00237             my_body( my_range );
+00238             return NULL;
+00239         } else {
+00240             finish_type& c = *new( allocate_continuation() ) finish_type( my_body );
+00241             recycle_as_child_of(c);
+00242             c.set_ref_count(2);
+00243             start_deterministic_reduce& b = *new( c.allocate_child() ) start_deterministic_reduce( *this, c );
+00244             task::spawn(b);
+00245             return this;
+00246         }
+00247     }
+00248 #endif /* TBB_PREVIEW_DETERMINISTIC_REDUCE */
+00249 } // namespace internal
+00251 } //namespace interfaceX
+00252 
+00254 namespace internal {
+00255     using interface6::internal::start_reduce;
+00256 #if TBB_PREVIEW_DETERMINISTIC_REDUCE
+00257     using interface6::internal::start_deterministic_reduce;
+00258 #endif
+00260 
+00264     template<typename Range, typename Value, typename RealBody, typename Reduction>
+00265     class lambda_reduce_body {
+00266 
+00267 //FIXME: decide if my_real_body, my_reduction, and identity_element should be copied or referenced
+00268 //       (might require some performance measurements)
+00269 
+00270         const Value&     identity_element;
+00271         const RealBody&  my_real_body;
+00272         const Reduction& my_reduction;
+00273         Value            my_value;
+00274         lambda_reduce_body& operator= ( const lambda_reduce_body& other );
+00275     public:
+00276         lambda_reduce_body( const Value& identity, const RealBody& body, const Reduction& reduction )
+00277             : identity_element(identity)
+00278             , my_real_body(body)
+00279             , my_reduction(reduction)
+00280             , my_value(identity)
+00281         { }
+00282         lambda_reduce_body( const lambda_reduce_body& other )
+00283             : identity_element(other.identity_element)
+00284             , my_real_body(other.my_real_body)
+00285             , my_reduction(other.my_reduction)
+00286             , my_value(other.my_value)
+00287         { }
+00288         lambda_reduce_body( lambda_reduce_body& other, tbb::split )
+00289             : identity_element(other.identity_element)
+00290             , my_real_body(other.my_real_body)
+00291             , my_reduction(other.my_reduction)
+00292             , my_value(other.identity_element)
+00293         { }
+00294         void operator()(Range& range) {
+00295             my_value = my_real_body(range, const_cast<const Value&>(my_value));
+00296         }
+00297         void join( lambda_reduce_body& rhs ) {
+00298             my_value = my_reduction(const_cast<const Value&>(my_value), const_cast<const Value&>(rhs.my_value));
+00299         }
+00300         Value result() const {
+00301             return my_value;
+00302         }
+00303     };
+00304 
+00305 } // namespace internal
+00307 
+00308 // Requirements on Range concept are documented in blocked_range.h
+00309 
+00328 
+00330 
+00331 template<typename Range, typename Body>
+00332 void parallel_reduce( const Range& range, Body& body ) {
+00333     internal::start_reduce<Range,Body, const __TBB_DEFAULT_PARTITIONER>::run( range, body, __TBB_DEFAULT_PARTITIONER() );
+00334 }
+00335 
+00337 
+00338 template<typename Range, typename Body>
+00339 void parallel_reduce( const Range& range, Body& body, const simple_partitioner& partitioner ) {
+00340     internal::start_reduce<Range,Body,const simple_partitioner>::run( range, body, partitioner );
+00341 }
+00342 
+00344 
+00345 template<typename Range, typename Body>
+00346 void parallel_reduce( const Range& range, Body& body, const auto_partitioner& partitioner ) {
+00347     internal::start_reduce<Range,Body,const auto_partitioner>::run( range, body, partitioner );
+00348 }
+00349 
+00351 
+00352 template<typename Range, typename Body>
+00353 void parallel_reduce( const Range& range, Body& body, affinity_partitioner& partitioner ) {
+00354     internal::start_reduce<Range,Body,affinity_partitioner>::run( range, body, partitioner );
+00355 }
+00356 
+00357 #if __TBB_TASK_GROUP_CONTEXT
+00359 
+00360 template<typename Range, typename Body>
+00361 void parallel_reduce( const Range& range, Body& body, const simple_partitioner& partitioner, task_group_context& context ) {
+00362     internal::start_reduce<Range,Body,const simple_partitioner>::run( range, body, partitioner, context );
+00363 }
+00364 
+00366 
+00367 template<typename Range, typename Body>
+00368 void parallel_reduce( const Range& range, Body& body, const auto_partitioner& partitioner, task_group_context& context ) {
+00369     internal::start_reduce<Range,Body,const auto_partitioner>::run( range, body, partitioner, context );
+00370 }
+00371 
+00373 
+00374 template<typename Range, typename Body>
+00375 void parallel_reduce( const Range& range, Body& body, affinity_partitioner& partitioner, task_group_context& context ) {
+00376     internal::start_reduce<Range,Body,affinity_partitioner>::run( range, body, partitioner, context );
+00377 }
+00378 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00379 
+00383 
+00384 
+00385 template<typename Range, typename Value, typename RealBody, typename Reduction>
+00386 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction ) {
+00387     internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
+00388     internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,const __TBB_DEFAULT_PARTITIONER>
+00389                           ::run(range, body, __TBB_DEFAULT_PARTITIONER() );
+00390     return body.result();
+00391 }
+00392 
+00394 
+00395 template<typename Range, typename Value, typename RealBody, typename Reduction>
+00396 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
+00397                        const simple_partitioner& partitioner ) {
+00398     internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
+00399     internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,const simple_partitioner>
+00400                           ::run(range, body, partitioner );
+00401     return body.result();
+00402 }
+00403 
+00405 
+00406 template<typename Range, typename Value, typename RealBody, typename Reduction>
+00407 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
+00408                        const auto_partitioner& partitioner ) {
+00409     internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
+00410     internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,const auto_partitioner>
+00411                           ::run( range, body, partitioner );
+00412     return body.result();
+00413 }
+00414 
+00416 
+00417 template<typename Range, typename Value, typename RealBody, typename Reduction>
+00418 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
+00419                        affinity_partitioner& partitioner ) {
+00420     internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
+00421     internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,affinity_partitioner>
+00422                                         ::run( range, body, partitioner );
+00423     return body.result();
+00424 }
+00425 
+00426 #if __TBB_TASK_GROUP_CONTEXT
+00428 
+00429 template<typename Range, typename Value, typename RealBody, typename Reduction>
+00430 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
+00431                        const simple_partitioner& partitioner, task_group_context& context ) {
+00432     internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
+00433     internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,const simple_partitioner>
+00434                           ::run( range, body, partitioner, context );
+00435     return body.result();
+00436 }
+00437 
+00439 
+00440 template<typename Range, typename Value, typename RealBody, typename Reduction>
+00441 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
+00442                        const auto_partitioner& partitioner, task_group_context& context ) {
+00443     internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
+00444     internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,const auto_partitioner>
+00445                           ::run( range, body, partitioner, context );
+00446     return body.result();
+00447 }
+00448 
+00450 
+00451 template<typename Range, typename Value, typename RealBody, typename Reduction>
+00452 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
+00453                        affinity_partitioner& partitioner, task_group_context& context ) {
+00454     internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
+00455     internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,affinity_partitioner>
+00456                                         ::run( range, body, partitioner, context );
+00457     return body.result();
+00458 }
+00459 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00460 
+00461 #if TBB_PREVIEW_DETERMINISTIC_REDUCE
+00463 
+00464 template<typename Range, typename Body>
+00465 void parallel_deterministic_reduce( const Range& range, Body& body ) {
+00466     internal::start_deterministic_reduce<Range,Body>::run( range, body );
+00467 }
+00468 
+00469 #if __TBB_TASK_GROUP_CONTEXT
+00471 
+00472 template<typename Range, typename Body>
+00473 void parallel_deterministic_reduce( const Range& range, Body& body, task_group_context& context ) {
+00474     internal::start_deterministic_reduce<Range,Body>::run( range, body, context );
+00475 }
+00476 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00477 
+00481 
+00482 
+00483 template<typename Range, typename Value, typename RealBody, typename Reduction>
+00484 Value parallel_deterministic_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction ) {
+00485     internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
+00486     internal::start_deterministic_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction> >
+00487                           ::run(range, body);
+00488     return body.result();
+00489 }
+00490 
+00491 #if __TBB_TASK_GROUP_CONTEXT
+00493 
+00494 template<typename Range, typename Value, typename RealBody, typename Reduction>
+00495 Value parallel_deterministic_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
+00496                        task_group_context& context ) {
+00497     internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
+00498     internal::start_deterministic_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction> >
+00499                           ::run( range, body, context );
+00500     return body.result();
+00501 }
+00502 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00503 #endif /* TBB_PREVIEW_DETERMINISTIC_REDUCE */
+00504 
+00505 
+00506 } // namespace tbb
+00507 
+00508 #endif /* __TBB_parallel_reduce_H */
+00509 
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00562.html b/src/tbb/doc/html/a00562.html new file mode 100644 index 0000000..bc3407f --- /dev/null +++ b/src/tbb/doc/html/a00562.html @@ -0,0 +1,341 @@ + + +parallel_scan.h Source File + + + + + + +

parallel_scan.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_parallel_scan_H
+00022 #define __TBB_parallel_scan_H
+00023 
+00024 #include "task.h"
+00025 #include "aligned_space.h"
+00026 #include <new>
+00027 #include "partitioner.h"
+00028 
+00029 namespace tbb {
+00030 
+00032 
+00033 struct pre_scan_tag {
+00034     static bool is_final_scan() {return false;}
+00035 };
+00036 
+00038 
+00039 struct final_scan_tag {
+00040     static bool is_final_scan() {return true;}
+00041 };
+00042 
+00044 namespace internal {
+00045 
+00047 
+00048     template<typename Range, typename Body>
+00049     class final_sum: public task {
+00050     public:
+00051         Body body;
+00052     private:
+00053         aligned_space<Range,1> range;
+00055         Body* stuff_last;
+00056     public:
+00057         final_sum( Body& body_ ) :
+00058             body(body_,split())
+00059         {
+00060             poison_pointer(stuff_last);
+00061         }
+00062         ~final_sum() {
+00063             range.begin()->~Range();
+00064         }     
+00065         void finish_construction( const Range& range_, Body* stuff_last_ ) {
+00066             new( range.begin() ) Range(range_);
+00067             stuff_last = stuff_last_;
+00068         }
+00069     private:
+00070         /*override*/ task* execute() {
+00071             body( *range.begin(), final_scan_tag() );
+00072             if( stuff_last )
+00073                 stuff_last->assign(body);
+00074             return NULL;
+00075         }
+00076     };       
+00077 
+00079 
+00080     template<typename Range, typename Body>
+00081     class sum_node: public task {
+00082         typedef final_sum<Range,Body> final_sum_type;
+00083     public:
+00084         final_sum_type *incoming; 
+00085         final_sum_type *body;
+00086         Body *stuff_last;
+00087     private:
+00088         final_sum_type *left_sum;
+00089         sum_node *left;
+00090         sum_node *right;     
+00091         bool left_is_final;
+00092         Range range;
+00093         sum_node( const Range range_, bool left_is_final_ ) : 
+00094             left_sum(NULL), 
+00095             left(NULL), 
+00096             right(NULL), 
+00097             left_is_final(left_is_final_), 
+00098             range(range_)
+00099         {
+00100             // Poison fields that will be set by second pass.
+00101             poison_pointer(body);
+00102             poison_pointer(incoming);
+00103         }
+00104         task* create_child( const Range& range_, final_sum_type& f, sum_node* n, final_sum_type* incoming_, Body* stuff_last_ ) {
+00105             if( !n ) {
+00106                 f.recycle_as_child_of( *this );
+00107                 f.finish_construction( range_, stuff_last_ );
+00108                 return &f;
+00109             } else {
+00110                 n->body = &f;
+00111                 n->incoming = incoming_;
+00112                 n->stuff_last = stuff_last_;
+00113                 return n;
+00114             }
+00115         }
+00116         /*override*/ task* execute() {
+00117             if( body ) {
+00118                 if( incoming )
+00119                     left_sum->body.reverse_join( incoming->body );
+00120                 recycle_as_continuation();
+00121                 sum_node& c = *this;
+00122                 task* b = c.create_child(Range(range,split()),*left_sum,right,left_sum,stuff_last);
+00123                 task* a = left_is_final ? NULL : c.create_child(range,*body,left,incoming,NULL);
+00124                 set_ref_count( (a!=NULL)+(b!=NULL) );
+00125                 body = NULL; 
+00126                 if( a ) spawn(*b);
+00127                 else a = b;
+00128                 return a;
+00129             } else {
+00130                 return NULL;
+00131             }
+00132         }
+00133         template<typename Range_,typename Body_,typename Partitioner_>
+00134         friend class start_scan;
+00135 
+00136         template<typename Range_,typename Body_>
+00137         friend class finish_scan;
+00138     };
+00139 
+00141 
+00142     template<typename Range, typename Body>
+00143     class finish_scan: public task {
+00144         typedef sum_node<Range,Body> sum_node_type;
+00145         typedef final_sum<Range,Body> final_sum_type;
+00146         final_sum_type** const sum;
+00147         sum_node_type*& return_slot;
+00148     public:
+00149         final_sum_type* right_zombie;
+00150         sum_node_type& result;
+00151 
+00152         /*override*/ task* execute() {
+00153             __TBB_ASSERT( result.ref_count()==(result.left!=NULL)+(result.right!=NULL), NULL );
+00154             if( result.left )
+00155                 result.left_is_final = false;
+00156             if( right_zombie && sum ) 
+00157                 ((*sum)->body).reverse_join(result.left_sum->body);
+00158             __TBB_ASSERT( !return_slot, NULL );
+00159             if( right_zombie || result.right ) {
+00160                 return_slot = &result;
+00161             } else {
+00162                 destroy( result );
+00163             }
+00164             if( right_zombie && !sum && !result.right ) destroy(*right_zombie);
+00165             return NULL;
+00166         }
+00167 
+00168         finish_scan( sum_node_type*& return_slot_, final_sum_type** sum_, sum_node_type& result_ ) : 
+00169             sum(sum_),
+00170             return_slot(return_slot_), 
+00171             right_zombie(NULL),
+00172             result(result_)
+00173         {
+00174             __TBB_ASSERT( !return_slot, NULL );
+00175         }
+00176     };
+00177 
+00179 
+00180     template<typename Range, typename Body, typename Partitioner=simple_partitioner>
+00181     class start_scan: public task {
+00182         typedef sum_node<Range,Body> sum_node_type;
+00183         typedef final_sum<Range,Body> final_sum_type;
+00184         final_sum_type* body;
+00186         final_sum_type** sum; 
+00187         sum_node_type** return_slot;
+00189         sum_node_type* parent_sum;
+00190         bool is_final;
+00191         bool is_right_child;
+00192         Range range;
+00193         typename Partitioner::partition_type partition;
+00194         /*override*/ task* execute();
+00195     public:
+00196         start_scan( sum_node_type*& return_slot_, start_scan& parent_, sum_node_type* parent_sum_ ) :
+00197             body(parent_.body),
+00198             sum(parent_.sum),
+00199             return_slot(&return_slot_),
+00200             parent_sum(parent_sum_),
+00201             is_final(parent_.is_final),
+00202             is_right_child(false),
+00203             range(parent_.range,split()),
+00204             partition(parent_.partition,split())
+00205         {
+00206             __TBB_ASSERT( !*return_slot, NULL );
+00207         }
+00208 
+00209         start_scan( sum_node_type*& return_slot_, const Range& range_, final_sum_type& body_, const Partitioner& partitioner_) :
+00210             body(&body_),
+00211             sum(NULL),
+00212             return_slot(&return_slot_),
+00213             parent_sum(NULL),
+00214             is_final(true),
+00215             is_right_child(false),
+00216             range(range_),
+00217             partition(partitioner_)
+00218         {
+00219             __TBB_ASSERT( !*return_slot, NULL );
+00220         }
+00221 
+00222         static void run( const Range& range_, Body& body_, const Partitioner& partitioner_ ) {
+00223             if( !range_.empty() ) {
+00224                 typedef internal::start_scan<Range,Body,Partitioner> start_pass1_type;
+00225                 internal::sum_node<Range,Body>* root = NULL;
+00226                 typedef internal::final_sum<Range,Body> final_sum_type;
+00227                 final_sum_type* temp_body = new(task::allocate_root()) final_sum_type( body_ );
+00228                 start_pass1_type& pass1 = *new(task::allocate_root()) start_pass1_type(
+00229                     /*return_slot=*/root,
+00230                     range_,
+00231                     *temp_body,
+00232                     partitioner_ );
+00233                 task::spawn_root_and_wait( pass1 );
+00234                 if( root ) {
+00235                     root->body = temp_body;
+00236                     root->incoming = NULL;
+00237                     root->stuff_last = &body_;
+00238                     task::spawn_root_and_wait( *root );
+00239                 } else {
+00240                     body_.assign(temp_body->body);
+00241                     temp_body->finish_construction( range_, NULL );
+00242                     temp_body->destroy(*temp_body);
+00243                 }
+00244             }
+00245         }
+00246     };
+00247 
+00248     template<typename Range, typename Body, typename Partitioner>
+00249     task* start_scan<Range,Body,Partitioner>::execute() {
+00250         typedef internal::finish_scan<Range,Body> finish_pass1_type;
+00251         finish_pass1_type* p = parent_sum ? static_cast<finish_pass1_type*>( parent() ) : NULL;
+00252         // Inspecting p->result.left_sum would ordinarily be a race condition.
+00253         // But we inspect it only if we are not a stolen task, in which case we
+00254         // know that task assigning to p->result.left_sum has completed.
+00255         bool treat_as_stolen = is_right_child && (is_stolen_task() || body!=p->result.left_sum);
+00256         if( treat_as_stolen ) {
+00257             // Invocation is for right child that has been really stolen or needs to be virtually stolen
+00258             p->right_zombie = body = new( allocate_root() ) final_sum_type(body->body);
+00259             is_final = false;
+00260         }
+00261         task* next_task = NULL;
+00262         if( (is_right_child && !treat_as_stolen) || !range.is_divisible() || partition.should_execute_range(*this) ) {
+00263             if( is_final )
+00264                 (body->body)( range, final_scan_tag() );
+00265             else if( sum )
+00266                 (body->body)( range, pre_scan_tag() );
+00267             if( sum ) 
+00268                 *sum = body;
+00269             __TBB_ASSERT( !*return_slot, NULL );
+00270         } else {
+00271             sum_node_type* result;
+00272             if( parent_sum ) 
+00273                 result = new(allocate_additional_child_of(*parent_sum)) sum_node_type(range,/*left_is_final=*/is_final);
+00274             else
+00275                 result = new(task::allocate_root()) sum_node_type(range,/*left_is_final=*/is_final);
+00276             finish_pass1_type& c = *new( allocate_continuation()) finish_pass1_type(*return_slot,sum,*result);
+00277             // Split off right child
+00278             start_scan& b = *new( c.allocate_child() ) start_scan( /*return_slot=*/result->right, *this, result );
+00279             b.is_right_child = true;    
+00280             // Left child is recycling of *this.  Must recycle this before spawning b, 
+00281             // otherwise b might complete and decrement c.ref_count() to zero, which
+00282             // would cause c.execute() to run prematurely.
+00283             recycle_as_child_of(c);
+00284             c.set_ref_count(2);
+00285             c.spawn(b);
+00286             sum = &result->left_sum;
+00287             return_slot = &result->left;
+00288             is_right_child = false;
+00289             next_task = this;
+00290             parent_sum = result; 
+00291             __TBB_ASSERT( !*return_slot, NULL );
+00292         }
+00293         return next_task;
+00294     } 
+00295 } // namespace internal
+00297 
+00298 // Requirements on Range concept are documented in blocked_range.h
+00299 
+00317 
+00319 
+00320 template<typename Range, typename Body>
+00321 void parallel_scan( const Range& range, Body& body ) {
+00322     internal::start_scan<Range,Body,__TBB_DEFAULT_PARTITIONER>::run(range,body,__TBB_DEFAULT_PARTITIONER());
+00323 }
+00324 
+00326 
+00327 template<typename Range, typename Body>
+00328 void parallel_scan( const Range& range, Body& body, const simple_partitioner& partitioner ) {
+00329     internal::start_scan<Range,Body,simple_partitioner>::run(range,body,partitioner);
+00330 }
+00331 
+00333 
+00334 template<typename Range, typename Body>
+00335 void parallel_scan( const Range& range, Body& body, const auto_partitioner& partitioner ) {
+00336     internal::start_scan<Range,Body,auto_partitioner>::run(range,body,partitioner);
+00337 }
+00339 
+00340 } // namespace tbb
+00341 
+00342 #endif /* __TBB_parallel_scan_H */
+00343 
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00567.html b/src/tbb/doc/html/a00567.html new file mode 100644 index 0000000..70fffb3 --- /dev/null +++ b/src/tbb/doc/html/a00567.html @@ -0,0 +1,229 @@ + + +parallel_sort.h Source File + + + + + + +

parallel_sort.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_parallel_sort_H
+00022 #define __TBB_parallel_sort_H
+00023 
+00024 #include "parallel_for.h"
+00025 #include "blocked_range.h"
+00026 #include <algorithm>
+00027 #include <iterator>
+00028 #include <functional>
+00029 
+00030 namespace tbb {
+00031 
+00033 namespace internal {
+00034 
+00036 
+00039 template<typename RandomAccessIterator, typename Compare>
+00040 class quick_sort_range: private no_assign {
+00041 
+00042     inline size_t median_of_three(const RandomAccessIterator &array, size_t l, size_t m, size_t r) const {
+00043         return comp(array[l], array[m]) ? ( comp(array[m], array[r]) ? m : ( comp( array[l], array[r]) ? r : l ) ) 
+00044                                         : ( comp(array[r], array[m]) ? m : ( comp( array[r], array[l] ) ? r : l ) );
+00045     }
+00046 
+00047     inline size_t pseudo_median_of_nine( const RandomAccessIterator &array, const quick_sort_range &range ) const {
+00048         size_t offset = range.size/8u;
+00049         return median_of_three(array, 
+00050                                median_of_three(array, 0, offset, offset*2),
+00051                                median_of_three(array, offset*3, offset*4, offset*5),
+00052                                median_of_three(array, offset*6, offset*7, range.size - 1) );
+00053 
+00054     }
+00055 
+00056 public:
+00057 
+00058     static const size_t grainsize = 500;
+00059     const Compare &comp;
+00060     RandomAccessIterator begin;
+00061     size_t size;
+00062 
+00063     quick_sort_range( RandomAccessIterator begin_, size_t size_, const Compare &comp_ ) :
+00064         comp(comp_), begin(begin_), size(size_) {}
+00065 
+00066     bool empty() const {return size==0;}
+00067     bool is_divisible() const {return size>=grainsize;}
+00068 
+00069     quick_sort_range( quick_sort_range& range, split ) : comp(range.comp) {
+00070         RandomAccessIterator array = range.begin;
+00071         RandomAccessIterator key0 = range.begin; 
+00072         size_t m = pseudo_median_of_nine(array, range);
+00073         if (m) std::swap ( array[0], array[m] );
+00074 
+00075         size_t i=0;
+00076         size_t j=range.size;
+00077         // Partition interval [i+1,j-1] with key *key0.
+00078         for(;;) {
+00079             __TBB_ASSERT( i<j, NULL );
+00080             // Loop must terminate since array[l]==*key0.
+00081             do {
+00082                 --j;
+00083                 __TBB_ASSERT( i<=j, "bad ordering relation?" );
+00084             } while( comp( *key0, array[j] ));
+00085             do {
+00086                 __TBB_ASSERT( i<=j, NULL );
+00087                 if( i==j ) goto partition;
+00088                 ++i;
+00089             } while( comp( array[i],*key0 ));
+00090             if( i==j ) goto partition;
+00091             std::swap( array[i], array[j] );
+00092         }
+00093 partition:
+00094         // Put the partition key were it belongs
+00095         std::swap( array[j], *key0 );
+00096         // array[l..j) is less or equal to key.
+00097         // array(j..r) is greater or equal to key.
+00098         // array[j] is equal to key
+00099         i=j+1;
+00100         begin = array+i;
+00101         size = range.size-i;
+00102         range.size = j;
+00103     }
+00104 };
+00105 
+00106 #if __TBB_TASK_GROUP_CONTEXT
+00108 
+00109 template<typename RandomAccessIterator, typename Compare>
+00110 class quick_sort_pretest_body : internal::no_assign {
+00111     const Compare &comp;
+00112 
+00113 public:
+00114     quick_sort_pretest_body(const Compare &_comp) : comp(_comp) {}
+00115 
+00116     void operator()( const blocked_range<RandomAccessIterator>& range ) const {
+00117         task &my_task = task::self();
+00118         RandomAccessIterator my_end = range.end();
+00119 
+00120         int i = 0;
+00121         for (RandomAccessIterator k = range.begin(); k != my_end; ++k, ++i) {
+00122             if ( i%64 == 0 && my_task.is_cancelled() ) break;
+00123           
+00124             // The k-1 is never out-of-range because the first chunk starts at begin+serial_cutoff+1
+00125             if ( comp( *(k), *(k-1) ) ) {
+00126                 my_task.cancel_group_execution();
+00127                 break;
+00128             }
+00129         }
+00130     }
+00131 
+00132 };
+00133 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00134 
+00136 
+00137 template<typename RandomAccessIterator, typename Compare>
+00138 struct quick_sort_body {
+00139     void operator()( const quick_sort_range<RandomAccessIterator,Compare>& range ) const {
+00140         //SerialQuickSort( range.begin, range.size, range.comp );
+00141         std::sort( range.begin, range.begin + range.size, range.comp );
+00142     }
+00143 };
+00144 
+00146 
+00147 template<typename RandomAccessIterator, typename Compare>
+00148 void parallel_quick_sort( RandomAccessIterator begin, RandomAccessIterator end, const Compare& comp ) {
+00149 #if __TBB_TASK_GROUP_CONTEXT
+00150     task_group_context my_context;
+00151     const int serial_cutoff = 9;
+00152 
+00153     __TBB_ASSERT( begin + serial_cutoff < end, "min_parallel_size is smaller than serial cutoff?" );
+00154     RandomAccessIterator k;
+00155     for ( k = begin ; k != begin + serial_cutoff; ++k ) {
+00156         if ( comp( *(k+1), *k ) ) {
+00157             goto do_parallel_quick_sort;
+00158         }
+00159     }
+00160 
+00161     parallel_for( blocked_range<RandomAccessIterator>(k+1, end),
+00162                   quick_sort_pretest_body<RandomAccessIterator,Compare>(comp),
+00163                   auto_partitioner(),
+00164                   my_context);
+00165 
+00166     if (my_context.is_group_execution_cancelled())
+00167 do_parallel_quick_sort:
+00168 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00169         parallel_for( quick_sort_range<RandomAccessIterator,Compare>(begin, end-begin, comp ), 
+00170                       quick_sort_body<RandomAccessIterator,Compare>(),
+00171                       auto_partitioner() );
+00172 }
+00173 
+00174 } // namespace internal
+00176 
+00187 
+00189 
+00192 template<typename RandomAccessIterator, typename Compare>
+00193 void parallel_sort( RandomAccessIterator begin, RandomAccessIterator end, const Compare& comp) { 
+00194     const int min_parallel_size = 500; 
+00195     if( end > begin ) {
+00196         if (end - begin < min_parallel_size) { 
+00197             std::sort(begin, end, comp);
+00198         } else {
+00199             internal::parallel_quick_sort(begin, end, comp);
+00200         }
+00201     }
+00202 }
+00203 
+00205 
+00206 template<typename RandomAccessIterator>
+00207 inline void parallel_sort( RandomAccessIterator begin, RandomAccessIterator end ) { 
+00208     parallel_sort( begin, end, std::less< typename std::iterator_traits<RandomAccessIterator>::value_type >() );
+00209 }
+00210 
+00212 
+00213 template<typename T>
+00214 inline void parallel_sort( T * begin, T * end ) {
+00215     parallel_sort( begin, end, std::less< T >() );
+00216 }   
+00218 
+00219 
+00220 } // namespace tbb
+00221 
+00222 #endif
+00223 
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00571.html b/src/tbb/doc/html/a00571.html new file mode 100644 index 0000000..7918b93 --- /dev/null +++ b/src/tbb/doc/html/a00571.html @@ -0,0 +1,196 @@ + + +parallel_while.h Source File + + + + + + +

parallel_while.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_parallel_while
+00022 #define __TBB_parallel_while
+00023 
+00024 #include "task.h"
+00025 #include <new>
+00026 
+00027 namespace tbb {
+00028 
+00029 template<typename Body>
+00030 class parallel_while;
+00031 
+00033 namespace internal {
+00034 
+00035     template<typename Stream, typename Body> class while_task;
+00036 
+00038 
+00040     template<typename Body>
+00041     class while_iteration_task: public task {
+00042         const Body& my_body;
+00043         typename Body::argument_type my_value;
+00044         /*override*/ task* execute() {
+00045             my_body(my_value); 
+00046             return NULL;
+00047         }
+00048         while_iteration_task( const typename Body::argument_type& value, const Body& body ) : 
+00049             my_body(body), my_value(value)
+00050         {}
+00051         template<typename Body_> friend class while_group_task;
+00052         friend class tbb::parallel_while<Body>;
+00053     };
+00054 
+00056 
+00058     template<typename Body>
+00059     class while_group_task: public task {
+00060         static const size_t max_arg_size = 4;         
+00061         const Body& my_body;
+00062         size_t size;
+00063         typename Body::argument_type my_arg[max_arg_size];
+00064         while_group_task( const Body& body ) : my_body(body), size(0) {} 
+00065         /*override*/ task* execute() {
+00066             typedef while_iteration_task<Body> iteration_type;
+00067             __TBB_ASSERT( size>0, NULL );
+00068             task_list list;
+00069             task* t; 
+00070             size_t k=0; 
+00071             for(;;) {
+00072                 t = new( allocate_child() ) iteration_type(my_arg[k],my_body); 
+00073                 if( ++k==size ) break;
+00074                 list.push_back(*t);
+00075             }
+00076             set_ref_count(int(k+1));
+00077             spawn(list);
+00078             spawn_and_wait_for_all(*t);
+00079             return NULL;
+00080         }
+00081         template<typename Stream, typename Body_> friend class while_task;
+00082     };
+00083     
+00085 
+00087     template<typename Stream, typename Body>
+00088     class while_task: public task {
+00089         Stream& my_stream;
+00090         const Body& my_body;
+00091         empty_task& my_barrier;
+00092         /*override*/ task* execute() {
+00093             typedef while_group_task<Body> block_type;
+00094             block_type& t = *new( allocate_additional_child_of(my_barrier) ) block_type(my_body);
+00095             size_t k=0; 
+00096             while( my_stream.pop_if_present(t.my_arg[k]) ) {
+00097                 if( ++k==block_type::max_arg_size ) {
+00098                     // There might be more iterations.
+00099                     recycle_to_reexecute();
+00100                     break;
+00101                 }
+00102             }
+00103             if( k==0 ) {
+00104                 destroy(t);
+00105                 return NULL;
+00106             } else {
+00107                 t.size = k;
+00108                 return &t;
+00109             }
+00110         }
+00111         while_task( Stream& stream, const Body& body, empty_task& barrier ) : 
+00112             my_stream(stream),
+00113             my_body(body),
+00114             my_barrier(barrier)
+00115         {} 
+00116         friend class tbb::parallel_while<Body>;
+00117     };
+00118 
+00119 } // namespace internal
+00121 
+00123 
+00128 template<typename Body>
+00129 class parallel_while: internal::no_copy {
+00130 public:
+00132     parallel_while() : my_body(NULL), my_barrier(NULL) {}
+00133 
+00135     ~parallel_while() {
+00136         if( my_barrier ) {
+00137             my_barrier->destroy(*my_barrier);    
+00138             my_barrier = NULL;
+00139         }
+00140     }
+00141 
+00143     typedef typename Body::argument_type value_type;
+00144 
+00146 
+00149     template<typename Stream>
+00150     void run( Stream& stream, const Body& body );
+00151 
+00153 
+00154     void add( const value_type& item );
+00155 
+00156 private:
+00157     const Body* my_body;
+00158     empty_task* my_barrier;
+00159 };
+00160 
+00161 template<typename Body>
+00162 template<typename Stream>
+00163 void parallel_while<Body>::run( Stream& stream, const Body& body ) {
+00164     using namespace internal;
+00165     empty_task& barrier = *new( task::allocate_root() ) empty_task();
+00166     my_body = &body;
+00167     my_barrier = &barrier;
+00168     my_barrier->set_ref_count(2);
+00169     while_task<Stream,Body>& w = *new( my_barrier->allocate_child() ) while_task<Stream,Body>( stream, body, barrier );
+00170     my_barrier->spawn_and_wait_for_all(w);
+00171     my_barrier->destroy(*my_barrier);
+00172     my_barrier = NULL;
+00173     my_body = NULL;
+00174 }
+00175 
+00176 template<typename Body>
+00177 void parallel_while<Body>::add( const value_type& item ) {
+00178     __TBB_ASSERT(my_barrier,"attempt to add to parallel_while that is not running");
+00179     typedef internal::while_iteration_task<Body> iteration_type;
+00180     iteration_type& i = *new( task::allocate_additional_child_of(*my_barrier) ) iteration_type(item,*my_body);
+00181     task::self().spawn( i );
+00182 }
+00183 
+00184 } // namespace 
+00185 
+00186 #endif /* __TBB_parallel_while */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00575.html b/src/tbb/doc/html/a00575.html new file mode 100644 index 0000000..7b9bbe9 --- /dev/null +++ b/src/tbb/doc/html/a00575.html @@ -0,0 +1,500 @@ + + +partitioner.h Source File + + + + + + +

partitioner.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_partitioner_H
+00022 #define __TBB_partitioner_H
+00023 
+00024 #ifndef __TBB_INITIAL_CHUNKS
+00025 #define __TBB_INITIAL_CHUNKS 2
+00026 #endif
+00027 #ifndef __TBB_RANGE_POOL_CAPACITY
+00028 #define __TBB_RANGE_POOL_CAPACITY 8
+00029 #endif
+00030 #ifndef __TBB_INIT_DEPTH
+00031 #define __TBB_INIT_DEPTH 5
+00032 #endif
+00033 
+00034 #include "task.h"
+00035 #include "aligned_space.h"
+00036 #include "atomic.h"
+00037 
+00038 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
+00039     // Workaround for overzealous compiler warnings
+00040     #pragma warning (push)
+00041     #pragma warning (disable: 4244)
+00042 #endif
+00043 
+00044 namespace tbb {
+00045 
+00046 class auto_partitioner;
+00047 class simple_partitioner;
+00048 class affinity_partitioner;
+00049 namespace interface6 {
+00050     namespace internal {
+00051         class affinity_partition_type;
+00052     }
+00053 }
+00054 
+00055 namespace internal {
+00056 size_t __TBB_EXPORTED_FUNC get_initial_auto_partitioner_divisor();
+00057 
+00059 class affinity_partitioner_base_v3: no_copy {
+00060     friend class tbb::affinity_partitioner;
+00061     friend class tbb::interface6::internal::affinity_partition_type;
+00063 
+00064     affinity_id* my_array;
+00066     size_t my_size;
+00068     affinity_partitioner_base_v3() : my_array(NULL), my_size(0) {}
+00070     ~affinity_partitioner_base_v3() {resize(0);}
+00072 
+00073     void __TBB_EXPORTED_METHOD resize( unsigned factor );
+00074 };
+00075 
+00077 class partition_type_base {
+00078 public:
+00079     void set_affinity( task & ) {}
+00080     void note_affinity( task::affinity_id ) {}
+00081     task* continue_after_execute_range() {return NULL;}
+00082     bool decide_whether_to_delay() {return false;}
+00083     void spawn_or_delay( bool, task& b ) {
+00084         task::spawn(b);
+00085     }
+00086 };
+00087 
+00088 template<typename Range, typename Body, typename Partitioner> class start_scan;
+00089 
+00090 } // namespace internal
+00092 
+00093 namespace serial {
+00094 namespace interface6 {
+00095 template<typename Range, typename Body, typename Partitioner> class start_for;
+00096 }
+00097 }
+00098 
+00099 namespace interface6 {
+00101 namespace internal {
+00102 using namespace tbb::internal;
+00103 template<typename Range, typename Body, typename Partitioner> class start_for;
+00104 template<typename Range, typename Body, typename Partitioner> class start_reduce;
+00105 
+00107 class flag_task: public task {
+00108 public:
+00109     tbb::atomic<bool> child_stolen;
+00110     flag_task() { child_stolen = false; }
+00111     task* execute() { return NULL; }
+00112 };
+00113 
+00115 class signal_task: public task {
+00116 public:
+00117     task* execute() {
+00118         if( is_stolen_task() ) {
+00119             static_cast<flag_task*>(parent())->child_stolen = true;
+00120         }
+00121         return NULL;
+00122     }
+00123 };
+00124 
+00128 typedef unsigned char depth_t;
+00129 
+00131 template <typename T, depth_t MaxCapacity>
+00132 class range_vector {
+00133     depth_t my_head;
+00134     depth_t my_tail;
+00135     depth_t my_size;
+00136     depth_t my_depth[MaxCapacity]; // relative depths of stored ranges
+00137     tbb::aligned_space<T, MaxCapacity> my_pool;
+00138 
+00139 public:
+00141     range_vector(const T& elem) : my_head(0), my_tail(0), my_size(1) {
+00142         my_depth[0] = 0;
+00143         new( my_pool.begin() ) T(elem);//TODO: std::move?
+00144     }
+00145     ~range_vector() {
+00146         while( !empty() ) pop_back();
+00147     }
+00148     bool empty() const { return my_size == 0; }
+00149     depth_t size() const { return my_size; }
+00152     void split_to_fill(depth_t max_depth) {
+00153         while( my_size < MaxCapacity && my_depth[my_head] < max_depth
+00154           && my_pool.begin()[my_head].is_divisible() ) {
+00155             depth_t prev = my_head;
+00156             my_head = (my_head + 1) % MaxCapacity;
+00157             new(my_pool.begin()+my_head) T(my_pool.begin()[prev]); // copy TODO: std::move?
+00158             my_pool.begin()[prev].~T(); // instead of assignment
+00159             new(my_pool.begin()+prev) T(my_pool.begin()[my_head], split()); // do 'inverse' split
+00160             my_depth[my_head] = ++my_depth[prev];
+00161             my_size++;
+00162         }
+00163     }
+00164     void pop_back() {
+00165         __TBB_ASSERT(my_size > 0, "range_vector::pop_back() with empty size");
+00166         my_pool.begin()[my_head].~T();
+00167         my_size--;
+00168         my_head = (my_head + MaxCapacity - 1) % MaxCapacity;
+00169     }
+00170     void pop_front() {
+00171         __TBB_ASSERT(my_size > 0, "range_vector::pop_front() with empty size");
+00172         my_pool.begin()[my_tail].~T();
+00173         my_size--;
+00174         my_tail = (my_tail + 1) % MaxCapacity;
+00175     }
+00176     T& back() {
+00177         __TBB_ASSERT(my_size > 0, "range_vector::back() with empty size");
+00178         return my_pool.begin()[my_head];
+00179     }
+00180     T& front() {
+00181         __TBB_ASSERT(my_size > 0, "range_vector::front() with empty size");
+00182         return my_pool.begin()[my_tail];
+00183     }
+00185     depth_t front_depth() {
+00186         __TBB_ASSERT(my_size > 0, "range_vector::front_depth() with empty size");
+00187         return my_depth[my_tail];
+00188     }
+00189 };
+00190 
+00192 template <typename Partition>
+00193 struct partition_type_base {
+00194     // decision makers
+00195     void set_affinity( task & ) {}
+00196     void note_affinity( task::affinity_id ) {}
+00197     bool check_being_stolen(task &) { return false; } // part of old should_execute_range()
+00198     bool check_for_demand(task &) { return false; }
+00199     bool divisions_left() { return true; } // part of old should_execute_range()
+00200     bool should_create_trap() { return false; }
+00201     depth_t max_depth() { return 0; }
+00202     void align_depth(depth_t) { }
+00203     // common function blocks
+00204     Partition& derived() { return *static_cast<Partition*>(this); }
+00205     template<typename StartType>
+00206     flag_task* split_work(StartType &start) {
+00207         flag_task* parent_ptr = start.create_continuation(); // the type here is to express expectation
+00208         start.set_parent(parent_ptr);
+00209         parent_ptr->set_ref_count(2);
+00210         StartType& right_work = *new( parent_ptr->allocate_child() ) StartType(start, split());
+00211         start.spawn(right_work);
+00212         return parent_ptr;
+00213     }
+00214     template<typename StartType, typename Range>
+00215     void execute(StartType &start, Range &range) {
+00216         // The algorithm in a few words ([]-denotes calls to decision methods of partitioner):
+00217         // [If this task is stolen, adjust depth and divisions if necessary, set flag].
+00218         // If range is divisible {
+00219         //    Spread the work while [initial divisions left];
+00220         //    Create trap task [if necessary];
+00221         // }
+00222         // If not divisible or [max depth is reached], execute, else do the range pool part
+00223         task* parent_ptr = start.parent();
+00224         if( range.is_divisible() ) {
+00225             if( derived().divisions_left() )
+00226                 do parent_ptr = split_work(start); // split until divisions_left()
+00227                 while( range.is_divisible() && derived().divisions_left() );
+00228             if( derived().should_create_trap() ) { // only for range pool
+00229                 if( parent_ptr->ref_count() > 1 ) { // create new parent if necessary
+00230                     parent_ptr = start.create_continuation();
+00231                     start.set_parent(parent_ptr);
+00232                 } else __TBB_ASSERT(parent_ptr->ref_count() == 1, NULL);
+00233                 parent_ptr->set_ref_count(2); // safe because parent has only one reference
+00234                 signal_task& right_signal = *new( parent_ptr->allocate_child() ) signal_task();
+00235                 start.spawn(right_signal); // pure signal is to avoid deep recursion in the end
+00236             }
+00237         }
+00238         if( !range.is_divisible() || !derived().max_depth() )
+00239             start.run_body( range ); // simple partitioner goes always here
+00240         else { // do range pool
+00241             internal::range_vector<Range, Partition::range_pool_size> range_pool(range);
+00242             do {
+00243                 range_pool.split_to_fill(derived().max_depth()); // fill range pool
+00244                 if( derived().check_for_demand( start ) ) {
+00245                     if( range_pool.size() > 1 ) {
+00246                         parent_ptr = start.create_continuation();
+00247                         start.set_parent(parent_ptr);
+00248                         parent_ptr->set_ref_count(2);
+00249                         StartType& right_work = *new( parent_ptr->allocate_child() ) StartType(start, range_pool.front(), range_pool.front_depth());
+00250                         start.spawn(right_work);
+00251                         range_pool.pop_front();
+00252                         continue;
+00253                     }
+00254                     if( range_pool.back().is_divisible() ) // was not enough depth to fork a task
+00255                         continue; // note: check_for_demand() should guarantee increasing max_depth() next time
+00256                 }
+00257                 start.run_body( range_pool.back() );
+00258                 range_pool.pop_back();
+00259             } while( !range_pool.empty() && !start.is_cancelled() );
+00260         }
+00261     }
+00262 };
+00263 
+00265 template <typename Partition>
+00266 struct auto_partition_type_base : partition_type_base<Partition> {
+00267     size_t my_divisor;
+00268     depth_t my_max_depth;
+00269     auto_partition_type_base() : my_max_depth(__TBB_INIT_DEPTH) {
+00270         my_divisor = tbb::internal::get_initial_auto_partitioner_divisor()*__TBB_INITIAL_CHUNKS/4;
+00271         __TBB_ASSERT(my_divisor, "initial value of get_initial_auto_partitioner_divisor() is not valid");
+00272     }
+00273     auto_partition_type_base(auto_partition_type_base &src, split) {
+00274         my_max_depth = src.my_max_depth;
+00275 #if __TBB_INITIAL_TASK_IMBALANCE
+00276         if( src.my_divisor <= 1 ) my_divisor = 0;
+00277         else my_divisor = src.my_divisor = (src.my_divisor+1u) / 2u;
+00278 #else
+00279         my_divisor = src.my_divisor / 2u;
+00280         src.my_divisor = src.my_divisor - my_divisor; // TODO: check the effect separately
+00281         if(my_divisor) src.my_max_depth += static_cast<depth_t>(__TBB_Log2(src.my_divisor/my_divisor));
+00282 #endif
+00283     }
+00284     bool check_being_stolen( task &t) { // part of old should_execute_range()
+00285         if( !my_divisor ) {
+00286             my_divisor = 1; // todo: replace by on-stack flag (partition_state's member)?
+00287             if( t.is_stolen_task() ) {
+00288 #if TBB_USE_EXCEPTIONS
+00289                 // RTTI is available, check whether the cast is valid
+00290                 __TBB_ASSERT(dynamic_cast<flag_task*>(t.parent()), 0);
+00291                 // correctness of the cast relies on avoiding the root task for which:
+00292                 // - initial value of my_divisor != 0 (protected by separate assertion)
+00293                 // - is_stolen_task() always return false for the root task.
+00294 #endif
+00295                 static_cast<flag_task*>(t.parent())->child_stolen = true;
+00296                 my_max_depth++;
+00297                 return true;
+00298             }
+00299         }
+00300         return false;
+00301     }
+00302     bool divisions_left() { // part of old should_execute_range()
+00303         if( my_divisor > 1 ) return true;
+00304         if( my_divisor && my_max_depth > 1 ) { // can split the task and once more internally. TODO: on-stack flag instead
+00305             // keep same fragmentation while splitting for the local task pool
+00306             my_max_depth--;
+00307             my_divisor = 0;
+00308             return true;
+00309         } else return false;
+00310     }
+00311     bool should_create_trap() {
+00312         return my_divisor > 0;
+00313     }
+00314     bool check_for_demand(task &t) {
+00315         if( static_cast<flag_task*>(t.parent())->child_stolen ) {
+00316             my_max_depth++;
+00317             return true;
+00318         } else return false;
+00319     }
+00320     void align_depth(depth_t base) {
+00321         __TBB_ASSERT(base <= my_max_depth, 0);
+00322         my_max_depth -= base;
+00323     }
+00324     depth_t max_depth() { return my_max_depth; }
+00325 };
+00326 
+00328 class affinity_partition_type : public auto_partition_type_base<affinity_partition_type> {
+00329     static const unsigned factor_power = 4;
+00330     static const unsigned factor = 1<<factor_power;
+00331     bool my_delay;
+00332     unsigned map_begin, map_end, map_mid;
+00333     tbb::internal::affinity_id* my_array;
+00334     void set_mid() {
+00335         unsigned d = (map_end - map_begin)/2; // we could add 1 but it is rather for LIFO affinity
+00336         if( d > factor )
+00337             d &= 0u-factor;
+00338         map_mid = map_end - d;
+00339     }
+00340 public:
+00341     affinity_partition_type( tbb::internal::affinity_partitioner_base_v3& ap ) {
+00342         __TBB_ASSERT( (factor&(factor-1))==0, "factor must be power of two" );
+00343         ap.resize(factor);
+00344         my_array = ap.my_array;
+00345         map_begin = 0;
+00346         map_end = unsigned(ap.my_size);
+00347         set_mid();
+00348         my_delay = true;
+00349         my_divisor /= __TBB_INITIAL_CHUNKS; // let exactly P tasks to be distributed across workers
+00350         my_max_depth = factor_power+1; // the first factor_power ranges will be spawned, and >=1 ranges should be left
+00351         __TBB_ASSERT( my_max_depth < __TBB_RANGE_POOL_CAPACITY, 0 );
+00352     }
+00353     affinity_partition_type(affinity_partition_type& p, split)
+00354         : auto_partition_type_base<affinity_partition_type>(p, split()), my_array(p.my_array) {
+00355         __TBB_ASSERT( p.map_end-p.map_begin<factor || (p.map_end-p.map_begin)%factor==0, NULL );
+00356         map_end = p.map_end;
+00357         map_begin = p.map_end = p.map_mid;
+00358         set_mid(); p.set_mid();
+00359         my_delay = p.my_delay;
+00360     }
+00361     void set_affinity( task &t ) {
+00362         if( map_begin<map_end )
+00363             t.set_affinity( my_array[map_begin] );
+00364     }
+00365     void note_affinity( task::affinity_id id ) {
+00366         if( map_begin<map_end )
+00367             my_array[map_begin] = id;
+00368     }
+00369     bool check_for_demand( task &t ) {
+00370         if( !my_delay ) {
+00371             if( map_mid<map_end ) {
+00372                 __TBB_ASSERT(my_max_depth>__TBB_Log2(map_end-map_mid), 0);
+00373                 return true;// do not do my_max_depth++ here, but be sure my_max_depth is big enough
+00374             }
+00375             if( static_cast<flag_task*>(t.parent())->child_stolen ) {
+00376                 my_max_depth++;
+00377                 return true;
+00378             }
+00379         } else my_delay = false;
+00380         return false;
+00381     }
+00382     bool divisions_left() { // part of old should_execute_range()
+00383         return my_divisor > 1;
+00384     }
+00385     bool should_create_trap() {
+00386         return true; // TODO: rethink for the stage after memorizing level
+00387     }
+00388     static const unsigned range_pool_size = __TBB_RANGE_POOL_CAPACITY;
+00389 };
+00390 
+00391 class auto_partition_type: public auto_partition_type_base<auto_partition_type> {
+00392 public:
+00393     auto_partition_type( const auto_partitioner& ) {}
+00394     auto_partition_type( auto_partition_type& src, split)
+00395       : auto_partition_type_base<auto_partition_type>(src, split()) {}
+00396     static const unsigned range_pool_size = __TBB_RANGE_POOL_CAPACITY;
+00397 };
+00398 
+00399 class simple_partition_type: public partition_type_base<simple_partition_type> {
+00400 public:
+00401     simple_partition_type( const simple_partitioner& ) {}
+00402     simple_partition_type( const simple_partition_type&, split ) {}
+00404     template<typename StartType, typename Range>
+00405     void execute(StartType &start, Range &range) {
+00406         while( range.is_divisible() )
+00407             split_work( start );
+00408         start.run_body( range );
+00409     }
+00410     //static const unsigned range_pool_size = 1; - not necessary because execute() is overridden
+00411 };
+00412 
+00414 class old_auto_partition_type: public tbb::internal::partition_type_base {
+00415     size_t num_chunks;
+00416     static const size_t VICTIM_CHUNKS = 4;
+00417 public:
+00418     bool should_execute_range(const task &t) {
+00419         if( num_chunks<VICTIM_CHUNKS && t.is_stolen_task() )
+00420             num_chunks = VICTIM_CHUNKS;
+00421         return num_chunks==1;
+00422     }
+00423     old_auto_partition_type( const auto_partitioner& )
+00424       : num_chunks(internal::get_initial_auto_partitioner_divisor()*__TBB_INITIAL_CHUNKS/4) {}
+00425     old_auto_partition_type( const affinity_partitioner& )
+00426       : num_chunks(internal::get_initial_auto_partitioner_divisor()*__TBB_INITIAL_CHUNKS/4) {}
+00427     old_auto_partition_type( old_auto_partition_type& pt, split ) {
+00428         num_chunks = pt.num_chunks = (pt.num_chunks+1u) / 2u;
+00429     }
+00430 };
+00431 
+00432 } // namespace interfaceX::internal
+00434 } // namespace interfaceX
+00435 
+00437 
+00439 class simple_partitioner {
+00440 public:
+00441     simple_partitioner() {}
+00442 private:
+00443     template<typename Range, typename Body, typename Partitioner> friend class serial::interface6::start_for;
+00444     template<typename Range, typename Body, typename Partitioner> friend class interface6::internal::start_for;
+00445     template<typename Range, typename Body, typename Partitioner> friend class interface6::internal::start_reduce;
+00446     template<typename Range, typename Body, typename Partitioner> friend class internal::start_scan;
+00447     // backward compatibility
+00448     class partition_type: public internal::partition_type_base {
+00449     public:
+00450         bool should_execute_range(const task& ) {return false;}
+00451         partition_type( const simple_partitioner& ) {}
+00452         partition_type( const partition_type&, split ) {}
+00453     };
+00454     // new implementation just extends existing interface
+00455     typedef interface6::internal::simple_partition_type task_partition_type;
+00456 };
+00457 
+00459 
+00462 class auto_partitioner {
+00463 public:
+00464     auto_partitioner() {}
+00465 
+00466 private:
+00467     template<typename Range, typename Body, typename Partitioner> friend class serial::interface6::start_for;
+00468     template<typename Range, typename Body, typename Partitioner> friend class interface6::internal::start_for;
+00469     template<typename Range, typename Body, typename Partitioner> friend class interface6::internal::start_reduce;
+00470     template<typename Range, typename Body, typename Partitioner> friend class internal::start_scan;
+00471     // backward compatibility
+00472     typedef interface6::internal::old_auto_partition_type partition_type;
+00473     // new implementation just extends existing interface
+00474     typedef interface6::internal::auto_partition_type task_partition_type;
+00475 };
+00476 
+00478 class affinity_partitioner: internal::affinity_partitioner_base_v3 {
+00479 public:
+00480     affinity_partitioner() {}
+00481 
+00482 private:
+00483     template<typename Range, typename Body, typename Partitioner> friend class serial::interface6::start_for;
+00484     template<typename Range, typename Body, typename Partitioner> friend class interface6::internal::start_for;
+00485     template<typename Range, typename Body, typename Partitioner> friend class interface6::internal::start_reduce;
+00486     template<typename Range, typename Body, typename Partitioner> friend class internal::start_scan;
+00487     // backward compatibility - for parallel_scan only
+00488     typedef interface6::internal::old_auto_partition_type partition_type;
+00489     // new implementation just extends existing interface
+00490     typedef interface6::internal::affinity_partition_type task_partition_type;
+00491 };
+00492 
+00493 } // namespace tbb
+00494 
+00495 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
+00496     #pragma warning (pop)
+00497 #endif // warning 4244 is back
+00498 #undef __TBB_INITIAL_CHUNKS
+00499 #undef __TBB_RANGE_POOL_CAPACITY
+00500 #undef __TBB_INIT_DEPTH
+00501 #endif /* __TBB_partitioner_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00587.html b/src/tbb/doc/html/a00587.html new file mode 100644 index 0000000..afc137a --- /dev/null +++ b/src/tbb/doc/html/a00587.html @@ -0,0 +1,612 @@ + + +pipeline.h Source File + + + + + + +

pipeline.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_pipeline_H 
+00022 #define __TBB_pipeline_H 
+00023 
+00024 #include "atomic.h"
+00025 #include "task.h"
+00026 #include "tbb_allocator.h"
+00027 #include <cstddef>
+00028 
+00029 #if !TBB_IMPLEMENT_CPP0X
+00030 #include <type_traits>
+00031 #endif
+00032 
+00033 namespace tbb {
+00034 
+00035 class pipeline;
+00036 class filter;
+00037 
+00039 namespace internal {
+00040 
+00041 // The argument for PIPELINE_VERSION should be an integer between 2 and 9
+00042 #define __TBB_PIPELINE_VERSION(x) (unsigned char)(x-2)<<1
+00043 
+00044 typedef unsigned long Token;
+00045 typedef long tokendiff_t;
+00046 class stage_task;
+00047 class input_buffer;
+00048 class pipeline_root_task;
+00049 class pipeline_cleaner;
+00050 
+00051 } // namespace internal
+00052 
+00053 namespace interface6 {
+00054     template<typename T, typename U> class filter_t;
+00055 
+00056     namespace internal {
+00057         class pipeline_proxy;
+00058     }
+00059 }
+00060 
+00062 
+00064 
+00065 class filter: internal::no_copy {
+00066 private:
+00068     static filter* not_in_pipeline() {return reinterpret_cast<filter*>(intptr_t(-1));}
+00069 protected:    
+00071     static const unsigned char filter_is_serial = 0x1; 
+00072 
+00074 
+00076     static const unsigned char filter_is_out_of_order = 0x1<<4;  
+00077 
+00079     static const unsigned char filter_is_bound = 0x1<<5;  
+00080 
+00082     static const unsigned char filter_may_emit_null = 0x1<<6;
+00083 
+00085     static const unsigned char exact_exception_propagation =
+00086 #if TBB_USE_CAPTURED_EXCEPTION
+00087             0x0;
+00088 #else
+00089             0x1<<7;
+00090 #endif /* TBB_USE_CAPTURED_EXCEPTION */
+00091 
+00092     static const unsigned char current_version = __TBB_PIPELINE_VERSION(5);
+00093     static const unsigned char version_mask = 0x7<<1; // bits 1-3 are for version
+00094 public:
+00095     enum mode {
+00097         parallel = current_version | filter_is_out_of_order, 
+00099         serial_in_order = current_version | filter_is_serial,
+00101         serial_out_of_order = current_version | filter_is_serial | filter_is_out_of_order,
+00103         serial = serial_in_order
+00104     };
+00105 protected:
+00106     filter( bool is_serial_ ) : 
+00107         next_filter_in_pipeline(not_in_pipeline()),
+00108         my_input_buffer(NULL),
+00109         my_filter_mode(static_cast<unsigned char>((is_serial_ ? serial : parallel) | exact_exception_propagation)),
+00110         prev_filter_in_pipeline(not_in_pipeline()),
+00111         my_pipeline(NULL),
+00112         next_segment(NULL)
+00113     {}
+00114     
+00115     filter( mode filter_mode ) :
+00116         next_filter_in_pipeline(not_in_pipeline()),
+00117         my_input_buffer(NULL),
+00118         my_filter_mode(static_cast<unsigned char>(filter_mode | exact_exception_propagation)),
+00119         prev_filter_in_pipeline(not_in_pipeline()),
+00120         my_pipeline(NULL),
+00121         next_segment(NULL)
+00122     {}
+00123 
+00124     // signal end-of-input for concrete_filters
+00125     void __TBB_EXPORTED_METHOD set_end_of_input();
+00126 
+00127 public:
+00129     bool is_serial() const {
+00130         return bool( my_filter_mode & filter_is_serial );
+00131     }  
+00132     
+00134     bool is_ordered() const {
+00135         return (my_filter_mode & (filter_is_out_of_order|filter_is_serial))==filter_is_serial;
+00136     }
+00137 
+00139     bool is_bound() const {
+00140         return ( my_filter_mode & filter_is_bound )==filter_is_bound;
+00141     }
+00142 
+00144     bool object_may_be_null() { 
+00145         return ( my_filter_mode & filter_may_emit_null ) == filter_may_emit_null;
+00146     }
+00147 
+00149 
+00150     virtual void* operator()( void* item ) = 0;
+00151 
+00153 
+00154     virtual __TBB_EXPORTED_METHOD ~filter();
+00155 
+00156 #if __TBB_TASK_GROUP_CONTEXT
+00158 
+00160     virtual void finalize( void* /*item*/ ) {};
+00161 #endif
+00162 
+00163 private:
+00165     filter* next_filter_in_pipeline;
+00166 
+00168     //  (pipeline has not yet reached end_of_input or this filter has not yet
+00169     //  seen the last token produced by input_filter)
+00170     bool has_more_work();
+00171 
+00173 
+00174     internal::input_buffer* my_input_buffer;
+00175 
+00176     friend class internal::stage_task;
+00177     friend class internal::pipeline_root_task;
+00178     friend class pipeline;
+00179     friend class thread_bound_filter;
+00180 
+00182     const unsigned char my_filter_mode;
+00183 
+00185     filter* prev_filter_in_pipeline;
+00186 
+00188     pipeline* my_pipeline;
+00189 
+00191 
+00192     filter* next_segment;
+00193 };
+00194 
+00196 
+00197 class thread_bound_filter: public filter {
+00198 public:
+00199     enum result_type {
+00200         // item was processed
+00201         success,
+00202         // item is currently not available
+00203         item_not_available,
+00204         // there are no more items to process
+00205         end_of_stream
+00206     };
+00207 protected:
+00208     thread_bound_filter(mode filter_mode): 
+00209          filter(static_cast<mode>(filter_mode | filter::filter_is_bound))
+00210     {}
+00211 public:
+00213 
+00218     result_type __TBB_EXPORTED_METHOD try_process_item(); 
+00219 
+00221 
+00225     result_type __TBB_EXPORTED_METHOD process_item();
+00226 
+00227 private:
+00229     result_type internal_process_item(bool is_blocking);
+00230 };
+00231 
+00233 
+00234 class pipeline {
+00235 public:
+00237     __TBB_EXPORTED_METHOD pipeline();
+00238 
+00241     virtual __TBB_EXPORTED_METHOD ~pipeline();
+00242 
+00244     void __TBB_EXPORTED_METHOD add_filter( filter& filter_ );
+00245 
+00247     void __TBB_EXPORTED_METHOD run( size_t max_number_of_live_tokens );
+00248 
+00249 #if __TBB_TASK_GROUP_CONTEXT
+00251     void __TBB_EXPORTED_METHOD run( size_t max_number_of_live_tokens, tbb::task_group_context& context );
+00252 #endif
+00253 
+00255     void __TBB_EXPORTED_METHOD clear();
+00256 
+00257 private:
+00258     friend class internal::stage_task;
+00259     friend class internal::pipeline_root_task;
+00260     friend class filter;
+00261     friend class thread_bound_filter;
+00262     friend class internal::pipeline_cleaner;
+00263     friend class tbb::interface6::internal::pipeline_proxy;
+00264 
+00266     filter* filter_list;
+00267 
+00269     filter* filter_end;
+00270 
+00272     task* end_counter;
+00273 
+00275     atomic<internal::Token> input_tokens;
+00276 
+00278     atomic<internal::Token> token_counter;
+00279 
+00281     bool end_of_input;
+00282 
+00284     bool has_thread_bound_filters;
+00285 
+00287     void remove_filter( filter& filter_ );
+00288 
+00290     void __TBB_EXPORTED_METHOD inject_token( task& self );
+00291 
+00292 #if __TBB_TASK_GROUP_CONTEXT
+00294     void clear_filters();
+00295 #endif
+00296 };
+00297 
+00298 //------------------------------------------------------------------------
+00299 // Support for lambda-friendly parallel_pipeline interface
+00300 //------------------------------------------------------------------------
+00301 
+00302 namespace interface6 {
+00303 
+00304 namespace internal {
+00305     template<typename T, typename U, typename Body> class concrete_filter;
+00306 }
+00307 
+00309 class flow_control {
+00310     bool is_pipeline_stopped;
+00311     flow_control() { is_pipeline_stopped = false; }
+00312     template<typename T, typename U, typename Body> friend class internal::concrete_filter;
+00313 public:
+00314     void stop() { is_pipeline_stopped = true; }
+00315 };
+00316 
+00318 namespace internal {
+00319 
+00320 template<typename T> struct tbb_large_object {enum { value = sizeof(T) > sizeof(void *) }; };
+00321 
+00322 #if TBB_IMPLEMENT_CPP0X
+00323 // cannot use SFINAE in current compilers.  Explicitly list the types we wish to be
+00324 // placed as-is in the pipeline input_buffers.
+00325 template<typename T> struct tbb_trivially_copyable { enum { value = false }; };
+00326 template<typename T> struct tbb_trivially_copyable <T*> { enum { value = true }; };
+00327 template<> struct tbb_trivially_copyable <short> { enum { value = true }; };
+00328 template<> struct tbb_trivially_copyable <unsigned short> { enum { value = true }; };
+00329 template<> struct tbb_trivially_copyable <int> { enum { value = !tbb_large_object<int>::value }; };
+00330 template<> struct tbb_trivially_copyable <unsigned int> { enum { value = !tbb_large_object<int>::value }; };
+00331 template<> struct tbb_trivially_copyable <long> { enum { value = !tbb_large_object<long>::value }; };
+00332 template<> struct tbb_trivially_copyable <unsigned long> { enum { value = !tbb_large_object<long>::value }; };
+00333 template<> struct tbb_trivially_copyable <float> { enum { value = !tbb_large_object<float>::value }; };
+00334 template<> struct tbb_trivially_copyable <double> { enum { value = !tbb_large_object<double>::value }; };
+00335 #else
+00336 #if __GNUC__==4 && __GNUC_MINOR__>=4 && __GXX_EXPERIMENTAL_CXX0X__
+00337 template<typename T> struct tbb_trivially_copyable { enum { value = std::has_trivial_copy_constructor<T>::value }; };
+00338 #else
+00339 template<typename T> struct tbb_trivially_copyable { enum { value = std::is_trivially_copyable<T>::value }; };
+00340 #endif //
+00341 #endif // __TBB_USE_CPP0X
+00342 
+00343 template<typename T> struct is_large_object {enum { value = tbb_large_object<T>::value || !tbb_trivially_copyable<T>::value }; };
+00344 
+00345 template<typename T, bool> class token_helper;
+00346 
+00347 // large object helper (uses tbb_allocator)
+00348 template<typename T>
+00349 class token_helper<T, true> {
+00350     public:
+00351     typedef typename tbb::tbb_allocator<T> allocator;
+00352     typedef T* pointer;
+00353     typedef T value_type;
+00354     static pointer create_token(const value_type & source) {
+00355         pointer output_t = allocator().allocate(1);
+00356         return new (output_t) T(source);
+00357     }
+00358     static value_type & token(pointer & t) { return *t;}
+00359     static void * cast_to_void_ptr(pointer ref) { return (void *) ref; }
+00360     static pointer cast_from_void_ptr(void * ref) { return (pointer)ref; }
+00361     static void destroy_token(pointer token) {
+00362         allocator().destroy(token);
+00363         allocator().deallocate(token,1);
+00364     }
+00365 };
+00366 
+00367 // pointer specialization
+00368 template<typename T>
+00369 class token_helper<T*, false > {
+00370     public:
+00371     typedef T* pointer;
+00372     typedef T* value_type;
+00373     static pointer create_token(const value_type & source) { return source; }
+00374     static value_type & token(pointer & t) { return t;}
+00375     static void * cast_to_void_ptr(pointer ref) { return (void *)ref; }
+00376     static pointer cast_from_void_ptr(void * ref) { return (pointer)ref; }
+00377     static void destroy_token( pointer /*token*/) {}
+00378 };
+00379 
+00380 // small object specialization (converts void* to the correct type, passes objects directly.)
+00381 template<typename T>
+00382 class token_helper<T, false> {
+00383     typedef union {
+00384         T actual_value;
+00385         void * void_overlay;
+00386     } type_to_void_ptr_map;
+00387     public:
+00388     typedef T pointer;  // not really a pointer in this case.
+00389     typedef T value_type;
+00390     static pointer create_token(const value_type & source) {
+00391         return source; }
+00392     static value_type & token(pointer & t) { return t;}
+00393     static void * cast_to_void_ptr(pointer ref) { 
+00394         type_to_void_ptr_map mymap; 
+00395         mymap.void_overlay = NULL;
+00396         mymap.actual_value = ref; 
+00397         return mymap.void_overlay; 
+00398     }
+00399     static pointer cast_from_void_ptr(void * ref) { 
+00400         type_to_void_ptr_map mymap;
+00401         mymap.void_overlay = ref;
+00402         return mymap.actual_value;
+00403     }
+00404     static void destroy_token( pointer /*token*/) {}
+00405 };
+00406 
+00407 template<typename T, typename U, typename Body>
+00408 class concrete_filter: public tbb::filter {
+00409     const Body& my_body;
+00410     typedef token_helper<T,is_large_object<T>::value > t_helper;
+00411     typedef typename t_helper::pointer t_pointer;
+00412     typedef token_helper<U,is_large_object<U>::value > u_helper;
+00413     typedef typename u_helper::pointer u_pointer;
+00414 
+00415     /*override*/ void* operator()(void* input) {
+00416         t_pointer temp_input = t_helper::cast_from_void_ptr(input);
+00417         u_pointer output_u = u_helper::create_token(my_body(t_helper::token(temp_input)));
+00418         t_helper::destroy_token(temp_input);
+00419         return u_helper::cast_to_void_ptr(output_u);
+00420     }
+00421 
+00422 public:
+00423     concrete_filter(tbb::filter::mode filter_mode, const Body& body) : filter(filter_mode), my_body(body) {}
+00424 };
+00425 
+00426 // input 
+00427 template<typename U, typename Body>
+00428 class concrete_filter<void,U,Body>: public filter {
+00429     const Body& my_body;
+00430     typedef token_helper<U, is_large_object<U>::value > u_helper;
+00431     typedef typename u_helper::pointer u_pointer;
+00432 
+00433     /*override*/void* operator()(void*) {
+00434         flow_control control;
+00435         u_pointer output_u = u_helper::create_token(my_body(control));
+00436         if(control.is_pipeline_stopped) {
+00437             u_helper::destroy_token(output_u);
+00438             set_end_of_input();
+00439             return NULL;
+00440         }
+00441         return u_helper::cast_to_void_ptr(output_u);
+00442     }
+00443 
+00444 public:
+00445     concrete_filter(tbb::filter::mode filter_mode, const Body& body) : 
+00446         filter(static_cast<tbb::filter::mode>(filter_mode | filter_may_emit_null)),
+00447         my_body(body)
+00448     {}
+00449 };
+00450 
+00451 template<typename T, typename Body>
+00452 class concrete_filter<T,void,Body>: public filter {
+00453     const Body& my_body;
+00454     typedef token_helper<T, is_large_object<T>::value > t_helper;
+00455     typedef typename t_helper::pointer t_pointer;
+00456    
+00457     /*override*/ void* operator()(void* input) {
+00458         t_pointer temp_input = t_helper::cast_from_void_ptr(input);
+00459         my_body(t_helper::token(temp_input));
+00460         t_helper::destroy_token(temp_input);
+00461         return NULL;
+00462     }
+00463 public:
+00464     concrete_filter(tbb::filter::mode filter_mode, const Body& body) : filter(filter_mode), my_body(body) {}
+00465 };
+00466 
+00467 template<typename Body>
+00468 class concrete_filter<void,void,Body>: public filter {
+00469     const Body& my_body;
+00470     
+00472     /*override*/ void* operator()(void*) {
+00473         flow_control control;
+00474         my_body(control);
+00475         void* output = control.is_pipeline_stopped ? NULL : (void*)(intptr_t)-1; 
+00476         return output;
+00477     }
+00478 public:
+00479     concrete_filter(filter::mode filter_mode, const Body& body) : filter(filter_mode), my_body(body) {}
+00480 };
+00481 
+00483 
+00484 class pipeline_proxy {
+00485     tbb::pipeline my_pipe;
+00486 public:
+00487     pipeline_proxy( const filter_t<void,void>& filter_chain );
+00488     ~pipeline_proxy() {
+00489         while( filter* f = my_pipe.filter_list ) 
+00490             delete f; // filter destructor removes it from the pipeline
+00491     }
+00492     tbb::pipeline* operator->() { return &my_pipe; }
+00493 };
+00494 
+00496 
+00497 class filter_node: tbb::internal::no_copy {
+00499     tbb::atomic<intptr_t> ref_count;
+00500 protected:
+00501     filter_node() {
+00502         ref_count = 0;
+00503 #ifdef __TBB_TEST_FILTER_NODE_COUNT
+00504         ++(__TBB_TEST_FILTER_NODE_COUNT);
+00505 #endif
+00506     }
+00507 public:
+00509     virtual void add_to( pipeline& ) = 0;
+00511     void add_ref() {++ref_count;}
+00513     void remove_ref() {
+00514         __TBB_ASSERT(ref_count>0,"ref_count underflow");
+00515         if( --ref_count==0 ) 
+00516             delete this;
+00517     }
+00518     virtual ~filter_node() {
+00519 #ifdef __TBB_TEST_FILTER_NODE_COUNT
+00520         --(__TBB_TEST_FILTER_NODE_COUNT);
+00521 #endif
+00522     }
+00523 };
+00524 
+00526 template<typename T, typename U, typename Body>
+00527 class filter_node_leaf: public filter_node  {
+00528     const tbb::filter::mode mode;
+00529     const Body body;
+00530     /*override*/void add_to( pipeline& p ) {
+00531         concrete_filter<T,U,Body>* f = new concrete_filter<T,U,Body>(mode,body);
+00532         p.add_filter( *f );
+00533     }
+00534 public:
+00535     filter_node_leaf( tbb::filter::mode m, const Body& b ) : mode(m), body(b) {}
+00536 };
+00537 
+00539 class filter_node_join: public filter_node {
+00540     friend class filter_node; // to suppress GCC 3.2 warnings
+00541     filter_node& left;
+00542     filter_node& right;
+00543     /*override*/~filter_node_join() {
+00544        left.remove_ref();
+00545        right.remove_ref();
+00546     }
+00547     /*override*/void add_to( pipeline& p ) {
+00548         left.add_to(p);
+00549         right.add_to(p);
+00550     }
+00551 public:
+00552     filter_node_join( filter_node& x, filter_node& y ) : left(x), right(y) {
+00553        left.add_ref();
+00554        right.add_ref();
+00555     }
+00556 };
+00557 
+00558 } // namespace internal
+00560 
+00562 template<typename T, typename U, typename Body>
+00563 filter_t<T,U> make_filter(tbb::filter::mode mode, const Body& body) {
+00564     return new internal::filter_node_leaf<T,U,Body>(mode, body);
+00565 }
+00566 
+00567 template<typename T, typename V, typename U>
+00568 filter_t<T,U> operator& (const filter_t<T,V>& left, const filter_t<V,U>& right) {
+00569     __TBB_ASSERT(left.root,"cannot use default-constructed filter_t as left argument of '&'");
+00570     __TBB_ASSERT(right.root,"cannot use default-constructed filter_t as right argument of '&'");
+00571     return new internal::filter_node_join(*left.root,*right.root);
+00572 }
+00573 
+00575 template<typename T, typename U>
+00576 class filter_t {
+00577     typedef internal::filter_node filter_node;
+00578     filter_node* root;
+00579     filter_t( filter_node* root_ ) : root(root_) {
+00580         root->add_ref();
+00581     }
+00582     friend class internal::pipeline_proxy;
+00583     template<typename T_, typename U_, typename Body>
+00584     friend filter_t<T_,U_> make_filter(tbb::filter::mode, const Body& );
+00585     template<typename T_, typename V_, typename U_>
+00586     friend filter_t<T_,U_> operator& (const filter_t<T_,V_>& , const filter_t<V_,U_>& );
+00587 public:
+00588     filter_t() : root(NULL) {}
+00589     filter_t( const filter_t<T,U>& rhs ) : root(rhs.root) {
+00590         if( root ) root->add_ref();
+00591     }
+00592     template<typename Body>
+00593     filter_t( tbb::filter::mode mode, const Body& body ) :
+00594         root( new internal::filter_node_leaf<T,U,Body>(mode, body) ) {
+00595         root->add_ref();
+00596     }
+00597 
+00598     void operator=( const filter_t<T,U>& rhs ) {
+00599         // Order of operations below carefully chosen so that reference counts remain correct
+00600         // in unlikely event that remove_ref throws exception.
+00601         filter_node* old = root;
+00602         root = rhs.root; 
+00603         if( root ) root->add_ref();
+00604         if( old ) old->remove_ref();
+00605     }
+00606     ~filter_t() {
+00607         if( root ) root->remove_ref();
+00608     }
+00609     void clear() {
+00610         // Like operator= with filter_t() on right side.
+00611         if( root ) {
+00612             filter_node* old = root;
+00613             root = NULL;
+00614             old->remove_ref();
+00615         }
+00616     }
+00617 };
+00618 
+00619 inline internal::pipeline_proxy::pipeline_proxy( const filter_t<void,void>& filter_chain ) : my_pipe() {
+00620     __TBB_ASSERT( filter_chain.root, "cannot apply parallel_pipeline to default-constructed filter_t"  );
+00621     filter_chain.root->add_to(my_pipe);
+00622 }
+00623 
+00624 inline void parallel_pipeline(size_t max_number_of_live_tokens, const filter_t<void,void>& filter_chain
+00625 #if __TBB_TASK_GROUP_CONTEXT
+00626     , tbb::task_group_context& context
+00627 #endif
+00628     ) {
+00629     internal::pipeline_proxy pipe(filter_chain);
+00630     // tbb::pipeline::run() is called via the proxy
+00631     pipe->run(max_number_of_live_tokens
+00632 #if __TBB_TASK_GROUP_CONTEXT
+00633               , context
+00634 #endif
+00635     );
+00636 }
+00637 
+00638 #if __TBB_TASK_GROUP_CONTEXT
+00639 inline void parallel_pipeline(size_t max_number_of_live_tokens, const filter_t<void,void>& filter_chain) {
+00640     tbb::task_group_context context;
+00641     parallel_pipeline(max_number_of_live_tokens, filter_chain, context);
+00642 }
+00643 #endif // __TBB_TASK_GROUP_CONTEXT
+00644 
+00645 } // interface6
+00646 
+00647 using interface6::flow_control;
+00648 using interface6::filter_t;
+00649 using interface6::make_filter;
+00650 using interface6::parallel_pipeline;
+00651 
+00652 } // tbb
+00653 
+00654 #endif /* __TBB_pipeline_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00603.html b/src/tbb/doc/html/a00603.html new file mode 100644 index 0000000..08d218c --- /dev/null +++ b/src/tbb/doc/html/a00603.html @@ -0,0 +1,136 @@ + + +queuing_mutex.h Source File + + + + + + +

queuing_mutex.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_queuing_mutex_H
+00022 #define __TBB_queuing_mutex_H
+00023 
+00024 #include "tbb_config.h"
+00025 
+00026 #if !TBB_USE_EXCEPTIONS && _MSC_VER
+00027     // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers
+00028     #pragma warning (push)
+00029     #pragma warning (disable: 4530)
+00030 #endif
+00031 
+00032 #include <cstring>
+00033 
+00034 #if !TBB_USE_EXCEPTIONS && _MSC_VER
+00035     #pragma warning (pop)
+00036 #endif
+00037 
+00038 #include "atomic.h"
+00039 #include "tbb_profiling.h"
+00040 
+00041 namespace tbb {
+00042 
+00044 
+00045 class queuing_mutex {
+00046 public:
+00048     queuing_mutex() {
+00049         q_tail = NULL;
+00050 #if TBB_USE_THREADING_TOOLS
+00051         internal_construct();
+00052 #endif
+00053     }
+00054 
+00056 
+00058     class scoped_lock: internal::no_copy {
+00060         void initialize() {
+00061             mutex = NULL;
+00062 #if TBB_USE_ASSERT
+00063             internal::poison_pointer(next);
+00064 #endif /* TBB_USE_ASSERT */
+00065         }
+00066 
+00067     public:
+00069 
+00070         scoped_lock() {initialize();}
+00071 
+00073         scoped_lock( queuing_mutex& m ) {
+00074             initialize();
+00075             acquire(m);
+00076         }
+00077 
+00079         ~scoped_lock() {
+00080             if( mutex ) release();
+00081         }
+00082 
+00084         void __TBB_EXPORTED_METHOD acquire( queuing_mutex& m );
+00085 
+00087         bool __TBB_EXPORTED_METHOD try_acquire( queuing_mutex& m );
+00088 
+00090         void __TBB_EXPORTED_METHOD release();
+00091 
+00092     private:
+00094         queuing_mutex* mutex;
+00095 
+00097         scoped_lock *next;
+00098 
+00100 
+00103         uintptr_t going;
+00104     };
+00105 
+00106     void __TBB_EXPORTED_METHOD internal_construct();
+00107 
+00108     // Mutex traits
+00109     static const bool is_rw_mutex = false;
+00110     static const bool is_recursive_mutex = false;
+00111     static const bool is_fair_mutex = true;
+00112 
+00113 private:
+00115     atomic<scoped_lock*> q_tail;
+00116 
+00117 };
+00118 
+00119 __TBB_DEFINE_PROFILING_SET_NAME(queuing_mutex)
+00120 
+00121 } // namespace tbb
+00122 
+00123 #endif /* __TBB_queuing_mutex_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00604.html b/src/tbb/doc/html/a00604.html new file mode 100644 index 0000000..c7351ca --- /dev/null +++ b/src/tbb/doc/html/a00604.html @@ -0,0 +1,166 @@ + + +queuing_rw_mutex.h Source File + + + + + + +

queuing_rw_mutex.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_queuing_rw_mutex_H
+00022 #define __TBB_queuing_rw_mutex_H
+00023 
+00024 #include "tbb_config.h"
+00025 
+00026 #if !TBB_USE_EXCEPTIONS && _MSC_VER
+00027     // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers
+00028     #pragma warning (push)
+00029     #pragma warning (disable: 4530)
+00030 #endif
+00031 
+00032 #include <cstring>
+00033 
+00034 #if !TBB_USE_EXCEPTIONS && _MSC_VER
+00035     #pragma warning (pop)
+00036 #endif
+00037 
+00038 #include "atomic.h"
+00039 #include "tbb_profiling.h"
+00040 
+00041 namespace tbb {
+00042 
+00044 
+00047 class queuing_rw_mutex {
+00048 public:
+00050     queuing_rw_mutex() {
+00051         q_tail = NULL;
+00052 #if TBB_USE_THREADING_TOOLS
+00053         internal_construct();
+00054 #endif
+00055     }
+00056 
+00058     ~queuing_rw_mutex() {
+00059 #if TBB_USE_ASSERT
+00060         __TBB_ASSERT( !q_tail, "destruction of an acquired mutex");
+00061 #endif
+00062     }
+00063 
+00065 
+00067     class scoped_lock: internal::no_copy {
+00069         void initialize() {
+00070             my_mutex = NULL;
+00071 #if TBB_USE_ASSERT
+00072             my_state = 0xFF; // Set to invalid state
+00073             internal::poison_pointer(my_next);
+00074             internal::poison_pointer(my_prev);
+00075 #endif /* TBB_USE_ASSERT */
+00076         }
+00077 
+00078     public:
+00080 
+00081         scoped_lock() {initialize();}
+00082 
+00084         scoped_lock( queuing_rw_mutex& m, bool write=true ) {
+00085             initialize();
+00086             acquire(m,write);
+00087         }
+00088 
+00090         ~scoped_lock() {
+00091             if( my_mutex ) release();
+00092         }
+00093 
+00095         void acquire( queuing_rw_mutex& m, bool write=true );
+00096 
+00098         bool try_acquire( queuing_rw_mutex& m, bool write=true );
+00099 
+00101         void release();
+00102 
+00104 
+00105         bool upgrade_to_writer();
+00106 
+00108         bool downgrade_to_reader();
+00109 
+00110     private:
+00112         queuing_rw_mutex* my_mutex;
+00113 
+00115         scoped_lock *__TBB_atomic my_prev, *__TBB_atomic my_next;
+00116 
+00117         typedef unsigned char state_t;
+00118 
+00120         atomic<state_t> my_state;
+00121 
+00123 
+00124         unsigned char __TBB_atomic my_going;
+00125 
+00127         unsigned char my_internal_lock;
+00128 
+00130         void acquire_internal_lock();
+00131 
+00133 
+00134         bool try_acquire_internal_lock();
+00135 
+00137         void release_internal_lock();
+00138 
+00140         void wait_for_release_of_internal_lock();
+00141 
+00143         void unblock_or_wait_on_internal_lock( uintptr_t );
+00144     };
+00145 
+00146     void __TBB_EXPORTED_METHOD internal_construct();
+00147 
+00148     // Mutex traits
+00149     static const bool is_rw_mutex = true;
+00150     static const bool is_recursive_mutex = false;
+00151     static const bool is_fair_mutex = true;
+00152 
+00153 private:
+00155     atomic<scoped_lock*> q_tail;
+00156 
+00157 };
+00158 
+00159 __TBB_DEFINE_PROFILING_SET_NAME(queuing_rw_mutex)
+00160 
+00161 } // namespace tbb
+00162 
+00163 #endif /* __TBB_queuing_rw_mutex_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00605.html b/src/tbb/doc/html/a00605.html new file mode 100644 index 0000000..af7240d --- /dev/null +++ b/src/tbb/doc/html/a00605.html @@ -0,0 +1,179 @@ + + +reader_writer_lock.h Source File + + + + + + +

reader_writer_lock.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_reader_writer_lock_H
+00022 #define __TBB_reader_writer_lock_H
+00023 
+00024 #include "tbb_thread.h"
+00025 #include "tbb_allocator.h"
+00026 #include "atomic.h"
+00027 
+00028 namespace tbb {
+00029 namespace interface5 {
+00031 
+00034     class reader_writer_lock : tbb::internal::no_copy {
+00035  public:
+00036     friend class scoped_lock;
+00037     friend class scoped_lock_read;
+00039 
+00074     enum status_t { waiting_nonblocking, waiting, active, invalid };
+00075 
+00077     reader_writer_lock() {
+00078         internal_construct();
+00079     }
+00080 
+00082     ~reader_writer_lock() {
+00083         internal_destroy();
+00084     }
+00085 
+00087 
+00089     class scoped_lock : tbb::internal::no_copy {
+00090     public:
+00091         friend class reader_writer_lock;
+00092 
+00094         scoped_lock(reader_writer_lock& lock) {
+00095             internal_construct(lock);
+00096         }
+00097 
+00099         ~scoped_lock() {
+00100             internal_destroy();
+00101         }
+00102 
+00103         void* operator new(size_t s) {
+00104             return tbb::internal::allocate_via_handler_v3(s);
+00105         }
+00106         void operator delete(void* p) {
+00107             tbb::internal::deallocate_via_handler_v3(p);
+00108         }
+00109 
+00110     private:
+00112         reader_writer_lock *mutex;
+00114         scoped_lock* next;
+00116         atomic<status_t> status;
+00117 
+00119         scoped_lock();
+00120 
+00121         void __TBB_EXPORTED_METHOD internal_construct(reader_writer_lock&);
+00122         void __TBB_EXPORTED_METHOD internal_destroy();
+00123    };
+00124 
+00126     class scoped_lock_read : tbb::internal::no_copy {
+00127     public:
+00128         friend class reader_writer_lock;
+00129 
+00131         scoped_lock_read(reader_writer_lock& lock) {
+00132             internal_construct(lock);
+00133         }
+00134 
+00136         ~scoped_lock_read() {
+00137             internal_destroy();
+00138         }
+00139 
+00140         void* operator new(size_t s) {
+00141             return tbb::internal::allocate_via_handler_v3(s);
+00142         }
+00143         void operator delete(void* p) {
+00144             tbb::internal::deallocate_via_handler_v3(p);
+00145         }
+00146 
+00147     private:
+00149         reader_writer_lock *mutex;
+00151         scoped_lock_read *next;
+00153         atomic<status_t> status;
+00154 
+00156         scoped_lock_read();
+00157 
+00158         void __TBB_EXPORTED_METHOD internal_construct(reader_writer_lock&);
+00159         void __TBB_EXPORTED_METHOD internal_destroy();
+00160     };
+00161 
+00163 
+00168     void __TBB_EXPORTED_METHOD lock();
+00169 
+00171 
+00175     bool __TBB_EXPORTED_METHOD try_lock();
+00176 
+00178 
+00182     void __TBB_EXPORTED_METHOD lock_read();
+00183 
+00185 
+00187     bool __TBB_EXPORTED_METHOD try_lock_read();
+00188 
+00190     void __TBB_EXPORTED_METHOD unlock();
+00191 
+00192  private:
+00193     void __TBB_EXPORTED_METHOD internal_construct();
+00194     void __TBB_EXPORTED_METHOD internal_destroy();
+00195 
+00197 
+00198     bool start_write(scoped_lock *);
+00200     void set_next_writer(scoped_lock *w);
+00202     void end_write(scoped_lock *);
+00204     bool is_current_writer();
+00205 
+00207 
+00208     void start_read(scoped_lock_read *);
+00210     void unblock_readers();
+00212     void end_read();
+00213 
+00215     atomic<scoped_lock_read*> reader_head;
+00217     atomic<scoped_lock*> writer_head;
+00219     atomic<scoped_lock*> writer_tail;
+00221     tbb_thread::id my_current_writer;
+00223     atomic<uintptr_t> rdr_count_and_flags; // used with __TBB_AtomicOR, which assumes uintptr_t
+00224 };
+00225 
+00226 } // namespace interface5
+00227 
+00228 using interface5::reader_writer_lock;
+00229 
+00230 } // namespace tbb
+00231 
+00232 #endif /* __TBB_reader_writer_lock_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00606.html b/src/tbb/doc/html/a00606.html new file mode 100644 index 0000000..ee3dea0 --- /dev/null +++ b/src/tbb/doc/html/a00606.html @@ -0,0 +1,241 @@ + + +recursive_mutex.h Source File + + + + + + +

recursive_mutex.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_recursive_mutex_H
+00022 #define __TBB_recursive_mutex_H
+00023 
+00024 #if _WIN32||_WIN64
+00025 #include "machine/windows_api.h"
+00026 #else
+00027 #include <pthread.h>
+00028 #endif /* _WIN32||_WIN64 */
+00029 
+00030 #include <new>
+00031 #include "aligned_space.h"
+00032 #include "tbb_stddef.h"
+00033 #include "tbb_profiling.h"
+00034 
+00035 namespace tbb {
+00037 
+00039 class recursive_mutex {
+00040 public:
+00042     recursive_mutex() {
+00043 #if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS
+00044         internal_construct();
+00045 #else
+00046   #if _WIN32||_WIN64
+00047         InitializeCriticalSection(&impl);
+00048   #else
+00049         pthread_mutexattr_t mtx_attr;
+00050         int error_code = pthread_mutexattr_init( &mtx_attr );
+00051         if( error_code )
+00052             tbb::internal::handle_perror(error_code,"recursive_mutex: pthread_mutexattr_init failed");
+00053 
+00054         pthread_mutexattr_settype( &mtx_attr, PTHREAD_MUTEX_RECURSIVE );
+00055         error_code = pthread_mutex_init( &impl, &mtx_attr );
+00056         if( error_code )
+00057             tbb::internal::handle_perror(error_code,"recursive_mutex: pthread_mutex_init failed");
+00058 
+00059         pthread_mutexattr_destroy( &mtx_attr );
+00060   #endif /* _WIN32||_WIN64*/
+00061 #endif /* TBB_USE_ASSERT */
+00062     };
+00063 
+00064     ~recursive_mutex() {
+00065 #if TBB_USE_ASSERT
+00066         internal_destroy();
+00067 #else
+00068   #if _WIN32||_WIN64
+00069         DeleteCriticalSection(&impl);
+00070   #else
+00071         pthread_mutex_destroy(&impl); 
+00072 
+00073   #endif /* _WIN32||_WIN64 */
+00074 #endif /* TBB_USE_ASSERT */
+00075     };
+00076 
+00077     class scoped_lock;
+00078     friend class scoped_lock;
+00079 
+00081 
+00083     class scoped_lock: internal::no_copy {
+00084     public:
+00086         scoped_lock() : my_mutex(NULL) {};
+00087 
+00089         scoped_lock( recursive_mutex& mutex ) {
+00090 #if TBB_USE_ASSERT
+00091             my_mutex = &mutex; 
+00092 #endif /* TBB_USE_ASSERT */
+00093             acquire( mutex );
+00094         }
+00095 
+00097         ~scoped_lock() {
+00098             if( my_mutex ) 
+00099                 release();
+00100         }
+00101 
+00103         void acquire( recursive_mutex& mutex ) {
+00104 #if TBB_USE_ASSERT
+00105             internal_acquire( mutex );
+00106 #else
+00107             my_mutex = &mutex;
+00108             mutex.lock();
+00109 #endif /* TBB_USE_ASSERT */
+00110         }
+00111 
+00113         bool try_acquire( recursive_mutex& mutex ) {
+00114 #if TBB_USE_ASSERT
+00115             return internal_try_acquire( mutex );
+00116 #else
+00117             bool result = mutex.try_lock();
+00118             if( result )
+00119                 my_mutex = &mutex;
+00120             return result;
+00121 #endif /* TBB_USE_ASSERT */
+00122         }
+00123 
+00125         void release() {
+00126 #if TBB_USE_ASSERT
+00127             internal_release();
+00128 #else
+00129             my_mutex->unlock();
+00130             my_mutex = NULL;
+00131 #endif /* TBB_USE_ASSERT */
+00132         }
+00133 
+00134     private:
+00136         recursive_mutex* my_mutex;
+00137 
+00139         void __TBB_EXPORTED_METHOD internal_acquire( recursive_mutex& m );
+00140 
+00142         bool __TBB_EXPORTED_METHOD internal_try_acquire( recursive_mutex& m );
+00143 
+00145         void __TBB_EXPORTED_METHOD internal_release();
+00146 
+00147         friend class recursive_mutex;
+00148     };
+00149 
+00150     // Mutex traits
+00151     static const bool is_rw_mutex = false;
+00152     static const bool is_recursive_mutex = true;
+00153     static const bool is_fair_mutex = false;
+00154 
+00155     // C++0x compatibility interface
+00156     
+00158     void lock() {
+00159 #if TBB_USE_ASSERT
+00160         aligned_space<scoped_lock,1> tmp;
+00161         new(tmp.begin()) scoped_lock(*this);
+00162 #else
+00163   #if _WIN32||_WIN64
+00164         EnterCriticalSection(&impl);
+00165   #else
+00166         pthread_mutex_lock(&impl);
+00167   #endif /* _WIN32||_WIN64 */
+00168 #endif /* TBB_USE_ASSERT */
+00169     }
+00170 
+00172 
+00173     bool try_lock() {
+00174 #if TBB_USE_ASSERT
+00175         aligned_space<scoped_lock,1> tmp;
+00176         return (new(tmp.begin()) scoped_lock)->internal_try_acquire(*this);
+00177 #else        
+00178   #if _WIN32||_WIN64
+00179         return TryEnterCriticalSection(&impl)!=0;
+00180   #else
+00181         return pthread_mutex_trylock(&impl)==0;
+00182   #endif /* _WIN32||_WIN64 */
+00183 #endif /* TBB_USE_ASSERT */
+00184     }
+00185 
+00187     void unlock() {
+00188 #if TBB_USE_ASSERT
+00189         aligned_space<scoped_lock,1> tmp;
+00190         scoped_lock& s = *tmp.begin();
+00191         s.my_mutex = this;
+00192         s.internal_release();
+00193 #else
+00194   #if _WIN32||_WIN64
+00195         LeaveCriticalSection(&impl);
+00196   #else
+00197         pthread_mutex_unlock(&impl);
+00198   #endif /* _WIN32||_WIN64 */
+00199 #endif /* TBB_USE_ASSERT */
+00200     }
+00201 
+00203   #if _WIN32||_WIN64
+00204     typedef LPCRITICAL_SECTION native_handle_type;
+00205   #else
+00206     typedef pthread_mutex_t* native_handle_type;
+00207   #endif
+00208     native_handle_type native_handle() { return (native_handle_type) &impl; }
+00209 
+00210 private:
+00211 #if _WIN32||_WIN64
+00212     CRITICAL_SECTION impl;
+00213     enum state_t {
+00214         INITIALIZED=0x1234,
+00215         DESTROYED=0x789A,
+00216     } state;
+00217 #else
+00218     pthread_mutex_t impl;
+00219 #endif /* _WIN32||_WIN64 */
+00220 
+00222     void __TBB_EXPORTED_METHOD internal_construct();
+00223 
+00225     void __TBB_EXPORTED_METHOD internal_destroy();
+00226 };
+00227 
+00228 __TBB_DEFINE_PROFILING_SET_NAME(recursive_mutex)
+00229 
+00230 } // namespace tbb 
+00231 
+00232 #endif /* __TBB_recursive_mutex_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00607.html b/src/tbb/doc/html/a00607.html new file mode 100644 index 0000000..b4b9673 --- /dev/null +++ b/src/tbb/doc/html/a00607.html @@ -0,0 +1,137 @@ + + +runtime_loader.h Source File + + + + + + +

runtime_loader.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_runtime_loader_H
+00022 #define __TBB_runtime_loader_H
+00023 
+00024 #if ! TBB_PREVIEW_RUNTIME_LOADER
+00025     #error Set TBB_PREVIEW_RUNTIME_LOADER to include runtime_loader.h
+00026 #endif
+00027 
+00028 #include "tbb/tbb_stddef.h"
+00029 #include <climits>
+00030 
+00031 #if _MSC_VER
+00032     #if ! __TBB_NO_IMPLICIT_LINKAGE
+00033         #ifdef _DEBUG
+00034             #pragma comment( linker, "/nodefaultlib:tbb_debug.lib" )
+00035             #pragma comment( linker, "/defaultlib:tbbproxy_debug.lib" )
+00036         #else
+00037             #pragma comment( linker, "/nodefaultlib:tbb.lib" )
+00038             #pragma comment( linker, "/defaultlib:tbbproxy.lib" )
+00039         #endif
+00040     #endif
+00041 #endif
+00042 
+00043 namespace tbb {
+00044 
+00045 namespace interface6 {
+00046 
+00048 
+00085 class runtime_loader : tbb::internal::no_copy {
+00086 
+00087     public:
+00088 
+00090         enum error_mode {
+00091             em_status,     
+00092             em_throw,      
+00093             em_abort       
+00094         }; // error_mode
+00095 
+00097         enum error_code {
+00098             ec_ok,         
+00099             ec_bad_call,   
+00100             ec_bad_arg,    
+00101             ec_bad_lib,    
+00102             ec_bad_ver,    
+00103             ec_no_lib      
+00104         }; // error_code
+00105 
+00107         runtime_loader( error_mode mode = em_abort );
+00108 
+00110 
+00115         runtime_loader(
+00116             char const * path[],                           
+00117             int          min_ver = TBB_INTERFACE_VERSION,  
+00118             int          max_ver = INT_MAX,                
+00119             error_mode   mode    = em_abort                
+00120         );
+00121 
+00123         ~runtime_loader();
+00124 
+00126 
+00150         error_code
+00151         load(
+00152             char const * path[],                           
+00153             int          min_ver = TBB_INTERFACE_VERSION,  
+00154             int          max_ver = INT_MAX                 
+00155 
+00156         );
+00157 
+00158 
+00160 
+00163         error_code status();
+00164 
+00165     private:
+00166 
+00167         error_mode const my_mode;
+00168         error_code       my_status;
+00169         bool             my_loaded;
+00170 
+00171 }; // class runtime_loader
+00172 
+00173 } // namespace interface6
+00174 
+00175 using interface6::runtime_loader;
+00176 
+00177 } // namespace tbb
+00178 
+00179 #endif /* __TBB_runtime_loader_H */
+00180 
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00608.html b/src/tbb/doc/html/a00608.html new file mode 100644 index 0000000..bac772f --- /dev/null +++ b/src/tbb/doc/html/a00608.html @@ -0,0 +1,275 @@ + + +scalable_allocator.h Source File + + + + + + +

scalable_allocator.h

Go to the documentation of this file.
00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_scalable_allocator_H
+00022 #define __TBB_scalable_allocator_H
+00023 
+00025 #include <stddef.h> /* Need ptrdiff_t and size_t from here. */
+00026 #if !_MSC_VER
+00027 #include <stdint.h> /* Need intptr_t from here. */
+00028 #endif
+00029 
+00030 #if !defined(__cplusplus) && __ICC==1100
+00031     #pragma warning (push)
+00032     #pragma warning (disable: 991)
+00033 #endif
+00034 
+00035 #ifdef __cplusplus
+00036 extern "C" {
+00037 #endif /* __cplusplus */
+00038 
+00039 #if _MSC_VER >= 1400
+00040 #define __TBB_EXPORTED_FUNC   __cdecl
+00041 #else
+00042 #define __TBB_EXPORTED_FUNC
+00043 #endif
+00044 
+00047 void * __TBB_EXPORTED_FUNC scalable_malloc (size_t size);
+00048 
+00051 void   __TBB_EXPORTED_FUNC scalable_free (void* ptr);
+00052 
+00055 void * __TBB_EXPORTED_FUNC scalable_realloc (void* ptr, size_t size);
+00056 
+00059 void * __TBB_EXPORTED_FUNC scalable_calloc (size_t nobj, size_t size);
+00060 
+00063 int __TBB_EXPORTED_FUNC scalable_posix_memalign (void** memptr, size_t alignment, size_t size);
+00064 
+00067 void * __TBB_EXPORTED_FUNC scalable_aligned_malloc (size_t size, size_t alignment);
+00068 
+00071 void * __TBB_EXPORTED_FUNC scalable_aligned_realloc (void* ptr, size_t size, size_t alignment);
+00072 
+00075 void __TBB_EXPORTED_FUNC scalable_aligned_free (void* ptr);
+00076 
+00081 size_t __TBB_EXPORTED_FUNC scalable_msize (void* ptr);
+00082 
+00083 #ifdef __cplusplus
+00084 } /* extern "C" */
+00085 #endif /* __cplusplus */
+00086 
+00087 #ifdef __cplusplus
+00088 
+00089 namespace rml {
+00090 class MemoryPool;
+00091 
+00092 typedef void *(*rawAllocType)(intptr_t pool_id, size_t &bytes);
+00093 typedef int   (*rawFreeType)(intptr_t pool_id, void* raw_ptr, size_t raw_bytes);
+00094 
+00095 /*
+00096 MemPoolPolicy extension must be compatible with such structure fields layout
+00097 
+00098 struct MemPoolPolicy {
+00099     rawAllocType pAlloc;
+00100     rawFreeType  pFree;
+00101     size_t       granularity;   // granularity of pAlloc allocations
+00102 };
+00103 */
+00104 
+00105 struct MemPoolPolicy {
+00106     enum {
+00107         VERSION = 1
+00108     };
+00109 
+00110     rawAllocType pAlloc;
+00111     rawFreeType  pFree;
+00112                  // granularity of pAlloc allocations. 0 means default used.
+00113     size_t       granularity;
+00114     int          version;
+00115                  // all memory consumed at 1st pAlloc call and never returned,
+00116                  // no more pAlloc calls after 1st
+00117     unsigned     fixedPool : 1,
+00118                  // memory consumed but returned only at pool termination
+00119                  keepAllMemory : 1,
+00120                  reserved : 30;
+00121 
+00122     MemPoolPolicy(rawAllocType pAlloc_, rawFreeType pFree_,
+00123                   size_t granularity_ = 0, bool fixedPool_ = false,
+00124                   bool keepAllMemory_ = false) :
+00125         pAlloc(pAlloc_), pFree(pFree_), granularity(granularity_), version(VERSION),
+00126         fixedPool(fixedPool_), keepAllMemory(keepAllMemory_),
+00127         reserved(0) {}
+00128 };
+00129 
+00130 enum MemPoolError {
+00131     POOL_OK,            // pool created successfully
+00132     INVALID_POLICY,     // invalid policy parameters found
+00133     UNSUPPORTED_POLICY, // requested pool policy is not supported by allocator library
+00134     NO_MEMORY           // lack of memory during pool creation
+00135 };
+00136 
+00137 MemPoolError pool_create_v1(intptr_t pool_id, const MemPoolPolicy *policy,
+00138                             rml::MemoryPool **pool);
+00139 
+00140 bool  pool_destroy(MemoryPool* memPool);
+00141 void *pool_malloc(MemoryPool* memPool, size_t size);
+00142 void *pool_realloc(MemoryPool* memPool, void *object, size_t size);
+00143 void *pool_aligned_malloc(MemoryPool* mPool, size_t size, size_t alignment);
+00144 void *pool_aligned_realloc(MemoryPool* mPool, void *ptr, size_t size, size_t alignment);
+00145 bool  pool_reset(MemoryPool* memPool);
+00146 bool  pool_free(MemoryPool *memPool, void *object);
+00147 }
+00148 
+00149 #include <new>      /* To use new with the placement argument */
+00150 
+00151 /* Ensure that including this header does not cause implicit linkage with TBB */
+00152 #ifndef __TBB_NO_IMPLICIT_LINKAGE
+00153     #define __TBB_NO_IMPLICIT_LINKAGE 1
+00154     #include "tbb_stddef.h"
+00155     #undef  __TBB_NO_IMPLICIT_LINKAGE
+00156 #else
+00157     #include "tbb_stddef.h"
+00158 #endif
+00159 
+00160 #if __TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_CPP11_STD_FORWARD_BROKEN
+00161  #include <utility> // std::forward
+00162 #endif
+00163 
+00164 namespace tbb {
+00165 
+00166 #if _MSC_VER && !defined(__INTEL_COMPILER)
+00167     // Workaround for erroneous "unreferenced parameter" warning in method destroy.
+00168     #pragma warning (push)
+00169     #pragma warning (disable: 4100)
+00170 #endif
+00171 
+00173 
+00176 template<typename T>
+00177 class scalable_allocator {
+00178 public:
+00179     typedef typename internal::allocator_type<T>::value_type value_type;
+00180     typedef value_type* pointer;
+00181     typedef const value_type* const_pointer;
+00182     typedef value_type& reference;
+00183     typedef const value_type& const_reference;
+00184     typedef size_t size_type;
+00185     typedef ptrdiff_t difference_type;
+00186     template<class U> struct rebind {
+00187         typedef scalable_allocator<U> other;
+00188     };
+00189 
+00190     scalable_allocator() throw() {}
+00191     scalable_allocator( const scalable_allocator& ) throw() {}
+00192     template<typename U> scalable_allocator(const scalable_allocator<U>&) throw() {}
+00193 
+00194     pointer address(reference x) const {return &x;}
+00195     const_pointer address(const_reference x) const {return &x;}
+00196 
+00198     pointer allocate( size_type n, const void* /*hint*/ =0 ) {
+00199         return static_cast<pointer>( scalable_malloc( n * sizeof(value_type) ) );
+00200     }
+00201 
+00203     void deallocate( pointer p, size_type ) {
+00204         scalable_free( p );
+00205     }
+00206 
+00208     size_type max_size() const throw() {
+00209         size_type absolutemax = static_cast<size_type>(-1) / sizeof (value_type);
+00210         return (absolutemax > 0 ? absolutemax : 1);
+00211     }
+00212 #if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT
+00213     template<typename... Args>
+00214     void construct(pointer p, Args&&... args)
+00215  #if __TBB_CPP11_STD_FORWARD_BROKEN
+00216         { ::new((void *)p) T((args)...); }
+00217  #else
+00218         { ::new((void *)p) T(std::forward<Args>(args)...); }
+00219  #endif
+00220 #else // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT
+00221     void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);}
+00222 #endif // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT
+00223     void destroy( pointer p ) {p->~value_type();}
+00224 };
+00225 
+00226 #if _MSC_VER && !defined(__INTEL_COMPILER)
+00227     #pragma warning (pop)
+00228 #endif // warning 4100 is back
+00229 
+00231 
+00232 template<>
+00233 class scalable_allocator<void> {
+00234 public:
+00235     typedef void* pointer;
+00236     typedef const void* const_pointer;
+00237     typedef void value_type;
+00238     template<class U> struct rebind {
+00239         typedef scalable_allocator<U> other;
+00240     };
+00241 };
+00242 
+00243 template<typename T, typename U>
+00244 inline bool operator==( const scalable_allocator<T>&, const scalable_allocator<U>& ) {return true;}
+00245 
+00246 template<typename T, typename U>
+00247 inline bool operator!=( const scalable_allocator<T>&, const scalable_allocator<U>& ) {return false;}
+00248 
+00249 } // namespace tbb
+00250 
+00251 #if _MSC_VER
+00252     #if (__TBB_BUILD || __TBBMALLOC_BUILD) && !defined(__TBBMALLOC_NO_IMPLICIT_LINKAGE)
+00253         #define __TBBMALLOC_NO_IMPLICIT_LINKAGE 1
+00254     #endif
+00255 
+00256     #if !__TBBMALLOC_NO_IMPLICIT_LINKAGE
+00257         #ifdef _DEBUG
+00258             #pragma comment(lib, "tbbmalloc_debug.lib")
+00259         #else
+00260             #pragma comment(lib, "tbbmalloc.lib")
+00261         #endif
+00262     #endif
+00263 
+00264 
+00265 #endif
+00266 
+00267 #endif /* __cplusplus */
+00268 
+00269 #if !defined(__cplusplus) && __ICC==1100
+00270     #pragma warning (pop)
+00271 #endif // ICC 11.0 warning 991 is back
+00272 
+00273 #endif /* __TBB_scalable_allocator_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00611.html b/src/tbb/doc/html/a00611.html new file mode 100644 index 0000000..5a8b6e3 --- /dev/null +++ b/src/tbb/doc/html/a00611.html @@ -0,0 +1,192 @@ + + +spin_mutex.h Source File + + + + + + +

spin_mutex.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_spin_mutex_H
+00022 #define __TBB_spin_mutex_H
+00023 
+00024 #include <cstddef>
+00025 #include <new>
+00026 #include "aligned_space.h"
+00027 #include "tbb_stddef.h"
+00028 #include "tbb_machine.h"
+00029 #include "tbb_profiling.h"
+00030 
+00031 namespace tbb {
+00032 
+00034 
+00039 class spin_mutex {
+00041     __TBB_atomic_flag flag;
+00042 
+00043 public:
+00045 
+00046     spin_mutex() : flag(0) {
+00047 #if TBB_USE_THREADING_TOOLS
+00048         internal_construct();
+00049 #endif
+00050     }
+00051 
+00053     class scoped_lock : internal::no_copy {
+00054     private:
+00056         spin_mutex* my_mutex; 
+00057 
+00059         __TBB_Flag my_unlock_value;
+00060 
+00062         void __TBB_EXPORTED_METHOD internal_acquire( spin_mutex& m );
+00063 
+00065         bool __TBB_EXPORTED_METHOD internal_try_acquire( spin_mutex& m );
+00066 
+00068         void __TBB_EXPORTED_METHOD internal_release();
+00069 
+00070         friend class spin_mutex;
+00071 
+00072     public:
+00074         scoped_lock() : my_mutex(NULL), my_unlock_value(0) {}
+00075 
+00077         scoped_lock( spin_mutex& m ) { 
+00078 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
+00079             my_mutex=NULL;
+00080             internal_acquire(m);
+00081 #else
+00082             my_unlock_value = __TBB_LockByte(m.flag);
+00083             my_mutex=&m;
+00084 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT*/
+00085         }
+00086 
+00088         void acquire( spin_mutex& m ) {
+00089 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
+00090             internal_acquire(m);
+00091 #else
+00092             my_unlock_value = __TBB_LockByte(m.flag);
+00093             my_mutex = &m;
+00094 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT*/
+00095         }
+00096 
+00098 
+00099         bool try_acquire( spin_mutex& m ) {
+00100 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
+00101             return internal_try_acquire(m);
+00102 #else
+00103             bool result = __TBB_TryLockByte(m.flag);
+00104             if( result ) {
+00105                 my_unlock_value = 0;
+00106                 my_mutex = &m;
+00107             }
+00108             return result;
+00109 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT*/
+00110         }
+00111 
+00113         void release() {
+00114 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
+00115             internal_release();
+00116 #else
+00117             __TBB_UnlockByte(my_mutex->flag, my_unlock_value);
+00118             my_mutex = NULL;
+00119 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */
+00120         }
+00121 
+00123         ~scoped_lock() {
+00124             if( my_mutex ) {
+00125 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
+00126                 internal_release();
+00127 #else
+00128                 __TBB_UnlockByte(my_mutex->flag, my_unlock_value);
+00129 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */
+00130             }
+00131         }
+00132     };
+00133 
+00134     void __TBB_EXPORTED_METHOD internal_construct();
+00135 
+00136     // Mutex traits
+00137     static const bool is_rw_mutex = false;
+00138     static const bool is_recursive_mutex = false;
+00139     static const bool is_fair_mutex = false;
+00140 
+00141     // ISO C++0x compatibility methods
+00142 
+00144     void lock() {
+00145 #if TBB_USE_THREADING_TOOLS
+00146         aligned_space<scoped_lock,1> tmp;
+00147         new(tmp.begin()) scoped_lock(*this);
+00148 #else
+00149         __TBB_LockByte(flag);
+00150 #endif /* TBB_USE_THREADING_TOOLS*/
+00151     }
+00152 
+00154 
+00155     bool try_lock() {
+00156 #if TBB_USE_THREADING_TOOLS
+00157         aligned_space<scoped_lock,1> tmp;
+00158         return (new(tmp.begin()) scoped_lock)->internal_try_acquire(*this);
+00159 #else
+00160         return __TBB_TryLockByte(flag);
+00161 #endif /* TBB_USE_THREADING_TOOLS*/
+00162     }
+00163 
+00165     void unlock() {
+00166 #if TBB_USE_THREADING_TOOLS
+00167         aligned_space<scoped_lock,1> tmp;
+00168         scoped_lock& s = *tmp.begin();
+00169         s.my_mutex = this;
+00170         s.my_unlock_value = 0;
+00171         s.internal_release();
+00172 #else
+00173         __TBB_store_with_release(flag, 0);
+00174 #endif /* TBB_USE_THREADING_TOOLS */
+00175     }
+00176 
+00177     friend class scoped_lock;
+00178 };
+00179 
+00180 __TBB_DEFINE_PROFILING_SET_NAME(spin_mutex)
+00181 
+00182 } // namespace tbb
+00183 
+00184 #endif /* __TBB_spin_mutex_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00612.html b/src/tbb/doc/html/a00612.html new file mode 100644 index 0000000..19d61ed --- /dev/null +++ b/src/tbb/doc/html/a00612.html @@ -0,0 +1,216 @@ + + +spin_rw_mutex.h Source File + + + + + + +

spin_rw_mutex.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_spin_rw_mutex_H
+00022 #define __TBB_spin_rw_mutex_H
+00023 
+00024 #include "tbb_stddef.h"
+00025 #include "tbb_machine.h"
+00026 #include "tbb_profiling.h"
+00027 
+00028 namespace tbb {
+00029 
+00030 class spin_rw_mutex_v3;
+00031 typedef spin_rw_mutex_v3 spin_rw_mutex;
+00032 
+00034 
+00035 class spin_rw_mutex_v3 {
+00037 
+00039     bool __TBB_EXPORTED_METHOD internal_acquire_writer();
+00040 
+00042 
+00043     void __TBB_EXPORTED_METHOD internal_release_writer();
+00044 
+00046     void __TBB_EXPORTED_METHOD internal_acquire_reader();
+00047 
+00049     bool __TBB_EXPORTED_METHOD internal_upgrade();
+00050 
+00052 
+00053     void __TBB_EXPORTED_METHOD internal_downgrade();
+00054 
+00056     void __TBB_EXPORTED_METHOD internal_release_reader();
+00057 
+00059     bool __TBB_EXPORTED_METHOD internal_try_acquire_writer();
+00060 
+00062     bool __TBB_EXPORTED_METHOD internal_try_acquire_reader();
+00063 
+00065 public:
+00067     spin_rw_mutex_v3() : state(0) {
+00068 #if TBB_USE_THREADING_TOOLS
+00069         internal_construct();
+00070 #endif
+00071     }
+00072 
+00073 #if TBB_USE_ASSERT
+00075     ~spin_rw_mutex_v3() {
+00076         __TBB_ASSERT( !state, "destruction of an acquired mutex");
+00077     };
+00078 #endif /* TBB_USE_ASSERT */
+00079 
+00081 
+00083     class scoped_lock : internal::no_copy {
+00084     public:
+00086 
+00087         scoped_lock() : mutex(NULL), is_writer(false) {}
+00088 
+00090         scoped_lock( spin_rw_mutex& m, bool write = true ) : mutex(NULL) {
+00091             acquire(m, write);
+00092         }
+00093 
+00095         ~scoped_lock() {
+00096             if( mutex ) release();
+00097         }
+00098 
+00100         void acquire( spin_rw_mutex& m, bool write = true ) {
+00101             __TBB_ASSERT( !mutex, "holding mutex already" );
+00102             is_writer = write;
+00103             mutex = &m;
+00104             if( write ) mutex->internal_acquire_writer();
+00105             else        mutex->internal_acquire_reader();
+00106         }
+00107 
+00109 
+00110         bool upgrade_to_writer() {
+00111             __TBB_ASSERT( mutex, "lock is not acquired" );
+00112             __TBB_ASSERT( !is_writer, "not a reader" );
+00113             is_writer = true;
+00114             return mutex->internal_upgrade();
+00115         }
+00116 
+00118         void release() {
+00119             __TBB_ASSERT( mutex, "lock is not acquired" );
+00120             spin_rw_mutex *m = mutex; 
+00121             mutex = NULL;
+00122 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
+00123             if( is_writer ) m->internal_release_writer();
+00124             else            m->internal_release_reader();
+00125 #else
+00126             if( is_writer ) __TBB_AtomicAND( &m->state, READERS ); 
+00127             else            __TBB_FetchAndAddWrelease( &m->state, -(intptr_t)ONE_READER);
+00128 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */
+00129         }
+00130 
+00132         bool downgrade_to_reader() {
+00133             __TBB_ASSERT( mutex, "lock is not acquired" );
+00134             __TBB_ASSERT( is_writer, "not a writer" );
+00135 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
+00136             mutex->internal_downgrade();
+00137 #else
+00138             __TBB_FetchAndAddW( &mutex->state, ((intptr_t)ONE_READER-WRITER));
+00139 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */
+00140             is_writer = false;
+00141             return true;
+00142         }
+00143 
+00145         bool try_acquire( spin_rw_mutex& m, bool write = true ) {
+00146             __TBB_ASSERT( !mutex, "holding mutex already" );
+00147             bool result;
+00148             is_writer = write; 
+00149             result = write? m.internal_try_acquire_writer()
+00150                           : m.internal_try_acquire_reader();
+00151             if( result ) 
+00152                 mutex = &m;
+00153             return result;
+00154         }
+00155 
+00156     protected:
+00158         spin_rw_mutex* mutex;
+00159 
+00161 
+00162         bool is_writer;
+00163     };
+00164 
+00165     // Mutex traits
+00166     static const bool is_rw_mutex = true;
+00167     static const bool is_recursive_mutex = false;
+00168     static const bool is_fair_mutex = false;
+00169 
+00170     // ISO C++0x compatibility methods
+00171 
+00173     void lock() {internal_acquire_writer();}
+00174 
+00176 
+00177     bool try_lock() {return internal_try_acquire_writer();}
+00178 
+00180     void unlock() {
+00181 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
+00182         if( state&WRITER ) internal_release_writer();
+00183         else               internal_release_reader();
+00184 #else
+00185         if( state&WRITER ) __TBB_AtomicAND( &state, READERS ); 
+00186         else               __TBB_FetchAndAddWrelease( &state, -(intptr_t)ONE_READER);
+00187 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */
+00188     }
+00189 
+00190     // Methods for reader locks that resemble ISO C++0x compatibility methods.
+00191 
+00193     void lock_read() {internal_acquire_reader();}
+00194 
+00196 
+00197     bool try_lock_read() {return internal_try_acquire_reader();}
+00198 
+00199 private:
+00200     typedef intptr_t state_t;
+00201     static const state_t WRITER = 1;
+00202     static const state_t WRITER_PENDING = 2;
+00203     static const state_t READERS = ~(WRITER | WRITER_PENDING);
+00204     static const state_t ONE_READER = 4;
+00205     static const state_t BUSY = WRITER | READERS;
+00207 
+00210     state_t state;
+00211 
+00212     void __TBB_EXPORTED_METHOD internal_construct();
+00213 };
+00214 
+00215 __TBB_DEFINE_PROFILING_SET_NAME(spin_rw_mutex)
+00216 
+00217 } // namespace tbb
+00218 
+00219 #endif /* __TBB_spin_rw_mutex_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00613.html b/src/tbb/doc/html/a00613.html new file mode 100644 index 0000000..17b567e --- /dev/null +++ b/src/tbb/doc/html/a00613.html @@ -0,0 +1,733 @@ + + +task.h Source File + + + + + + +

task.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_task_H
+00022 #define __TBB_task_H
+00023 
+00024 #include "tbb_stddef.h"
+00025 #include "tbb_machine.h"
+00026 #include <climits>
+00027 
+00028 typedef struct ___itt_caller *__itt_caller;
+00029 
+00030 namespace tbb {
+00031 
+00032 class task;
+00033 class task_list;
+00034 
+00035 #if __TBB_TASK_GROUP_CONTEXT
+00036 class task_group_context;
+00037 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00038 
+00039 // MSVC does not allow taking the address of a member that was defined
+00040 // privately in task_base and made public in class task via a using declaration.
+00041 #if _MSC_VER || (__GNUC__==3 && __GNUC_MINOR__<3)
+00042 #define __TBB_TASK_BASE_ACCESS public
+00043 #else
+00044 #define __TBB_TASK_BASE_ACCESS private
+00045 #endif
+00046 
+00047 namespace internal {
+00048 
+00049     class allocate_additional_child_of_proxy: no_assign {
+00051         task* self;
+00052         task& parent;
+00053     public:
+00054         explicit allocate_additional_child_of_proxy( task& parent_ ) : self(NULL), parent(parent_) {}
+00055         task& __TBB_EXPORTED_METHOD allocate( size_t size ) const;
+00056         void __TBB_EXPORTED_METHOD free( task& ) const;
+00057     };
+00058 
+00059 }
+00060 
+00061 namespace interface5 {
+00062     namespace internal {
+00064 
+00069         class task_base: tbb::internal::no_copy {
+00070         __TBB_TASK_BASE_ACCESS:
+00071             friend class tbb::task;
+00072 
+00074             static void spawn( task& t );
+00075 
+00077             static void spawn( task_list& list );
+00078 
+00080 
+00082             static tbb::internal::allocate_additional_child_of_proxy allocate_additional_child_of( task& t ) {
+00083                 return tbb::internal::allocate_additional_child_of_proxy(t);
+00084             }
+00085 
+00087 
+00091             static void __TBB_EXPORTED_FUNC destroy( task& victim );
+00092         };
+00093     } // internal
+00094 } // interface5
+00095 
+00097 namespace internal {
+00098 
+00099     class scheduler: no_copy {
+00100     public:
+00102         virtual void spawn( task& first, task*& next ) = 0;
+00103 
+00105         virtual void wait_for_all( task& parent, task* child ) = 0;
+00106 
+00108         virtual void spawn_root_and_wait( task& first, task*& next ) = 0;
+00109 
+00111         //  Have to have it just to shut up overzealous compilation warnings
+00112         virtual ~scheduler() = 0;
+00113 
+00115         virtual void enqueue( task& t, void* reserved ) = 0;
+00116     };
+00117 
+00119 
+00120     typedef intptr_t reference_count;
+00121 
+00123     typedef unsigned short affinity_id;
+00124 
+00125 #if __TBB_TASK_GROUP_CONTEXT
+00126     class generic_scheduler;
+00127 
+00128     struct context_list_node_t {
+00129         context_list_node_t *my_prev,
+00130                             *my_next;
+00131     };
+00132 
+00133     class allocate_root_with_context_proxy: no_assign {
+00134         task_group_context& my_context;
+00135     public:
+00136         allocate_root_with_context_proxy ( task_group_context& ctx ) : my_context(ctx) {}
+00137         task& __TBB_EXPORTED_METHOD allocate( size_t size ) const;
+00138         void __TBB_EXPORTED_METHOD free( task& ) const;
+00139     };
+00140 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00141 
+00142     class allocate_root_proxy: no_assign {
+00143     public:
+00144         static task& __TBB_EXPORTED_FUNC allocate( size_t size );
+00145         static void __TBB_EXPORTED_FUNC free( task& );
+00146     };
+00147 
+00148     class allocate_continuation_proxy: no_assign {
+00149     public:
+00150         task& __TBB_EXPORTED_METHOD allocate( size_t size ) const;
+00151         void __TBB_EXPORTED_METHOD free( task& ) const;
+00152     };
+00153 
+00154     class allocate_child_proxy: no_assign {
+00155     public:
+00156         task& __TBB_EXPORTED_METHOD allocate( size_t size ) const;
+00157         void __TBB_EXPORTED_METHOD free( task& ) const;
+00158     };
+00159 
+00161 
+00172     class task_prefix {
+00173     private:
+00174         friend class tbb::task;
+00175         friend class tbb::interface5::internal::task_base;
+00176         friend class tbb::task_list;
+00177         friend class internal::scheduler;
+00178         friend class internal::allocate_root_proxy;
+00179         friend class internal::allocate_child_proxy;
+00180         friend class internal::allocate_continuation_proxy;
+00181         friend class internal::allocate_additional_child_of_proxy;
+00182 
+00183 #if __TBB_TASK_GROUP_CONTEXT
+00185 
+00188         task_group_context  *context;
+00189 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00190 
+00192 
+00197         scheduler* origin;
+00198 
+00199 #if __TBB_TASK_PRIORITY
+00200         union {
+00201 #endif /* __TBB_TASK_PRIORITY */
+00203 
+00205         scheduler* owner;
+00206 
+00207 #if __TBB_TASK_PRIORITY
+00209 
+00210         task* next_offloaded;
+00211         };
+00212 #endif /* __TBB_TASK_PRIORITY */
+00213 
+00215 
+00218         tbb::task* parent;
+00219 
+00221 
+00225         __TBB_atomic reference_count ref_count;
+00226 
+00228 
+00230         int depth;
+00231 
+00233 
+00234         unsigned char state;
+00235 
+00237 
+00243         unsigned char extra_state;
+00244 
+00245         affinity_id affinity;
+00246 
+00248         tbb::task* next;
+00249 
+00251         tbb::task& task() {return *reinterpret_cast<tbb::task*>(this+1);}
+00252     };
+00253 
+00254 } // namespace internal
+00256 
+00257 #if __TBB_TASK_GROUP_CONTEXT
+00258 
+00259 #if __TBB_TASK_PRIORITY
+00260 namespace internal {
+00261     static const int priority_stride_v4 = INT_MAX / 4;
+00262 }
+00263 
+00264 enum priority_t {
+00265     priority_normal = internal::priority_stride_v4 * 2,
+00266     priority_low = priority_normal - internal::priority_stride_v4,
+00267     priority_high = priority_normal + internal::priority_stride_v4
+00268 };
+00269 
+00270 #endif /* __TBB_TASK_PRIORITY */
+00271 
+00272 #if TBB_USE_CAPTURED_EXCEPTION
+00273     class tbb_exception;
+00274 #else
+00275     namespace internal {
+00276         class tbb_exception_ptr;
+00277     }
+00278 #endif /* !TBB_USE_CAPTURED_EXCEPTION */
+00279 
+00280 class task_scheduler_init;
+00281 
+00283 
+00303 class task_group_context : internal::no_copy {
+00304 private:
+00305     friend class internal::generic_scheduler;
+00306     friend class task_scheduler_init;
+00307 
+00308 #if TBB_USE_CAPTURED_EXCEPTION
+00309     typedef tbb_exception exception_container_type;
+00310 #else
+00311     typedef internal::tbb_exception_ptr exception_container_type;
+00312 #endif
+00313 
+00314     enum version_traits_word_layout {
+00315         traits_offset = 16,
+00316         version_mask = 0xFFFF,
+00317         traits_mask = 0xFFFFul << traits_offset
+00318     };
+00319 
+00320 public:
+00321     enum kind_type {
+00322         isolated,
+00323         bound
+00324     };
+00325 
+00326     enum traits_type {
+00327         exact_exception = 0x0001ul << traits_offset,
+00328         concurrent_wait = 0x0004ul << traits_offset,
+00329 #if TBB_USE_CAPTURED_EXCEPTION
+00330         default_traits = 0
+00331 #else
+00332         default_traits = exact_exception
+00333 #endif /* !TBB_USE_CAPTURED_EXCEPTION */
+00334     };
+00335 
+00336 private:
+00337     enum state {
+00338         may_have_children = 1
+00339     };
+00340 
+00341     union {
+00343         kind_type my_kind;
+00344         uintptr_t _my_kind_aligner;
+00345     };
+00346 
+00348     task_group_context *my_parent;
+00349 
+00351 
+00353     internal::context_list_node_t my_node;
+00354 
+00356     __itt_caller itt_caller;
+00357 
+00359 
+00362     char _leading_padding[internal::NFS_MaxLineSize
+00363                           - 2 * sizeof(uintptr_t)- sizeof(void*) - sizeof(internal::context_list_node_t)
+00364                           - sizeof(__itt_caller)];
+00365 
+00367     uintptr_t my_cancellation_requested;
+00368 
+00370 
+00373     uintptr_t  my_version_and_traits;
+00374 
+00376     exception_container_type *my_exception;
+00377 
+00379     internal::generic_scheduler *my_owner;
+00380 
+00382     uintptr_t my_state;
+00383 
+00384 #if __TBB_TASK_PRIORITY
+00386     intptr_t my_priority;
+00387 #endif /* __TBB_TASK_PRIORITY */
+00388 
+00390 
+00391     char _trailing_padding[internal::NFS_MaxLineSize - 2 * sizeof(uintptr_t) - 2 * sizeof(void*)
+00392 #if __TBB_TASK_PRIORITY
+00393                             - sizeof(intptr_t)
+00394 #endif /* __TBB_TASK_PRIORITY */
+00395                           ];
+00396 
+00397 public:
+00399 
+00427     task_group_context ( kind_type relation_with_parent = bound,
+00428                          uintptr_t traits = default_traits )
+00429         : my_kind(relation_with_parent)
+00430         , my_version_and_traits(1 | traits)
+00431     {
+00432         init();
+00433     }
+00434 
+00435     __TBB_EXPORTED_METHOD ~task_group_context ();
+00436 
+00438 
+00445     void __TBB_EXPORTED_METHOD reset ();
+00446 
+00448 
+00455     bool __TBB_EXPORTED_METHOD cancel_group_execution ();
+00456 
+00458     bool __TBB_EXPORTED_METHOD is_group_execution_cancelled () const;
+00459 
+00461 
+00467     void __TBB_EXPORTED_METHOD register_pending_exception ();
+00468 
+00469 #if __TBB_TASK_PRIORITY
+00471     void set_priority ( priority_t );
+00472 
+00474     priority_t priority () const;
+00475 #endif /* __TBB_TASK_PRIORITY */
+00476 
+00477 protected:
+00479 
+00480     void __TBB_EXPORTED_METHOD init ();
+00481 
+00482 private:
+00483     friend class task;
+00484     friend class internal::allocate_root_with_context_proxy;
+00485 
+00486     static const kind_type binding_required = bound;
+00487     static const kind_type binding_completed = kind_type(bound+1);
+00488     static const kind_type detached = kind_type(binding_completed+1);
+00489     static const kind_type dying = kind_type(detached+1);
+00490 
+00492 
+00494     template <typename T>
+00495     void propagate_state_from_ancestors ( T task_group_context::*mptr_state, T new_state );
+00496 
+00498     inline void finish_initialization ( internal::generic_scheduler *local_sched );
+00499 
+00501     void bind_to ( internal::generic_scheduler *local_sched );
+00502 
+00504     void register_with ( internal::generic_scheduler *local_sched );
+00505 
+00506 }; // class task_group_context
+00507 
+00508 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00509 
+00511 
+00512 class task: __TBB_TASK_BASE_ACCESS interface5::internal::task_base {
+00513 
+00515     void __TBB_EXPORTED_METHOD internal_set_ref_count( int count );
+00516 
+00518     internal::reference_count __TBB_EXPORTED_METHOD internal_decrement_ref_count();
+00519 
+00520 protected:
+00522     task() {prefix().extra_state=1;}
+00523 
+00524 public:
+00526     virtual ~task() {}
+00527 
+00529     virtual task* execute() = 0;
+00530 
+00532     enum state_type {
+00534         executing,
+00536         reexecute,
+00538         ready,
+00540         allocated,
+00542         freed,
+00544         recycle
+00545     };
+00546 
+00547     //------------------------------------------------------------------------
+00548     // Allocating tasks
+00549     //------------------------------------------------------------------------
+00550 
+00552     static internal::allocate_root_proxy allocate_root() {
+00553         return internal::allocate_root_proxy();
+00554     }
+00555 
+00556 #if __TBB_TASK_GROUP_CONTEXT
+00558     static internal::allocate_root_with_context_proxy allocate_root( task_group_context& ctx ) {
+00559         return internal::allocate_root_with_context_proxy(ctx);
+00560     }
+00561 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00562 
+00564 
+00565     internal::allocate_continuation_proxy& allocate_continuation() {
+00566         return *reinterpret_cast<internal::allocate_continuation_proxy*>(this);
+00567     }
+00568 
+00570     internal::allocate_child_proxy& allocate_child() {
+00571         return *reinterpret_cast<internal::allocate_child_proxy*>(this);
+00572     }
+00573 
+00575     using task_base::allocate_additional_child_of;
+00576 
+00577 #if __TBB_DEPRECATED_TASK_INTERFACE
+00579 
+00583     void __TBB_EXPORTED_METHOD destroy( task& t );
+00584 #else /* !__TBB_DEPRECATED_TASK_INTERFACE */
+00586     using task_base::destroy;
+00587 #endif /* !__TBB_DEPRECATED_TASK_INTERFACE */
+00588 
+00589     //------------------------------------------------------------------------
+00590     // Recycling of tasks
+00591     //------------------------------------------------------------------------
+00592 
+00594 
+00600     void recycle_as_continuation() {
+00601         __TBB_ASSERT( prefix().state==executing, "execute not running?" );
+00602         prefix().state = allocated;
+00603     }
+00604 
+00606 
+00608     void recycle_as_safe_continuation() {
+00609         __TBB_ASSERT( prefix().state==executing, "execute not running?" );
+00610         prefix().state = recycle;
+00611     }
+00612 
+00614     void recycle_as_child_of( task& new_parent ) {
+00615         internal::task_prefix& p = prefix();
+00616         __TBB_ASSERT( prefix().state==executing||prefix().state==allocated, "execute not running, or already recycled" );
+00617         __TBB_ASSERT( prefix().ref_count==0, "no child tasks allowed when recycled as a child" );
+00618         __TBB_ASSERT( p.parent==NULL, "parent must be null" );
+00619         __TBB_ASSERT( new_parent.prefix().state<=recycle, "corrupt parent's state" );
+00620         __TBB_ASSERT( new_parent.prefix().state!=freed, "parent already freed" );
+00621         p.state = allocated;
+00622         p.parent = &new_parent;
+00623 #if __TBB_TASK_GROUP_CONTEXT
+00624         p.context = new_parent.prefix().context;
+00625 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00626     }
+00627 
+00629 
+00630     void recycle_to_reexecute() {
+00631         __TBB_ASSERT( prefix().state==executing, "execute not running, or already recycled" );
+00632         __TBB_ASSERT( prefix().ref_count==0, "no child tasks allowed when recycled for reexecution" );
+00633         prefix().state = reexecute;
+00634     }
+00635 
+00636     // All depth-related methods are obsolete, and are retained for the sake
+00637     // of backward source compatibility only
+00638     intptr_t depth() const {return 0;}
+00639     void set_depth( intptr_t ) {}
+00640     void add_to_depth( int ) {}
+00641 
+00642 
+00643     //------------------------------------------------------------------------
+00644     // Spawning and blocking
+00645     //------------------------------------------------------------------------
+00646 
+00648     void set_ref_count( int count ) {
+00649 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
+00650         internal_set_ref_count(count);
+00651 #else
+00652         prefix().ref_count = count;
+00653 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */
+00654     }
+00655 
+00657 
+00658     void increment_ref_count() {
+00659         __TBB_FetchAndIncrementWacquire( &prefix().ref_count );
+00660     }
+00661 
+00663 
+00664     int decrement_ref_count() {
+00665 #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
+00666         return int(internal_decrement_ref_count());
+00667 #else
+00668         return int(__TBB_FetchAndDecrementWrelease( &prefix().ref_count ))-1;
+00669 #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */
+00670     }
+00671 
+00673     using task_base::spawn;
+00674 
+00676     void spawn_and_wait_for_all( task& child ) {
+00677         prefix().owner->wait_for_all( *this, &child );
+00678     }
+00679 
+00681     void __TBB_EXPORTED_METHOD spawn_and_wait_for_all( task_list& list );
+00682 
+00684     static void spawn_root_and_wait( task& root ) {
+00685         root.prefix().owner->spawn_root_and_wait( root, root.prefix().next );
+00686     }
+00687 
+00689 
+00691     static void spawn_root_and_wait( task_list& root_list );
+00692 
+00694 
+00695     void wait_for_all() {
+00696         prefix().owner->wait_for_all( *this, NULL );
+00697     }
+00698 
+00700 #if __TBB_TASK_PRIORITY
+00701 
+00711 #endif /* __TBB_TASK_PRIORITY */
+00712     static void enqueue( task& t ) {
+00713         t.prefix().owner->enqueue( t, NULL );
+00714     }
+00715 
+00716 #if __TBB_TASK_PRIORITY
+00718     static void enqueue( task& t, priority_t p ) {
+00719         __TBB_ASSERT( p == priority_low || p == priority_normal || p == priority_high, "Invalid priority level value" );
+00720         t.prefix().owner->enqueue( t, (void*)p );
+00721     }
+00722 #endif /* __TBB_TASK_PRIORITY */
+00723 
+00725     static task& __TBB_EXPORTED_FUNC self();
+00726 
+00728     task* parent() const {return prefix().parent;}
+00729 
+00731     void set_parent(task* p) {
+00732 #if __TBB_TASK_GROUP_CONTEXT
+00733         __TBB_ASSERT(prefix().context == p->prefix().context, "The tasks must be in the same context");
+00734 #endif
+00735         prefix().parent = p;
+00736     }
+00737 
+00738 #if __TBB_TASK_GROUP_CONTEXT
+00740 
+00741     task_group_context* context() {return prefix().context;}
+00742 
+00744     task_group_context* group () { return prefix().context; }
+00745 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00746 
+00748     bool is_stolen_task() const {
+00749         return (prefix().extra_state & 0x80)!=0;
+00750     }
+00751 
+00752     //------------------------------------------------------------------------
+00753     // Debugging
+00754     //------------------------------------------------------------------------
+00755 
+00757     state_type state() const {return state_type(prefix().state);}
+00758 
+00760     int ref_count() const {
+00761 #if TBB_USE_ASSERT
+00762         internal::reference_count ref_count_ = prefix().ref_count;
+00763         __TBB_ASSERT( ref_count_==int(ref_count_), "integer overflow error");
+00764 #endif
+00765         return int(prefix().ref_count);
+00766     }
+00767 
+00769     bool __TBB_EXPORTED_METHOD is_owned_by_current_thread() const;
+00770 
+00771     //------------------------------------------------------------------------
+00772     // Affinity
+00773     //------------------------------------------------------------------------
+00774 
+00776 
+00777     typedef internal::affinity_id affinity_id;
+00778 
+00780     void set_affinity( affinity_id id ) {prefix().affinity = id;}
+00781 
+00783     affinity_id affinity() const {return prefix().affinity;}
+00784 
+00786 
+00790     virtual void __TBB_EXPORTED_METHOD note_affinity( affinity_id id );
+00791 
+00792 #if __TBB_TASK_GROUP_CONTEXT
+00794 
+00804     void __TBB_EXPORTED_METHOD change_group ( task_group_context& ctx );
+00805 
+00807 
+00808     bool cancel_group_execution () { return prefix().context->cancel_group_execution(); }
+00809 
+00811     bool is_cancelled () const { return prefix().context->is_group_execution_cancelled(); }
+00812 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00813 
+00814 #if __TBB_TASK_PRIORITY
+00816     void set_group_priority ( priority_t p ) {  prefix().context->set_priority(p); }
+00817 
+00819     priority_t group_priority () const { return prefix().context->priority(); }
+00820 
+00821 #endif /* __TBB_TASK_PRIORITY */
+00822 
+00823 private:
+00824     friend class interface5::internal::task_base;
+00825     friend class task_list;
+00826     friend class internal::scheduler;
+00827     friend class internal::allocate_root_proxy;
+00828 #if __TBB_TASK_GROUP_CONTEXT
+00829     friend class internal::allocate_root_with_context_proxy;
+00830 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00831     friend class internal::allocate_continuation_proxy;
+00832     friend class internal::allocate_child_proxy;
+00833     friend class internal::allocate_additional_child_of_proxy;
+00834 
+00836 
+00837     internal::task_prefix& prefix( internal::version_tag* = NULL ) const {
+00838         return reinterpret_cast<internal::task_prefix*>(const_cast<task*>(this))[-1];
+00839     }
+00840 }; // class task
+00841 
+00843 
+00844 class empty_task: public task {
+00845     /*override*/ task* execute() {
+00846         return NULL;
+00847     }
+00848 };
+00849 
+00851 
+00853 class task_list: internal::no_copy {
+00854 private:
+00855     task* first;
+00856     task** next_ptr;
+00857     friend class task;
+00858     friend class interface5::internal::task_base;
+00859 public:
+00861     task_list() : first(NULL), next_ptr(&first) {}
+00862 
+00864     ~task_list() {}
+00865 
+00867     bool empty() const {return !first;}
+00868 
+00870     void push_back( task& task ) {
+00871         task.prefix().next = NULL;
+00872         *next_ptr = &task;
+00873         next_ptr = &task.prefix().next;
+00874     }
+00875 
+00877     task& pop_front() {
+00878         __TBB_ASSERT( !empty(), "attempt to pop item from empty task_list" );
+00879         task* result = first;
+00880         first = result->prefix().next;
+00881         if( !first ) next_ptr = &first;
+00882         return *result;
+00883     }
+00884 
+00886     void clear() {
+00887         first=NULL;
+00888         next_ptr=&first;
+00889     }
+00890 };
+00891 
+00892 inline void interface5::internal::task_base::spawn( task& t ) {
+00893     t.prefix().owner->spawn( t, t.prefix().next );
+00894 }
+00895 
+00896 inline void interface5::internal::task_base::spawn( task_list& list ) {
+00897     if( task* t = list.first ) {
+00898         t->prefix().owner->spawn( *t, *list.next_ptr );
+00899         list.clear();
+00900     }
+00901 }
+00902 
+00903 inline void task::spawn_root_and_wait( task_list& root_list ) {
+00904     if( task* t = root_list.first ) {
+00905         t->prefix().owner->spawn_root_and_wait( *t, *root_list.next_ptr );
+00906         root_list.clear();
+00907     }
+00908 }
+00909 
+00910 } // namespace tbb
+00911 
+00912 inline void *operator new( size_t bytes, const tbb::internal::allocate_root_proxy& ) {
+00913     return &tbb::internal::allocate_root_proxy::allocate(bytes);
+00914 }
+00915 
+00916 inline void operator delete( void* task, const tbb::internal::allocate_root_proxy& ) {
+00917     tbb::internal::allocate_root_proxy::free( *static_cast<tbb::task*>(task) );
+00918 }
+00919 
+00920 #if __TBB_TASK_GROUP_CONTEXT
+00921 inline void *operator new( size_t bytes, const tbb::internal::allocate_root_with_context_proxy& p ) {
+00922     return &p.allocate(bytes);
+00923 }
+00924 
+00925 inline void operator delete( void* task, const tbb::internal::allocate_root_with_context_proxy& p ) {
+00926     p.free( *static_cast<tbb::task*>(task) );
+00927 }
+00928 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00929 
+00930 inline void *operator new( size_t bytes, const tbb::internal::allocate_continuation_proxy& p ) {
+00931     return &p.allocate(bytes);
+00932 }
+00933 
+00934 inline void operator delete( void* task, const tbb::internal::allocate_continuation_proxy& p ) {
+00935     p.free( *static_cast<tbb::task*>(task) );
+00936 }
+00937 
+00938 inline void *operator new( size_t bytes, const tbb::internal::allocate_child_proxy& p ) {
+00939     return &p.allocate(bytes);
+00940 }
+00941 
+00942 inline void operator delete( void* task, const tbb::internal::allocate_child_proxy& p ) {
+00943     p.free( *static_cast<tbb::task*>(task) );
+00944 }
+00945 
+00946 inline void *operator new( size_t bytes, const tbb::internal::allocate_additional_child_of_proxy& p ) {
+00947     return &p.allocate(bytes);
+00948 }
+00949 
+00950 inline void operator delete( void* task, const tbb::internal::allocate_additional_child_of_proxy& p ) {
+00951     p.free( *static_cast<tbb::task*>(task) );
+00952 }
+00953 
+00954 #endif /* __TBB_task_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00623.html b/src/tbb/doc/html/a00623.html new file mode 100644 index 0000000..4cb6f36 --- /dev/null +++ b/src/tbb/doc/html/a00623.html @@ -0,0 +1,274 @@ + + +task_group.h Source File + + + + + + +

task_group.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_task_group_H
+00022 #define __TBB_task_group_H
+00023 
+00024 #include "task.h"
+00025 #include "tbb_exception.h"
+00026 
+00027 #if __TBB_TASK_GROUP_CONTEXT
+00028 
+00029 namespace tbb {
+00030 
+00031 namespace internal {
+00032     template<typename F> class task_handle_task;
+00033 }
+00034 
+00035 template<typename F>
+00036 class task_handle : internal::no_assign {
+00037     template<typename _F> friend class internal::task_handle_task;
+00038 
+00039     static const intptr_t scheduled = 0x1;
+00040 
+00041     F my_func;
+00042     intptr_t my_state;
+00043 
+00044     void mark_scheduled () {
+00045         // The check here is intentionally lax to avoid the impact of interlocked operation
+00046         if ( my_state & scheduled )
+00047             internal::throw_exception( internal::eid_invalid_multiple_scheduling );
+00048         my_state |= scheduled;
+00049     }
+00050 public:
+00051     task_handle( const F& f ) : my_func(f), my_state(0) {}
+00052 
+00053     void operator() () const { my_func(); }
+00054 };
+00055 
+00056 enum task_group_status {
+00057     not_complete,
+00058     complete,
+00059     canceled
+00060 };
+00061 
+00062 namespace internal {
+00063 
+00064 // Suppress gratuitous warnings from icc 11.0 when lambda expressions are used in instances of function_task.
+00065 //#pragma warning(disable: 588)
+00066 
+00067 template<typename F>
+00068 class function_task : public task {
+00069     F my_func;
+00070     /*override*/ task* execute() {
+00071         my_func();
+00072         return NULL;
+00073     }
+00074 public:
+00075     function_task( const F& f ) : my_func(f) {}
+00076 };
+00077 
+00078 template<typename F>
+00079 class task_handle_task : public task {
+00080     task_handle<F>& my_handle;
+00081     /*override*/ task* execute() {
+00082         my_handle();
+00083         return NULL;
+00084     }
+00085 public:
+00086     task_handle_task( task_handle<F>& h ) : my_handle(h) { h.mark_scheduled(); }
+00087 };
+00088 
+00089 class task_group_base : internal::no_copy {
+00090 protected:
+00091     empty_task* my_root;
+00092     task_group_context my_context;
+00093 
+00094     task& owner () { return *my_root; }
+00095 
+00096     template<typename F>
+00097     task_group_status internal_run_and_wait( F& f ) {
+00098         __TBB_TRY {
+00099             if ( !my_context.is_group_execution_cancelled() )
+00100                 f();
+00101         } __TBB_CATCH( ... ) {
+00102             my_context.register_pending_exception();
+00103         }
+00104         return wait();
+00105     }
+00106 
+00107     template<typename F, typename Task>
+00108     void internal_run( F& f ) {
+00109         owner().spawn( *new( owner().allocate_additional_child_of(*my_root) ) Task(f) );
+00110     }
+00111 
+00112 public:
+00113     task_group_base( uintptr_t traits = 0 )
+00114         : my_context(task_group_context::bound, task_group_context::default_traits | traits)
+00115     {
+00116         my_root = new( task::allocate_root(my_context) ) empty_task;
+00117         my_root->set_ref_count(1);
+00118     }
+00119 
+00120     ~task_group_base() {
+00121         if( my_root->ref_count() > 1 ) {
+00122             bool stack_unwinding_in_progress = std::uncaught_exception();
+00123             // Always attempt to do proper cleanup to avoid inevitable memory corruption 
+00124             // in case of missing wait (for the sake of better testability & debuggability)
+00125             if ( !is_canceling() )
+00126                 cancel();
+00127             __TBB_TRY {
+00128                 my_root->wait_for_all();
+00129             } __TBB_CATCH (...) {
+00130                 task::destroy(*my_root);
+00131                 __TBB_RETHROW();
+00132             }
+00133             task::destroy(*my_root);
+00134             if ( !stack_unwinding_in_progress )
+00135                 internal::throw_exception( internal::eid_missing_wait );
+00136         }
+00137         else {
+00138             task::destroy(*my_root);
+00139         }
+00140     }
+00141 
+00142     template<typename F>
+00143     void run( task_handle<F>& h ) {
+00144         internal_run< task_handle<F>, internal::task_handle_task<F> >( h );
+00145     }
+00146 
+00147     task_group_status wait() {
+00148         __TBB_TRY {
+00149             my_root->wait_for_all();
+00150         } __TBB_CATCH( ... ) {
+00151             my_context.reset();
+00152             __TBB_RETHROW();
+00153         }
+00154         if ( my_context.is_group_execution_cancelled() ) {
+00155             my_context.reset();
+00156             return canceled;
+00157         }
+00158         return complete;
+00159     }
+00160 
+00161     bool is_canceling() {
+00162         return my_context.is_group_execution_cancelled();
+00163     }
+00164 
+00165     void cancel() {
+00166         my_context.cancel_group_execution();
+00167     }
+00168 }; // class task_group_base
+00169 
+00170 } // namespace internal
+00171 
+00172 class task_group : public internal::task_group_base {
+00173 public:
+00174     task_group () : task_group_base( task_group_context::concurrent_wait ) {}
+00175 
+00176 #if TBB_DEPRECATED
+00177     ~task_group() __TBB_TRY {
+00178         __TBB_ASSERT( my_root->ref_count() != 0, NULL );
+00179         if( my_root->ref_count() > 1 )
+00180             my_root->wait_for_all();
+00181     }
+00182 #if TBB_USE_EXCEPTIONS
+00183     catch (...) {
+00184         // Have to destroy my_root here as the base class destructor won't be called
+00185         task::destroy(*my_root);
+00186         throw;
+00187     }
+00188 #endif /* TBB_USE_EXCEPTIONS */
+00189 #endif /* TBB_DEPRECATED */
+00190 
+00191 #if __SUNPRO_CC
+00192     template<typename F>
+00193     void run( task_handle<F>& h ) {
+00194         internal_run< task_handle<F>, internal::task_handle_task<F> >( h );
+00195     }
+00196 #else
+00197     using task_group_base::run;
+00198 #endif
+00199 
+00200     template<typename F>
+00201     void run( const F& f ) {
+00202         internal_run< const F, internal::function_task<F> >( f );
+00203     }
+00204 
+00205     template<typename F>
+00206     task_group_status run_and_wait( const F& f ) {
+00207         return internal_run_and_wait<const F>( f );
+00208     }
+00209 
+00210     template<typename F>
+00211     task_group_status run_and_wait( task_handle<F>& h ) {
+00212       return internal_run_and_wait< task_handle<F> >( h );
+00213     }
+00214 }; // class task_group
+00215 
+00216 class structured_task_group : public internal::task_group_base {
+00217 public:
+00218     template<typename F>
+00219     task_group_status run_and_wait ( task_handle<F>& h ) {
+00220         return internal_run_and_wait< task_handle<F> >( h );
+00221     }
+00222 
+00223     task_group_status wait() {
+00224         task_group_status res = task_group_base::wait();
+00225         my_root->set_ref_count(1);
+00226         return res;
+00227     }
+00228 }; // class structured_task_group
+00229 
+00230 inline 
+00231 bool is_current_task_group_canceling() {
+00232     return task::self().is_cancelled();
+00233 }
+00234 
+00235 template<class F>
+00236 task_handle<F> make_task( const F& f ) {
+00237     return task_handle<F>( f );
+00238 }
+00239 
+00240 } // namespace tbb
+00241 
+00242 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00243 
+00244 #endif /* __TBB_task_group_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00630.html b/src/tbb/doc/html/a00630.html new file mode 100644 index 0000000..5fe9a9e --- /dev/null +++ b/src/tbb/doc/html/a00630.html @@ -0,0 +1,117 @@ + + +task_scheduler_init.h Source File + + + + + + +

task_scheduler_init.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_task_scheduler_init_H
+00022 #define __TBB_task_scheduler_init_H
+00023 
+00024 #include "tbb_stddef.h"
+00025 #include "limits.h"
+00026 
+00027 namespace tbb {
+00028 
+00029 typedef std::size_t stack_size_type;
+00030 
+00032 namespace internal {
+00034 
+00035     class scheduler;
+00036 } // namespace internal
+00038 
+00040 
+00053 class task_scheduler_init: internal::no_copy {
+00054     enum ExceptionPropagationMode {
+00055         propagation_mode_exact = 1u,
+00056         propagation_mode_captured = 2u,
+00057         propagation_mode_mask = propagation_mode_exact | propagation_mode_captured
+00058     };
+00059 
+00061     internal::scheduler* my_scheduler;
+00062 public:
+00063 
+00065     static const int automatic = -1;
+00066 
+00068     static const int deferred = -2;
+00069 
+00071 
+00082     void __TBB_EXPORTED_METHOD initialize( int number_of_threads=automatic );
+00083 
+00085 
+00086     void __TBB_EXPORTED_METHOD initialize( int number_of_threads, stack_size_type thread_stack_size );
+00087 
+00089     void __TBB_EXPORTED_METHOD terminate();
+00090 
+00092     task_scheduler_init( int number_of_threads=automatic, stack_size_type thread_stack_size=0 ) : my_scheduler(NULL)  {
+00093         // Two lowest order bits of the stack size argument may be taken to communicate
+00094         // default exception propagation mode of the client to be used when the
+00095         // client manually creates tasks in the master thread and does not use
+00096         // explicit task group context object. This is necessary because newer 
+00097         // TBB binaries with exact propagation enabled by default may be used 
+00098         // by older clients that expect tbb::captured_exception wrapper.
+00099         // All zeros mean old client - no preference. 
+00100         __TBB_ASSERT( !(thread_stack_size & propagation_mode_mask), "Requested stack size is not aligned" );
+00101 #if TBB_USE_EXCEPTIONS
+00102         thread_stack_size |= TBB_USE_CAPTURED_EXCEPTION ? propagation_mode_captured : propagation_mode_exact;
+00103 #endif /* TBB_USE_EXCEPTIONS */
+00104         initialize( number_of_threads, thread_stack_size );
+00105     }
+00106 
+00108     ~task_scheduler_init() {
+00109         if( my_scheduler ) 
+00110             terminate();
+00111         internal::poison_pointer( my_scheduler );
+00112     }
+00114 
+00131     static int __TBB_EXPORTED_FUNC default_num_threads ();
+00132 
+00134     bool is_active() const { return my_scheduler != NULL; }
+00135 };
+00136 
+00137 } // namespace tbb
+00138 
+00139 #endif /* __TBB_task_scheduler_init_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00631.html b/src/tbb/doc/html/a00631.html new file mode 100644 index 0000000..e4b06b7 --- /dev/null +++ b/src/tbb/doc/html/a00631.html @@ -0,0 +1,90 @@ + + +task_scheduler_observer.h Source File + + + + + + +

task_scheduler_observer.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_task_scheduler_observer_H
+00022 #define __TBB_task_scheduler_observer_H
+00023 
+00024 #include "atomic.h"
+00025 
+00026 #if __TBB_SCHEDULER_OBSERVER
+00027 
+00028 namespace tbb {
+00029 
+00030 namespace internal {
+00031 
+00032 class observer_proxy;
+00033 
+00034 class task_scheduler_observer_v3 {
+00035     friend class observer_proxy;
+00036     observer_proxy* my_proxy;
+00037     atomic<intptr_t> my_busy_count;
+00038 public:
+00040     void __TBB_EXPORTED_METHOD observe( bool state=true );
+00041 
+00043     bool is_observing() const {return my_proxy!=NULL;}
+00044 
+00046     task_scheduler_observer_v3() : my_proxy(NULL) {my_busy_count=0;}
+00047 
+00049     virtual void on_scheduler_entry( bool /*is_worker*/ ) {} 
+00050 
+00052     virtual void on_scheduler_exit( bool /*is_worker*/ ) {}
+00053 
+00055     virtual ~task_scheduler_observer_v3() {observe(false);}
+00056 };
+00057 
+00058 } // namespace internal
+00059 
+00060 typedef internal::task_scheduler_observer_v3 task_scheduler_observer;
+00061 
+00062 } // namespace tbb
+00063 
+00064 #endif /* __TBB_SCHEDULER_OBSERVER */
+00065 
+00066 #endif /* __TBB_task_scheduler_observer_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00633.html b/src/tbb/doc/html/a00633.html new file mode 100644 index 0000000..0415691 --- /dev/null +++ b/src/tbb/doc/html/a00633.html @@ -0,0 +1,98 @@ + + +tbb.h Source File + + + + + + +

tbb.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_tbb_H
+00022 #define __TBB_tbb_H
+00023 
+00032 #if TBB_PREVIEW_AGGREGATOR
+00033 #include "aggregator.h"
+00034 #endif
+00035 #include "aligned_space.h"
+00036 #include "atomic.h"
+00037 #include "blocked_range.h"
+00038 #include "blocked_range2d.h"
+00039 #include "blocked_range3d.h"
+00040 #include "cache_aligned_allocator.h"
+00041 #include "combinable.h"
+00042 #include "concurrent_unordered_map.h"
+00043 #include "concurrent_hash_map.h"
+00044 #include "concurrent_queue.h"
+00045 #include "concurrent_vector.h"
+00046 #include "critical_section.h"
+00047 #include "enumerable_thread_specific.h"
+00048 #include "mutex.h"
+00049 #include "null_mutex.h"
+00050 #include "null_rw_mutex.h"
+00051 #include "parallel_do.h"
+00052 #include "parallel_for.h"
+00053 #include "parallel_for_each.h"
+00054 #include "parallel_invoke.h"
+00055 #include "parallel_reduce.h"
+00056 #include "parallel_scan.h"
+00057 #include "parallel_sort.h"
+00058 #include "partitioner.h"
+00059 #include "pipeline.h"
+00060 #include "queuing_mutex.h"
+00061 #include "queuing_rw_mutex.h"
+00062 #include "reader_writer_lock.h"
+00063 #include "concurrent_priority_queue.h"
+00064 #include "recursive_mutex.h"
+00065 #include "spin_mutex.h"
+00066 #include "spin_rw_mutex.h"
+00067 #include "task.h"
+00068 #include "task_group.h"
+00069 #include "task_scheduler_init.h"
+00070 #include "task_scheduler_observer.h"
+00071 #include "tbb_allocator.h"
+00072 #include "tbb_exception.h"
+00073 #include "tbb_thread.h"
+00074 #include "tick_count.h"
+00075 
+00076 #endif /* __TBB_tbb_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00634.html b/src/tbb/doc/html/a00634.html new file mode 100644 index 0000000..db5d1fc --- /dev/null +++ b/src/tbb/doc/html/a00634.html @@ -0,0 +1,225 @@ + + +tbb_allocator.h Source File + + + + + + +

tbb_allocator.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_tbb_allocator_H
+00022 #define __TBB_tbb_allocator_H
+00023 
+00024 #include "tbb_stddef.h"
+00025 #include <new>
+00026 #if __TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_CPP11_STD_FORWARD_BROKEN
+00027  #include <utility> // std::forward
+00028 #endif
+00029 
+00030 #if !TBB_USE_EXCEPTIONS && _MSC_VER
+00031     // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers
+00032     #pragma warning (push)
+00033     #pragma warning (disable: 4530)
+00034 #endif
+00035 
+00036 #include <cstring>
+00037 
+00038 #if !TBB_USE_EXCEPTIONS && _MSC_VER
+00039     #pragma warning (pop)
+00040 #endif
+00041 
+00042 namespace tbb {
+00043 
+00045 namespace internal {
+00046 
+00048 
+00049     void __TBB_EXPORTED_FUNC deallocate_via_handler_v3( void *p );
+00050 
+00052 
+00053     void* __TBB_EXPORTED_FUNC allocate_via_handler_v3( size_t n );
+00054 
+00056     bool __TBB_EXPORTED_FUNC is_malloc_used_v3();
+00057 }
+00059 
+00060 #if _MSC_VER && !defined(__INTEL_COMPILER)
+00061     // Workaround for erroneous "unreferenced parameter" warning in method destroy.
+00062     #pragma warning (push)
+00063     #pragma warning (disable: 4100)
+00064 #endif
+00065 
+00067 
+00072 template<typename T>
+00073 class tbb_allocator {
+00074 public:
+00075     typedef typename internal::allocator_type<T>::value_type value_type;
+00076     typedef value_type* pointer;
+00077     typedef const value_type* const_pointer;
+00078     typedef value_type& reference;
+00079     typedef const value_type& const_reference;
+00080     typedef size_t size_type;
+00081     typedef ptrdiff_t difference_type;
+00082     template<typename U> struct rebind {
+00083         typedef tbb_allocator<U> other;
+00084     };
+00085 
+00087     enum malloc_type {
+00088         scalable, 
+00089         standard
+00090     };
+00091 
+00092     tbb_allocator() throw() {}
+00093     tbb_allocator( const tbb_allocator& ) throw() {}
+00094     template<typename U> tbb_allocator(const tbb_allocator<U>&) throw() {}
+00095 
+00096     pointer address(reference x) const {return &x;}
+00097     const_pointer address(const_reference x) const {return &x;}
+00098     
+00100     pointer allocate( size_type n, const void* /*hint*/ = 0) {
+00101         return pointer(internal::allocate_via_handler_v3( n * sizeof(value_type) ));
+00102     }
+00103 
+00105     void deallocate( pointer p, size_type ) {
+00106         internal::deallocate_via_handler_v3(p);        
+00107     }
+00108 
+00110     size_type max_size() const throw() {
+00111         size_type max = static_cast<size_type>(-1) / sizeof (value_type);
+00112         return (max > 0 ? max : 1);
+00113     }
+00114     
+00116 #if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT
+00117     template<typename... Args>
+00118     void construct(pointer p, Args&&... args)
+00119  #if __TBB_CPP11_STD_FORWARD_BROKEN
+00120         { ::new((void *)p) T((args)...); }
+00121  #else
+00122         { ::new((void *)p) T(std::forward<Args>(args)...); }
+00123  #endif
+00124 #else // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT
+00125     void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);}
+00126 #endif // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT
+00127 
+00129     void destroy( pointer p ) {p->~value_type();}
+00130 
+00132     static malloc_type allocator_type() {
+00133         return internal::is_malloc_used_v3() ? standard : scalable;
+00134     }
+00135 };
+00136 
+00137 #if _MSC_VER && !defined(__INTEL_COMPILER)
+00138     #pragma warning (pop)
+00139 #endif // warning 4100 is back
+00140 
+00142 
+00143 template<> 
+00144 class tbb_allocator<void> {
+00145 public:
+00146     typedef void* pointer;
+00147     typedef const void* const_pointer;
+00148     typedef void value_type;
+00149     template<typename U> struct rebind {
+00150         typedef tbb_allocator<U> other;
+00151     };
+00152 };
+00153 
+00154 template<typename T, typename U>
+00155 inline bool operator==( const tbb_allocator<T>&, const tbb_allocator<U>& ) {return true;}
+00156 
+00157 template<typename T, typename U>
+00158 inline bool operator!=( const tbb_allocator<T>&, const tbb_allocator<U>& ) {return false;}
+00159 
+00161 
+00166 template <typename T, template<typename X> class Allocator = tbb_allocator>
+00167 class zero_allocator : public Allocator<T>
+00168 {
+00169 public:
+00170     typedef Allocator<T> base_allocator_type;
+00171     typedef typename base_allocator_type::value_type value_type;
+00172     typedef typename base_allocator_type::pointer pointer;
+00173     typedef typename base_allocator_type::const_pointer const_pointer;
+00174     typedef typename base_allocator_type::reference reference;
+00175     typedef typename base_allocator_type::const_reference const_reference;
+00176     typedef typename base_allocator_type::size_type size_type;
+00177     typedef typename base_allocator_type::difference_type difference_type;
+00178     template<typename U> struct rebind {
+00179         typedef zero_allocator<U, Allocator> other;
+00180     };
+00181 
+00182     zero_allocator() throw() { }
+00183     zero_allocator(const zero_allocator &a) throw() : base_allocator_type( a ) { }
+00184     template<typename U>
+00185     zero_allocator(const zero_allocator<U> &a) throw() : base_allocator_type( Allocator<U>( a ) ) { }
+00186 
+00187     pointer allocate(const size_type n, const void *hint = 0 ) {
+00188         pointer ptr = base_allocator_type::allocate( n, hint );
+00189         std::memset( ptr, 0, n * sizeof(value_type) );
+00190         return ptr;
+00191     }
+00192 };
+00193 
+00195 
+00196 template<template<typename T> class Allocator> 
+00197 class zero_allocator<void, Allocator> : public Allocator<void> {
+00198 public:
+00199     typedef Allocator<void> base_allocator_type;
+00200     typedef typename base_allocator_type::value_type value_type;
+00201     typedef typename base_allocator_type::pointer pointer;
+00202     typedef typename base_allocator_type::const_pointer const_pointer;
+00203     template<typename U> struct rebind {
+00204         typedef zero_allocator<U, Allocator> other;
+00205     };
+00206 };
+00207 
+00208 template<typename T1, template<typename X1> class B1, typename T2, template<typename X2> class B2>
+00209 inline bool operator==( const zero_allocator<T1,B1> &a, const zero_allocator<T2,B2> &b) {
+00210     return static_cast< B1<T1> >(a) == static_cast< B2<T2> >(b);
+00211 }
+00212 template<typename T1, template<typename X1> class B1, typename T2, template<typename X2> class B2>
+00213 inline bool operator!=( const zero_allocator<T1,B1> &a, const zero_allocator<T2,B2> &b) {
+00214     return static_cast< B1<T1> >(a) != static_cast< B2<T2> >(b);
+00215 }
+00216 
+00217 } // namespace tbb 
+00218 
+00219 #endif /* __TBB_tbb_allocator_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00638.html b/src/tbb/doc/html/a00638.html new file mode 100644 index 0000000..ba7c842 --- /dev/null +++ b/src/tbb/doc/html/a00638.html @@ -0,0 +1,323 @@ + + +tbb_config.h Source File + + + + + + +

tbb_config.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_tbb_config_H
+00022 #define __TBB_tbb_config_H
+00023 
+00032 #define __TBB_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+00033 #if __clang__
+00034 #define __TBB_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
+00035 #endif
+00036 
+00039 #if (__TBB_GCC_VERSION >= 40400) && !defined(__INTEL_COMPILER)
+00040 
+00041     #define __TBB_GCC_WARNING_SUPPRESSION_PRESENT 1
+00042 #endif
+00043 
+00044 
+00045 /* Select particular features of C++11 based on compiler version.
+00046    ICC 12.1 (Linux), GCC 4.3 and higher, clang 2.9 and higher
+00047    set __GXX_EXPERIMENTAL_CXX0X__ in c++11 mode.
+00048 
+00049    Compilers that mimics other compilers (ICC, clang) must be processed before
+00050    compilers they mimic.
+00051 
+00052    TODO: The following conditions should be extended when new compilers/runtimes
+00053    support added.
+00054  */
+00055 
+00056 #if __INTEL_COMPILER
+00057     #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT __GXX_EXPERIMENTAL_CXX0X__ && __VARIADIC_TEMPLATES
+00058     #define __TBB_CPP11_RVALUE_REF_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ || _MSC_VER >= 1600) && (__INTEL_COMPILER >= 1200)
+00059     #define __TBB_EXCEPTION_PTR_PRESENT 0
+00060 #elif __clang__
+00061     #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __TBB_CLANG_VERSION >= 20900)
+00062     #define __TBB_CPP11_RVALUE_REF_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __TBB_CLANG_VERSION >= 20900)
+00063     #define __TBB_EXCEPTION_PTR_PRESENT __GXX_EXPERIMENTAL_CXX0X__
+00064 #elif __GNUC__
+00065     #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT __GXX_EXPERIMENTAL_CXX0X__
+00066     #define __TBB_CPP11_RVALUE_REF_PRESENT __GXX_EXPERIMENTAL_CXX0X__
+00067     #define __TBB_EXCEPTION_PTR_PRESENT __GXX_EXPERIMENTAL_CXX0X__
+00068 #elif _MSC_VER
+00069     #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT 0
+00070     #define __TBB_CPP11_RVALUE_REF_PRESENT 0
+00071     #define __TBB_EXCEPTION_PTR_PRESENT (_MSC_VER >= 1600)
+00072 #else
+00073     #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT 0
+00074     #define __TBB_CPP11_RVALUE_REF_PRESENT 0
+00075     #define __TBB_EXCEPTION_PTR_PRESENT 0
+00076 #endif
+00077 
+00078 // Work around a bug in MinGW32
+00079 #if __MINGW32__ && __TBB_EXCEPTION_PTR_PRESENT && !defined(_GLIBCXX_ATOMIC_BUILTINS_4)
+00080     #define _GLIBCXX_ATOMIC_BUILTINS_4
+00081 #endif
+00082 
+00083 #if __GNUC__ || __SUNPRO_CC || __IBMCPP__
+00084     /* ICC defines __GNUC__ and so is covered */
+00085     #define __TBB_ATTRIBUTE_ALIGNED_PRESENT 1
+00086 #elif _MSC_VER && (_MSC_VER >= 1300 || __INTEL_COMPILER)
+00087     #define __TBB_DECLSPEC_ALIGN_PRESENT 1
+00088 #endif
+00089 
+00090 /* TODO: change the version back to 4.1.2 once macro __TBB_WORD_SIZE become optional */
+00091 #if (__TBB_GCC_VERSION >= 40306) && !defined(__INTEL_COMPILER)
+00092 
+00093     #define __TBB_GCC_BUILTIN_ATOMICS_PRESENT 1
+00094 #endif
+00095 
+00098 #ifndef TBB_USE_DEBUG
+00099 #ifdef TBB_DO_ASSERT
+00100 #define TBB_USE_DEBUG TBB_DO_ASSERT
+00101 #else
+00102 #ifdef _DEBUG
+00103 #define TBB_USE_DEBUG _DEBUG
+00104 #else
+00105 #define TBB_USE_DEBUG 0
+00106 #endif
+00107 #endif /* TBB_DO_ASSERT */
+00108 #endif /* TBB_USE_DEBUG */
+00109 
+00110 #ifndef TBB_USE_ASSERT
+00111 #ifdef TBB_DO_ASSERT
+00112 #define TBB_USE_ASSERT TBB_DO_ASSERT
+00113 #else 
+00114 #define TBB_USE_ASSERT TBB_USE_DEBUG
+00115 #endif /* TBB_DO_ASSERT */
+00116 #endif /* TBB_USE_ASSERT */
+00117 
+00118 #ifndef TBB_USE_THREADING_TOOLS
+00119 #ifdef TBB_DO_THREADING_TOOLS
+00120 #define TBB_USE_THREADING_TOOLS TBB_DO_THREADING_TOOLS
+00121 #else 
+00122 #define TBB_USE_THREADING_TOOLS TBB_USE_DEBUG
+00123 #endif /* TBB_DO_THREADING_TOOLS */
+00124 #endif /* TBB_USE_THREADING_TOOLS */
+00125 
+00126 #ifndef TBB_USE_PERFORMANCE_WARNINGS
+00127 #ifdef TBB_PERFORMANCE_WARNINGS
+00128 #define TBB_USE_PERFORMANCE_WARNINGS TBB_PERFORMANCE_WARNINGS
+00129 #else 
+00130 #define TBB_USE_PERFORMANCE_WARNINGS TBB_USE_DEBUG
+00131 #endif /* TBB_PEFORMANCE_WARNINGS */
+00132 #endif /* TBB_USE_PERFORMANCE_WARNINGS */
+00133 
+00134 #if __MIC__ || __MIC2__
+00135 #define __TBB_DEFINE_MIC 1
+00136 #endif
+00137 
+00138 #if !defined(__EXCEPTIONS) && !defined(_CPPUNWIND) && !defined(__SUNPRO_CC) || defined(_XBOX)
+00139     #if TBB_USE_EXCEPTIONS
+00140         #error Compilation settings do not support exception handling. Please do not set TBB_USE_EXCEPTIONS macro or set it to 0.
+00141     #elif !defined(TBB_USE_EXCEPTIONS)
+00142         #define TBB_USE_EXCEPTIONS 0
+00143     #endif
+00144 #elif !defined(TBB_USE_EXCEPTIONS)
+00145     #if __TBB_DEFINE_MIC
+00146     #define TBB_USE_EXCEPTIONS 0
+00147     #else
+00148     #define TBB_USE_EXCEPTIONS 1
+00149     #endif
+00150 #elif TBB_USE_EXCEPTIONS && __TBB_DEFINE_MIC
+00151     #error Please do not set TBB_USE_EXCEPTIONS macro or set it to 0.
+00152 #endif
+00153 
+00154 #ifndef TBB_IMPLEMENT_CPP0X
+00155 
+00156     #if __GNUC__==4 && __GNUC_MINOR__>=4 && __GXX_EXPERIMENTAL_CXX0X__
+00157         #define TBB_IMPLEMENT_CPP0X 0
+00158     #else
+00159         #define TBB_IMPLEMENT_CPP0X 1
+00160     #endif
+00161 #endif /* TBB_IMPLEMENT_CPP0X */
+00162 
+00163 #ifndef TBB_USE_CAPTURED_EXCEPTION
+00164     #if __TBB_EXCEPTION_PTR_PRESENT
+00165         #define TBB_USE_CAPTURED_EXCEPTION 0
+00166     #else
+00167         #define TBB_USE_CAPTURED_EXCEPTION 1
+00168     #endif
+00169 #else /* defined TBB_USE_CAPTURED_EXCEPTION */
+00170     #if !TBB_USE_CAPTURED_EXCEPTION && !__TBB_EXCEPTION_PTR_PRESENT
+00171         #error Current runtime does not support std::exception_ptr. Set TBB_USE_CAPTURED_EXCEPTION and make sure that your code is ready to catch tbb::captured_exception.
+00172     #endif
+00173 #endif /* defined TBB_USE_CAPTURED_EXCEPTION */
+00174 
+00176 #if (TBB_USE_GCC_BUILTINS && !__TBB_GCC_BUILTIN_ATOMICS_PRESENT)
+00177     #error "GCC atomic built-ins are not supported."
+00178 #endif
+00179 
+00187 #ifndef __TBB_DYNAMIC_LOAD_ENABLED
+00188     #define __TBB_DYNAMIC_LOAD_ENABLED 1
+00189 #elif !(_WIN32||_WIN64) && !__TBB_DYNAMIC_LOAD_ENABLED
+00190     #define __TBB_WEAK_SYMBOLS 1
+00191 #endif
+00192 
+00193 #if (_WIN32||_WIN64) && __TBB_SOURCE_DIRECTLY_INCLUDED
+00194     #define __TBB_NO_IMPLICIT_LINKAGE 1
+00195     #define __TBBMALLOC_NO_IMPLICIT_LINKAGE 1
+00196 #endif
+00197 
+00198 #ifndef __TBB_COUNT_TASK_NODES
+00199     #define __TBB_COUNT_TASK_NODES TBB_USE_ASSERT
+00200 #endif
+00201 
+00202 #ifndef __TBB_TASK_GROUP_CONTEXT
+00203     #define __TBB_TASK_GROUP_CONTEXT 1
+00204 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00205 
+00206 #if TBB_USE_EXCEPTIONS && !__TBB_TASK_GROUP_CONTEXT
+00207     #error TBB_USE_EXCEPTIONS requires __TBB_TASK_GROUP_CONTEXT to be enabled
+00208 #endif
+00209 
+00210 #ifndef __TBB_SCHEDULER_OBSERVER
+00211     #define __TBB_SCHEDULER_OBSERVER 1
+00212 #endif /* __TBB_SCHEDULER_OBSERVER */
+00213 
+00214 #ifndef __TBB_TASK_PRIORITY
+00215     #define __TBB_TASK_PRIORITY __TBB_TASK_GROUP_CONTEXT
+00216 #endif /* __TBB_TASK_PRIORITY */
+00217 
+00218 #if __TBB_TASK_PRIORITY && !__TBB_TASK_GROUP_CONTEXT
+00219     #error __TBB_TASK_PRIORITY requires __TBB_TASK_GROUP_CONTEXT to be enabled
+00220 #endif
+00221 
+00222 #if !defined(__TBB_SURVIVE_THREAD_SWITCH) && (_WIN32 || _WIN64 || __linux__)
+00223     #define __TBB_SURVIVE_THREAD_SWITCH 1
+00224 #endif /* __TBB_SURVIVE_THREAD_SWITCH */
+00225 
+00226 #ifndef __TBB_DEFAULT_PARTITIONER
+00227 #if TBB_DEPRECATED
+00228 
+00229 #define __TBB_DEFAULT_PARTITIONER tbb::simple_partitioner
+00230 #else
+00231 
+00232 #define __TBB_DEFAULT_PARTITIONER tbb::auto_partitioner
+00233 #endif /* TBB_DEPRECATED */
+00234 #endif /* !defined(__TBB_DEFAULT_PARTITIONER */
+00235 
+00236 #ifdef _VARIADIC_MAX
+00237 #define __TBB_VARIADIC_MAX _VARIADIC_MAX
+00238 #else
+00239 #if _MSC_VER >= 1700
+00240 #define __TBB_VARIADIC_MAX 5  // current VS11 setting, may change.
+00241 #else
+00242 #define __TBB_VARIADIC_MAX 10
+00243 #endif
+00244 #endif
+00245 
+00252 #if __GNUC__ && __TBB_x86_64 && __INTEL_COMPILER == 1200
+00253     #define __TBB_ICC_12_0_INL_ASM_FSTCW_BROKEN 1
+00254 #endif
+00255 
+00256 #if _MSC_VER && __INTEL_COMPILER && (__INTEL_COMPILER<1110 || __INTEL_COMPILER==1110 && __INTEL_COMPILER_BUILD_DATE < 20091012)
+00257 
+00260     #define __TBB_DEFAULT_DTOR_THROW_SPEC_BROKEN 1
+00261 #endif
+00262 
+00263 #if defined(_MSC_VER) && _MSC_VER < 1500 && !defined(__INTEL_COMPILER)
+00264 
+00266     #define __TBB_TEMPLATE_FRIENDS_BROKEN 1
+00267 #endif
+00268 
+00269 #if __GLIBC__==2 && __GLIBC_MINOR__==3 || __MINGW32__ || (__APPLE__ && __INTEL_COMPILER==1200 && !TBB_USE_DEBUG)
+00271 
+00272     #define __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN 1
+00273 #endif
+00274 
+00275 #if (_WIN32||_WIN64) && __INTEL_COMPILER == 1110
+00276 
+00277     #define __TBB_ICL_11_1_CODE_GEN_BROKEN 1
+00278 #endif
+00279 
+00280 #if __clang__ || (__GNUC__==3 && __GNUC_MINOR__==3 && !defined(__INTEL_COMPILER))
+00281 
+00282     #define __TBB_PROTECTED_NESTED_CLASS_BROKEN 1
+00283 #endif
+00284 
+00285 #if __MINGW32__ && (__GNUC__<4 || __GNUC__==4 && __GNUC_MINOR__<2)
+00286 
+00288     #define __TBB_SSE_STACK_ALIGNMENT_BROKEN 1
+00289 #endif
+00290 
+00291 #if __GNUC__==4 && __GNUC_MINOR__==3 && __GNUC_PATCHLEVEL__==0
+00292     // GCC of this version may rashly ignore control dependencies
+00293     #define __TBB_GCC_OPTIMIZER_ORDERING_BROKEN 1
+00294 #endif
+00295 
+00296 #if __FreeBSD__
+00297 
+00299     #define __TBB_PRIO_INHERIT_BROKEN 1
+00300 
+00303     #define __TBB_PLACEMENT_NEW_EXCEPTION_SAFETY_BROKEN 1
+00304 #endif /* __FreeBSD__ */
+00305 
+00306 #if (__linux__ || __APPLE__) && __i386__ && defined(__INTEL_COMPILER)
+00307 
+00309     #define __TBB_ICC_ASM_VOLATILE_BROKEN 1
+00310 #endif
+00311 
+00312 #if !__INTEL_COMPILER && (_MSC_VER || __GNUC__==3 && __GNUC_MINOR__<=2)
+00313 
+00315     #define __TBB_ALIGNOF_NOT_INSTANTIATED_TYPES_BROKEN 1
+00316 #endif
+00317 
+00318 #if __INTEL_COMPILER
+00319     #define __TBB_CPP11_STD_FORWARD_BROKEN 1
+00320 #else
+00321     #define __TBB_CPP11_STD_FORWARD_BROKEN 0
+00322 #endif
+00323 
+00324 #if __TBB_DEFINE_MIC
+00325 
+00326     #define __TBB_MAIN_THREAD_AFFINITY_BROKEN 1
+00327 #endif
+00328 
+00329 #endif /* __TBB_tbb_config_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00639.html b/src/tbb/doc/html/a00639.html new file mode 100644 index 0000000..7c36f8b --- /dev/null +++ b/src/tbb/doc/html/a00639.html @@ -0,0 +1,322 @@ + + +tbb_exception.h Source File + + + + + + +

tbb_exception.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_exception_H
+00022 #define __TBB_exception_H
+00023 
+00024 #include "tbb_stddef.h"
+00025 
+00026 #if !TBB_USE_EXCEPTIONS && _MSC_VER
+00027     // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers
+00028     #pragma warning (push)
+00029     #pragma warning (disable: 4530)
+00030 #endif
+00031 
+00032 #include <stdexcept>
+00033 #include <string> // required to construct std exception classes
+00034 
+00035 #if !TBB_USE_EXCEPTIONS && _MSC_VER
+00036     #pragma warning (pop)
+00037 #endif
+00038 
+00039 namespace tbb {
+00040 
+00042 class bad_last_alloc : public std::bad_alloc {
+00043 public:
+00044     /*override*/ const char* what() const throw();
+00045 #if __TBB_DEFAULT_DTOR_THROW_SPEC_BROKEN
+00046     /*override*/ ~bad_last_alloc() throw() {}
+00047 #endif
+00048 };
+00049 
+00051 class improper_lock : public std::exception {
+00052 public:
+00053     /*override*/ const char* what() const throw();
+00054 };
+00055 
+00057 class user_abort : public std::exception {
+00058 public:
+00059     /*override*/ const char* what() const throw();
+00060 };
+00061 
+00063 class missing_wait : public std::exception {
+00064 public:
+00065     /*override*/ const char* what() const throw();
+00066 };
+00067 
+00069 class invalid_multiple_scheduling : public std::exception {
+00070 public:
+00071     /*override*/ const char* what() const throw();
+00072 };
+00073 
+00074 namespace internal {
+00076 void __TBB_EXPORTED_FUNC throw_bad_last_alloc_exception_v4();
+00077 
+00078 enum exception_id {
+00079     eid_bad_alloc = 1,
+00080     eid_bad_last_alloc,
+00081     eid_nonpositive_step,
+00082     eid_out_of_range,
+00083     eid_segment_range_error,
+00084     eid_index_range_error,
+00085     eid_missing_wait,
+00086     eid_invalid_multiple_scheduling,
+00087     eid_improper_lock,
+00088     eid_possible_deadlock,
+00089     eid_operation_not_permitted,
+00090     eid_condvar_wait_failed,
+00091     eid_invalid_load_factor,
+00092     eid_reserved, // free slot for backward compatibility, can be reused.
+00093     eid_invalid_swap,
+00094     eid_reservation_length_error,
+00095     eid_invalid_key,
+00096     eid_user_abort,
+00098 
+00100     eid_max
+00101 };
+00102 
+00104 
+00106 void __TBB_EXPORTED_FUNC throw_exception_v4 ( exception_id );
+00107 
+00109 inline void throw_exception ( exception_id eid ) { throw_exception_v4(eid); }
+00110 
+00111 } // namespace internal
+00112 } // namespace tbb
+00113 
+00114 #if __TBB_TASK_GROUP_CONTEXT
+00115 #include "tbb_allocator.h"
+00116 #include <exception>
+00117 #include <typeinfo>
+00118 #include <new>
+00119 
+00120 namespace tbb {
+00121 
+00123 
+00143 class tbb_exception : public std::exception
+00144 {
+00148     void* operator new ( size_t );
+00149 
+00150 public:
+00152 
+00153     virtual tbb_exception* move () throw() = 0;
+00154 
+00156 
+00158     virtual void destroy () throw() = 0;
+00159 
+00161 
+00165     virtual void throw_self () = 0;
+00166 
+00168     virtual const char* name() const throw() = 0;
+00169 
+00171     virtual const char* what() const throw() = 0;
+00172 
+00179     void operator delete ( void* p ) {
+00180         internal::deallocate_via_handler_v3(p);
+00181     }
+00182 };
+00183 
+00185 
+00189 class captured_exception : public tbb_exception
+00190 {
+00191 public:
+00192     captured_exception ( const captured_exception& src )
+00193         : tbb_exception(src), my_dynamic(false)
+00194     {
+00195         set(src.my_exception_name, src.my_exception_info);
+00196     }
+00197 
+00198     captured_exception ( const char* name_, const char* info )
+00199         : my_dynamic(false)
+00200     {
+00201         set(name_, info);
+00202     }
+00203 
+00204     __TBB_EXPORTED_METHOD ~captured_exception () throw();
+00205 
+00206     captured_exception& operator= ( const captured_exception& src ) {
+00207         if ( this != &src ) {
+00208             clear();
+00209             set(src.my_exception_name, src.my_exception_info);
+00210         }
+00211         return *this;
+00212     }
+00213 
+00214     /*override*/
+00215     captured_exception* __TBB_EXPORTED_METHOD move () throw();
+00216 
+00217     /*override*/
+00218     void __TBB_EXPORTED_METHOD destroy () throw();
+00219 
+00220     /*override*/
+00221     void throw_self () { __TBB_THROW(*this); }
+00222 
+00223     /*override*/
+00224     const char* __TBB_EXPORTED_METHOD name() const throw();
+00225 
+00226     /*override*/
+00227     const char* __TBB_EXPORTED_METHOD what() const throw();
+00228 
+00229     void __TBB_EXPORTED_METHOD set ( const char* name, const char* info ) throw();
+00230     void __TBB_EXPORTED_METHOD clear () throw();
+00231 
+00232 private:
+00234     captured_exception() {}
+00235 
+00237     static captured_exception* allocate ( const char* name, const char* info );
+00238 
+00239     bool my_dynamic;
+00240     const char* my_exception_name;
+00241     const char* my_exception_info;
+00242 };
+00243 
+00245 
+00249 template<typename ExceptionData>
+00250 class movable_exception : public tbb_exception
+00251 {
+00252     typedef movable_exception<ExceptionData> self_type;
+00253 
+00254 public:
+00255     movable_exception ( const ExceptionData& data_ )
+00256         : my_exception_data(data_)
+00257         , my_dynamic(false)
+00258         , my_exception_name(
+00259 #if TBB_USE_EXCEPTIONS
+00260         typeid(self_type).name()
+00261 #else /* !TBB_USE_EXCEPTIONS */
+00262         "movable_exception"
+00263 #endif /* !TBB_USE_EXCEPTIONS */
+00264         )
+00265     {}
+00266 
+00267     movable_exception ( const movable_exception& src ) throw ()
+00268         : tbb_exception(src)
+00269         , my_exception_data(src.my_exception_data)
+00270         , my_dynamic(false)
+00271         , my_exception_name(src.my_exception_name)
+00272     {}
+00273 
+00274     ~movable_exception () throw() {}
+00275 
+00276     const movable_exception& operator= ( const movable_exception& src ) {
+00277         if ( this != &src ) {
+00278             my_exception_data = src.my_exception_data;
+00279             my_exception_name = src.my_exception_name;
+00280         }
+00281         return *this;
+00282     }
+00283 
+00284     ExceptionData& data () throw() { return my_exception_data; }
+00285 
+00286     const ExceptionData& data () const throw() { return my_exception_data; }
+00287 
+00288     /*override*/ const char* name () const throw() { return my_exception_name; }
+00289 
+00290     /*override*/ const char* what () const throw() { return "tbb::movable_exception"; }
+00291 
+00292     /*override*/
+00293     movable_exception* move () throw() {
+00294         void* e = internal::allocate_via_handler_v3(sizeof(movable_exception));
+00295         if ( e ) {
+00296             ::new (e) movable_exception(*this);
+00297             ((movable_exception*)e)->my_dynamic = true;
+00298         }
+00299         return (movable_exception*)e;
+00300     }
+00301     /*override*/
+00302     void destroy () throw() {
+00303         __TBB_ASSERT ( my_dynamic, "Method destroy can be called only on dynamically allocated movable_exceptions" );
+00304         if ( my_dynamic ) {
+00305             this->~movable_exception();
+00306             internal::deallocate_via_handler_v3(this);
+00307         }
+00308     }
+00309     /*override*/
+00310     void throw_self () { __TBB_THROW( *this ); }
+00311 
+00312 protected:
+00314     ExceptionData  my_exception_data;
+00315 
+00316 private:
+00318     bool my_dynamic;
+00319 
+00321 
+00322     const char* my_exception_name;
+00323 };
+00324 
+00325 #if !TBB_USE_CAPTURED_EXCEPTION
+00326 namespace internal {
+00327 
+00329 
+00331 class tbb_exception_ptr {
+00332     std::exception_ptr  my_ptr;
+00333 
+00334 public:
+00335     static tbb_exception_ptr* allocate ();
+00336     static tbb_exception_ptr* allocate ( const tbb_exception& tag );
+00338     static tbb_exception_ptr* allocate ( captured_exception& src );
+00339 
+00341 
+00342     void destroy () throw();
+00343 
+00345     void throw_self () { std::rethrow_exception(my_ptr); }
+00346 
+00347 private:
+00348     tbb_exception_ptr ( const std::exception_ptr& src ) : my_ptr(src) {}
+00349     tbb_exception_ptr ( const captured_exception& src ) : my_ptr(std::copy_exception(src)) {}
+00350 }; // class tbb::internal::tbb_exception_ptr
+00351 
+00352 } // namespace internal
+00353 #endif /* !TBB_USE_CAPTURED_EXCEPTION */
+00354 
+00355 } // namespace tbb
+00356 
+00357 #endif /* __TBB_TASK_GROUP_CONTEXT */
+00358 
+00359 #endif /* __TBB_exception_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00640.html b/src/tbb/doc/html/a00640.html new file mode 100644 index 0000000..618adc7 --- /dev/null +++ b/src/tbb/doc/html/a00640.html @@ -0,0 +1,782 @@ + + +tbb_machine.h Source File + + + + + + +

tbb_machine.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_machine_H
+00022 #define __TBB_machine_H
+00023 
+00116 #include "tbb_stddef.h"
+00117 
+00118 namespace tbb {
+00119 namespace internal {
+00120 
+00122 // Overridable helpers declarations
+00123 //
+00124 // A machine/*.h file may choose to define these templates, otherwise it must
+00125 // request default implementation by setting appropriate __TBB_USE_GENERIC_XXX macro(s).
+00126 //
+00127 template <typename T, std::size_t S>
+00128 struct machine_load_store;
+00129 
+00130 template <typename T, std::size_t S>
+00131 struct machine_load_store_relaxed;
+00132 
+00133 template <typename T, std::size_t S>
+00134 struct machine_load_store_seq_cst;
+00135 //
+00136 // End of overridable helpers declarations
+00138 
+00139 template<size_t S> struct atomic_selector;
+00140 
+00141 template<> struct atomic_selector<1> {
+00142     typedef int8_t word;
+00143     inline static word fetch_store ( volatile void* location, word value );
+00144 };
+00145 
+00146 template<> struct atomic_selector<2> {
+00147     typedef int16_t word;
+00148     inline static word fetch_store ( volatile void* location, word value );
+00149 };
+00150 
+00151 template<> struct atomic_selector<4> {
+00152 #if _MSC_VER && !_WIN64
+00153     // Work-around that avoids spurious /Wp64 warnings
+00154     typedef intptr_t word;
+00155 #else
+00156     typedef int32_t word;
+00157 #endif
+00158     inline static word fetch_store ( volatile void* location, word value );
+00159 };
+00160 
+00161 template<> struct atomic_selector<8> {
+00162     typedef int64_t word;
+00163     inline static word fetch_store ( volatile void* location, word value );
+00164 };
+00165 
+00166 }} // namespaces internal, tbb
+00167 
+00168 #if _WIN32||_WIN64
+00169 
+00170 #ifdef _MANAGED
+00171 #pragma managed(push, off)
+00172 #endif
+00173 
+00174     #if __MINGW64__ || __MINGW32__
+00175         extern "C" __declspec(dllimport) int __stdcall SwitchToThread( void );
+00176         #define __TBB_Yield()  SwitchToThread()
+00177         #if (TBB_USE_GCC_BUILTINS && __TBB_GCC_BUILTIN_ATOMICS_PRESENT)
+00178             #include "machine/gcc_generic.h"
+00179         #elif __MINGW64__
+00180             #include "machine/linux_intel64.h"
+00181         #elif __MINGW32__
+00182             #include "machine/linux_ia32.h"
+00183         #endif
+00184     #elif defined(_M_IX86)
+00185         #include "machine/windows_ia32.h"
+00186     #elif defined(_M_X64) 
+00187         #include "machine/windows_intel64.h"
+00188     #elif _XBOX
+00189         #include "machine/xbox360_ppc.h"
+00190     #endif
+00191 
+00192 #ifdef _MANAGED
+00193 #pragma managed(pop)
+00194 #endif
+00195 
+00196 #elif __TBB_DEFINE_MIC
+00197 
+00198     #include "machine/mic_common.h"
+00199     #include "machine/linux_intel64.h"
+00200 
+00201 #elif __linux__ || __FreeBSD__ || __NetBSD__
+00202 
+00203     #if (TBB_USE_GCC_BUILTINS && __TBB_GCC_BUILTIN_ATOMICS_PRESENT)
+00204         #include "machine/gcc_generic.h"
+00205     #elif __i386__
+00206         #include "machine/linux_ia32.h"
+00207     #elif __x86_64__
+00208         #include "machine/linux_intel64.h"
+00209     #elif __ia64__
+00210         #include "machine/linux_ia64.h"
+00211     #elif __powerpc__
+00212         #include "machine/mac_ppc.h"
+00213     #elif __TBB_GCC_BUILTIN_ATOMICS_PRESENT
+00214         #include "machine/gcc_generic.h"
+00215     #endif
+00216     #include "machine/linux_common.h"
+00217 
+00218 #elif __APPLE__
+00219 
+00220     #if __i386__
+00221         #include "machine/linux_ia32.h"
+00222     #elif __x86_64__
+00223         #include "machine/linux_intel64.h"
+00224     #elif __POWERPC__
+00225         #include "machine/mac_ppc.h"
+00226     #endif
+00227     #include "machine/macos_common.h"
+00228 
+00229 #elif _AIX
+00230 
+00231     #include "machine/ibm_aix51.h"
+00232 
+00233 #elif __sun || __SUNPRO_CC
+00234 
+00235     #define __asm__ asm
+00236     #define __volatile__ volatile
+00237 
+00238     #if __i386  || __i386__
+00239         #include "machine/linux_ia32.h"
+00240     #elif __x86_64__
+00241         #include "machine/linux_intel64.h"
+00242     #elif __sparc
+00243         #include "machine/sunos_sparc.h"
+00244     #endif
+00245     #include <sched.h>
+00246 
+00247     #define __TBB_Yield() sched_yield()
+00248 
+00249 #endif /* OS selection */
+00250 
+00251 #ifndef __TBB_64BIT_ATOMICS
+00252     #define __TBB_64BIT_ATOMICS 1
+00253 #endif
+00254 
+00255 // Special atomic functions
+00256 #if __TBB_USE_FENCED_ATOMICS
+00257     #define __TBB_machine_cmpswp1   __TBB_machine_cmpswp1full_fence
+00258     #define __TBB_machine_cmpswp2   __TBB_machine_cmpswp2full_fence
+00259     #define __TBB_machine_cmpswp4   __TBB_machine_cmpswp4full_fence
+00260     #define __TBB_machine_cmpswp8   __TBB_machine_cmpswp8full_fence
+00261 
+00262     #if __TBB_WORDSIZE==8
+00263         #define __TBB_machine_fetchadd8             __TBB_machine_fetchadd8full_fence
+00264         #define __TBB_machine_fetchstore8           __TBB_machine_fetchstore8full_fence
+00265         #define __TBB_FetchAndAddWrelease(P,V)      __TBB_machine_fetchadd8release(P,V)
+00266         #define __TBB_FetchAndIncrementWacquire(P)  __TBB_machine_fetchadd8acquire(P,1)
+00267         #define __TBB_FetchAndDecrementWrelease(P)  __TBB_machine_fetchadd8release(P,(-1))
+00268     #else
+00269         #error Define macros for 4-byte word, similarly to the above __TBB_WORDSIZE==8 branch.
+00270     #endif /* __TBB_WORDSIZE==4 */
+00271 #else /* !__TBB_USE_FENCED_ATOMICS */
+00272     #define __TBB_FetchAndAddWrelease(P,V)      __TBB_FetchAndAddW(P,V)
+00273     #define __TBB_FetchAndIncrementWacquire(P)  __TBB_FetchAndAddW(P,1)
+00274     #define __TBB_FetchAndDecrementWrelease(P)  __TBB_FetchAndAddW(P,(-1))
+00275 #endif /* !__TBB_USE_FENCED_ATOMICS */
+00276 
+00277 #if __TBB_WORDSIZE==4
+00278     #define __TBB_CompareAndSwapW(P,V,C)    __TBB_machine_cmpswp4(P,V,C)
+00279     #define __TBB_FetchAndAddW(P,V)         __TBB_machine_fetchadd4(P,V)
+00280     #define __TBB_FetchAndStoreW(P,V)       __TBB_machine_fetchstore4(P,V)
+00281 #elif  __TBB_WORDSIZE==8
+00282     #if __TBB_USE_GENERIC_DWORD_LOAD_STORE || __TBB_USE_GENERIC_DWORD_FETCH_ADD || __TBB_USE_GENERIC_DWORD_FETCH_STORE
+00283         #error These macros should only be used on 32-bit platforms.
+00284     #endif
+00285 
+00286     #define __TBB_CompareAndSwapW(P,V,C)    __TBB_machine_cmpswp8(P,V,C)
+00287     #define __TBB_FetchAndAddW(P,V)         __TBB_machine_fetchadd8(P,V)
+00288     #define __TBB_FetchAndStoreW(P,V)       __TBB_machine_fetchstore8(P,V)
+00289 #else /* __TBB_WORDSIZE != 8 */
+00290     #error Unsupported machine word size.
+00291 #endif /* __TBB_WORDSIZE */
+00292 
+00293 #ifndef __TBB_Pause
+00294     inline void __TBB_Pause(int32_t) {
+00295         __TBB_Yield();
+00296     }
+00297 #endif
+00298 
+00299 namespace tbb {
+00300 
+00302 inline void atomic_fence () { __TBB_full_memory_fence(); }
+00303 
+00304 namespace internal {
+00305 
+00307 
+00308 class atomic_backoff : no_copy {
+00310 
+00312     static const int32_t LOOPS_BEFORE_YIELD = 16;
+00313     int32_t count;
+00314 public:
+00315     atomic_backoff() : count(1) {}
+00316 
+00318     void pause() {
+00319         if( count<=LOOPS_BEFORE_YIELD ) {
+00320             __TBB_Pause(count);
+00321             // Pause twice as long the next time.
+00322             count*=2;
+00323         } else {
+00324             // Pause is so long that we might as well yield CPU to scheduler.
+00325             __TBB_Yield();
+00326         }
+00327     }
+00328 
+00329     // pause for a few times and then return false immediately.
+00330     bool bounded_pause() {
+00331         if( count<=LOOPS_BEFORE_YIELD ) {
+00332             __TBB_Pause(count);
+00333             // Pause twice as long the next time.
+00334             count*=2;
+00335             return true;
+00336         } else {
+00337             return false;
+00338         }
+00339     }
+00340 
+00341     void reset() {
+00342         count = 1;
+00343     }
+00344 };
+00345 
+00347 
+00348 template<typename T, typename U>
+00349 void spin_wait_while_eq( const volatile T& location, U value ) {
+00350     atomic_backoff backoff;
+00351     while( location==value ) backoff.pause();
+00352 }
+00353 
+00355 
+00356 template<typename T, typename U>
+00357 void spin_wait_until_eq( const volatile T& location, const U value ) {
+00358     atomic_backoff backoff;
+00359     while( location!=value ) backoff.pause();
+00360 }
+00361 
+00362 //TODO: add static_assert for the requirements stated below
+00363 //TODO: check if it works with signed types
+00364 
+00365 // there are following restrictions/limitations for this operation:
+00366 //  - T should be unsigned, otherwise sign propagation will break correctness of bit manipulations.
+00367 //  - T should be integer type of at most 4 bytes, for the casts and calculations to work.
+00368 //      (Together, these rules limit applicability of Masked CAS to uint8_t and uint16_t only,
+00369 //      as it does nothing useful for 4 bytes).
+00370 //  - The operation assumes that the architecture consistently uses either little-endian or big-endian:
+00371 //      it does not support mixed-endian or page-specific bi-endian architectures.
+00372 // This function is the only use of __TBB_BIG_ENDIAN.
+00373 #if (__TBB_BIG_ENDIAN!=-1)
+00374     #if ( __TBB_USE_GENERIC_PART_WORD_CAS)
+00375         #error generic implementation of part-word CAS was explicitly disabled for this configuration
+00376     #endif
+00377 template<typename T>
+00378 inline T __TBB_MaskedCompareAndSwap (volatile T * const ptr, const T value, const T comparand ) {
+00379     struct endianness{ static bool is_big_endian(){
+00380         #ifndef __TBB_BIG_ENDIAN
+00381             const uint32_t probe = 0x03020100;
+00382             return (((const char*)(&probe))[0]==0x03);
+00383         #elif (__TBB_BIG_ENDIAN==0) || (__TBB_BIG_ENDIAN==1)
+00384             return __TBB_BIG_ENDIAN;
+00385         #else
+00386             #error unexpected value of __TBB_BIG_ENDIAN
+00387         #endif
+00388     }};
+00389 
+00390     const uint32_t byte_offset            = (uint32_t) ((uintptr_t)ptr & 0x3);
+00391     volatile uint32_t * const aligned_ptr = (uint32_t*)((uintptr_t)ptr - byte_offset );
+00392 
+00393     // location of T within uint32_t for a C++ shift operation
+00394     const uint32_t bits_to_shift     = 8*(endianness::is_big_endian() ? (4 - sizeof(T) - (byte_offset)) : byte_offset);
+00395     const uint32_t mask              = (((uint32_t)1<<(sizeof(T)*8)) - 1 )<<bits_to_shift;
+00396     const uint32_t shifted_comparand = ((uint32_t)comparand << bits_to_shift)&mask;
+00397     const uint32_t shifted_value     = ((uint32_t)value     << bits_to_shift)&mask;
+00398 
+00399     for(atomic_backoff b;;b.pause()) {
+00400         const uint32_t surroundings  = *aligned_ptr & ~mask ; // reload the aligned_ptr value which might change during the pause
+00401         const uint32_t big_comparand = surroundings | shifted_comparand ;
+00402         const uint32_t big_value     = surroundings | shifted_value     ;
+00403         // __TBB_machine_cmpswp4 presumed to have full fence.
+00404         // Cast shuts up /Wp64 warning
+00405         const uint32_t big_result = (uint32_t)__TBB_machine_cmpswp4( aligned_ptr, big_value, big_comparand );
+00406         if( big_result == big_comparand                    // CAS succeeded
+00407           || ((big_result ^ big_comparand) & mask) != 0)   // CAS failed and the bits of interest have changed
+00408         {
+00409             return T((big_result & mask) >> bits_to_shift);
+00410         }
+00411         else continue;                                     // CAS failed but the bits of interest left unchanged
+00412     }
+00413 }
+00414 #endif
+00415 template<size_t S, typename T>
+00416 inline T __TBB_CompareAndSwapGeneric (volatile void *ptr, T value, T comparand );
+00417 
+00418 template<>
+00419 inline uint8_t __TBB_CompareAndSwapGeneric <1,uint8_t> (volatile void *ptr, uint8_t value, uint8_t comparand ) {
+00420 #if __TBB_USE_GENERIC_PART_WORD_CAS
+00421     return __TBB_MaskedCompareAndSwap<uint8_t>((volatile uint8_t *)ptr,value,comparand);
+00422 #else
+00423     return __TBB_machine_cmpswp1(ptr,value,comparand);
+00424 #endif
+00425 }
+00426 
+00427 template<>
+00428 inline uint16_t __TBB_CompareAndSwapGeneric <2,uint16_t> (volatile void *ptr, uint16_t value, uint16_t comparand ) {
+00429 #if __TBB_USE_GENERIC_PART_WORD_CAS
+00430     return __TBB_MaskedCompareAndSwap<uint16_t>((volatile uint16_t *)ptr,value,comparand);
+00431 #else
+00432     return __TBB_machine_cmpswp2(ptr,value,comparand);
+00433 #endif
+00434 }
+00435 
+00436 template<>
+00437 inline uint32_t __TBB_CompareAndSwapGeneric <4,uint32_t> (volatile void *ptr, uint32_t value, uint32_t comparand ) {
+00438     // Cast shuts up /Wp64 warning
+00439     return (uint32_t)__TBB_machine_cmpswp4(ptr,value,comparand);
+00440 }
+00441 
+00442 #if __TBB_64BIT_ATOMICS
+00443 template<>
+00444 inline uint64_t __TBB_CompareAndSwapGeneric <8,uint64_t> (volatile void *ptr, uint64_t value, uint64_t comparand ) {
+00445     return __TBB_machine_cmpswp8(ptr,value,comparand);
+00446 }
+00447 #endif
+00448 
+00449 template<size_t S, typename T>
+00450 inline T __TBB_FetchAndAddGeneric (volatile void *ptr, T addend) {
+00451     atomic_backoff b;
+00452     T result;
+00453     for(;;) {
+00454         result = *reinterpret_cast<volatile T *>(ptr);
+00455         // __TBB_CompareAndSwapGeneric presumed to have full fence.
+00456         if( __TBB_CompareAndSwapGeneric<S,T> ( ptr, result+addend, result )==result )
+00457             break;
+00458         b.pause();
+00459     }
+00460     return result;
+00461 }
+00462 
+00463 template<size_t S, typename T>
+00464 inline T __TBB_FetchAndStoreGeneric (volatile void *ptr, T value) {
+00465     atomic_backoff b;
+00466     T result;
+00467     for(;;) {
+00468         result = *reinterpret_cast<volatile T *>(ptr);
+00469         // __TBB_CompareAndSwapGeneric presumed to have full fence.
+00470         if( __TBB_CompareAndSwapGeneric<S,T> ( ptr, value, result )==result )
+00471             break;
+00472         b.pause();
+00473     }
+00474     return result;
+00475 }
+00476 
+00477 #if __TBB_USE_GENERIC_PART_WORD_CAS
+00478 #define __TBB_machine_cmpswp1 tbb::internal::__TBB_CompareAndSwapGeneric<1,uint8_t>
+00479 #define __TBB_machine_cmpswp2 tbb::internal::__TBB_CompareAndSwapGeneric<2,uint16_t>
+00480 #endif
+00481 
+00482 #if __TBB_USE_GENERIC_FETCH_ADD || __TBB_USE_GENERIC_PART_WORD_FETCH_ADD
+00483 #define __TBB_machine_fetchadd1 tbb::internal::__TBB_FetchAndAddGeneric<1,uint8_t>
+00484 #define __TBB_machine_fetchadd2 tbb::internal::__TBB_FetchAndAddGeneric<2,uint16_t>
+00485 #endif
+00486 
+00487 #if __TBB_USE_GENERIC_FETCH_ADD
+00488 #define __TBB_machine_fetchadd4 tbb::internal::__TBB_FetchAndAddGeneric<4,uint32_t>
+00489 #endif
+00490 
+00491 #if __TBB_USE_GENERIC_FETCH_ADD || __TBB_USE_GENERIC_DWORD_FETCH_ADD
+00492 #define __TBB_machine_fetchadd8 tbb::internal::__TBB_FetchAndAddGeneric<8,uint64_t>
+00493 #endif
+00494 
+00495 #if __TBB_USE_GENERIC_FETCH_STORE || __TBB_USE_GENERIC_PART_WORD_FETCH_STORE
+00496 #define __TBB_machine_fetchstore1 tbb::internal::__TBB_FetchAndStoreGeneric<1,uint8_t>
+00497 #define __TBB_machine_fetchstore2 tbb::internal::__TBB_FetchAndStoreGeneric<2,uint16_t>
+00498 #endif
+00499 
+00500 #if __TBB_USE_GENERIC_FETCH_STORE
+00501 #define __TBB_machine_fetchstore4 tbb::internal::__TBB_FetchAndStoreGeneric<4,uint32_t>
+00502 #endif
+00503 
+00504 #if __TBB_USE_GENERIC_FETCH_STORE || __TBB_USE_GENERIC_DWORD_FETCH_STORE
+00505 #define __TBB_machine_fetchstore8 tbb::internal::__TBB_FetchAndStoreGeneric<8,uint64_t>
+00506 #endif
+00507 
+00508 #if __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE
+00509 #define __TBB_MACHINE_DEFINE_ATOMIC_SELECTOR_FETCH_STORE(S)                                             \
+00510     atomic_selector<S>::word atomic_selector<S>::fetch_store ( volatile void* location, word value ) {  \
+00511         return __TBB_machine_fetchstore##S( location, value );                                          \
+00512     }
+00513 
+00514 __TBB_MACHINE_DEFINE_ATOMIC_SELECTOR_FETCH_STORE(1)
+00515 __TBB_MACHINE_DEFINE_ATOMIC_SELECTOR_FETCH_STORE(2)
+00516 __TBB_MACHINE_DEFINE_ATOMIC_SELECTOR_FETCH_STORE(4)
+00517 __TBB_MACHINE_DEFINE_ATOMIC_SELECTOR_FETCH_STORE(8)
+00518 
+00519 #undef __TBB_MACHINE_DEFINE_ATOMIC_SELECTOR_FETCH_STORE
+00520 #endif /* __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE */
+00521 
+00522 #if __TBB_USE_GENERIC_DWORD_LOAD_STORE
+00523 inline void __TBB_machine_store8 (volatile void *ptr, int64_t value) {
+00524     for(;;) {
+00525         int64_t result = *(int64_t *)ptr;
+00526         if( __TBB_machine_cmpswp8(ptr,value,result)==result ) break;
+00527     }
+00528 }
+00529 
+00530 inline int64_t __TBB_machine_load8 (const volatile void *ptr) {
+00531     // Comparand and new value may be anything, they only must be equal, and
+00532     // the value should have a low probability to be actually found in 'location'.
+00533     const int64_t anyvalue = 2305843009213693951LL;
+00534     return __TBB_machine_cmpswp8(const_cast<volatile void *>(ptr),anyvalue,anyvalue);
+00535 }
+00536 #endif /* __TBB_USE_GENERIC_DWORD_LOAD_STORE */
+00537 
+00538 #if __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE
+00539 
+00545 template <typename T, size_t S>
+00546 struct machine_load_store {
+00547     static T load_with_acquire ( const volatile T& location ) {
+00548         T to_return = location;
+00549         __TBB_acquire_consistency_helper();
+00550         return to_return;
+00551     }
+00552     static void store_with_release ( volatile T &location, T value ) {
+00553         __TBB_release_consistency_helper();
+00554         location = value;
+00555     }
+00556 };
+00557 
+00558 //in general, plain load and store of 32bit compiler is not atomic for 64bit types
+00559 #if __TBB_WORDSIZE==4 && __TBB_64BIT_ATOMICS
+00560 template <typename T>
+00561 struct machine_load_store<T,8> {
+00562     static T load_with_acquire ( const volatile T& location ) {
+00563         return (T)__TBB_machine_load8( (const volatile void*)&location );
+00564     }
+00565     static void store_with_release ( volatile T& location, T value ) {
+00566         __TBB_machine_store8( (volatile void*)&location, (int64_t)value );
+00567     }
+00568 };
+00569 #endif /* __TBB_WORDSIZE==4 && __TBB_64BIT_ATOMICS */
+00570 #endif /* __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE */
+00571 
+00572 #if __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE
+00573 template <typename T, size_t S>
+00574 struct machine_load_store_seq_cst {
+00575     static T load ( const volatile T& location ) {
+00576         __TBB_full_memory_fence();
+00577         return machine_load_store<T,S>::load_with_acquire( location );
+00578     }
+00579 #if __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE
+00580     static void store ( volatile T &location, T value ) {
+00581         atomic_selector<S>::fetch_store( (volatile void*)&location, (typename atomic_selector<S>::word)value );
+00582     }
+00583 #else /* !__TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE */
+00584     static void store ( volatile T &location, T value ) {
+00585         machine_load_store<T,S>::store_with_release( location, value );
+00586         __TBB_full_memory_fence();
+00587     }
+00588 #endif /* !__TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE */
+00589 };
+00590 
+00591 #if __TBB_WORDSIZE==4 && __TBB_64BIT_ATOMICS
+00592 
+00594 template <typename T>
+00595 struct machine_load_store_seq_cst<T,8> {
+00596     static T load ( const volatile T& location ) {
+00597         // Comparand and new value may be anything, they only must be equal, and
+00598         // the value should have a low probability to be actually found in 'location'.
+00599         const int64_t anyvalue = 2305843009213693951LL;
+00600         return __TBB_machine_cmpswp8( (volatile void*)const_cast<volatile T*>(&location), anyvalue, anyvalue );
+00601     }
+00602     static void store ( volatile T &location, T value ) {
+00603         int64_t result = (volatile int64_t&)location;
+00604         while ( __TBB_machine_cmpswp8((volatile void*)&location, (int64_t)value, result) != result )
+00605             result = (volatile int64_t&)location;
+00606     }
+00607 };
+00608 #endif /* __TBB_WORDSIZE==4 && __TBB_64BIT_ATOMICS */
+00609 #endif /*__TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE */
+00610 
+00611 #if __TBB_USE_GENERIC_RELAXED_LOAD_STORE
+00612 // Relaxed operations add volatile qualifier to prevent compiler from optimizing them out.
+00616 template <typename T, size_t S>
+00617 struct machine_load_store_relaxed {
+00618     static inline T load ( const volatile T& location ) {
+00619         return location;
+00620     }
+00621     static inline void store ( volatile T& location, T value ) {
+00622         location = value;
+00623     }
+00624 };
+00625 
+00626 #if __TBB_WORDSIZE==4 && __TBB_64BIT_ATOMICS
+00627 template <typename T>
+00628 struct machine_load_store_relaxed<T,8> {
+00629     static inline T load ( const volatile T& location ) {
+00630         return (T)__TBB_machine_load8( (const volatile void*)&location );
+00631     }
+00632     static inline void store ( volatile T& location, T value ) {
+00633         __TBB_machine_store8( (volatile void*)&location, (int64_t)value );
+00634     }
+00635 };
+00636 #endif /* __TBB_WORDSIZE==4 && __TBB_64BIT_ATOMICS */
+00637 #endif /* __TBB_USE_GENERIC_RELAXED_LOAD_STORE */
+00638 
+00639 #undef __TBB_WORDSIZE //this macro is forbidden to use outside of atomic machinery
+00640 
+00641 template<typename T>
+00642 inline T __TBB_load_with_acquire(const volatile T &location) {
+00643     return machine_load_store<T,sizeof(T)>::load_with_acquire( location );
+00644 }
+00645 template<typename T, typename V>
+00646 inline void __TBB_store_with_release(volatile T& location, V value) {
+00647     machine_load_store<T,sizeof(T)>::store_with_release( location, T(value) );
+00648 }
+00650 inline void __TBB_store_with_release(volatile size_t& location, size_t value) {
+00651     machine_load_store<size_t,sizeof(size_t)>::store_with_release( location, value );
+00652 }
+00653 
+00654 template<typename T>
+00655 inline T __TBB_load_full_fence(const volatile T &location) {
+00656     return machine_load_store_seq_cst<T,sizeof(T)>::load( location );
+00657 }
+00658 template<typename T, typename V>
+00659 inline void __TBB_store_full_fence(volatile T& location, V value) {
+00660     machine_load_store_seq_cst<T,sizeof(T)>::store( location, T(value) );
+00661 }
+00663 inline void __TBB_store_full_fence(volatile size_t& location, size_t value) {
+00664     machine_load_store_seq_cst<size_t,sizeof(size_t)>::store( location, value );
+00665 }
+00666 
+00667 template<typename T>
+00668 inline T __TBB_load_relaxed (const volatile T& location) {
+00669     return machine_load_store_relaxed<T,sizeof(T)>::load( const_cast<T&>(location) );
+00670 }
+00671 template<typename T, typename V>
+00672 inline void __TBB_store_relaxed ( volatile T& location, V value ) {
+00673     machine_load_store_relaxed<T,sizeof(T)>::store( const_cast<T&>(location), T(value) );
+00674 }
+00676 inline void __TBB_store_relaxed ( volatile size_t& location, size_t value ) {
+00677     machine_load_store_relaxed<size_t,sizeof(size_t)>::store( const_cast<size_t&>(location), value );
+00678 }
+00679 
+00680 // Macro __TBB_TypeWithAlignmentAtLeastAsStrict(T) should be a type with alignment at least as
+00681 // strict as type T.  The type should have a trivial default constructor and destructor, so that
+00682 // arrays of that type can be declared without initializers.
+00683 // It is correct (but perhaps a waste of space) if __TBB_TypeWithAlignmentAtLeastAsStrict(T) expands
+00684 // to a type bigger than T.
+00685 // The default definition here works on machines where integers are naturally aligned and the
+00686 // strictest alignment is 64.
+00687 #ifndef __TBB_TypeWithAlignmentAtLeastAsStrict
+00688 
+00689 #if __TBB_ATTRIBUTE_ALIGNED_PRESENT
+00690 
+00691 #define __TBB_DefineTypeWithAlignment(PowerOf2)       \
+00692 struct __TBB_machine_type_with_alignment_##PowerOf2 { \
+00693     uint32_t member[PowerOf2/sizeof(uint32_t)];       \
+00694 } __attribute__((aligned(PowerOf2)));
+00695 #define __TBB_alignof(T) __alignof__(T)
+00696 
+00697 #elif __TBB_DECLSPEC_ALIGN_PRESENT
+00698 
+00699 #define __TBB_DefineTypeWithAlignment(PowerOf2)       \
+00700 __declspec(align(PowerOf2))                           \
+00701 struct __TBB_machine_type_with_alignment_##PowerOf2 { \
+00702     uint32_t member[PowerOf2/sizeof(uint32_t)];       \
+00703 };
+00704 #define __TBB_alignof(T) __alignof(T)
+00705 
+00706 #else /* A compiler with unknown syntax for data alignment */
+00707 #error Must define __TBB_TypeWithAlignmentAtLeastAsStrict(T)
+00708 #endif
+00709 
+00710 /* Now declare types aligned to useful powers of two */
+00711 // TODO: Is __TBB_DefineTypeWithAlignment(8) needed on 32 bit platforms?
+00712 __TBB_DefineTypeWithAlignment(16)
+00713 __TBB_DefineTypeWithAlignment(32)
+00714 __TBB_DefineTypeWithAlignment(64)
+00715 
+00716 typedef __TBB_machine_type_with_alignment_64 __TBB_machine_type_with_strictest_alignment;
+00717 
+00718 // Primary template is a declaration of incomplete type so that it fails with unknown alignments
+00719 template<size_t N> struct type_with_alignment;
+00720 
+00721 // Specializations for allowed alignments
+00722 template<> struct type_with_alignment<1> { char member; };
+00723 template<> struct type_with_alignment<2> { uint16_t member; };
+00724 template<> struct type_with_alignment<4> { uint32_t member; };
+00725 template<> struct type_with_alignment<8> { uint64_t member; };
+00726 template<> struct type_with_alignment<16> {__TBB_machine_type_with_alignment_16 member; };
+00727 template<> struct type_with_alignment<32> {__TBB_machine_type_with_alignment_32 member; };
+00728 template<> struct type_with_alignment<64> {__TBB_machine_type_with_alignment_64 member; };
+00729 
+00730 #if __TBB_ALIGNOF_NOT_INSTANTIATED_TYPES_BROKEN
+00732 
+00734 template<size_t Size, typename T>
+00735 struct work_around_alignment_bug {
+00736     static const size_t alignment = __TBB_alignof(T);
+00737 };
+00738 #define __TBB_TypeWithAlignmentAtLeastAsStrict(T) tbb::internal::type_with_alignment<tbb::internal::work_around_alignment_bug<sizeof(T),T>::alignment>
+00739 #else
+00740 #define __TBB_TypeWithAlignmentAtLeastAsStrict(T) tbb::internal::type_with_alignment<__TBB_alignof(T)>
+00741 #endif  /* __TBB_ALIGNOF_NOT_INSTANTIATED_TYPES_BROKEN */
+00742 
+00743 #endif  /* __TBB_TypeWithAlignmentAtLeastAsStrict */
+00744 
+00745 // Template class here is to avoid instantiation of the static data for modules that don't use it
+00746 template<typename T>
+00747 struct reverse {
+00748     static const T byte_table[256];
+00749 };
+00750 // An efficient implementation of the reverse function utilizes a 2^8 lookup table holding the bit-reversed
+00751 // values of [0..2^8 - 1]. Those values can also be computed on the fly at a slightly higher cost.
+00752 template<typename T>
+00753 const T reverse<T>::byte_table[256] = {
+00754     0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
+00755     0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
+00756     0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
+00757     0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
+00758     0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
+00759     0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
+00760     0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
+00761     0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
+00762     0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
+00763     0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
+00764     0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
+00765     0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
+00766     0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
+00767     0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
+00768     0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
+00769     0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
+00770 };
+00771 
+00772 } // namespace internal
+00773 } // namespace tbb
+00774 
+00775 // Preserving access to legacy APIs
+00776 using tbb::internal::__TBB_load_with_acquire;
+00777 using tbb::internal::__TBB_store_with_release;
+00778 
+00779 // Mapping historically used names to the ones expected by atomic_load_store_traits
+00780 #define __TBB_load_acquire  __TBB_load_with_acquire
+00781 #define __TBB_store_release __TBB_store_with_release
+00782 
+00783 #ifndef __TBB_Log2
+00784 inline intptr_t __TBB_Log2( uintptr_t x ) {
+00785     if( x==0 ) return -1;
+00786     intptr_t result = 0;
+00787     uintptr_t tmp;
+00788 
+00789     if( sizeof(x)>4 && (tmp = ((uint64_t)x)>>32)) { x=tmp; result += 32; }
+00790     if( (tmp = x>>16) ) { x=tmp; result += 16; }
+00791     if( (tmp = x>>8) )  { x=tmp; result += 8; }
+00792     if( (tmp = x>>4) )  { x=tmp; result += 4; }
+00793     if( (tmp = x>>2) )  { x=tmp; result += 2; }
+00794     return (x&2)? result+1: result;
+00795 }
+00796 #endif
+00797 
+00798 #ifndef __TBB_AtomicOR
+00799 inline void __TBB_AtomicOR( volatile void *operand, uintptr_t addend ) {
+00800     tbb::internal::atomic_backoff b;
+00801     for(;;) {
+00802         uintptr_t tmp = *(volatile uintptr_t *)operand;
+00803         uintptr_t result = __TBB_CompareAndSwapW(operand, tmp|addend, tmp);
+00804         if( result==tmp ) break;
+00805         b.pause();
+00806     }
+00807 }
+00808 #endif
+00809 
+00810 #ifndef __TBB_AtomicAND
+00811 inline void __TBB_AtomicAND( volatile void *operand, uintptr_t addend ) {
+00812     tbb::internal::atomic_backoff b;
+00813     for(;;) {
+00814         uintptr_t tmp = *(volatile uintptr_t *)operand;
+00815         uintptr_t result = __TBB_CompareAndSwapW(operand, tmp&addend, tmp);
+00816         if( result==tmp ) break;
+00817         b.pause();
+00818     }
+00819 }
+00820 #endif
+00821 
+00822 #ifndef __TBB_Flag
+00823 typedef unsigned char __TBB_Flag;
+00824 #endif
+00825 typedef __TBB_atomic __TBB_Flag __TBB_atomic_flag;
+00826 
+00827 #ifndef __TBB_TryLockByte
+00828 inline bool __TBB_TryLockByte( __TBB_atomic_flag &flag ) {
+00829     return __TBB_machine_cmpswp1(&flag,1,0)==0;
+00830 }
+00831 #endif
+00832 
+00833 #ifndef __TBB_LockByte
+00834 inline __TBB_Flag __TBB_LockByte( __TBB_atomic_flag& flag ) {
+00835     if ( !__TBB_TryLockByte(flag) ) {
+00836         tbb::internal::atomic_backoff b;
+00837         do {
+00838             b.pause();
+00839         } while ( !__TBB_TryLockByte(flag) );
+00840     }
+00841     return 0;
+00842 }
+00843 #endif
+00844 
+00845 #ifndef  __TBB_UnlockByte
+00846 #define __TBB_UnlockByte __TBB_store_with_release
+00847 #endif
+00848 
+00849 #ifndef __TBB_ReverseByte
+00850 inline unsigned char __TBB_ReverseByte(unsigned char src) {
+00851     return tbb::internal::reverse<unsigned char>::byte_table[src];
+00852 }
+00853 #endif
+00854 
+00855 template<typename T>
+00856 T __TBB_ReverseBits(T src) {
+00857     T dst;
+00858     unsigned char *original = (unsigned char *) &src;
+00859     unsigned char *reversed = (unsigned char *) &dst;
+00860 
+00861     for( int i = sizeof(T)-1; i >= 0; i-- )
+00862         reversed[i] = __TBB_ReverseByte( original[sizeof(T)-i-1] );
+00863 
+00864     return dst;
+00865 }
+00866 
+00867 #endif /* __TBB_machine_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00647.html b/src/tbb/doc/html/a00647.html new file mode 100644 index 0000000..b343b15 --- /dev/null +++ b/src/tbb/doc/html/a00647.html @@ -0,0 +1,225 @@ + + +tbb_profiling.h Source File + + + + + + +

tbb_profiling.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_profiling_H
+00022 #define __TBB_profiling_H
+00023 
+00024 // Check if the tools support is enabled
+00025 #if (_WIN32||_WIN64||__linux__) && !__MINGW32__ && TBB_USE_THREADING_TOOLS
+00026 
+00027 #if _WIN32||_WIN64
+00028 #include <stdlib.h>  /* mbstowcs_s */
+00029 #endif
+00030 #include "tbb_stddef.h"
+00031 
+00032 namespace tbb {
+00033     namespace internal {
+00034 #if _WIN32||_WIN64
+00035         void __TBB_EXPORTED_FUNC itt_set_sync_name_v3( void *obj, const wchar_t* name );
+00036         inline size_t multibyte_to_widechar( wchar_t* wcs, const char* mbs, size_t bufsize) {
+00037 #if _MSC_VER>=1400
+00038             size_t len;
+00039             mbstowcs_s( &len, wcs, bufsize, mbs, _TRUNCATE );
+00040             return len;   // mbstowcs_s counts null terminator
+00041 #else
+00042             size_t len = mbstowcs( wcs, mbs, bufsize );
+00043             if(wcs && len!=size_t(-1) )
+00044                 wcs[len<bufsize-1? len: bufsize-1] = wchar_t('\0');
+00045             return len+1; // mbstowcs does not count null terminator
+00046 #endif
+00047         }
+00048 #else
+00049         void __TBB_EXPORTED_FUNC itt_set_sync_name_v3( void *obj, const char* name );
+00050 #endif
+00051     } // namespace internal
+00052 } // namespace tbb
+00053 
+00055 
+00057 #if _WIN32||_WIN64
+00058     #define __TBB_DEFINE_PROFILING_SET_NAME(sync_object_type)    \
+00059         namespace profiling {                                                       \
+00060             inline void set_name( sync_object_type& obj, const wchar_t* name ) {    \
+00061                 tbb::internal::itt_set_sync_name_v3( &obj, name );                  \
+00062             }                                                                       \
+00063             inline void set_name( sync_object_type& obj, const char* name ) {       \
+00064                 size_t len = tbb::internal::multibyte_to_widechar(NULL, name, 0);   \
+00065                 wchar_t *wname = new wchar_t[len];                                  \
+00066                 tbb::internal::multibyte_to_widechar(wname, name, len);             \
+00067                 set_name( obj, wname );                                             \
+00068                 delete[] wname;                                                     \
+00069             }                                                                       \
+00070         }
+00071 #else /* !WIN */
+00072     #define __TBB_DEFINE_PROFILING_SET_NAME(sync_object_type)    \
+00073         namespace profiling {                                                       \
+00074             inline void set_name( sync_object_type& obj, const char* name ) {       \
+00075                 tbb::internal::itt_set_sync_name_v3( &obj, name );                  \
+00076             }                                                                       \
+00077         }
+00078 #endif /* !WIN */
+00079 
+00080 #else /* no tools support */
+00081 
+00082 #if _WIN32||_WIN64
+00083     #define __TBB_DEFINE_PROFILING_SET_NAME(sync_object_type)    \
+00084         namespace profiling {                                               \
+00085             inline void set_name( sync_object_type&, const wchar_t* ) {}    \
+00086             inline void set_name( sync_object_type&, const char* ) {}       \
+00087         }
+00088 #else /* !WIN */
+00089     #define __TBB_DEFINE_PROFILING_SET_NAME(sync_object_type)    \
+00090         namespace profiling {                                               \
+00091             inline void set_name( sync_object_type&, const char* ) {}       \
+00092         }
+00093 #endif /* !WIN */
+00094 
+00095 #endif /* no tools support */
+00096 
+00097 #include "atomic.h"
+00098 // Need these to work regardless of tools support
+00099 namespace tbb {
+00100     namespace internal {
+00101 
+00102         enum notify_type {prepare=0, cancel, acquired, releasing};
+00103         const uintptr_t NUM_NOTIFY_TYPES = 4; // set to # elements in enum above
+00104 
+00105         void __TBB_EXPORTED_FUNC call_itt_notify_v5(int t, void *ptr);
+00106         void __TBB_EXPORTED_FUNC itt_store_pointer_with_release_v3(void *dst, void *src);
+00107         void* __TBB_EXPORTED_FUNC itt_load_pointer_with_acquire_v3(const void *src);
+00108         void* __TBB_EXPORTED_FUNC itt_load_pointer_v3( const void* src );
+00109 
+00110         // two template arguments are to workaround /Wp64 warning with tbb::atomic specialized for unsigned type
+00111         template <typename T, typename U>
+00112         inline void itt_store_word_with_release(tbb::atomic<T>& dst, U src) {
+00113 #if TBB_USE_THREADING_TOOLS
+00114             // This assertion should be replaced with static_assert
+00115             __TBB_ASSERT(sizeof(T) == sizeof(void *), "Type must be word-sized.");
+00116             itt_store_pointer_with_release_v3(&dst, (void *)uintptr_t(src));
+00117 #else
+00118             dst = src;
+00119 #endif // TBB_USE_THREADING_TOOLS
+00120         }
+00121 
+00122         template <typename T>
+00123         inline T itt_load_word_with_acquire(const tbb::atomic<T>& src) {
+00124 #if TBB_USE_THREADING_TOOLS
+00125             // This assertion should be replaced with static_assert
+00126             __TBB_ASSERT(sizeof(T) == sizeof(void *), "Type must be word-sized.");
+00127 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
+00128             // Workaround for overzealous compiler warnings
+00129             #pragma warning (push)
+00130             #pragma warning (disable: 4311)
+00131 #endif
+00132             T result = (T)itt_load_pointer_with_acquire_v3(&src);
+00133 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
+00134             #pragma warning (pop)
+00135 #endif
+00136             return result;
+00137 #else
+00138             return src;
+00139 #endif // TBB_USE_THREADING_TOOLS
+00140         }
+00141 
+00142         template <typename T>
+00143         inline void itt_store_word_with_release(T& dst, T src) {
+00144 #if TBB_USE_THREADING_TOOLS
+00145             // This assertion should be replaced with static_assert
+00146             __TBB_ASSERT(sizeof(T) == sizeof(void *), "Type must be word-sized.");
+00147             itt_store_pointer_with_release_v3(&dst, (void *)src);
+00148 #else
+00149             __TBB_store_with_release(dst, src); 
+00150 #endif // TBB_USE_THREADING_TOOLS
+00151         }
+00152 
+00153         template <typename T>
+00154         inline T itt_load_word_with_acquire(const T& src) {
+00155 #if TBB_USE_THREADING_TOOLS
+00156             // This assertion should be replaced with static_assert
+00157             __TBB_ASSERT(sizeof(T) == sizeof(void *), "Type must be word-sized");
+00158             return (T)itt_load_pointer_with_acquire_v3(&src);
+00159 #else
+00160             return __TBB_load_with_acquire(src);
+00161 #endif // TBB_USE_THREADING_TOOLS
+00162         }
+00163 
+00164         template <typename T>
+00165         inline void itt_hide_store_word(T& dst, T src) {
+00166 #if TBB_USE_THREADING_TOOLS
+00167             // This assertion should be replaced with static_assert
+00168             __TBB_ASSERT(sizeof(T) == sizeof(void *), "Type must be word-sized");
+00169             itt_store_pointer_with_release_v3(&dst, (void *)src);
+00170 #else
+00171             dst = src;
+00172 #endif
+00173         }
+00174 
+00175         template <typename T>
+00176         inline T itt_hide_load_word(const T& src) {
+00177 #if TBB_USE_THREADING_TOOLS
+00178             // This assertion should be replaced with static_assert
+00179             __TBB_ASSERT(sizeof(T) == sizeof(void *), "Type must be word-sized.");
+00180             return (T)itt_load_pointer_v3(&src);
+00181 #else
+00182             return src;
+00183 #endif
+00184         }
+00185 
+00186 #if TBB_USE_THREADING_TOOLS
+00187         inline void call_itt_notify(notify_type t, void *ptr) {
+00188             call_itt_notify_v5((int)t, ptr);
+00189         }
+00190 #else
+00191         inline void call_itt_notify(notify_type /*t*/, void * /*ptr*/) {}
+00192 #endif // TBB_USE_THREADING_TOOLS
+00193 
+00194     } // namespace internal
+00195 } // namespace tbb
+00196 
+00197 #endif /* __TBB_profiling_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00648.html b/src/tbb/doc/html/a00648.html new file mode 100644 index 0000000..81b0e16 --- /dev/null +++ b/src/tbb/doc/html/a00648.html @@ -0,0 +1,302 @@ + + +tbb_stddef.h Source File + + + + + + +

tbb_stddef.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_tbb_stddef_H
+00022 #define __TBB_tbb_stddef_H
+00023 
+00024 // Marketing-driven product version
+00025 #define TBB_VERSION_MAJOR 4
+00026 #define TBB_VERSION_MINOR 0
+00027 
+00028 // Engineering-focused interface version
+00029 #define TBB_INTERFACE_VERSION 6005
+00030 #define TBB_INTERFACE_VERSION_MAJOR TBB_INTERFACE_VERSION/1000
+00031 
+00032 // The oldest major interface version still supported
+00033 // To be used in SONAME, manifests, etc.
+00034 #define TBB_COMPATIBLE_INTERFACE_VERSION 2
+00035 
+00036 #define __TBB_STRING_AUX(x) #x
+00037 #define __TBB_STRING(x) __TBB_STRING_AUX(x)
+00038 
+00039 // We do not need defines below for resource processing on windows
+00040 #if !defined RC_INVOKED
+00041 
+00042 // Define groups for Doxygen documentation
+00052 // Simple text that is displayed on the main page of Doxygen documentation.
+00094 // Define preprocessor symbols used to determine architecture
+00095 #if _WIN32||_WIN64
+00096 #   if defined(_M_X64)||defined(__x86_64__)  // the latter for MinGW support
+00097 #       define __TBB_x86_64 1
+00098 #   elif defined(_M_IA64)
+00099 #       define __TBB_ipf 1
+00100 #   elif defined(_M_IX86)||defined(__i386__) // the latter for MinGW support
+00101 #       define __TBB_x86_32 1
+00102 #   endif
+00103 #else /* Assume generic Unix */
+00104 #   if !__linux__ && !__APPLE__
+00105 #       define __TBB_generic_os 1
+00106 #   endif
+00107 #   if __x86_64__
+00108 #       define __TBB_x86_64 1
+00109 #   elif __ia64__
+00110 #       define __TBB_ipf 1
+00111 #   elif __i386__||__i386  // __i386 is for Sun OS
+00112 #       define __TBB_x86_32 1
+00113 #   else
+00114 #       define __TBB_generic_arch 1
+00115 #   endif
+00116 #endif
+00117 
+00118 // tbb_config.h should be included the first since it contains macro definitions used in other headers
+00119 #include "tbb_config.h"
+00120 
+00121 #if _MSC_VER >=1400
+00122     #define __TBB_EXPORTED_FUNC   __cdecl
+00123     #define __TBB_EXPORTED_METHOD __thiscall
+00124 #else
+00125     #define __TBB_EXPORTED_FUNC
+00126     #define __TBB_EXPORTED_METHOD
+00127 #endif
+00128 
+00129 #if __INTEL_COMPILER || _MSC_VER
+00130 #define __TBB_NOINLINE(decl) __declspec(noinline) decl
+00131 #elif __GNUC__
+00132 #define __TBB_NOINLINE(decl) decl __attribute__ ((noinline))
+00133 #else
+00134 #define __TBB_NOINLINE(decl) decl
+00135 #endif
+00136 
+00137 #include <cstddef>      /* Need size_t and ptrdiff_t */
+00138 
+00139 #if _MSC_VER
+00140     #define __TBB_tbb_windef_H
+00141     #include "internal/_tbb_windef.h"
+00142     #undef __TBB_tbb_windef_H
+00143 #endif
+00144 #if !defined(_MSC_VER) || _MSC_VER>=1600
+00145     #include <stdint.h>
+00146 #endif
+00147 
+00149 typedef void(*assertion_handler_type)( const char* filename, int line, const char* expression, const char * comment );
+00150 
+00151 #if TBB_USE_ASSERT
+00152 
+00153      #define __TBB_ASSERT_NS(predicate,message,ns) ((predicate)?((void)0) : ns::assertion_failure(__FILE__,__LINE__,#predicate,message))
+00155 
+00158 #if __TBBMALLOC_BUILD
+00159 namespace rml { namespace internal {
+00160     #define __TBB_ASSERT(predicate,message) __TBB_ASSERT_NS(predicate,message,rml::internal)
+00161 #else
+00162 namespace tbb {
+00163     #define __TBB_ASSERT(predicate,message) __TBB_ASSERT_NS(predicate,message,tbb)
+00164 #endif
+00165 
+00166     #define __TBB_ASSERT_EX __TBB_ASSERT
+00167 
+00169     assertion_handler_type __TBB_EXPORTED_FUNC set_assertion_handler( assertion_handler_type new_handler );
+00170 
+00172 
+00175     void __TBB_EXPORTED_FUNC assertion_failure( const char* filename, int line, const char* expression, const char* comment );
+00176 
+00177 #if __TBBMALLOC_BUILD
+00178 }}  // namespace rml::internal
+00179 #else
+00180 } // namespace tbb
+00181 #endif
+00182 #else /* !TBB_USE_ASSERT */
+00183 
+00185     #define __TBB_ASSERT(predicate,comment) ((void)0)
+00187     #define __TBB_ASSERT_EX(predicate,comment) ((void)(1 && (predicate)))
+00188 
+00189 #endif /* !TBB_USE_ASSERT */
+00190 
+00192 namespace tbb {
+00193 
+00194 #if _MSC_VER && _MSC_VER<1600
+00195     namespace internal {
+00196         typedef __int8 int8_t;
+00197         typedef __int16 int16_t;
+00198         typedef __int32 int32_t;
+00199         typedef __int64 int64_t;
+00200         typedef unsigned __int8 uint8_t;
+00201         typedef unsigned __int16 uint16_t;
+00202         typedef unsigned __int32 uint32_t;
+00203         typedef unsigned __int64 uint64_t;
+00204     } // namespace internal
+00205 #else /* Posix */
+00206     namespace internal {
+00207         using ::int8_t;
+00208         using ::int16_t;
+00209         using ::int32_t;
+00210         using ::int64_t;
+00211         using ::uint8_t;
+00212         using ::uint16_t;
+00213         using ::uint32_t;
+00214         using ::uint64_t;
+00215     } // namespace internal
+00216 #endif /* Posix */
+00217 
+00218     using std::size_t;
+00219     using std::ptrdiff_t;
+00220 
+00222 
+00226 extern "C" int __TBB_EXPORTED_FUNC TBB_runtime_interface_version();
+00227 
+00229 
+00233 class split {
+00234 };
+00235 
+00240 namespace internal {
+00241 
+00243 
+00246 const size_t NFS_MaxLineSize = 128;
+00247 
+00267 #define __TBB_atomic // intentionally empty, see above
+00268 
+00269 template<class T, int S>
+00270 struct padded_base : T {
+00271     char pad[NFS_MaxLineSize - sizeof(T) % NFS_MaxLineSize];
+00272 };
+00273 template<class T> struct padded_base<T, 0> : T {};
+00274 
+00276 template<class T>
+00277 struct padded : padded_base<T, sizeof(T)> {};
+00278 
+00280 
+00282 #define __TBB_offsetof(class_name, member_name) \
+00283     ((ptrdiff_t)&(reinterpret_cast<class_name*>(0x1000)->member_name) - 0x1000)
+00284 
+00286 #define __TBB_get_object_ref(class_name, member_name, member_addr) \
+00287     (*reinterpret_cast<class_name*>((char*)member_addr - __TBB_offsetof(class_name, member_name)))
+00288 
+00290 void __TBB_EXPORTED_FUNC handle_perror( int error_code, const char* aux_info );
+00291 
+00292 #if TBB_USE_EXCEPTIONS
+00293     #define __TBB_TRY try
+00294     #define __TBB_CATCH(e) catch(e)
+00295     #define __TBB_THROW(e) throw e
+00296     #define __TBB_RETHROW() throw
+00297 #else /* !TBB_USE_EXCEPTIONS */
+00298     inline bool __TBB_false() { return false; }
+00299     #define __TBB_TRY
+00300     #define __TBB_CATCH(e) if ( tbb::internal::__TBB_false() )
+00301     #define __TBB_THROW(e) ((void)0)
+00302     #define __TBB_RETHROW() ((void)0)
+00303 #endif /* !TBB_USE_EXCEPTIONS */
+00304 
+00306 void __TBB_EXPORTED_FUNC runtime_warning( const char* format, ... );
+00307 
+00308 #if TBB_USE_ASSERT
+00309 static void* const poisoned_ptr = reinterpret_cast<void*>(-1);
+00310 
+00312 template<typename T>
+00313 inline void poison_pointer( T*& p ) { p = reinterpret_cast<T*>(poisoned_ptr); }
+00314 
+00316 template<typename T>
+00317 inline bool is_poisoned( T* p ) { return p == reinterpret_cast<T*>(poisoned_ptr); }
+00318 #else
+00319 template<typename T>
+00320 inline void poison_pointer( T* ) {/*do nothing*/}
+00321 #endif /* !TBB_USE_ASSERT */
+00322 
+00324 
+00326 template<typename T, typename U> 
+00327 inline T punned_cast( U* ptr ) {
+00328     uintptr_t x = reinterpret_cast<uintptr_t>(ptr);
+00329     return reinterpret_cast<T>(x);
+00330 }
+00331 
+00333 class no_assign {
+00334     // Deny assignment
+00335     void operator=( const no_assign& );
+00336 public:
+00337 #if __GNUC__
+00339     no_assign() {}
+00340 #endif /* __GNUC__ */
+00341 };
+00342 
+00344 class no_copy: no_assign {
+00346     no_copy( const no_copy& );
+00347 public:
+00349     no_copy() {}
+00350 };
+00351 
+00353 template<typename T>
+00354 struct allocator_type {
+00355     typedef T value_type;
+00356 };
+00357 
+00358 #if _MSC_VER
+00360 template<typename T>
+00361 struct allocator_type<const T> {
+00362     typedef T value_type;
+00363 };
+00364 #endif
+00365 
+00367 inline size_t size_t_select( unsigned u, unsigned long long ull ) {
+00368     /* Explicit cast of the arguments to size_t is done to avoid compiler warnings
+00369        (e.g. by Clang and MSVC) about possible truncation. The value of the right size,
+00370        which is selected by ?:, is anyway not truncated or promoted.
+00371        MSVC still warns if this trick is applied directly to constants, hence this function. */
+00372     return (sizeof(size_t)==sizeof(u)) ? size_t(u) : size_t(ull);
+00373 }
+00374 
+00375 // Struct to be used as a version tag for inline functions.
+00378 struct version_tag_v3 {};
+00379 
+00380 typedef version_tag_v3 version_tag;
+00381 
+00382 } // internal
+00384 
+00385 } // tbb
+00386 
+00387 #endif /* RC_INVOKED */
+00388 #endif /* __TBB_tbb_stddef_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00655.html b/src/tbb/doc/html/a00655.html new file mode 100644 index 0000000..baea25f --- /dev/null +++ b/src/tbb/doc/html/a00655.html @@ -0,0 +1,298 @@ + + +tbb_thread.h Source File + + + + + + +

tbb_thread.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_tbb_thread_H
+00022 #define __TBB_tbb_thread_H
+00023 
+00024 #if _WIN32||_WIN64
+00025 #include "machine/windows_api.h"
+00026 #define __TBB_NATIVE_THREAD_ROUTINE unsigned WINAPI
+00027 #define __TBB_NATIVE_THREAD_ROUTINE_PTR(r) unsigned (WINAPI* r)( void* )
+00028 #else
+00029 #define __TBB_NATIVE_THREAD_ROUTINE void*
+00030 #define __TBB_NATIVE_THREAD_ROUTINE_PTR(r) void* (*r)( void* )
+00031 #include <pthread.h>
+00032 #endif // _WIN32||_WIN64
+00033 
+00034 #include "tbb_stddef.h"
+00035 #include "tick_count.h"
+00036 
+00037 #if !TBB_USE_EXCEPTIONS && _MSC_VER
+00038     // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers
+00039     #pragma warning (push)
+00040     #pragma warning (disable: 4530)
+00041 #endif
+00042 
+00043 #include <iosfwd>
+00044 
+00045 #if !TBB_USE_EXCEPTIONS && _MSC_VER
+00046     #pragma warning (pop)
+00047 #endif
+00048 
+00049 namespace tbb {
+00050 
+00052 namespace internal {
+00053     
+00054     class tbb_thread_v3;
+00055 
+00056 } // namespace internal
+00057 
+00058 inline void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 ); 
+00059 
+00060 namespace internal {
+00061 
+00063     void* __TBB_EXPORTED_FUNC allocate_closure_v3( size_t size );
+00065     void __TBB_EXPORTED_FUNC free_closure_v3( void* );
+00066    
+00067     struct thread_closure_base {
+00068         void* operator new( size_t size ) {return allocate_closure_v3(size);}
+00069         void operator delete( void* ptr ) {free_closure_v3(ptr);}
+00070     };
+00071 
+00072     template<class F> struct thread_closure_0: thread_closure_base {
+00073         F function;
+00074 
+00075         static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
+00076             thread_closure_0 *self = static_cast<thread_closure_0*>(c);
+00077             self->function();
+00078             delete self;
+00079             return 0;
+00080         }
+00081         thread_closure_0( const F& f ) : function(f) {}
+00082     };
+00084     template<class F, class X> struct thread_closure_1: thread_closure_base {
+00085         F function;
+00086         X arg1;
+00088         static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
+00089             thread_closure_1 *self = static_cast<thread_closure_1*>(c);
+00090             self->function(self->arg1);
+00091             delete self;
+00092             return 0;
+00093         }
+00094         thread_closure_1( const F& f, const X& x ) : function(f), arg1(x) {}
+00095     };
+00096     template<class F, class X, class Y> struct thread_closure_2: thread_closure_base {
+00097         F function;
+00098         X arg1;
+00099         Y arg2;
+00101         static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) {
+00102             thread_closure_2 *self = static_cast<thread_closure_2*>(c);
+00103             self->function(self->arg1, self->arg2);
+00104             delete self;
+00105             return 0;
+00106         }
+00107         thread_closure_2( const F& f, const X& x, const Y& y ) : function(f), arg1(x), arg2(y) {}
+00108     };
+00109 
+00111     class tbb_thread_v3 {
+00112         tbb_thread_v3(const tbb_thread_v3&); // = delete;   // Deny access
+00113     public:
+00114 #if _WIN32||_WIN64
+00115         typedef HANDLE native_handle_type; 
+00116 #else
+00117         typedef pthread_t native_handle_type; 
+00118 #endif // _WIN32||_WIN64
+00119 
+00120         class id;
+00122         tbb_thread_v3() : my_handle(0)
+00123 #if _WIN32||_WIN64
+00124             , my_thread_id(0)
+00125 #endif // _WIN32||_WIN64
+00126         {}
+00127         
+00129         template <class F> explicit tbb_thread_v3(F f) {
+00130             typedef internal::thread_closure_0<F> closure_type;
+00131             internal_start(closure_type::start_routine, new closure_type(f));
+00132         }
+00134         template <class F, class X> tbb_thread_v3(F f, X x) {
+00135             typedef internal::thread_closure_1<F,X> closure_type;
+00136             internal_start(closure_type::start_routine, new closure_type(f,x));
+00137         }
+00139         template <class F, class X, class Y> tbb_thread_v3(F f, X x, Y y) {
+00140             typedef internal::thread_closure_2<F,X,Y> closure_type;
+00141             internal_start(closure_type::start_routine, new closure_type(f,x,y));
+00142         }
+00143 
+00144         tbb_thread_v3& operator=(tbb_thread_v3& x) {
+00145             if (joinable()) detach();
+00146             my_handle = x.my_handle;
+00147             x.my_handle = 0;
+00148 #if _WIN32||_WIN64
+00149             my_thread_id = x.my_thread_id;
+00150             x.my_thread_id = 0;
+00151 #endif // _WIN32||_WIN64
+00152             return *this;
+00153         }
+00154         void swap( tbb_thread_v3& t ) {tbb::swap( *this, t );}
+00155         bool joinable() const {return my_handle!=0; }
+00157         void __TBB_EXPORTED_METHOD join();
+00159         void __TBB_EXPORTED_METHOD detach();
+00160         ~tbb_thread_v3() {if( joinable() ) detach();}
+00161         inline id get_id() const;
+00162         native_handle_type native_handle() { return my_handle; }
+00163     
+00165 
+00174         static unsigned __TBB_EXPORTED_FUNC hardware_concurrency();
+00175     private:
+00176         native_handle_type my_handle; 
+00177 #if _WIN32||_WIN64
+00178         DWORD my_thread_id;
+00179 #endif // _WIN32||_WIN64
+00180 
+00182         void __TBB_EXPORTED_METHOD internal_start( __TBB_NATIVE_THREAD_ROUTINE_PTR(start_routine), 
+00183                              void* closure );
+00184         friend void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 );
+00185         friend void tbb::swap( tbb_thread_v3& t1, tbb_thread_v3& t2 ); 
+00186     };
+00187         
+00188     class tbb_thread_v3::id { 
+00189 #if _WIN32||_WIN64
+00190         DWORD my_id;
+00191         id( DWORD id_ ) : my_id(id_) {}
+00192 #else
+00193         pthread_t my_id;
+00194         id( pthread_t id_ ) : my_id(id_) {}
+00195 #endif // _WIN32||_WIN64
+00196         friend class tbb_thread_v3;
+00197     public:
+00198         id() : my_id(0) {}
+00199 
+00200         friend bool operator==( tbb_thread_v3::id x, tbb_thread_v3::id y );
+00201         friend bool operator!=( tbb_thread_v3::id x, tbb_thread_v3::id y );
+00202         friend bool operator<( tbb_thread_v3::id x, tbb_thread_v3::id y );
+00203         friend bool operator<=( tbb_thread_v3::id x, tbb_thread_v3::id y );
+00204         friend bool operator>( tbb_thread_v3::id x, tbb_thread_v3::id y );
+00205         friend bool operator>=( tbb_thread_v3::id x, tbb_thread_v3::id y );
+00206         
+00207         template<class charT, class traits>
+00208         friend std::basic_ostream<charT, traits>&
+00209         operator<< (std::basic_ostream<charT, traits> &out, 
+00210                     tbb_thread_v3::id id)
+00211         {
+00212             out << id.my_id;
+00213             return out;
+00214         }
+00215         friend tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3();
+00216     }; // tbb_thread_v3::id
+00217 
+00218     tbb_thread_v3::id tbb_thread_v3::get_id() const {
+00219 #if _WIN32||_WIN64
+00220         return id(my_thread_id);
+00221 #else
+00222         return id(my_handle);
+00223 #endif // _WIN32||_WIN64
+00224     }
+00225     void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 );
+00226     tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3();
+00227     void __TBB_EXPORTED_FUNC thread_yield_v3();
+00228     void __TBB_EXPORTED_FUNC thread_sleep_v3(const tick_count::interval_t &i);
+00229 
+00230     inline bool operator==(tbb_thread_v3::id x, tbb_thread_v3::id y)
+00231     {
+00232         return x.my_id == y.my_id;
+00233     }
+00234     inline bool operator!=(tbb_thread_v3::id x, tbb_thread_v3::id y)
+00235     {
+00236         return x.my_id != y.my_id;
+00237     }
+00238     inline bool operator<(tbb_thread_v3::id x, tbb_thread_v3::id y)
+00239     {
+00240         return x.my_id < y.my_id;
+00241     }
+00242     inline bool operator<=(tbb_thread_v3::id x, tbb_thread_v3::id y)
+00243     {
+00244         return x.my_id <= y.my_id;
+00245     }
+00246     inline bool operator>(tbb_thread_v3::id x, tbb_thread_v3::id y)
+00247     {
+00248         return x.my_id > y.my_id;
+00249     }
+00250     inline bool operator>=(tbb_thread_v3::id x, tbb_thread_v3::id y)
+00251     {
+00252         return x.my_id >= y.my_id;
+00253     }
+00254 
+00255 } // namespace internal;
+00256 
+00258 typedef internal::tbb_thread_v3 tbb_thread;
+00259 
+00260 using internal::operator==;
+00261 using internal::operator!=;
+00262 using internal::operator<;
+00263 using internal::operator>;
+00264 using internal::operator<=;
+00265 using internal::operator>=;
+00266 
+00267 inline void move( tbb_thread& t1, tbb_thread& t2 ) {
+00268     internal::move_v3(t1, t2);
+00269 }
+00270 
+00271 inline void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 ) {
+00272     tbb::tbb_thread::native_handle_type h = t1.my_handle;
+00273     t1.my_handle = t2.my_handle;
+00274     t2.my_handle = h;
+00275 #if _WIN32||_WIN64
+00276     DWORD i = t1.my_thread_id;
+00277     t1.my_thread_id = t2.my_thread_id;
+00278     t2.my_thread_id = i;
+00279 #endif /* _WIN32||_WIN64 */
+00280 }
+00281 
+00282 namespace this_tbb_thread {
+00283     inline tbb_thread::id get_id() { return internal::thread_get_id_v3(); }
+00285     inline void yield() { internal::thread_yield_v3(); }
+00287     inline void sleep(const tick_count::interval_t &i) { 
+00288         internal::thread_sleep_v3(i);  
+00289     }
+00290 }  // namespace this_tbb_thread
+00291 
+00292 } // namespace tbb
+00293 
+00294 #endif /* __TBB_tbb_thread_H */
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00663.html b/src/tbb/doc/html/a00663.html new file mode 100644 index 0000000..ad2e389 --- /dev/null +++ b/src/tbb/doc/html/a00663.html @@ -0,0 +1,96 @@ + + +tbbmalloc_proxy.h Source File + + + + + + +

tbbmalloc_proxy.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 /*
+00022 Replacing the standard memory allocation routines in Microsoft* C/C++ RTL 
+00023 (malloc/free, global new/delete, etc.) with the TBB memory allocator. 
+00024 
+00025 Include the following header to a source of any binary which is loaded during 
+00026 application startup
+00027 
+00028 #include "tbb/tbbmalloc_proxy.h"
+00029 
+00030 or add following parameters to the linker options for the binary which is 
+00031 loaded during application startup. It can be either exe-file or dll.
+00032 
+00033 For win32
+00034 tbbmalloc_proxy.lib /INCLUDE:"___TBB_malloc_proxy"
+00035 win64
+00036 tbbmalloc_proxy.lib /INCLUDE:"__TBB_malloc_proxy"
+00037 */
+00038 
+00039 #ifndef __TBB_tbbmalloc_proxy_H
+00040 #define __TBB_tbbmalloc_proxy_H
+00041 
+00042 #if _MSC_VER
+00043 
+00044 #ifdef _DEBUG
+00045     #pragma comment(lib, "tbbmalloc_proxy_debug.lib")
+00046 #else
+00047     #pragma comment(lib, "tbbmalloc_proxy.lib")
+00048 #endif
+00049 
+00050 #if defined(_WIN64)
+00051     #pragma comment(linker, "/include:__TBB_malloc_proxy")
+00052 #else
+00053     #pragma comment(linker, "/include:___TBB_malloc_proxy")
+00054 #endif
+00055 
+00056 #else
+00057 /* Primarily to support MinGW */
+00058 
+00059 extern "C" void __TBB_malloc_proxy();
+00060 struct __TBB_malloc_proxy_caller {
+00061     __TBB_malloc_proxy_caller() { __TBB_malloc_proxy(); }
+00062 } volatile __TBB_malloc_proxy_helper_object;
+00063 
+00064 #endif // _MSC_VER
+00065 
+00066 #endif //__TBB_tbbmalloc_proxy_H
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/a00665.html b/src/tbb/doc/html/a00665.html new file mode 100644 index 0000000..e6ecab1 --- /dev/null +++ b/src/tbb/doc/html/a00665.html @@ -0,0 +1,164 @@ + + +tick_count.h Source File + + + + + + +

tick_count.h

00001 /*
+00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
+00003 
+00004     The source code contained or described herein and all documents related
+00005     to the source code ("Material") are owned by Intel Corporation or its
+00006     suppliers or licensors.  Title to the Material remains with Intel
+00007     Corporation or its suppliers and licensors.  The Material is protected
+00008     by worldwide copyright laws and treaty provisions.  No part of the
+00009     Material may be used, copied, reproduced, modified, published, uploaded,
+00010     posted, transmitted, distributed, or disclosed in any way without
+00011     Intel's prior express written permission.
+00012 
+00013     No license under any patent, copyright, trade secret or other
+00014     intellectual property right is granted to or conferred upon you by
+00015     disclosure or delivery of the Materials, either expressly, by
+00016     implication, inducement, estoppel or otherwise.  Any license under such
+00017     intellectual property rights must be express and approved by Intel in
+00018     writing.
+00019 */
+00020 
+00021 #ifndef __TBB_tick_count_H
+00022 #define __TBB_tick_count_H
+00023 
+00024 #include "tbb_stddef.h"
+00025 
+00026 #if _WIN32||_WIN64
+00027 #include "machine/windows_api.h"
+00028 #elif __linux__
+00029 #include <ctime>
+00030 #else /* generic Unix */
+00031 #include <sys/time.h>
+00032 #endif /* (choice of OS) */
+00033 
+00034 namespace tbb {
+00035 
+00037 
+00038 class tick_count {
+00039 public:
+00041     class interval_t {
+00042         long long value;
+00043         explicit interval_t( long long value_ ) : value(value_) {}
+00044     public:
+00046         interval_t() : value(0) {};
+00047 
+00049         explicit interval_t( double sec );
+00050 
+00052         double seconds() const;
+00053 
+00054         friend class tbb::tick_count;
+00055 
+00057         friend interval_t operator-( const tick_count& t1, const tick_count& t0 );
+00058 
+00060         friend interval_t operator+( const interval_t& i, const interval_t& j ) {
+00061             return interval_t(i.value+j.value);
+00062         }
+00063 
+00065         friend interval_t operator-( const interval_t& i, const interval_t& j ) {
+00066             return interval_t(i.value-j.value);
+00067         }
+00068 
+00070         interval_t& operator+=( const interval_t& i ) {value += i.value; return *this;}
+00071 
+00073         interval_t& operator-=( const interval_t& i ) {value -= i.value; return *this;}
+00074     };
+00075     
+00077     tick_count() : my_count(0) {};
+00078 
+00080     static tick_count now();
+00081     
+00083     friend interval_t operator-( const tick_count& t1, const tick_count& t0 );
+00084 
+00085 private:
+00086     long long my_count;
+00087 };
+00088 
+00089 inline tick_count tick_count::now() {
+00090     tick_count result;
+00091 #if _WIN32||_WIN64
+00092     LARGE_INTEGER qpcnt;
+00093     QueryPerformanceCounter(&qpcnt);
+00094     result.my_count = qpcnt.QuadPart;
+00095 #elif __linux__
+00096     struct timespec ts;
+00097 #if TBB_USE_ASSERT
+00098     int status = 
+00099 #endif /* TBB_USE_ASSERT */
+00100         clock_gettime( CLOCK_REALTIME, &ts );
+00101     __TBB_ASSERT( status==0, "CLOCK_REALTIME not supported" );
+00102     result.my_count = static_cast<long long>(1000000000UL)*static_cast<long long>(ts.tv_sec) + static_cast<long long>(ts.tv_nsec);
+00103 #else /* generic Unix */
+00104     struct timeval tv;
+00105 #if TBB_USE_ASSERT
+00106     int status = 
+00107 #endif /* TBB_USE_ASSERT */
+00108         gettimeofday(&tv, NULL);
+00109     __TBB_ASSERT( status==0, "gettimeofday failed" );
+00110     result.my_count = static_cast<long long>(1000000)*static_cast<long long>(tv.tv_sec) + static_cast<long long>(tv.tv_usec);
+00111 #endif /*(choice of OS) */
+00112     return result;
+00113 }
+00114 
+00115 inline tick_count::interval_t::interval_t( double sec )
+00116 {
+00117 #if _WIN32||_WIN64
+00118     LARGE_INTEGER qpfreq;
+00119     QueryPerformanceFrequency(&qpfreq);
+00120     value = static_cast<long long>(sec*qpfreq.QuadPart);
+00121 #elif __linux__
+00122     value = static_cast<long long>(sec*1E9);
+00123 #else /* generic Unix */
+00124     value = static_cast<long long>(sec*1E6);
+00125 #endif /* (choice of OS) */
+00126 }
+00127 
+00128 inline tick_count::interval_t operator-( const tick_count& t1, const tick_count& t0 ) {
+00129     return tick_count::interval_t( t1.my_count-t0.my_count );
+00130 }
+00131 
+00132 inline double tick_count::interval_t::seconds() const {
+00133 #if _WIN32||_WIN64
+00134     LARGE_INTEGER qpfreq;
+00135     QueryPerformanceFrequency(&qpfreq);
+00136     return value/(double)qpfreq.QuadPart;
+00137 #elif __linux__
+00138     return value*1E-9;
+00139 #else /* generic Unix */
+00140     return value*1E-6;
+00141 #endif /* (choice of OS) */
+00142 }
+00143 
+00144 } // namespace tbb
+00145 
+00146 #endif /* __TBB_tick_count_H */
+00147 
+

+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/annotated.html b/src/tbb/doc/html/annotated.html new file mode 100644 index 0000000..2293f51 --- /dev/null +++ b/src/tbb/doc/html/annotated.html @@ -0,0 +1,139 @@ + + +Class List + + + + + + +

Class List

Here are the classes, structs, unions and interfaces with brief descriptions: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
tbb::affinity_partitionerAn affinity partitioner
tbb::internal::affinity_partitioner_base_v3Defines entry point for affinity partitioner into tbb run-time library
tbb::interface6::aggregatorBasic aggregator interface
tbb::interface6::aggregator_ext< handler_type >Aggregator base class and expert interface
tbb::aligned_space< T, N >Block of space aligned sufficiently to construct an array T with N elements
tbb::atomic< T >Primary template for atomic
tbb::atomic< void * >Specialization for atomic<void*>, for sake of not allowing arithmetic or operator->
tbb::internal::atomic_backoffClass that implements exponential backoff
tbb::auto_partitionerAn auto partitioner
tbb::bad_last_allocException for concurrent containers
tbb::blocked_range< Value >A range over which to iterate
tbb::blocked_range2d< RowValue, ColValue >A 2-dimensional range that models the Range concept
tbb::blocked_range3d< PageValue, RowValue, ColValue >A 3-dimensional range that models the Range concept
tbb::flow::interface6::broadcast_node< T >Forwards messages of type T to all successors
tbb::flow::interface6::buffer_node< T, A >Forwards messages in arbitrary order
tbb::cache_aligned_allocator< T >Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5
tbb::cache_aligned_allocator< void >Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1
tbb::captured_exceptionThis class is used by TBB to propagate information about unhandled exceptions into the root thread
tbb::combinable< T >Thread-local storage with optional reduction
tbb::concurrent_bounded_queue< T, A >A high-performance thread-safe blocking concurrent bounded queue
tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >Unordered map from Key to T
tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::accessorAllows write access to elements and combines data access, locking, and garbage collection
tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::bucket_accessorBucket accessor is to find, rehash, acquire a lock, and access a bucket
tbb::interface5::concurrent_hash_map< Key, T, HashCompare, Allocator >::const_accessorCombines data access, locking, and garbage collection
tbb::interface5::concurrent_priority_queue< T, Compare, A >Concurrent priority queue
tbb::strict_ppl::concurrent_queue< T, A >A high-performance thread-safe non-blocking concurrent queue
tbb::deprecated::concurrent_queue< T, A >A high-performance thread-safe blocking concurrent bounded queue
tbb::concurrent_vector< T, A >Concurrent vector container
tbb::flow::interface6::continue_msgAn empty class used for messages that mean "I'm done"
tbb::flow::interface6::continue_node< Output >Implements an executable node that supports continue_msg -> Output
tbb::flow::interface6::continue_receiverBase class for receivers of completion messages
tbb::empty_taskTask that does nothing. Useful for synchronization
tbb::interface6::enumerable_thread_specific< T, Allocator, ETS_key_type >The enumerable_thread_specific container
tbb::filterA stage in a pipeline
tbb::interface6::filter_t< T, U >Class representing a chain of type-safe pipeline filters
tbb::final_scan_tagUsed to indicate that the final scan is being performed
tbb::interface6::flow_controlInput_filter control to signal end-of-input for parallel_pipeline
tbb::flow::interface6::function_node< Input, Output,, Allocator >Implements a function node that supports Input -> Output
tbb::flow::interface6::function_node< Input, Output, queueing, Allocator >Implements a function node that supports Input -> Output
tbb::flow::interface6::graphThe graph class
tbb::flow::interface6::graph_nodeThe base of all graph nodes
tbb::improper_lockException for PPL locks
tbb::invalid_multiple_schedulingException for repeated scheduling of the same task_handle
tbb::flow::interface6::limiter_node< T >Forwards messages only if the threshold has not been reached
tbb::internal::machine_load_store_relaxed< T, S >
tbb::internal::machine_load_store_seq_cst< T, 8 >
tbb::interface6::memory_pool< Alloc >Thread-safe growable pool allocator for variable-size requests
tbb::interface6::memory_pool_allocator< T, P >Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5
tbb::interface6::memory_pool_allocator< void, P >Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1
tbb::missing_waitException for missing wait on structured_task_group
tbb::movable_exception< ExceptionData >Template that can be used to implement exception that transfers arbitrary ExceptionData to the root thread
tbb::flow::interface6::multifunction_node< Input, Output,, Allocator >Implements a function node that supports Input -> (set of outputs)
tbb::mutexWrapper around the platform's native reader-writer lock
tbb::mutex::scoped_lockThe scoped locking pattern
tbb::null_mutexA mutex which does nothing
tbb::null_mutex::scoped_lockRepresents acquisition of a mutex
tbb::null_rw_mutexA rw mutex which does nothing
tbb::null_rw_mutex::scoped_lockRepresents acquisition of a mutex
tbb::parallel_do_feeder< Item >Class the user supplied algorithm body uses to add new tasks
tbb::parallel_while< Body >Parallel iteration over a stream, with optional addition of more work
tbb::internal::partition_type_baseProvides backward-compatible methods for partition objects without affinity
tbb::pipelineA processing pipeline that applies filters to items
tbb::pre_scan_tagUsed to indicate that the initial scan is being performed
tbb::flow::interface6::priority_queue_node< T, Compare, A >Forwards messages in priority order
tbb::flow::interface6::queue_node< T, A >Forwards messages in FIFO order
tbb::queuing_mutexQueuing mutex with local-only spinning
tbb::queuing_mutex::scoped_lockThe scoped locking pattern
tbb::queuing_rw_mutexQueuing reader-writer mutex with local-only spinning
tbb::queuing_rw_mutex::scoped_lockThe scoped locking pattern
tbb::interface5::reader_writer_lockWriter-preference reader-writer lock with local-only spinning on readers
tbb::interface5::reader_writer_lock::scoped_lockThe scoped lock pattern for write locks
tbb::interface5::reader_writer_lock::scoped_lock_readThe scoped lock pattern for read locks
tbb::flow::interface6::receiver< T >Pure virtual template class that defines a receiver of messages of type T
tbb::recursive_mutexMutex that allows recursive mutex acquisition
tbb::recursive_mutex::scoped_lockThe scoped locking pattern
tbb::interface6::runtime_loaderLoad TBB at runtime
tbb::scalable_allocator< T >Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5
tbb::scalable_allocator< void >Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1
tbb::flow::interface6::sender< T >Pure virtual template class that defines a sender of messages of type T
tbb::flow::interface6::sequencer_node< T, A >Forwards messages in sequence order
tbb::simple_partitionerA simple partitioner
tbb::flow::interface6::source_node< Output >An executable node that acts as a source, i.e. it has no predecessors
tbb::spin_mutexA lock that occupies a single byte
tbb::spin_mutex::scoped_lockRepresents acquisition of a mutex
tbb::spin_rw_mutex_v3Fast, unfair, spinning reader-writer lock with backoff and writer-preference
tbb::spin_rw_mutex_v3::scoped_lockThe scoped locking pattern
tbb::splitDummy type that distinguishes splitting constructor from copy constructor
tbb::flow::interface6::split_node< TupleType, Allocator >Split_node: accepts a tuple as input, forwards each element of the tuple to its
tbb::taskBase class for user-defined tasks
tbb::interface5::internal::task_baseBase class for methods that became static in TBB 3.0
tbb::task_group_context
tbb::task_group_contextUsed to form groups of tasks
tbb::task_listA list of children
tbb::task_scheduler_initClass delimiting the scope of task scheduler activity
tbb::tbb_allocator< T >Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5
tbb::tbb_allocator< void >Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1
tbb::tbb_exceptionInterface to be implemented by all exceptions TBB recognizes and propagates across the threads
tbb::internal::tbb_exception_ptrException container that preserves the exact copy of the original exception
tbb::tbb_hash_compare< Key >Hash_compare that is default argument for concurrent_hash_map
tbb::thread_bound_filterA stage in a pipeline served by a user thread
tbb::tick_countAbsolute timestamp
tbb::tick_count::interval_tRelative time interval
tbb::user_abortException for user-initiated abort
tbb::internal::work_around_alignment_bug< Size, T >Work around for bug in GNU 3.2 and MSVC compilers
tbb::zero_allocator< T, Allocator >Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5
tbb::zero_allocator< void, Allocator >Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1
+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/concepts.html b/src/tbb/doc/html/concepts.html new file mode 100644 index 0000000..75a2bf9 --- /dev/null +++ b/src/tbb/doc/html/concepts.html @@ -0,0 +1,31 @@ + + +TBB concepts + + + + + + +

TBB concepts

A concept is a set of requirements to a type, which are necessary and sufficient for the type to model a particular behavior or a set of behaviors. Some concepts are specific to a particular algorithm (e.g. algorithm body), while other ones are common to several algorithms (e.g. range concept).

+All TBB algorithms make use of different classes implementing various concepts. Implementation classes are supplied by the user as type arguments of template parameters and/or as objects passed as function call arguments. The library provides predefined implementations of some concepts (e.g. several kinds of ranges), while other ones must always be implemented by the user.

+TBB defines a set of minimal requirements each concept must conform to. Here is the list of different concepts hyperlinked to the corresponding requirements specifications:

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/deprecated.html b/src/tbb/doc/html/deprecated.html new file mode 100644 index 0000000..66a2611 --- /dev/null +++ b/src/tbb/doc/html/deprecated.html @@ -0,0 +1,29 @@ + + +Deprecated List + + + + + +

Deprecated List

+
Member tbb::deprecated::concurrent_queue::pop_if_present (T &destination)
+
Use try_pop()
+
+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/doxygen.css b/src/tbb/doc/html/doxygen.css new file mode 100644 index 0000000..5d58369 --- /dev/null +++ b/src/tbb/doc/html/doxygen.css @@ -0,0 +1,358 @@ +BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { + font-family: Geneva, Arial, Helvetica, sans-serif; +} +BODY,TD { + font-size: 90%; +} +H1 { + text-align: center; + font-size: 160%; +} +H2 { + font-size: 120%; +} +H3 { + font-size: 100%; +} +CAPTION { font-weight: bold } +DIV.qindex { + width: 100%; + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.nav { + width: 100%; + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.navtab { + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +TD.navtab { + font-size: 70%; +} +A.qindex { + text-decoration: none; + font-weight: bold; + color: #1A419D; +} +A.qindex:visited { + text-decoration: none; + font-weight: bold; + color: #1A419D +} +A.qindex:hover { + text-decoration: none; + background-color: #ddddff; +} +A.qindexHL { + text-decoration: none; + font-weight: bold; + background-color: #6666cc; + color: #ffffff; + border: 1px double #9295C2; +} +A.qindexHL:hover { + text-decoration: none; + background-color: #6666cc; + color: #ffffff; +} +A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff } +A.el { text-decoration: none; font-weight: bold } +A.elRef { font-weight: bold } +A.code:link { text-decoration: none; font-weight: normal; color: #0000FF} +A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF} +A.codeRef:link { font-weight: normal; color: #0000FF} +A.codeRef:visited { font-weight: normal; color: #0000FF} +A:hover { text-decoration: none; background-color: #f2f2ff } +DL.el { margin-left: -1cm } +.fragment { + font-family: monospace, fixed; + font-size: 95%; +} +PRE.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 2px; + margin-right: 8px; + padding-left: 6px; + padding-right: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } + +DIV.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; +} +DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% } +BODY { + background: white; + color: black; + margin-right: 20px; + margin-left: 20px; +} +TD.indexkey { + background-color: #e8eef2; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TD.indexvalue { + background-color: #e8eef2; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TR.memlist { + background-color: #f0f0f0; +} +P.formulaDsp { text-align: center; } +IMG.formulaDsp { } +IMG.formulaInl { vertical-align: middle; } +SPAN.keyword { color: #008000 } +SPAN.keywordtype { color: #604020 } +SPAN.keywordflow { color: #e08000 } +SPAN.comment { color: #800000 } +SPAN.preprocessor { color: #806020 } +SPAN.stringliteral { color: #002080 } +SPAN.charliteral { color: #008080 } +.mdescLeft { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.mdescRight { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.memItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplParams { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + color: #606060; + background-color: #FAFAFA; + font-size: 80%; +} +.search { color: #003399; + font-weight: bold; +} +FORM.search { + margin-bottom: 0px; + margin-top: 0px; +} +INPUT.search { font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +TD.tiny { font-size: 75%; +} +a { + color: #1A41A8; +} +a:visited { + color: #2A3798; +} +.dirtab { padding: 4px; + border-collapse: collapse; + border: 1px solid #84b0c7; +} +TH.dirtab { background: #e8eef2; + font-weight: bold; +} +HR { height: 1px; + border: none; + border-top: 1px solid black; +} + +/* Style for detailed member documentation */ +.memtemplate { + font-size: 80%; + color: #606060; + font-weight: normal; +} +.memnav { + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +.memitem { + padding: 4px; + background-color: #eef3f5; + border-width: 1px; + border-style: solid; + border-color: #dedeee; + -moz-border-radius: 8px 8px 8px 8px; +} +.memname { + white-space: nowrap; + font-weight: bold; +} +.memdoc{ + padding-left: 10px; +} +.memproto { + background-color: #d5e1e8; + width: 100%; + border-width: 1px; + border-style: solid; + border-color: #84b0c7; + font-weight: bold; + -moz-border-radius: 8px 8px 8px 8px; +} +.paramkey { + text-align: right; +} +.paramtype { + white-space: nowrap; +} +.paramname { + color: #602020; + font-style: italic; +} +/* End Styling for detailed member documentation */ + +/* for the tree view */ +.ftvtree { + font-family: sans-serif; + margin:0.5em; +} +.directory { font-size: 9pt; font-weight: bold; } +.directory h3 { margin: 0px; margin-top: 1em; font-size: 11pt; } +.directory > h3 { margin-top: 0; } +.directory p { margin: 0px; white-space: nowrap; } +.directory div { display: none; margin: 0px; } +.directory img { vertical-align: -30%; } + diff --git a/src/tbb/doc/html/doxygen.png b/src/tbb/doc/html/doxygen.png new file mode 100644 index 0000000000000000000000000000000000000000..f0a274bbaffdd67f6d784c894d9cf28729db0e14 GIT binary patch literal 1281 zcmaJ>ZA?>F7(Vx-ms?uoS`b@hdRtpo6o^%HU>M$hfGrBvQnk$LE?p^P!kn&ikhyq! zX~V@&tPF5Qt@V?oTL96Bi%aRiwbe1)9DWQI#?)=HxS7QSw`J`5fAJ*eJbB;uNuKA& zdERDo*{Y<(If(#(B$Lr#;nB(8Y#ia=ZCeW?JfPLuQY`=@cW$k}Rivq|vbxGrRq1Tl9;+(gNt?}UtVKM2`T5t1jLzuL@0UIs`S#vlhl4)^ zLgSYrPj@$+`|j?eSbXTmiHGkWxV8V}BzNR?pl9k_s4pDu9vd5a_UzZEPk)}Ad{AV_ zzddrjrh4=Imr`E06;LY{)YYt?o}L~H@7C}F^WB!Ra=v`Q0bj{>5&$66CWF>mf6vjP z2N>RRY6ZYa=K`76>+|_)Xdwko+7wv}7cN|btOhWb(*{sta~6b?S8Omrxw}!4`NhGr zZVpNqpu1@BE`QGWNTpEpcJVW5izu~2B^GlM?1(OPg)zwW;QcP@Ltcclm>XbJL9C|j z=9!2?ua=uIlf0%AndzHsRC}IyTL$EhAee(fdKB`?27KeS^2M8M_7b~PiCFO&r5LC7 z7gl1*a<8;SjNaw#h=843_AV9iZbWQOAp5YOC^&_F*9K0> zB|6%IDb?aM#3viTxkLU4aXg&@+CkNTOnQ1iMP*^?b|^lJy$4C)Zk4isV!|RZ*XhXh zw8q3$=*0LeGC!XI_Wc?dkT~3+*Gu%%yIqP+Wr3H$=&ROMQU6q}Ag^P~>c5vAEO;a- z_dK-3PPeKar%)6$j~vI2#*-YH!1h6HYVtwCX5_wM`iF#UKz&&@9Oo5w3%XGYrX zW>dY~)SG-((Yim%`InwgTvyRC?e=Wh^8KCao!R6Eg&TpVWUY1sN~4G}V?nFnEGo-; zHZ_$eW9-GnC%^WS9b z@p;-$oH#MtC0v>Q$HX%4^JdFdO$0cbv-W)Q TtK}Eh@>>I#ipmV1>S*>q-hkC} literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/files.html b/src/tbb/doc/html/files.html new file mode 100644 index 0000000..2013158 --- /dev/null +++ b/src/tbb/doc/html/files.html @@ -0,0 +1,86 @@ + + +File Index + + + + + + +

File List

Here is a list of all documented files with brief descriptions: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
aggregator.h [code]
aligned_space.h [code]
atomic.h [code]
blocked_range.h [code]
blocked_range2d.h [code]
blocked_range3d.h [code]
cache_aligned_allocator.h [code]
combinable.h [code]
concurrent_hash_map.h [code]
concurrent_lru_cache.h [code]
concurrent_priority_queue.h [code]
concurrent_queue.h [code]
concurrent_unordered_map.h [code]
concurrent_unordered_set.h [code]
concurrent_vector.h [code]
critical_section.h [code]
enumerable_thread_specific.h [code]
flow_graph.h [code]The graph related classes and functions
memory_pool.h [code]
mutex.h [code]
null_mutex.h [code]
null_rw_mutex.h [code]
parallel_do.h [code]
parallel_for.h [code]
parallel_for_each.h [code]
parallel_invoke.h [code]
parallel_reduce.h [code]
parallel_scan.h [code]
parallel_sort.h [code]
parallel_while.h [code]
partitioner.h [code]
pipeline.h [code]
queuing_mutex.h [code]
queuing_rw_mutex.h [code]
reader_writer_lock.h [code]
recursive_mutex.h [code]
runtime_loader.h [code]
scalable_allocator.h [code]
spin_mutex.h [code]
spin_rw_mutex.h [code]
task.h [code]
task_group.h [code]
task_scheduler_init.h [code]
task_scheduler_observer.h [code]
tbb.h [code]
tbb_allocator.h [code]
tbb_config.h [code]
tbb_exception.h [code]
tbb_machine.h [code]
tbb_profiling.h [code]
tbb_stddef.h [code]
tbb_thread.h [code]
tbbmalloc_proxy.h [code]
tick_count.h [code]
+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions.html b/src/tbb/doc/html/functions.html new file mode 100644 index 0000000..6506554 --- /dev/null +++ b/src/tbb/doc/html/functions.html @@ -0,0 +1,89 @@ + + +Class Members + + + + + + + +
+ +
+ +

+Here is a list of all documented class members with links to the class documentation for each member: +

+

- a -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_0x62.html b/src/tbb/doc/html/functions_0x62.html new file mode 100644 index 0000000..c697e3f --- /dev/null +++ b/src/tbb/doc/html/functions_0x62.html @@ -0,0 +1,78 @@ + + +Class Members + + + + + + + +
+ +
+ +

+Here is a list of all documented class members with links to the class documentation for each member: +

+

- b -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_0x63.html b/src/tbb/doc/html/functions_0x63.html new file mode 100644 index 0000000..c22c70c --- /dev/null +++ b/src/tbb/doc/html/functions_0x63.html @@ -0,0 +1,96 @@ + + +Class Members + + + + + + + +
+ +
+ +

+Here is a list of all documented class members with links to the class documentation for each member: +

+

- c -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_0x64.html b/src/tbb/doc/html/functions_0x64.html new file mode 100644 index 0000000..4322d4f --- /dev/null +++ b/src/tbb/doc/html/functions_0x64.html @@ -0,0 +1,82 @@ + + +Class Members + + + + + + + +
+ +
+ +

+Here is a list of all documented class members with links to the class documentation for each member: +

+

- d -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_0x65.html b/src/tbb/doc/html/functions_0x65.html new file mode 100644 index 0000000..20ff978 --- /dev/null +++ b/src/tbb/doc/html/functions_0x65.html @@ -0,0 +1,94 @@ + + +Class Members + + + + + + + +
+ +
+ +

+Here is a list of all documented class members with links to the class documentation for each member: +

+

- e -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_0x66.html b/src/tbb/doc/html/functions_0x66.html new file mode 100644 index 0000000..7872813 --- /dev/null +++ b/src/tbb/doc/html/functions_0x66.html @@ -0,0 +1,83 @@ + + +Class Members + + + + + + + +
+ +
+ +

+Here is a list of all documented class members with links to the class documentation for each member: +

+

- f -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_0x67.html b/src/tbb/doc/html/functions_0x67.html new file mode 100644 index 0000000..4247d32 --- /dev/null +++ b/src/tbb/doc/html/functions_0x67.html @@ -0,0 +1,80 @@ + + +Class Members + + + + + + + +
+ +
+ +

+Here is a list of all documented class members with links to the class documentation for each member: +

+

- g -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_0x69.html b/src/tbb/doc/html/functions_0x69.html new file mode 100644 index 0000000..aca7f13 --- /dev/null +++ b/src/tbb/doc/html/functions_0x69.html @@ -0,0 +1,96 @@ + + +Class Members + + + + + + + +
+ +
+ +

+Here is a list of all documented class members with links to the class documentation for each member: +

+

- i -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_0x6c.html b/src/tbb/doc/html/functions_0x6c.html new file mode 100644 index 0000000..d7befaf --- /dev/null +++ b/src/tbb/doc/html/functions_0x6c.html @@ -0,0 +1,79 @@ + + +Class Members + + + + + + + +
+ +
+ +

+Here is a list of all documented class members with links to the class documentation for each member: +

+

- l -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_0x6d.html b/src/tbb/doc/html/functions_0x6d.html new file mode 100644 index 0000000..6f5bde3 --- /dev/null +++ b/src/tbb/doc/html/functions_0x6d.html @@ -0,0 +1,80 @@ + + +Class Members + + + + + + + +
+ +
+ +

+Here is a list of all documented class members with links to the class documentation for each member: +

+

- m -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_0x6e.html b/src/tbb/doc/html/functions_0x6e.html new file mode 100644 index 0000000..43343da --- /dev/null +++ b/src/tbb/doc/html/functions_0x6e.html @@ -0,0 +1,77 @@ + + +Class Members + + + + + + + +
+ +
+ +

+Here is a list of all documented class members with links to the class documentation for each member: +

+

- n -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_0x6f.html b/src/tbb/doc/html/functions_0x6f.html new file mode 100644 index 0000000..990f9a0 --- /dev/null +++ b/src/tbb/doc/html/functions_0x6f.html @@ -0,0 +1,85 @@ + + +Class Members + + + + + + + +
+ +
+ +

+Here is a list of all documented class members with links to the class documentation for each member: +

+

- o -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_0x70.html b/src/tbb/doc/html/functions_0x70.html new file mode 100644 index 0000000..f754b72 --- /dev/null +++ b/src/tbb/doc/html/functions_0x70.html @@ -0,0 +1,90 @@ + + +Class Members + + + + + + + +
+ +
+ +

+Here is a list of all documented class members with links to the class documentation for each member: +

+

- p -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_0x71.html b/src/tbb/doc/html/functions_0x71.html new file mode 100644 index 0000000..ea52877 --- /dev/null +++ b/src/tbb/doc/html/functions_0x71.html @@ -0,0 +1,76 @@ + + +Class Members + + + + + + + +
+ +
+ +

+Here is a list of all documented class members with links to the class documentation for each member: +

+

- q -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_0x72.html b/src/tbb/doc/html/functions_0x72.html new file mode 100644 index 0000000..f3b1ee4 --- /dev/null +++ b/src/tbb/doc/html/functions_0x72.html @@ -0,0 +1,102 @@ + + +Class Members + + + + + + + +
+ +
+ +

+Here is a list of all documented class members with links to the class documentation for each member: +

+

- r -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_0x73.html b/src/tbb/doc/html/functions_0x73.html new file mode 100644 index 0000000..93d374e --- /dev/null +++ b/src/tbb/doc/html/functions_0x73.html @@ -0,0 +1,99 @@ + + +Class Members + + + + + + + +
+ +
+ +

+Here is a list of all documented class members with links to the class documentation for each member: +

+

- s -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_0x74.html b/src/tbb/doc/html/functions_0x74.html new file mode 100644 index 0000000..6e9c379 --- /dev/null +++ b/src/tbb/doc/html/functions_0x74.html @@ -0,0 +1,91 @@ + + +Class Members + + + + + + + +
+ +
+ +

+Here is a list of all documented class members with links to the class documentation for each member: +

+

- t -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_0x75.html b/src/tbb/doc/html/functions_0x75.html new file mode 100644 index 0000000..8ba813c --- /dev/null +++ b/src/tbb/doc/html/functions_0x75.html @@ -0,0 +1,76 @@ + + +Class Members + + + + + + + +
+ +
+ +

+Here is a list of all documented class members with links to the class documentation for each member: +

+

- u -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_0x76.html b/src/tbb/doc/html/functions_0x76.html new file mode 100644 index 0000000..6dbc36c --- /dev/null +++ b/src/tbb/doc/html/functions_0x76.html @@ -0,0 +1,74 @@ + + +Class Members + + + + + + + +
+ +
+ +

+Here is a list of all documented class members with links to the class documentation for each member: +

+

- v -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_0x77.html b/src/tbb/doc/html/functions_0x77.html new file mode 100644 index 0000000..6d15f6d --- /dev/null +++ b/src/tbb/doc/html/functions_0x77.html @@ -0,0 +1,75 @@ + + +Class Members + + + + + + + +
+ +
+ +

+Here is a list of all documented class members with links to the class documentation for each member: +

+

- w -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_0x7e.html b/src/tbb/doc/html/functions_0x7e.html new file mode 100644 index 0000000..9220fce --- /dev/null +++ b/src/tbb/doc/html/functions_0x7e.html @@ -0,0 +1,98 @@ + + +Class Members + + + + + + + +
+ +
+ +

+Here is a list of all documented class members with links to the class documentation for each member: +

+

- ~ -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_enum.html b/src/tbb/doc/html/functions_enum.html new file mode 100644 index 0000000..3adb98c --- /dev/null +++ b/src/tbb/doc/html/functions_enum.html @@ -0,0 +1,51 @@ + + +Class Members - Enumerations + + + + + + + +  +

+

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_eval.html b/src/tbb/doc/html/functions_eval.html new file mode 100644 index 0000000..2e4b60e --- /dev/null +++ b/src/tbb/doc/html/functions_eval.html @@ -0,0 +1,61 @@ + + +Class Members - Enumerator + + + + + + + +  +

+

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_func.html b/src/tbb/doc/html/functions_func.html new file mode 100644 index 0000000..ad36560 --- /dev/null +++ b/src/tbb/doc/html/functions_func.html @@ -0,0 +1,84 @@ + + +Class Members - Functions + + + + + + + +
+ +
+ +

+  +

+

- a -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_func_0x62.html b/src/tbb/doc/html/functions_func_0x62.html new file mode 100644 index 0000000..fc5b63f --- /dev/null +++ b/src/tbb/doc/html/functions_func_0x62.html @@ -0,0 +1,77 @@ + + +Class Members - Functions + + + + + + + +
+ +
+ +

+  +

+

- b -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_func_0x63.html b/src/tbb/doc/html/functions_func_0x63.html new file mode 100644 index 0000000..20e2186 --- /dev/null +++ b/src/tbb/doc/html/functions_func_0x63.html @@ -0,0 +1,93 @@ + + +Class Members - Functions + + + + + + + +
+ +
+ +

+  +

+

- c -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_func_0x64.html b/src/tbb/doc/html/functions_func_0x64.html new file mode 100644 index 0000000..accd1e1 --- /dev/null +++ b/src/tbb/doc/html/functions_func_0x64.html @@ -0,0 +1,78 @@ + + +Class Members - Functions + + + + + + + +
+ +
+ +

+  +

+

- d -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_func_0x65.html b/src/tbb/doc/html/functions_func_0x65.html new file mode 100644 index 0000000..59f24b5 --- /dev/null +++ b/src/tbb/doc/html/functions_func_0x65.html @@ -0,0 +1,80 @@ + + +Class Members - Functions + + + + + + + +
+ +
+ +

+  +

+

- e -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_func_0x66.html b/src/tbb/doc/html/functions_func_0x66.html new file mode 100644 index 0000000..8ea4b35 --- /dev/null +++ b/src/tbb/doc/html/functions_func_0x66.html @@ -0,0 +1,77 @@ + + +Class Members - Functions + + + + + + + +
+ +
+ +

+  +

+

- f -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_func_0x67.html b/src/tbb/doc/html/functions_func_0x67.html new file mode 100644 index 0000000..b02d40d --- /dev/null +++ b/src/tbb/doc/html/functions_func_0x67.html @@ -0,0 +1,79 @@ + + +Class Members - Functions + + + + + + + +
+ +
+ +

+  +

+

- g -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_func_0x69.html b/src/tbb/doc/html/functions_func_0x69.html new file mode 100644 index 0000000..3072e1b --- /dev/null +++ b/src/tbb/doc/html/functions_func_0x69.html @@ -0,0 +1,94 @@ + + +Class Members - Functions + + + + + + + +
+ +
+ +

+  +

+

- i -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_func_0x6c.html b/src/tbb/doc/html/functions_func_0x6c.html new file mode 100644 index 0000000..6935655 --- /dev/null +++ b/src/tbb/doc/html/functions_func_0x6c.html @@ -0,0 +1,78 @@ + + +Class Members - Functions + + + + + + + +
+ +
+ +

+  +

+

- l -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_func_0x6d.html b/src/tbb/doc/html/functions_func_0x6d.html new file mode 100644 index 0000000..5568614 --- /dev/null +++ b/src/tbb/doc/html/functions_func_0x6d.html @@ -0,0 +1,76 @@ + + +Class Members - Functions + + + + + + + +
+ +
+ +

+  +

+

- m -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_func_0x6e.html b/src/tbb/doc/html/functions_func_0x6e.html new file mode 100644 index 0000000..d6305b7 --- /dev/null +++ b/src/tbb/doc/html/functions_func_0x6e.html @@ -0,0 +1,75 @@ + + +Class Members - Functions + + + + + + + +
+ +
+ +

+  +

+

- n -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_func_0x6f.html b/src/tbb/doc/html/functions_func_0x6f.html new file mode 100644 index 0000000..0eaaf02 --- /dev/null +++ b/src/tbb/doc/html/functions_func_0x6f.html @@ -0,0 +1,81 @@ + + +Class Members - Functions + + + + + + + +
+ +
+ +

+  +

+

- o -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_func_0x70.html b/src/tbb/doc/html/functions_func_0x70.html new file mode 100644 index 0000000..1660308 --- /dev/null +++ b/src/tbb/doc/html/functions_func_0x70.html @@ -0,0 +1,87 @@ + + +Class Members - Functions + + + + + + + +
+ +
+ +

+  +

+

- p -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_func_0x71.html b/src/tbb/doc/html/functions_func_0x71.html new file mode 100644 index 0000000..77e504c --- /dev/null +++ b/src/tbb/doc/html/functions_func_0x71.html @@ -0,0 +1,75 @@ + + +Class Members - Functions + + + + + + + +
+ +
+ +

+  +

+

- q -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_func_0x72.html b/src/tbb/doc/html/functions_func_0x72.html new file mode 100644 index 0000000..a633329 --- /dev/null +++ b/src/tbb/doc/html/functions_func_0x72.html @@ -0,0 +1,96 @@ + + +Class Members - Functions + + + + + + + +
+ +
+ +

+  +

+

- r -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_func_0x73.html b/src/tbb/doc/html/functions_func_0x73.html new file mode 100644 index 0000000..2135a1f --- /dev/null +++ b/src/tbb/doc/html/functions_func_0x73.html @@ -0,0 +1,94 @@ + + +Class Members - Functions + + + + + + + +
+ +
+ +

+  +

+

- s -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_func_0x74.html b/src/tbb/doc/html/functions_func_0x74.html new file mode 100644 index 0000000..8f00301 --- /dev/null +++ b/src/tbb/doc/html/functions_func_0x74.html @@ -0,0 +1,90 @@ + + +Class Members - Functions + + + + + + + +
+ +
+ +

+  +

+

- t -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_func_0x75.html b/src/tbb/doc/html/functions_func_0x75.html new file mode 100644 index 0000000..380d3df --- /dev/null +++ b/src/tbb/doc/html/functions_func_0x75.html @@ -0,0 +1,75 @@ + + +Class Members - Functions + + + + + + + +
+ +
+ +

+  +

+

- u -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_func_0x77.html b/src/tbb/doc/html/functions_func_0x77.html new file mode 100644 index 0000000..dd067aa --- /dev/null +++ b/src/tbb/doc/html/functions_func_0x77.html @@ -0,0 +1,74 @@ + + +Class Members - Functions + + + + + + + +
+ +
+ +

+  +

+

- w -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_func_0x7e.html b/src/tbb/doc/html/functions_func_0x7e.html new file mode 100644 index 0000000..6cd6e45 --- /dev/null +++ b/src/tbb/doc/html/functions_func_0x7e.html @@ -0,0 +1,97 @@ + + +Class Members - Functions + + + + + + + +
+ +
+ +

+  +

+

- ~ -

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_rela.html b/src/tbb/doc/html/functions_rela.html new file mode 100644 index 0000000..00b0793 --- /dev/null +++ b/src/tbb/doc/html/functions_rela.html @@ -0,0 +1,49 @@ + + +Class Members - Related Functions + + + + + + + +  +

+

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_type.html b/src/tbb/doc/html/functions_type.html new file mode 100644 index 0000000..d75b769 --- /dev/null +++ b/src/tbb/doc/html/functions_type.html @@ -0,0 +1,61 @@ + + +Class Members - Typedefs + + + + + + + +  +

+

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/functions_vars.html b/src/tbb/doc/html/functions_vars.html new file mode 100644 index 0000000..f45ce51 --- /dev/null +++ b/src/tbb/doc/html/functions_vars.html @@ -0,0 +1,57 @@ + + +Class Members - Variables + + + + + + + +  +

+

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/globals.html b/src/tbb/doc/html/globals.html new file mode 100644 index 0000000..ff26950 --- /dev/null +++ b/src/tbb/doc/html/globals.html @@ -0,0 +1,49 @@ + + +Class Members + + + + + + +
+ +
+Here is a list of all documented file members with links to the documentation: +

+

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/globals_func.html b/src/tbb/doc/html/globals_func.html new file mode 100644 index 0000000..359a759 --- /dev/null +++ b/src/tbb/doc/html/globals_func.html @@ -0,0 +1,49 @@ + + +Class Members + + + + + + +
+ +
+  +

+

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/hierarchy.html b/src/tbb/doc/html/hierarchy.html new file mode 100644 index 0000000..e84d06c --- /dev/null +++ b/src/tbb/doc/html/hierarchy.html @@ -0,0 +1,181 @@ + + +Hierarchical Index + + + + + + +

Class Hierarchy

This inheritance list is sorted roughly, but not completely, alphabetically: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/index.html b/src/tbb/doc/html/index.html new file mode 100644 index 0000000..611b2d7 --- /dev/null +++ b/src/tbb/doc/html/index.html @@ -0,0 +1,32 @@ + + +Main Page + + + + + +

Main Page

+

+Click the tabs above for information about the

    +
  • Modules (groups of functionality) implemented by the library
  • Classes provided by the library
  • Files constituting the library.
+Please note that significant part of TBB functionality is implemented in the form of template functions, descriptions of which are not accessible on the Classes tab. Use Modules or Namespace/Namespace Members tabs to find them.

+Additional pieces of information can be found here

+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/modules.html b/src/tbb/doc/html/modules.html new file mode 100644 index 0000000..f258e2f --- /dev/null +++ b/src/tbb/doc/html/modules.html @@ -0,0 +1,33 @@ + + +Module Index + + + + + +

Modules

Here is a list of all modules: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/namespacemembers.html b/src/tbb/doc/html/namespacemembers.html new file mode 100644 index 0000000..9a710ac --- /dev/null +++ b/src/tbb/doc/html/namespacemembers.html @@ -0,0 +1,59 @@ + + +Class Members + + + + + + + +Here is a list of all documented namespace members with links to the namespaces they belong to: +

+

    +
  • __TBB_DECL_ATOMIC_ALT() +: tbb
  • acquire +: tbb
  • atomic_fence() +: tbb
  • ets_key_usage_type +: tbb
  • full_fence +: tbb
  • memory_semantics +: tbb
  • parallel_deterministic_reduce() +: tbb
  • parallel_do() +: tbb
  • parallel_for() +: tbb
  • parallel_for_each() +: tbb
  • parallel_invoke() +: tbb
  • parallel_reduce() +: tbb
  • parallel_scan() +: tbb
  • parallel_sort() +: tbb
  • relaxed +: tbb
  • release +: tbb
  • TBB_runtime_interface_version() +: tbb
+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/namespacemembers_enum.html b/src/tbb/doc/html/namespacemembers_enum.html new file mode 100644 index 0000000..07bd92e --- /dev/null +++ b/src/tbb/doc/html/namespacemembers_enum.html @@ -0,0 +1,44 @@ + + +Class Members + + + + + + + +  +

+

    +
  • ets_key_usage_type +: tbb
  • memory_semantics +: tbb
+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/namespacemembers_eval.html b/src/tbb/doc/html/namespacemembers_eval.html new file mode 100644 index 0000000..d8a2486 --- /dev/null +++ b/src/tbb/doc/html/namespacemembers_eval.html @@ -0,0 +1,46 @@ + + +Class Members + + + + + + + +  +

+

    +
  • acquire +: tbb
  • full_fence +: tbb
  • relaxed +: tbb
  • release +: tbb
+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/namespacemembers_func.html b/src/tbb/doc/html/namespacemembers_func.html new file mode 100644 index 0000000..30db35e --- /dev/null +++ b/src/tbb/doc/html/namespacemembers_func.html @@ -0,0 +1,53 @@ + + +Class Members + + + + + + + +  +

+

    +
  • __TBB_DECL_ATOMIC_ALT() +: tbb
  • atomic_fence() +: tbb
  • parallel_deterministic_reduce() +: tbb
  • parallel_do() +: tbb
  • parallel_for() +: tbb
  • parallel_for_each() +: tbb
  • parallel_invoke() +: tbb
  • parallel_reduce() +: tbb
  • parallel_scan() +: tbb
  • parallel_sort() +: tbb
  • TBB_runtime_interface_version() +: tbb
+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/namespaces.html b/src/tbb/doc/html/namespaces.html new file mode 100644 index 0000000..f7efd0e --- /dev/null +++ b/src/tbb/doc/html/namespaces.html @@ -0,0 +1,34 @@ + + +Namespace Index + + + + + + +

Namespace List

Here is a list of all documented namespaces with brief descriptions: + + +
rmlAssert that x is true
tbbThe namespace tbb contains all components of the library
+
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/pages.html b/src/tbb/doc/html/pages.html new file mode 100644 index 0000000..a336994 --- /dev/null +++ b/src/tbb/doc/html/pages.html @@ -0,0 +1,31 @@ + + +Page Index + + + + + +

Related Pages

Here is a list of all related documentation pages: +
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/parallel_do_body_req.html b/src/tbb/doc/html/parallel_do_body_req.html new file mode 100644 index 0000000..1220998 --- /dev/null +++ b/src/tbb/doc/html/parallel_do_body_req.html @@ -0,0 +1,38 @@ + + +Requirements on parallel_do body + + + + + + +

Requirements on parallel_do body

Class Body implementing the concept of parallel_do body must define: -
        B::operator()( 
+                cv_item_type item,
+                parallel_do_feeder<item_type>& feeder
+        ) const
+        
+        OR
+
+        B::operator()( cv_item_type& item ) const
+
Process item. May be invoked concurrently for the same this but different item.

+-

 item_type( const item_type& ) 
+
Copy a work item. -
 ~item_type() 
+
Destroy a work item
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/parallel_for_body_req.html b/src/tbb/doc/html/parallel_for_body_req.html new file mode 100644 index 0000000..239c5be --- /dev/null +++ b/src/tbb/doc/html/parallel_for_body_req.html @@ -0,0 +1,30 @@ + + +Requirements on parallel_for body + + + + + + +

Requirements on parallel_for body

Class Body implementing the concept of parallel_for body must define: -
 Body::Body( const Body& ); 
+
Copy constructor -
 Body::~Body(); 
+
Destructor -
 void Body::operator()( Range& r ) const; 
+
Function call operator applying the body to range r.
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/parallel_reduce_body_req.html b/src/tbb/doc/html/parallel_reduce_body_req.html new file mode 100644 index 0000000..ab7a76f --- /dev/null +++ b/src/tbb/doc/html/parallel_reduce_body_req.html @@ -0,0 +1,31 @@ + + +Requirements on parallel_reduce body + + + + + + +

Requirements on parallel_reduce body

Class Body implementing the concept of parallel_reduce body must define: -
 Body::Body( Body&, split ); 
+
Splitting constructor. Must be able to run concurrently with operator() and method join -
 Body::~Body(); 
+
Destructor -
 void Body::operator()( Range& r ); 
+
Function call operator applying body to range r and accumulating the result -
 void Body::join( Body& b ); 
+
Join results. The result in b should be merged into the result of this
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/parallel_reduce_lambda_req.html b/src/tbb/doc/html/parallel_reduce_lambda_req.html new file mode 100644 index 0000000..ed51780 --- /dev/null +++ b/src/tbb/doc/html/parallel_reduce_lambda_req.html @@ -0,0 +1,25 @@ + + +Requirements on parallel_reduce anonymous function objects (lambda functions) + + + + + +

Requirements on parallel_reduce anonymous function objects (lambda functions)

TO BE DOCUMENTED
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/parallel_scan_body_req.html b/src/tbb/doc/html/parallel_scan_body_req.html new file mode 100644 index 0000000..afb27ab --- /dev/null +++ b/src/tbb/doc/html/parallel_scan_body_req.html @@ -0,0 +1,32 @@ + + +Requirements on parallel_scan body + + + + + + +

Requirements on parallel_scan body

Class Body implementing the concept of parallel_scan body must define: -
 Body::Body( Body&, split ); 
+
Splitting constructor. Split b so that this and b can accumulate separately -
 Body::~Body(); 
+
Destructor -
 void Body::operator()( const Range& r, pre_scan_tag ); 
+
Preprocess iterations for range r -
 void Body::operator()( const Range& r, final_scan_tag ); 
+
Do final processing for iterations of range r -
 void Body::reverse_join( Body& a ); 
+
Merge preprocessing state of a into this, where a was created earlier from b by b's splitting constructor
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/parallel_sort_iter_req.html b/src/tbb/doc/html/parallel_sort_iter_req.html new file mode 100644 index 0000000..2dd69f6 --- /dev/null +++ b/src/tbb/doc/html/parallel_sort_iter_req.html @@ -0,0 +1,29 @@ + + +Requirements on iterators for parallel_sort + + + + + + +

Requirements on iterators for parallel_sort

Requirements on value type T of RandomAccessIterator for parallel_sort: -
 void swap( T& x, T& y ) 
+
Swaps x and y -
 bool Compare::operator()( const T& x, const T& y ) 
+
True if x comes before y;
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/range_req.html b/src/tbb/doc/html/range_req.html new file mode 100644 index 0000000..0d72cdc --- /dev/null +++ b/src/tbb/doc/html/range_req.html @@ -0,0 +1,32 @@ + + +Requirements on range concept + + + + + + +

Requirements on range concept

Class R implementing the concept of range must define: -
 R::R( const R& ); 
+
Copy constructor -
 R::~R(); 
+
Destructor -
 bool R::is_divisible() const; 
+
True if range can be partitioned into two subranges -
 bool R::empty() const; 
+
True if range is empty -
 R::R( R& r, split ); 
+
Split range r into two subranges.
+

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are +registered trademarks or trademarks of Intel Corporation or its +subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. diff --git a/src/tbb/doc/html/tab_b.gif b/src/tbb/doc/html/tab_b.gif new file mode 100644 index 0000000000000000000000000000000000000000..0d623483ffdf5f9f96900108042a7ab0643fe2a3 GIT binary patch literal 35 ncmZ?wbhEHbWMp7uXkcJy*>IeJfk6j|fqX^=1|}vKMh0sDa2W*H literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/tab_l.gif b/src/tbb/doc/html/tab_l.gif new file mode 100644 index 0000000000000000000000000000000000000000..9b1e6337c9299a700401a2a78a2c6ffced475216 GIT binary patch literal 706 zcmZ?wbhEHbZT`}F1e&(Gg}Y(8=I;HA5#Z$3JI=gGB)FQ#odI(O&E^@q;x zK6mr*m3xOS-#u~t!I@i+u0DKm^U160k6t`|^WpV}&n+8{U%dD9&a>B#U%!9-@yol< zU%&tQ{rk_K|NsC0`}dE5ET99@1@a36+kb~?0UJ*yc&I3X_m z!ND^5$O7$#8OFRuDhG}!?8z?cdZK&!`PWjdR;Aj^wZ` zeK{IEYHBJ)6K8VIp1`BVt++swf6j+=L{p1*nO(VhE`pFexG@5$|>uaCcd z`0m=9m+yak{QmXN#Sc$^{$X9h9&q2jiKAI|&T)a;PPx2K9p`YIdw8HtR5k2Q$2-O2 z*;3y{MQ-RnJTgJfI&R5|O)AHxDf_00XbPvDZPy4t=hHd)nfLPvms&O`Ok(sD()5v$ z5U@&h;a=#xbxVbo2~X&Xj0Ie(f{v>vERH+qC+nTG=B8Nca=wU-O$?1&vUgV~9=!H; zx>3p9Yn%*<>t~sk+&0xfyS8RsPfYBd<~wWK%j-LmpU>O7yX^h#UCp1x-p#i7@bE;py8XI6 zmY<)m>~)W~yIWcMVoiPg{duuf<*)9qZ9l$m*Ph&W&$jlv*Vpa+{pH@n=IQ$L?0$ax ec60Ul|8o2P|NVbd{6P)#weSbE3}s?04AuZvx_~SI literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/tab_r.gif b/src/tbb/doc/html/tab_r.gif new file mode 100644 index 0000000000000000000000000000000000000000..ce9dd9f533cb5486d6941844f442b59d4a9e9175 GIT binary patch literal 2585 zcmbV}`9Bkk1ILFF--w5zJc=ZZT(zjE=;2|_S)Qm~rCWz1Pc)KPl;jv%A#&v2*x}yc zmf2~Jm~&=xjJY?PqwIN}f8qQ2{r$uH{c*nJbmr{cR5??*egHrs-B=MzCF`3%e{FAW z{oL5xTHn~5TM{jaB;@|_Ue5F&Zb@p(kMyG{*;gWDg zyeL|eZf7Qd8=#bXzSiR{yzRgLSj-fJS8>lBjVHN z^o-0eS=nE6a`W;LChBs=`+QAJP~{b93>H^eRb5kCSC1zUNezun%`L5M?RDzv#%jk7 zYVRX=vATPD`+oEfum^{RM@GjuP?-r=yh0!p;Vx^T9G7~`7%5ydH%70=jyJ;;`d;hv92x3R=z{xp+Lg2!*@OK*K15-t&okoPtSED)h&$RLxdbA zseWm^C3d%-yRNi-ryk^!ek+C`n&~cd$#ZWct_cUL{l~i+Nzx^5d!n94(>bW-iL~Rl z&8r)?q|1DIo=0=judQ{FaGcfLERz8gfn3-Qt<2lksh{mzpT}DXxUuR^z=^key&q4! z+wWI45vL0k$R^(F#{qfqhUsN@WA+w-V?LPH33!Q?WFSB3)WBojE@hK41Nb?KfS+Qo zXgrzfsP$wr4Qzy*{OD>uJBjdgGM@VMml5)2f~_}lD*YyOb}Hjeobhz#4c`w(l^>KK zr?Ud;W~Z}*w;%hZ|2^p^+f06gJDJQD zeIhGADbDmm&6arh(q>EZ<7mjzg7l|z$hRL8=1>)Nv=S7CY$B}iYJ&*T_-T_OG*L1q ztZ3Lana33?y3AKnyq^YCF|4x%Rb5WU&2qcl{TFKey%QJeMxn^SdT!hZ5+0i1zeusiYVp-phBl7b5+Px-X&LhByq z0F&<;K0l2+v>qiHlXb#$jXMv$uK-dEGE9L~qtdU(XeRXmvu*K2Q&6!fD**JxYP4b4BR7FdJ$Qx9G9`J%-_X!a#LGpp3g9)VWytGCa;7`S1_e8F~!R+aSJ zOF17p2`H?2kPs8Q`_;U}+D%3p zs2-0BTqFwpUoBk`?P;iPQ(IbEA|JmMx!P&YYG|R@S=5Mnw;-?A6rEEVyV%d7{iU4a zNk`i!%F(Ykpm`}#oH;BjY->@b8vQedv;pza2FL&*6ufjd+*3Ute&>kes~TU?^KkojsTh(o~(3tk1Y6>4(yn( z#U*ID9@eg-beKo1B;HXe+}{Z%n@7m0+yxivuqk9~;!1LGQlah)xYK4>wgL}l6dsaN zIxlRlq`*`j9PG4*0hD6YV_b_2w5b#)o7J?`q#{GjvvKlD`T*dWcZx<-s(ZvLB44E# z=!|sw!?)@%y$oRNL#25WS3lzdii}TuQ3?CLnvQ1_n};2sT_;Y;#d3=+-(O% zMN$>O!3;ke(UuLR%h_&)N zs^!-@A>QR}4yB1bPp`9S19ikTbZ~O{&FF-yHK{En;mmShDUIEw03`j(DBIsM}Rjki2J#SQa3gFZTKBPDeIiLt9Z z%bL3(B@Qw%(B`wSMS~dPh$=R`(}lBoFXKy(s|*{#ru$wjsBc_O#zxNk9w+UUHmx(U zmJ8+M+ndtnZ<7|VU9Mbt61zpo9T&3%Wx&XII=#QJxjR`CZf22ac3d51Z?GD%LEe_&*t46Qf;4`bZ7p2K(Ab5>GfT^}4! zBT&HZD`^PEgWoI&{~o-ID0F?O`75sm(87x%A{(}Ch1)QlzdJ)1B-eqe5a(weg0`4lQIf1evjvbBY50DVbzO7CLf|vP z2#0(U-|jZ`H{y5N^o7%iK6H>_HEGN->U6^!)1{XpJV!!4(Ig7wzZQ*9WYF4X1rG0x z=1uA@i`rIAciubDC{;~b(|&|A@xkjRP5aRcvRU9tvIm}jDB6J eQ0-6-y)mpwdT=ayS0tBxKDA*~;EWmo literal 0 HcmV?d00001 diff --git a/src/tbb/doc/html/tabs.css b/src/tbb/doc/html/tabs.css new file mode 100644 index 0000000..a61552a --- /dev/null +++ b/src/tbb/doc/html/tabs.css @@ -0,0 +1,102 @@ +/* tabs styles, based on http://www.alistapart.com/articles/slidingdoors */ + +DIV.tabs +{ + float : left; + width : 100%; + background : url("tab_b.gif") repeat-x bottom; + margin-bottom : 4px; +} + +DIV.tabs UL +{ + margin : 0px; + padding-left : 10px; + list-style : none; +} + +DIV.tabs LI, DIV.tabs FORM +{ + display : inline; + margin : 0px; + padding : 0px; +} + +DIV.tabs FORM +{ + float : right; +} + +DIV.tabs A +{ + float : left; + background : url("tab_r.gif") no-repeat right top; + border-bottom : 1px solid #84B0C7; + font-size : x-small; + font-weight : bold; + text-decoration : none; +} + +DIV.tabs A:hover +{ + background-position: 100% -150px; +} + +DIV.tabs A:link, DIV.tabs A:visited, +DIV.tabs A:active, DIV.tabs A:hover +{ + color: #1A419D; +} + +DIV.tabs SPAN +{ + float : left; + display : block; + background : url("tab_l.gif") no-repeat left top; + padding : 5px 9px; + white-space : nowrap; +} + +DIV.tabs INPUT +{ + float : right; + display : inline; + font-size : 1em; +} + +DIV.tabs TD +{ + font-size : x-small; + font-weight : bold; + text-decoration : none; +} + + + +/* Commented Backslash Hack hides rule from IE5-Mac \*/ +DIV.tabs SPAN {float : none;} +/* End IE5-Mac hack */ + +DIV.tabs A:hover SPAN +{ + background-position: 0% -150px; +} + +DIV.tabs LI#current A +{ + background-position: 100% -150px; + border-width : 0px; +} + +DIV.tabs LI#current SPAN +{ + background-position: 0% -150px; + padding-bottom : 6px; +} + +DIV.nav +{ + background : none; + border : none; + border-bottom : 1px solid #84B0C7; +} diff --git a/src/tbb/examples/GettingStarted/index.html b/src/tbb/examples/GettingStarted/index.html new file mode 100644 index 0000000..3413ef8 --- /dev/null +++ b/src/tbb/examples/GettingStarted/index.html @@ -0,0 +1,24 @@ + + + +

Overview

+This directory contains the examples referenced by the Intel® Threading Building Blocks Getting Started Guide. + +

Directories

+
+
sub_string_finder +
Finds largest matching substrings. +
+ +
+Up to parent directory +

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. + + + diff --git a/src/tbb/examples/GettingStarted/sub_string_finder/Makefile b/src/tbb/examples/GettingStarted/sub_string_finder/Makefile new file mode 100644 index 0000000..4a41000 --- /dev/null +++ b/src/tbb/examples/GettingStarted/sub_string_finder/Makefile @@ -0,0 +1,76 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# GNU Makefile that builds and runs example. +PROG=sub_string_finder_extended +ARGS= +LIGHT_PROG=sub_string_finder + +# The C++ compiler +ifneq (,$(shell which icc 2>/dev/null)) +CXX=icc +endif # icc + +ifeq ($(offload), mic) +override CXXFLAGS += -opt-report-phase:offload -D__TBB_MIC=1 +endif + +ifeq ($(CXX), icc) +TBBLIB = -tbb +TBBLIB_DEBUG = -tbb +else +TBBLIB = -ltbb +TBBLIB_DEBUG = -ltbb_debug +endif + +ifeq ($(shell uname), Linux) +LIBS+= -lrt +endif + +all: release test + +release: *.cpp +ifeq ($(offload),) + $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o sub_string_finder sub_string_finder.cpp $(TBBLIB) $(LIBS) + $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o sub_string_finder_pretty sub_string_finder_pretty.cpp $(TBBLIB) $(LIBS) +endif + $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o sub_string_finder_extended sub_string_finder_extended.cpp $(TBBLIB) $(LIBS) + +debug: *.cpp +ifeq ($(offload),) + $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o sub_string_finder sub_string_finder.cpp $(TBBLIB_DEBUG) $(LIBS) + $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o sub_string_finder_pretty sub_string_finder_pretty.cpp $(TBBLIB_DEBUG) $(LIBS) +endif + $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o sub_string_finder_extended sub_string_finder_extended.cpp $(TBBLIB_DEBUG) $(LIBS) + +clean: + $(RM) sub_string_finder sub_string_finder_extended sub_string_finder_pretty *.o *.d + +test: + ./$(PROG) $(ARGS) + +light_test: + ./$(LIGHT_PROG) $(ARGS) diff --git a/src/tbb/examples/GettingStarted/sub_string_finder/Makefile.windows b/src/tbb/examples/GettingStarted/sub_string_finder/Makefile.windows new file mode 100644 index 0000000..551ecdd --- /dev/null +++ b/src/tbb/examples/GettingStarted/sub_string_finder/Makefile.windows @@ -0,0 +1,58 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Common Makefile that builds and runs examples. +PROG=sub_string_finder_extended +ARGS= +LIGHT_PROG=sub_string_finder + +# The C++ compiler options +# Trying to find if icl.exe is set +CXX1 = $(TBB_CXX)- +CXX2 = $(CXX1:icl.exe-=icl.exe) +CXX = $(CXX2:-=cl.exe) + +MYCXXFLAGS = /TP /EHsc /W3 /nologo /D _CONSOLE /D _MBCS /D WIN32 $(CXXFLAGS) +MYLDFLAGS =/INCREMENTAL:NO /NOLOGO /DEBUG /FIXED:NO $(LDFLAGS) + +all: release test +release: compiler_check + $(CXX) sub_string_finder.cpp /MD /O2 /D NDEBUG $(MYCXXFLAGS) /link tbb.lib $(LIBS) $(MYLDFLAGS) /OUT:sub_string_finder.exe + $(CXX) sub_string_finder_extended.cpp /MD /O2 /D NDEBUG $(MYCXXFLAGS) /link tbb.lib $(LIBS) $(MYLDFLAGS) /OUT:sub_string_finder_extended.exe + $(CXX) sub_string_finder_pretty.cpp /MD /O2 /D NDEBUG $(MYCXXFLAGS) /link tbb.lib $(LIBS) $(MYLDFLAGS) /OUT:sub_string_finder_pretty.exe +debug: compiler_check + $(CXX) sub_string_finder.cpp /MDd /Od /Zi /D TBB_USE_DEBUG /D _DEBUG $(MYCXXFLAGS) /link tbb_debug.lib $(LIBS) $(MYLDFLAGS) /OUT:sub_string_finder.exe + $(CXX) sub_string_finder_extended.cpp /MDd /Od /Zi /D TBB_USE_DEBUG /D _DEBUG $(MYCXXFLAGS) /link tbb_debug.lib $(LIBS) $(MYLDFLAGS) /OUT:sub_string_finder_extended.exe + $(CXX) sub_string_finder_pretty.cpp /MDd /Od /Zi /D TBB_USE_DEBUG /D _DEBUG $(MYCXXFLAGS) /link tbb_debug.lib $(LIBS) $(MYLDFLAGS) /OUT:sub_string_finder_pretty.exe +clean: + @cmd.exe /C del sub_string_finder*.exe *.obj *.?db *.manifest +test: + $(PROG) $(ARGS) +light_test: + $(LIGHT_PROG) $(ARGS) +compiler_check: + @echo compiler_test>compiler_test && @$(CXX) /E compiler_test >nul 2>&1 || echo "$(CXX) command not found. Check if CXX=$(CXX) is set properly" + @cmd.exe /C del compiler_test diff --git a/src/tbb/examples/GettingStarted/sub_string_finder/index.html b/src/tbb/examples/GettingStarted/sub_string_finder/index.html new file mode 100644 index 0000000..cd751f6 --- /dev/null +++ b/src/tbb/examples/GettingStarted/sub_string_finder/index.html @@ -0,0 +1,67 @@ + + + +

Overview

+
+
A simple example that uses the parallel_for template in a substring matching program. For each position +in a string, the program displays the length of the largest matching substring elsewhere in the string. +The program also displays the location of a largest match for each position. Consider the string "babba" +as an example. Starting at position 0, "ba" is the largest substring with a match elsewhere in the +string (position 3). +
The code located in the sub_string_finder_extended.cpp file +demonstrates offload programming for Intel® Many Integrated Core (Intel® MIC) Architecture (see build instructions). +
+ +

Files

+
+
sub_string_finder.cpp +
The example as it appears in the Getting Started Guide. +
sub_string_finder_extended.cpp +
An example similar to the one in the Getting Started Guide, but with an added sequential + implementation, and with an offload region added that can be executed on Intel® MIC Architecture based coprocessor. + The three implementations are timed, by using tick_count, + and the speedup of the parallel version and + the speedup of the parallel version and, if applicable, the offload version is calculated and displayed. +
sub_string_finder_pretty.cpp +
An example similar to the one in the Getting Started Guide, but with more attractive printing of the results. +
Makefile +
Makefile for building example. +
+ +

Directories

+
+
msvs +
Contains Microsoft* Visual Studio* 2005 workspace for building and running the example (Windows* systems only). +
xcode +
Contains Xcode* IDE workspace for building and running the example (Mac OS* X systems only). +
+ +

To Build

+General build directions can be found here. + +

Usage

+
+
sub_string_finder +
Runs the example as it appears in the Getting Started Guide. +
sub_string_finder_pretty +
Runs the similar example with more attractive printing of the results. +
sub_string_finder_extended +
Runs the example extended with a sequential implementation and an offload region that can be executed on Intel® MIC Architecture based coprocessor. +
To run a short version of this example, e.g., for use with Intel® Threading Tools: +
Build a debug version of the sub_string_finder_pretty example + (see the build directions). +
Run it, e.g., sub_string_finder_pretty. +
+ +
+Up to parent directory +

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. + + + diff --git a/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder.icproj b/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder.icproj new file mode 100644 index 0000000..fb1bb75 --- /dev/null +++ b/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder.icproj @@ -0,0 +1,11 @@ + + + + + diff --git a/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder.vcproj b/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder.vcproj new file mode 100644 index 0000000..97cc62e --- /dev/null +++ b/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder.vcproj @@ -0,0 +1,352 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_cl.sln b/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_cl.sln new file mode 100644 index 0000000..0054e4f --- /dev/null +++ b/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_cl.sln @@ -0,0 +1,50 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sub_string_finder", "sub_string_finder.vcproj", "{3AA40693-F93D-4D4B-B32E-068F511A2525}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sub_string_finder_extended", "sub_string_finder_extended.vcproj", "{3AA40693-F93D-4D4B-B32E-068F511A2526}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sub_string_finder_pretty", "sub_string_finder_pretty.vcproj", "{3AA40693-F93D-4D4B-B32E-068F511A2524}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A26B588D-97F7-4466-9672-8A7E3173FBA1}" + ProjectSection(SolutionItems) = preProject + ..\index.html = ..\index.html + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3AA40693-F93D-4D4B-B32E-068F511A2525}.Debug|Win32.ActiveCfg = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2525}.Debug|Win32.Build.0 = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2525}.Debug|x64.ActiveCfg = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2525}.Debug|x64.Build.0 = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2525}.Release|Win32.ActiveCfg = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2525}.Release|Win32.Build.0 = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2525}.Release|x64.ActiveCfg = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2525}.Release|x64.Build.0 = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2526}.Debug|Win32.ActiveCfg = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2526}.Debug|Win32.Build.0 = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2526}.Debug|x64.ActiveCfg = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2526}.Debug|x64.Build.0 = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2526}.Release|Win32.ActiveCfg = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2526}.Release|Win32.Build.0 = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2526}.Release|x64.ActiveCfg = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2526}.Release|x64.Build.0 = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2524}.Debug|Win32.ActiveCfg = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2524}.Debug|Win32.Build.0 = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2524}.Debug|x64.ActiveCfg = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2524}.Debug|x64.Build.0 = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2524}.Release|Win32.ActiveCfg = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2524}.Release|Win32.Build.0 = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2524}.Release|x64.ActiveCfg = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2524}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_extended.icproj b/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_extended.icproj new file mode 100644 index 0000000..576e473 --- /dev/null +++ b/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_extended.icproj @@ -0,0 +1,11 @@ + + + + + diff --git a/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_extended.vcproj b/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_extended.vcproj new file mode 100644 index 0000000..05175b2 --- /dev/null +++ b/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_extended.vcproj @@ -0,0 +1,352 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_icl.sln b/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_icl.sln new file mode 100644 index 0000000..5dcab35 --- /dev/null +++ b/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_icl.sln @@ -0,0 +1,74 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "sub_string_finder", "sub_string_finder.icproj", "{3929DD8E-420D-4360-BCBA-3C14C674EFC7}" +EndProject +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "sub_string_finder_extended", "sub_string_finder_extended.icproj", "{BFF3077B-EB9A-4AF5-998B-7C1BA757C06F}" +EndProject +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "sub_string_finder_pretty", "sub_string_finder_pretty.icproj", "{8ADCDB85-B3E0-4376-9378-0C349F9E6140}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A26B588D-97F7-4466-9672-8A7E3173FBA1}" + ProjectSection(SolutionItems) = preProject + ..\index.html = ..\index.html + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3929DD8E-420D-4360-BCBA-3C14C674EFC7}.Debug|Win32.ActiveCfg = Debug|Win32 + {3929DD8E-420D-4360-BCBA-3C14C674EFC7}.Debug|Win32.Build.0 = Debug|Win32 + {3929DD8E-420D-4360-BCBA-3C14C674EFC7}.Debug|x64.ActiveCfg = Debug|x64 + {3929DD8E-420D-4360-BCBA-3C14C674EFC7}.Debug|x64.Build.0 = Debug|x64 + {3929DD8E-420D-4360-BCBA-3C14C674EFC7}.Release|Win32.ActiveCfg = Release|Win32 + {3929DD8E-420D-4360-BCBA-3C14C674EFC7}.Release|Win32.Build.0 = Release|Win32 + {3929DD8E-420D-4360-BCBA-3C14C674EFC7}.Release|x64.ActiveCfg = Release|x64 + {3929DD8E-420D-4360-BCBA-3C14C674EFC7}.Release|x64.Build.0 = Release|x64 + {BFF3077B-EB9A-4AF5-998B-7C1BA757C06F}.Debug|Win32.ActiveCfg = Debug|Win32 + {BFF3077B-EB9A-4AF5-998B-7C1BA757C06F}.Debug|Win32.Build.0 = Debug|Win32 + {BFF3077B-EB9A-4AF5-998B-7C1BA757C06F}.Debug|x64.ActiveCfg = Debug|x64 + {BFF3077B-EB9A-4AF5-998B-7C1BA757C06F}.Debug|x64.Build.0 = Debug|x64 + {BFF3077B-EB9A-4AF5-998B-7C1BA757C06F}.Release|Win32.ActiveCfg = Release|Win32 + {BFF3077B-EB9A-4AF5-998B-7C1BA757C06F}.Release|Win32.Build.0 = Release|Win32 + {BFF3077B-EB9A-4AF5-998B-7C1BA757C06F}.Release|x64.ActiveCfg = Release|x64 + {BFF3077B-EB9A-4AF5-998B-7C1BA757C06F}.Release|x64.Build.0 = Release|x64 + {8ADCDB85-B3E0-4376-9378-0C349F9E6140}.Debug|Win32.ActiveCfg = Debug|Win32 + {8ADCDB85-B3E0-4376-9378-0C349F9E6140}.Debug|Win32.Build.0 = Debug|Win32 + {8ADCDB85-B3E0-4376-9378-0C349F9E6140}.Debug|x64.ActiveCfg = Debug|x64 + {8ADCDB85-B3E0-4376-9378-0C349F9E6140}.Debug|x64.Build.0 = Debug|x64 + {8ADCDB85-B3E0-4376-9378-0C349F9E6140}.Release|Win32.ActiveCfg = Release|Win32 + {8ADCDB85-B3E0-4376-9378-0C349F9E6140}.Release|Win32.Build.0 = Release|Win32 + {8ADCDB85-B3E0-4376-9378-0C349F9E6140}.Release|x64.ActiveCfg = Release|x64 + {8ADCDB85-B3E0-4376-9378-0C349F9E6140}.Release|x64.Build.0 = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2525}.Release|x64.Build.0 = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2525}.Release|x64.ActiveCfg = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2525}.Release|Win32.Build.0 = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2525}.Release|Win32.ActiveCfg = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2525}.Debug|x64.Build.0 = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2525}.Debug|x64.ActiveCfg = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2525}.Debug|Win32.Build.0 = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2525}.Debug|Win32.ActiveCfg = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2526}.Release|x64.Build.0 = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2526}.Release|x64.ActiveCfg = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2526}.Release|Win32.Build.0 = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2526}.Release|Win32.ActiveCfg = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2526}.Debug|x64.Build.0 = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2526}.Debug|x64.ActiveCfg = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2526}.Debug|Win32.Build.0 = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2526}.Debug|Win32.ActiveCfg = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2524}.Release|x64.Build.0 = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2524}.Release|x64.ActiveCfg = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2524}.Release|Win32.Build.0 = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2524}.Release|Win32.ActiveCfg = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2524}.Debug|x64.Build.0 = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2524}.Debug|x64.ActiveCfg = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2524}.Debug|Win32.Build.0 = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2524}.Debug|Win32.ActiveCfg = Debug|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_pretty.icproj b/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_pretty.icproj new file mode 100644 index 0000000..a303820 --- /dev/null +++ b/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_pretty.icproj @@ -0,0 +1,11 @@ + + + + + diff --git a/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_pretty.vcproj b/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_pretty.vcproj new file mode 100644 index 0000000..527a11b --- /dev/null +++ b/src/tbb/examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_pretty.vcproj @@ -0,0 +1,352 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/GettingStarted/sub_string_finder/sub_string_finder.cpp b/src/tbb/examples/GettingStarted/sub_string_finder/sub_string_finder.cpp new file mode 100644 index 0000000..491d923 --- /dev/null +++ b/src/tbb/examples/GettingStarted/sub_string_finder/sub_string_finder.cpp @@ -0,0 +1,85 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include +#include +#include +#include "tbb/parallel_for.h" +#include "tbb/blocked_range.h" + +using namespace tbb; +using namespace std; +static const size_t N = 23; + +class SubStringFinder { + const string str; + size_t *max_array; + size_t *pos_array; +public: + void operator() ( const blocked_range& r ) const { + for ( size_t i = r.begin(); i != r.end(); ++i ) { + size_t max_size = 0, max_pos = 0; + for (size_t j = 0; j < str.size(); ++j) + if (j != i) { + size_t limit = str.size()-max(i,j); + for (size_t k = 0; k < limit; ++k) { + if (str[i + k] != str[j + k]) break; + if (k > max_size) { + max_size = k; + max_pos = j; + } + } + } + max_array[i] = max_size; + pos_array[i] = max_pos; + } + } + SubStringFinder(string &s, size_t *m, size_t *p) : + str(s), max_array(m), pos_array(p) { } +}; + +int main() { + + string str[N] = { string("a"), string("b") }; + for (size_t i = 2; i < N; ++i) str[i] = str[i-1]+str[i-2]; + string &to_scan = str[N-1]; + size_t num_elem = to_scan.size(); + + size_t *max = new size_t[num_elem]; + size_t *pos = new size_t[num_elem]; + + parallel_for(blocked_range(0, num_elem ), + SubStringFinder( to_scan, max, pos ) ); + + for (size_t i = 0; i < num_elem; ++i) + cout << " " << max[i] << "(" << pos[i] << ")" << endl; + delete[] pos; + delete[] max; + return 0; +} + diff --git a/src/tbb/examples/GettingStarted/sub_string_finder/sub_string_finder_extended.cpp b/src/tbb/examples/GettingStarted/sub_string_finder/sub_string_finder_extended.cpp new file mode 100644 index 0000000..4eb5b70 --- /dev/null +++ b/src/tbb/examples/GettingStarted/sub_string_finder/sub_string_finder_extended.cpp @@ -0,0 +1,171 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if __TBB_MIC +#pragma offload_attribute (push,target(mic)) +#endif // __TBB_MIC + +#include +#include +#include + +#include "tbb/parallel_for.h" +#include "tbb/blocked_range.h" +#include "tbb/tick_count.h" + +#if __TBB_MIC +#pragma offload_attribute (pop) + +class __declspec(target(mic)) SubStringFinder; +#endif // __TBB_MIC + +using namespace tbb; +using namespace std; +static const size_t N = 22; + +void SerialSubStringFinder ( const string &str, size_t *max_array, size_t *pos_array) { + for ( size_t i = 0; i < str.size(); ++i ) { + size_t max_size = 0, max_pos = 0; + for (size_t j = 0; j < str.size(); ++j) + if (j != i) { + size_t limit = str.size()-( i > j ? i : j ); + for (size_t k = 0; k < limit; ++k) { + if (str[i + k] != str[j + k]) break; + if (k > max_size) { + max_size = k; + max_pos = j; + } + } + } + max_array[i] = max_size; + pos_array[i] = max_pos; + } +} + +class SubStringFinder { + const string str; + size_t *max_array; + size_t *pos_array; + public: + void operator() ( const blocked_range& r ) const { + for ( size_t i = r.begin(); i != r.end(); ++i ) { + size_t max_size = 0, max_pos = 0; + for (size_t j = 0; j < str.size(); ++j) + if (j != i) { + size_t limit = str.size()-( i > j ? i : j ); + for (size_t k = 0; k < limit; ++k) { + if (str[i + k] != str[j + k]) break; + if (k > max_size) { + max_size = k; + max_pos = j; + } + } + } + max_array[i] = max_size; + pos_array[i] = max_pos; + } + } + SubStringFinder(string &s, size_t *m, size_t *p) : + str(s), max_array(m), pos_array(p) { } +}; + +int main(int argc, char *argv[]) { + + + string str[N] = { string("a"), string("b") }; + for (size_t i = 2; i < N; ++i) str[i] = str[i-1]+str[i-2]; + string &to_scan = str[N-1]; + size_t num_elem = to_scan.size(); + + size_t *max = new size_t[num_elem]; + size_t *max2 = new size_t[num_elem]; + size_t *pos = new size_t[num_elem]; + size_t *pos2 = new size_t[num_elem]; + cout << " Done building string." << endl; + + + tick_count serial_t0 = tick_count::now(); + SerialSubStringFinder(to_scan, max2, pos2); + tick_count serial_t1 = tick_count::now(); + cout << " Done with serial version." << endl; + + tick_count parallel_t0 = tick_count::now(); + parallel_for(blocked_range(0, num_elem, 100), + SubStringFinder( to_scan, max, pos ) ); + tick_count parallel_t1 = tick_count::now(); + cout << " Done with parallel version." << endl; + + for (size_t i = 0; i < num_elem; ++i) { + if (max[i] != max2[i] || pos[i] != pos2[i]) { + cout << "ERROR: Serial and Parallel Results are Different!" << endl; + } + } + cout << " Done validating results." << endl; + + cout << "Serial version ran in " << (serial_t1 - serial_t0).seconds() << " seconds" << endl + << "Parallel version ran in " << (parallel_t1 - parallel_t0).seconds() << " seconds" << endl + << "Resulting in a speedup of " << (serial_t1 - serial_t0).seconds() / (parallel_t1 - parallel_t0).seconds() << endl; + +#if __TBB_MIC + // Do offloadable version. Do the timing on host. + size_t *max3 = new size_t[num_elem]; + size_t *pos3 = new size_t[num_elem]; + tick_count parallel_tt0 = tick_count::now(); + const char* to_scan_str = to_scan.c_str(); // Offload the string as a char array. + #pragma offload target(mic) in(num_elem) in(to_scan_str:length(num_elem)) out(max3,pos3:length(num_elem)) + { + string to_scan(to_scan_str, num_elem); // Reconstruct the string in offloadable region. + // Suboptimal performance because of making a copy from to_scan_str at creating to_scan. + parallel_for(blocked_range(0, num_elem, 100), + SubStringFinder( to_scan, max3, pos3 ) ); + } + tick_count parallel_tt1 = tick_count::now(); + cout << " Done with offloadable version." << endl; + + // Do validation of offloadable results on host. + for (size_t i = 0; i < num_elem; ++i) { + if (max3[i] != max2[i] || pos3[i] != pos2[i]) { + cout << "ERROR: Serial and Offloadable Results are Different!" << endl; + } + } + cout << " Done validating offloadable results." << endl; + + cout << "Offloadable version ran in " << (parallel_tt1 - parallel_tt0).seconds() << " seconds" << endl + << "Resulting in a speedup of " << (serial_t1 - serial_t0).seconds() / (parallel_tt1 - parallel_tt0).seconds() << " of offloadable version" << endl; + + delete[] max3; + delete[] pos3; +#endif // __TBB_MIC + + delete[] max; + delete[] pos; + delete[] max2; + delete[] pos2; + return 0; +} + diff --git a/src/tbb/examples/GettingStarted/sub_string_finder/sub_string_finder_pretty.cpp b/src/tbb/examples/GettingStarted/sub_string_finder/sub_string_finder_pretty.cpp new file mode 100644 index 0000000..9160dc4 --- /dev/null +++ b/src/tbb/examples/GettingStarted/sub_string_finder/sub_string_finder_pretty.cpp @@ -0,0 +1,98 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include +#include +#include + +#include "tbb/parallel_for.h" +#include "tbb/blocked_range.h" + +using namespace tbb; +static const size_t N = 9; + +class SubStringFinder { + const std::string str; + size_t *max_array; + size_t *pos_array; + public: + void operator() ( const blocked_range& r ) const { + for ( size_t i = r.begin(); i != r.end(); ++i ) { + size_t max_size = 0, max_pos = 0; + for (size_t j = 0; j < str.size(); ++j) + if (j != i) { + size_t limit = str.size()-( i > j ? i : j ); + for (size_t k = 0; k < limit; ++k) { + if (str[i + k] != str[j + k]) break; + if (k+1 > max_size) { + max_size = k+1; + max_pos = j; + } + } + } + max_array[i] = max_size; + pos_array[i] = max_pos; + } + } + SubStringFinder(std::string &s, size_t *m, size_t *p) : + str(s), max_array(m), pos_array(p) { } +}; + +int main(int argc, char *argv[]) { + + + std::string str[N] = { std::string("a"), std::string("b") }; + for (size_t i = 2; i < N; ++i) str[i] = str[i-1]+str[i-2]; + std::string &to_scan = str[N-1]; + size_t num_elem = to_scan.size(); + std::cout << "String to scan: " << to_scan << std::endl; + + size_t *max = new size_t[num_elem]; + size_t *pos = new size_t[num_elem]; + + parallel_for(blocked_range(0, num_elem, 100), + SubStringFinder( to_scan, max, pos ) ); + + for (size_t i = 0; i < num_elem; ++i) { + for (size_t j = 0; j < num_elem; ++j) { + if (j >= i && j < i + max[i]) std::cout << "_"; + else std::cout << " "; + } + std::cout << std::endl << to_scan << std::endl; + + for (size_t j = 0; j < num_elem; ++j) { + if (j >= pos[i] && j < pos[i] + max[i]) std::cout << "*"; + else std::cout << " "; + } + std::cout << std::endl; + } + delete[] max; + delete[] pos; + return 0; +} + diff --git a/src/tbb/examples/GettingStarted/sub_string_finder/xcode/sub_string_finder.xcodeproj/project.pbxproj b/src/tbb/examples/GettingStarted/sub_string_finder/xcode/sub_string_finder.xcodeproj/project.pbxproj new file mode 100644 index 0000000..9e28b39 --- /dev/null +++ b/src/tbb/examples/GettingStarted/sub_string_finder/xcode/sub_string_finder.xcodeproj/project.pbxproj @@ -0,0 +1,573 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + A1F593A60B8F042A00073279 /* sub_string_finder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1F593A50B8F042A00073279 /* sub_string_finder.cpp */; }; + A1F593B70B8F06F900073279 /* libtbb.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; + A1F593BB0B8F072500073279 /* libtbb.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; + A1F594120B8F1E0C00073279 /* sub_string_finder_pretty.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1F594110B8F1E0C00073279 /* sub_string_finder_pretty.cpp */; }; + A1F594130B8F1E1700073279 /* libtbb.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; + A1F594160B8F1E8000073279 /* libtbb.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; + A1F594240B8F1F5F00073279 /* libtbb.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; + A1F594250B8F1F6800073279 /* libtbb.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; + A1F594270B8F1F8100073279 /* sub_string_finder_extended.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1F594260B8F1F8100073279 /* sub_string_finder_extended.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8DD76F690486A84900D96B5E /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = ""; + dstSubfolderSpec = 16; + files = ( + A1F593BB0B8F072500073279 /* libtbb.dylib in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1F594140B8F1E2D00073279 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 16; + files = ( + A1F594160B8F1E8000073279 /* libtbb.dylib in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1F5941D0B8F1F2D00073279 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 16; + files = ( + A1F594250B8F1F6800073279 /* libtbb.dylib in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 8DD76F6C0486A84900D96B5E /* sub_string_finder */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sub_string_finder; sourceTree = BUILT_PRODUCTS_DIR; }; + A1F593A50B8F042A00073279 /* sub_string_finder.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = sub_string_finder.cpp; path = ../sub_string_finder.cpp; sourceTree = SOURCE_ROOT; }; + A1F593B30B8F06F900073279 /* libtbb.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtbb.dylib; path = ../../../../lib/libtbb.dylib; sourceTree = SOURCE_ROOT; }; + A1F5940A0B8F1D8E00073279 /* sub_string_finder_pretty */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sub_string_finder_pretty; sourceTree = BUILT_PRODUCTS_DIR; }; + A1F594110B8F1E0C00073279 /* sub_string_finder_pretty.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = sub_string_finder_pretty.cpp; path = ../sub_string_finder_pretty.cpp; sourceTree = SOURCE_ROOT; }; + A1F5941B0B8F1F0900073279 /* sub_string_finder_extended */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sub_string_finder_extended; sourceTree = BUILT_PRODUCTS_DIR; }; + A1F594260B8F1F8100073279 /* sub_string_finder_extended.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = sub_string_finder_extended.cpp; path = ../sub_string_finder_extended.cpp; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8DD76F660486A84900D96B5E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A1F593B70B8F06F900073279 /* libtbb.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1F594080B8F1D8E00073279 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A1F594130B8F1E1700073279 /* libtbb.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1F594190B8F1F0900073279 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A1F594240B8F1F5F00073279 /* libtbb.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* sub_string_finder */ = { + isa = PBXGroup; + children = ( + 08FB7795FE84155DC02AAC07 /* Source */, + A1F593B20B8F06F900073279 /* External Frameworks and Libraries */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + ); + name = sub_string_finder; + sourceTree = ""; + }; + 08FB7795FE84155DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + A1F594260B8F1F8100073279 /* sub_string_finder_extended.cpp */, + A1F594110B8F1E0C00073279 /* sub_string_finder_pretty.cpp */, + A1F593A50B8F042A00073279 /* sub_string_finder.cpp */, + ); + name = Source; + sourceTree = ""; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8DD76F6C0486A84900D96B5E /* sub_string_finder */, + A1F5940A0B8F1D8E00073279 /* sub_string_finder_pretty */, + A1F5941B0B8F1F0900073279 /* sub_string_finder_extended */, + ); + name = Products; + sourceTree = ""; + }; + A1F593B20B8F06F900073279 /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + A1F593B30B8F06F900073279 /* libtbb.dylib */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8DD76F620486A84900D96B5E /* sub_string_finder */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "sub_string_finder" */; + buildPhases = ( + 8DD76F640486A84900D96B5E /* Sources */, + 8DD76F660486A84900D96B5E /* Frameworks */, + 8DD76F690486A84900D96B5E /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = sub_string_finder; + productInstallPath = "$(HOME)/bin"; + productName = sub_string_finder; + productReference = 8DD76F6C0486A84900D96B5E /* sub_string_finder */; + productType = "com.apple.product-type.tool"; + }; + A1F594090B8F1D8E00073279 /* sub_string_finder_pretty */ = { + isa = PBXNativeTarget; + buildConfigurationList = A1F5940C0B8F1DB600073279 /* Build configuration list for PBXNativeTarget "sub_string_finder_pretty" */; + buildPhases = ( + A1F594070B8F1D8E00073279 /* Sources */, + A1F594080B8F1D8E00073279 /* Frameworks */, + A1F594140B8F1E2D00073279 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = sub_string_finder_pretty; + productName = sub_string_finder_pretty; + productReference = A1F5940A0B8F1D8E00073279 /* sub_string_finder_pretty */; + productType = "com.apple.product-type.tool"; + }; + A1F5941A0B8F1F0900073279 /* sub_string_finder_extended */ = { + isa = PBXNativeTarget; + buildConfigurationList = A1F5941F0B8F1F4E00073279 /* Build configuration list for PBXNativeTarget "sub_string_finder_extended" */; + buildPhases = ( + A1F594180B8F1F0900073279 /* Sources */, + A1F594190B8F1F0900073279 /* Frameworks */, + A1F5941D0B8F1F2D00073279 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = sub_string_finder_extended; + productName = sub_string_finder_extended; + productReference = A1F5941B0B8F1F0900073279 /* sub_string_finder_extended */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0410; + }; + buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "sub_string_finder" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 08FB7794FE84155DC02AAC07 /* sub_string_finder */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + A1F5941A0B8F1F0900073279 /* sub_string_finder_extended */, + A1F594090B8F1D8E00073279 /* sub_string_finder_pretty */, + 8DD76F620486A84900D96B5E /* sub_string_finder */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 8DD76F640486A84900D96B5E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1F593A60B8F042A00073279 /* sub_string_finder.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1F594070B8F1D8E00073279 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1F594120B8F1E0C00073279 /* sub_string_finder_pretty.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1F594180B8F1F0900073279 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1F594270B8F1F8100073279 /* sub_string_finder_extended.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1DEB923208733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = sub_string_finder; + ZERO_LINK = NO; + }; + name = Debug; + }; + 1DEB923308733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = sub_string_finder; + ZERO_LINK = NO; + }; + name = Release; + }; + 1DEB923608733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Debug; + }; + 1DEB923708733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Release; + }; + A1F593C60B8F0E6E00073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = sub_string_finder; + ZERO_LINK = NO; + }; + name = Debug64; + }; + A1F593C70B8F0E6E00073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = sub_string_finder; + ZERO_LINK = NO; + }; + name = Release64; + }; + A1F593C80B8F0E6E00073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-m64", + ); + OTHER_LDFLAGS = "-m64"; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Debug64; + }; + A1F593C90B8F0E6E00073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-m64", + ); + OTHER_LDFLAGS = "-m64"; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Release64; + }; + A1F5940D0B8F1DB600073279 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = sub_string_finder_pretty; + ZERO_LINK = NO; + }; + name = Debug; + }; + A1F5940E0B8F1DB600073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = sub_string_finder_pretty; + ZERO_LINK = NO; + }; + name = Debug64; + }; + A1F5940F0B8F1DB600073279 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = sub_string_finder_pretty; + ZERO_LINK = NO; + }; + name = Release; + }; + A1F594100B8F1DB600073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = sub_string_finder_pretty; + ZERO_LINK = NO; + }; + name = Release64; + }; + A1F594200B8F1F4E00073279 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = sub_string_finder_extended; + ZERO_LINK = NO; + }; + name = Debug; + }; + A1F594210B8F1F4E00073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = sub_string_finder_extended; + ZERO_LINK = NO; + }; + name = Debug64; + }; + A1F594220B8F1F4E00073279 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = sub_string_finder_extended; + ZERO_LINK = NO; + }; + name = Release; + }; + A1F594230B8F1F4E00073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = sub_string_finder_extended; + ZERO_LINK = NO; + }; + name = Release64; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "sub_string_finder" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923208733DC60010E9CD /* Debug */, + A1F593C60B8F0E6E00073279 /* Debug64 */, + 1DEB923308733DC60010E9CD /* Release */, + A1F593C70B8F0E6E00073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "sub_string_finder" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923608733DC60010E9CD /* Debug */, + A1F593C80B8F0E6E00073279 /* Debug64 */, + 1DEB923708733DC60010E9CD /* Release */, + A1F593C90B8F0E6E00073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A1F5940C0B8F1DB600073279 /* Build configuration list for PBXNativeTarget "sub_string_finder_pretty" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A1F5940D0B8F1DB600073279 /* Debug */, + A1F5940E0B8F1DB600073279 /* Debug64 */, + A1F5940F0B8F1DB600073279 /* Release */, + A1F594100B8F1DB600073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A1F5941F0B8F1F4E00073279 /* Build configuration list for PBXNativeTarget "sub_string_finder_extended" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A1F594200B8F1F4E00073279 /* Debug */, + A1F594210B8F1F4E00073279 /* Debug64 */, + A1F594220B8F1F4E00073279 /* Release */, + A1F594230B8F1F4E00073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/src/tbb/examples/Makefile b/src/tbb/examples/Makefile new file mode 100644 index 0000000..3e6a265 --- /dev/null +++ b/src/tbb/examples/Makefile @@ -0,0 +1,157 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# This file should be always located and called in $(tbb_root)/examples + +# Usage: +# make [all] [clean] [release] [debug] [test] +# executes specified targets for all examples. +# make {example's dir}/{target} +# calls specified example with specified target. +# For instance: make task/tree_sum/all + +tbb_root?=.. +BUILDING_PHASE:=0 +include ../build/common.inc + +#check, if tbb_root is not absolute path (the filter keeps only /* paths) +ifeq ($(filter /% $(SLASH)%, $(subst :, ,$(tbb_root)) ),) + # also changes related variables like work_dir + override tbb_root := $(CWD)$(SLASH).. + export TBBROOT := $(tbb_root) +endif + +ifeq ($(tbb_os),windows) + ifeq ($(UNIXMODE),1) + EXAMPLE_MAKEFILE = Makefile + EXAMPLES = $(wildcard */*/$(EXAMPLE_MAKEFILE)) + ifeq ($(compiler),gcc) + override CXXFLAGS += -Wl,--enable-auto-import + endif + export CPATH := $(CPATH);$(tbb_root)/include + export LIBRARY_PATH := $(LIBRARY_PATH);$(work_dir)_release;$(work_dir)_debug + export RM = cmd /C del /Q /F + else + EXAMPLE_MAKEFILE = Makefile.windows + EXAMPLES = $(wildcard */*/$(EXAMPLE_MAKEFILE)) + EXAMPLE_MAKEFILE := $(if $(EXAMPLES),Makefile.windows,Makefile) + export INCLUDE := $(tbb_root)$(SLASH)include;$(INCLUDE) + export LIB := $(work_dir)_release;$(work_dir)_debug;$(LIB) + endif + work_dir := $(subst /,$(SLASH),$(work_dir)) + export PATH := $(work_dir)_release;$(work_dir)_debug;$(PATH) + export TBB_ARCH_PLATFORM = $(arch)\$(runtime) + export TBB_TARGET_ARCH = $(arch) +else + EXAMPLE_MAKEFILE = Makefile + EXAMPLES := $(wildcard */*/$(EXAMPLE_MAKEFILE)) + # platform-specific settings + ifeq ($(arch),ia64) + override CXXFLAGS += $(PIC_KEY) + endif + ifeq ($(subst suncc,gcc,$(compiler)),gcc) + ifeq ($(compiler),suncc) + override CXXFLAGS += -I$(tbb_root)$(SLASH)include -library=stlport4 -M$(tbb_root)/build/suncc.map.pause -erroff=unassigned,attrskipunsup,badargtype2w,badbinaryopw,wbadasg,wvarhidemem,wbadinit + endif + ifeq ($(arch),intel64) + override CXXFLAGS += -m64 + endif + ifeq ($(arch),ia32) + override CXXFLAGS += -m32 + endif + ifeq ($(arch),ppc64) + override CXXFLAGS += -m64 + endif + ifeq ($(arch),ppc32) + override CXXFLAGS += -m32 + endif + ifeq ($(arch),sparc) + override CXXFLAGS += -mcpu=v9 -m64 + endif + endif + ifeq ($(compiler),xl) + # -qsuppress=1540-0198 suppresses warnings like "1540-0198 (W) The omitted keyword "private" is assumed for base class "no_copy"." + # -qsuppress=1540-1401 suppresses warnings like "1540-1401 (I) An unknown "pragma ivdep" is specified." + override CXXFLAGS += -I$(tbb_root)$(SLASH)include -qsuppress=1540-0198:1540-1401 -L$(work_dir)_release -L$(work_dir)_debug + ifeq ($(arch),intel64) + override CXXFLAGS += -q64 + endif + ifeq ($(arch),ia32) + override CXXFLAGS += -q32 + endif + ifeq ($(arch),ppc64) + override CXXFLAGS += -q64 + endif + ifeq ($(arch),ppc32) + override CXXFLAGS += -q32 + endif + endif + ifeq ($(tbb_os),macos) + # GUI for examples does not support 64-bit platforms + ifeq ($(arch),intel64) + export UI=con + endif + ifeq ($(arch),ppc64) + export UI=con + endif + export DYLD_LIBRARY_PATH := $(DYLD_LIBRARY_PATH):$(work_dir)_release:$(work_dir)_debug + else + # -L necessary for non-native compilers which don't search $LIBRARY_PATH + override CXXFLAGS += -L$(work_dir)_release -L$(work_dir)_debug + export LD_LIBRARY_PATH := $(LD_LIBRARY_PATH):$(work_dir)_release:$(work_dir)_debug + endif + export LIBS + export LIBRARY_PATH := $(LIBRARY_PATH):$(work_dir)_release:$(work_dir)_debug + export CPATH := $(CPATH):$(tbb_root)/include +endif + +COMMON_TARGETS := all clean release debug test perf_build perf_run +# list of directories of examples +EXAMPLES_DIRS := $(foreach T,$(EXAMPLES),$(dir $(T))) +# targets to explicitly call example have format: {example's dir}/{example's target} +EXAMPLES_TARGETS := $(foreach T,$(COMMON_TARGETS),$(addsuffix $(T),$(EXAMPLES_DIRS))) + +.PHONY: $(COMMON_TARGETS) $(EXAMPLES_TARGETS) + +.DEFAULT: all + +# execute standard targets for all examples +$(COMMON_TARGETS):: % : $(addsuffix %,$(EXAMPLES_DIRS)) + +# proxy rule for calling appropriate example +$(EXAMPLES_TARGETS):: + @echo -------------------------------------------------- + -$(MAKE) SHELL=$(SHELL) -C $(@D) -f $(EXAMPLE_MAKEFILE) $(notdir $@) CXX="$(CPLUS)" CXXFLAGS="$(CXXFLAGS)" + +printenv: +ifeq ($(tbb_os),windows) + @cmd /C set PATH + @cmd /C set LIB + @cmd /C set INCLUDE +else + @env | grep PATH +endif + diff --git a/src/tbb/examples/common/copy_libraries.bat b/src/tbb/examples/common/copy_libraries.bat new file mode 100644 index 0000000..ff77b4d --- /dev/null +++ b/src/tbb/examples/common/copy_libraries.bat @@ -0,0 +1,74 @@ +@echo off +REM +REM Copyright 2005-2012 Intel Corporation. All Rights Reserved. +REM +REM This file is part of Threading Building Blocks. +REM +REM Threading Building Blocks is free software; you can redistribute it +REM and/or modify it under the terms of the GNU General Public License +REM version 2 as published by the Free Software Foundation. +REM +REM Threading Building Blocks is distributed in the hope that it will be +REM useful, but WITHOUT ANY WARRANTY; without even the implied warranty +REM of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +REM GNU General Public License for more details. +REM +REM You should have received a copy of the GNU General Public License +REM along with Threading Building Blocks; if not, write to the Free Software +REM Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +REM +REM As a special exception, you may use this file as part of a free software +REM library without restriction. Specifically, if other files instantiate +REM templates or use macros or inline functions from this file, or you compile +REM this file and link it with other files to produce an executable, this +REM file does not by itself cause the resulting executable to be covered by +REM the GNU General Public License. This exception does not however +REM invalidate any other reasons why the executable file might be covered by +REM the GNU General Public License. +REM + +:: Getting parameters +if ("%1") == ("") goto error +if ("%2") == ("") goto error +if ("%3") == ("") goto error +set arch=%1 +if ("%2") == ("debug") set postfix=_debug +set output_dir=%3 + +:: Optional 4th parameter to set install root +if ("%4") NEQ ("") set TBBROOT=%4 +:: Actually we can set install root by ourselves +if ("%TBBROOT%") == ("") set TBBROOT=%~d0%~p0..\..\ + +:: Getting vs folders in case vc_mt binaries are not provided +if ("%VS80COMNTOOLS%") NEQ ("") set vc_dir=vc8 +if ("%VS90COMNTOOLS%") NEQ ("") set vc_dir=vc9 +if ("%VS100COMNTOOLS%") NEQ ("") set vc_dir=vc10 + +:: Are we standalone/oss or inside compiler? +if exist "%TBBROOT%\bin\%arch%\vc8\tbb%postfix%.dll" set interim_path=bin\%arch% +if exist "%TBBROOT%\..\redist\%arch%\tbb\vc8\tbb%postfix%.dll" set interim_path=..\redist\%arch%\tbb +if ("%interim_path%") == ("") goto error + +:: Do we provide vc_mt binaries? +if exist "%TBBROOT%\%interim_path%\vc_mt\tbb%postfix%.dll" set vc_dir=vc_mt +if ("%vc_dir%") == ("") goto error + +:: We know everything we wanted and there are no errors +:: Copying binaries + +copy "%TBBROOT%\%interim_path%\%vc_dir%\tbb%postfix%.dll" "%output_dir%" +copy "%TBBROOT%\%interim_path%\%vc_dir%\tbb%postfix%.pdb" "%output_dir%" +copy "%TBBROOT%\%interim_path%\%vc_dir%\tbbmalloc%postfix%.dll" "%output_dir%" +copy "%TBBROOT%\%interim_path%\%vc_dir%\tbbmalloc%postfix%.pdb" "%output_dir%" +if exist "%TBBROOT%\%interim_path%\%vc_dir%\tbb_preview%postfix%.dll" copy "%TBBROOT%\%interim_path%\%vc_dir%\tbb_preview%postfix%.dll" "%output_dir%" +if exist "%TBBROOT%\%interim_path%\%vc_dir%\tbb_preview%postfix%.pdb" copy "%TBBROOT%\%interim_path%\%vc_dir%\tbb_preview%postfix%.pdb" "%output_dir%" + +goto end +:error +echo Error occurred in libraries copying during post-build step. +exit /B 1 + +:end +exit /B 0 + diff --git a/src/tbb/examples/common/gui/Makefile.gmake b/src/tbb/examples/common/gui/Makefile.gmake new file mode 100644 index 0000000..6348aca --- /dev/null +++ b/src/tbb/examples/common/gui/Makefile.gmake @@ -0,0 +1,77 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# The C++ compiler +#CXX=g++ + +# detecting MS Windows (for MinGW support) +ifeq ($(OS), Windows_NT) +RM = cmd /C del /Q /F +RD = cmd /C rmdir +UI = con +EXE = $(NAME)$(SUFFIX).exe + +else +RM = rm -f +RD = rmdir -r +# detecting x64 +ifeq ($(shell uname -m),x86_64) +x64 ?= 64 +endif +# detecting UI ("mac", "x" or "con") +ifeq ($(shell uname),Darwin) +UI ?= mac +else +UI ?= $(shell sh -c "[ -f /usr/X11R6/lib$(x64)/libX11.so -o -f /usr/lib$(x64)/libX11.so ] && echo x || echo con") +endif + +ifeq ($(UI),x) +EXE = $(NAME)$(SUFFIX) +UI_CXXFLAGS += -I/usr/X11R6/include +LIBS += -lpthread -L/usr/X11R6/lib$(x64) -lX11 +# detect if libXext can be found +ifeq ($(shell sh -c "[ -f /usr/X11R6/lib$(x64)/libXext.so -o -f /usr/lib$(x64)/libXext.so ] && echo 0"),0) +LIBS += -lXext +else # no libXext +UI_CXXFLAGS += -DX_NOSHMEM +endif # libXext + +else # ! X +ifeq ($(UI),mac) +CXX_UI?=g++ +LIBS += -framework OpenGL -framework Foundation -framework Cocoa +MACUISOURCES = ../../common/gui/xcode/tbbExample/OpenGLView.m ../../common/gui/xcode/tbbExample/main.m ../../common/gui/xcode/tbbExample/tbbAppDelegate.m +MACUIOBJS = OpenGLView.o main.o tbbAppDelegate.o +APPRES = $(NAME)$(SUFFIX).app/Contents/Resources +EXE = $(NAME)$(SUFFIX).app/Contents/MacOS/$(NAME)$(SUFFIX) + +else # ! Mac +UI = con +EXE = $(NAME)$(SUFFIX) + +endif # Mac +endif # X +endif # Windows vs. other diff --git a/src/tbb/examples/common/gui/Makefile.win b/src/tbb/examples/common/gui/Makefile.win new file mode 100644 index 0000000..dce2cd8 --- /dev/null +++ b/src/tbb/examples/common/gui/Makefile.win @@ -0,0 +1,82 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Per-build Makefile rules (for recursive $(MAKE) calls from Makefile) + +# Base compile/link options +MYCXXFLAGS = /nologo /EHsc /Zc:forScope /D WIN32 /D _MBCS /D _CRT_SECURE_NO_DEPRECATE $(CXXFLAGS) +MYLFLAGS = /link /incremental:no /fixed:no $(LFLAGS) +CXXFLAGS_NDEBUG = /MD /O2 /Ot /Gy /D NDEBUG +CXXFLAGS_DEBUG = /MDd /Od /Zi /D _DEBUG + +# Specify library directory for Direct X SDK +DDLIB_DIR=$(DXSDK_DIR)\lib\$(XARCH:AMD64=x64) + +# Input and output files +#SOURCE = v +#RCNAME = specified externaly +#EXE = ^ +# defaults on XARCH = x86 +UISRC = ../../common/gui/$(UI)video.cpp + +default: + +build_echo: + -@echo Building$(DEBUG) $(EXE) with UI=$(UI) XARCH=$(XARCH) + +build_one: build_echo build_$(UI)$(DEBUG) + +build_con: $(SOURCE) $(UISRC) compiler_check + $(CXX) $(CXXFLAGS_NDEBUG) $(MYCXXFLAGS) $(SOURCE) $(UISRC) $(MYLFLAGS) /subsystem:console /OUT:$(EXE) + @cmd.exe /C del *.obj + +build_con_debug: $(SOURCE) $(UISRC) compiler_check + $(CXX) $(CXXFLAGS_DEBUG) $(MYCXXFLAGS) $(SOURCE) $(UISRC) $(MYLFLAGS) /debug /subsystem:console /OUT:$(EXE) + @cmd.exe /C del *.obj + +build_gdi: $(SOURCE) $(UISRC) msvs/$(RCNAME).res compiler_check + $(CXX) $(CXXFLAGS_NDEBUG) /D _WINDOWS $(MYCXXFLAGS) $(SOURCE) $(UISRC) $(MYLFLAGS) msvs/$(RCNAME).res /subsystem:windows /machine:$(XARCH) /OUT:$(EXE) + @cmd.exe /C del *.obj + +build_gdi_debug: $(SOURCE) $(UISRC) msvs/$(RCNAME).res compiler_check + $(CXX) $(CXXFLAGS_DEBUG) /D _WINDOWS $(MYCXXFLAGS) $(SOURCE) $(UISRC) $(MYLFLAGS) msvs/$(RCNAME).res /debug /subsystem:windows /machine:$(XARCH) /OUT:$(EXE) + @cmd.exe /C del *.obj + +build_dd: $(SOURCE) $(UISRC) msvs/$(RCNAME).res compiler_check + -@echo Using DirectX SDK from "$(DDLIB_DIR)" + $(CXX) $(CXXFLAGS_NDEBUG) /D _WINDOWS $(MYCXXFLAGS) /I "$(DXSDK_DIR)\include" $(SOURCE) $(UISRC) $(MYLFLAGS) /LIBPATH:"$(DDLIB_DIR)" msvs/$(RCNAME).res /subsystem:windows /machine:$(XARCH) /OUT:$(EXE) + @cmd.exe /C del *.obj + +build_dd_debug: $(SOURCE) $(UISRC) msvs/$(RCNAME).res compiler_check + -@echo Using DirectX SDK from "$(DDLIB_DIR)" + $(CXX) $(CXXFLAGS_DEBUG) /D _WINDOWS $(MYCXXFLAGS) /I "$(DXSDK_DIR)\include" $(SOURCE) $(UISRC) $(MYLFLAGS) /LIBPATH:"$(DDLIB_DIR)" msvs/$(RCNAME).res /debug /subsystem:windows /machine:$(XARCH) /OUT:$(EXE) + @cmd.exe /C del *.obj + +msvs/$(RCNAME).res: + rc /r msvs/$(RCNAME) +compiler_check: + @echo compiler_test>compiler_test && @$(CXX) /E compiler_test >nul 2>&1 || echo "$(CXX) command not found. Check if CXX=$(CXX) is set properly" + @cmd.exe /C del compiler_test diff --git a/src/tbb/examples/common/gui/convideo.cpp b/src/tbb/examples/common/gui/convideo.cpp new file mode 100644 index 0000000..6d06733 --- /dev/null +++ b/src/tbb/examples/common/gui/convideo.cpp @@ -0,0 +1,138 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "video.h" +#include +#include + +unsigned int * g_pImg = 0; +int g_sizex, g_sizey; +static video *g_video = 0; +static int g_fps = 0; + +#if _WIN32 || _WIN64 + +static DWORD g_msec = 0; +#ifdef _WINDOWS +HINSTANCE video::win_hInstance = 0; +int video::win_iCmdShow = 0; +void video::win_set_class(WNDCLASSEX &wcex) { } +void video::win_load_accelerators(int idc) { } +#endif //_WINDOWS + +#else + +#include +#include +struct timeval g_time; + +#endif //_WIN32||_WIN64 + +video::video() + : red_mask(0xff0000), red_shift(16), green_mask(0xff00), + green_shift(8), blue_mask(0xff), blue_shift(0), depth(24) +{ + assert(g_video == 0); + g_video = this; title = "Video"; updating = calc_fps = false; +} + +bool video::init_window(int x, int y) +{ + g_sizex = x; g_sizey = y; + g_pImg = new unsigned int[x*y]; + running = true; + return false; +} + +bool video::init_console() +{ + running = true; + return true; +} + +void video::terminate() +{ + if(calc_fps) { + double fps = g_fps; +#if _WIN32 || _WIN64 + fps /= (GetTickCount()-g_msec)/1000.0; +#else + struct timezone tz; struct timeval end_time; gettimeofday(&end_time, &tz); + fps /= (end_time.tv_sec+1.0*end_time.tv_usec/1000000.0) - (g_time.tv_sec+1.0*g_time.tv_usec/1000000.0); +#endif + printf("%s: %.1f fps\n", title, fps); + } + g_video = 0; running = false; + if(g_pImg) { delete[] g_pImg; g_pImg = 0; } +} + +video::~video() +{ + if(g_video) terminate(); +} + +//! Count and display FPS count in titlebar +bool video::next_frame() +{ + if(calc_fps){ + if(!g_fps) { +#if _WIN32 || _WIN64 + g_msec = GetTickCount(); +#else + struct timezone tz; gettimeofday(&g_time, &tz); +#endif + } + g_fps++; + } + return running; +} + +//! Do standard loop +void video::main_loop() +{ + on_process(); +} + +//! Change window title +void video::show_title() +{ +} + +///////////////////////////////////////////// public methods of video class /////////////////////// + +drawing_area::drawing_area(int x, int y, int sizex, int sizey) + : start_x(x), start_y(y), size_x(sizex), size_y(sizey), pixel_depth(24), + base_index(y*g_sizex + x), max_index(g_sizex*g_sizey), index_stride(g_sizex), ptr32(g_pImg) +{ + assert(x < g_sizex); assert(y < g_sizey); + assert(x+sizex <= g_sizex); assert(y+sizey <= g_sizey); + + index = base_index; // current index +} + +void drawing_area::update() {} diff --git a/src/tbb/examples/common/gui/d2dvideo.cpp b/src/tbb/examples/common/gui/d2dvideo.cpp new file mode 100644 index 0000000..2dd545a --- /dev/null +++ b/src/tbb/examples/common/gui/d2dvideo.cpp @@ -0,0 +1,209 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// common Windows parts +#include "winvideo.h" + +// and another headers +#include +#include +#include +#if _DXSDK_PRODUCT_MAJOR < 9 +#error DXSDK Version 9 and above required. +#endif +#include +#include +#pragma comment(lib, "d2d1.lib") + +ID2D1Factory *m_pD2DFactory; +ID2D1HwndRenderTarget *m_pRenderTarget; +ID2D1Bitmap *m_pBitmap; +D2D1_SIZE_U bitmapSize; + +HANDLE g_hVSync; + +#include +#pragma comment(lib, "DxErr.lib") + +//! Create a dialog box and tell the user what went wrong +bool DisplayError(LPSTR lpstrErr, HRESULT hres) +{ + if(hres != S_OK){ + static bool InError = false; + int retval = 0; + if (!InError) + { + InError = true; + const char *message = hres?DXGetErrorString(hres):0; + retval = MessageBoxA(g_hAppWnd, lpstrErr, hres?message:"Error!", MB_OK|MB_ICONERROR); + InError = false; + } + } + return false; +} + +void DrawBitmap() +{ + HRESULT hr = S_OK; + if (m_pRenderTarget) { + m_pRenderTarget->BeginDraw(); + if (m_pBitmap) + hr = m_pBitmap->CopyFromMemory(NULL,(BYTE*)g_pImg, 4*g_sizex); + DisplayError( "DrawBitmap error", hr ); + m_pRenderTarget->DrawBitmap(m_pBitmap); + m_pRenderTarget->EndDraw(); + } + return; +} + +inline void mouse(int k, LPARAM lParam) +{ + int x = (int)LOWORD(lParam); + int y = (int)HIWORD(lParam); + RECT rc; + GetClientRect(g_hAppWnd, &rc); + g_video->on_mouse( x*g_sizex/(rc.right - rc.left), y*g_sizey/(rc.bottom - rc.top), k ); +} + +//! Win event processing function +LRESULT CALLBACK InternalWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + switch (iMsg) + { + case WM_MOVE: + // Check to make sure our window exists before we tell it to repaint. + // This will fail the first time (while the window is being created). + if (hwnd) { + InvalidateRect(hwnd, NULL, FALSE); + UpdateWindow(hwnd); + } + return 0L; + + case WM_SIZE: + case WM_PAINT: + if( g_video->running && g_video->updating ) { + DrawBitmap(); + Sleep(0); + } + break; + // Proccess all mouse and keyboard events + case WM_LBUTTONDOWN: mouse( 1, lParam ); break; + case WM_LBUTTONUP: mouse(-1, lParam ); break; + case WM_RBUTTONDOWN: mouse( 2, lParam ); break; + case WM_RBUTTONUP: mouse(-2, lParam ); break; + case WM_MBUTTONDOWN: mouse( 3, lParam ); break; + case WM_MBUTTONUP: mouse(-3, lParam ); break; + case WM_CHAR: g_video->on_key( (int)wParam); break; + + // some useless stuff + case WM_ERASEBKGND: return 1; // keeps erase-background events from happening, reduces chop + case WM_DISPLAYCHANGE: return 0; + + // Now, shut down the window... + case WM_DESTROY: PostQuitMessage(0); return 0; + } + // call user defined proc, if exists + return g_pUserProc? g_pUserProc(hwnd, iMsg, wParam, lParam) : DefWindowProc(hwnd, iMsg, wParam, lParam); +} + +bool video::init_window(int sizex, int sizey) +{ + assert(win_hInstance != 0); + g_sizex = sizex; g_sizey = sizey; + if (!WinInit(win_hInstance, win_iCmdShow, gWndClass, title, false)) { + DisplayError("Unable to initialize the program's window."); + return false; + } + ShowWindow(g_hAppWnd, SW_SHOW); + g_pImg = new unsigned int[sizex*sizey]; + + HRESULT hr = S_OK; + + hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pD2DFactory); + // Create a Direct2D render target. + if (SUCCEEDED(hr) && !m_pRenderTarget){ + RECT rc; + GetClientRect(g_hAppWnd, &rc); + + bitmapSize = D2D1::SizeU( + rc.right - rc.left, + rc.bottom - rc.top + ); + + hr = m_pD2DFactory->CreateHwndRenderTarget( + D2D1::RenderTargetProperties(), + D2D1::HwndRenderTargetProperties(g_hAppWnd, bitmapSize), + &m_pRenderTarget + ); + if (SUCCEEDED(hr) && !m_pBitmap){ + D2D1_PIXEL_FORMAT pixelFormat = D2D1::PixelFormat( + DXGI_FORMAT_B8G8R8A8_UNORM, + D2D1_ALPHA_MODE_IGNORE + ); + D2D1_BITMAP_PROPERTIES bitmapProperties; + bitmapProperties.pixelFormat = pixelFormat; + m_pRenderTarget->GetDpi( &bitmapProperties.dpiX, &bitmapProperties.dpiY ); + m_pRenderTarget->CreateBitmap(bitmapSize,bitmapProperties,&m_pBitmap); + m_pRenderTarget->DrawBitmap(m_pBitmap); + } + } + + running = true; + return true; +} + +void video::terminate() +{ + if (m_pBitmap) m_pBitmap->Release(); + if (m_pRenderTarget) m_pRenderTarget->Release(); + if (m_pD2DFactory) m_pD2DFactory->Release(); + g_video = 0; running = false; + if(g_pImg) { delete[] g_pImg; g_pImg = 0; } +} + +//////////// drawing area constructor & destructor ///////////// + +drawing_area::drawing_area(int x, int y, int sizex, int sizey) +: start_x(x), start_y(y), size_x(sizex), size_y(sizey), pixel_depth(24), + base_index(y*g_sizex + x), max_index(g_sizex*g_sizey), index_stride(g_sizex), ptr32(g_pImg) +{ + assert(x < g_sizex); assert(y < g_sizey); + assert(x+sizex <= g_sizex); assert(y+sizey <= g_sizey); + + index = base_index; // current index +} + +void drawing_area::update() +{ + if(g_video->updating) { + RECT r; + r.left = start_x; r.right = start_x + size_x; + r.top = start_y; r.bottom = start_y + size_y; + InvalidateRect(g_hAppWnd, &r, false); + } +} diff --git a/src/tbb/examples/common/gui/ddvideo.cpp b/src/tbb/examples/common/gui/ddvideo.cpp new file mode 100644 index 0000000..3538b2f --- /dev/null +++ b/src/tbb/examples/common/gui/ddvideo.cpp @@ -0,0 +1,589 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// common Windows parts +#include "winvideo.h" + +#include +#if _DXSDK_PRODUCT_MAJOR >= 9 +// new implementation based on Direct2D +#include "d2dvideo.cpp" +#else // _DXSDK_PRODUCT_MAJOR >= 9 + +// and another headers +#include +#include +#include + +#pragma comment(lib, "ddraw.lib") +#pragma comment(lib, "dxguid.lib") + +LPDIRECTDRAW7 g_pDD = NULL; // DirectDraw object +LPDIRECTDRAWSURFACE7 g_pDDSPrimary = NULL;// DirectDraw primary surface +LPDIRECTDRAWSURFACE7 g_pDDSBack = NULL; // DirectDraw back surface +LPDIRECTDRAWSURFACE7 g_pDDSOverlay = NULL;// DirectDraw overlay surface +LPDIRECTDRAWCLIPPER g_pClipper = NULL; // DirectDraw clipping struct +DDOVERLAYFX g_OverlayFX; // DirectDraw overlay effects struct +DDCAPS g_DDCaps; // DirectDraw hardware capabilities struct +DWORD g_OverlayFlags = 0; // DirectDraw overlay flags variable +DWORD g_dwXRatio, + g_dwYRatio; // The ratios between the src and dst rects +RECT g_rcSrc = {0, 0, 0, 0}, + g_rcDst = {0, 0, 0, 0}; +HANDLE g_hVSync; + +// check for new DX SDK (8 & 9) +#ifdef DDSCAPS_PRIMARYSURFACELEFT +#include +#pragma comment(lib, "dxerr8.lib") +#else +// old SDK (7) +#include +#pragma comment(lib, "d3dx.lib") +#endif + +//! Create a dialog box and tell the user what went wrong +bool DisplayError(LPSTR lpstrErr, HRESULT hres) +{ + static bool InError = false; + int retval = 0; + if (!InError) + { + InError = true; +#ifdef DDSCAPS_PRIMARYSURFACELEFT + const char *message = hres?DXGetErrorString8A(hres):0; +#else + char message[256]; if(hres) D3DXGetErrorString(hres, 256, message); +#endif + retval = MessageBoxA(g_hAppWnd, lpstrErr, hres?message:"Error!", MB_OK|MB_ICONERROR); + InError = false; + } + return false; +} + +//! Releases the overlay surface +void DestroyOverlay() +{ + if (g_pClipper) + g_pClipper->Release(); + if (g_pDDSOverlay) { + g_pImg = 0; LPDIRECTDRAWSURFACE7 pDDSOverlay(g_pDDSOverlay); + g_pDDSOverlay = NULL; + YIELD_TO_THREAD(); + pDDSOverlay->Release(); // be sure nobody uses old value + } +} + +//! Releases the primary surface +void DestroyPrimary() +{ + if (g_pDDSPrimary) + { + g_pDDSPrimary->Release(); + g_pDDSPrimary = NULL; + } +} + +//! Releases core DirectDraw objects +void DestroyDDraw() +{ + DestroyPrimary(); + // Release the DDraw object + if (g_pDD) { + LPDIRECTDRAW7 pDD(g_pDD); // be sure nobody uses old value + g_pDD = NULL; Sleep(1); pDD->Release(); + } +} + +//! Checks and corrects all boundries for alignment and stretching +void CheckBoundries(void) +{ + // Make sure the coordinates fulfill the stretching requirements. Often + // the hardware will require a certain ammount of stretching to do + // overlays. This stretch factor is held in dwMinOverlayStretch as the + // stretch factor multiplied by 1000 (to keep an accuracy of 3 decimal places). + if ((g_DDCaps.dwCaps & DDCAPS_OVERLAYSTRETCH) && (g_DDCaps.dwMinOverlayStretch) + && (g_dwXRatio < g_DDCaps.dwMinOverlayStretch)) + { + g_rcDst.right = 2 * GetSystemMetrics(SM_CXSIZEFRAME) + g_rcDst.left + (g_sizex + * (g_DDCaps.dwMinOverlayStretch + 1)) / 1000; + SetWindowTextA(g_hAppWnd, "Window is too small!"); + } + else if ((g_DDCaps.dwCaps & DDCAPS_OVERLAYSTRETCH) && (g_DDCaps.dwMaxOverlayStretch) + && (g_dwXRatio > g_DDCaps.dwMaxOverlayStretch)) + { + g_rcDst.right = 2 * GetSystemMetrics(SM_CXSIZEFRAME) + g_rcDst.left + (g_sizey + * (g_DDCaps.dwMaxOverlayStretch + 999)) / 1000; + SetWindowTextA(g_hAppWnd, "Window is too large!"); + } + else if(!g_video->calc_fps) SetWindowText(g_hAppWnd, g_video->title); + + // Recalculate the ratio's for the upcoming calculations + g_dwXRatio = (g_rcDst.right - g_rcDst.left) * 1000 / (g_rcSrc.right - g_rcSrc.left); + g_dwYRatio = (g_rcDst.bottom - g_rcDst.top) * 1000 / (g_rcSrc.bottom - g_rcSrc.top); + + // Check to make sure we're within the screen's boundries, if not then fix + // the problem by adjusting the source rectangle which we draw from. + if (g_rcDst.left < 0) + { + g_rcSrc.left = -g_rcDst.left * 1000 / g_dwXRatio; + g_rcDst.left = 0; + } + if (g_rcDst.right > GetSystemMetrics(SM_CXSCREEN)) + { + g_rcSrc.right = g_sizex - ((g_rcDst.right - GetSystemMetrics(SM_CXSCREEN)) * 1000 / g_dwXRatio); + g_rcDst.right = GetSystemMetrics(SM_CXSCREEN); + } + if (g_rcDst.bottom > GetSystemMetrics(SM_CYSCREEN)) + { + g_rcSrc.bottom = g_sizey - ((g_rcDst.bottom - GetSystemMetrics(SM_CYSCREEN)) * 1000 / g_dwYRatio); + g_rcDst.bottom = GetSystemMetrics(SM_CYSCREEN); + } + // I don't know how useful this is... but just in case someone can do it - here's the check. + if (g_rcDst.top < 0) + { + g_rcSrc.top = -g_rcDst.top * 1000 / g_dwYRatio; + g_rcDst.top = 0; + } + + // Make sure the coordinates fulfill the alignment requirements + // these expressions (x & -y) just do alignment by dropping low order bits... + // so to round up, we add first, then truncate. + if ((g_DDCaps.dwCaps & DDCAPS_ALIGNBOUNDARYSRC) && g_DDCaps.dwAlignBoundarySrc) + g_rcSrc.left = (g_rcSrc.left + g_DDCaps.dwAlignBoundarySrc / 2) & -(signed) + (g_DDCaps.dwAlignBoundarySrc); + if ((g_DDCaps.dwCaps & DDCAPS_ALIGNSIZESRC) && g_DDCaps.dwAlignSizeSrc) + g_rcSrc.right = g_rcSrc.left + (g_rcSrc.right - g_rcSrc.left + g_DDCaps.dwAlignSizeSrc + / 2) & -(signed) (g_DDCaps.dwAlignSizeSrc); + if ((g_DDCaps.dwCaps & DDCAPS_ALIGNBOUNDARYDEST) && g_DDCaps.dwAlignBoundaryDest) + g_rcDst.left = (g_rcDst.left + g_DDCaps.dwAlignBoundaryDest / 2) & -(signed) + (g_DDCaps.dwAlignBoundaryDest); + if ((g_DDCaps.dwCaps & DDCAPS_ALIGNSIZEDEST) && g_DDCaps.dwAlignSizeDest) + g_rcDst.right = g_rcDst.left + (g_rcDst.right - g_rcDst.left) & -(signed) (g_DDCaps.dwAlignSizeDest); +} + +//! Get translated by system color value +DWORD DDColorMatch(IDirectDrawSurface7 * pdds, COLORREF rgb) +{ + COLORREF rgbT; + HDC hdc; + DWORD dw = CLR_INVALID; + DDSURFACEDESC2 ddsd; + HRESULT hres; + + // Use GDI SetPixel to color match for us + if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK) { + rgbT = GetPixel(hdc, 0, 0); // Save current pixel value + SetPixel(hdc, 0, 0, rgb); // Set our value + pdds->ReleaseDC(hdc); + } + // Now lock the surface so we can read back the converted color + ddsd.dwSize = sizeof(ddsd); + while ((hres = pdds->Lock(NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING) + YIELD_TO_THREAD(); + if (hres == DD_OK) { + dw = *(DWORD *) ddsd.lpSurface; // Get DWORD + if (ddsd.ddpfPixelFormat.dwRGBBitCount < 32) + dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount) - 1; // Mask it to bpp + pdds->Unlock(NULL); + } + else return DisplayError("Can't lock primary surface", hres); + // Now put the color that was there back. + if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK) { + SetPixel(hdc, 0, 0, rgbT); + pdds->ReleaseDC(hdc); + } + return dw; +} + +//! Load the bitmap and copy it to the overlay surface +bool DrawOverlay() +{ + HRESULT hRet; // This is where we put return values from DirectDraw. + DDSURFACEDESC2 surfDesc; + // Setup structure + memset(&surfDesc, 0, sizeof(surfDesc)); surfDesc.dwSize = sizeof(surfDesc); + + hRet = g_pDDSOverlay->Lock(NULL, &surfDesc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_NOSYSLOCK | DDLOCK_WRITEONLY, NULL); + if (hRet != DD_OK || surfDesc.lpSurface == NULL) + return DisplayError("Can't lock overlay surface", hRet); + else { + g_pImg = (unsigned int *)surfDesc.lpSurface; + //g_pDDSOverlay->Unlock(NULL); is not needed? + } + // Setup effects structure + memset(&g_OverlayFX, 0, sizeof(g_OverlayFX)); g_OverlayFX.dwSize = sizeof(g_OverlayFX); + // Setup overlay flags. + g_OverlayFlags = DDOVER_SHOW; + // Check for destination color keying capability + if ((g_DDCaps.dwCKeyCaps & DDCKEYCAPS_DESTOVERLAY) && ((g_DDCaps.dwCaps & DDCAPS_OVERLAYCANTCLIP) || (g_DDCaps.dwCKeyCaps & DDCKEYCAPS_NOCOSTOVERLAY) )) + { + // If so, we'll use it to clip the bitmap when other windows go on top + // of us. Just for the record - this color range for color keying (the + // high/low values) are not heavily supported right now, so for almost + // all cards, just use the same color for both. + g_OverlayFX.dckDestColorkey.dwColorSpaceLowValue = + g_OverlayFX.dckDestColorkey.dwColorSpaceHighValue = DDColorMatch(g_pDDSPrimary, RGBKEY); + g_OverlayFlags |= DDOVER_DDFX | DDOVER_KEYDESTOVERRIDE; + } else { + // If not, we'll setup a clipper for the window. This will fix the + // problem on a few video cards - but the ones that don't shouldn't care. + hRet = g_pDD->CreateClipper(0, &g_pClipper, NULL); + if (hRet != DD_OK) + return DisplayError("Can't create clipper", hRet); + hRet = g_pClipper->SetHWnd(0, g_hAppWnd); + if (hRet != DD_OK) + return DisplayError("Can't attach clipper", hRet); + hRet = g_pDDSPrimary->SetClipper(g_pClipper); + if (hRet != DD_OK) + return DisplayError("Can't set clipper", hRet); + } + return true; +} + +//! Init the primary surface +bool DDPrimaryInit() +{ + HRESULT hRet; + DDSURFACEDESC2 ddsd; // A surface description structure + + // Create the primary surface. The primary surface is the full screen - + // since we're a windowed app - we'll just write to the portion of the + // screen within our window. + memset(&ddsd, 0, sizeof(ddsd)); // Set all fields of struct to 0 and set .dwSize to + ddsd.dwSize = sizeof(ddsd); // Sizeof the variable - these two steps required for most DDraw structs + ddsd.dwFlags = DDSD_CAPS; // Set flags for variables we're using... + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; // Set the variables we said we would in dwFlags + hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSPrimary, NULL); + if (hRet != DD_OK) + return DisplayError("Can't create primary surface", hRet); + return true; +} + +//! Init DirectDraw Stuff +bool DDInit() +{ + HRESULT hRet; + g_rcSrc.right = g_sizex; + g_rcSrc.bottom = g_sizey; + + hRet = DirectDrawCreateEx(NULL, (VOID**)&g_pDD, IID_IDirectDraw7, NULL); + if (hRet != DD_OK) + return DisplayError("Can't create DirectDraw7 instance", hRet); + + // Set cooperation level with other windows to be normal (ie. not full screen) + // You MUST set the cooperation level to be SOMETHING, for windowed apps use + // DDSCL_NORMAL, for full screen use: DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN. + hRet = g_pDD->SetCooperativeLevel(g_hAppWnd, DDSCL_NORMAL); + if (hRet != DD_OK) + return DisplayError("Can't set cooperative level", hRet); + return DDPrimaryInit(); +} + +//! Setup the overlay object +bool DDOverlayInit() +{ + // Get hardware's CAPabilitieS + memset(&g_DDCaps, 0, sizeof(g_DDCaps)); + g_DDCaps.dwSize = sizeof(g_DDCaps); + if (g_pDD->GetCaps(&g_DDCaps, 0)) + return DisplayError("Can't get capabilities"); + + // Make sure it supports overlays + if (!(g_DDCaps.dwCaps & DDCAPS_OVERLAY)) + return DisplayError("Hardware doesn't support overlays"); + + //DO NOT Make sure it supports stretching (scaling) + //if (!(g_DDCaps.dwCaps & DDCAPS_OVERLAYSTRETCH)) return false; + + DDSURFACEDESC2 ddsd; // DirectDraw surface descriptor + HRESULT hRet; // I'm not even going to try... + // The pixel formats that we want the surface to be in + DDPIXELFORMAT ddpfOverlayFormats[] = { + {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 32, 0xFF0000, 0x0FF00, 0x0000FF, 0}, // 32-bit RGB + {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x007C00, 0x003e0, 0x00001F, 0}, // 16-bit RGB 5:5:5 + {sizeof(DDPIXELFORMAT), DDPF_RGB, 0, 16, 0x00F800, 0x007e0, 0x00001F, 0}, // 16-bit RGB 5:6:5 + {sizeof(DDPIXELFORMAT), DDPF_FOURCC, mmioFOURCC('U','Y','V','Y'), 16, 0, 0, 0, 0}, // UYVY + {sizeof(DDPIXELFORMAT), DDPF_FOURCC, mmioFOURCC('Y','4','2','2'), 16, 0, 0, 0, 0}, // the same as UYVY + {sizeof(DDPIXELFORMAT), DDPF_FOURCC, mmioFOURCC('Y','U','Y','2'), 16, 0, 0, 0, 0}, // YUY2 is unsupported color-space here + {0}}; + + // Setup the overlay surface's attributes in the surface descriptor + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | g_DDCaps.ddsCaps.dwCaps&DDSCAPS_VIDEOMEMORY; + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; + ddsd.dwBackBufferCount = 0; + ddsd.dwWidth = g_sizex; + ddsd.dwHeight = g_sizey; + for(int format = 0; ddpfOverlayFormats[format].dwSize; format++) { + ddsd.ddpfPixelFormat = ddpfOverlayFormats[format]; + // Attempt to create the surface with theses settings + hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSOverlay, NULL); + if(hRet == DD_OK) break; + } + if (hRet != DD_OK) + return DisplayError("Can't create appropriate overlay surface", hRet); + return true; +} + +inline void mouse(int k, LPARAM lParam) +{ + int x = (int)LOWORD(lParam), y = (int)HIWORD(lParam); + g_video->on_mouse( x*g_sizex/(g_rcDst.right - g_rcDst.left), + y*g_sizey/(g_rcDst.bottom - g_rcDst.top), k); +} + +LRESULT CALLBACK InternalWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + PAINTSTRUCT ps; // Structure for the paint message + POINT p = {0, 0}; // Translation point for the window's client region + HRESULT hRet; + + switch (iMsg) + { + case WM_MOVE: + // Make sure we're not moving to be minimized - because otherwise + // our ratio varialbes (g_dwXRatio and g_dwYRatio) will end up + // being 0, and once we hit CheckBoundries it divides by 0. + if (!IsIconic(hwnd)) + { + g_rcSrc.left = 0; + g_rcSrc.right = g_sizex; + g_rcSrc.top = 0; + g_rcSrc.bottom = g_sizey; + GetClientRect(hwnd, &g_rcDst); + g_dwXRatio = (g_rcDst.right - g_rcDst.left) * 1000 / + (g_rcSrc.right - g_rcSrc.left); + g_dwYRatio = (g_rcDst.bottom - g_rcDst.top) * 1000 / + (g_rcSrc.bottom - g_rcSrc.top); + ClientToScreen(hwnd, &p); + g_rcDst.left = p.x; + g_rcDst.top = p.y; + g_rcDst.bottom += p.y; + g_rcDst.right += p.x; + CheckBoundries(); + } + else + // Else, hide the overlay... just in case we can't do + // destination color keying, this will pull the overlay + // off of the screen for the user. + if (g_pDDSOverlay && g_pDDSPrimary) + g_pDDSOverlay->UpdateOverlay(NULL, g_pDDSPrimary, NULL, DDOVER_HIDE, NULL); + // Check to make sure our window exists before we tell it to + // repaint. This will fail the first time (while the window is being created). + if (hwnd) + { + InvalidateRect(hwnd, NULL, FALSE); + UpdateWindow(hwnd); + } + return 0L; + + case WM_SIZE: + // Another check for the minimization action. This check is + // quicker though... + if (wParam != SIZE_MINIMIZED) + { + GetClientRect(hwnd, &g_rcDst); + ClientToScreen(hwnd, &p); + g_rcDst.left = p.x; + g_rcDst.top = p.y; + g_rcDst.bottom += p.y; + g_rcDst.right += p.x; + g_rcSrc.left = 0; + g_rcSrc.right = g_sizex; + g_rcSrc.top = 0; + g_rcSrc.bottom = g_sizey; + // Here we multiply by 1000 to preserve 3 decimal places in the + // division opperation (we picked 1000 to be on the same order + // of magnitude as the stretch factor for easier comparisons) + g_dwXRatio = (g_rcDst.right - g_rcDst.left) * 1000 / + (g_rcSrc.right - g_rcSrc.left); + g_dwYRatio = (g_rcDst.bottom - g_rcDst.top) * 1000 / + (g_rcSrc.bottom - g_rcSrc.top); + CheckBoundries(); + } + return 0L; + + case WM_PAINT: + BeginPaint(hwnd, &ps); + // Check the primary surface to see if it's lost - if so you can + // pretty much bet that the other surfaces are also lost - thus + // restore EVERYTHING! If we got our surfaces stolen by a full + // screen app - then we'll destroy our primary - and won't be able + // to initialize it again. When we get our next paint message (the + // full screen app closed for example) we'll want to try to reinit + // the surfaces again - that's why there is a check for + // g_pDDSPrimary == NULL. The other option, is that our program + // went through this process, could init the primary again, but it + // couldn't init the overlay, that's why there's a third check for + // g_pDDSOverlay == NULL. Make sure that the check for + // !g_pDDSPrimary is BEFORE the IsLost call - that way if the + // pointer is NULL (ie. !g_pDDSPrimary is TRUE) - the compiler + // won't try to evaluate the IsLost function (which, since the + // g_pDDSPrimary surface is NULL, would be bad...). + if (!g_pDDSPrimary || (g_pDDSPrimary->IsLost() != DD_OK) || + (g_pDDSOverlay == NULL)) + { + DestroyOverlay(); + DestroyPrimary(); + if (DDPrimaryInit()) + if (DDOverlayInit()) + if (!DrawOverlay()) + DestroyOverlay(); + } + // UpdateOverlay is how we put the overlay on the screen. + if (g_pDDSOverlay && g_pDDSPrimary && g_video->updating) + { + hRet = g_pDDSOverlay->UpdateOverlay(&g_rcSrc, g_pDDSPrimary, + &g_rcDst, g_OverlayFlags, + &g_OverlayFX); +#ifdef _DEBUG + if(hRet != DD_OK) DisplayError("Can't update overlay", hRet); +#endif + } + EndPaint(hwnd, &ps); + return 0L; + + // process mouse and keyboard events + case WM_LBUTTONDOWN: mouse(1, lParam); break; + case WM_LBUTTONUP: mouse(-1, lParam); break; + case WM_RBUTTONDOWN: mouse(2, lParam); break; + case WM_RBUTTONUP: mouse(-2, lParam); break; + case WM_MBUTTONDOWN: mouse(3, lParam); break; + case WM_MBUTTONUP: mouse(-3, lParam); break; + case WM_CHAR: g_video->on_key(wParam); break; + + case WM_DISPLAYCHANGE: return 0L; + + case WM_DESTROY: + // Now, shut down the window... + PostQuitMessage(0); + return 0L; + } + return g_pUserProc? g_pUserProc(hwnd, iMsg, wParam, lParam) : DefWindowProc(hwnd, iMsg, wParam, lParam); +} + +DWORD WINAPI thread_vsync(LPVOID lpParameter) +{ + BOOL vblank = false; + while(g_video && g_video->running) { + while(!vblank && g_video && g_video->running) { + YIELD_TO_THREAD(); + LPDIRECTDRAW7 pDD(g_pDD); + if(pDD) pDD->GetVerticalBlankStatus(&vblank); + } + LPDIRECTDRAWSURFACE7 pDDSOverlay(g_pDDSOverlay); + if(pDDSOverlay) pDDSOverlay->UpdateOverlay(&g_rcSrc, g_pDDSPrimary, &g_rcDst, g_OverlayFlags | DDOVER_REFRESHALL, &g_OverlayFX); + do { + Sleep(1); + LPDIRECTDRAW7 pDD(g_pDD); + if(pDD) pDD->GetVerticalBlankStatus(&vblank); + } while(vblank && g_video && g_video->running); + while(g_video && !g_video->updating && g_video->running) Sleep(10); + } + return 0; +} + +///////////////////////////////////////////// public methods of video class /////////////////////// + +inline void mask2bits(unsigned int mask, color_t &save, depth_t &shift) +{ + save = mask; if(!mask) { shift = 8; return; } + shift = 0; while(!(mask&1)) ++shift, mask >>= 1; + int bits = 0; while(mask&1) ++bits, mask >>= 1; + shift += bits - 8; +} + +bool video::init_window(int sizex, int sizey) +{ + assert(win_hInstance != 0); + g_sizex = sizex; g_sizey = sizey; + if( !WinInit(win_hInstance, win_iCmdShow, gWndClass, title, false) ) + return DisplayError("Unable to initialize the program's window."); + running = true; + if( !DDInit() ) { + DestroyDDraw(); + goto fail; + } + if( !DDOverlayInit() || !DrawOverlay() ) { + DestroyOverlay(); + DestroyDDraw(); + goto fail; + } + DDPIXELFORMAT PixelFormat; memset(&PixelFormat, 0, sizeof(PixelFormat)); PixelFormat.dwSize = sizeof(PixelFormat); + g_pDDSOverlay->GetPixelFormat(&PixelFormat); + mask2bits(PixelFormat.dwRBitMask, red_mask, red_shift); + mask2bits(PixelFormat.dwGBitMask, green_mask, green_shift); + mask2bits(PixelFormat.dwBBitMask, blue_mask, blue_shift); + if(PixelFormat.dwFlags == DDPF_RGB) + depth = depth_t(PixelFormat.dwRGBBitCount); + else depth = -depth_t(PixelFormat.dwFourCC); + for(int i = 0, e = sizex * sizey * PixelFormat.dwRGBBitCount / 32, c = get_color(0, 0, 0); i < e; i++) + g_pImg[i] = c; // clear surface + ShowWindow(g_hAppWnd, SW_SHOW); + g_hVSync = CreateThread ( + NULL, // LPSECURITY_ATTRIBUTES security_attrs + 0, // SIZE_T stacksize + (LPTHREAD_START_ROUTINE) thread_vsync, + this, // argument + 0, 0); + SetPriorityClass(g_hVSync, IDLE_PRIORITY_CLASS); // questionable + return true; +fail: + g_pImg = new unsigned int[g_sizex * g_sizey]; + return false; +} + +void video::terminate() +{ + running = false; + DestroyOverlay(); + if(WaitForSingleObject(g_hVSync, 100) == WAIT_TIMEOUT) TerminateThread(g_hVSync, 0); + CloseHandle(g_hVSync); + DestroyDDraw(); + if(g_pImg) delete[] g_pImg; + g_pImg = 0; g_video = 0; +} +//////////// drawing area constructor & destructor ///////////// + +drawing_area::drawing_area(int x, int y, int sizex, int sizey) +: start_x(x), start_y(y), size_x(sizex), size_y(sizey), pixel_depth(g_video->depth), + base_index(y*g_sizex + x), max_index(g_sizex*g_sizey), index_stride(g_sizex), ptr32(g_pImg) +{ + assert(ptr32); assert(x < g_sizex); assert(y < g_sizey); + assert(x+sizex <= g_sizex); assert(y+sizey <= g_sizey); + + index = base_index; // current index +} + +void drawing_area::update() +{ +} + +#endif //_DXSDK_PRODUCT_MAJOR >= 9 diff --git a/src/tbb/examples/common/gui/dxcheck.bat b/src/tbb/examples/common/gui/dxcheck.bat new file mode 100644 index 0000000..60bd56a --- /dev/null +++ b/src/tbb/examples/common/gui/dxcheck.bat @@ -0,0 +1,36 @@ +@echo off +REM +REM Copyright 2005-2012 Intel Corporation. All Rights Reserved. +REM +REM This file is part of Threading Building Blocks. +REM +REM Threading Building Blocks is free software; you can redistribute it +REM and/or modify it under the terms of the GNU General Public License +REM version 2 as published by the Free Software Foundation. +REM +REM Threading Building Blocks is distributed in the hope that it will be +REM useful, but WITHOUT ANY WARRANTY; without even the implied warranty +REM of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +REM GNU General Public License for more details. +REM +REM You should have received a copy of the GNU General Public License +REM along with Threading Building Blocks; if not, write to the Free Software +REM Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +REM +REM As a special exception, you may use this file as part of a free software +REM library without restriction. Specifically, if other files instantiate +REM templates or use macros or inline functions from this file, or you compile +REM this file and link it with other files to produce an executable, this +REM file does not by itself cause the resulting executable to be covered by +REM the GNU General Public License. This exception does not however +REM invalidate any other reasons why the executable file might be covered by +REM the GNU General Public License. +REM +if "%DXSDK_DIR%"=="" goto error_no_DXSDK +goto end + +:error_no_DXSDK +echo DirectX SDK Check : error : This example requires the DirectX SDK. Either (re)-install the DirectX SDK, or set the DXSDK_DIR environment variable to indicate where it is installed. + +:end + diff --git a/src/tbb/examples/common/gui/gdivideo.cpp b/src/tbb/examples/common/gui/gdivideo.cpp new file mode 100644 index 0000000..3f15121 --- /dev/null +++ b/src/tbb/examples/common/gui/gdivideo.cpp @@ -0,0 +1,154 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// common Windows parts +#include "winvideo.h" +// include GDI+ headers +#include +// and another headers +#include + +// tag linking library +#pragma comment(lib, "gdiplus.lib") + +// global specific variables +Gdiplus::Bitmap * g_pBitmap; // main drawing bitmap +ULONG_PTR gdiplusToken; +Gdiplus::GdiplusStartupInput gdiplusStartupInput;// GDI+ + +//! display system error +bool DisplayError(LPSTR lpstrErr, HRESULT hres) +{ + static bool InError = false; + int retval = 0; + if (!InError) + { + InError = true; + LPCSTR lpMsgBuf; + if(!hres) hres = GetLastError(); + FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, hres, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); + retval = MessageBox(g_hAppWnd, lpstrErr, lpMsgBuf, MB_OK|MB_ICONERROR); + LocalFree( (HLOCAL)lpMsgBuf ); + InError = false; + } + return false; +} + +//! Win event processing function +LRESULT CALLBACK InternalWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + switch (iMsg) + { + case WM_MOVE: + // Check to make sure our window exists before we tell it to repaint. + // This will fail the first time (while the window is being created). + if (hwnd) { + InvalidateRect(hwnd, NULL, FALSE); + UpdateWindow(hwnd); + } + return 0L; + + case WM_PAINT: + { + PAINTSTRUCT ps; + Gdiplus::Graphics graphics( BeginPaint(hwnd, &ps) ); + // redraw just requested area. This call is as fast as simple DrawImage() call. + if(g_video->updating) graphics.DrawImage(g_pBitmap, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.left, ps.rcPaint.top, + ps.rcPaint.right, ps.rcPaint.bottom, Gdiplus::UnitPixel); + EndPaint(hwnd, &ps); + } + return 0L; + + // Proccess all mouse and keyboard events + case WM_LBUTTONDOWN: g_video->on_mouse( (int)LOWORD(lParam), (int)HIWORD(lParam), 1); break; + case WM_LBUTTONUP: g_video->on_mouse( (int)LOWORD(lParam), (int)HIWORD(lParam), -1); break; + case WM_RBUTTONDOWN: g_video->on_mouse( (int)LOWORD(lParam), (int)HIWORD(lParam), 2); break; + case WM_RBUTTONUP: g_video->on_mouse( (int)LOWORD(lParam), (int)HIWORD(lParam), -2); break; + case WM_MBUTTONDOWN: g_video->on_mouse( (int)LOWORD(lParam), (int)HIWORD(lParam), 3); break; + case WM_MBUTTONUP: g_video->on_mouse( (int)LOWORD(lParam), (int)HIWORD(lParam), -3); break; + case WM_CHAR: g_video->on_key( (int)wParam); break; + + // some useless stuff + case WM_ERASEBKGND: return 1; // keeps erase-background events from happening, reduces chop + case WM_DISPLAYCHANGE: return 0; + + // Now, shut down the window... + case WM_DESTROY: PostQuitMessage(0); return 0; + } + // call user defined proc, if exists + return g_pUserProc? g_pUserProc(hwnd, iMsg, wParam, lParam) : DefWindowProc(hwnd, iMsg, wParam, lParam); +} + +///////////// video functions //////////////// + +bool video::init_window(int sizex, int sizey) +{ + assert(win_hInstance != 0); + g_sizex = sizex; g_sizey = sizey; + if (!WinInit(win_hInstance, win_iCmdShow, gWndClass, title, true)) { + DisplayError("Unable to initialize the program's window."); + return false; + } + ShowWindow(g_hAppWnd, SW_SHOW); + Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); + g_pImg = new unsigned int[sizex*sizey]; + g_pBitmap = new Gdiplus::Bitmap(g_sizex, g_sizey, 4*g_sizex, PixelFormat32bppRGB, (BYTE*)g_pImg ); + running = true; + return true; +} + +void video::terminate() +{ + if(g_pBitmap) { delete g_pBitmap; g_pBitmap = 0; } + Gdiplus::GdiplusShutdown(gdiplusToken); + g_video = 0; running = false; + if(g_pImg) { delete[] g_pImg; g_pImg = 0; } +} + +//////////// drawing area constructor & destructor ///////////// + +drawing_area::drawing_area(int x, int y, int sizex, int sizey) +: start_x(x), start_y(y), size_x(sizex), size_y(sizey), pixel_depth(24), + base_index(y*g_sizex + x), max_index(g_sizex*g_sizey), index_stride(g_sizex), ptr32(g_pImg) +{ + assert(x < g_sizex); assert(y < g_sizey); + assert(x+sizex <= g_sizex); assert(y+sizey <= g_sizey); + + index = base_index; // current index +} + +void drawing_area::update() +{ + if(g_video->updating) { + RECT r; + r.left = start_x; r.right = start_x + size_x; + r.top = start_y; r.bottom = start_y + size_y; + InvalidateRect(g_hAppWnd, &r, false); + } +} diff --git a/src/tbb/examples/common/gui/macvideo.cpp b/src/tbb/examples/common/gui/macvideo.cpp new file mode 100644 index 0000000..58863b6 --- /dev/null +++ b/src/tbb/examples/common/gui/macvideo.cpp @@ -0,0 +1,166 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "video.h" +#include +#include +#include +#include + +unsigned int* g_pImg = 0; +int g_sizex=0, g_sizey=0; +static video *g_video = 0; +static int g_fps = 0; +char *window_title=NULL; +#define WINDOW_TITLE_SIZE 256 +int cocoa_update=0; + +#include +#include +struct timeval g_time; + +video::video() + : red_mask(0xff0000), red_shift(16), green_mask(0xff00), + green_shift(8), blue_mask(0xff), blue_shift(0), depth(24) +{ + assert(g_video == 0); + g_video = this; title = "Video"; cocoa_update=1; updating = true; calc_fps = false; +} + +bool video::init_window(int x, int y) +{ + g_sizex = x; g_sizey = y; + g_pImg = new unsigned int[x*y]; + if( window_title==NULL ) + window_title = (char*)malloc(WINDOW_TITLE_SIZE); + strncpy( window_title, title, WINDOW_TITLE_SIZE-1 ); + running = true; + return true; +} + +bool video::init_console() +{ + running = true; + return true; +} + +void video::terminate() +{ + if(calc_fps) { + double fps = g_fps; + struct timezone tz; struct timeval end_time; gettimeofday(&end_time, &tz); + fps /= (end_time.tv_sec+1.0*end_time.tv_usec/1000000.0) - (g_time.tv_sec+1.0*g_time.tv_usec/1000000.0); + printf("%s: %.1f fps\n", title, fps); + } + g_video = 0; running = false; + if(g_pImg) { delete[] g_pImg; g_pImg = 0; } +} + +video::~video() +{ + if(g_video) terminate(); +} + +//! Count and display FPS count in titlebar +bool video::next_frame() +{ + if(calc_fps){ + if(!g_fps) { + struct timezone tz; gettimeofday(&g_time, &tz); + } + g_fps++; + } + struct timezone tz; struct timeval now_time; gettimeofday(&now_time, &tz); + double sec=((now_time.tv_sec+1.0*now_time.tv_usec/1000000.0) - (g_time.tv_sec+1.0*g_time.tv_usec/1000000.0)); + if( sec>1 ){ + if(calc_fps) { + memcpy(&g_time, &now_time, sizeof(g_time)); + int fps; + fps = g_fps/sec; + cocoa_update = (int)updating; + snprintf(window_title,WINDOW_TITLE_SIZE, "%s%s: %d fps", title, updating?"":" (no updating)", int(fps)); + g_fps=0; + } + } + return running; +} + + +void* thread_func(void*) +{ + g_video->on_process(); + exit(EXIT_SUCCESS); +} + +extern "C" void on_mouse_func(int x, int y, int k) +{ + g_video->on_mouse(x, y, k); + return; +} + +extern "C" void on_key_func(int x) +{ + g_video->on_key(x); + return; +} + +extern "C" int cocoa_main( int argc, char *argv[] ); +//! Do standard loop +void video::main_loop() +{ + pthread_t handle; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_create(&handle,&attr,&thread_func,(void*)NULL); + pthread_detach(handle); + cocoa_main( NULL, NULL ); +} + +//! Change window title +void video::show_title() +{ + strncpy( window_title, title, WINDOW_TITLE_SIZE ); + return; +} + +///////////////////////////////////////////// public methods of video class /////////////////////// + +drawing_area::drawing_area(int x, int y, int sizex, int sizey) + : start_x(x), start_y(y), size_x(sizex), size_y(sizey), pixel_depth(24), + base_index(y*g_sizex + x), max_index(g_sizex*g_sizey), index_stride(g_sizex), ptr32(g_pImg) +{ + assert(x < g_sizex); assert(y < g_sizey); + assert(x+sizex <= g_sizex); assert(y+sizey <= g_sizey); + + index = base_index; // current index +} + +void drawing_area::update() +{ + //nothing to do, updating via timer in cocoa part. +} diff --git a/src/tbb/examples/common/gui/video.h b/src/tbb/examples/common/gui/video.h new file mode 100644 index 0000000..4c8ef90 --- /dev/null +++ b/src/tbb/examples/common/gui/video.h @@ -0,0 +1,244 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __VIDEO_H__ +#define __VIDEO_H__ + +#include +#if _MSC_VER +#include // for uintptr_t +#else +#include // for uintptr_t +#endif +#if _WIN32 || _WIN64 +#include +#else +#include +#endif + +typedef unsigned int color_t; +typedef unsigned char colorcomp_t; +typedef signed char depth_t; + +//! Class for getting access to drawing memory +class drawing_memory +{ +#ifdef __TBB_MIC + // The address is kept as uintptr_t since + // the compiler could not offload a pointer +#endif + uintptr_t my_address; +public: + depth_t pixel_depth; + int sizex, sizey; + //! Get drawing memory + inline char* get_address() const { return reinterpret_cast(my_address); } + //! Get drawing memory size + inline int get_size() const { return ((pixel_depth>16) ? 4:2) * sizex * sizey; } + //! Set drawing memory + inline void set_address(char *mem) { my_address = reinterpret_cast(mem); } + + friend class drawing_area; + friend class video; +}; + +//! Simple proxy class for managing of different video systems +class video +{ + //! colorspace information + depth_t depth, red_shift, green_shift, blue_shift; + color_t red_mask, green_mask, blue_mask; + friend class drawing_area; + +public: + //! Constructor + video(); + //! Destructor + ~video(); + //! member to set window name + const char *title; + //! true is enable to show fps + bool calc_fps; + //! if true: on windows fork processing thread for on_process(), on non-windows note that next_frame() is called concurrently. + bool threaded; + //! true while running within main_loop() + bool running; + //! if true, do gui updating + bool updating; + //! initialize graphical video system + bool init_window(int sizex, int sizey); + //! initialize console. returns true if console is available + bool init_console(); + //! terminate video system + void terminate(); + //! Do standard event & processing loop. Use threaded = true to separate event/updating loop from frame processing + void main_loop(); + //! Process next frame + bool next_frame(); + //! Change window title + void show_title(); + //! translate RGB components into packed type + inline color_t get_color(colorcomp_t red, colorcomp_t green, colorcomp_t blue) const; + //! Get drawing memory descriptor + inline drawing_memory get_drawing_memory() const; + + //! code of the ESCape key + static const int esc_key = 27; + //! Mouse events handler. + virtual void on_mouse(int x, int y, int key) { } + //! Mouse events handler. + virtual void on_key(int key) { } + //! Main processing loop. Redefine with your own + virtual void on_process() { while(next_frame()); } + +#ifdef _WINDOWS + //! Windows specific members + //! if VIDEO_WINMAIN isn't defined then set this just before init() by arguments of WinMain + static HINSTANCE win_hInstance; static int win_iCmdShow; + //! optionally call it just before init() to set own. Use ascii strings convention + void win_set_class(WNDCLASSEX &); + //! load and set accelerator table from resources + void win_load_accelerators(int idc); +#endif +}; + +//! Drawing class +class drawing_area +{ + const size_t base_index, max_index, index_stride; + const depth_t pixel_depth; + unsigned int * const ptr32; + size_t index; +public: + const int start_x, start_y, size_x, size_y; + //! constructors + drawing_area(int x, int y, int sizex, int sizey); + inline drawing_area(int x, int y, int sizex, int sizey, const drawing_memory &dmem); + //! destructor + inline ~drawing_area(); + //! update the image + void update(); + //! set current position. local_x could be bigger then size_x + inline void set_pos(int local_x, int local_y); + //! put pixel in current position with incremental address calculating to next right pixel + inline void put_pixel(color_t color); + //! draw pixel at position by packed color + void set_pixel(int localx, int localy, color_t color) + { set_pos(localx, localy); put_pixel(color); } +}; + +extern int g_sizex; +extern int g_sizey; +extern unsigned int *g_pImg; + +inline drawing_memory video::get_drawing_memory() const +{ + drawing_memory dmem; + dmem.pixel_depth = depth; + dmem.my_address = reinterpret_cast(g_pImg); + dmem.sizex = g_sizex; + dmem.sizey = g_sizey; + return dmem; +} + +inline color_t video::get_color(colorcomp_t red, colorcomp_t green, colorcomp_t blue) const +{ + if(red_shift == 16) // only for depth == 24 && red_shift > blue_shift + return (red<<16) | (green<<8) | blue; + else if(depth >= 24) + return (red< 0) { + register depth_t bs = blue_shift, rs = red_shift; + if(blue_shift < 0) blue >>= -bs, bs = 0; + else /*red_shift < 0*/ red >>= -rs, rs = 0; + return (red<2^16 + u = (2048 + (blue << 3) - (y >> 5)) >> 4; // (limit->2^12)>>4 + v = (2048 + (red << 3) - (y >> 5)) >> 4; + y = y >> 8; + return u | (y << 8) | (v << 16) | (y << 24); + } +} + +inline drawing_area::drawing_area(int x, int y, int sizex, int sizey, const drawing_memory &dmem) + : start_x(x), start_y(y), size_x(sizex), size_y(sizey), pixel_depth(dmem.pixel_depth), + base_index(y*dmem.sizex + x), max_index(dmem.sizex*dmem.sizey), index_stride(dmem.sizex), + ptr32(reinterpret_cast(dmem.my_address)) +{ + assert(x < dmem.sizex); assert(y < dmem.sizey); + assert(x+sizex <= dmem.sizex); assert(y+sizey <= dmem.sizey); + + index = base_index; // current index +} + +inline void drawing_area::set_pos(int local_x, int local_y) +{ + index = base_index + local_x + local_y*index_stride; +} + +inline void drawing_area::put_pixel(color_t color) +{ + assert(index < max_index); + if(pixel_depth > 16) ptr32[index++] = color; + else if(pixel_depth > 0) + ((unsigned short*)ptr32)[index++] = (unsigned short)color; + else { // UYVY colorspace + if(index&1) color >>= 16; + ((unsigned short*)ptr32)[index++] = (unsigned short)color; + } +} + +inline drawing_area::~drawing_area() +{ +#if ! __TBB_DEFINE_MIC + update(); +#endif +} + +#if defined(_WINDOWS) && (defined(VIDEO_WINMAIN) || defined(VIDEO_WINMAIN_ARGS) ) +#include +//! define WinMain for subsystem:windows. +#ifdef VIDEO_WINMAIN_ARGS +int main(int, char *[]); +#else +int main(); +#endif +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR szCmdLine, int iCmdShow) +{ + video::win_hInstance = hInstance; video::win_iCmdShow = iCmdShow; +#ifdef VIDEO_WINMAIN_ARGS + return main(__argc, __argv); +#else + return main(); +#endif +} +#endif + +#endif// __VIDEO_H__ diff --git a/src/tbb/examples/common/gui/winvideo.h b/src/tbb/examples/common/gui/winvideo.h new file mode 100644 index 0000000..00b6152 --- /dev/null +++ b/src/tbb/examples/common/gui/winvideo.h @@ -0,0 +1,291 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/////// Common internal implementation of Windows-specific stuff ////////////// +/////// Must be the first included header ////////////// + +#ifndef __WINVIDEO_H__ +#define __WINVIDEO_H__ + +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE +#endif +// Check that the target Windows version has all API calls requried. +#ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0400 +#endif +#if _WIN32_WINNT<0x0400 +# define YIELD_TO_THREAD() Sleep(0) +#else +# define YIELD_TO_THREAD() SwitchToThread() +#endif +#include "video.h" +#include +#include +#include +#include + +#pragma comment(lib, "gdi32.lib") +#pragma comment(lib, "user32.lib") + +// maximum mumber of lines the output console should have +static const WORD MAX_CONSOLE_LINES = 500; +const COLORREF RGBKEY = RGB(8, 8, 16); // at least 8 for 16-bit palette +HWND g_hAppWnd; // The program's window handle +HANDLE g_handles[2] = {0,0};// thread and wake up event +unsigned int * g_pImg = 0; // drawing memory +int g_sizex, g_sizey; +static video * g_video = 0; +WNDPROC g_pUserProc = 0; +HINSTANCE video::win_hInstance = 0; +int video::win_iCmdShow = 0; +static WNDCLASSEX * gWndClass = 0; +static HACCEL hAccelTable = 0; +static DWORD g_msec = 0; +static int g_fps = 0, g_updates = 0, g_skips = 0; + +bool DisplayError(LPSTR lpstrErr, HRESULT hres = 0); // always returns false +LRESULT CALLBACK InternalWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam); + +//! Create window +bool WinInit(HINSTANCE hInstance, int nCmdShow, WNDCLASSEX *uwc, const char *title, bool fixedsize) +{ + WNDCLASSEX wndclass; // Our app's windows class + if(uwc) { + memcpy(&wndclass, uwc, sizeof(wndclass)); + g_pUserProc = uwc->lpfnWndProc; + } else { + memset(&wndclass, 0, sizeof(wndclass)); + wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndclass.lpszClassName = title; + } + wndclass.cbSize = sizeof(wndclass); + wndclass.hInstance = hInstance; + wndclass.lpfnWndProc = InternalWndProc; + wndclass.style |= CS_HREDRAW | CS_VREDRAW; + wndclass.hbrBackground = CreateSolidBrush(RGBKEY); + + if( !RegisterClassExA(&wndclass) ) return false; + int xaddend = GetSystemMetrics(fixedsize?SM_CXFIXEDFRAME:SM_CXFRAME)*2; + int yaddend = GetSystemMetrics(fixedsize?SM_CYFIXEDFRAME:SM_CYFRAME)*2 + GetSystemMetrics(SM_CYCAPTION); + if(wndclass.lpszMenuName) yaddend += GetSystemMetrics(SM_CYMENU); + + // Setup the new window's physical parameters - and tell Windows to create it + g_hAppWnd = CreateWindowA(wndclass.lpszClassName, // Window class name + title, // Window caption + !fixedsize ? WS_OVERLAPPEDWINDOW : // Window style + WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX, + CW_USEDEFAULT, // Initial x pos: use default placement + 0, // Initial y pos: not used here + g_sizex+xaddend,// Initial x size + g_sizey+yaddend,// Initial y size + NULL, // parent window handle + NULL, // window menu handle + hInstance, // program instance handle + NULL); // Creation parameters + return g_hAppWnd != NULL; +} + +//! create console window with redirection +static bool RedirectIOToConsole(void) +{ + int hConHandle; size_t lStdHandle; + CONSOLE_SCREEN_BUFFER_INFO coninfo; + FILE *fp; + // allocate a console for this app + AllocConsole(); + + // set the screen buffer to be big enough to let us scroll text + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo); + coninfo.dwSize.Y = MAX_CONSOLE_LINES; + SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize); + + // redirect unbuffered STDOUT to the console + lStdHandle = (size_t)GetStdHandle(STD_OUTPUT_HANDLE); + hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); + if(hConHandle <= 0) return false; + fp = _fdopen( hConHandle, "w" ); + *stdout = *fp; + setvbuf( stdout, NULL, _IONBF, 0 ); + + // redirect unbuffered STDERR to the console + lStdHandle = (size_t)GetStdHandle(STD_ERROR_HANDLE); + hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); + if(hConHandle > 0) { + fp = _fdopen( hConHandle, "w" ); + *stderr = *fp; + setvbuf( stderr, NULL, _IONBF, 0 ); + } + + // redirect unbuffered STDIN to the console + lStdHandle = (size_t)GetStdHandle(STD_INPUT_HANDLE); + hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); + if(hConHandle > 0) { + fp = _fdopen( hConHandle, "r" ); + *stdin = *fp; + setvbuf( stdin, NULL, _IONBF, 0 ); + } + + // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog + // point to console as well + std::ios::sync_with_stdio(); + return true; +} + + +video::video() + : red_mask(0xff0000), red_shift(16), green_mask(0xff00), + green_shift(8), blue_mask(0xff), blue_shift(0), depth(24) +{ + assert(g_video == 0); + g_video = this; title = "Video"; running = threaded = calc_fps = false; updating = true; +} + +//! optionally call it just before init() to set own +void video::win_set_class(WNDCLASSEX &wcex) +{ + gWndClass = &wcex; +} + +void video::win_load_accelerators(int idc) +{ + hAccelTable = LoadAccelerators(win_hInstance, MAKEINTRESOURCE(idc)); +} + +bool video::init_console() +{ + if(RedirectIOToConsole()) { + if(!g_pImg && g_sizex && g_sizey) + g_pImg = new unsigned int[g_sizex * g_sizey]; + if(g_pImg) running = true; + return true; + } + return false; +} + +video::~video() +{ + if(g_video) terminate(); +} + +DWORD WINAPI thread_video(LPVOID lpParameter) +{ + video *v = (video*)lpParameter; + v->on_process(); + return 0; +} + +static bool loop_once(video *v) +{ + // screen update notify + if(int updates = g_updates) { + g_updates = 0; + if(g_video->updating) { g_skips += updates-1; g_fps++; } + else g_skips += updates; + UpdateWindow(g_hAppWnd); + } + // update fps + DWORD msec = GetTickCount(); + if(v->calc_fps && msec >= g_msec+1000) { + double sec = (msec - g_msec)/1000.0; + char buffer[256], n = _snprintf(buffer, 128, "%s: %d fps", v->title, int(double(g_fps + g_skips)/sec)); + if(g_skips) _snprintf(buffer+n, 128, " - %d skipped = %d updates", int(g_skips/sec), int(g_fps/sec)); + SetWindowTextA(g_hAppWnd, buffer); + g_msec = msec; g_skips = g_fps = 0; + } + // event processing, including painting + MSG msg; + if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){ + if( msg.message == WM_QUIT ) { v->running = false; return false; } + if( !hAccelTable || !TranslateAccelerator(msg.hwnd, hAccelTable, &msg) ){ + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return true; // try again + } + return false; +} + +//! Do standard event loop +void video::main_loop() +{ + // let Windows draw and unroll the window + InvalidateRect(g_hAppWnd, 0, false); + g_msec = GetTickCount(); // let's stay for 0,5 sec + while(g_msec + 500 > GetTickCount()) { loop_once(this); Sleep(1); } + g_msec = GetTickCount(); + // now, start main process + if(threaded) { + g_handles[0] = CreateThread ( + NULL, // LPSECURITY_ATTRIBUTES security_attrs + 0, // SIZE_T stacksize + (LPTHREAD_START_ROUTINE) thread_video, + this, // argument + 0, 0); + if(!g_handles[0]) { DisplayError("Can't create thread"); return; } + else // harmless race is possible here + g_handles[1] = CreateEvent(NULL, false, false, NULL); + while(running) { + while(loop_once(this)); + YIELD_TO_THREAD(); // give time for processing when running on single CPU + DWORD r = MsgWaitForMultipleObjects(2, g_handles, false, INFINITE, QS_ALLINPUT^QS_MOUSEMOVE); + if(r == WAIT_OBJECT_0) break; // thread terminated + } + running = false; + if(WaitForSingleObject(g_handles[0], 3000) == WAIT_TIMEOUT){ + // there was not enough time for graceful shutdown, killing the example with code 1. + exit(1); + } + if(g_handles[0]) CloseHandle(g_handles[0]); + if(g_handles[1]) CloseHandle(g_handles[1]); + g_handles[0] = g_handles[1] = 0; + } + else on_process(); +} + +//! Refresh screen picture +bool video::next_frame() +{ + if(!running) return false; + g_updates++; // Fast but inaccurate counter. The data race here is benign. + if(!threaded) while(loop_once(this)); + else if(g_handles[1]) { + SetEvent(g_handles[1]); + YIELD_TO_THREAD(); + } + return true; +} + +//! Change window title +void video::show_title() +{ + if(g_hAppWnd) + SetWindowTextA(g_hAppWnd, title); +} + +#endif //__WINVIDEO_H__ diff --git a/src/tbb/examples/common/gui/xcode/tbbExample/Info.plist b/src/tbb/examples/common/gui/xcode/tbbExample/Info.plist new file mode 100644 index 0000000..b94b968 --- /dev/null +++ b/src/tbb/examples/common/gui/xcode/tbbExample/Info.plist @@ -0,0 +1,59 @@ + + + + + BuildMachineOSBuild + 11D50d + CFBundleDevelopmentRegion + en + CFBundleDisplayName + + CFBundleExecutable + tbbExample + CFBundleIdentifier + Intel.tbbExample + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + tbbExample + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 4E1019 + DTPlatformVersion + GM + DTSDKBuild + 11D50a + DTSDKName + macosx10.7 + DTXcode + 0431 + DTXcodeBuild + 4E1019 + LSApplicationCategoryType + public.app-category.business + LSEnvironment + + DYLD_LIBRARY_PATH + Contents/Resources:.:../Resources:/tmp:$DYLD_LIBRARY_PATH + LIBRARY_PATH + Contents/Resources:.:../:/tmp:$DYLD_LIBRARY_PATH + + LSMinimumSystemVersion + 10.7 + NSHumanReadableCopyright + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/src/tbb/examples/common/gui/xcode/tbbExample/OpenGLView.h b/src/tbb/examples/common/gui/xcode/tbbExample/OpenGLView.h new file mode 100644 index 0000000..61f3616 --- /dev/null +++ b/src/tbb/examples/common/gui/xcode/tbbExample/OpenGLView.h @@ -0,0 +1,35 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + The source code contained or described herein and all documents related + to the source code ("Material") are owned by Intel Corporation or its + suppliers or licensors. Title to the Material remains with Intel + Corporation or its suppliers and licensors. The Material is protected + by worldwide copyright laws and treaty provisions. No part of the + Material may be used, copied, reproduced, modified, published, uploaded, + posted, transmitted, distributed, or disclosed in any way without + Intel's prior express written permission. + + No license under any patent, copyright, trade secret or other + intellectual property right is granted to or conferred upon you by + disclosure or delivery of the Materials, either expressly, by + implication, inducement, estoppel or otherwise. Any license under such + intellectual property rights must be express and approved by Intel in + writing. + */ + +#import +#import + +@interface OpenGLView : NSOpenGLView +{} + +@property (nonatomic,retain) NSTimer *timer; + +- (void) drawRect:(NSRect)start; +- (void) mouseDown:(NSEvent *)theEvent; +- (void) keyDown:(NSEvent *)theEvent; +- (BOOL) acceptsFirstResponder; +- (void) viewDidEndLiveResize; + +@end diff --git a/src/tbb/examples/common/gui/xcode/tbbExample/OpenGLView.m b/src/tbb/examples/common/gui/xcode/tbbExample/OpenGLView.m new file mode 100644 index 0000000..9c0c410 --- /dev/null +++ b/src/tbb/examples/common/gui/xcode/tbbExample/OpenGLView.m @@ -0,0 +1,106 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + The source code contained or described herein and all documents related + to the source code ("Material") are owned by Intel Corporation or its + suppliers or licensors. Title to the Material remains with Intel + Corporation or its suppliers and licensors. The Material is protected + by worldwide copyright laws and treaty provisions. No part of the + Material may be used, copied, reproduced, modified, published, uploaded, + posted, transmitted, distributed, or disclosed in any way without + Intel's prior express written permission. + + No license under any patent, copyright, trade secret or other + intellectual property right is granted to or conferred upon you by + disclosure or delivery of the Materials, either expressly, by + implication, inducement, estoppel or otherwise. Any license under such + intellectual property rights must be express and approved by Intel in + writing. + */ + +#import "OpenGLView.h" +#import +#import "tbbAppDelegate.h" + +int x,y; +void on_mouse_func(int x, int y, int k); +void on_key_func(int x); +void* windows_ptr=0; + +//defined in cpp-file +extern char* window_title; +extern int cocoa_update; +extern int g_sizex, g_sizey; +extern unsigned int *g_pImg; + +void draw(void) +{ + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + glBegin(GL_POINT); + glDrawPixels(g_sizex, g_sizey, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, g_pImg); + glEnd(); + glFlush(); +} + +@implementation OpenGLView + +@synthesize timer; + +- (void) drawRect:(NSRect)start +{ + x=g_sizex; + y=g_sizey; + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + draw(); + glFlush(); + timer = [NSTimer scheduledTimerWithTimeInterval:0.03 target:self selector:@selector(update_window) userInfo:nil repeats:YES]; +} + +-(void) update_window{ + if( cocoa_update ) draw(); + if( window_title )[_window setTitle:[NSString stringWithFormat:@"%s", window_title]]; + return; +} + +-(void) keyDown:(NSEvent *)theEvent{ + on_key_func([theEvent.characters characterAtIndex:0]); + return; +} + +-(void) mouseDown:(NSEvent *)theEvent{ + // mouse event for seismic and fractal + NSPoint point= theEvent.locationInWindow; + x = point.x; + y = point.y; + NSRect rect = self.visibleRect; + on_mouse_func(x*g_sizex/rect.size.width,y*g_sizey/rect.size.height,1); + draw(); + return; + +} + +- (BOOL) acceptsFirstResponder +{ + return YES; +} + +- (void) rightMouseDown:(NSEvent *)theEvent +{ + return; +} + +-(void) viewDidEndLiveResize +{ + NSRect rect = self.visibleRect; + x=rect.size.width; + y=rect.size.height; + glPixelZoom((float)x/(float)g_sizex, (float)y/(float)g_sizey); + [_window setTitle:[NSString stringWithFormat:@"X=%d Y=%d", x,y]]; + draw(); + return; +} + +@end diff --git a/src/tbb/examples/common/gui/xcode/tbbExample/PkgInfo b/src/tbb/examples/common/gui/xcode/tbbExample/PkgInfo new file mode 100644 index 0000000..bd04210 --- /dev/null +++ b/src/tbb/examples/common/gui/xcode/tbbExample/PkgInfo @@ -0,0 +1 @@ +APPL???? \ No newline at end of file diff --git a/src/tbb/examples/common/gui/xcode/tbbExample/en.lproj/InfoPlist.strings b/src/tbb/examples/common/gui/xcode/tbbExample/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/src/tbb/examples/common/gui/xcode/tbbExample/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/src/tbb/examples/common/gui/xcode/tbbExample/en.lproj/MainMenu.nib b/src/tbb/examples/common/gui/xcode/tbbExample/en.lproj/MainMenu.nib new file mode 100644 index 0000000000000000000000000000000000000000..bbcd0057ed0aaf2c2790d9f47cf0c2bbd6ac98a6 GIT binary patch literal 3312 zcmZWr32;@_8UD`Q&jaMWAcQRokN{y#*klVK3ri#m@<>QR;Cb_M4HsVSi*F&sO!VNs zqODcjYB4xg+}mkgTCGxCM`~L{MXA(ws#dI3>xgCS4E^uD?*St(Gr7z8&%b=%_y6a1 z^u+9Bsi% zWUvuB3>07ziZBhcQHu+)26br1CTvCo7sEs+EL;K`-AJMzm*WZuT#XxWBW}gd@DP5E zhw(U`z?1kTp2joy4PLva@j7J{wBEeuoxYK#tKKvb#;FyMRWi)CfDUuztQ+*lpc!I2Rf3W68 za=o6r>r4(p6|;mSmWc*YE=G!_qE6I{`a@K6AtqqrMoP%dvBB)Ngd${0u(F5fkD6|V zhfs{kn1ZQoekBfBwfMJIax-mBCsXlmAB91(D{0Br;|7?H8JJ1M&&p^;oc{o33GG9a zq6~8|7xOS53&`*SEW{!##u6+=IhLUU%Tb9cRHFtfu#(=aCR}~k*AaG$H<*+v<%3&(FH4O|G-3 zkc3I(l1(_8uq?+7%U(}dk+J7(;(RD8t|z}4~Y zo`kE`xU)84#}lMjul&{NF51zReJ6rqNGL=dE{2JrVz@Z3t+B^)R@J$fQRldqwlifn z_m|BmTr}Wa$_9K9b|C5s&edwT*X-%B5`*YKNhCO`zn{?Za4VbR0!JXu85oEJ3tddl z`gtp7J!c$uVT;$?8AVxywVAR8(S;H}@>XmkQPihXt~|n4YA?1ThLR={ik0$p?jSB^ z?nMtSMM8`c<3!$JA}NJ5wxbt2(1%eQ8p3sEhZQ5))R5Q+O}D{_rf@u+h+1N-7$b6p zlx@rbYR1ukYIs>o?(M+=5+VhL|o&ME()nh9BX_RMGAD3GTq1*p0hzH}1i` zxDP+Y{T|~qh*n&hwzt>EJ6*vOtM!(XrhaL3YP-!Yiv~f~gfOUgtnRpDN9*EI7hHRX z)#+IgOkPvx&^U%D5EI2zF(K!QQ>RXe$)fNu_D~iNPzHn8iw99oN_C^S4ew51Z;H(q z7l;MIAmLw>wo`>?I_RQH-=^LBXz)FPNAVcJLp|Z4@9irVMPd@g_ww-C#&uo2#fon0 zHWS-?(4WFDJhk|fFS~ybPodgYjw6(I{v>mrT-=%}2V&(%lDCT^CV?dc9Q@0TwM*o;M|>D9KN0sV`wCxYlsQQE zB^$}&>`dJ=@mnHbF%htmCS$$nkaQD1e6QlagDzTGl)iUS8byCTPNN7XdZNQt%HSjs zPV|(qXS!JOI9Z&7Yi4dp=i=+nlI;Fm+RsL_F>EXw$Hucfmd^@UA)CM^vPrB+REXuG zQdEg*Q6pA}m131xEo#MuVogXIACmGyQhrD(2uXz@X+lVv7?LK1q@s{i9Fiu7q$we3 zY6d+vPt4qt4S9iBLiYq5Tf`QVc518q!@kB$nS*SRJAdgDhWgs-tjv4|{+X4tWt(cN zGN*ngSqes9gJUp}$eB;ad<8zjCu{_Lqs^m_%GIoqwXrSiGIl3>iXCKcu|Kgx>@a(m z9bq4^zp!KMBldUpIs1;CWZz3%%8~M<$jz}L% z|C6~qPA-<`$`x{0Zjv|1t@1{Ble}5JSniNJWn11Rcgu14M)?l;e))iWP(G$W8LCWF zmMQC$^-8nSs%%s?DG|j~qKc!W6`@?G>{50s4=Il-FDsuaU#YTcs3A39Emo(i^V9`u zxmuxCs@3XxwO!q+Ce^gstM;k=>ecGC>h)anzV~GN9)(F(yrHT)Na;xX}4*2XuGw$wMVq4wHLG(wf))w?G^1k z?S1VN?OW|T?WFd-F6$%pe7#IxpjYcF^i_JT-mY7EkDk^q*M)wiew%);{-FN6en3B@ zAJvcRU+X6g$xw`3V~jD*$TJFz3C1L&*qCCJ7>kXi#xi5MQDxK_O~wYJ&1g5SF?Jbu z8TT0X8TT7|j6vf;<00c=W1sP?vEMjgylT8|yki_QJ~oaUCyY~^ahZqsSYE)V@@c%B zSMW++%~$YMyq2%w^}La{@HU?2y}Xb2^8tPZ-^s7y*YNB34g4m43%`}$#qZ(2=Fjlw z_;2|O{6)T>AK*Z3R!P5uY|M}COE!;kQz{22cm{|En+ALn22ulP6o1V0sE0Vyyf hFf4FhAU7~MFg;Kns0yrw_md?5$}0S8_J3gA{{ii7$-e*q literal 0 HcmV?d00001 diff --git a/src/tbb/examples/common/gui/xcode/tbbExample/en.lproj/MainMenu.xib b/src/tbb/examples/common/gui/xcode/tbbExample/en.lproj/MainMenu.xib new file mode 100644 index 0000000..14faab3 --- /dev/null +++ b/src/tbb/examples/common/gui/xcode/tbbExample/en.lproj/MainMenu.xib @@ -0,0 +1,291 @@ + + + + 1070 + 11D50d + 2182 + 1138.32 + 568.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 2182 + + + NSWindowTemplate + NSView + NSMenu + NSMenuItem + NSCustomObject + + + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + + + tbbExample + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + tbbExample + + + + Quit tbbExample + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + _NSMainMenu + + + 15 + 2 + {{100, 100}, {480, 360}} + 1148718080 + tbbExample + NSWindow + + + + + 4352 + {480, 360} + + + 2 + {1, 9} + {1, 1} + + {{0, 0}, {1280, 1002}} + {10000000000000, 10000000000000} + YES + + + tbbAppDelegate + + + NSFontManager + + + + + + + terminate: + + + + 449 + + + + delegate + + + + 495 + + + + window + + + + 532 + + + + + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + + + + + + 56 + + + + + + + + 57 + + + + + + + + 136 + + + + + 371 + + + + + + + + 372 + + + + + 420 + + + + + 494 + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + com.apple.InterfaceBuilder.CocoaPlugin + {{380, 496}, {480, 360}} + + OpenGLView + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + 539 + + + + + OpenGLView + NSOpenGLView + + IBProjectSource + ./Classes/OpenGLView.h + + + + tbbAppDelegate + NSObject + + saveAction: + id + + + saveAction: + + saveAction: + id + + + + window + NSWindow + + + window + + window + NSWindow + + + + IBProjectSource + ./Classes/tbbAppDelegate.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + YES + 3 + + {11, 11} + {10, 3} + + + diff --git a/src/tbb/examples/common/gui/xcode/tbbExample/main.m b/src/tbb/examples/common/gui/xcode/tbbExample/main.m new file mode 100644 index 0000000..82436a4 --- /dev/null +++ b/src/tbb/examples/common/gui/xcode/tbbExample/main.m @@ -0,0 +1,27 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + The source code contained or described herein and all documents related + to the source code ("Material") are owned by Intel Corporation or its + suppliers or licensors. Title to the Material remains with Intel + Corporation or its suppliers and licensors. The Material is protected + by worldwide copyright laws and treaty provisions. No part of the + Material may be used, copied, reproduced, modified, published, uploaded, + posted, transmitted, distributed, or disclosed in any way without + Intel's prior express written permission. + + No license under any patent, copyright, trade secret or other + intellectual property right is granted to or conferred upon you by + disclosure or delivery of the Materials, either expressly, by + implication, inducement, estoppel or otherwise. Any license under such + intellectual property rights must be express and approved by Intel in + writing. + */ + + +#import + +int cocoa_main(int argc, char *argv[]) +{ + return NSApplicationMain(argc, (const char **)argv); +} diff --git a/src/tbb/examples/common/gui/xcode/tbbExample/tbbAppDelegate.h b/src/tbb/examples/common/gui/xcode/tbbExample/tbbAppDelegate.h new file mode 100644 index 0000000..3470b5a --- /dev/null +++ b/src/tbb/examples/common/gui/xcode/tbbExample/tbbAppDelegate.h @@ -0,0 +1,33 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + The source code contained or described herein and all documents related + to the source code ("Material") are owned by Intel Corporation or its + suppliers or licensors. Title to the Material remains with Intel + Corporation or its suppliers and licensors. The Material is protected + by worldwide copyright laws and treaty provisions. No part of the + Material may be used, copied, reproduced, modified, published, uploaded, + posted, transmitted, distributed, or disclosed in any way without + Intel's prior express written permission. + + No license under any patent, copyright, trade secret or other + intellectual property right is granted to or conferred upon you by + disclosure or delivery of the Materials, either expressly, by + implication, inducement, estoppel or otherwise. Any license under such + intellectual property rights must be express and approved by Intel in + writing. + */ + +// +// Created by Xcode* 4.3.2 +// + +#import + +@interface tbbAppDelegate : NSObject + +@property (assign) IBOutlet NSWindow *window; + +- (BOOL) applicationShouldTerminateAfterLastWindowClosed:(NSApplication *) sender; + +@end diff --git a/src/tbb/examples/common/gui/xcode/tbbExample/tbbAppDelegate.m b/src/tbb/examples/common/gui/xcode/tbbExample/tbbAppDelegate.m new file mode 100644 index 0000000..f39dff6 --- /dev/null +++ b/src/tbb/examples/common/gui/xcode/tbbExample/tbbAppDelegate.m @@ -0,0 +1,51 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + The source code contained or described herein and all documents related + to the source code ("Material") are owned by Intel Corporation or its + suppliers or licensors. Title to the Material remains with Intel + Corporation or its suppliers and licensors. The Material is protected + by worldwide copyright laws and treaty provisions. No part of the + Material may be used, copied, reproduced, modified, published, uploaded, + posted, transmitted, distributed, or disclosed in any way without + Intel's prior express written permission. + + No license under any patent, copyright, trade secret or other + intellectual property right is granted to or conferred upon you by + disclosure or delivery of the Materials, either expressly, by + implication, inducement, estoppel or otherwise. Any license under such + intellectual property rights must be express and approved by Intel in + writing. + */ + +// +// Created by Xcode* 4.3.2 +// + +#import "tbbAppDelegate.h" +#import + +@implementation tbbAppDelegate + +@synthesize window = _window; + +//declared in macvideo.cpp file +extern int g_sizex, g_sizey; + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification +{ + // Insert code here to initialize your application + NSRect windowSize; + windowSize.size.height = g_sizey; + windowSize.size.width = g_sizex; + windowSize.origin=_window.frame.origin; + [_window setFrame:windowSize display:YES]; + +} + +- (BOOL) applicationShouldTerminateAfterLastWindowClosed:(NSApplication *) sender +{ + return YES; +} + +@end diff --git a/src/tbb/examples/common/gui/xcode/tbbExample/tbbExample-Info.plist b/src/tbb/examples/common/gui/xcode/tbbExample/tbbExample-Info.plist new file mode 100644 index 0000000..9a0148a --- /dev/null +++ b/src/tbb/examples/common/gui/xcode/tbbExample/tbbExample-Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + Intel.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + LSEnvironment + + DYLD_LIBRARY_PATH + Contents/Resources:.:../Resources:/tmp:$DYLD_LIBRARY_PATH + LIBRARY_PATH + Contents/Resources:.:../:/tmp:$DYLD_LIBRARY_PATH + + CFBundleDisplayName + + CFBundleVersion + 1 + LSApplicationCategoryType + public.app-category.business + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + NSHumanReadableCopyright + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/src/tbb/examples/common/gui/xcode/tbbExample/tbbExample-Prefix.pch b/src/tbb/examples/common/gui/xcode/tbbExample/tbbExample-Prefix.pch new file mode 100644 index 0000000..a5f51a8 --- /dev/null +++ b/src/tbb/examples/common/gui/xcode/tbbExample/tbbExample-Prefix.pch @@ -0,0 +1,27 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + The source code contained or described herein and all documents related + to the source code ("Material") are owned by Intel Corporation or its + suppliers or licensors. Title to the Material remains with Intel + Corporation or its suppliers and licensors. The Material is protected + by worldwide copyright laws and treaty provisions. No part of the + Material may be used, copied, reproduced, modified, published, uploaded, + posted, transmitted, distributed, or disclosed in any way without + Intel's prior express written permission. + + No license under any patent, copyright, trade secret or other + intellectual property right is granted to or conferred upon you by + disclosure or delivery of the Materials, either expressly, by + implication, inducement, estoppel or otherwise. Any license under such + intellectual property rights must be express and approved by Intel in + writing. + */ + +// +// Prefix header for all source files of the 'tbbExample' target in the 'tbbExample' project +// + +#ifdef __OBJC__ + #import +#endif diff --git a/src/tbb/examples/common/gui/xvideo.cpp b/src/tbb/examples/common/gui/xvideo.cpp new file mode 100644 index 0000000..47dcb84 --- /dev/null +++ b/src/tbb/examples/common/gui/xvideo.cpp @@ -0,0 +1,387 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Uncomment next line to disable shared memory features if you do not have libXext +// (http://www.xfree86.org/current/mit-shm.html) +//#define X_NOSHMEM + +// Note that it may happen that the build environment supports the shared-memory extension +// (so there's no build-time reason to disable the relevant code by defining X_NOSHMEM), +// but that using shared memory still fails at run time. +// This situation will (ultimately) cause the error handler set by XSetErrorHandler() +// to be invoked with XErrorEvent::minor_code==X_ShmAttach. The code below tries to make +// such a determination at XShmAttach() time, which seems plausible, but unfortunately +// it has also been observed in a specific environment that the error may be reported +// at a later time instead, even after video::init_window() has returned. +// It is not clear whether this may happen in that way in any environment where it might +// depend on the kind of display, e.g., local vs. over "ssh -X", so #define'ing X_NOSHMEM +// may not always be the appropriate solution, therefore an environment variable +// has been introduced to disable shared memory at run time. +// A diagnostic has been added to advise the user about possible workarounds. +// X_ShmAttach macro was changed to 1 due to recent changes to X11/extensions/XShm.h header. + +#include "video.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef X_NOSHMEM +#include +#include +#include +#include + +static XShmSegmentInfo shmseginfo; +static Pixmap pixmap = 0; +static bool already_called_X_ShmAttach = false; +static bool already_advised_about_NOSHMEM_workarounds = false; +static const char* NOSHMEM_env_var_name = "TBB_EXAMPLES_X_NOSHMEM"; +#endif +static char *display_name = NULL; +static Display *dpy = NULL; +static Screen *scrn; +static Visual *vis; +static Colormap cmap; +static GC gc; +static Window win, rootW; +static int dispdepth = 0; +static XGCValues xgcv; +static XImage *ximage; +static int x_error = 0; +static int vidtype = 3; +int g_sizex, g_sizey; +static video *g_video = 0; +unsigned int *g_pImg = 0; +static int g_fps = 0; +struct timeval g_time; +static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; +Atom _XA_WM_DELETE_WINDOW = 0;// like in Xatom.h + +///////////////////////////////////////////// public methods of video class /////////////////////// + +video::video() +{ + assert(g_video == 0); + g_video = this; title = "Video"; calc_fps = running = false; updating = true; +} + +inline void mask2bits(unsigned int mask, unsigned int &save, depth_t &shift) +{ + save = mask; if(!mask) { shift = dispdepth/3; return; } + shift = 0; while(!(mask&1)) ++shift, mask >>= 1; + int bits = 0; while(mask&1) ++bits, mask >>= 1; + shift += bits - 8; +} + +int xerr_handler(Display* dpy_, XErrorEvent *error) +{ + x_error = error->error_code; + if(g_video) g_video->running = false; +#ifndef X_NOSHMEM + if (error->minor_code==1/*X_ShmAttach*/ && already_called_X_ShmAttach && !already_advised_about_NOSHMEM_workarounds) + { + char err[256]; XGetErrorText(dpy_, x_error, err, 255); + fprintf(stderr, "Warning: Can't attach shared memory to display: %s (%d)\n", err, x_error); + fprintf(stderr, "If you are seeing a black output window, try setting %s environment variable to 1" + " to disable shared memory extensions (0 to re-enable, other values undefined)," + " or rebuilding with X_NOSHMEM defined in " __FILE__ "\n", NOSHMEM_env_var_name); + already_advised_about_NOSHMEM_workarounds = true; + } +#else + (void) dpy_; // warning prevention +#endif + return 0; +} + +bool video::init_window(int xsize, int ysize) +{ + { //enclose local variables before fail label + g_sizex = xsize; g_sizey = ysize; + + // Open the display + if (!dpy) { + dpy = XOpenDisplay(display_name); + if (!dpy) { + fprintf(stderr, "Can't open X11 display %s\n", XDisplayName(display_name)); + goto fail; + } + } + int theScreen = DefaultScreen(dpy); + scrn = ScreenOfDisplay(dpy, theScreen); + dispdepth = DefaultDepth(dpy, theScreen); + XVisualInfo vinfo; + if (!( (dispdepth >= 15 && dispdepth <= 32 && XMatchVisualInfo(dpy, theScreen, dispdepth, TrueColor, &vinfo) ) + || XMatchVisualInfo(dpy, theScreen, 24, TrueColor, &vinfo) + || XMatchVisualInfo(dpy, theScreen, 32, TrueColor, &vinfo) + || XMatchVisualInfo(dpy, theScreen, 16, TrueColor, &vinfo) + || XMatchVisualInfo(dpy, theScreen, 15, TrueColor, &vinfo) + )) { + fprintf(stderr, "Display has no appropriate True Color visual\n"); + goto fail; + } + vis = vinfo.visual; + depth = dispdepth = vinfo.depth; + mask2bits(vinfo.red_mask, red_mask, red_shift); + mask2bits(vinfo.green_mask, green_mask, green_shift); + mask2bits(vinfo.blue_mask, blue_mask, blue_shift); + rootW = RootWindow(dpy, theScreen); + cmap = XCreateColormap(dpy, rootW, vis, AllocNone); + XSetWindowAttributes attrs; + attrs.backing_store = Always; + attrs.colormap = cmap; + attrs.event_mask = StructureNotifyMask|KeyPressMask|ButtonPressMask|ButtonReleaseMask; + attrs.background_pixel = BlackPixelOfScreen(scrn); + attrs.border_pixel = WhitePixelOfScreen(scrn); + win = XCreateWindow(dpy, rootW, + 0, 0, xsize, ysize, 2, + dispdepth, InputOutput, vis, + CWBackingStore | CWColormap | CWEventMask | + CWBackPixel | CWBorderPixel, + &attrs); + if(!win) { + fprintf(stderr, "Can't create the window\n"); + goto fail; + } + XSizeHints sh; + sh.flags = PSize | PMinSize | PMaxSize; + sh.width = sh.min_width = sh.max_width = xsize; + sh.height = sh.min_height = sh.max_height = ysize; + XSetStandardProperties( dpy, win, g_video->title, g_video->title, None, NULL, 0, &sh ); + _XA_WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", false); + XSetWMProtocols(dpy, win, &_XA_WM_DELETE_WINDOW, 1); + gc = XCreateGC(dpy, win, 0L, &xgcv); + XMapRaised(dpy, win); + XFlush(dpy); +#ifdef X_FULLSYNC + XSynchronize(dpy, true); +#endif + XSetErrorHandler(xerr_handler); + + int imgbytes = xsize*ysize*(dispdepth<=16?2:4); + const char *vidstr; +#ifndef X_NOSHMEM + int major, minor, pixmaps; + if(XShmQueryExtension(dpy) && + XShmQueryVersion(dpy, &major, &minor, &pixmaps)) + { // Shared memory + if(NULL!=getenv(NOSHMEM_env_var_name) && 0!=strcmp("0",getenv(NOSHMEM_env_var_name))) { + goto generic; + } + shmseginfo.shmid = shmget(IPC_PRIVATE, imgbytes, IPC_CREAT|0777); + if(shmseginfo.shmid < 0) { + fprintf(stderr, "Warning: Can't get shared memory: %s\n", strerror(errno)); + goto generic; + } + g_pImg = (unsigned int*)(shmseginfo.shmaddr = (char*)shmat(shmseginfo.shmid, 0, 0)); + if(g_pImg == (unsigned int*)-1) { + fprintf(stderr, "Warning: Can't attach to shared memory: %s\n", strerror(errno)); + shmctl(shmseginfo.shmid, IPC_RMID, NULL); + goto generic; + } + shmseginfo.readOnly = false; + if(!XShmAttach(dpy, &shmseginfo) || x_error) { + char err[256]; XGetErrorText(dpy, x_error, err, 255); + fprintf(stderr, "Warning: Can't attach shared memory to display: %s (%d)\n", err, x_error); + shmdt(shmseginfo.shmaddr); shmctl(shmseginfo.shmid, IPC_RMID, NULL); + goto generic; + } + already_called_X_ShmAttach = true; + +#ifndef X_NOSHMPIX + if(pixmaps && XShmPixmapFormat(dpy) == ZPixmap) + { // Pixmaps + vidtype = 2; vidstr = "X11 shared memory pixmap"; + pixmap = XShmCreatePixmap(dpy, win, (char*)g_pImg, &shmseginfo, xsize, ysize, dispdepth); + XSetWindowBackgroundPixmap(dpy, win, pixmap); + } else +#endif//!X_NOSHMPIX + { // Standard + vidtype = 1; vidstr = "X11 shared memory"; + ximage = XShmCreateImage(dpy, vis, dispdepth, + ZPixmap, 0, &shmseginfo, xsize, ysize); + if(!ximage) { + fprintf(stderr, "Can't create the shared image\n"); + goto fail; + } + assert(ximage->bytes_per_line == xsize*(dispdepth<=16?2:4)); + ximage->data = shmseginfo.shmaddr; + } + } else +#endif + { +#ifndef X_NOSHMEM +generic: +#endif + vidtype = 0; vidstr = "generic X11"; + g_pImg = new unsigned int[imgbytes/sizeof(int)]; + ximage = XCreateImage(dpy, vis, dispdepth, ZPixmap, 0, (char*)g_pImg, xsize, ysize, 32, imgbytes/ysize); + if(!ximage) { + fprintf(stderr, "Can't create the image\n"); + goto fail; + } + } + printf("Note: using %s with %s visual for %d-bit color depth\n", vidstr, vis==DefaultVisual(dpy, theScreen)?"default":"non-default", dispdepth); + running = true; + return true; + } // end of enclosing local variables +fail: + terminate(); init_console(); + return false; +} + +bool video::init_console() +{ + if(!g_pImg && g_sizex && g_sizey) { + dispdepth = 24; red_shift = 16; vidtype = 3; // fake video + g_pImg = new unsigned int[g_sizex*g_sizey]; + running = true; + } + return true; +} + +void video::terminate() +{ + running = false; + if(dpy) { + vidtype = 3; // stop video + if(threaded) { pthread_mutex_lock(&g_mutex); pthread_mutex_unlock(&g_mutex); } + if(ximage) { XDestroyImage(ximage); ximage = 0; g_pImg = 0; } // it frees g_pImg for vidtype == 0 +#ifndef X_NOSHMEM + if(pixmap) XFreePixmap(dpy, pixmap); + if(shmseginfo.shmaddr) { XShmDetach(dpy, &shmseginfo); shmdt(shmseginfo.shmaddr); g_pImg = 0; } + if(shmseginfo.shmid >= 0) shmctl(shmseginfo.shmid, IPC_RMID, NULL); +#endif + if(gc) XFreeGC(dpy, gc); + if(win) XDestroyWindow(dpy, win); + XCloseDisplay(dpy); dpy = 0; + } + if(g_pImg) { delete[] g_pImg; g_pImg = 0; } // if was allocated for console mode +} + +video::~video() +{ + if(g_video) terminate(); + g_video = 0; +} + +//! Do standard event loop +void video::main_loop() +{ + struct timezone tz; gettimeofday(&g_time, &tz); + on_process(); +} + +//! Check for pending events once +bool video::next_frame() +{ + if(!running) return false; + //! try acquire mutex if threaded code, returns on failure + if(vidtype == 3 || threaded && pthread_mutex_trylock(&g_mutex)) + return running; + //! Refresh screen picture + g_fps++; +#ifndef X_NOSHMPIX + if(vidtype == 2 && updating) XClearWindow(dpy, win); +#endif + while( XPending(dpy) ) { + XEvent report; XNextEvent(dpy, &report); + switch( report.type ) { + case ClientMessage: + if(report.xclient.format != 32 || report.xclient.data.l[0] != _XA_WM_DELETE_WINDOW) break; + case DestroyNotify: + running = false; + case KeyPress: + on_key( XLookupKeysym(&report.xkey, 0) ); break; + case ButtonPress: + on_mouse( report.xbutton.x, report.xbutton.y, report.xbutton.button ); break; + case ButtonRelease: + on_mouse( report.xbutton.x, report.xbutton.y, -report.xbutton.button ); break; + } + } + struct timezone tz; struct timeval now_time; gettimeofday(&now_time, &tz); + double sec = (now_time.tv_sec+1.0*now_time.tv_usec/1000000.0) - (g_time.tv_sec+1.0*g_time.tv_usec/1000000.0); + if(sec > 1) { + memcpy(&g_time, &now_time, sizeof(g_time)); + if(calc_fps) { + double fps = g_fps; g_fps = 0; + char buffer[256]; snprintf(buffer, 256, "%s%s: %d fps", title, updating?"":" (no updating)", int(fps/sec)); + XStoreName(dpy, win, buffer); + } +#ifndef X_FULLSYNC + XSync(dpy, false); // It is often better then using XSynchronize(dpy, true) +#endif//X_FULLSYNC + } + if(threaded) pthread_mutex_unlock(&g_mutex); + return true; +} + +//! Change window title +void video::show_title() +{ + if(vidtype < 3) + XStoreName(dpy, win, title); +} + +drawing_area::drawing_area(int x, int y, int sizex, int sizey) + : start_x(x), start_y(y), size_x(sizex), size_y(sizey), pixel_depth(dispdepth), + base_index(y*g_sizex + x), max_index(g_sizex*g_sizey), index_stride(g_sizex), ptr32(g_pImg) +{ + assert(x < g_sizex); assert(y < g_sizey); + assert(x+sizex <= g_sizex); assert(y+sizey <= g_sizey); + + index = base_index; // current index +} + +void drawing_area::update() +{ + if(!g_video->updating) return; +#ifndef X_NOSHMEM + switch(vidtype) { + case 0: +#endif + pthread_mutex_lock(&g_mutex); + if(vidtype == 0) XPutImage(dpy, win, gc, ximage, start_x, start_y, start_x, start_y, size_x, size_y); + pthread_mutex_unlock(&g_mutex); +#ifndef X_NOSHMEM + break; + case 1: + pthread_mutex_lock(&g_mutex); + if(vidtype == 1) XShmPutImage(dpy, win, gc, ximage, start_x, start_y, start_x, start_y, size_x, size_y, false); + pthread_mutex_unlock(&g_mutex); + break; + /*case 2: make it in next_frame(); break;*/ + } +#endif +} diff --git a/src/tbb/examples/common/index.html b/src/tbb/examples/common/index.html new file mode 100644 index 0000000..3817f05 --- /dev/null +++ b/src/tbb/examples/common/index.html @@ -0,0 +1,39 @@ + + + +

Overview

+This directory contains common code that is used in the Intel® Threading Building Blocks examples. + +

+This code is not intended to be used directly. It is incorporated automatically by the examples that need it. +

+ +

Directories

+
+
gui +
GUI code for examples that have graphical user interfaces. Currently supports: +
    +
  • GDI+*, DirectDraw*, Direct2D* (Windows* systems) +
  • OpenGL* (Mac OS* X systems) +
  • X window (Linux* or Mac OS* X systems) +
+ See the examples that use the GUI + (tachyon and seismic) + for more details. +
+
+
utility +
common driver code for examples. +
+ +
+Up to parent directory +

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. + + diff --git a/src/tbb/examples/common/utility/fast_random.h b/src/tbb/examples/common/utility/fast_random.h new file mode 100644 index 0000000..c1b8d28 --- /dev/null +++ b/src/tbb/examples/common/utility/fast_random.h @@ -0,0 +1,90 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef FAST_RANDOM_H_ +#define FAST_RANDOM_H_ +namespace utility{ +//------------------------------------------------------------------------ +// FastRandom +//------------------------------------------------------------------------ + +namespace internal{ + size_t GetPrime ( size_t seed ); +} + +//! A fast random number generator. +/** Uses linear congruential method. */ +class FastRandom { + size_t x, a; +public: + //! Get a random number. + unsigned short get() { + return get(x); + } + //! Get a random number for the given seed; update the seed for next use. + unsigned short get( size_t& seed ) { + unsigned short r = (unsigned short)(seed>>16); + seed = seed*a+1; + return r; + } + //! Construct a random number generator. + FastRandom( size_t seed ) { + x = seed*internal::GetPrime(seed); + a = internal::GetPrime(x); + } +}; +} + +namespace utility { +namespace internal{ +//! Table of primes used by fast random-number generator (FastRandom). + static const unsigned Primes[] = { + 0x9e3779b1, 0xffe6cc59, 0x2109f6dd, 0x43977ab5, + 0xba5703f5, 0xb495a877, 0xe1626741, 0x79695e6b, + 0xbc98c09f, 0xd5bee2b3, 0x287488f9, 0x3af18231, + 0x9677cd4d, 0xbe3a6929, 0xadc6a877, 0xdcf0674b, + 0xbe4d6fe9, 0x5f15e201, 0x99afc3fd, 0xf3f16801, + 0xe222cfff, 0x24ba5fdb, 0x0620452d, 0x79f149e3, + 0xc8b93f49, 0x972702cd, 0xb07dd827, 0x6c97d5ed, + 0x085a3d61, 0x46eb5ea7, 0x3d9910ed, 0x2e687b5b, + 0x29609227, 0x6eb081f1, 0x0954c4e1, 0x9d114db9, + 0x542acfa9, 0xb3e6bd7b, 0x0742d917, 0xe9f3ffa7, + 0x54581edb, 0xf2480f45, 0x0bb9288f, 0xef1affc7, + 0x85fa0ca7, 0x3ccc14db, 0xe6baf34b, 0x343377f7, + 0x5ca19031, 0xe6d9293b, 0xf0a9f391, 0x5d2e980b, + 0xfc411073, 0xc3749363, 0xb892d829, 0x3549366b, + 0x629750ad, 0xb98294e5, 0x892d9483, 0xc235baf3, + 0x3d2402a3, 0x6bdef3c9, 0xbec333cd, 0x40c9520f + }; + size_t GetPrime ( size_t seed ) { + return Primes[seed%(sizeof(Primes)/sizeof(Primes[0]))]; + } +} +} + +#endif /* FAST_RANDOM_H_ */ diff --git a/src/tbb/examples/common/utility/utility.h b/src/tbb/examples/common/utility/utility.h new file mode 100644 index 0000000..4f6939b --- /dev/null +++ b/src/tbb/examples/common/utility/utility.h @@ -0,0 +1,396 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef UTILITY_H_ +#define UTILITY_H_ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace utility{ + namespace internal{ + //TODO: add tcs + template + dest_type& string_to(std::string const& s, dest_type& result){ + std::stringstream stream(s); + stream>>result; + if ((!stream)||(stream.fail())){ + throw std::invalid_argument("error converting string \""+std::string(s)+"\""); + } + return result; + } + + template + dest_type string_to(std::string const& s){ + dest_type result; + return string_to(s,result); + } + + + template + struct is_bool { enum{value=false};}; + + template<> + struct is_bool { enum{value=true};}; + + class type_base { + type_base& operator=(const type_base&); + public: + const std::string name; + const std::string description; + + type_base (std::string name, std::string description) : name(name), description(description) {} + virtual void parse_and_store (const std::string & s)=0; + virtual std::string value() const =0; + virtual std::auto_ptr clone()const =0; + virtual ~type_base(){} + }; + template + class type_impl : public type_base { + private: + type_impl& operator=(const type_impl&); + typedef bool(*validating_function_type)(const type&); + private: + type & target; + validating_function_type validating_function; + public: + type_impl(std::string name, std::string description, type & target, validating_function_type validating_function = NULL) + : type_base (name,description), target(target),validating_function(validating_function) + {}; + void parse_and_store (const std::string & s){ + try{ + const bool is_bool_type =is_bool::value; + if ((is_bool_type)&&(s.empty())){ + //to avoid directly assigning true + //(as it will impose additional layer of indirection) + //so, simply pass it as string + internal::string_to("1",target); + }else { + internal::string_to(s,target); + } + }catch(std::invalid_argument& ){ + std::stringstream str; + str + <<"\""< clone()const { + return std::auto_ptr(new type_impl(*this)); + } + }; + + class argument{ + private: + std::auto_ptr p_type; + bool matched_; + public: + argument(argument const& other): p_type(other.p_type.get() ? other.p_type->clone():std::auto_ptr()),matched_(other.matched_){} + argument& operator=(argument a){ + this->swap(a); + return *this; + } + void swap(argument& other){ + std::auto_ptr tmp; tmp=p_type; p_type=other.p_type; other.p_type=tmp; + std::swap(matched_,other.matched_); + } + template + argument(std::string name, std::string description, type& dest, bool(*validating_function)(const type&)= NULL) + :p_type(new type_impl(name,description,dest,validating_function)) + ,matched_(false) + {} + std::string value()const{ + return p_type->value(); + } + std::string name()const{ + return p_type->name; + } + std::string description() const{ + return p_type->description; + } + void parse_and_store(const std::string & s){ + p_type->parse_and_store(s); + matched_=true; + } + bool is_matched() const{return matched_;} + }; + + } + class cli_argument_pack{ + typedef std::map args_map_type; + typedef std::vector args_display_order_type; + typedef std::vector positional_arg_names_type; + private: + args_map_type args_map; + args_display_order_type args_display_order; + positional_arg_names_type positional_arg_names; + std::set bool_args_names; + private: + void add_arg(internal::argument const& a){ + std::pair result = args_map.insert(std::make_pair(a.name(),a)); + if (!result.second){ + throw std::invalid_argument("argument with name: \""+a.name()+"\" already registered"); + } + args_display_order.push_back(a.name()); + } + public: + template + cli_argument_pack& arg(type& dest,std::string const& name, std::string const& description, bool(*validate)(const type &)= NULL){ + internal::argument a(name,description,dest,validate); + add_arg(a); + if (internal::is_bool::value){ + bool_args_names.insert(name); + } + return *this; + } + + //Positional means that argument name can be omitted in actual CL + //only key to match values for parameters with + template + cli_argument_pack& positional_arg(type& dest,std::string const& name, std::string const& description, bool(*validate)(const type &)= NULL){ + internal::argument a(name,description,dest,validate); + add_arg(a); + if (internal::is_bool::value){ + bool_args_names.insert(name); + } + positional_arg_names.push_back(name); + return *this; + } + + void parse(int argc, char const* argv[]){ + { + std::size_t current_positional_index=0; + for (int j=1;jis_matched()){ + throw std::invalid_argument(std::string("several values specified for: \"")+pa->name()+"\" argument"); + } + pa->parse_and_store(argument_value); + } + } + } + std::string usage_string(const std::string& binary_name)const{ + std::string command_line_params; + std::string summary_description; + + for (args_display_order_type::const_iterator it = args_display_order.begin();it!=args_display_order.end();++it){ + const bool is_bool = (0!=bool_args_names.count((*it))); + args_map_type::const_iterator argument_it = args_map.find(*it); + //TODO: probably use of smarter assert would help here + assert(argument_it!=args_map.end()/*&&"args_display_order and args_map are out of sync"*/); + if (argument_it==args_map.end()){ + throw std::logic_error("args_display_order and args_map are out of sync"); + } + const internal::argument & a = (*argument_it).second; + command_line_params +=" [" + a.name() + (is_bool ?"":"=value")+ "]"; + summary_description +=" " + a.name() + " - " + a.description() +" ("+a.value() +")" + "\n"; + } + + std::string positional_arg_cl; + for (positional_arg_names_type::const_iterator it = positional_arg_names.begin();it!=positional_arg_names.end();++it){ + positional_arg_cl +=" ["+(*it); + } + for (std::size_t i=0;i-1) ? high_ : auto_number_of_threads_()) + { + if (first>last){ + throw std::invalid_argument(""); + } + } + friend std::istream& operator>>(std::istream& i, thread_number_range& range){ + try{ + std::string s; + i>>s; + struct string_to_number_of_threads{ + int auto_value; + string_to_number_of_threads(int auto_value_):auto_value(auto_value_){} + int operator()(const std::string & value)const{ + int result=0; + if (value=="auto"){ + result = auto_value; + } + else{ + internal::string_to(value,result); + } + return result; + } + }; + string_to_number_of_threads string_to_number_of_threads(range.auto_number_of_threads()); + int low =0; + int high=0; + std::size_t semicolon = s.find(':'); + if (semicolon == std::string::npos ){ + high= (low = string_to_number_of_threads(s)); + }else { + //it is a range + std::string::iterator semicolon_it = s.begin()+semicolon; + low = string_to_number_of_threads(std::string(s.begin(),semicolon_it)); + high = string_to_number_of_threads(std::string(semicolon_it+1,s.end())); + } + range = thread_number_range(range.auto_number_of_threads,low,high); + }catch(std::invalid_argument&){ + i.setstate(std::ios::failbit); + } + return i; + } + friend std::ostream& operator<<(std::ostream& o, thread_number_range const& range){ + o< +namespace utility{ + inline void report_elapsed_time(double seconds){ + std::cout << "elapsed time : "< +namespace utility{ + inline void parse_cli_arguments(int argc, const char* argv[], utility::cli_argument_pack cli_pack){ + bool show_help = false; + cli_pack.arg(show_help,"-h","show this message"); + + bool invalid_input=false; + try { + cli_pack.parse(argc,argv); + }catch(std::exception& e){ + std::cerr + <<"error occurred while parsing command line."<(argv), cli_pack); + } +} +#endif /* UTILITY_H_ */ diff --git a/src/tbb/examples/concurrent_hash_map/count_strings/Makefile b/src/tbb/examples/concurrent_hash_map/count_strings/Makefile new file mode 100644 index 0000000..2ecd86c --- /dev/null +++ b/src/tbb/examples/concurrent_hash_map/count_strings/Makefile @@ -0,0 +1,59 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# GNU Makefile that builds and runs example. +PROG=count_strings +ARGS= +PERF_RUN_ARGS=auto 10000000 silent + +# The C++ compiler +ifneq (,$(shell which icc 2>/dev/null)) +CXX=icc +endif # icc + +ifeq ($(shell uname), Linux) +LIBS+= -lrt +endif + +all: release test + +release: *.cpp + $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb $(LIBS) + +debug: *.cpp + $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(LIBS) + +clean: + $(RM) $(PROG) *.o *.d + +test: + ./$(PROG) $(ARGS) + +perf_build: release + +perf_run: + ./$(PROG) $(PERF_RUN_ARGS) + diff --git a/src/tbb/examples/concurrent_hash_map/count_strings/Makefile.windows b/src/tbb/examples/concurrent_hash_map/count_strings/Makefile.windows new file mode 100644 index 0000000..ba04a1c --- /dev/null +++ b/src/tbb/examples/concurrent_hash_map/count_strings/Makefile.windows @@ -0,0 +1,59 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Common Makefile that builds and runs example. + +# Just specify your program basename +PROG=Count_Strings +ARGS= +PERF_RUN_ARGS=auto 10000000 silent + +# The C++ compiler options + +# Trying to find if icl.exe is set +CXX1 = $(TBB_CXX)- +CXX2 = $(CXX1:icl.exe-=icl.exe) +CXX = $(CXX2:-=cl.exe) + +MYCXXFLAGS = /TP /EHsc /W3 /nologo /D _CONSOLE /D _MBCS /D WIN32 $(CXXFLAGS) +MYLDFLAGS =/INCREMENTAL:NO /NOLOGO /DEBUG /FIXED:NO $(LDFLAGS) + +all: release test +release: compiler_check + $(CXX) *.cpp /MD /O2 /D NDEBUG $(MYCXXFLAGS) /link tbb.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +debug: compiler_check + $(CXX) *.cpp /MDd /Od /Zi /D TBB_USE_DEBUG /D _DEBUG $(MYCXXFLAGS) /link tbb_debug.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +clean: + @cmd.exe /C del $(PROG).exe *.obj *.?db *.manifest +test: + $(PROG) $(ARGS) +compiler_check: + @echo compiler_test>compiler_test && @$(CXX) /E compiler_test >nul 2>&1 || echo "$(CXX) command not found. Check if CXX=$(CXX) is set properly" + @cmd.exe /C del compiler_test +perf_build: release +perf_run: + $(PROG) $(PERF_RUN_ARGS) + diff --git a/src/tbb/examples/concurrent_hash_map/count_strings/count_strings.cpp b/src/tbb/examples/concurrent_hash_map/count_strings/count_strings.cpp new file mode 100644 index 0000000..bd671e1 --- /dev/null +++ b/src/tbb/examples/concurrent_hash_map/count_strings/count_strings.cpp @@ -0,0 +1,243 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Workaround for ICC 11.0 not finding __sync_fetch_and_add_4 on some of the Linux platforms. +#if __linux__ && defined(__INTEL_COMPILER) +#define __sync_fetch_and_add(ptr,addend) _InterlockedExchangeAdd(const_cast(reinterpret_cast(ptr)), addend) +#endif +#include +#include +#include +#include +#include +#include "tbb/concurrent_hash_map.h" +#include "tbb/blocked_range.h" +#include "tbb/parallel_for.h" +#include "tbb/tick_count.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/tbb_allocator.h" +#include "../../common/utility/utility.h" + + +//! String type with scalable allocator. +/** On platforms with non-scalable default memory allocators, the example scales + better if the string allocator is changed to tbb::tbb_allocator. */ +typedef std::basic_string,tbb::tbb_allocator > MyString; + +using namespace tbb; +using namespace std; + +//! Set to true to counts. +static bool verbose = false; +static bool silent = false; +//! Problem size +long N = 1000000; +const int size_factor = 2; + +//! A concurrent hash table that maps strings to ints. +typedef concurrent_hash_map StringTable; + +//! Function object for counting occurrences of strings. +struct Tally { + StringTable& table; + Tally( StringTable& table_ ) : table(table_) {} + void operator()( const blocked_range range ) const { + for( MyString* p=range.begin(); p!=range.end(); ++p ) { + StringTable::accessor a; + table.insert( a, *p ); + a->second += 1; + } + } +}; + +static MyString* Data; + +static void CountOccurrences(int nthreads) { + StringTable table; + + tick_count t0 = tick_count::now(); + parallel_for( blocked_range( Data, Data+N, 1000 ), Tally(table) ); + tick_count t1 = tick_count::now(); + + int n = 0; + for( StringTable::iterator i=table.begin(); i!=table.end(); ++i ) { + if( verbose && nthreads ) + printf("%s %d\n",i->first.c_str(),i->second); + n += i->second; + } + + if ( !silent ) printf("total = %d unique = %u time = %g\n", n, unsigned(table.size()), (t1-t0).seconds()); +} + +/// Generator of random words + +struct Sound { + const char *chars; + int rates[3];// begining, middle, ending +}; +Sound Vowels[] = { + {"e", {445,6220,1762}}, {"a", {704,5262,514}}, {"i", {402,5224,162}}, {"o", {248,3726,191}}, + {"u", {155,1669,23}}, {"y", {4,400,989}}, {"io", {5,512,18}}, {"ia", {1,329,111}}, + {"ea", {21,370,16}}, {"ou", {32,298,4}}, {"ie", {0,177,140}}, {"ee", {2,183,57}}, + {"ai", {17,206,7}}, {"oo", {1,215,7}}, {"au", {40,111,2}}, {"ua", {0,102,4}}, + {"ui", {0,104,1}}, {"ei", {6,94,3}}, {"ue", {0,67,28}}, {"ay", {1,42,52}}, + {"ey", {1,14,80}}, {"oa", {5,84,3}}, {"oi", {2,81,1}}, {"eo", {1,71,5}}, + {"iou", {0,61,0}}, {"oe", {2,46,9}}, {"eu", {12,43,0}}, {"iu", {0,45,0}}, + {"ya", {12,19,5}}, {"ae", {7,18,10}}, {"oy", {0,10,13}}, {"ye", {8,7,7}}, + {"ion", {0,0,20}}, {"ing", {0,0,20}}, {"ium", {0,0,10}}, {"er", {0,0,20}} +}; +Sound Consonants[] = { + {"r", {483,1414,1110}}, {"n", {312,1548,1114}}, {"t", {363,1653,251}}, {"l", {424,1341,489}}, + {"c", {734,735,260}}, {"m", {732,785,161}}, {"d", {558,612,389}}, {"s", {574,570,405}}, + {"p", {519,361,98}}, {"b", {528,356,30}}, {"v", {197,598,16}}, {"ss", {3,191,567}}, + {"g", {285,430,42}}, {"st", {142,323,180}}, {"h", {470,89,30}}, {"nt", {0,350,231}}, + {"ng", {0,117,442}}, {"f", {319,194,19}}, {"ll", {1,414,83}}, {"w", {249,131,64}}, + {"k", {154,179,47}}, {"nd", {0,279,92}}, {"bl", {62,235,0}}, {"z", {35,223,16}}, + {"sh", {112,69,79}}, {"ch", {139,95,25}}, {"th", {70,143,39}}, {"tt", {0,219,19}}, + {"tr", {131,104,0}}, {"pr", {186,41,0}}, {"nc", {0,223,2}}, {"j", {184,32,1}}, + {"nn", {0,188,20}}, {"rt", {0,148,51}}, {"ct", {0,160,29}}, {"rr", {0,182,3}}, + {"gr", {98,87,0}}, {"ck", {0,92,86}}, {"rd", {0,81,88}}, {"x", {8,102,48}}, + {"ph", {47,101,10}}, {"br", {115,43,0}}, {"cr", {92,60,0}}, {"rm", {0,131,18}}, + {"ns", {0,124,18}}, {"sp", {81,55,4}}, {"sm", {25,29,85}}, {"sc", {53,83,1}}, + {"rn", {0,100,30}}, {"cl", {78,42,0}}, {"mm", {0,116,0}}, {"pp", {0,114,2}}, + {"mp", {0,99,14}}, {"rs", {0,96,16}}, /*{"q", {52,57,1}},*/ {"rl", {0,97,7}}, + {"rg", {0,81,15}}, {"pl", {56,39,0}}, {"sn", {32,62,1}}, {"str", {38,56,0}}, + {"dr", {47,44,0}}, {"fl", {77,13,1}}, {"fr", {77,11,0}}, {"ld", {0,47,38}}, + {"ff", {0,62,20}}, {"lt", {0,61,19}}, {"rb", {0,75,4}}, {"mb", {0,72,7}}, + {"rc", {0,76,1}}, {"gg", {0,74,1}}, {"pt", {1,56,10}}, {"bb", {0,64,1}}, + {"sl", {48,17,0}}, {"dd", {0,59,2}}, {"gn", {3,50,4}}, {"rk", {0,30,28}}, + {"nk", {0,35,20}}, {"gl", {40,14,0}}, {"wh", {45,6,0}}, {"ntr", {0,50,0}}, + {"rv", {0,47,1}}, {"ght", {0,19,29}}, {"sk", {23,17,5}}, {"nf", {0,46,0}}, + {"cc", {0,45,0}}, {"ln", {0,41,0}}, {"sw", {36,4,0}}, {"rp", {0,36,4}}, + {"dn", {0,38,0}}, {"ps", {14,19,5}}, {"nv", {0,38,0}}, {"tch", {0,21,16}}, + {"nch", {0,26,11}}, {"lv", {0,35,0}}, {"wn", {0,14,21}}, {"rf", {0,32,3}}, + {"lm", {0,30,5}}, {"dg", {0,34,0}}, {"ft", {0,18,15}}, {"scr", {23,10,0}}, + {"rch", {0,24,6}}, {"rth", {0,23,7}}, {"rh", {13,15,0}}, {"mpl", {0,29,0}}, + {"cs", {0,1,27}}, {"gh", {4,10,13}}, {"ls", {0,23,3}}, {"ndr", {0,25,0}}, + {"tl", {0,23,1}}, {"ngl", {0,25,0}}, {"lk", {0,15,9}}, {"rw", {0,23,0}}, + {"lb", {0,23,1}}, {"tw", {15,8,0}}, /*{"sq", {15,8,0}},*/ {"chr", {18,4,0}}, + {"dl", {0,23,0}}, {"ctr", {0,22,0}}, {"nst", {0,21,0}}, {"lc", {0,22,0}}, + {"sch", {16,4,0}}, {"ths", {0,1,20}}, {"nl", {0,21,0}}, {"lf", {0,15,6}}, + {"ssn", {0,20,0}}, {"xt", {0,18,1}}, {"xp", {0,20,0}}, {"rst", {0,15,5}}, + {"nh", {0,19,0}}, {"wr", {14,5,0}} +}; +const int VowelsNumber = sizeof(Vowels)/sizeof(Sound); +const int ConsonantsNumber = sizeof(Consonants)/sizeof(Sound); +int VowelsRatesSum[3] = {0,0,0}, ConsonantsRatesSum[3] = {0,0,0}; + +int CountRateSum(Sound sounds[], const int num, const int part) +{ + int sum = 0; + for(int i = 0; i < num; i++) + sum += sounds[i].rates[part]; + return sum; +} + +const char *GetLetters(int type, const int part) +{ + Sound *sounds; int rate, i = 0; + if(type & 1) + sounds = Vowels, rate = rand() % VowelsRatesSum[part]; + else + sounds = Consonants, rate = rand() % ConsonantsRatesSum[part]; + do { + rate -= sounds[i++].rates[part]; + } while(rate > 0); + return sounds[--i].chars; +} + +static void CreateData() { + for(int i = 0; i < 3; i++) { + ConsonantsRatesSum[i] = CountRateSum(Consonants, ConsonantsNumber, i); + VowelsRatesSum[i] = CountRateSum(Vowels, VowelsNumber, i); + } + for( int i=0; i + + +

Overview

+The example counts the number of unique words in a text. + + +

Files

+
+
count_strings.cpp +
Source code for example. +
Makefile +
Makefile for building example. +
+ +

Directories

+
+
msvs +
Contains Microsoft* Visual Studio* 2005 workspace for building and running the example (Windows* systems only). +
xcode +
Contains Xcode* IDE workspace for building and running the example (Mac OS* X systems only). +
+ +

To Build

+General build directions can be found here. + +

Usage

+
+
count_strings -h +
Prints the help for command line options +
count_strings [n-of-threads=value] [n-of-strings=value] [verbose] [silent] +
count_strings [n-of-threads [n-of-strings]] [verbose] [silent] +
n-of-threads is the number of threads to use; a range of the form low[:high], where low and optional high are non-negative integers or 'auto' for the TBB default.
+ n-of-strings is a number of strings.
+ verbose - enables printing of extra information during execution.
+ silent - no output except elapsed time.
+ +
To run a short version of this example, e.g., for use with Intel® Parallel Inspector: +
Build a debug version of the example + (see the build directions). +
Run it with a small number of strings and the desired number of threads, e.g., count_strings 2 10000. +
+ +
+Up to parent directory +

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. + + + diff --git a/src/tbb/examples/concurrent_hash_map/count_strings/msvs/count_strings.icproj b/src/tbb/examples/concurrent_hash_map/count_strings/msvs/count_strings.icproj new file mode 100644 index 0000000..c873cd5 --- /dev/null +++ b/src/tbb/examples/concurrent_hash_map/count_strings/msvs/count_strings.icproj @@ -0,0 +1,11 @@ + + + + + diff --git a/src/tbb/examples/concurrent_hash_map/count_strings/msvs/count_strings.vcproj b/src/tbb/examples/concurrent_hash_map/count_strings/msvs/count_strings.vcproj new file mode 100644 index 0000000..6a74e2e --- /dev/null +++ b/src/tbb/examples/concurrent_hash_map/count_strings/msvs/count_strings.vcproj @@ -0,0 +1,356 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/concurrent_hash_map/count_strings/msvs/count_strings_cl.sln b/src/tbb/examples/concurrent_hash_map/count_strings/msvs/count_strings_cl.sln new file mode 100644 index 0000000..5a9c27e --- /dev/null +++ b/src/tbb/examples/concurrent_hash_map/count_strings/msvs/count_strings_cl.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "count_strings", "count_strings.vcproj", "{3AA40693-F93D-4D4B-B32E-068F511A252C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3AA40693-F93D-4D4B-B32E-068F511A252C}.Debug|Win32.ActiveCfg = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252C}.Debug|Win32.Build.0 = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252C}.Debug|x64.ActiveCfg = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252C}.Debug|x64.Build.0 = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252C}.Release|Win32.ActiveCfg = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252C}.Release|Win32.Build.0 = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252C}.Release|x64.ActiveCfg = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252C}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/concurrent_hash_map/count_strings/msvs/count_strings_icl.sln b/src/tbb/examples/concurrent_hash_map/count_strings/msvs/count_strings_icl.sln new file mode 100644 index 0000000..ff1ba24 --- /dev/null +++ b/src/tbb/examples/concurrent_hash_map/count_strings/msvs/count_strings_icl.sln @@ -0,0 +1,33 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "count_strings", "count_strings.icproj", "{ACC0CC2E-3102-4ED2-AFA2-996AF7DEC9A8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ACC0CC2E-3102-4ED2-AFA2-996AF7DEC9A8}.Debug|Win32.ActiveCfg = Debug|Win32 + {ACC0CC2E-3102-4ED2-AFA2-996AF7DEC9A8}.Debug|Win32.Build.0 = Debug|Win32 + {ACC0CC2E-3102-4ED2-AFA2-996AF7DEC9A8}.Debug|x64.ActiveCfg = Debug|x64 + {ACC0CC2E-3102-4ED2-AFA2-996AF7DEC9A8}.Debug|x64.Build.0 = Debug|x64 + {ACC0CC2E-3102-4ED2-AFA2-996AF7DEC9A8}.Release|Win32.ActiveCfg = Release|Win32 + {ACC0CC2E-3102-4ED2-AFA2-996AF7DEC9A8}.Release|Win32.Build.0 = Release|Win32 + {ACC0CC2E-3102-4ED2-AFA2-996AF7DEC9A8}.Release|x64.ActiveCfg = Release|x64 + {ACC0CC2E-3102-4ED2-AFA2-996AF7DEC9A8}.Release|x64.Build.0 = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252C}.Release|x64.Build.0 = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252C}.Release|x64.ActiveCfg = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252C}.Release|Win32.Build.0 = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252C}.Release|Win32.ActiveCfg = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252C}.Debug|x64.Build.0 = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252C}.Debug|x64.ActiveCfg = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252C}.Debug|Win32.Build.0 = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252C}.Debug|Win32.ActiveCfg = Debug|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/concurrent_hash_map/count_strings/xcode/count_strings.xcodeproj/project.pbxproj b/src/tbb/examples/concurrent_hash_map/count_strings/xcode/count_strings.xcodeproj/project.pbxproj new file mode 100644 index 0000000..1b90bf7 --- /dev/null +++ b/src/tbb/examples/concurrent_hash_map/count_strings/xcode/count_strings.xcodeproj/project.pbxproj @@ -0,0 +1,305 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + A1F593A60B8F042A00073279 /* count_strings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1F593A50B8F042A00073279 /* count_strings.cpp */; }; + A1F593B70B8F06F900073279 /* libtbb.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; + A1F593BB0B8F072500073279 /* libtbb.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8DD76F690486A84900D96B5E /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = ""; + dstSubfolderSpec = 16; + files = ( + A1F593BB0B8F072500073279 /* libtbb.dylib in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 8DD76F6C0486A84900D96B5E /* count_strings */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = count_strings; sourceTree = BUILT_PRODUCTS_DIR; }; + A1F593A50B8F042A00073279 /* count_strings.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = count_strings.cpp; path = ../count_strings.cpp; sourceTree = SOURCE_ROOT; }; + A1F593B30B8F06F900073279 /* libtbb.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtbb.dylib; path = ../../../../lib/libtbb.dylib; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8DD76F660486A84900D96B5E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A1F593B70B8F06F900073279 /* libtbb.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* count_strings */ = { + isa = PBXGroup; + children = ( + 08FB7795FE84155DC02AAC07 /* Source */, + A1F593B20B8F06F900073279 /* External Frameworks and Libraries */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + ); + name = count_strings; + sourceTree = ""; + }; + 08FB7795FE84155DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + A1F593A50B8F042A00073279 /* count_strings.cpp */, + ); + name = Source; + sourceTree = ""; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8DD76F6C0486A84900D96B5E /* count_strings */, + ); + name = Products; + sourceTree = ""; + }; + A1F593B20B8F06F900073279 /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + A1F593B30B8F06F900073279 /* libtbb.dylib */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8DD76F620486A84900D96B5E /* count_strings */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "count_strings" */; + buildPhases = ( + 8DD76F640486A84900D96B5E /* Sources */, + 8DD76F660486A84900D96B5E /* Frameworks */, + 8DD76F690486A84900D96B5E /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = count_strings; + productInstallPath = "$(HOME)/bin"; + productName = count_strings; + productReference = 8DD76F6C0486A84900D96B5E /* count_strings */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0410; + }; + buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "count_strings" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 08FB7794FE84155DC02AAC07 /* count_strings */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DD76F620486A84900D96B5E /* count_strings */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 8DD76F640486A84900D96B5E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1F593A60B8F042A00073279 /* count_strings.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1DEB923208733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = count_strings; + ZERO_LINK = NO; + }; + name = Debug; + }; + 1DEB923308733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = count_strings; + ZERO_LINK = NO; + }; + name = Release; + }; + 1DEB923608733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Debug; + }; + 1DEB923708733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Release; + }; + A1F593C60B8F0E6E00073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = count_strings; + ZERO_LINK = NO; + }; + name = Debug64; + }; + A1F593C70B8F0E6E00073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = count_strings; + ZERO_LINK = NO; + }; + name = Release64; + }; + A1F593C80B8F0E6E00073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-m64", + ); + OTHER_LDFLAGS = "-m64"; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Debug64; + }; + A1F593C90B8F0E6E00073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-m64", + ); + OTHER_LDFLAGS = "-m64"; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Release64; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "count_strings" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923208733DC60010E9CD /* Debug */, + A1F593C60B8F0E6E00073279 /* Debug64 */, + 1DEB923308733DC60010E9CD /* Release */, + A1F593C70B8F0E6E00073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "count_strings" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923608733DC60010E9CD /* Debug */, + A1F593C80B8F0E6E00073279 /* Debug64 */, + 1DEB923708733DC60010E9CD /* Release */, + A1F593C90B8F0E6E00073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/src/tbb/examples/concurrent_hash_map/index.html b/src/tbb/examples/concurrent_hash_map/index.html new file mode 100644 index 0000000..4b4db68 --- /dev/null +++ b/src/tbb/examples/concurrent_hash_map/index.html @@ -0,0 +1,24 @@ + + + +

Overview

+This directory has examples of the template concurrent_hash_map. + +

Directories

+
+
count_strings +
Concurrently inserts strings into a concurrent_hash_map. +
+ +
+Up to parent directory +

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. + + + diff --git a/src/tbb/examples/concurrent_priority_queue/shortpath/Makefile b/src/tbb/examples/concurrent_priority_queue/shortpath/Makefile new file mode 100644 index 0000000..5bc5133 --- /dev/null +++ b/src/tbb/examples/concurrent_priority_queue/shortpath/Makefile @@ -0,0 +1,61 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# GNU Makefile that builds and runs example. +PROG=shortpath +ARGS=4 N=1000 start=0 end=999 verbose +PERF_RUN_ARGS=auto N=1000 start=0 end=99 silent + +# The C++ compiler +ifneq (,$(shell which icc 2>/dev/null)) +CXX=icc +endif # which icc +ifeq ($(CXX),icc) +CXX0XFLAGS?=-std=c++0x -D_TBB_CPP0X +endif # icc + +ifeq ($(shell uname), Linux) +LIBS+= -lrt +endif + +all: release test + +release: *.cpp + $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb $(LIBS) $(CXX0XFLAGS) + +debug: *.cpp + $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(LIBS) $(CXX0XFLAGS) + +clean: + $(RM) $(PROG) *.o *.d + +test: + ./$(PROG) $(ARGS) + +perf_build: release + +perf_run: + ./$(PROG) $(PERF_RUN_ARGS) diff --git a/src/tbb/examples/concurrent_priority_queue/shortpath/Makefile.windows b/src/tbb/examples/concurrent_priority_queue/shortpath/Makefile.windows new file mode 100644 index 0000000..d77b56d --- /dev/null +++ b/src/tbb/examples/concurrent_priority_queue/shortpath/Makefile.windows @@ -0,0 +1,58 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Common Makefile that builds and runs example. + +# Just specify your program basename +PROG=shortpath +ARGS=4 N=1000 start=0 end=999 verbose +PERF_RUN_ARGS=auto N=1000 start=0 end=99 silent + +# Trying to find if icl.exe is set +CXX1 = $(TBB_CXX)- +CXX2 = $(CXX1:icl.exe-=icl.exe) +CXX = $(CXX2:-=cl.exe) + +# The C++ compiler options +MYCXXFLAGS = /TP /EHsc /W3 /nologo /D _CONSOLE /D _MBCS /D WIN32 /D _CRT_SECURE_NO_DEPRECATE $(CXXFLAGS) +MYLDFLAGS =/INCREMENTAL:NO /NOLOGO /DEBUG /FIXED:NO $(LDFLAGS) + +all: release test +release: + $(CXX) *.cpp /MD /O2 /D NDEBUG $(MYCXXFLAGS) /link tbb.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +debug: + $(CXX) *.cpp /MDd /Od /Zi /D TBB_USE_DEBUG /D _DEBUG $(MYCXXFLAGS) /link tbb_debug.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +clean: + @cmd.exe /C del $(PROG).exe *.obj *.?db *.manifest +test: + $(PROG) $(ARGS) +compiler_check: + @$(CXX) >nul 2>&1 || echo "$(CXX) command not found. Check if CXX=$(CXX) is set properly" + +perf_build: release + +perf_run: + $(PROG) $(PERF_RUN_ARGS) diff --git a/src/tbb/examples/concurrent_priority_queue/shortpath/index.html b/src/tbb/examples/concurrent_priority_queue/shortpath/index.html new file mode 100644 index 0000000..1262435 --- /dev/null +++ b/src/tbb/examples/concurrent_priority_queue/shortpath/index.html @@ -0,0 +1,82 @@ + + + +

Overview

+ +This directory contains a simple example that solves the single source +shortest path problem. It is parameterized by N, a number of nodes, +and a start and end node in [0..N). A graph is generated with N nodes +and some random number of connections between those nodes. A parallel +algorithm based on A* is used to find the shortest path. This +algorithm varies from serial A* in that it needs to add nodes back to +the open set when the g estimate (shortest path from start to the +node) is improved, even if the node has already been "visited". This +is because nodes are added and removed from the open-set in parallel, +resulting in some less optimal paths being explored. The open-set is +implemented with the concurrent_priority_queue. Note that since we +re-visit nodes, the f estimate (on which the priority queue is sorted) +is not technically needed, so we could use this same parallel +algorithm with just a concurrent_queue. However, keeping the f +estimate and using concurrent_priority_queue results in much better +performance. Silent mode prints run time only, regular mode prints +shortest path length, and verbose mode prints out the shortest path. +The generated graph follows a pattern in which the closer two pairs of +node ids are together, the fewer hops there are in a typical path +between those nodes. So, for example, the path between 5 and 7 likely +has few hops whereas 14 to 78 has more and 0 to 9999 has even more, +etc. + + +

Files

+
+
shortpath.cpp +
Driver. + +
Makefile +
Makefile for building example. + +
+ +

Directories

+
+
msvs +
Contains Microsoft* Visual Studio* 2008 workspace for building and running the example with the Intel® C++ compiler (Windows* systems only). +
xcode +
Contains Mac OS* Xcode* workspace for building and running the example (Mac OS* X systems only). +
+ +

To Build

+General build directions can be found here. +

+ +

Usage

+
+ +
shortpath -h +
Prints the help for command line options +
shortpath [#threads=value] [verbose] [silent] [N=value] [start=value] [end=value] [#threads] +
#threads is the number of threads to use; a range of the form low[:high] where low and optional high are non-negative integers, or 'auto' for the TBB default.
+ verbose print full path to screen
+ silent limits output to timing info; overrides verbose
+ N number of nodes in graph
+ start node to start path at
+ end node to end path at
+ + +
To run a short version of this example, e.g., for use with Intel® Parallel Inspector: +
Build a debug version of the example + (see the build directions). +
Run it with a small problem size and the desired number of threads, e.g., shortpath 4 N=20 start=0 end=19. +
+ +
+Up to parent directory +

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. + + diff --git a/src/tbb/examples/concurrent_priority_queue/shortpath/msvs/shortpath.icproj b/src/tbb/examples/concurrent_priority_queue/shortpath/msvs/shortpath.icproj new file mode 100644 index 0000000..38334ea --- /dev/null +++ b/src/tbb/examples/concurrent_priority_queue/shortpath/msvs/shortpath.icproj @@ -0,0 +1,11 @@ + + + + + diff --git a/src/tbb/examples/concurrent_priority_queue/shortpath/msvs/shortpath.vcproj b/src/tbb/examples/concurrent_priority_queue/shortpath/msvs/shortpath.vcproj new file mode 100644 index 0000000..e5463df --- /dev/null +++ b/src/tbb/examples/concurrent_priority_queue/shortpath/msvs/shortpath.vcproj @@ -0,0 +1,356 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/concurrent_priority_queue/shortpath/msvs/shortpath_cl.sln b/src/tbb/examples/concurrent_priority_queue/shortpath/msvs/shortpath_cl.sln new file mode 100644 index 0000000..cf1789a --- /dev/null +++ b/src/tbb/examples/concurrent_priority_queue/shortpath/msvs/shortpath_cl.sln @@ -0,0 +1,25 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shortpath", "shortpath.vcproj", "{3AA40693-F93D-4D4B-B32E-068F511A252A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|Win32.ActiveCfg = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|Win32.Build.0 = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|x64.ActiveCfg = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|x64.Build.0 = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|Win32.ActiveCfg = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|Win32.Build.0 = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|x64.ActiveCfg = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/concurrent_priority_queue/shortpath/msvs/shortpath_icl.sln b/src/tbb/examples/concurrent_priority_queue/shortpath/msvs/shortpath_icl.sln new file mode 100644 index 0000000..70881aa --- /dev/null +++ b/src/tbb/examples/concurrent_priority_queue/shortpath/msvs/shortpath_icl.sln @@ -0,0 +1,33 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "shortpath", "shortpath.icproj", "{D731702C-B704-468D-9497-A75EE0521C89}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D731702C-B704-468D-9497-A75EE0521C89}.Debug|Win32.ActiveCfg = Debug|Win32 + {D731702C-B704-468D-9497-A75EE0521C89}.Debug|Win32.Build.0 = Debug|Win32 + {D731702C-B704-468D-9497-A75EE0521C89}.Debug|x64.ActiveCfg = Debug|x64 + {D731702C-B704-468D-9497-A75EE0521C89}.Debug|x64.Build.0 = Debug|x64 + {D731702C-B704-468D-9497-A75EE0521C89}.Release|Win32.ActiveCfg = Release|Win32 + {D731702C-B704-468D-9497-A75EE0521C89}.Release|Win32.Build.0 = Release|Win32 + {D731702C-B704-468D-9497-A75EE0521C89}.Release|x64.ActiveCfg = Release|x64 + {D731702C-B704-468D-9497-A75EE0521C89}.Release|x64.Build.0 = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|x64.Build.0 = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|x64.ActiveCfg = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|Win32.Build.0 = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|Win32.ActiveCfg = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|x64.Build.0 = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|x64.ActiveCfg = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|Win32.Build.0 = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|Win32.ActiveCfg = Debug|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/concurrent_priority_queue/shortpath/shortpath.cpp b/src/tbb/examples/concurrent_priority_queue/shortpath/shortpath.cpp new file mode 100644 index 0000000..a28166e --- /dev/null +++ b/src/tbb/examples/concurrent_priority_queue/shortpath/shortpath.cpp @@ -0,0 +1,381 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include +#include +#include +#include "tbb/atomic.h" +#include "tbb/tick_count.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/task_group.h" +#include "tbb/concurrent_priority_queue.h" +#include "tbb/spin_mutex.h" +#include "tbb/parallel_for.h" +#include "tbb/blocked_range.h" +#include "../../common/utility/utility.h" +#include "../../common/utility/fast_random.h" + +#if defined(_MSC_VER) && defined(_Wp64) + // Workaround for overzealous compiler warnings in /Wp64 mode + #pragma warning (disable: 4267) +#endif /* _MSC_VER && _Wp64 */ + +#if __INTEL_COMPILER +#define __TBB_LAMBDAS_PRESENT ( _TBB_CPP0X && __INTEL_COMPILER > 1100 ) +#elif __GNUC__ +#define __TBB_LAMBDAS_PRESENT ( _TBB_CPP0X && __TBB_GCC_VERSION >= 40500 ) +#elif _MSC_VER +#define __TBB_LAMBDAS_PRESENT ( _MSC_VER>=1600 ) +#endif + +using namespace std; +using namespace tbb; + +struct point { + double x, y; + point() {} + point(double _x, double _y) : x(_x), y(_y) {} + point(const point& p) : x(p.x), y(p.y) {} +}; + +double get_distance(const point& p1, const point& p2) { + double xdiff=p1.x-p2.x, ydiff=p1.y-p2.y; + return sqrt(xdiff*xdiff + ydiff*ydiff); +} + +// generates random points on 2D plane within a box of maxsize width & height +point generate_random_point(utility::FastRandom& mr) { + const size_t maxsize=500; + double x = (double)(mr.get() % maxsize); + double y = (double)(mr.get() % maxsize); + return point(x,y); +} + +// weighted toss makes closer nodes (in the point vector) heavily connected +bool die_toss(size_t a, size_t b, utility::FastRandom& mr) { + int node_diff = std::abs((int)(a-b)); + // near nodes + if (node_diff < 16) return true; + // mid nodes + if (node_diff < 64) return ((int)mr.get() % 8 == 0); + // far nodes + if (node_diff < 512) return ((int)mr.get() % 16 == 0); + return false; +} + +typedef vector point_set; +typedef size_t vertex_id; +typedef std::pair vertex_rec; +typedef vector > edge_set; + +bool verbose = false; // prints bin details and other diagnostics to screen +bool silent = false; // suppress all output except for time +size_t N = 1000; // number of vertices +size_t src = 0; // start of path +size_t dst = N-1; // end of path +double INF=100000.0; // infinity +size_t grainsize = 16; // number of vertices per task on average +size_t max_spawn; // max tasks to spawn +atomic num_spawn; // number of active tasks + +point_set vertices; // vertices +edge_set edges; // edges +vector predecessor; // for recreating path from src to dst + +vector f_distance; // estimated distances at particular vertex +vector g_distance; // current shortest distances from src vertex +vector locks; // a lock for each vertex +task_group *sp_group; // task group for tasks executing sub-problems + +class compare_f { +public: + bool operator()(const vertex_rec& u, const vertex_rec& v) const { + return u.second>v.second; + } +}; + +concurrent_priority_queue open_set; // tentative vertices + +void shortpath_helper(); + +#if !__TBB_LAMBDAS_PRESENT +class shortpath_helper_functor { +public: + shortpath_helper_functor() {}; + void operator() () const { shortpath_helper(); } +}; +#endif + +void shortpath() { + g_distance[src] = 0.0; // src's distance from src is zero + f_distance[src] = get_distance(vertices[src], vertices[dst]); // estimate distance from src to dst + open_set.push(make_pair(src,f_distance[src])); // push src into open_set +#if __TBB_LAMBDAS_PRESENT + sp_group->run([](){ shortpath_helper(); }); +#else + sp_group->run( shortpath_helper_functor() ); +#endif + sp_group->wait(); +} + +void shortpath_helper() { + vertex_rec u_rec; + while (open_set.try_pop(u_rec)) { + vertex_id u = u_rec.first; + if (u==dst) continue; + double f = u_rec.second; + double old_g_u = 0.0; + { + spin_mutex::scoped_lock l(locks[u]); + if (f > f_distance[u]) continue; // prune search space + old_g_u = g_distance[u]; + } + for (size_t i=0; irun([]{ shortpath_helper(); }); +#else + sp_group->run( shortpath_helper_functor() ); +#endif + } + else --num_spawn; + } + } + } + --num_spawn; +} + +void make_path(vertex_id src, vertex_id dst, vector& path) { + vertex_id at = predecessor[dst]; + if (at == N) path.push_back(src); + else if (at == src) { path.push_back(src); path.push_back(dst); } + else { make_path(src, at, path); path.push_back(dst); } +} + +void print_path() { + vector path; + double path_length=0.0; + make_path(src, dst, path); + if (verbose) printf("\n "); + for (size_t i=0; i", (int)path[i]); + else printf("(%4d)\n", (int)path[i]); + } + } + if (verbose) printf("Total distance = %5.1f\n", path_length); + else if (!silent) printf(" %5.1f\n", path_length); +} + +int get_default_num_threads() { + static int threads = 0; + if (threads == 0) + threads = tbb::task_scheduler_init::default_num_threads(); + return threads; +} + +#if !__TBB_LAMBDAS_PRESENT +class gen_vertices { +public: + gen_vertices() {} + void operator() (blocked_range& r) const { + utility::FastRandom my_random((unsigned int)r.begin()); + for (size_t i=r.begin(); i!=r.end(); ++i) { + vertices[i] = generate_random_point(my_random); + } + } +}; + +class gen_edges { +public: + gen_edges() {} + void operator() (blocked_range& r) const { + utility::FastRandom my_random((unsigned int)r.begin()); + for (size_t i=r.begin(); i!=r.end(); ++i) { + for (size_t j=0; j& r) const { + for (size_t i=r.begin(); i!=r.end(); ++i) { + f_distance[i] = g_distance[i] = INF; + predecessor[i] = N; + } + } +}; +#endif + +void InitializeGraph() { + sp_group = new task_group; + vertices.resize(N); + edges.resize(N); + predecessor.resize(N); + g_distance.resize(N); + f_distance.resize(N); + locks.resize(N); + task_scheduler_init init(get_default_num_threads()); + if (verbose) printf("Generating vertices...\n"); +#if __TBB_LAMBDAS_PRESENT + parallel_for(blocked_range(0,N,64), + [&](blocked_range& r) { + utility::FastRandom my_random(r.begin()); + for (size_t i=r.begin(); i!=r.end(); ++i) { + vertices[i] = generate_random_point(my_random); + } + }, simple_partitioner()); +#else + parallel_for(blocked_range(0,N,64), gen_vertices(), simple_partitioner()); +#endif + if (verbose) printf("Generating edges...\n"); +#if __TBB_LAMBDAS_PRESENT + parallel_for(blocked_range(0,N,64), + [&](blocked_range& r) { + utility::FastRandom my_random(r.begin()); + for (size_t i=r.begin(); i!=r.end(); ++i) { + for (size_t j=0; j(0,N,64), gen_edges(), simple_partitioner()); +#endif + for (size_t i=0; i(0,N), + [&](blocked_range& r) { + for (size_t i=r.begin(); i!=r.end(); ++i) { + f_distance[i] = g_distance[i] = INF; + predecessor[i] = N; + } + }); +#else + parallel_for(blocked_range(0,N), reset_vertices()); +#endif +} + +int main(int argc, char *argv[]) { + try { + utility::thread_number_range threads(get_default_num_threads); + utility::parse_cli_arguments(argc, argv, + utility::cli_argument_pack() + //"-h" option for for displaying help is present implicitly + .positional_arg(threads,"#threads"," number of threads to use; a range of the " + "form low[:high]\n where low and optional high are " + "non-negative integers,\n or 'auto' for the TBB " + "default") + .arg(verbose,"verbose"," print diagnostic output to screen") + .arg(silent,"silent"," limits output to timing info; overrides verbose") + .arg(N,"N"," number of vertices") + .arg(src,"start"," start of path") + .arg(dst,"end"," end of path") + ); + if (silent) verbose = false; // make silent override verbose + else + printf("shortpath will run with %d vertices to find shortest path between vertices" + " %d and %d using %d:%d threads.\n", + (int)N, (int)src, (int)dst, (int)threads.first, (int)threads.last); + + if (dst >= N) { + if (verbose) + printf("end value %d is invalid for %d vertices; correcting to %d\n", (int)dst, (int)N, (int)N-1); + dst = N-1; + } + + num_spawn = 0; + max_spawn = N/grainsize; + tick_count t0, t1; + InitializeGraph(); + for (int n_thr=threads.first; n_thr<=threads.last; ++n_thr) { + ResetGraph(); + task_scheduler_init init(n_thr); + t0 = tick_count::now(); + shortpath(); + t1 = tick_count::now(); + if (!silent) { + if (predecessor[dst] != N) { + printf("%d threads: [%6.6f] The shortest path from vertex %d to vertex %d is:", + (int)n_thr, (t1-t0).seconds(), (int)src, (int)dst); + print_path(); + } + else { + printf("%d threads: [%6.6f] There is no path from vertex %d to vertex %d\n", + (int)n_thr, (t1-t0).seconds(), (int)src, (int)dst); + } + } else + utility::report_elapsed_time((t1-t0).seconds()); + } + return 0; + } catch(std::exception& e) { + cerr<<"error occurred. error text is :\"" </dev/null)) +CXX=icc +endif # which icc + +ifeq ($(shell uname), Linux) +LIBS+= -lrt +endif + +all: release test + +release: *.cpp + $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb $(LIBS) $(CXX0XFLAGS) + +debug: *.cpp + $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(LIBS) $(CXX0XFLAGS) + +clean: + $(RM) $(PROG) *.o *.d + +test: + ./$(PROG) $(ARGS) + +perf_build: release + +perf_run: + ./$(PROG) $(PERF_RUN_ARGS) diff --git a/src/tbb/examples/graph/binpack/Makefile.windows b/src/tbb/examples/graph/binpack/Makefile.windows new file mode 100644 index 0000000..9f8fcbe --- /dev/null +++ b/src/tbb/examples/graph/binpack/Makefile.windows @@ -0,0 +1,58 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Common Makefile that builds and runs example. + +# Just specify your program basename +PROG=binpack +ARGS= 4 N=1000 +PERF_RUN_ARGS=auto N=1000 silent + +# Trying to find if icl.exe is set +CXX1 = $(TBB_CXX)- +CXX2 = $(CXX1:icl.exe-=icl.exe) +CXX = $(CXX2:-=cl.exe) + +# The C++ compiler options +MYCXXFLAGS = /TP /EHsc /W3 /nologo /D _CONSOLE /D _MBCS /D WIN32 /D _CRT_SECURE_NO_DEPRECATE $(CXXFLAGS) +MYLDFLAGS =/INCREMENTAL:NO /NOLOGO /DEBUG /FIXED:NO $(LDFLAGS) + +all: release test +release: + $(CXX) *.cpp /MD /O2 /D NDEBUG $(MYCXXFLAGS) /link tbb.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +debug: + $(CXX) *.cpp /MDd /Od /Zi /D TBB_USE_DEBUG /D _DEBUG $(MYCXXFLAGS) /link tbb_debug.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +clean: + @cmd.exe /C del $(PROG).exe *.obj *.?db *.manifest +test: + $(PROG) $(ARGS) +compiler_check: + @$(CXX) >nul 2>&1 || echo "$(CXX) command not found. Check if CXX=$(CXX) is set properly" + +perf_build: release + +perf_run: + $(PROG) $(PERF_RUN_ARGS) diff --git a/src/tbb/examples/graph/binpack/binpack.cpp b/src/tbb/examples/graph/binpack/binpack.cpp new file mode 100644 index 0000000..5da84cf --- /dev/null +++ b/src/tbb/examples/graph/binpack/binpack.cpp @@ -0,0 +1,310 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + + +/* Bin-packing algorithm that attempts to use minimal number of bins B of + size V to contain N items of varying sizes. */ + +#include +#include +#include +#include "tbb/atomic.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/tick_count.h" +#include "tbb/flow_graph.h" +#include "../../common/utility/utility.h" + +using namespace std; +using namespace tbb; +using namespace tbb::flow; + +typedef size_t size_type; // to represent non-zero indices, capacities, etc. +typedef size_t value_type; // the type of items we are attempting to pack into bins +typedef vector bin; // we use a simple vector to represent a bin +// Our bin packers will be function nodes in the graph that take value_type items and +// return a dummy value. They will also implicitly send packed bins to the bin_buffer +// node, and unused items back to the value_pool node: +typedef function_node bin_packer; +// Items are placed into a pool that all bin packers grab from, represent by a queue_node: +typedef queue_node value_pool; +// Packed bins are placed in this buffer waiting to be serially printed and/or accounted for: +typedef buffer_node bin_buffer; +// Packed bins are taken from the_bin_buffer and processed by the_writer: +typedef function_node bin_writer; +// Items are injected into the graph when this node sends them to the_value_pool: +typedef source_node value_source; + +// User-specified globals with default values +size_type V = 42; // desired capacity for each bin +size_type N = 1000; // number of elements to generate +bool verbose = false; // prints bin details and other diagnostics to screen +bool silent = false; // suppress all output except for time +int num_bin_packers=-1; // number of concurrent bin packers in operation; default is #threads; + // larger values can result in more bins at less than full capacity +size_type optimality=1; // 1 (default) is highest the algorithm can obtain; larger numbers run faster + +// Calculated globals +size_type min_B; // lower bound on the optimal number of bins +size_type B; // the answer, i.e. number of bins used by the algorithm +size_type *input_array; // stores randomly generated input values +value_type item_sum; // sum of all randomly generated input values +atomic packed_sum; // sum of all values currently packed into all bins +atomic packed_items; // number of values currently packed into all bins +atomic active_bins; // number of active bin_packers +bin_packer **bins; // the array of bin packers + +// This class is the Body type for bin_packer +class bin_filler { + bin my_bin; // the current bin that this bin_filler is packing + size_type my_used; // capacity of bin used by current contents (not to be confused with my_bin.size()) + size_type relax, relax_val; // relaxation counter for determining when to settle for a non-full bin + bin_packer* my_bin_packer; // ptr to the bin packer that this body object is associated with + size_type bin_index; // index of the encapsulating bin packer in the global bins array + value_pool* the_value_pool; // ptr to the pool of items to pack + bin_buffer* the_bin_buffer; // ptr to the buffer of resulting bins + value_type looking_for; // the minimum size of item this bin_packer will accept + bool done; // flag to indicate that this binpacker has been deactivated + public: + bin_filler(size_t bidx, value_pool* q, bin_buffer* r) : + my_used(0), relax(0), relax_val(0), my_bin_packer(NULL), bin_index(bidx), the_value_pool(q), + the_bin_buffer(r), looking_for(V), done(false) {} + continue_msg operator()(const value_type& item) { + if (!my_bin_packer) my_bin_packer = bins[bin_index]; + if (done) the_value_pool->try_put(item); // this bin_packer is done packing items; put item back to pool + else if (item > V) { // signal that packed_sum has reached item_sum at some point + size_type remaining = active_bins--; + if (remaining == 1 && packed_sum == item_sum) { // this is the last bin and it has seen everything + // this bin_packer may not have seen everything, so stay active + if (my_used>0) the_bin_buffer->try_put(my_bin); + my_bin.clear(); + my_used = 0; + looking_for = V; + ++active_bins; + } + else if (remaining == 1) { // this is the last bin, but there are remaining items + the_value_pool->try_put(V+1); // send out signal + ++active_bins; + } + else if (remaining > 1) { // this is not the last bin; deactivate + if (my_used < V/(1+optimality*.1)) { // this bin is ill-utilized; throw back items and deactivate + packed_sum -= my_used; + packed_items -= my_bin.size(); + for (size_type i=0; itry_put(my_bin[i]); + the_value_pool->remove_successor(*my_bin_packer); // deactivate + done = true; + the_value_pool->try_put(V+1); // send out signal + } + else { // this bin is well-utilized; send out bin and deactivate + the_value_pool->remove_successor(*my_bin_packer); // build no more bins + done = true; + if (my_used>0) the_bin_buffer->try_put(my_bin); + the_value_pool->try_put(V+1); // send out signal + } + } + } + else if (item <= V-my_used && item >= looking_for) { // this item can be packed + my_bin.push_back(item); + my_used += item; + packed_sum += item; + ++packed_items; + looking_for = V-my_used; + relax = 0; + if (packed_sum == item_sum) { + the_value_pool->try_put(V+1); // send out signal + } + if (my_used == V) { + the_bin_buffer->try_put(my_bin); + my_bin.clear(); + my_used = 0; + looking_for = V; + } + } + else { // this item can't be packed; relax constraints + ++relax; + if (relax >= (N-packed_items)/optimality) { // this bin_packer has looked through enough items + relax = 0; + --looking_for; // accept a wider range of items + if (looking_for == 0 && my_used < V/(1+optimality*.1) && my_used > 0 && active_bins > 1) { + // this bin_packer is ill-utilized and can't find items; deactivate and throw back items + size_type remaining = active_bins--; + if (remaining > 1) { // not the last bin_packer + the_value_pool->remove_successor(*my_bin_packer); // deactivate + done = true; + } + else active_bins++; // can't deactivate last bin_packer + packed_sum -= my_used; + packed_items -= my_bin.size(); + for (size_type i=0; itry_put(my_bin[i]); + my_bin.clear(); + my_used = 0; + } + else if (looking_for == 0 && (my_used >= V/(1+optimality*.1) || active_bins == 1)) { + // this bin_packer can't find items but is well-utilized, so send it out and reset + the_bin_buffer->try_put(my_bin); + my_bin.clear(); + my_used = 0; + looking_for = V; + } + } + the_value_pool->try_put(item); // put unused item back to pool + } + return continue_msg(); // need to return something + } +}; + +// source node uses this to send the values to the value_pool +class item_generator { + size_type counter; +public: + item_generator() : counter(0) {} + bool operator()(value_type& m) { + if (counter my_max) my_max = sum; + avg += sum; + running_count += sum; + if (verbose) + cout << "]=" << sum << "; Done/Packed/Total cap: " << running_count << "/" << packed_sum << "/" << item_sum + << " items:" << item_count << "/" << packed_items << "/" << N << " B=" << B << endl; + if (item_count == N) { // should be the last; print stats + avg = avg/(double)B; + if (!silent) + cout << "SUMMARY: #Bins used: " << B << "; Avg size: " << avg << "; Max size: " << my_max + << "; Min size: " << my_min << "\n Lower bound on optimal #bins: " << min_B + << "; Start #bins: " << num_bin_packers << endl; + } + return continue_msg(); // need to return something + } +}; + +int get_default_num_threads() { + static int threads = 0; + if (threads == 0) + threads = tbb::task_scheduler_init::default_num_threads(); + return threads; +} + +int main(int argc, char *argv[]) { + try { + utility::thread_number_range threads(get_default_num_threads); + utility::parse_cli_arguments(argc, argv, + utility::cli_argument_pack() + //"-h" option for for displaying help is present implicitly + .positional_arg(threads,"#threads"," number of threads to use; a range of the " + "form low[:high]\n where low and optional high are " + "non-negative integers,\n or 'auto' for the TBB " + "default") + .arg(verbose,"verbose"," print diagnostic output to screen") + .arg(silent,"silent"," limits output to timing info; overrides verbose") + .arg(N,"N"," number of values to pack") + .arg(V,"V"," capacity of each bin") + .arg(num_bin_packers,"#packers"," number of concurrent bin packers to use " + "(default=#threads)") + .arg(optimality,"optimality","controls optimality of solution; 1 is highest, use\n" + " larger numbers for less optimal but faster solution") + ); + + if (silent) verbose = false; // make silent override verbose + // Generate random input data + srand(42); + input_array = new value_type[N]; + item_sum = 0; + for (size_type i=0; i + + +

Overview

+ +This directory contains a simple tbb::flow example that performs +binpacking of N integer values into a near-optimal number of bins +of capacity V. It features a source_node which passes randomly +generated integer values of size<=V to a queue_node. Multiple +function_nodes set about taking values from this queue_node and +packing them into bins according to a best-fit policy. Items that +cannot be made to fit are rejected and returned to the queue. When +a bin is packed as well as it can be, it is passed to a buffer_node +where it waits to be picked up by another function_node. This final +function nodes gathers stats about the bin and optionally prints its +contents. When all bins are accounted for, it optionally prints a +summary of the quality of the bin-packing. + +

Files

+
+
binpack.cpp +
Driver. + +
Makefile +
Makefile for building example. + +
+ +

Directories

+
+
msvs +
Contains Microsoft* Visual Studio* 2008 workspace for building and running the example with the Intel® C++ compiler (Windows* systems only). +
xcode +
Contains Xcode* IDE workspace for building and running the example (Mac OS* X systems only). +
+ +

To Build

+General build directions can be found here. +

+ +

Usage

+
+ +
binpack -h +
Prints the help for command line options +
binpack [#threads=value] [verbose] [silent] [N=value] [V=value] [#packers=value] [optimality=value] [#threads] +
#threads is the number of threads to use; a range of the form low[:high] where low and optional high are non-negative integers, or 'auto' for the TBB default.
+ verbose print diagnostic output to screen
+ silent limits output to timing info; overrides verbose
+ N number of values to pack
+ V capacity of each bin
+ #packers number of concurrent bin packers to use (default=#threads)
+ optimality controls optimality of solution; 1 is highest, use larger numbers for less optimal but faster solution
+ + +
To run a short version of this example, e.g., for use with Intel® Parallel Inspector: +
Build a debug version of the example + (see the build directions). +
Run it with a small problem size and the desired number of threads, e.g., binpack 4 N=100. +
+ +
+Up to parent directory +

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. + + diff --git a/src/tbb/examples/graph/binpack/msvs/binpack.icproj b/src/tbb/examples/graph/binpack/msvs/binpack.icproj new file mode 100644 index 0000000..74a4049 --- /dev/null +++ b/src/tbb/examples/graph/binpack/msvs/binpack.icproj @@ -0,0 +1,11 @@ + + + + + diff --git a/src/tbb/examples/graph/binpack/msvs/binpack.vcproj b/src/tbb/examples/graph/binpack/msvs/binpack.vcproj new file mode 100644 index 0000000..b93a9ae --- /dev/null +++ b/src/tbb/examples/graph/binpack/msvs/binpack.vcproj @@ -0,0 +1,356 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/graph/binpack/msvs/binpack_cl.sln b/src/tbb/examples/graph/binpack/msvs/binpack_cl.sln new file mode 100644 index 0000000..ac5cd2f --- /dev/null +++ b/src/tbb/examples/graph/binpack/msvs/binpack_cl.sln @@ -0,0 +1,25 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "binpack", "binpack.vcproj", "{C931C7A2-074E-4150-9E7A-39A03250411E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|Win32.ActiveCfg = Debug|Win32 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|Win32.Build.0 = Debug|Win32 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|x64.ActiveCfg = Debug|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|x64.Build.0 = Debug|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|Win32.ActiveCfg = Release|Win32 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|Win32.Build.0 = Release|Win32 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|x64.ActiveCfg = Release|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/graph/binpack/msvs/binpack_icl.sln b/src/tbb/examples/graph/binpack/msvs/binpack_icl.sln new file mode 100644 index 0000000..4f86c03 --- /dev/null +++ b/src/tbb/examples/graph/binpack/msvs/binpack_icl.sln @@ -0,0 +1,33 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "binpack", "binpack.icproj", "{CB292CD9-903E-464C-AAFE-E7A49003565C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Debug|Win32.Build.0 = Debug|Win32 + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Debug|x64.ActiveCfg = Debug|x64 + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Debug|x64.Build.0 = Debug|x64 + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Release|Win32.ActiveCfg = Release|Win32 + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Release|Win32.Build.0 = Release|Win32 + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Release|x64.ActiveCfg = Release|x64 + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Release|x64.Build.0 = Release|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|x64.Build.0 = Release|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|x64.ActiveCfg = Release|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|Win32.Build.0 = Release|Win32 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|Win32.ActiveCfg = Release|Win32 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|x64.Build.0 = Debug|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|x64.ActiveCfg = Debug|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|Win32.Build.0 = Debug|Win32 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|Win32.ActiveCfg = Debug|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/graph/binpack/xcode/binpack.xcodeproj/project.pbxproj b/src/tbb/examples/graph/binpack/xcode/binpack.xcodeproj/project.pbxproj new file mode 100644 index 0000000..18c42f4 --- /dev/null +++ b/src/tbb/examples/graph/binpack/xcode/binpack.xcodeproj/project.pbxproj @@ -0,0 +1,305 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 0E8A7311136F4A4600453C80 /* libtbb.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0E8A7310136F4A4600453C80 /* libtbb.dylib */; }; + 0E8A7325136F4D3600453C80 /* libtbb.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E8A7310136F4A4600453C80 /* libtbb.dylib */; }; + A1F593A60B8F042A00073279 /* binpack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1F593A50B8F042A00073279 /* binpack.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8DD76F690486A84900D96B5E /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = ""; + dstSubfolderSpec = 16; + files = ( + 0E8A7311136F4A4600453C80 /* libtbb.dylib in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0E8A7310136F4A4600453C80 /* libtbb.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = ../../../../lib/libtbb.dylib; sourceTree = ""; }; + 8DD76F6C0486A84900D96B5E /* Binpack */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Binpack; sourceTree = BUILT_PRODUCTS_DIR; }; + A1F593A50B8F042A00073279 /* binpack.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = binpack.cpp; path = ../binpack.cpp; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8DD76F660486A84900D96B5E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0E8A7325136F4D3600453C80 /* libtbb.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* Binpack */ = { + isa = PBXGroup; + children = ( + 08FB7795FE84155DC02AAC07 /* Source */, + A1F593B20B8F06F900073279 /* External Frameworks and Libraries */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + ); + name = Binpack; + sourceTree = ""; + }; + 08FB7795FE84155DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + A1F593A50B8F042A00073279 /* binpack.cpp */, + ); + name = Source; + sourceTree = ""; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8DD76F6C0486A84900D96B5E /* Binpack */, + ); + name = Products; + sourceTree = ""; + }; + A1F593B20B8F06F900073279 /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + 0E8A7310136F4A4600453C80 /* libtbb.dylib */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8DD76F620486A84900D96B5E /* Binpack */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "Binpack" */; + buildPhases = ( + 8DD76F640486A84900D96B5E /* Sources */, + 8DD76F660486A84900D96B5E /* Frameworks */, + 8DD76F690486A84900D96B5E /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Binpack; + productInstallPath = "$(HOME)/bin"; + productName = Binpack; + productReference = 8DD76F6C0486A84900D96B5E /* Binpack */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0410; + }; + buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "binpack" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 08FB7794FE84155DC02AAC07 /* Binpack */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DD76F620486A84900D96B5E /* Binpack */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 8DD76F640486A84900D96B5E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1F593A60B8F042A00073279 /* binpack.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1DEB923208733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = Binpack; + ZERO_LINK = NO; + }; + name = Debug; + }; + 1DEB923308733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = Binpack; + ZERO_LINK = NO; + }; + name = Release; + }; + 1DEB923608733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Debug; + }; + 1DEB923708733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Release; + }; + A1F593C60B8F0E6E00073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = Binpack; + ZERO_LINK = NO; + }; + name = Debug64; + }; + A1F593C70B8F0E6E00073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = Binpack; + ZERO_LINK = NO; + }; + name = Release64; + }; + A1F593C80B8F0E6E00073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-m64", + ); + OTHER_LDFLAGS = "-m64"; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Debug64; + }; + A1F593C90B8F0E6E00073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-m64", + ); + OTHER_LDFLAGS = "-m64"; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Release64; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "Binpack" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923208733DC60010E9CD /* Debug */, + A1F593C60B8F0E6E00073279 /* Debug64 */, + 1DEB923308733DC60010E9CD /* Release */, + A1F593C70B8F0E6E00073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "binpack" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923608733DC60010E9CD /* Debug */, + A1F593C80B8F0E6E00073279 /* Debug64 */, + 1DEB923708733DC60010E9CD /* Release */, + A1F593C90B8F0E6E00073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/src/tbb/examples/graph/dining_philosophers/Makefile b/src/tbb/examples/graph/dining_philosophers/Makefile new file mode 100644 index 0000000..89ad152 --- /dev/null +++ b/src/tbb/examples/graph/dining_philosophers/Makefile @@ -0,0 +1,55 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# GNU Makefile that builds and runs example. +PROG=dining_philosophers +ARGS= auto 5 +LIGHT_ARGS= auto 3 + +ifneq (,$(shell which icc 2>/dev/null)) +CXX=icc +endif # icc + +ifeq ($(shell uname), Linux) +LIBS+= -lrt +endif + +all: release test + +release: dining_philosophers.cpp + $(CXX) -O2 -DNDEBUG -D_CONSOLE $(CXXFLAGS) -o $(PROG) $^ -ltbb $(LIBS) + +debug: dining_philosophers.cpp + $(CXX) -O0 -D_CONSOLE -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(LIBS) + +clean: + rm -f $(PROG) *.o *.d + +test: + ./$(PROG) $(ARGS) + +light_test: + ./$(PROG) $(LIGHT_ARGS) diff --git a/src/tbb/examples/graph/dining_philosophers/Makefile.windows b/src/tbb/examples/graph/dining_philosophers/Makefile.windows new file mode 100644 index 0000000..f955886 --- /dev/null +++ b/src/tbb/examples/graph/dining_philosophers/Makefile.windows @@ -0,0 +1,54 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Common Makefile that builds and runs example. + +# Just specify your program basename +PROG=dining_philosophers +ARGS= auto 5 +LIGHT_ARGS= auto 3 + +# Trying to find if icl.exe is set +CXX1 = $(TBB_CXX)- +CXX2 = $(CXX1:icl.exe-=icl.exe) +CXX = $(CXX2:-=cl.exe) + +# The C++ compiler options +MYCXXFLAGS = /TP /EHsc /W3 /nologo /D _CONSOLE /D _MBCS /D WIN32 /D _CRT_SECURE_NO_DEPRECATE $(CXXFLAGS) +MYLDFLAGS =/INCREMENTAL:NO /NOLOGO /DEBUG /FIXED:NO $(LDFLAGS) + +all: release test +release: + $(CXX) ./dining_philosophers.cpp /MD /O2 /D NDEBUG $(MYCXXFLAGS) /link tbb.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +debug: + $(CXX) ./dining_philosophers.cpp /MDd /Od /Zi /D _DEBUG $(MYCXXFLAGS) /link tbb_debug.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +clean: + @cmd.exe /C del $(PROG).exe *.obj *.?db *.manifest +test: + $(PROG) $(ARGS) +light_test: + $(PROG) $(LIGHT_ARGS) + diff --git a/src/tbb/examples/graph/dining_philosophers/dining_philosophers.cpp b/src/tbb/examples/graph/dining_philosophers/dining_philosophers.cpp new file mode 100644 index 0000000..b1b447d --- /dev/null +++ b/src/tbb/examples/graph/dining_philosophers/dining_philosophers.cpp @@ -0,0 +1,324 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if _MSC_VER + // Suppress "decorated name length exceeded, name was truncated" warning + #pragma warning (disable: 4503) +#endif + +#include "tbb/flow_graph.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/tick_count.h" +#include "tbb/atomic.h" +#include "tbb/spin_mutex.h" +#include +#include "../../common/utility/utility.h" +#include +#include + +#if _WIN32 || _WIN64 +#include "windows.h" +#define SLEEP(a) Sleep(a*1000) +#else +#define SLEEP(a) sleep(a) +#endif + +// Each philosopher is an object, and is invoked in the think() function_node, the +// eat() function_node and forward() multifunction_node. +// +// The graph is constructed, and each think() function_node is started with a continue_msg. +// +// The philosopher will think, then gather two chopsticks, eat, place the chopsticks back, +// and if they have not completed the required number of cycles, will start to think() again +// by sending a continue_msg to their corresponding think() function_node. +// +// The reserving join has as its inputs the left and right chopstick queues an a queue +// that stores the continue_msg emitted by the function_node after think()ing is done. +// When all three inputs are available, a tuple of the inputs will be forwarded to the +// eat() function_node. The output of the eat() function_node is sent to the forward() +// multifunction_node. + +const int think_time = 1; +const int eat_time = 1; +const int num_times = 10; + +tbb::tick_count t0; +bool verbose = false; + +const char *names[] = { "Archimedes", "Bakunin", "Confucius", "Democritus", "Euclid" + , "Favorinus", "Geminus", "Heraclitus", "Ichthyas", "Jason of Nysa", + "Kant", "Lavrov", "Metrocles", "Nausiphanes", "Onatas", "Phaedrus", + "Quillot", "Russell", "Socrates", "Thales", "Udayana", + "Vernadsky", "Wittgenstein", "Xenophilus", "Yen Yuan", "Zenodotus" +}; +const int NumPhilosophers = sizeof(names) / sizeof(char*); + +struct RunOptions { + utility::thread_number_range threads; + int number_of_philosophers; + bool silent; + RunOptions(utility::thread_number_range threads_, int number_of_philosophers_, bool silent_) : + threads(threads_), number_of_philosophers(number_of_philosophers_), silent(silent_) { } +}; + +RunOptions ParseCommandLine(int argc, char *argv[]) { + int auto_threads = tbb::task_scheduler_init::default_num_threads(); + utility::thread_number_range threads(tbb::task_scheduler_init::default_num_threads, auto_threads, auto_threads); + int nPhilosophers = 5; + bool verbose = false; + char charbuf[100]; + std::sprintf(charbuf, "%d", NumPhilosophers); + std::string pCount = "how many philosophers, from 2-"; + pCount += charbuf; + + utility::cli_argument_pack cli_pack; + cli_pack.positional_arg(threads, "n-of_threads", "number of threads to use, a range of the form low[:high], where low and high are non-negative integers or 'auto' for the TBB default.") + .positional_arg(nPhilosophers, "n-of-philosophers", pCount) + .arg(verbose,"verbose","verbose output"); + utility::parse_cli_arguments(argc, argv, cli_pack); + if(nPhilosophers < 2 || nPhilosophers > NumPhilosophers) { + std::cout << "Number of philosophers (" << nPhilosophers << ") out of range [2:" << NumPhilosophers << "]\n"; + std::cout << cli_pack.usage_string(argv[0]) << std::flush; + std::exit(1); + } + return RunOptions(threads, nPhilosophers,!verbose); +} + + +tbb::spin_mutex my_mutex; + +class chopstick {}; + +using namespace tbb::flow; + +typedef std::tuple join_output; +typedef join_node< join_output, reserving > join_node_type; + +typedef function_node think_node_type; +typedef function_node eat_node_type; +typedef multifunction_node forward_node_type; + +class philosopher { +public: + + philosopher( const char *name ) : + my_name(name), my_count(num_times) { } + + ~philosopher() { + } + + void check(); + const char *name() const { return my_name; } + +private: + + friend std::ostream& operator<<(std::ostream& o, philosopher const &p); + + const char *my_name; + int my_count; + + friend class think_node_body; + friend class eat_node_body; + friend class forward_node_body; + + void think( ); + void eat(); + void forward( const continue_msg &in, forward_node_type::output_ports_type &out_ports ); +}; + +std::ostream& operator<<(std::ostream& o, philosopher const &p) { + o << "< philosopher[" << reinterpret_cast(const_cast(&p)) << "] " << p.name() + << ", my_count=" << p.my_count; + return o; +} + +class think_node_body { + philosopher& my_philosopher; +public: + think_node_body( philosopher &p ) : my_philosopher(p) { } + think_node_body( const think_node_body &other ) : my_philosopher(other.my_philosopher) { } + continue_msg operator()( continue_msg /*m*/) { + my_philosopher.think(); + return continue_msg(); + } +}; + +class eat_node_body { + philosopher &my_philosopher; +public: + eat_node_body( philosopher &p) : my_philosopher(p) {} + eat_node_body( const eat_node_body &other ) : my_philosopher(other.my_philosopher) { } + continue_msg operator()(const join_output &in) { + my_philosopher.eat(); + return continue_msg(); + } +}; + +class forward_node_body { + philosopher &my_philosopher; +public: + forward_node_body( philosopher &p) : my_philosopher(p) {} + forward_node_body( const forward_node_body &other ) : my_philosopher(other.my_philosopher) { } + void operator()( const continue_msg &in, forward_node_type::output_ports_type &out) { + my_philosopher.forward( in, out); + } +}; + +void philosopher::check() { + if ( my_count != 0 ) { + std::printf("ERROR: philosopher %s still had to run %d more times\n", name(), my_count); + std::exit(1); + } +} + +void philosopher::forward( const continue_msg &/*in*/, forward_node_type::output_ports_type &out_ports ) { + if(my_count < 0) abort(); + --my_count; + (void)std::get<1>(out_ports).try_put(chopstick()); + (void)std::get<2>(out_ports).try_put(chopstick()); + if (my_count > 0) { + (void)std::get<0>(out_ports).try_put(continue_msg()); //start thinking again + } else { + if(verbose) { + tbb::spin_mutex::scoped_lock lock(my_mutex); + std::printf("%s has left the building\n", name()); + } + } +} + +void philosopher::eat() { + if(verbose) { + tbb::spin_mutex::scoped_lock lock(my_mutex); + std::printf("%s eating\n", name()); + } + SLEEP(eat_time); + if(verbose) { + tbb::spin_mutex::scoped_lock lock(my_mutex); + std::printf("%s done eating\n", name()); + } +} + +void philosopher::think() { + if(verbose) { + tbb::spin_mutex::scoped_lock lock(my_mutex); + std::printf("%s thinking\n", name()); + } + SLEEP(think_time); + if(verbose) { + tbb::spin_mutex::scoped_lock lock(my_mutex); + std::printf("%s done thinking\n", name()); + } +} + +typedef queue_node thinking_done_type; + +int main(int argc, char *argv[]) { + try { + tbb::tick_count main_time = tbb::tick_count::now(); + int num_threads; + int num_philosophers; + + RunOptions options = ParseCommandLine(argc, argv); + num_philosophers = options.number_of_philosophers; + verbose = !options.silent; + + for(num_threads = options.threads.first; num_threads <= options.threads.last; ++num_threads) { + + tbb::task_scheduler_init init(num_threads); + + graph g; + + if(verbose) std::cout << std::endl << num_philosophers << " philosophers with " + << num_threads << " threads" << std::endl << std::endl; + t0 = tbb::tick_count::now(); + + std::vector > places(num_philosophers, queue_node(g)); + std::vector philosophers; + philosophers.reserve(num_philosophers); + std::vector think_nodes; + think_nodes.reserve(num_philosophers); + std::vector done_vector(num_philosophers, thinking_done_type(g)); + std::vector join_vector(num_philosophers,join_node_type(g)); + std::vector eat_nodes; + eat_nodes.reserve(num_philosophers); + std::vector forward_nodes; + forward_nodes.reserve(num_philosophers); + for ( int i = 0; i < num_philosophers; ++i ) { + places[i].try_put(chopstick()); + philosophers.push_back( philosopher( names[i] ) ); // allowed because of default generated assignment + if(verbose) { + tbb::spin_mutex::scoped_lock lock(my_mutex); + std::cout << "Built philosopher " << philosophers[i] << std::endl; + } + think_nodes.push_back(new think_node_type(g, unlimited, think_node_body(philosophers[i]))); + eat_nodes.push_back( new eat_node_type(g, unlimited, eat_node_body(philosophers[i]))); + forward_nodes.push_back( new forward_node_type(g, unlimited, forward_node_body(philosophers[i]))); + } + + // attach chopstick buffers and think function_nodes to joins + for(int i = 0; i < num_philosophers; ++i) { + think_nodes[i]->register_successor(done_vector[i]); + done_vector[i].register_successor(input_port<0>(join_vector[i])); + places[i].register_successor(input_port<1>(join_vector[i])); // left chopstick + places[(i+1) % num_philosophers].register_successor(input_port<2>(join_vector[i])); // right chopstick + // attach join to eat function_node + join_vector[i].register_successor(*(eat_nodes[i])); + // attach eat to forward mofn + make_edge(*(eat_nodes[i]), *(forward_nodes[i])); + // attach mofn to think function_nodes + output_port<0>(*(forward_nodes[i])).register_successor(*(think_nodes[i])); + // attach mofn to chopstick queues + output_port<1>(*(forward_nodes[i])).register_successor(places[i]); + output_port<2>(*(forward_nodes[i])).register_successor(places[(i+1) % num_philosophers]); + } + + // start all the philosophers thinking + for(int i = 0; i < num_philosophers; ++i) think_nodes[i]->try_put(continue_msg()); + + g.wait_for_all(); + + tbb::tick_count t1 = tbb::tick_count::now(); + if(verbose) std::cout << std::endl << num_philosophers << " philosophers with " + << num_threads << " threads have taken " << (t1-t0).seconds() << "seconds" << std::endl; + + for ( int i = 0; i < num_philosophers; ++i ) philosophers[i].check(); + + for(int i = 0; i < num_philosophers; ++i) { + delete think_nodes[i]; + delete eat_nodes[i]; + delete forward_nodes[i]; + } + } + + utility::report_elapsed_time((tbb::tick_count::now() - main_time).seconds()); + return 0; + } catch(std::exception& e) { + std::cerr<<"error occurred. error text is :\"" < + + +

Overview

+The Dining Philosophers problem demonstrates tbb::flow and the use of the reserving join node to +solve the potential deadlock. +
This program runs some number of philosophers in parallel, each thinking and then waiting for chopsticks +to be available before eating. Eating and thinking are implemented with sleep(). The chopstick positions are represented by a queue_node with one item. + +

Source Files

+
+
dining_philosophers.cpp +
Source code for the example. +
Makefile, Makefile.windows +
Makefiles for building example. +
+ +

Directories

+
+
src +
Contains source file mentioned above. +
msvs +
Contains Microsoft* Visual Studio* 2005 workspace for building and running the + example (Windows* systems only).
xcode +
Contains Xcode* IDE workspace for building and running the example (Mac OS* X + systems only).
+ +

To Build

+General build directions can be found here. +

+ +
+Up to parent directory +

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. + + + diff --git a/src/tbb/examples/graph/dining_philosophers/msvs/dining_philosophers.icproj b/src/tbb/examples/graph/dining_philosophers/msvs/dining_philosophers.icproj new file mode 100644 index 0000000..c27e179 --- /dev/null +++ b/src/tbb/examples/graph/dining_philosophers/msvs/dining_philosophers.icproj @@ -0,0 +1,11 @@ + + + + + diff --git a/src/tbb/examples/graph/dining_philosophers/msvs/dining_philosophers.vcproj b/src/tbb/examples/graph/dining_philosophers/msvs/dining_philosophers.vcproj new file mode 100644 index 0000000..d49c0b1 --- /dev/null +++ b/src/tbb/examples/graph/dining_philosophers/msvs/dining_philosophers.vcproj @@ -0,0 +1,356 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/graph/dining_philosophers/msvs/dining_philosophers_cl.sln b/src/tbb/examples/graph/dining_philosophers/msvs/dining_philosophers_cl.sln new file mode 100644 index 0000000..ed55faa --- /dev/null +++ b/src/tbb/examples/graph/dining_philosophers/msvs/dining_philosophers_cl.sln @@ -0,0 +1,25 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{3EC5FFF9-397F-47A7-BAF9-FDD602956644}") = "dining_philosophers", "dining_philosophers.vcproj", "{3894D1D2-A574-4937-AD56-726758EFE5B7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3894D1D2-A574-4937-AD56-726758EFE5B7}.Debug|Win32.ActiveCfg = Debug|Win32 + {3894D1D2-A574-4937-AD56-726758EFE5B7}.Debug|Win32.Build.0 = Debug|Win32 + {3894D1D2-A574-4937-AD56-726758EFE5B7}.Debug|x64.ActiveCfg = Debug|x64 + {3894D1D2-A574-4937-AD56-726758EFE5B7}.Debug|x64.Build.0 = Debug|x64 + {3894D1D2-A574-4937-AD56-726758EFE5B7}.Release|Win32.ActiveCfg = Release|Win32 + {3894D1D2-A574-4937-AD56-726758EFE5B7}.Release|Win32.Build.0 = Release|Win32 + {3894D1D2-A574-4937-AD56-726758EFE5B7}.Release|x64.ActiveCfg = Release|x64 + {3894D1D2-A574-4937-AD56-726758EFE5B7}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/graph/dining_philosophers/msvs/dining_philosophers_icl.sln b/src/tbb/examples/graph/dining_philosophers/msvs/dining_philosophers_icl.sln new file mode 100644 index 0000000..d86e64b --- /dev/null +++ b/src/tbb/examples/graph/dining_philosophers/msvs/dining_philosophers_icl.sln @@ -0,0 +1,33 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{b651a8c1-851b-4873-ab7a-428d9f15be2d}") = "dining_philosophers", "dining_philosophers.icproj", "{bbdf68ee-c8b2-4836-b3fc-385ce2265dc0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {bbdf68ee-c8b2-4836-b3fc-385ce2265dc0}.Debug|Win32.ActiveCfg = Debug|Win32 + {bbdf68ee-c8b2-4836-b3fc-385ce2265dc0}.Debug|Win32.Build.0 = Debug|Win32 + {bbdf68ee-c8b2-4836-b3fc-385ce2265dc0}.Debug|x64.ActiveCfg = Debug|x64 + {bbdf68ee-c8b2-4836-b3fc-385ce2265dc0}.Debug|x64.Build.0 = Debug|x64 + {bbdf68ee-c8b2-4836-b3fc-385ce2265dc0}.Release|Win32.ActiveCfg = Release|Win32 + {bbdf68ee-c8b2-4836-b3fc-385ce2265dc0}.Release|Win32.Build.0 = Release|Win32 + {bbdf68ee-c8b2-4836-b3fc-385ce2265dc0}.Release|x64.ActiveCfg = Release|x64 + {bbdf68ee-c8b2-4836-b3fc-385ce2265dc0}.Release|x64.Build.0 = Release|x64 + {3894d1d2-a574-4937-ad56-726758efe5b7}.Release|x64.Build.0 = Release|x64 + {3894d1d2-a574-4937-ad56-726758efe5b7}.Release|x64.ActiveCfg = Release|x64 + {3894d1d2-a574-4937-ad56-726758efe5b7}.Release|Win32.Build.0 = Release|Win32 + {3894d1d2-a574-4937-ad56-726758efe5b7}.Release|Win32.ActiveCfg = Release|Win32 + {3894d1d2-a574-4937-ad56-726758efe5b7}.Debug|x64.Build.0 = Debug|x64 + {3894d1d2-a574-4937-ad56-726758efe5b7}.Debug|x64.ActiveCfg = Debug|x64 + {3894d1d2-a574-4937-ad56-726758efe5b7}.Debug|Win32.Build.0 = Debug|Win32 + {3894d1d2-a574-4937-ad56-726758efe5b7}.Debug|Win32.ActiveCfg = Debug|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/graph/dining_philosophers/xcode/dining_philosophers.xcodeproj/project.pbxproj b/src/tbb/examples/graph/dining_philosophers/xcode/dining_philosophers.xcodeproj/project.pbxproj new file mode 100644 index 0000000..fc04882 --- /dev/null +++ b/src/tbb/examples/graph/dining_philosophers/xcode/dining_philosophers.xcodeproj/project.pbxproj @@ -0,0 +1,305 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + A1F593A60B8F042A00073279 /* dining_philosophers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1F593A50B8F042A00073279 /* dining_philosophers.cpp */; }; + A1F593B70B8F06F900073279 /* libtbb.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; + A1F593BB0B8F072500073279 /* libtbb.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8DD76F690486A84900D96B5E /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = ""; + dstSubfolderSpec = 16; + files = ( + A1F593BB0B8F072500073279 /* libtbb.dylib in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 8DD76F6C0486A84900D96B5E /* dining_philosophers */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dining_philosophers; sourceTree = BUILT_PRODUCTS_DIR; }; + A1F593A50B8F042A00073279 /* dining_philosophers.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = dining_philosophers.cpp; path = ../dining_philosophers.cpp; sourceTree = SOURCE_ROOT; }; + A1F593B30B8F06F900073279 /* libtbb.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtbb.dylib; path = ../../../../lib/libtbb.dylib; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8DD76F660486A84900D96B5E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A1F593B70B8F06F900073279 /* libtbb.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* dining_philosophers */ = { + isa = PBXGroup; + children = ( + 08FB7795FE84155DC02AAC07 /* Source */, + A1F593B20B8F06F900073279 /* External Frameworks and Libraries */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + ); + name = dining_philosophers; + sourceTree = ""; + }; + 08FB7795FE84155DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + A1F593A50B8F042A00073279 /* dining_philosophers.cpp */, + ); + name = Source; + sourceTree = ""; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8DD76F6C0486A84900D96B5E /* dining_philosophers */, + ); + name = Products; + sourceTree = ""; + }; + A1F593B20B8F06F900073279 /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + A1F593B30B8F06F900073279 /* libtbb.dylib */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8DD76F620486A84900D96B5E /* dining_philosophers */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "dining_philosophers" */; + buildPhases = ( + 8DD76F640486A84900D96B5E /* Sources */, + 8DD76F660486A84900D96B5E /* Frameworks */, + 8DD76F690486A84900D96B5E /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = dining_philosophers; + productInstallPath = "$(HOME)/bin"; + productName = dining_philosophers; + productReference = 8DD76F6C0486A84900D96B5E /* dining_philosophers */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0410; + }; + buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "dining_philosophers" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 08FB7794FE84155DC02AAC07 /* dining_philosophers */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DD76F620486A84900D96B5E /* dining_philosophers */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 8DD76F640486A84900D96B5E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1F593A60B8F042A00073279 /* dining_philosophers.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1DEB923208733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = dining_philosophers; + ZERO_LINK = NO; + }; + name = Debug; + }; + 1DEB923308733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = dining_philosophers; + ZERO_LINK = NO; + }; + name = Release; + }; + 1DEB923608733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Debug; + }; + 1DEB923708733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Release; + }; + A1F593C60B8F0E6E00073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = dining_philosophers; + ZERO_LINK = NO; + }; + name = Debug64; + }; + A1F593C70B8F0E6E00073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = dining_philosophers; + ZERO_LINK = NO; + }; + name = Release64; + }; + A1F593C80B8F0E6E00073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-m64", + ); + OTHER_LDFLAGS = "-m64"; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Debug64; + }; + A1F593C90B8F0E6E00073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-m64", + ); + OTHER_LDFLAGS = "-m64"; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Release64; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "dining_philosophers" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923208733DC60010E9CD /* Debug */, + A1F593C60B8F0E6E00073279 /* Debug64 */, + 1DEB923308733DC60010E9CD /* Release */, + A1F593C70B8F0E6E00073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "dining_philosophers" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923608733DC60010E9CD /* Debug */, + A1F593C80B8F0E6E00073279 /* Debug64 */, + 1DEB923708733DC60010E9CD /* Release */, + A1F593C90B8F0E6E00073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/src/tbb/examples/graph/index.html b/src/tbb/examples/graph/index.html new file mode 100644 index 0000000..dd28c46 --- /dev/null +++ b/src/tbb/examples/graph/index.html @@ -0,0 +1,28 @@ + + + +

Overview

+This directory has examples of tbb::flow. + +

Directories

+
+
dining_philosophers +
An implementation of dining philosophers in graph using the reserving join node. +
binpack +
A solution to the binpacking problem using a queue_node, a buffer_node and function_nodes. +
logic_sim +
A simplistic example of a collection of digital logic gates that can be easily composed into larger circuits. +
+ +
+Up to parent directory +

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. + + + diff --git a/src/tbb/examples/graph/logic_sim/D_latch.h b/src/tbb/examples/graph/logic_sim/D_latch.h new file mode 100644 index 0000000..15fd82e --- /dev/null +++ b/src/tbb/examples/graph/logic_sim/D_latch.h @@ -0,0 +1,64 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBBexample_graph_logicsim_dlatch_H +#define __TBBexample_graph_logicsim_dlatch_H 1 + +#include "basics.h" + +class D_latch { + broadcast_node D_port; + broadcast_node E_port; + not_gate a_not; + and_gate first_and; + and_gate second_and; + nor_gate first_nor; + nor_gate second_nor; + graph& my_graph; + public: + D_latch(graph& g) : my_graph(g), D_port(g), E_port(g), a_not(g), first_and(g), second_and(g), + first_nor(g), second_nor(g) + { + make_edge(D_port, a_not.get_in(0)); + make_edge(D_port, second_and.get_in(1)); + make_edge(E_port, first_and.get_in(1)); + make_edge(E_port, second_and.get_in(0)); + make_edge(a_not.get_out(), first_and.get_in(0)); + make_edge(first_and.get_out(), first_nor.get_in(0)); + make_edge(second_and.get_out(), second_nor.get_in(1)); + make_edge(first_nor.get_out(), second_nor.get_in(0)); + make_edge(second_nor.get_out(), first_nor.get_in(1)); + } + ~D_latch() {} + receiver& get_D() { return D_port; } + receiver& get_E() { return E_port; } + sender& get_Q() { return first_nor.get_out(); } + sender& get_notQ() { return second_nor.get_out(); } +}; + +#endif /* __TBBexample_graph_logicsim_dlatch_H */ diff --git a/src/tbb/examples/graph/logic_sim/Makefile b/src/tbb/examples/graph/logic_sim/Makefile new file mode 100644 index 0000000..c069095 --- /dev/null +++ b/src/tbb/examples/graph/logic_sim/Makefile @@ -0,0 +1,57 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# GNU Makefile that builds and runs example. +PROG=test_all +ARGS=4 +PERF_RUN_ARGS=auto silent + +# The C++ compiler +ifneq (,$(shell which icc 2>/dev/null)) +CXX=icc +endif # which icc + +ifeq ($(shell uname), Linux) +LIBS+= -lrt +endif + +all: release test + +release: *.cpp + $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $(PROG).cpp -ltbb $(LIBS) $(CXX0XFLAGS) + +debug: *.cpp + $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $(PROG).cpp -ltbb_debug $(LIBS) $(CXX0XFLAGS) +clean: + $(RM) $(PROG) *.o *.d + +test: + ./$(PROG) $(ARGS) + +perf_build: release + +perf_run: + ./$(PROG) $(PERF_RUN_ARGS) diff --git a/src/tbb/examples/graph/logic_sim/Makefile.windows b/src/tbb/examples/graph/logic_sim/Makefile.windows new file mode 100644 index 0000000..8e3bde4 --- /dev/null +++ b/src/tbb/examples/graph/logic_sim/Makefile.windows @@ -0,0 +1,61 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Common Makefile that builds and runs example. +PROG=test_all +ARGS=4 +PERF_RUN_ARGS=auto silent + +# Try to find icl.exe +CXX1 = $(TBB_CXX)- +CXX2 = $(CXX1:icl.exe-=icl.exe) +CXX = $(CXX2:-=cl.exe) + +# The C++ compiler options +MYCXXFLAGS = /TP /EHsc /W3 /nologo /D _CONSOLE /D _MBCS /D WIN32 /D _CRT_SECURE_NO_DEPRECATE $(CXXFLAGS) +MYLDFLAGS =/INCREMENTAL:NO /NOLOGO /DEBUG /FIXED:NO $(LDFLAGS) + +all: release test + +release: *.cpp + $(CXX) $(PROG).cpp /MD /O2 /D NDEBUG $(MYCXXFLAGS) /link tbb.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe + +debug: *.cpp + $(CXX) $(PROG).cpp /MDd /Od /Zi /D TBB_USE_DEBUG /D _DEBUG $(MYCXXFLAGS) /link tbb_debug.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe + +clean: + @cmd.exe /C del $(PROG).exe *.obj *.?db *.manifest + +test: + $(PROG) $(ARGS) + +compiler_check: + @$(CXX) >nul 2>&1 || echo "$(CXX) command not found. Check if CXX=$(CXX) is set properly" + +perf_build: release + +perf_run: + $(PROG) $(PERF_RUN_ARGS) diff --git a/src/tbb/examples/graph/logic_sim/basics.h b/src/tbb/examples/graph/logic_sim/basics.h new file mode 100644 index 0000000..00e91cc --- /dev/null +++ b/src/tbb/examples/graph/logic_sim/basics.h @@ -0,0 +1,543 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBBexample_graph_logicsim_basics_H +#define __TBBexample_graph_logicsim_basics_H 1 + +#define TBB_PREVIEW_GRAPH_NODES 1 + +#include +#include +#include "tbb/atomic.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/tick_count.h" +#include "tbb/flow_graph.h" +#include "../../common/utility/utility.h" + +#ifndef _WIN32 +#include +#include + +void rt_sleep(int msec) { + usleep(msec*1000); +} + +#else //_WIN32 + +#undef OLDUNIXTIME +#undef STDTIME + +#include + +void rt_sleep(int msec) { + Sleep(msec); +} +#endif /* _WIN32 */ + + +using namespace std; +using namespace tbb; +using namespace tbb::flow; + +typedef enum { low=0, high, undefined } signal_t; + +typedef tuple one_input; +typedef tuple two_input; +typedef tuple three_input; +typedef tuple four_input; + +template +struct gate_helper { + template + static inline receiver& get_inport(or_node& in_ports, int port) { + if (N-1 == port) return input_port(in_ports); + else return gate_helper::get_inport(in_ports, port); + } +}; +template <> +struct gate_helper<1> { + template + static inline receiver& get_inport(or_node& in_ports, int port) { + return input_port<0>(in_ports); + } +}; + +template +class gate { +protected: + typedef or_node input_port_t; + typedef multifunction_node< typename input_port_t::output_type, tuple > gate_fn_t; + typedef typename gate_fn_t::output_ports_type ports_type; +public: + static const int N = std::tuple_size::value; + + template + gate(graph& g, Body b) : my_graph(g), in_ports(g), gate_fn(g, 1, b) { + make_edge(in_ports, gate_fn); + } + virtual ~gate() {} + gate& operator=(const gate& src) { return *this; } + sender& get_out() { return output_port<0>(gate_fn); } + receiver& get_in(size_t port) { + return gate_helper::get_inport(in_ports, (int)port); + } +protected: + graph& my_graph; +private: + input_port_t in_ports; + gate_fn_t gate_fn; +}; + + +template +struct or_output_helper { + template + static inline signal_t get_or_output(const OrOutputType& out) { + if (N-1 == out.indx) return std::get(out.result); + else return or_output_helper::get_or_output(out); + } +}; +template <> +struct or_output_helper<1> { + template + static inline signal_t get_or_output(const OrOutputType& out) { + return std::get<0>(out.result); + } +}; + +// Input devices +class steady_signal { + graph& my_graph; + signal_t init_signal; + write_once_node signal_node; + public: + steady_signal(graph& g, signal_t v) : + my_graph(g), init_signal(v), signal_node(g) {} + steady_signal(const steady_signal& src) : + my_graph(src.my_graph), init_signal(src.init_signal), + signal_node(src.my_graph) {} + ~steady_signal() {} + // Assignment is ignored + steady_signal& operator=(const steady_signal& src) { return *this; } + sender& get_out() { return signal_node; } + void activate() { signal_node.try_put(init_signal); } +}; + +class pulse { + class clock_body { + size_t& ms; + int& reps; + signal_t val; + public: + clock_body(size_t& _ms, int& _reps) : ms(_ms), reps(_reps), val(low) {} + bool operator()(signal_t& out) { + rt_sleep((int)ms); + if (reps>0) --reps; + if (val==low) val = high; + else val = low; + out = val; + return reps>0 || reps == -1; + } + }; + graph& my_graph; + size_t ms, init_ms; + int reps, init_reps; + source_node clock_node; + +public: + pulse(graph& g, size_t _ms=1000, int _reps=-1) : + my_graph(g), ms(_ms), init_ms(_ms), reps(_reps), init_reps(_reps), + clock_node(g, clock_body(ms, reps), false) + {} + pulse(const pulse& src) : + my_graph(src.my_graph), ms(src.init_ms), init_ms(src.init_ms), + reps(src.init_reps), init_reps(src.init_reps), + clock_node(src.my_graph, clock_body(ms, reps), false) + {} + ~pulse() {} + // Assignment changes the behavior of LHS to that of the RHS, but doesn't change owning graph + pulse& operator=(const pulse& src) { + ms = src.ms; init_ms = src.init_ms; reps = src.reps; init_reps = src.init_reps; + return *this; + } + sender& get_out() { return clock_node; } + void activate() { clock_node.activate(); } + void reset() { reps = init_reps; } +}; + +class push_button { + graph& my_graph; + overwrite_node push_button_node; + public: + push_button(graph& g) : my_graph(g), push_button_node(g) { + push_button_node.try_put(low); + } + push_button(const push_button& src) : + my_graph(src.my_graph), push_button_node(src.my_graph) { + push_button_node.try_put(low); + } + ~push_button() {} + // Assignment is ignored + push_button& operator=(const push_button& src) { return *this; } + sender& get_out() { return push_button_node; } + void press() { push_button_node.try_put(high); } + void release() { push_button_node.try_put(low); } +}; + +class toggle { + graph& my_graph; + signal_t state; + overwrite_node toggle_node; + public: + toggle(graph& g) : my_graph(g), state(undefined), toggle_node(g) {} + toggle(const toggle& src) : my_graph(src.my_graph), state(undefined), + toggle_node(src.my_graph) {} + ~toggle() {} + // Assignment ignored + toggle& operator=(const toggle& src) { return *this; } + sender& get_out() { return toggle_node; } + void flip() { + if (state==high) state = low; + else state = high; + toggle_node.try_put(state); + } + void activate() { + state = low; + toggle_node.try_put(state); + } +}; + +// Basic gates +class buffer : public gate { + using gate::my_graph; + typedef gate::ports_type ports_type; + class buffer_body { + signal_t state; + bool touched; + public: + buffer_body() : state(undefined), touched(false) {} + void operator()(const input_port_t::output_type &v, ports_type& p) { + if (!touched || state != std::get<0>(v.result)) { + state = std::get<0>(v.result); + std::get<0>(p).try_put(state); + touched = true; + } + } + }; +public: + buffer(graph& g) : gate(g, buffer_body()) {} + buffer(const buffer& src) : gate(src.my_graph, buffer_body()) {} + ~buffer() {} +}; + +class not_gate : public gate { + using gate::my_graph; + typedef gate::ports_type ports_type; + class not_body { + signal_t port; + bool touched; + public: + not_body() : port(undefined), touched(false) {} + void operator()(const input_port_t::output_type &v, ports_type& p) { + if (!touched || port != std::get<0>(v.result)) { + port = std::get<0>(v.result); + signal_t state = low; + if (port==low) state = high; + std::get<0>(p).try_put(state); + touched = true; + } + } + }; + public: + not_gate(graph& g) : gate(g, not_body()) {} + not_gate(const not_gate& src) : gate(src.my_graph, not_body()) {} + ~not_gate() {} +}; + +template +class and_gate : public gate { + using gate::N; + using gate::my_graph; + typedef typename gate::ports_type ports_type; + typedef typename gate::input_port_t::output_type from_input; + typedef or_output_helper< gate::N > or_output; + class and_body { + signal_t *ports; + signal_t state; + bool touched; + public: + and_body() : state(undefined), touched(false) { + ports = new signal_t[N]; + for (int i=0; i(p).try_put(state); + touched = true; + } + } + }; + public: + and_gate(graph& g) : gate(g, and_body()) {} + and_gate(const and_gate& src) : gate(src.my_graph, and_body()) {} + ~and_gate() {} +}; + +template +class or_gate : public gate { + using gate::N; + using gate::my_graph; + typedef typename gate::ports_type ports_type; + typedef typename gate::input_port_t::output_type from_input; + typedef or_output_helper< gate::N > or_output; + class or_body { + signal_t *ports; + signal_t state; + bool touched; + public: + or_body() : state(undefined), touched(false) { + ports = new signal_t[N]; + for (int i=0; i(p).try_put(state); + touched = true; + } + } + }; +public: + or_gate(graph& g) : gate(g, or_body()) {} + or_gate(const or_gate& src) : gate(src.my_graph, or_body()) {} + ~or_gate() {} +}; + +template +class xor_gate : public gate { + using gate::N; + using gate::my_graph; + typedef typename gate::ports_type ports_type; + typedef typename gate::input_port_t input_port_t; + typedef or_output_helper< gate::N > or_output; + class xor_body { + signal_t *ports; + signal_t state; + bool touched; + public: + xor_body() : state(undefined), touched(false) { + ports = new signal_t[N]; + for (int i=0; i 0) { new_state = low; break; } + else if (ports[i] == high ) { ++highs; } + ++i; + } + if (!touched || state != new_state) { + state = new_state; + std::get<0>(p).try_put(state); + touched = true; + } + } + }; + public: + xor_gate(graph& g) : gate(g, xor_body()) {} + xor_gate(const xor_gate& src) : gate(src.my_graph, xor_body()) {} + ~xor_gate() {} +}; + +template +class nor_gate : public gate { + using gate::N; + using gate::my_graph; + typedef typename gate::ports_type ports_type; + typedef typename gate::input_port_t input_port_t; + typedef or_output_helper< gate::N > or_output; + class nor_body { + signal_t *ports; + signal_t state; + bool touched; + public: + nor_body() : state(undefined), touched(false) { + ports = new signal_t[N]; + for (int i=0; i(p).try_put(state); + touched = true; + } + } + }; + public: + nor_gate(graph& g) : gate(g, nor_body()) {} + nor_gate(const nor_gate& src) : gate(src.my_graph, nor_body()) {} + ~nor_gate() {} +}; + +// Output devices +class led { + class led_body { + signal_t &state; + string &label; + bool report_changes; + bool touched; + public: + led_body(signal_t &s, string &l, bool r) : + state(s), label(l), report_changes(r), touched(false) + {} + continue_msg operator()(signal_t b) { + if (!touched || b!=state) { + state = b; + if (state != undefined && report_changes) { + if (state) printf("%s: (*)\n", label.c_str()); + else printf("%s: ( )\n", label.c_str()); + } + touched = false; + } + return continue_msg(); + } + }; + graph& my_graph; + string label; + signal_t state; + bool report_changes; + function_node led_node; + public: + led(graph& g, string l, bool rc=false) : my_graph(g), label(l), state(undefined), + report_changes(rc), + led_node(g, 1, led_body(state, label, report_changes)) + {} + led(const led& src) : my_graph(src.my_graph), label(src.label), state(undefined), + report_changes(src.report_changes), + led_node(src.my_graph, 1, led_body(state, label, report_changes)) + {} + ~led() {} + // Assignment changes the behavior of LHS to that of the RHS, but doesn't change owning graph + // state is set to undefined so that next signal changes it + led& operator=(const led& src) { + label = src.label; state = undefined; report_changes = src.report_changes; + return *this; + } + receiver& get_in() { return led_node; } + void display() { + if (state == high) printf("%s: (*)\n", label.c_str()); + else if (state == low) printf("%s: ( )\n", label.c_str()); + else printf("%s: (u)\n", label.c_str()); + } + signal_t get_value() { return state; } +}; + +class digit : public gate { + using gate::my_graph; + typedef gate::ports_type ports_type; + typedef gate::input_port_t input_port_t; + class digit_body { + signal_t ports[4]; + unsigned int &state; + string &label; + bool& report_changes; + public: + digit_body(unsigned int &s, string &l, bool& r) : state(s), label(l), report_changes(r) { + for (int i=0; i(v.result); + else if (v.indx == 1) ports[1] = std::get<1>(v.result); + else if (v.indx == 2) ports[2] = std::get<2>(v.result); + else if (v.indx == 3) ports[3] = std::get<3>(v.result); + if (ports[0] == high) ++new_state; + if (ports[1] == high) new_state += 2; + if (ports[2] == high) new_state += 4; + if (ports[3] == high) new_state += 8; + if (state != new_state) { + state = new_state; + if (report_changes) { + printf("%s: %x\n", label.c_str(), state); + } + } + } + }; + string label; + unsigned int state; + bool report_changes; + public: + digit(graph& g, string l, bool rc=false) : + gate(g, digit_body(state, label, report_changes)), + label(l), state(0), report_changes(rc) {} + digit(const digit& src) : + gate(src.my_graph, digit_body(state, label, report_changes)), + label(src.label), state(0), report_changes(src.report_changes) {} + ~digit() {} + // Assignment changes the behavior of LHS to that of the RHS, but doesn't change owning graph. + // state is reset as in constructors + digit& operator=(const digit& src) { + label = src.label; state = 0; report_changes = src.report_changes; + return *this; + } + void display() { printf("%s: %x\n", label.c_str(), state); } + unsigned int get_value() { return state; } +}; + +#endif /* __TBBexample_graph_logicsim_basics_H */ diff --git a/src/tbb/examples/graph/logic_sim/four_bit_adder.h b/src/tbb/examples/graph/logic_sim/four_bit_adder.h new file mode 100644 index 0000000..ca4185b --- /dev/null +++ b/src/tbb/examples/graph/logic_sim/four_bit_adder.h @@ -0,0 +1,70 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBBexample_graph_logicsim_fba_H +#define __TBBexample_graph_logicsim_fba_H 1 + +#include "one_bit_adder.h" + +class four_bit_adder { + graph& my_graph; + std::vector four_adders; + public: + four_bit_adder(graph& g) : my_graph(g), four_adders(4, one_bit_adder(g)) { + make_connections(); + } + four_bit_adder(const four_bit_adder& src) : + my_graph(src.my_graph), four_adders(4, one_bit_adder(src.my_graph)) + { + make_connections(); + } + ~four_bit_adder() {} + receiver& get_A(size_t bit) { + return four_adders[bit].get_A(); + } + receiver& get_B(size_t bit) { + return four_adders[bit].get_B(); + } + receiver& get_CI() { + return four_adders[0].get_CI(); + } + sender& get_out(size_t bit) { + return four_adders[bit].get_out(); + } + sender& get_CO() { + return four_adders[3].get_CO(); + } +private: + void make_connections() { + make_edge(four_adders[0].get_CO(), four_adders[1].get_CI()); + make_edge(four_adders[1].get_CO(), four_adders[2].get_CI()); + make_edge(four_adders[2].get_CO(), four_adders[3].get_CI()); + } +}; + +#endif /* __TBBexample_graph_logicsim_fba_H */ diff --git a/src/tbb/examples/graph/logic_sim/index.html b/src/tbb/examples/graph/logic_sim/index.html new file mode 100644 index 0000000..d3940b4 --- /dev/null +++ b/src/tbb/examples/graph/logic_sim/index.html @@ -0,0 +1,67 @@ + + + +

Overview

+ +This directory contains a simple tbb::flow example that performs +simplistic digital logic simulations with basic logic gates that can +be easily composed to create more interesting circuits. It +exemplifies the multifunction_node and the or_node CPF, among others. + +

Files

+
+
basics.h +
Several I/O devices and basic gates. +
one_bit_adder.h +
A one-bit full adder composed of basic gates. +
four_bit_adder.h +
A four-bit full adder composed of one-bit adders. +
D_latch.h +
A D-latch composed of basic gates. +
test_all.cpp +
A simple test program that exercises the code in the headers. + +
Makefile +
Makefile for building example. + +
+ +

Directories

+
+
msvs +
Contains Microsoft* Visual Studio* 2008 workspace for building and running the example with the Intel® C++ compiler (Windows* systems only). +
xcode +
Contains Xcode* IDE workspace for building and running the example (Mac OS* X systems only). +
+ +

To Build

+General build directions can be found here. +

+ +

Usage

+
+ +
test_all -h +
Prints the help for command line options +
test_all [#threads=value] [verbose] [silent] [#threads] +
#threads is the number of threads to use; a range of the form low[:high] where low and optional high are non-negative integers, or 'auto' for the TBB default.
+ verbose print diagnostic output to screen
+ silent limits output to timing info; overrides verbose
+ +
To run a short version of this example, e.g., for use with Intel® Parallel Inspector: +
Build a debug version of the example + (see the build directions). +
Run it with the desired number of threads, e.g., test_all 4. +
+ +
+Up to parent directory +

+Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

+Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

+* Other names and brands may be claimed as the property of others. + + diff --git a/src/tbb/examples/graph/logic_sim/msvs/logic_sim_cl.sln b/src/tbb/examples/graph/logic_sim/msvs/logic_sim_cl.sln new file mode 100644 index 0000000..7865512 --- /dev/null +++ b/src/tbb/examples/graph/logic_sim/msvs/logic_sim_cl.sln @@ -0,0 +1,52 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_all", "test_all.vcproj", "{6E9B1702-78E0-4D64-B771-8B274D963B58}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6E9B1702-78E0-4D64-B771-8B274D963B58}.Debug|Win32.ActiveCfg = Debug|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.Debug|Win32.Build.0 = Debug|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.Debug|x64.ActiveCfg = Debug|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.Debug|x64.Build.0 = Debug|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.Release|Win32.ActiveCfg = Release|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.Release|Win32.Build.0 = Release|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.Release|x64.ActiveCfg = Release|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.Release|x64.Build.0 = Release|x64 + + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.Debug|Win32.ActiveCfg = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.Debug|Win32.Build.0 = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.Debug|x64.ActiveCfg = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.Debug|x64.Build.0 = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.Release|Win32.ActiveCfg = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.Release|Win32.Build.0 = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.Release|x64.ActiveCfg = Release|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.Release|x64.Build.0 = Release|x64 + + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.Debug|Win32.ActiveCfg = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.Debug|Win32.Build.0 = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.Debug|x64.ActiveCfg = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.Debug|x64.Build.0 = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.Release|Win32.ActiveCfg = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.Release|Win32.Build.0 = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.Release|x64.ActiveCfg = Release|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.Release|x64.Build.0 = Release|x64 + + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.Debug|Win32.ActiveCfg = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.Debug|Win32.Build.0 = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.Debug|x64.ActiveCfg = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.Debug|x64.Build.0 = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.Release|Win32.ActiveCfg = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.Release|Win32.Build.0 = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.Release|x64.ActiveCfg = Release|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/graph/logic_sim/msvs/logic_sim_icl.sln b/src/tbb/examples/graph/logic_sim/msvs/logic_sim_icl.sln new file mode 100644 index 0000000..b62ecdd --- /dev/null +++ b/src/tbb/examples/graph/logic_sim/msvs/logic_sim_icl.sln @@ -0,0 +1,132 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "test_all", "test_all.icproj", "{2D08E05F-D0E0-48A7-9597-28B95ACE70B6}" + ProjectSection(ProjectDependencies) = postProject + {5F685DBD-9A04-4E94-A1CA-FC48FE799830} = {5F685DBD-9A04-4E94-A1CA-FC48FE799830} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + DD Debug|Win32 = DD Debug|Win32 + DD Debug|x64 = DD Debug|x64 + DD Release|Win32 = DD Release|Win32 + DD Release|x64 = DD Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.DD Debug|Win32.Build.0 = DDDebug|Win32 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.DD Debug|x64.Build.0 = DDDebug|x64 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.DD Release|Win32.Build.0 = DDRelease|Win32 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.DD Release|x64.ActiveCfg = DDRelease|x64 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.DD Release|x64.Build.0 = DDRelease|x64 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.GDI Debug|Win32.Build.0 = Debug|Win32 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.GDI Debug|x64.ActiveCfg = Debug|x64 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.GDI Debug|x64.Build.0 = Debug|x64 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}._GDI Release|Win32.ActiveCfg = Release|Win32 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}._GDI Release|Win32.Build.0 = Release|Win32 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}._GDI Release|x64.ActiveCfg = Release|x64 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}._GDI Release|x64.Build.0 = Release|x64 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.DD Debug|Win32.Build.0 = DDDebug|Win32 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.DD Debug|x64.Build.0 = DDDebug|x64 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.DD Release|Win32.Build.0 = DDRelease|Win32 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.DD Release|x64.ActiveCfg = DDRelease|x64 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.DD Release|x64.Build.0 = DDRelease|x64 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.GDI Debug|Win32.Build.0 = Debug|Win32 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.GDI Debug|x64.ActiveCfg = Debug|x64 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.GDI Debug|x64.Build.0 = Debug|x64 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}._GDI Release|Win32.ActiveCfg = Release|Win32 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}._GDI Release|Win32.Build.0 = Release|Win32 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}._GDI Release|x64.ActiveCfg = Release|x64 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}._GDI Release|x64.Build.0 = Release|x64 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.DD Debug|Win32.Build.0 = DDDebug|Win32 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.DD Debug|x64.Build.0 = DDDebug|x64 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.DD Release|Win32.Build.0 = DDRelease|Win32 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.DD Release|x64.ActiveCfg = DDRelease|x64 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.DD Release|x64.Build.0 = DDRelease|x64 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.GDI Debug|Win32.Build.0 = Debug|Win32 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.GDI Debug|x64.ActiveCfg = Debug|x64 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.GDI Debug|x64.Build.0 = Debug|x64 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}._GDI Release|Win32.ActiveCfg = Release|Win32 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}._GDI Release|Win32.Build.0 = Release|Win32 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}._GDI Release|x64.ActiveCfg = Release|x64 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}._GDI Release|x64.Build.0 = Release|x64 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.DD Debug|Win32.Build.0 = DDDebug|Win32 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.DD Debug|x64.Build.0 = DDDebug|x64 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.DD Release|Win32.Build.0 = DDRelease|Win32 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.DD Release|x64.ActiveCfg = DDRelease|x64 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.DD Release|x64.Build.0 = DDRelease|x64 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.GDI Debug|Win32.Build.0 = Debug|Win32 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.GDI Debug|x64.ActiveCfg = Debug|x64 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.GDI Debug|x64.Build.0 = Debug|x64 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}._GDI Release|Win32.ActiveCfg = Release|Win32 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}._GDI Release|Win32.Build.0 = Release|Win32 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}._GDI Release|x64.ActiveCfg = Release|x64 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}._GDI Release|x64.Build.0 = Release|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.DD Debug|Win32.ActiveCfg = Debug|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.DD Debug|x64.ActiveCfg = Debug|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.DD Release|Win32.ActiveCfg = Release|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.DD Release|x64.ActiveCfg = Release|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.GDI Debug|Win32.Build.0 = Debug|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.GDI Debug|x64.ActiveCfg = Debug|x64 +y {6E9B1702-78E0-4D64-B771-8B274D963B58}.GDI Debug|x64.Build.0 = Debug|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}._GDI Release|Win32.ActiveCfg = Release|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}._GDI Release|Win32.Build.0 = Release|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}._GDI Release|x64.ActiveCfg = Release|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}._GDI Release|x64.Build.0 = Release|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.DD Debug|Win32.ActiveCfg = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.DD Debug|x64.ActiveCfg = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.DD Release|Win32.ActiveCfg = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.DD Release|x64.ActiveCfg = Release|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.GDI Debug|Win32.Build.0 = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.GDI Debug|x64.ActiveCfg = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.GDI Debug|x64.Build.0 = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}._GDI Release|Win32.ActiveCfg = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}._GDI Release|Win32.Build.0 = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}._GDI Release|x64.ActiveCfg = Release|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}._GDI Release|x64.Build.0 = Release|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.DD Debug|Win32.ActiveCfg = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.DD Debug|x64.ActiveCfg = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.DD Release|Win32.ActiveCfg = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.DD Release|x64.ActiveCfg = Release|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.GDI Debug|Win32.Build.0 = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.GDI Debug|x64.ActiveCfg = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.GDI Debug|x64.Build.0 = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}._GDI Release|Win32.ActiveCfg = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}._GDI Release|Win32.Build.0 = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}._GDI Release|x64.ActiveCfg = Release|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}._GDI Release|x64.Build.0 = Release|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.DD Debug|Win32.ActiveCfg = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.DD Debug|x64.ActiveCfg = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.DD Release|Win32.ActiveCfg = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.DD Release|x64.ActiveCfg = Release|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.GDI Debug|Win32.Build.0 = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.GDI Debug|x64.ActiveCfg = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.GDI Debug|x64.Build.0 = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}._GDI Release|Win32.ActiveCfg = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}._GDI Release|Win32.Build.0 = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}._GDI Release|x64.ActiveCfg = Release|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}._GDI Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/graph/logic_sim/msvs/test_all.icproj b/src/tbb/examples/graph/logic_sim/msvs/test_all.icproj new file mode 100644 index 0000000..f10414a --- /dev/null +++ b/src/tbb/examples/graph/logic_sim/msvs/test_all.icproj @@ -0,0 +1,11 @@ + + + + + diff --git a/src/tbb/examples/graph/logic_sim/msvs/test_all.vcproj b/src/tbb/examples/graph/logic_sim/msvs/test_all.vcproj new file mode 100644 index 0000000..2a258a8 --- /dev/null +++ b/src/tbb/examples/graph/logic_sim/msvs/test_all.vcproj @@ -0,0 +1,356 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/graph/logic_sim/one_bit_adder.h b/src/tbb/examples/graph/logic_sim/one_bit_adder.h new file mode 100644 index 0000000..1f3ea08 --- /dev/null +++ b/src/tbb/examples/graph/logic_sim/one_bit_adder.h @@ -0,0 +1,82 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBBexample_graph_logicsim_oba_H +#define __TBBexample_graph_logicsim_oba_H 1 + +#include "basics.h" + +class one_bit_adder { + broadcast_node A_port; + broadcast_node B_port; + broadcast_node CI_port; + xor_gate FirstXOR; + xor_gate SecondXOR; + and_gate FirstAND; + and_gate SecondAND; + or_gate FirstOR; + graph& my_graph; +public: + one_bit_adder(graph& g) : my_graph(g), A_port(g), B_port(g), CI_port(g), FirstXOR(g), + SecondXOR(g), FirstAND(g), SecondAND(g), FirstOR(g) { + make_connections(); + } + one_bit_adder(const one_bit_adder& src) : + my_graph(src.my_graph), A_port(src.my_graph), B_port(src.my_graph), + CI_port(src.my_graph), FirstXOR(src.my_graph), SecondXOR(src.my_graph), + FirstAND(src.my_graph), SecondAND(src.my_graph), FirstOR(src.my_graph) + { + make_connections(); + } + + ~one_bit_adder() {} + receiver& get_A() { return A_port; } + receiver& get_B() { return B_port; } + receiver& get_CI() { return CI_port; } + sender& get_out() { + return SecondXOR.get_out(); + } + sender& get_CO() { + return FirstOR.get_out(); + } +private: + void make_connections() { + make_edge(A_port, FirstXOR.get_in(0)); + make_edge(A_port, FirstAND.get_in(0)); + make_edge(B_port, FirstXOR.get_in(1)); + make_edge(B_port, FirstAND.get_in(1)); + make_edge(CI_port, SecondXOR.get_in(1)); + make_edge(CI_port, SecondAND.get_in(1)); + make_edge(FirstXOR.get_out(), SecondXOR.get_in(0)); + make_edge(FirstXOR.get_out(), SecondAND.get_in(0)); + make_edge(SecondAND.get_out(), FirstOR.get_in(0)); + make_edge(FirstAND.get_out(), FirstOR.get_in(1)); + } +}; + +#endif /* __TBBexample_graph_logicsim_oba_H */ diff --git a/src/tbb/examples/graph/logic_sim/test_all.cpp b/src/tbb/examples/graph/logic_sim/test_all.cpp new file mode 100644 index 0000000..719d950 --- /dev/null +++ b/src/tbb/examples/graph/logic_sim/test_all.cpp @@ -0,0 +1,580 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if _MSC_VER +#pragma warning (disable: 4503) // Suppress "decorated name length exceeded, name was truncated" warning +#endif + +#include "basics.h" +#include "one_bit_adder.h" +#include "four_bit_adder.h" +#include "D_latch.h" +#include + +// User-specified globals with default values +bool verbose = false; // prints bin details and other diagnostics to screen +bool silent = false; // suppress all output except for time + +int get_default_num_threads() { + static int threads = 0; + if (threads == 0) + threads = tbb::task_scheduler_init::default_num_threads(); + return threads; +} + +int main(int argc, char *argv[]) { + try { + utility::thread_number_range threads(get_default_num_threads); + utility::parse_cli_arguments(argc, argv, + utility::cli_argument_pack() + //"-h" option for for displaying help is present implicitly + .positional_arg(threads,"#threads"," number of threads to use; a range of the " + "form low[:high]\n where low and optional high are " + "non-negative integers,\n or 'auto' for the TBB " + "default") + .arg(verbose,"verbose"," print diagnostic output to screen") + .arg(silent,"silent"," limits output to timing info; overrides verbose") + ); + + if (silent) verbose = false; // make silent override verbose + + tick_count start = tick_count::now(); + for(int p = threads.first; p <= threads.last; ++p ) { + task_scheduler_init init(p); + if (!silent) cout << "graph test running on " << p << " threads.\n"; + + graph g; + + { // test buffer: 0, 1 + buffer b(g); + toggle input(g); + led output(g, "OUTPUT", false); // false means we will explicitly call display to see LED + + make_edge(input.get_out(), b.get_in(0)); + make_edge(b.get_out(), output.get_in()); + + if (!silent) printf("Testing buffer...\n"); + input.activate(); // 0 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == low); + input.flip(); // 1 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == high); + } + + { // test not_gate: 0, 1 + not_gate n(g); + toggle input(g); + led output(g, "OUTPUT", false); + + make_edge(input.get_out(), n.get_in(0)); + make_edge(n.get_out(), output.get_in()); + + if (!silent) printf("Testing not_gate...\n"); + input.activate(); // 0 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == high); + input.flip(); // 1 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == low); + } + + { // test two-input and_gate: 00, 01, 10, 11 + and_gate a(g); + toggle input0(g); + toggle input1(g); + led output(g, "OUTPUT", false); + + make_edge(input0.get_out(), a.get_in(0)); + make_edge(input1.get_out(), a.get_in(1)); + make_edge(a.get_out(), output.get_in()); + + if (!silent) printf("Testing and_gate...\n"); + input1.activate(); input0.activate(); // 0 0 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == low); + input0.flip(); // 0 1 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == low); + input1.flip(); input0.flip(); // 1 0 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == low); + input0.flip(); // 1 1 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == high); + } + + { // test three-input or_gate: 000, 001, 010, 100, 011, 101, 110, 111 + or_gate o(g); + toggle input0(g); + toggle input1(g); + toggle input2(g); + led output(g, "OUTPUT", false); + + make_edge(input0.get_out(), o.get_in(0)); + make_edge(input1.get_out(), o.get_in(1)); + make_edge(input2.get_out(), o.get_in(2)); + make_edge(o.get_out(), output.get_in()); + + if (!silent) printf("Testing or_gate...\n"); + input2.activate(); input1.activate(); input0.activate(); // 0 0 0 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == low); + input0.flip(); // 0 0 1 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == high); + input1.flip(); input0.flip(); // 0 1 0 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == high); + input2.flip(); input1.flip(); // 1 0 0 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == high); + input2.flip(); input1.flip(); input0.flip(); // 0 1 1 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == high); + input2.flip(); input1.flip(); // 1 0 1 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == high); + input1.flip(); input0.flip(); // 1 1 0 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == high); + input0.flip(); // 1 1 1 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == high); + } + + { // test two-input xor_gate: 00, 01, 10, 11 + xor_gate x(g); + toggle input0(g); + toggle input1(g); + led output(g, "OUTPUT", false); + + make_edge(input0.get_out(), x.get_in(0)); + make_edge(input1.get_out(), x.get_in(1)); + make_edge(x.get_out(), output.get_in()); + + if (!silent) printf("Testing xor_gate...\n"); + input1.activate(); input0.activate(); // 0 0 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == low); + input0.flip(); // 0 1 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == high); + input1.flip(); input0.flip(); // 1 0 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == high); + input0.flip(); // 1 1 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == low); + } + + + { // test two-input nor_gate: 00, 01, 10, 11 + nor_gate n(g); + toggle input0(g); + toggle input1(g); + led output(g, "OUTPUT", false); + + make_edge(input0.get_out(), n.get_in(0)); + make_edge(input1.get_out(), n.get_in(1)); + make_edge(n.get_out(), output.get_in()); + + if (!silent) printf("Testing nor_gate...\n"); + input1.activate(); input0.activate(); // 0 0 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == high); + input0.flip(); // 0 1 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == low); + input1.flip(); input0.flip(); // 1 0 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == low); + input0.flip(); // 1 1 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == low); + } + + { // test steady_signal and digit + steady_signal input0(g, high); + steady_signal input1(g, low); + and_gate a(g); + or_gate o(g); + xor_gate x(g); + nor_gate n(g); + digit output(g, "OUTPUT", false); + + make_edge(input0.get_out(), a.get_in(0)); + make_edge(input1.get_out(), a.get_in(1)); + make_edge(a.get_out(), output.get_in(0)); + + make_edge(input0.get_out(), o.get_in(0)); + make_edge(input1.get_out(), o.get_in(1)); + make_edge(o.get_out(), output.get_in(1)); + + make_edge(input0.get_out(), x.get_in(0)); + make_edge(input1.get_out(), x.get_in(1)); + make_edge(x.get_out(), output.get_in(2)); + + make_edge(input0.get_out(), n.get_in(0)); + make_edge(input1.get_out(), n.get_in(1)); + make_edge(n.get_out(), output.get_in(3)); + + if (!silent) printf("Testing steady_signal...\n"); + input0.activate(); // 1 + input1.activate(); // 0 + g.wait_for_all(); + if (!silent) output.display(); + assert(output.get_value() == 6); + } + + { // test push_button + push_button p(g); + buffer b(g); + led output(g, "OUTPUT", !silent); // true means print all LED state changes + + make_edge(p.get_out(), b.get_in(0)); + make_edge(b.get_out(), output.get_in()); + + if (!silent) printf("Testing push_button...\n"); + p.press(); + p.release(); + p.press(); + p.release(); + g.wait_for_all(); + } + + { // test one_bit_adder + one_bit_adder my_adder(g); + toggle A(g); + toggle B(g); + toggle CarryIN(g); + led Sum(g, "SUM"); + led CarryOUT(g, "CarryOUT"); + + make_edge(A.get_out(), my_adder.get_A()); + make_edge(B.get_out(), my_adder.get_B()); + make_edge(CarryIN.get_out(), my_adder.get_CI()); + make_edge(my_adder.get_out(), Sum.get_in()); + make_edge(my_adder.get_CO(), CarryOUT.get_in()); + + A.activate(); + B.activate(); + CarryIN.activate(); + + if (!silent) printf("A on\n"); + A.flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == high) && (CarryOUT.get_value() == low)); + + if (!silent) printf("A off\n"); + A.flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == low) && (CarryOUT.get_value() == low)); + + if (!silent) printf("B on\n"); + B.flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == high) && (CarryOUT.get_value() == low)); + if (!silent) printf("B off\n"); + B.flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == low) && (CarryOUT.get_value() == low)); + + if (!silent) printf("CarryIN on\n"); + CarryIN.flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == high) && (CarryOUT.get_value() == low)); + if (!silent) printf("CarryIN off\n"); + CarryIN.flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == low) && (CarryOUT.get_value() == low)); + + if (!silent) printf("A&B on\n"); + A.flip(); + B.flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == low) && (CarryOUT.get_value() == high)); + if (!silent) printf("A&B off\n"); + A.flip(); + B.flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == low) && (CarryOUT.get_value() == low)); + + if (!silent) printf("A&CarryIN on\n"); + A.flip(); + CarryIN.flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == low) && (CarryOUT.get_value() == high)); + if (!silent) printf("A&CarryIN off\n"); + A.flip(); + CarryIN.flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == low) && (CarryOUT.get_value() == low)); + + if (!silent) printf("B&CarryIN on\n"); + B.flip(); + CarryIN.flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == low) && (CarryOUT.get_value() == high)); + if (!silent) printf("B&CarryIN off\n"); + B.flip(); + CarryIN.flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == low) && (CarryOUT.get_value() == low)); + + if (!silent) printf("A&B&CarryIN on\n"); + A.flip(); + B.flip(); + CarryIN.flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == high) && (CarryOUT.get_value() == high)); + if (!silent) printf("A&B&CarryIN off\n"); + A.flip(); + B.flip(); + CarryIN.flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == low) && (CarryOUT.get_value() == low)); + } + + { // test four_bit_adder + four_bit_adder four_adder(g); + std::vector A(4, toggle(g)); + std::vector B(4, toggle(g)); + toggle CarryIN(g); + digit Sum(g, "SUM"); + led CarryOUT(g, "CarryOUT"); + + for (int i=0; i<4; ++i) { + make_edge(A[i].get_out(), four_adder.get_A(i)); + make_edge(B[i].get_out(), four_adder.get_B(i)); + make_edge(four_adder.get_out(i), Sum.get_in(i)); + } + make_edge(CarryIN.get_out(), four_adder.get_CI()); + make_edge(four_adder.get_CO(), CarryOUT.get_in()); + + // Activate all switches at low state + for (int i=0; i<4; ++i) { + A[i].activate(); + B[i].activate(); + } + CarryIN.activate(); + + if (!silent) printf("1+0\n"); + A[0].flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == 1) && (CarryOUT.get_value() == low)); + + if (!silent) printf("0+1\n"); + A[0].flip(); + B[0].flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == 1) && (CarryOUT.get_value() == low)); + + if (!silent) printf("3+4\n"); + A[0].flip(); + A[1].flip(); + B[0].flip(); + B[2].flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == 7) && (CarryOUT.get_value() == low)); + + if (!silent) printf("6+1\n"); + A[0].flip(); + A[2].flip(); + B[0].flip(); + B[2].flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == 7) && (CarryOUT.get_value() == low)); + + if (!silent) printf("0+0+carry\n"); + A[1].flip(); + A[2].flip(); + B[0].flip(); + CarryIN.flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == 1) && (CarryOUT.get_value() == low)); + + if (!silent) printf("15+15+carry\n"); + A[0].flip(); + A[1].flip(); + A[2].flip(); + A[3].flip(); + B[0].flip(); + B[1].flip(); + B[2].flip(); + B[3].flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == 0xf) && (CarryOUT.get_value() == high)); + + if (!silent) printf("8+8\n"); + A[0].flip(); + A[1].flip(); + A[2].flip(); + B[0].flip(); + B[1].flip(); + B[2].flip(); + CarryIN.flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == 0) && (CarryOUT.get_value() == high)); + + if (!silent) printf("0+0\n"); + A[3].flip(); + B[3].flip(); + g.wait_for_all(); + if (!silent) Sum.display(); + if (!silent) CarryOUT.display(); + assert((Sum.get_value() == 0) && (CarryOUT.get_value() == low)); + } + + { // test D_latch + D_latch my_d_latch(g); + toggle D(g); + pulse E(g, 500, 4); // clock changes every 500ms; stops after 4 changes + led Q(g, " Q", verbose); // if true, LEDs print at every state change + led notQ(g, "~Q", verbose); + + make_edge(D.get_out(), my_d_latch.get_D()); + make_edge(E.get_out(), my_d_latch.get_E()); + make_edge(my_d_latch.get_Q(), Q.get_in()); + make_edge(my_d_latch.get_notQ(), notQ.get_in()); + + D.activate(); + + if (!silent) printf("Toggling D\n"); + E.activate(); + D.flip(); + g.wait_for_all(); + if (!silent && !verbose) { Q.display(); notQ.display(); } + assert((Q.get_value() == high) && (notQ.get_value() == low)); + E.reset(); + + if (!silent) printf("Toggling D\n"); + E.activate(); + D.flip(); + g.wait_for_all(); + if (!silent && !verbose) { Q.display(); notQ.display(); } + assert((Q.get_value() == low) && (notQ.get_value() == high)); + E.reset(); + + if (!silent) printf("Toggling D\n"); + E.activate(); + D.flip(); + g.wait_for_all(); + if (!silent && !verbose) { Q.display(); notQ.display(); } + assert((Q.get_value() == high) && (notQ.get_value() == low)); + E.reset(); + + if (!silent) printf("Toggling D\n"); + E.activate(); + D.flip(); + g.wait_for_all(); + if (!silent && !verbose) { Q.display(); notQ.display(); } + assert((Q.get_value() == low) && (notQ.get_value() == high)); + E.reset(); + + if (!silent) printf("Toggling D\n"); + E.activate(); + D.flip(); + g.wait_for_all(); + if (!silent && !verbose) { Q.display(); notQ.display(); } + assert((Q.get_value() == high) && (notQ.get_value() == low)); + } + } + utility::report_elapsed_time((tbb::tick_count::now() - start).seconds()); + return 0; + } catch(std::exception& e) { + cerr<<"error occurred. error text is :\"" < + + +

Overview

+This directory has example usages of Intel® Threading Building Blocks (Intel® TBB). + +

Directories

+
+
GettingStarted +
Examples from the Getting Started Guide. +
concurrent_hash_map +
Examples using concurrent_hash_map. +
concurrent_priority_queue +
Examples using concurrent_priority_queue. +
graph +
Examples using tbb::flow graph. +
parallel_do +
Examples using parallel_do. +
parallel_for +
Examples using parallel_for. +
parallel_reduce +
Examples using parallel_reduce. +
pipeline +
Examples using pipeline. +
task +
Examples using raw task interface. +
task_group +
Examples using task_group interface. +
task_priority +
Examples using the task priority feature. +
test_all +
Examples that test all the parts of the package. +
common +
Common files for building various examples. Should not be used directly. But if you copy an example to other place this folder should be copied also and should have the same relative path for copied example. +
+ +

To Build

+Build each example by using one of the following methods. The specific directions for each +method can be found below. + + +

+Some of the following directions refer to a shell window; this refers +to the command prompt environment/window normally used on your system. +A shell might be a cmd.exe command prompt window (Windows* systems), or a +sh, bash, csh, ksh, etc. (or compatible) shell window (Windows*, Linux* or Mac OS* X systems). +

+ +

To build by using a Microsoft* Visual Studio* project (Windows* systems):

+Perform the following steps: +
    +
  1. Identify the solution (*.sln) file for the example you wish to build and run.For Microsoft* Visual Studio* 2005, the *.sln file is in the example's msvs sub-directory. For other versions please use Microsoft* + Visual Studio* project converter +
      +
    • <example_name>_cl.sln  - Solution for Microsoft* Visual C++* compiler +
    • +
    • <example_name>_icl.sln - Solution for Intel® C++ Compiler
    • +
    +
  2. +
  3. Open the project by using one of the following methods: +
      +
    • Navigate to the *.sln file from My Computer, by using Windows Explorer, or by using another file browser. Double-click the *.sln file to invoke Microsoft* Visual Studio* and open the project.
    • +
    • Invoke Microsoft* Visual Studio* from the Start menu and use the "Open Project" dialog to navigate to and open the project.
    • +
    +
  4. +
  5. Press <ctrl-F5> to build and run the example.
  6. +
  7. If you copied an example to another place separately from libraries you need to + set %TBBROOT% variable pointing to <installdir> folder.
  8. +
+ +

To build by using a Xcode* IDE project (Mac OS* X systems):

+Perform the following steps: +
    +
  1. Identify the project (*.xcodeproj) file for the example you wish to build and run. +
      +
    • The *.xcodeproj file is in the example's xcode sub-directory. +
    +
  2. +
  3. Open the project by using one of the following methods: +
      +
    • Navigate to the *.xcodeproj file by using the Finder.Double-click the *.xcodeproj file to invoke the Xcode* IDE and open the project.
    • +
    • Invoke the Xcode* IDE and use the "File -> Open" dialog to navigate to and open the project.
    • +
    +
  4. +
  5. Press <Apple-R>, or press the "Build and Go" button in the toolbox, to build and run the example. +
  6. +
+ +

To build by using a Makefile (Windows*, Linux* or Mac OS* X systems):

+Perform the following steps: +
    +
  1. Open a shell window. For Windows* systems, make sure this shell window has the proper environment + defined for use with Microsoft* Visual Studio* (.NET 2003 or 2005); such a shell can be invoked + from the Start menu, under Visual Studio, Visual Studio Tools, Visual Studio Command Prompt. +
  2. Set up the environment in this shell window for use with Intel TBB. +
    See below for how to set up the environment for Windows*, Linux* or Mac OS* X systems. +
  3. Unless you installed Intel TBB yourself, you may not have write permissions to the directory + containing the example. In this case, make a copy of the example, and use the copy for the following steps. +
  4. In the shell window, navigate to the directory for the example + (or to the directory for the copy of the example if you made one in the previous step). +
  5. Use one or more of the following commands to build and run the example. + Here, make refers to the make command normally used on your system: this could be + nmake, gmake, or make on Windows* systems, or make or gmake on Linux* or Mac OS* X systems. +
    +
    make +
    Default build and run. Equivalent to 'make release test'. +
    make release +
    Compile and link against the release version of Intel TBB runtime library. The resulting executable is left in the directory for the example. +
    make debug +
    Compile and link against the debug version of Intel TBB runtime library. The resulting executable is left in the directory for the example. +
    make test +
    Run an executable previously produced by one of the above commands. +
    make [(above options or targets)] CXX={icl, icc} +
    Build and run as above, but use Intel® compilers instead of default, native compilers (e.g., icl instead of cl.exe on Windows* systems, or icc instead of g++ on Linux* or Mac OS* X systems). +
    make [(above options or targets)] offload=mic +
    Build and run the offload version of an example for Intel® Many Integrated Core (Intel® MIC) Architecture. +
    Note: Only Intel® MIC Architecture with Linux* based host is currently supported. +
    make clean +
    Remove any executables or intermediate files produced by the above commands. +
    +
+ +

To set up the environment (Windows* systems):

+It is strongly recommended that the environment be set up when installing Intel TBB. +Do this by selecting the appropriate check-box during the install. However, if the environment is not set up +during installation, or you wish to build for an alternate architecture or Microsoft* Visual Studio* version, +it may be set up, for a given type of shell window, by using one of the following commands: +
+
For cmd.exe (command prompt): +
<installdir>\bin\tbbvars.bat (arch) (vs) +
+    where (arch) must be is one of the following
+       ia32         : Set up for IA-32  architecture
+       intel64      : Set up for Intel® 64  architecture
+   (vs) should be one of the following
+       vs2005      : Set to use with Microsoft Visual Studio 2005 runtime DLLs
+       vs2008      : Set to use with Microsoft Visual Studio 2008 runtime DLLs
+       vs2010      : Set to use with Microsoft Visual Studio 2010 runtime DLLs
+       all         : Set to use TBB statically linked with Microsoft Visual C++ runtime
+   if (vs) is not set TBB statically linked with Microsoft Visual C++ runtime will be used.
+
+
+ +

To set up the environment (Linux* or Mac OS* X systems):

+The environment may be set up, for a given type of shell window, by using one of the following commands: +
+
For sh, bash, ksh (or compatibles): +
. <installdir>/bin/tbbvars.sh (arch) +
For csh (or compatibles): +
source <installdir>/bin/tbbvars.csh + (arch)
For sh, bash, ksh (or compatibles), when using an alternate architecture or platform: +
. <installdir>/{ia32,intel64}/cc<gccversion>_libc<libcversion>_kernel<kernelversion>/bin/tbbvars.sh +
For csh (or compatibles), when using an alternate architecture or platform: +
source <installdir>/{ia32,intel64}/cc<gccversion>_libc<libcversion>_kernel<kernelversion>/bin/tbbvars.csh +
Notes: +
+
  • Choose one of {ia32,intel64} depending on the architecture to be used. +
  • Choose a cc<gccversion>_libc<libcversion>_kernel<kernelversion> + value, from among the available platforms installed with Intel TBB + (for ia32 or intel64), + depending on the platform to be used. +
  • Environment setup need only be performed once per shell window to be used. +
  • Always source tbbvars.sh or tbbvars.csh rather than executing them directly. + +
  • + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + diff --git a/src/tbb/examples/parallel_do/index.html b/src/tbb/examples/parallel_do/index.html new file mode 100644 index 0000000..a72e1e6 --- /dev/null +++ b/src/tbb/examples/parallel_do/index.html @@ -0,0 +1,24 @@ + + + +

    Overview

    +This directory has examples of the template parallel_do. + +

    Directories

    +
    +
    parallel_preorder +
    Parallel preorder traversal of a graph. +
    + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + + diff --git a/src/tbb/examples/parallel_do/parallel_preorder/Graph.cpp b/src/tbb/examples/parallel_do/parallel_preorder/Graph.cpp new file mode 100644 index 0000000..6d9655f --- /dev/null +++ b/src/tbb/examples/parallel_do/parallel_preorder/Graph.cpp @@ -0,0 +1,109 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include +#include "Graph.h" +#include + +using namespace std; + +void Graph::create_random_dag( size_t number_of_nodes ) { + my_vertex_set.resize(number_of_nodes); + for( size_t k=0; k>8)%5u); + if( op>int(k) ) op = int(k); + switch( op ) { + default: + c.op = OP_VALUE; + c.value = Cell::value_type((float)k); + break; + case 1: + c.op = OP_NEGATE; + break; + case 2: + c.op = OP_SUB; + break; + case 3: + c.op = OP_ADD; + break; + case 4: + c.op = OP_MUL; + break; + } + for( int j=0; j& root_set ) { + for( size_t k=0; ksuccessor.push_back(&c); + } + if( ArityOfOp[c.op]==0 ) + root_set.push_back(&my_vertex_set[k]); + } +} + +void Cell::update() { + switch( op ) { + case OP_VALUE: + break; + case OP_NEGATE: + value = -(input[0]->value); + break; + case OP_ADD: + value = input[0]->value + input[1]->value; + break; + case OP_SUB: + value = input[0]->value - input[1]->value; + break; + case OP_MUL: + value = input[0]->value * input[1]->value; + break; + } +} + diff --git a/src/tbb/examples/parallel_do/parallel_preorder/Graph.h b/src/tbb/examples/parallel_do/parallel_preorder/Graph.h new file mode 100644 index 0000000..0b6d5ea --- /dev/null +++ b/src/tbb/examples/parallel_do/parallel_preorder/Graph.h @@ -0,0 +1,88 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "Matrix.h" +#include "tbb/atomic.h" +#include + +enum OpKind { + // Use Cell's value + OP_VALUE, + // Unary negation + OP_NEGATE, + // Addition + OP_ADD, + // Subtraction + OP_SUB, + // Multiplication + OP_MUL +}; + +static const int ArityOfOp[] = {0,1,2,2,2}; + +class Cell { +public: + //! Operation for this cell + OpKind op; + + //! Inputs to this cell + Cell* input[2]; + + //! Type of value stored in a Cell + typedef Matrix value_type; + + //! Value associated with this Cell + value_type value; + + //! Set of cells that use this Cell as an input + std::vector successor; + + //! Reference count of number of inputs that are not yet updated. + tbb::atomic ref_count; + + //! Update the Cell's value. + void update(); + + //! Default construtor + Cell() {} +}; + +//! A directed graph where the vertices are Cells. +class Graph { + std::vector my_vertex_set; +public: + //! Create a random acyclic directed graph + void create_random_dag( size_t number_of_nodes ); + + //! Print the graph + void print(); + + //! Get set of cells that have no inputs. + void get_root_set( std::vector& root_set ); +}; + diff --git a/src/tbb/examples/parallel_do/parallel_preorder/Makefile b/src/tbb/examples/parallel_do/parallel_preorder/Makefile new file mode 100644 index 0000000..84c110f --- /dev/null +++ b/src/tbb/examples/parallel_do/parallel_preorder/Makefile @@ -0,0 +1,59 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# GNU Makefile that builds and runs example. +PROG=parallel_preorder +ARGS= +PERF_RUN_ARGS=auto silent 500000 100 + +# The C++ compiler +ifneq (,$(shell which icc 2>/dev/null)) +CXX=icc +endif # icc + +ifeq ($(shell uname), Linux) +LIBS+= -lrt +endif + +all: release test + +release: *.cpp + $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb $(LIBS) + +debug: *.cpp + $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(LIBS) + +clean: + $(RM) $(PROG) *.o *.d + +test: + ./$(PROG) $(ARGS) + +perf_build: release + +perf_run: + ./$(PROG) $(PERF_RUN_ARGS) + diff --git a/src/tbb/examples/parallel_do/parallel_preorder/Makefile.windows b/src/tbb/examples/parallel_do/parallel_preorder/Makefile.windows new file mode 100644 index 0000000..37b92a6 --- /dev/null +++ b/src/tbb/examples/parallel_do/parallel_preorder/Makefile.windows @@ -0,0 +1,59 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Common Makefile that builds and runs example. + +# Just specify your program basename +PROG=Parallel_Preorder +ARGS= +PERF_RUN_ARGS=auto silent 500000 100 + +# Trying to find if icl.exe is set +CXX1 = $(TBB_CXX)- +CXX2 = $(CXX1:icl.exe-=icl.exe) +CXX = $(CXX2:-=cl.exe) + +# The C++ compiler options +MYCXXFLAGS = /TP /EHsc /W3 /nologo /D _CONSOLE /D _MBCS /D WIN32 /D _CRT_SECURE_NO_DEPRECATE $(CXXFLAGS) +MYLDFLAGS =/INCREMENTAL:NO /NOLOGO /DEBUG /FIXED:NO $(LDFLAGS) + +all: release test +release: compiler_check + $(CXX) *.cpp /MD /O2 /D NDEBUG $(MYCXXFLAGS) /link tbb.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +debug: compiler_check + $(CXX) *.cpp /MDd /Od /Zi /D TBB_USE_DEBUG /D _DEBUG $(MYCXXFLAGS) /link tbb_debug.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +clean: + @cmd.exe /C del $(PROG).exe *.obj *.?db *.manifest +test: + $(PROG) $(ARGS) +compiler_check: + @echo compiler_test>compiler_test && @$(CXX) /E compiler_test >nul 2>&1 || echo "$(CXX) command not found. Check if CXX=$(CXX) is set properly" + @cmd.exe /C del compiler_test + +perf_build: release + +perf_run: + ./$(PROG) $(PERF_RUN_ARGS) diff --git a/src/tbb/examples/parallel_do/parallel_preorder/Matrix.h b/src/tbb/examples/parallel_do/parallel_preorder/Matrix.h new file mode 100644 index 0000000..9b0a2f3 --- /dev/null +++ b/src/tbb/examples/parallel_do/parallel_preorder/Matrix.h @@ -0,0 +1,68 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +class Matrix { + static const int n = 20; + float array[n][n]; +public: + Matrix() {} + Matrix( float z ) { + for( int i=0; i + + +

    Overview

    +Example that uses parallel_do to do parallel preorder traversal of a sparse graph. +

    +Each vertex in the graph is called a "cell". +Each cell has a value. +The value is a matrix. +Some of the cells have operators +that compute the cell's value, using other cell's values as input. +A cell that uses the value of cell x is called a successor of x. +

    +The algorithm works as follows. +

      +
    1. Compute the set of cells that have no inputs. This set is called root_set. +
    2. Each cell has an associated field ref_count that is an atomic integer. + Initialize ref_count to the number of inputs for the Cell. +
    3. Update each cell in root_set, by applying a parallel_do to a root_set +
    4. After updating a cell, for each of its successors +
        +
      1. Atomically decrement the successor's ref_count +
      2. If the count became zero, add the cell to the set of cells to be updated, + by calling parallel_do_feeder_impl::add. +
      +
    +

    +The times printed are for the traversal and update, +and do not include time for computing the root_set. +

    +NOTE: It is important to understand that this example is unlikely to show speedup +if the cell values are changed to type "float". The reason is twofold. +
      +
    • The smaller value type causes each Cell to be significantly smaller than a cache line, + which leads to false sharing conflicts. +
    • The time to update the cells becomes very small, and consequently the overhead of + parallel_do swamps the useful work. +
    + +

    Files

    +
    +
    main.cpp +
    Main program which parses command line options and runs the algorithm with different numbers of threads. +
    parallel_preorder.cpp +
    Implementation of the parallel preorder traversal algorithm. +
    Graph.h +
    Interfaces of the Graph and Cell classes. +
    Graph.cpp +
    Implementations of the Graph and Cell classes. +
    Matrix.h +
    The Matrix class definition. +
    Makefile +
    Makefile for building example. +
    + +

    Directories

    +
    +
    msvs +
    Contains Microsoft* Visual Studio* 2005 workspace for building and running the example (Windows* systems only). +
    xcode +
    Contains Xcode* IDE workspace for building and running the example (Mac OS* X systems only). +
    + +

    To Build

    +General build directions can be found here. + +

    Usage

    +
    +
    parallel_preorder -h +
    Prints the help for command line options +
    parallel_preorder [n-of-threads=value] [n-of-nodes=value] [n-of-traversals=value] [silent] +
    parallel_preorder [n-of-threads [n-of-nodes [n-of-traversals]]] [silent] +
    n-of-threads is the number of threads to use; a range of the form low[:high], where low and optional high are non-negative integers or 'auto' for the TBB default.
    + n-of-nodes is a number of nodes in the graph. Default value is 1000.
    + n-of-traversals is the number of times to evaluate the graph. Default value is 500.
    + silent - no output except elapsed time.
    +
    To run a short version of this example, e.g., for use with Intel® Parallel Inspector: +
    Build a debug version of the example + (see the build directions). +
    Run it with the desired number of threads and smaller number of traversals, e.g., parallel_preorder 4 1000 5. +
    + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + + diff --git a/src/tbb/examples/parallel_do/parallel_preorder/main.cpp b/src/tbb/examples/parallel_do/parallel_preorder/main.cpp new file mode 100644 index 0000000..a437172 --- /dev/null +++ b/src/tbb/examples/parallel_do/parallel_preorder/main.cpp @@ -0,0 +1,101 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* Example program that shows how to use parallel_do to do parallel preorder + traversal of a directed acyclic graph. */ + +#include +#include "tbb/task_scheduler_init.h" +#include "tbb/tick_count.h" +#include "../../common/utility/utility.h" +#include +#include +#include "Graph.h" + +// some forward declarations +class Cell; +void ParallelPreorderTraversal( const std::vector& root_set ); + +//------------------------------------------------------------------------ +// Test driver +//------------------------------------------------------------------------ +utility::thread_number_range threads(tbb::task_scheduler_init::default_num_threads); +static unsigned nodes = 1000; +static unsigned traversals = 500; +static bool SilentFlag = false; + +//! Parse the command line. +static void ParseCommandLine( int argc, const char* argv[] ) { + utility::parse_cli_arguments( + argc,argv, + utility::cli_argument_pack() + //"-h" option for for displaying help is present implicitly + .positional_arg(threads,"n-of-threads","number of threads to use; a range of the form low[:high], where low and optional high are non-negative integers or 'auto' for the TBB default.") + .positional_arg(nodes,"n-of-nodes","number of nodes in the graph.") + .positional_arg(traversals,"n-of-traversals","number of times to evaluate the graph. Reduce it (e.g. to 100) to shorten example run time\n") + .arg(SilentFlag,"silent","no output except elapsed time ") + ); +} + +int main( int argc, const char* argv[] ) { + try { + tbb::tick_count main_start = tbb::tick_count::now(); + ParseCommandLine(argc,argv); + + // Start scheduler with given number of threads. + for( int p=threads.first; p<=threads.last; ++p ) { + tbb::tick_count t0 = tbb::tick_count::now(); + tbb::task_scheduler_init init(p); + srand(2); + size_t root_set_size = 0; + { + Graph g; + g.create_random_dag(nodes); + std::vector root_set; + g.get_root_set(root_set); + root_set_size = root_set.size(); + for( unsigned int trial=0; trial + + + + diff --git a/src/tbb/examples/parallel_do/parallel_preorder/msvs/parallel_preorder.vcproj b/src/tbb/examples/parallel_do/parallel_preorder/msvs/parallel_preorder.vcproj new file mode 100644 index 0000000..2a0d923 --- /dev/null +++ b/src/tbb/examples/parallel_do/parallel_preorder/msvs/parallel_preorder.vcproj @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/parallel_do/parallel_preorder/msvs/parallel_preorder_cl.sln b/src/tbb/examples/parallel_do/parallel_preorder/msvs/parallel_preorder_cl.sln new file mode 100644 index 0000000..665106e --- /dev/null +++ b/src/tbb/examples/parallel_do/parallel_preorder/msvs/parallel_preorder_cl.sln @@ -0,0 +1,25 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "parallel_preorder", "parallel_preorder.vcproj", "{3AA40693-F93D-4D4B-B32E-068F511A252B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3AA40693-F93D-4D4B-B32E-068F511A252B}.Debug|Win32.ActiveCfg = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252B}.Debug|Win32.Build.0 = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252B}.Debug|x64.ActiveCfg = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252B}.Debug|x64.Build.0 = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252B}.Release|Win32.ActiveCfg = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252B}.Release|Win32.Build.0 = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252B}.Release|x64.ActiveCfg = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252B}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/parallel_do/parallel_preorder/msvs/parallel_preorder_icl.sln b/src/tbb/examples/parallel_do/parallel_preorder/msvs/parallel_preorder_icl.sln new file mode 100644 index 0000000..b0ba4ac --- /dev/null +++ b/src/tbb/examples/parallel_do/parallel_preorder/msvs/parallel_preorder_icl.sln @@ -0,0 +1,33 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "parallel_preorder", "parallel_preorder.icproj", "{68C4AFEA-1847-4EEE-9CC5-D4FCB712D09F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {68C4AFEA-1847-4EEE-9CC5-D4FCB712D09F}.Debug|Win32.ActiveCfg = Debug|Win32 + {68C4AFEA-1847-4EEE-9CC5-D4FCB712D09F}.Debug|Win32.Build.0 = Debug|Win32 + {68C4AFEA-1847-4EEE-9CC5-D4FCB712D09F}.Debug|x64.ActiveCfg = Debug|x64 + {68C4AFEA-1847-4EEE-9CC5-D4FCB712D09F}.Debug|x64.Build.0 = Debug|x64 + {68C4AFEA-1847-4EEE-9CC5-D4FCB712D09F}.Release|Win32.ActiveCfg = Release|Win32 + {68C4AFEA-1847-4EEE-9CC5-D4FCB712D09F}.Release|Win32.Build.0 = Release|Win32 + {68C4AFEA-1847-4EEE-9CC5-D4FCB712D09F}.Release|x64.ActiveCfg = Release|x64 + {68C4AFEA-1847-4EEE-9CC5-D4FCB712D09F}.Release|x64.Build.0 = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252B}.Release|x64.Build.0 = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252B}.Release|x64.ActiveCfg = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252B}.Release|Win32.Build.0 = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252B}.Release|Win32.ActiveCfg = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252B}.Debug|x64.Build.0 = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252B}.Debug|x64.ActiveCfg = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252B}.Debug|Win32.Build.0 = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252B}.Debug|Win32.ActiveCfg = Debug|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/parallel_do/parallel_preorder/parallel_preorder.cpp b/src/tbb/examples/parallel_do/parallel_preorder/parallel_preorder.cpp new file mode 100644 index 0000000..0e0ca3a --- /dev/null +++ b/src/tbb/examples/parallel_do/parallel_preorder/parallel_preorder.cpp @@ -0,0 +1,61 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/parallel_do.h" +#include +#include +#include "Graph.h" + + +class Body { +public: + Body() {}; + + //------------------------------------------------------------------------ + // Following signatures are required by parallel_do + //------------------------------------------------------------------------ + typedef Cell* argument_type; + + void operator()( Cell* c, tbb::parallel_do_feeder& feeder ) const { + c->update(); + // Restore ref_count in preparation for subsequent traversal. + c->ref_count = ArityOfOp[c->op]; + for( size_t k=0; ksuccessor.size(); ++k ) { + Cell* successor = c->successor[k]; + if( 0 == --(successor->ref_count) ) { + feeder.add( successor ); + } + } + } +}; + +void ParallelPreorderTraversal( const std::vector& root_set ) { + tbb::parallel_do(root_set.begin(), root_set.end(),Body()); +} + + diff --git a/src/tbb/examples/parallel_do/parallel_preorder/xcode/parallel_preorder.xcodeproj/project.pbxproj b/src/tbb/examples/parallel_do/parallel_preorder/xcode/parallel_preorder.xcodeproj/project.pbxproj new file mode 100644 index 0000000..6773133 --- /dev/null +++ b/src/tbb/examples/parallel_do/parallel_preorder/xcode/parallel_preorder.xcodeproj/project.pbxproj @@ -0,0 +1,317 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 05593AA80B8F55D500DE73AB /* Graph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05593AA40B8F55D500DE73AB /* Graph.cpp */; }; + 05593AAB0B8F55D500DE73AB /* parallel_preorder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05593AA70B8F55D500DE73AB /* parallel_preorder.cpp */; }; + A1F593B70B8F06F900073279 /* libtbb.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; + A1F593BB0B8F072500073279 /* libtbb.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; + EAD808FA13051AB300FE8C7C /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAD808F913051AB300FE8C7C /* main.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8DD76F690486A84900D96B5E /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = ""; + dstSubfolderSpec = 16; + files = ( + A1F593BB0B8F072500073279 /* libtbb.dylib in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 05593AA40B8F55D500DE73AB /* Graph.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Graph.cpp; path = ../Graph.cpp; sourceTree = SOURCE_ROOT; }; + 05593AA50B8F55D500DE73AB /* Graph.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Graph.h; path = ../Graph.h; sourceTree = SOURCE_ROOT; }; + 05593AA60B8F55D500DE73AB /* Matrix.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Matrix.h; path = ../Matrix.h; sourceTree = SOURCE_ROOT; }; + 05593AA70B8F55D500DE73AB /* parallel_preorder.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = parallel_preorder.cpp; path = ../parallel_preorder.cpp; sourceTree = SOURCE_ROOT; }; + 8DD76F6C0486A84900D96B5E /* parallel_preorder */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = parallel_preorder; sourceTree = BUILT_PRODUCTS_DIR; }; + A1F593B30B8F06F900073279 /* libtbb.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtbb.dylib; path = ../../../../lib/libtbb.dylib; sourceTree = SOURCE_ROOT; }; + EAD808F913051AB300FE8C7C /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = ../main.cpp; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8DD76F660486A84900D96B5E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A1F593B70B8F06F900073279 /* libtbb.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* parallel_preorder */ = { + isa = PBXGroup; + children = ( + 08FB7795FE84155DC02AAC07 /* Source */, + A1F593B20B8F06F900073279 /* External Frameworks and Libraries */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + ); + name = parallel_preorder; + sourceTree = ""; + }; + 08FB7795FE84155DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + EAD808F913051AB300FE8C7C /* main.cpp */, + 05593AA70B8F55D500DE73AB /* parallel_preorder.cpp */, + 05593AA40B8F55D500DE73AB /* Graph.cpp */, + 05593AA50B8F55D500DE73AB /* Graph.h */, + 05593AA60B8F55D500DE73AB /* Matrix.h */, + ); + name = Source; + sourceTree = ""; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8DD76F6C0486A84900D96B5E /* parallel_preorder */, + ); + name = Products; + sourceTree = ""; + }; + A1F593B20B8F06F900073279 /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + A1F593B30B8F06F900073279 /* libtbb.dylib */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8DD76F620486A84900D96B5E /* parallel_preorder */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "parallel_preorder" */; + buildPhases = ( + 8DD76F640486A84900D96B5E /* Sources */, + 8DD76F660486A84900D96B5E /* Frameworks */, + 8DD76F690486A84900D96B5E /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = parallel_preorder; + productInstallPath = "$(HOME)/bin"; + productName = parallel_preorder; + productReference = 8DD76F6C0486A84900D96B5E /* parallel_preorder */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0410; + }; + buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "parallel_preorder" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 08FB7794FE84155DC02AAC07 /* parallel_preorder */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DD76F620486A84900D96B5E /* parallel_preorder */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 8DD76F640486A84900D96B5E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 05593AA80B8F55D500DE73AB /* Graph.cpp in Sources */, + 05593AAB0B8F55D500DE73AB /* parallel_preorder.cpp in Sources */, + EAD808FA13051AB300FE8C7C /* main.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1DEB923208733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = parallel_preorder; + ZERO_LINK = NO; + }; + name = Debug; + }; + 1DEB923308733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = parallel_preorder; + ZERO_LINK = NO; + }; + name = Release; + }; + 1DEB923608733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Debug; + }; + 1DEB923708733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Release; + }; + A1F593C60B8F0E6E00073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = parallel_preorder; + ZERO_LINK = NO; + }; + name = Debug64; + }; + A1F593C70B8F0E6E00073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = parallel_preorder; + ZERO_LINK = NO; + }; + name = Release64; + }; + A1F593C80B8F0E6E00073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-m64", + ); + OTHER_LDFLAGS = "-m64"; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Debug64; + }; + A1F593C90B8F0E6E00073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-m64", + ); + OTHER_LDFLAGS = "-m64"; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Release64; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "parallel_preorder" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923208733DC60010E9CD /* Debug */, + A1F593C60B8F0E6E00073279 /* Debug64 */, + 1DEB923308733DC60010E9CD /* Release */, + A1F593C70B8F0E6E00073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "parallel_preorder" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923608733DC60010E9CD /* Debug */, + A1F593C80B8F0E6E00073279 /* Debug64 */, + 1DEB923708733DC60010E9CD /* Release */, + A1F593C90B8F0E6E00073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/src/tbb/examples/parallel_for/game_of_life/Makefile b/src/tbb/examples/parallel_for/game_of_life/Makefile new file mode 100644 index 0000000..3d4b182 --- /dev/null +++ b/src/tbb/examples/parallel_for/game_of_life/Makefile @@ -0,0 +1,53 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# GNU Makefile that builds and runs example. +PROG=game_of_life +ARGS=2:4 -t 5 +LIGHT_ARGS=1:2 -t 5 +ifneq (,$(shell which icc 2>/dev/null)) +CXX=icc +endif # icc + +ifeq ($(shell uname), Linux) +LIBS+= -lrt +endif + +all: release test + +release: src/Evolution.cpp src/Update_state.cpp src/Game_of_life.cpp + $(CXX) -O2 -DNDEBUG -D_CONSOLE $(CXXFLAGS) -o $(PROG) $^ -ltbb $(LIBS) + +debug: src/Evolution.cpp src/Update_state.cpp src/Game_of_life.cpp + $(CXX) -O0 -D_CONSOLE -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(LIBS) + +clean: + rm -f $(PROG) *.o *.d + +test: + ./$(PROG) $(ARGS) +light_test: + ./$(PROG) $(LIGHT_ARGS) diff --git a/src/tbb/examples/parallel_for/game_of_life/Makefile.windows b/src/tbb/examples/parallel_for/game_of_life/Makefile.windows new file mode 100644 index 0000000..adbadc6 --- /dev/null +++ b/src/tbb/examples/parallel_for/game_of_life/Makefile.windows @@ -0,0 +1,54 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Common Makefile that builds and runs example. + +# Just specify your program basename +PROG=game_of_life +ARGS=2:4 -t 5 +LIGHT_ARGS=1:2 -t 5 + +# Trying to find if icl.exe is set +CXX1 = $(TBB_CXX)- +CXX2 = $(CXX1:icl.exe-=icl.exe) +CXX = $(CXX2:-=cl.exe) + +# The C++ compiler options +MYCXXFLAGS = /TP /EHsc /W3 /nologo /D _CONSOLE /D _MBCS /D WIN32 /D _CRT_SECURE_NO_DEPRECATE $(CXXFLAGS) +MYLDFLAGS =/INCREMENTAL:NO /NOLOGO /DEBUG /FIXED:NO $(LDFLAGS) + +all: release test +release: + $(CXX) ./src/Evolution.cpp ./src/Game_of_life.cpp ./src/Update_state.cpp /MD /O2 /D NDEBUG $(MYCXXFLAGS) /link tbb.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +debug: + $(CXX) ./src/Evolution.cpp ./src/Game_of_life.cpp ./src/Update_state.cpp /MDd /Od /Zi /D _DEBUG $(MYCXXFLAGS) /link tbb_debug.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +clean: + @cmd.exe /C del $(PROG).exe *.obj *.?db *.manifest +test: + $(PROG) $(ARGS) +light_test: + $(PROG) $(LIGHT_ARGS) + diff --git a/src/tbb/examples/parallel_for/game_of_life/index.html b/src/tbb/examples/parallel_for/game_of_life/index.html new file mode 100644 index 0000000..67f096d --- /dev/null +++ b/src/tbb/examples/parallel_for/game_of_life/index.html @@ -0,0 +1,54 @@ + + + +

    Overview

    +The "Game of life" example demonstrates interoperability of TBB and .NET. +
    This program runs 2 simultaneous instances of the classic Conway's "Game of Life". +One of these instances uses serial calculations to update the board. The other one calculates in parallel with TBB. +The visualization is written in managed C++ and uses .NET CLR. + +

    Source Files

    +
    +
    Form1.h, Board.h +
    Header files for GUI classes. +
    Evolution.h, Evolution.cpp +
    Contain class hierarchy to implement game evolution in serial and parallel. +
    Update_state.cpp +
    Implements 2 approaches for calculating steps in the program: with the use of SSE intrinsics, and ordinary C++ code. +
    Game_of_life.cpp +
    Contains program entry point and other source not related to logical structure of the example. +
    Makefile +
    Makefile for building example. +
    + +

    Directories

    +
    +
    src +
    Contains source files mentioned above. +
    msvs +
    Contains Microsoft* Visual Studio* 2005 workspace for building and running the example (Windows* systems only). +
    xcode +
    Contains Xcode* IDE workspace for building and running the example (Mac OS* X systems only). +
    + +

    To Build

    +General build directions can be found here. +

    + +

    Usage

    +
    +For Windows* systems, Microsoft* Visual Studio* projects are provided for each of the above versions. +
    + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + + diff --git a/src/tbb/examples/parallel_for/game_of_life/msvs/Game_of_life.sln b/src/tbb/examples/parallel_for/game_of_life/msvs/Game_of_life.sln new file mode 100644 index 0000000..2aabfd5 --- /dev/null +++ b/src/tbb/examples/parallel_for/game_of_life/msvs/Game_of_life.sln @@ -0,0 +1,37 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Game of Life", "Game_of_life.vcproj", "{731C7E2E-2766-41D9-96FC-0A3548973803}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug(console)|Win32 = Debug(console)|Win32 + Debug(console)|x64 = Debug(console)|x64 + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release(console)|Win32 = Release(console)|Win32 + Release(console)|x64 = Release(console)|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {731C7E2E-2766-41D9-96FC-0A3548973803}.Debug(console)|Win32.ActiveCfg = Debug(console)|Win32 + {731C7E2E-2766-41D9-96FC-0A3548973803}.Debug(console)|Win32.Build.0 = Debug(console)|Win32 + {731C7E2E-2766-41D9-96FC-0A3548973803}.Debug(console)|x64.ActiveCfg = Debug(console)|x64 + {731C7E2E-2766-41D9-96FC-0A3548973803}.Debug(console)|x64.Build.0 = Debug(console)|x64 + {731C7E2E-2766-41D9-96FC-0A3548973803}.Debug|Win32.ActiveCfg = Debug|Win32 + {731C7E2E-2766-41D9-96FC-0A3548973803}.Debug|Win32.Build.0 = Debug|Win32 + {731C7E2E-2766-41D9-96FC-0A3548973803}.Debug|x64.ActiveCfg = Debug|x64 + {731C7E2E-2766-41D9-96FC-0A3548973803}.Debug|x64.Build.0 = Debug|x64 + {731C7E2E-2766-41D9-96FC-0A3548973803}.Release(console)|Win32.ActiveCfg = Release(console)|Win32 + {731C7E2E-2766-41D9-96FC-0A3548973803}.Release(console)|Win32.Build.0 = Release(console)|Win32 + {731C7E2E-2766-41D9-96FC-0A3548973803}.Release(console)|x64.ActiveCfg = Release(console)|x64 + {731C7E2E-2766-41D9-96FC-0A3548973803}.Release(console)|x64.Build.0 = Release(console)|x64 + {731C7E2E-2766-41D9-96FC-0A3548973803}.Release|Win32.ActiveCfg = Release|Win32 + {731C7E2E-2766-41D9-96FC-0A3548973803}.Release|Win32.Build.0 = Release|Win32 + {731C7E2E-2766-41D9-96FC-0A3548973803}.Release|x64.ActiveCfg = Release|x64 + {731C7E2E-2766-41D9-96FC-0A3548973803}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/parallel_for/game_of_life/msvs/Game_of_life.vcproj b/src/tbb/examples/parallel_for/game_of_life/msvs/Game_of_life.vcproj new file mode 100644 index 0000000..554055a --- /dev/null +++ b/src/tbb/examples/parallel_for/game_of_life/msvs/Game_of_life.vcproj @@ -0,0 +1,794 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/parallel_for/game_of_life/msvs/app.ico b/src/tbb/examples/parallel_for/game_of_life/msvs/app.ico new file mode 100644 index 0000000000000000000000000000000000000000..3a5525fd794f7a7c5c8e6187f470ea3af38cd2b6 GIT binary patch literal 1078 zcmeHHJr05}7=1t!Hp3A*8IHkVf+j?-!eHY14Gtcw1Eb*_9>Bq^zETJ@GKj{_2j4$w zo9}xCh!8{T3=X##Skq>ikMjsvB|y%crWBM2iW(4pI}c%z6%lW!=~4v77#3{z!dmB1 z__&l)-{KUYR+|8|;wB^R|9ET$J@(@=#rd^=)qs85?vAy(PSF5CyNkus435LVkZ$rj zNw|JG-P7^hF<(;#o*Vk}5R#e|^13tBbQkeF?djULtvqyxd3<{9 literal 0 HcmV?d00001 diff --git a/src/tbb/examples/parallel_for/game_of_life/msvs/app.rc b/src/tbb/examples/parallel_for/game_of_life/msvs/app.rc new file mode 100644 index 0000000..807aa89 --- /dev/null +++ b/src/tbb/examples/parallel_for/game_of_life/msvs/app.rc @@ -0,0 +1,63 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon placed first or with lowest ID value becomes application icon + +LANGUAGE 9, 1 +#pragma code_page(1252) +1 ICON "app.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" + "\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\0" +END + +#endif // APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/tbb/examples/parallel_for/game_of_life/msvs/resource.h b/src/tbb/examples/parallel_for/game_of_life/msvs/resource.h new file mode 100644 index 0000000..d5ac7c4 --- /dev/null +++ b/src/tbb/examples/parallel_for/game_of_life/msvs/resource.h @@ -0,0 +1,3 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by app.rc diff --git a/src/tbb/examples/parallel_for/game_of_life/src/AssemblyInfo.cpp b/src/tbb/examples/parallel_for/game_of_life/src/AssemblyInfo.cpp new file mode 100644 index 0000000..2f33826 --- /dev/null +++ b/src/tbb/examples/parallel_for/game_of_life/src/AssemblyInfo.cpp @@ -0,0 +1,66 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +using namespace System; +using namespace System::Reflection; +using namespace System::Runtime::CompilerServices; +using namespace System::Runtime::InteropServices; +using namespace System::Security::Permissions; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly:AssemblyTitleAttribute("Automata")]; +[assembly:AssemblyDescriptionAttribute("")]; +[assembly:AssemblyConfigurationAttribute("")]; +[assembly:AssemblyCompanyAttribute("")]; +[assembly:AssemblyProductAttribute("Automata")]; +[assembly:AssemblyCopyrightAttribute("Copyright (c) 2007")]; +[assembly:AssemblyTrademarkAttribute("")]; +[assembly:AssemblyCultureAttribute("")]; + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the value or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly:AssemblyVersionAttribute("1.0.*")]; + +[assembly:ComVisible(false)]; + +[assembly:CLSCompliantAttribute(true)]; + +[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)]; diff --git a/src/tbb/examples/parallel_for/game_of_life/src/Board.h b/src/tbb/examples/parallel_for/game_of_life/src/Board.h new file mode 100644 index 0000000..54fcac2 --- /dev/null +++ b/src/tbb/examples/parallel_for/game_of_life/src/Board.h @@ -0,0 +1,115 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#define WIN32_LEAN_AND_MEAN + +#ifndef _CONSOLE +#include + +using namespace System; +using namespace System::ComponentModel; +using namespace System::Collections; +using namespace System::Windows::Forms; +using namespace System::Data; +using namespace System::Drawing; +#define LabelPtr Label^ +#define BoardPtr Board^ +#else +#define LabelPtr int* +#define BoardPtr Board* +#endif + +struct Matrix +{ + int width; + int height; + char* data; +}; + +#ifndef _CONSOLE +public ref class Board : public System::Windows::Forms::UserControl +#else +class Board +#endif + { + public: + Board(int width, int height, int squareSize, LabelPtr counter); + virtual ~Board(); + void seed(int s); + void seed(const BoardPtr s); +#ifndef _CONSOLE + protected: + virtual void OnPaint(PaintEventArgs^ e) override; + void Board::draw(Graphics^ g); + + private: + System::ComponentModel::Container ^components; + +#pragma region Windows Form Designer generated code + void InitializeComponent(void) + { + this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; + } +#pragma endregion + + private: delegate void drawDelegate(Int32); + public: + //! Called from the Evolution thread + void draw( Int32 nCurIteration ) + { + if (this->InvokeRequired) + { + drawDelegate^ d = gcnew drawDelegate(this, &Board::draw); + IAsyncResult^ result = BeginInvoke(d, nCurIteration); + EndInvoke(result); + return; + } + m_counter->Text = nCurIteration.ToString(); + Invalidate(); + } +#endif + public: + Matrix *m_matrix; + + private: +#ifndef _CONSOLE + SolidBrush^ m_occupiedBrush; + SolidBrush^ m_freeBrush; + Graphics^ m_graphics; + Graphics^ m_mem_dc; + Bitmap^ m_bmp; +#endif + int m_width; + int m_height; + int m_squareSize; + LabelPtr m_counter; + }; +#endif diff --git a/src/tbb/examples/parallel_for/game_of_life/src/Evolution.cpp b/src/tbb/examples/parallel_for/game_of_life/src/Evolution.cpp new file mode 100644 index 0000000..5b7cabc --- /dev/null +++ b/src/tbb/examples/parallel_for/game_of_life/src/Evolution.cpp @@ -0,0 +1,251 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + Evolution.cpp: implementation file for evolution classes; evolution + classes do looped evolution of patterns in a defined + 2 dimensional space +*/ + +#include "Evolution.h" +#include "Board.h" + +#ifdef USE_SSE +#define GRAIN_SIZE 14 +#else +#define GRAIN_SIZE 4000 +#endif +#define TIME_SLICE 330 + +/* + Evolution +*/ + +/** + Evolution::UpdateMatrix() - moves the calculated destination data + to the source data block. No destination zeroing is required since it will + be completely overwritten during the next calculation cycle. +**/ +void Evolution::UpdateMatrix() +{ + memcpy(m_matrix->data, m_dest, m_size); +} + +/* + SequentialEvolution +*/ + +//! SequentialEvolution::Run - begins looped evolution +#ifndef _CONSOLE +void SequentialEvolution::Run() +{ +#else +void SequentialEvolution::Run(double execution_time, int nthread) +{ + printf("Starting game (Sequential evolution)\n"); +#endif + + m_nIteration = 0; + m_serial_time = 0; + tbb::tick_count t0 = tbb::tick_count::now(); + while (!m_done) + { + if( !is_paused ) + { + tbb::tick_count t = tbb::tick_count::now(); + Step(); + tbb::tick_count t1 = tbb::tick_count::now(); + ++m_nIteration; + double work_time = (t1-t0).seconds(); +#ifndef _CONSOLE + if ( work_time * 1000 < TIME_SLICE ) + continue; + m_serial_time += work_time; + m_board->draw(m_nIteration); +#else + m_serial_time += work_time; +#endif + } + //! Let the parallel algorithm work uncontended almost the same time + //! as the serial one. See ParallelEvolution::Run() as well. +#ifndef _CONSOLE + m_evt_start_parallel->Set(); + m_evt_start_serial->WaitOne(); + t0 = tbb::tick_count::now(); +#else + t0 = tbb::tick_count::now(); + if(m_serial_time > execution_time) + { + printf("iterations count = %d time = %g\n", m_nIteration, m_serial_time); + break; + } +#endif + } +} + +//! SequentialEvolution::Step() - override of step method +void SequentialEvolution::Step() +{ + if( !is_paused ) + { +#ifdef USE_SSE + UpdateState(m_matrix, m_matrix->data, 0, m_matrix->height); +#else + UpdateState(m_matrix, m_dest, 0, (m_matrix->width * m_matrix->height)-1); + UpdateMatrix(); +#endif + } +} + +/* + ParallelEvolution +*/ + +//! SequentialEvolution::Run - begins looped evolution +#ifndef _CONSOLE +void ParallelEvolution::Run() +{ +#else +void ParallelEvolution::Run(double execution_time, int nthread) +{ + if(nthread == tbb::task_scheduler_init::automatic) + printf("Starting game (Parallel evolution for automatic number of thread(s))\n"); + else + printf("Starting game (Parallel evolution for %d thread(s))\n", nthread); +#endif + + m_nIteration = 0; + m_parallel_time = 0; + +#ifndef _CONSOLE + //! start task scheduler as necessary + if (m_pInit == NULL) + { + m_pInit = new tbb::task_scheduler_init(); + } + m_evt_start_parallel->WaitOne(); +#else + tbb::task_scheduler_init init(nthread); +#endif + + double work_time = m_serial_time; + tbb::tick_count t0 = tbb::tick_count::now(); + + while (!m_done) + { + if( !is_paused ) + { + tbb::tick_count t = tbb::tick_count::now(); + Step(); + tbb::tick_count t1 = tbb::tick_count::now(); + ++m_nIteration; + double real_work_time = (t1-t0).seconds(); +#ifndef _CONSOLE + if ( real_work_time < work_time ) + continue; + m_parallel_time += real_work_time; + m_board->draw(m_nIteration); +#else + m_parallel_time += real_work_time; +#endif + } + //! Let the serial algorithm work the same time as the parallel one. +#ifndef _CONSOLE + m_evt_start_serial->Set(); + m_evt_start_parallel->WaitOne(); + + work_time = m_serial_time - m_parallel_time; + t0 = tbb::tick_count::now(); +#else + t0 = tbb::tick_count::now(); + if(m_parallel_time > execution_time) + { + printf("iterations count = %d time = %g\n", m_nIteration, m_parallel_time); + init.terminate(); + break; + } +#endif + } +} + +/** + class tbb_parallel_task + + TBB requires a class for parallel loop implementations. The actual + loop "chunks" are performed using the () operator of the class. + The blocked_range contains the range to calculate. Please see the + TBB documentation for more information. +**/ +#ifndef _CONSOLE +public class tbb_parallel_task +#else +class tbb_parallel_task +#endif +{ +public: + static void set_values (Matrix* source, char* dest) + { + m_source = source; + m_dest = dest; + return; + } + + void operator()( const tbb::blocked_range& r ) const + { + int begin = (int)r.begin(); //! capture lower range number for this chunk + int end = (int)r.end(); //! capture upper range number for this chunk + UpdateState(m_source, m_dest, begin, end); + } + + tbb_parallel_task () {} + +private: + static Matrix* m_source; + static char* m_dest; +}; + +Matrix* tbb_parallel_task::m_source; +char* tbb_parallel_task::m_dest; + +//! ParallelEvolution::Step() - override of Step method +void ParallelEvolution::Step() +{ + size_t begin = 0; //! beginning cell position +#ifdef USE_SSE + size_t end = m_matrix->height; //! ending cell position +#else + size_t end = m_size-1; //! ending cell position +#endif + + //! set matrix pointers + tbb_parallel_task::set_values(m_matrix, m_dest); + + //! do calculation loop + parallel_for (tbb::blocked_range (begin, end, GRAIN_SIZE), tbb_parallel_task()); + UpdateMatrix(); +} diff --git a/src/tbb/examples/parallel_for/game_of_life/src/Evolution.h b/src/tbb/examples/parallel_for/game_of_life/src/Evolution.h new file mode 100644 index 0000000..e9fe10f --- /dev/null +++ b/src/tbb/examples/parallel_for/game_of_life/src/Evolution.h @@ -0,0 +1,203 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/** + Evolution.h: Header file for evolution classes; evolution classes do + looped evolution of patterns in a defined 2 dimensional space +**/ + +#ifndef __EVOLUTION_H__ +#define __EVOLUTION_H__ + +#include "Board.h" +#include +#include +#include + +#define WIN32_LEAN_AND_MEAN + +#include "tbb/task_scheduler_init.h" +#include "tbb/blocked_range.h" +#include "tbb/parallel_for.h" +#include "tbb/tick_count.h" + +#ifndef _CONSOLE +#include +using namespace System::Threading; +#else +typedef unsigned int Int32; +#endif + +void UpdateState(Matrix * m_matrix, char * dest ,int begin, int end); + +/** + class Evolution - base class for SequentialEvolution and ParallelEvolution +**/ +#ifndef _CONSOLE +public ref class Evolution abstract +#else +class Evolution +#endif +{ +public: + Evolution( Matrix *m, //! beginning matrix including initial pattern + BoardPtr board //! the board to update + ) : m_matrix(m), m_board(board), + m_size(m_matrix->height * m_matrix->width), m_done(false) + { + //! allocate memory for second matrix data block + m_dest = new char[m_size]; + is_paused = false; +#ifdef _CONSOLE + m_serial_time = 0; +#endif + } + + virtual ~Evolution() + { + delete[] m_dest; + } + + //! Run() - begins looped evolution +#ifndef _CONSOLE + virtual void Run() = 0; +#else + virtual void Run(double execution_time, int nthread) = 0; +#endif + + //! Quit() - tell the thread to terminate + virtual void Quit() { m_done = true; } + + //! Step() - performs a single evolutionary generation computation on the game matrix + virtual void Step() = 0; + + //! SetPause() - change condition of variable is_paused + virtual void SetPause(bool condition) + { + if ( condition == true ) + is_paused = true; + else + is_paused = false; + } + +protected: + /** + UpdateMatrix() - moves the previous destination data to the source + data block and zeros out destination. + **/ + void UpdateMatrix(); + +protected: + Matrix* m_matrix; //! Pointer to initial matrix + char* m_dest; //! Pointer to calculation destination data + BoardPtr m_board; //! The game board to update + int m_size; //! size of the matrix data block + volatile bool m_done; //! a flag used to terminate the thread + Int32 m_nIteration; //! current calculation cycle index + volatile bool is_paused; //! is needed to perform next iteration + + //! Calculation time of the sequential version (since the start), seconds. + /** + This member is updated by the sequential version and read by parallel, + so no synchronization is necessary. + **/ +#ifndef _CONSOLE + static volatile double m_serial_time = 0; + + static System::Threading::AutoResetEvent ^m_evt_start_serial = gcnew AutoResetEvent(false), + ^m_evt_start_parallel = gcnew AutoResetEvent(false); +#else + double m_serial_time; +#endif +}; + +/** + class SequentialEvolution - derived from Evolution - calculate life generations serially +**/ +#ifndef _CONSOLE +public ref class SequentialEvolution: public Evolution +#else +class SequentialEvolution: public Evolution +#endif +{ +public: + SequentialEvolution(Matrix *m, BoardPtr board) + : Evolution(m, board) + {} +#ifndef _CONSOLE + virtual void Run() override; + virtual void Step() override; +#else + virtual void Run(double execution_time, int nthread); + virtual void Step(); +#endif + +}; + +/** + class ParallelEvolution - derived from Evolution - calculate life generations + in parallel using Intel's TBB package +**/ +#ifndef _CONSOLE +public ref class ParallelEvolution: public Evolution +#else +class ParallelEvolution: public Evolution +#endif +{ +public: + + ParallelEvolution(Matrix *m, BoardPtr board) + : Evolution(m, board), + m_parallel_time(0) + { + // instantiate a task_scheduler_init object and save a pointer to it + m_pInit = NULL; + } + + ~ParallelEvolution() + { + //! delete task_scheduler_init object + if (m_pInit != NULL) + delete m_pInit; + } +#ifndef _CONSOLE + virtual void Run() override; + virtual void Step() override; +#else + virtual void Run(double execution_time, int nthread); + virtual void Step(); +#endif + + +private: + tbb::task_scheduler_init* m_pInit; + + double m_parallel_time; +}; + +#endif diff --git a/src/tbb/examples/parallel_for/game_of_life/src/Form1.h b/src/tbb/examples/parallel_for/game_of_life/src/Form1.h new file mode 100644 index 0000000..531c4c2 --- /dev/null +++ b/src/tbb/examples/parallel_for/game_of_life/src/Form1.h @@ -0,0 +1,314 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _CONSOLE +#ifndef __FORM1_H__ +#define __FORM1_H__ + +#include +#include "Board.h" +#include "Evolution.h" + +#define BOARD_SQUARE_SIZE 2 + + using namespace System; + using namespace System::ComponentModel; + using namespace System::Collections; + using namespace System::Windows::Forms; + using namespace System::Data; + using namespace System::Drawing; + + public ref class Form1 : public System::Windows::Forms::Form + { + public: + Form1(void) + { + InitializeComponent(); + + FormBorderStyle = System::Windows::Forms::FormBorderStyle::FixedDialog; + ClientSize = System::Drawing::Size(1206, 600+m_ribbonHeight+menuStrip1->Height); + + int boardWidth = (ClientRectangle.Width/2-m_sepWidth/2)/BOARD_SQUARE_SIZE; + int boardHeight = (ClientRectangle.Height-menuStrip1->Height-m_ribbonHeight)/BOARD_SQUARE_SIZE; + + m_board1 = gcnew Board(boardWidth, boardHeight, BOARD_SQUARE_SIZE, seqGen); + m_board2 = gcnew Board(boardWidth, boardHeight, BOARD_SQUARE_SIZE, parGen); + + Controls->Add(m_board1); + Controls->Add(m_board2); + + m_board1->Location = System::Drawing::Point(2, m_ribbonHeight + menuStrip1->Height); + m_board2->Location = System::Drawing::Point(2 + boardWidth*BOARD_SQUARE_SIZE + m_sepWidth/2, m_ribbonHeight + menuStrip1->Height); + + m_seq = gcnew SequentialEvolution(m_board1->m_matrix, m_board1); + m_par = gcnew ParallelEvolution(m_board2->m_matrix, m_board2); + + m_seqThread = gcnew Thread(gcnew ThreadStart(m_seq, &SequentialEvolution::Run)); + m_parThread = gcnew Thread(gcnew ThreadStart(m_par, &ParallelEvolution::Run)); + + Thread::CurrentThread->Priority = ThreadPriority::AboveNormal; + + m_suspend = true; + } + protected: + ~Form1() + { + if (components) + { + delete components; + } + } + private: System::Windows::Forms::MenuStrip^ menuStrip1; + private: System::Windows::Forms::ToolStripMenuItem^ fileToolStripMenuItem; + private: System::Windows::Forms::ToolStripMenuItem^ exitToolStripMenuItem; + private: System::Windows::Forms::ToolStripMenuItem^ gameToolStripMenuItem; + private: System::Windows::Forms::ToolStripMenuItem^ seedToolStripMenuItem; + private: System::Windows::Forms::ToolStripMenuItem^ runToolStripMenuItem; + private: System::Windows::Forms::ToolStripMenuItem^ pauseToolStripMenuItem; + private: Board^ m_board1; + private: Board^ m_board2; + private: System::Windows::Forms::Label^ Sequential; + private: System::Windows::Forms::Label^ label1; + private: static const int m_sepWidth = 5; + private: static const int m_ribbonHeight = 26; + private: SequentialEvolution^ m_seq; + private: ParallelEvolution^ m_par; + private: Thread^ m_seqThread; + private: Thread^ m_parThread; + private: System::Windows::Forms::Label^ seqGen; + private: System::Windows::Forms::Label^ parGen; + private: bool m_suspend; + + private: + System::ComponentModel::Container ^components; + +#pragma region Windows Form Designer generated code + void InitializeComponent(void) + { + this->menuStrip1 = (gcnew System::Windows::Forms::MenuStrip()); + this->fileToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem()); + this->exitToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem()); + this->gameToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem()); + this->seedToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem()); + this->runToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem()); + this->pauseToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem()); + this->Sequential = (gcnew System::Windows::Forms::Label()); + this->label1 = (gcnew System::Windows::Forms::Label()); + this->seqGen = (gcnew System::Windows::Forms::Label()); + this->parGen = (gcnew System::Windows::Forms::Label()); + this->menuStrip1->SuspendLayout(); + this->SuspendLayout(); + // + // menuStrip1 + // + this->menuStrip1->Items->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^ >(2) + {this->fileToolStripMenuItem, this->gameToolStripMenuItem}); + this->menuStrip1->Location = System::Drawing::Point(0, 0); + this->menuStrip1->Name = L"menuStrip1"; + this->menuStrip1->Padding = System::Windows::Forms::Padding(8, 2, 0, 2); + this->menuStrip1->Size = System::Drawing::Size(1600, 26); + this->menuStrip1->TabIndex = 0; + this->menuStrip1->Text = L"menuStrip1"; + this->menuStrip1->ItemClicked += gcnew System::Windows::Forms::ToolStripItemClickedEventHandler(this, &Form1::menuStrip1_ItemClicked); + // + // fileToolStripMenuItem + // + this->fileToolStripMenuItem->DropDownItems->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^ >(1) {this->exitToolStripMenuItem}); + this->fileToolStripMenuItem->Name = L"fileToolStripMenuItem"; + this->fileToolStripMenuItem->Size = System::Drawing::Size(40, 22); + this->fileToolStripMenuItem->Text = L"File"; + // + // exitToolStripMenuItem + // + this->exitToolStripMenuItem->Name = L"exitToolStripMenuItem"; + this->exitToolStripMenuItem->Size = System::Drawing::Size(99, 22); + this->exitToolStripMenuItem->Text = L"Exit"; + this->exitToolStripMenuItem->Click += gcnew System::EventHandler(this, &Form1::OnExit); + // + // gameToolStripMenuItem + // + this->gameToolStripMenuItem->DropDownItems->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^ >(3) {this->seedToolStripMenuItem, + this->runToolStripMenuItem, this->pauseToolStripMenuItem}); + this->gameToolStripMenuItem->Name = L"gameToolStripMenuItem"; + this->gameToolStripMenuItem->Size = System::Drawing::Size(59, 22); + this->gameToolStripMenuItem->Text = L"Game"; + // + // seedToolStripMenuItem + // + this->seedToolStripMenuItem->Name = L"seedToolStripMenuItem"; + this->seedToolStripMenuItem->Size = System::Drawing::Size(115, 22); + this->seedToolStripMenuItem->Text = L"Seed"; + this->seedToolStripMenuItem->Click += gcnew System::EventHandler(this, &Form1::OnSeed); + // + // runToolStripMenuItem + // + this->runToolStripMenuItem->Enabled = false; + this->runToolStripMenuItem->Name = L"runToolStripMenuItem"; + this->runToolStripMenuItem->Size = System::Drawing::Size(115, 22); + this->runToolStripMenuItem->Text = L"Run"; + this->runToolStripMenuItem->Click += gcnew System::EventHandler(this, &Form1::OnRun); + // + // pauseToolStripMenuItem + // + this->pauseToolStripMenuItem->Enabled = false; + this->pauseToolStripMenuItem->Name = L"pauseToolStripMenuItem"; + this->pauseToolStripMenuItem->Size = System::Drawing::Size(115, 22); + this->pauseToolStripMenuItem->Text = L"Pause"; + this->pauseToolStripMenuItem->Click += gcnew System::EventHandler(this, &Form1::OnPauseResume); + // + // Sequential + // + this->Sequential->AutoSize = true; + this->Sequential->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 9, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point, + static_cast(0))); + this->Sequential->Location = System::Drawing::Point(12, 32); + this->Sequential->Margin = System::Windows::Forms::Padding(4, 0, 4, 0); + this->Sequential->Name = L"Sequential"; + this->Sequential->Size = System::Drawing::Size(239, 18); + this->Sequential->TabIndex = 1; + this->Sequential->Text = L"Sequential Algorithm generation:"; + // + // label1 + // + this->label1->AutoSize = true; + this->label1->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 9, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point, + static_cast(0))); + this->label1->Location = System::Drawing::Point(813, 32); + this->label1->Margin = System::Windows::Forms::Padding(4, 0, 4, 0); + this->label1->Name = L"label1"; + this->label1->Size = System::Drawing::Size(219, 18); + this->label1->TabIndex = 2; + this->label1->Text = L"Parallel Algorithm generation: "; + // + // seqGen + // + this->seqGen->AutoSize = true; + this->seqGen->Location = System::Drawing::Point(289, 35); + this->seqGen->Margin = System::Windows::Forms::Padding(4, 0, 4, 0); + this->seqGen->Name = L"seqGen"; + this->seqGen->Size = System::Drawing::Size(16, 17); + this->seqGen->TabIndex = 3; + this->seqGen->Text = L"0"; + // + // parGen + // + this->parGen->AutoSize = true; + this->parGen->Location = System::Drawing::Point(1068, 35); + this->parGen->Margin = System::Windows::Forms::Padding(4, 0, 4, 0); + this->parGen->Name = L"parGen"; + this->parGen->Size = System::Drawing::Size(16, 17); + this->parGen->TabIndex = 4; + this->parGen->Text = L"0"; + // + // Form1 + // + this->AutoScaleDimensions = System::Drawing::SizeF(8, 16); + this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; + this->ClientSize = System::Drawing::Size(1600, 738); + this->Controls->Add(this->parGen); + this->Controls->Add(this->seqGen); + this->Controls->Add(this->label1); + this->Controls->Add(this->Sequential); + this->Controls->Add(this->menuStrip1); + this->MainMenuStrip = this->menuStrip1; + this->Margin = System::Windows::Forms::Padding(4); + this->MaximizeBox = false; + this->Name = L"Form1"; + this->Text = L"Game of Life"; + this->menuStrip1->ResumeLayout(false); + this->menuStrip1->PerformLayout(); + this->ResumeLayout(false); + this->PerformLayout(); + + } +#pragma endregion + protected: + void CloseApp () + { + m_seq->Quit(); + m_par->Quit(); + //! Perform a very ungracious exit, should coordinate the threads + System::Environment::Exit(0); + } + + protected: + virtual void OnPaint(PaintEventArgs^ e) override + { + } + + virtual void OnFormClosing(FormClosingEventArgs^ e) override + { + CloseApp(); + } + + void OnExit(System::Object^ sender, System::EventArgs^ e) + { + CloseApp(); + } + + void OnSeed(System::Object^ sender, System::EventArgs^ e) + { + this->seedToolStripMenuItem->Enabled = false; + this->runToolStripMenuItem->Enabled = true; + time_t now = time(NULL); + this->m_board1->seed((int)now); + this->m_board2->seed(this->m_board1); + this->Invalidate(); + } + + void OnRun(System::Object^ sender, System::EventArgs^ e) + { + this->runToolStripMenuItem->Enabled = false; + this->pauseToolStripMenuItem->Enabled = true; + m_seqThread->Start(); + m_parThread->Start(); + } + + void OnPauseResume(System::Object^ sender, System::EventArgs^ e) + { + if (m_suspend) + { + m_seq->SetPause(true); + m_par->SetPause(true); + this->pauseToolStripMenuItem->Text = L"Resume"; + } + else + { + m_seq->SetPause(false); + m_par->SetPause(false); + this->pauseToolStripMenuItem->Text = L"Pause"; + } + m_suspend = !m_suspend; + } + + private: + System::Void menuStrip1_ItemClicked(System::Object^ sender, System::Windows::Forms::ToolStripItemClickedEventArgs^ e) + {} +}; +#endif +#endif diff --git a/src/tbb/examples/parallel_for/game_of_life/src/Game_of_life.cpp b/src/tbb/examples/parallel_for/game_of_life/src/Game_of_life.cpp new file mode 100644 index 0000000..bfb6402 --- /dev/null +++ b/src/tbb/examples/parallel_for/game_of_life/src/Game_of_life.cpp @@ -0,0 +1,238 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + Game_of_life.cpp : + main project file. +*/ +#include "Board.h" +#include "Form1.h" + +#define WIN32_LEAN_AND_MEAN + +#ifndef _CONSOLE +#include +#else +#include +#include +#include +#include "Evolution.h" + +#define BOARD_SQUARE_SIZE 2 + +int low; //! lower range limit of threads +int high; //! high range limit of threads +double execution_time; //! time for game of life iterations +#endif + +Board::Board(int width, int height, int squareSize, LabelPtr counter) +: m_width(width), m_height(height), m_squareSize(squareSize), m_counter(counter) +{ +#ifndef _CONSOLE + InitializeComponent(); + DoubleBuffered = true; + + this->Width = m_squareSize*width; + this->Height = m_squareSize*height; +#endif + m_matrix = new Matrix(); + m_matrix->width = width; + m_matrix->height = height; + m_matrix->data = new char[width*height]; + memset(m_matrix->data, 0, width*height); +#ifndef _CONSOLE + m_occupiedBrush = gcnew SolidBrush(Color::Black); + m_freeBrush = gcnew SolidBrush(Color::LightGray); + + m_graphics = CreateGraphics(); + m_bmp = gcnew Bitmap(Width, Height); + m_mem_dc = Graphics::FromImage(m_bmp); +#endif +} + +Board::~Board() +{ +#ifndef _CONSOLE + if (components) + { + delete components; + } +#endif + delete[] m_matrix->data; + delete m_matrix; +} + +void Board::seed(int s) +{ + srand(s); + for (int j=0; jdata[i+j*m_width] = x>75? 1: 0; // 25% occupied + } + } +#ifndef _CONSOLE + Invalidate(); +#endif +} + +void Board::seed( const BoardPtr src ) +{ + memcpy(m_matrix->data, src->m_matrix->data, m_height*m_width); +#ifndef _CONSOLE + Invalidate(); +#endif +} + +#ifndef _CONSOLE +void Board::draw(Graphics^ g) +{ + m_mem_dc->FillRectangle(m_freeBrush, Drawing::Rectangle(0, 0, m_width*m_squareSize, m_height*m_squareSize)); + for (int j=0; jdata[i+j*m_width] ) + { + m_mem_dc->FillRectangle(m_occupiedBrush, Drawing::Rectangle(i*m_squareSize, j*m_squareSize, m_squareSize, m_squareSize)); + } + } + } + g->DrawImage(m_bmp, 0, 0); +} + +void Board::OnPaint(PaintEventArgs^ e) +{ + draw(e->Graphics); +} + +[STAThreadAttribute] +int main(array ^args) +{ + // Enabling Windows XP visual effects before any controls are created + Application::EnableVisualStyles(); + Application::SetCompatibleTextRenderingDefault(false); + + // Create the main window and run it + Application::Run(gcnew Form1()); + return 0; +} +#else + +//! Print usage of this program +void PrintUsage() +{ + printf("Usage: gol [M[:N] -t execution_time]\nM and N are a range of numbers of threads to be used.\nexecution_time is a time (in sec) for execution game_of_life iterations\n"); + printf("Default values:\nM:\t\tautomatic\nN:\t\tM\nexecution_time:\t10\n"); +} + +//! Parse command line +bool ParseCommandLine(int argc, char * argv []) +{ + char* s = argv[1]; + char* end; + //! command line without parameters + if(argc == 1) + { + low = tbb::task_scheduler_init::automatic; + high = low; + execution_time = 5; + return true; + } + //! command line with parameters + if(argc != 4) + { + PrintUsage(); + return false; + } + if(std::string("-t") != argv[argc-2]) + //! process M[:N] parameter + high = strtol(s,&end,0); + low = strtol(s,&end,0); + switch( *end ) + { + case ':': + high = strtol(end+1,0,0); + break; + case '\0': + break; + default: + PrintUsage(); + return false; + } + if (high < low) + { + std::cout << "Set correct range. Current range: " << low << ":" << high << std::endl; + PrintUsage(); + return false; + + } + //! process execution_time parameter + execution_time = strtol(argv[argc-1],&end,0); + return true; +} + +int main( int argc, char* argv[] ) +{ + if(!ParseCommandLine( argc, argv )) + return 1; + SequentialEvolution* m_seq; + ParallelEvolution* m_par; + Board* m_board1; + Board* m_board2; + int* count = NULL; + + int boardWidth = 300; + int boardHeight = 300; + + m_board1 = new Board(boardWidth, boardHeight, BOARD_SQUARE_SIZE, count); + m_board2 = new Board(boardWidth, boardHeight, BOARD_SQUARE_SIZE, count); + + time_t now = time(NULL); + printf("Generate Game of life board\n"); + m_board1->seed((int)now); + m_board2->seed(m_board1); + + m_seq = new SequentialEvolution(m_board1->m_matrix, m_board1); + m_seq->Run(execution_time, 1); + delete m_seq; + + m_par = new ParallelEvolution(m_board2->m_matrix, m_board2); + for( int p = low; p <= high; ++p ) + { + m_par->Run(execution_time, p); + } + delete m_par; + + delete m_board1; + delete m_board2; + return 0; +} +#endif diff --git a/src/tbb/examples/parallel_for/game_of_life/src/Update_state.cpp b/src/tbb/examples/parallel_for/game_of_life/src/Update_state.cpp new file mode 100644 index 0000000..594391a --- /dev/null +++ b/src/tbb/examples/parallel_for/game_of_life/src/Update_state.cpp @@ -0,0 +1,410 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "Evolution.h" + +#ifdef USE_SSE +/* Update states with SSE */ + +#include +#include + +inline void create_record( char * src, unsigned * dst, unsigned width) +{ + dst[0] |= src[width - 1]; + for( unsigned a=0; a<31u; ++a ) + dst[0] |= src[a]<<(a+1); + unsigned a; + for( a=31u; a>=31; + X[ind] =_mm_or_si128( _mm_slli_epi16(X[ind],1), + _mm_srli_epi16( _mm_slli_si128( X[ind], 2), 15) ); + + unsigned x1 = X[ind + 1].m128i_u32[3]; x1>>=31; + X[ind + 1] =_mm_or_si128( _mm_slli_epi16(X[ind + 1],1), + _mm_srli_epi16( _mm_slli_si128( X[ind + 1], 2), 15) ); + X[ind + 1].m128i_u32[0] |= x0; + + unsigned* dst = (unsigned*)&X[ind]; + unsigned x2 = dst[301/32u] & (1<<(301%32u)); x2>>=(301%32u); + X[ind + 2] =_mm_or_si128( _mm_slli_epi16(X[ind + 2],1), + _mm_srli_epi16( _mm_slli_si128( X[ind + 2], 2), 15) ); + X[ind + 2].m128i_u32[0] |= x1; + X[ind].m128i_u32[0] |= x2; + } +} + +void UpdateState(Matrix * m_matrix, char * dest ,int begin, int end) +{ + //300/128 + 1 =3, 3*300=900 + unsigned size_sse_row = m_matrix->width/128 + 1; //3 + unsigned size_sse_ar=size_sse_row * (end - begin); + __m128i X[906], A[900], B[900], C[900]; + char * mas = m_matrix->data; + + for( unsigned i=0; iwidth; + for( unsigned b = 0 ; b < height; ++b ) + { + char* src = &mas[(b + begin)*width]; + unsigned* dst = (unsigned*)&X[(b+1)*size_sse_row]; + create_record(src, dst, width); + } + // create high row in X[] + char * src; + if(begin == 0) + { + src = &mas[(m_matrix->height-1)*width]; + } + else + { + src = &mas[(begin-1)*width]; + } + unsigned* dst = (unsigned*)X; + create_record(src, dst, width); + + //create lower row in X[] + if(end == m_matrix->height ) + { + src = mas; + } + else + { + src = &mas[end*width]; + } + dst = (unsigned*)&X[(height+1)*size_sse_row]; + create_record(src, dst, width); + + //sum( C, B, A, X+offset_for_upwards ); high-left friend + sum_offset(X,A,B,C,size_sse_ar, 0); + + //sum( C, B, A, X+offset_for_no_vertical_shift ); + sum_offset(X,A,B,C,size_sse_ar, size_sse_row); + + //sum( C, B, A, X+offset_for_downwards ); + sum_offset(X,A,B,C,size_sse_ar, 2*size_sse_row); + + //shift_left( X ); (when view 2D) in our logic it is in right + height = end - begin + 2; + shift_left2D( X, height, size_sse_row); + + //sum( C, B, A, X+offset_for_upwards ); high-left friend + sum_offset(X,A,B,C,size_sse_ar, 0); + + //sum( C, B, A, X+offset_for_downwards ); + sum_offset(X,A,B,C,size_sse_ar, 2*size_sse_row); + + //shift_left( X ); (view in 2D) in our logic it is right shift + height = end - begin + 2; + shift_left2D( X, height, size_sse_row); + + //sum( C, B, A, X+offset_for_upwards ); high-right friend + sum_offset(X,A,B,C,size_sse_ar, 0); + + //sum( C, B, A, X+offset_for_no_vertical_shift ); right friend + sum_offset(X,A,B,C,size_sse_ar, size_sse_row); + + //sum( C, B, A, X+offset_for_downwards ); right down friend + sum_offset(X,A,B,C,size_sse_ar, 2*size_sse_row); + + //shift_right( X ); (when view in 2D) in our case it left shift. + height = end - begin + 2; + shift_right2D( X, height, size_sse_row); + + //X = (X|A)&B&~C (done bitwise over the arrays) + unsigned shift = size_sse_row; + for(unsigned i=0; iwidth; + for( unsigned b=0; b>(a%32u); + } + } +} +#else +/* end SSE block */ + +// ---------------------------------------------------------------------- +// GetAdjacentCellState() - returns the state (value) of the specified +// adjacent cell of the current cell "cellNumber" +char GetAdjacentCellState( + char* source, // pointer to source data block + int x, // logical width of field + int y, // logical height of field + int cellNumber, // number of cell position to examine + int cp // which adjacent position + ) +{ +/* +cp +*-- cp=1 ... --- cp=8 (summary: -1-2-3- +-x- -x- -4-x-5- +--- --* -6-7-8- ) +*/ + char cellState = 0; // return value + + // set up boundary flags to trigger field-wrap logic + bool onTopRow = false; + bool onBottomRow = false; + bool onLeftColumn = false; + bool onRightColumn = false; + + // check to see if cell is on top row + if (cellNumber < x) + { + onTopRow = true; + } + // check to see if cell is on bottom row + if ((x*y)-cellNumber <= x) + { + onBottomRow = true; + } + // check to see if cell is on left column + if (cellNumber%x == 0) + { + onLeftColumn = true; + } + // check to see if cell is on right column + if ((cellNumber+1)%x == 0) + { + onRightColumn = true; + } + + switch (cp) + { + case 1: + if (onTopRow && onLeftColumn) + { + return *(source+((x*y)-1)); + } + if (onTopRow && !onLeftColumn) + { + return *(source+(((x*y)-x)+(cellNumber-1))); + } + if (onLeftColumn && !onTopRow) + { + return *(source+(cellNumber-1)); + } + return *((source+cellNumber)-(x+1)); + + case 2: + if (onTopRow) + { + return *(source+(((x*y)-x)+cellNumber)); + } + return *((source+cellNumber)-x); + + case 3: + if (onTopRow && onRightColumn) + { + return *(source+((x*y)-x)); + } + if (onTopRow && !onRightColumn) + { + return *(source+(((x*y)-x)+(cellNumber+1))); + } + if (onRightColumn && !onTopRow) + { + return *(source+((cellNumber-(x*2))+1)); + } + return *(source+(cellNumber-(x-1))); + + case 4: + if (onRightColumn) + { + return *(source+(cellNumber-(x-1))); + } + return *(source+(cellNumber+1)); + + case 5: + if (onBottomRow && onRightColumn) + { + return *source; + } + if (onBottomRow && !onRightColumn) + { + return *(source+((cellNumber-((x*y)-x))+1)); + } + if (onRightColumn && !onBottomRow) + { + return *(source+(cellNumber+1)); + } + return *(source+(((cellNumber+x))+1)); + + case 6: + if (onBottomRow) + { + return *(source+(cellNumber-((x*y)-x))); + } + return *(source+(cellNumber+x)); + + case 7: + if (onBottomRow && onLeftColumn) + { + return *(source+(x-1)); + } + if (onBottomRow && !onLeftColumn) + { + return *(source+(cellNumber-((x*y)-x)-1)); + } + if (onLeftColumn && !onBottomRow) + { + return *(source+(cellNumber+((x*2)-1))); + } + return *(source+(cellNumber+(x-1))); + + case 8: + if (onLeftColumn) + { + return *(source+(cellNumber+(x-1))); + } + return *(source+(cellNumber-1)); + } + return cellState; +} + +char CheckCell(Matrix * m_matrix, int cellNumber) +{ + char total = 0; + char* source = m_matrix->data; + //look around to find cell's with status "alive" + for(int i=1; i<9; i++) + { + total += GetAdjacentCellState(source, m_matrix->width, m_matrix->height, cellNumber, i); + } + // if the number of adjacent live cells is < 2 or > 3, the result is a dead + // cell regardless of its current state. (A live cell dies of loneliness if it + // has less than 2 neighbors, and of overcrowding if it has more than 3; a new + // cell is born in an empty spot only if it has exactly 3 neighbors. + if (total < 2 || total > 3) + { + return 0; + } + + // if we get here and the cell position holds a living cell, it stays alive + if (*(source+cellNumber)) + { + return 1; + } + + // we have an empty position. If there are only 2 neighbors, the position stays + // empty. + if (total == 2) + { + return 0; + } + + // we have an empty position and exactly 3 neighbors. A cell is born. + return 1; +} + +void UpdateState(Matrix * m_matrix, char * dest ,int begin, int end) +{ + for (int i=begin; i<=end; i++) + { + *(dest+i) = CheckCell(m_matrix, i); + } +} + +#endif +/* end non-SSE block */ diff --git a/src/tbb/examples/parallel_for/game_of_life/xcode/game_of_life.xcodeproj/project.pbxproj b/src/tbb/examples/parallel_for/game_of_life/xcode/game_of_life.xcodeproj/project.pbxproj new file mode 100644 index 0000000..1c1cd6a --- /dev/null +++ b/src/tbb/examples/parallel_for/game_of_life/xcode/game_of_life.xcodeproj/project.pbxproj @@ -0,0 +1,317 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 612CD8DD11F573FC00A587B2 /* Game_of_life.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 612CD8DB11F573FC00A587B2 /* Game_of_life.cpp */; }; + 612CD8DE11F573FC00A587B2 /* Update_state.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 612CD8DC11F573FC00A587B2 /* Update_state.cpp */; }; + 612CD8E111F5742000A587B2 /* Evolution.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 612CD8E011F5742000A587B2 /* Evolution.cpp */; }; + A1F593B70B8F06F900073279 /* libtbb.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; + A1F593BB0B8F072500073279 /* libtbb.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8DD76F690486A84900D96B5E /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = ""; + dstSubfolderSpec = 16; + files = ( + A1F593BB0B8F072500073279 /* libtbb.dylib in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 612CD8DB11F573FC00A587B2 /* Game_of_life.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Game_of_life.cpp; path = ../src/Game_of_life.cpp; sourceTree = SOURCE_ROOT; }; + 612CD8DC11F573FC00A587B2 /* Update_state.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Update_state.cpp; path = ../src/Update_state.cpp; sourceTree = SOURCE_ROOT; }; + 612CD8E011F5742000A587B2 /* Evolution.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Evolution.cpp; path = ../src/Evolution.cpp; sourceTree = SOURCE_ROOT; }; + 8DD76F6C0486A84900D96B5E /* game_of_life */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = game_of_life; sourceTree = BUILT_PRODUCTS_DIR; }; + A1F593B30B8F06F900073279 /* libtbb.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtbb.dylib; path = ../../../../lib/libtbb.dylib; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8DD76F660486A84900D96B5E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A1F593B70B8F06F900073279 /* libtbb.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* game_of_life */ = { + isa = PBXGroup; + children = ( + 08FB7795FE84155DC02AAC07 /* Source */, + A1F593B20B8F06F900073279 /* External Frameworks and Libraries */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + ); + name = game_of_life; + sourceTree = ""; + }; + 08FB7795FE84155DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + 612CD8E011F5742000A587B2 /* Evolution.cpp */, + 612CD8DB11F573FC00A587B2 /* Game_of_life.cpp */, + 612CD8DC11F573FC00A587B2 /* Update_state.cpp */, + ); + name = Source; + sourceTree = ""; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8DD76F6C0486A84900D96B5E /* game_of_life */, + ); + name = Products; + sourceTree = ""; + }; + A1F593B20B8F06F900073279 /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + A1F593B30B8F06F900073279 /* libtbb.dylib */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8DD76F620486A84900D96B5E /* game_of_life */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "game_of_life" */; + buildPhases = ( + 8DD76F640486A84900D96B5E /* Sources */, + 8DD76F660486A84900D96B5E /* Frameworks */, + 8DD76F690486A84900D96B5E /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = game_of_life; + productInstallPath = "$(HOME)/bin"; + productName = game_of_life; + productReference = 8DD76F6C0486A84900D96B5E /* game_of_life */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0410; + }; + buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "game_of_life" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 08FB7794FE84155DC02AAC07 /* game_of_life */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DD76F620486A84900D96B5E /* game_of_life */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 8DD76F640486A84900D96B5E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 612CD8DD11F573FC00A587B2 /* Game_of_life.cpp in Sources */, + 612CD8DE11F573FC00A587B2 /* Update_state.cpp in Sources */, + 612CD8E111F5742000A587B2 /* Evolution.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1DEB923208733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = _CONSOLE; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = game_of_life; + ZERO_LINK = NO; + }; + name = Debug; + }; + 1DEB923308733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_PREPROCESSOR_DEFINITIONS = _CONSOLE; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = game_of_life; + ZERO_LINK = NO; + }; + name = Release; + }; + 1DEB923608733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Debug; + }; + 1DEB923708733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Release; + }; + A1F593C60B8F0E6E00073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = _CONSOLE; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = game_of_life; + ZERO_LINK = NO; + }; + name = Debug64; + }; + A1F593C70B8F0E6E00073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_PREPROCESSOR_DEFINITIONS = _CONSOLE; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = game_of_life; + ZERO_LINK = NO; + }; + name = Release64; + }; + A1F593C80B8F0E6E00073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-m64", + ); + OTHER_LDFLAGS = "-m64"; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Debug64; + }; + A1F593C90B8F0E6E00073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-m64", + ); + OTHER_LDFLAGS = "-m64"; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Release64; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "game_of_life" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923208733DC60010E9CD /* Debug */, + A1F593C60B8F0E6E00073279 /* Debug64 */, + 1DEB923308733DC60010E9CD /* Release */, + A1F593C70B8F0E6E00073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "game_of_life" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923608733DC60010E9CD /* Debug */, + A1F593C80B8F0E6E00073279 /* Debug64 */, + 1DEB923708733DC60010E9CD /* Release */, + A1F593C90B8F0E6E00073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/src/tbb/examples/parallel_for/index.html b/src/tbb/examples/parallel_for/index.html new file mode 100644 index 0000000..64078eb --- /dev/null +++ b/src/tbb/examples/parallel_for/index.html @@ -0,0 +1,30 @@ + + + +

    Overview

    +This directory has examples of the template parallel_for. + +

    Directories

    +
    +
    seismic +
    Parallel seismic wave simulation. +
    tachyon +
    Parallel 2-D raytracer/renderer. +
    polygon_overlay +
    Simple polygon overlay. +
    game_of_life +
    Simple Game of life overlay. +
    + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + + diff --git a/src/tbb/examples/parallel_for/polygon_overlay/Makefile b/src/tbb/examples/parallel_for/polygon_overlay/Makefile new file mode 100644 index 0000000..e73f0d8 --- /dev/null +++ b/src/tbb/examples/parallel_for/polygon_overlay/Makefile @@ -0,0 +1,96 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# GNU Makefile that builds and runs example. +NAME=pover +ARGS= +LIGHT_ARGS= --polys 10 --size 5x5 + +# The C++ compiler +ifneq (,$(shell which icc 2>/dev/null)) +CXX=icc +endif # icc + +include ../../common/gui/Makefile.gmake + +ifeq ($(UI),x) +UI_CXXFLAGS += -DX_FULLSYNC +endif # X + +override CXXFLAGS += $(UI_CXXFLAGS) + +SRCFILES = ../../common/gui/$(UI)video.cpp pover_video.cpp polymain.cpp polyover.cpp + +ifeq ($(shell uname), Linux) +LIBS+= -lrt +endif + +all: release test + +resources: +ifeq ($(UI),mac) + mkdir -p $(APPRES)/en.lproj $(NAME).app/Contents/MacOS + cp ../../common/gui/xcode/tbbExample/Info.plist $(NAME).app/Contents + cp ../../common/gui/xcode/tbbExample/PkgInfo $(NAME).app/Contents + cp ../../common/gui/xcode/tbbExample/en.lproj/* $(APPRES)/en.lproj +endif # Mac + +release: $(SRCFILES) resources +ifeq ($(compiler),xl) + # Avoiding "1586-346 (U) An error occurred during code generation. The code generation return code was 40." with -O3. + $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(EXE) $(SRCFILES) -ltbb -ltbbmalloc $(LIBS) +else +ifeq ($(UI),mac) + $(CXX_UI) -O3 -DNDEBUG $(CXXFLAGS) -c $(MACUISOURCES) +endif # Mac + $(CXX) -O3 -DNDEBUG $(CXXFLAGS) -o $(EXE) $(SRCFILES) $(MACUIOBJS) -ltbb -ltbbmalloc $(LIBS) +endif + +debug: $(SRCFILES) resources +ifeq ($(UI),mac) + $(CXX_UI) -g -O0 -DTBB_USE_DEBUG -D_DEBUG $(CXXFLAGS) -c $(MACUISOURCES) +endif # Mac + $(CXX) -g -O0 -DTBB_USE_DEBUG -D_DEBUG $(CXXFLAGS) -o $(EXE) $(SRCFILES) $(MACUIOBJS) -ltbb_debug -ltbbmalloc_debug $(LIBS) + +clean: + $(RM) $(EXE) *.o *.d +ifeq ($(UI),mac) + rm -rf $(NAME).app +endif + +test: +ifeq ($(UI),mac) + export DYLD_LIBRARY_PATH="$(DYLD_LIBRARY_PATH):$(TBBLIBSPATH)"; ./$(EXE) $(ARGS) +else + ./$(EXE) $(ARGS) +endif + +light_test: +ifeq ($(UI),mac) + export DYLD_LIBRARY_PATH="$(DYLD_LIBRARY_PATH):$(TBBLIBSPATH)"; ./$(EXE) $(LIGHT_ARGS) +else + ./$(EXE) $(LIGHT_ARGS) +endif diff --git a/src/tbb/examples/parallel_for/polygon_overlay/Makefile.windows b/src/tbb/examples/parallel_for/polygon_overlay/Makefile.windows new file mode 100644 index 0000000..3f344fe --- /dev/null +++ b/src/tbb/examples/parallel_for/polygon_overlay/Makefile.windows @@ -0,0 +1,68 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Common Makefile that builds and runs example. + +# Just specify your program basename +PROG=Pover +ARGS= +LIGHT_ARGS= --polys 10 --size 5x5 + +# Trying to find if icl.exe is set +CXX1 = $(TBB_CXX)- +CXX2 = $(CXX1:icl.exe-=icl.exe) +CXX = $(CXX2:-=cl.exe) + +# The C++ compiler options + +# Uncomment one of next lines to choose user interface type (console, gdiplus, direct draw) +#UI = con +UI = gdi +#UI = dd + +# Machine architecture, auto-detected from TBB_TARGET_ARCH by default +# Use XARCH variable to change it. See index.html for more information +ARCH0 = $(TBB_TARGET_ARCH)- +ARCH1 = $(ARCH0:ia32-=x86) +ARCH2 = $(ARCH1:intel64-=AMD64) +XARCH = $(ARCH2:-=x86) + +MAKEINC = ../../common/gui/Makefile.win + +all: release test +release: compiler_check + @$(MAKE) -f $(MAKEINC) UI=$(UI) CXX="$(CXX)" CXXFLAGS="$(CXXFLAGS)" LFLAGS="$(LDFLAGS) tbb.lib tbbmalloc.lib $(LIBS)" XARCH=$(XARCH) RCNAME=pover SOURCE=*.cpp EXE=$(PROG).exe build_one +debug: compiler_check + @$(MAKE) -f $(MAKEINC) UI=$(UI) DEBUG=_debug CXX="$(CXX)" CXXFLAGS="$(CXXFLAGS) /D TBB_USE_DEBUG" LFLAGS="$(LDFLAGS) tbb_debug.lib tbbmalloc_debug.lib $(LIBS)" XARCH=$(XARCH) RCNAME=pover SOURCE=*.cpp EXE=$(PROG).exe build_one +clean: + @cmd.exe /C del $(PROG).exe *.obj *.?db *.manifest msvs\pover.res +test: + $(PROG) $(ARGS) +light_test: + $(PROG) $(LIGHT_ARGS) +compiler_check: + @echo compiler_test>compiler_test && @$(CXX) /E compiler_test >nul 2>&1 || echo "$(CXX) command not found. Check if CXX=$(CXX) is set properly" + @cmd.exe /C del compiler_test diff --git a/src/tbb/examples/parallel_for/polygon_overlay/index.html b/src/tbb/examples/parallel_for/polygon_overlay/index.html new file mode 100644 index 0000000..2dd18c9 --- /dev/null +++ b/src/tbb/examples/parallel_for/polygon_overlay/index.html @@ -0,0 +1,121 @@ + + + +

    Overview

    +Polygon Overlay example that demonstrates the use of parallel_for. +

    +This example is a simple implementation of polygon overlay, as described in + + Parallelizing the Polygon Overlay Problem Using Orca, by H.F. Langendoen. +

    +The solution was implemented in three forms: +
      +
    • The naive serial solution. +
    • The naive parallel solution, by splitting list of polygons from one map and intersecting + each sub-list against the entire list of polygons from the second map. +
    • A parallel solution where each map is split into submaps, with each resulting submap being + intersected against the corresponding submap from the other map. This solution requires some + redundancy (some polygons are members of more than one submap). To prevent multiple copies + of a polygon from being placed in the solution map, if both polygons are duplicated (that is, + if they both appear in more than one map), they are intersected but the result is not placed + in the solution map. +
    +The only optimization in each solution is that the area of the generated sub-polygons are subtracted from +the original area of one of the source polygons. When the remaining area is zero, the intersection process +is halted. +

    +A word about the speedup of the submap case. One may get superlinear speedup in this case (for instance a +laptop with Intel® Core(TM) Duo processor got a speedup of about 20 percent over serial.) This results from two effects: +

    +
      +
    • the number of threads used, and +
    • the fact that for each submap, the number of polygons is smaller than that for the other two cases. +
    +If there are, say, 400 polygons in each map, then on average the number of intersections calculated is +approximately 80,000 (400 * 200, where 200 is the average number of polygons examined before stopping.) +If the maps are split into 2 submaps, the time for each submap is about 200*100, or 20,000. So even +comparing the two sets of submaps serially should result in a speedup somewhere around 2. This number +is affected by the number of redundant polygons being compared; this effect would eventually swamp the gain +from comparing smaller numbers of polygons per submap. And remember the submaps are created by intersecting each +map with a rectangular polygon covering the submap being generated, which is additional work taking about N * O(400) +in the case above, where N is the number of submaps generated, that can be done in parallel. +

    +Running the default release pover while varying the number of submaps from 1 to 1000, the speedup on the submap +case for a 2-processor system looks like
    +Table of speedup for the algorithm
    +

    +

    +One further optimization would be to sort one map, say map1, by maxY, and sort the other map (map2) +by minY. For p1 in map1, start testing for intersection at the first p2 in map2 +that intersected the last polygon tested in map1. This would speed up the intersection process greatly, +but the optimization would apply to all the methods, and the sort would have to be accounted for in the timing. +

    +

    +The source maps are generated pseudo-randomly in the manner described in the paper above. That is, if +we need N polygons, then N "boxes" are chosen at random, then one-at-a-time the areas are expanded in +one of fours directions until the area hits an adjacent polygon. When this process is finished, the +resulting map is inspected and any remaining unoccupied "boxes" are made into additional polygons, as +large as possible in each case. So the actual number of polygons in each map will in general be larger +than the number of polygons requested (sometimes by 10% or more.) +

    +

    +One limitation of the program is that if the number of polygons in the source map is greater than the number of +"boxes" (pixels in the GUI case), the maps cannot be generated. +

    + +

    Files

    +
    +
    polyover.cpp +
    Source code for main program. +
    polyover.h +
    Global variables, classes and enums. +
    pover_video.cpp +
    Source code for the GUI interface. +
    pover_video.h +
    Defines for the GUI version. +
    Makefile +
    Makefile for building example. +
    + +

    Directories

    +
    +
    msvs +
    Contains Microsoft* Visual Studio* 2005 workspace for building and running the + example (Windows* systems only).
    xcode +
    Contains Xcode* IDE workspace for building and running the example (Mac OS* X + systems only).
    + +

    To Build

    +General build directions can be found here. For the various UI options, see the common GUI code build instructions. + +

    Usage

    +Building via the above make commands, or via Visual Studio projects on Windows* systems, produces executable files +named pover.exe. To run these executables directly, use one or more of the following commands. +
    +
    pover.exe +
    Run this version (release or debug). +
    pover.exe n:m +
    Run this version (release or debug) (m-n+1) times, with n threads to m threads inclusive. +
    To run a short version of this example, e.g., for use with Intel® Threading Tools: +
    Build a debug version with the GUI turned off + (e.g., make UI=con debug; see also the build directions above). +
    Run it with a small dataset, e.g., pover.exe --polys 10 --size 5x5. +
    + +

    Notes

    +
      +
    • While running with the GUI display should yield reasonable performance in most cases, running with no GUI + display is strongly recommended in order to demonstrate the full performance and scalability of the example. +
    + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + diff --git a/src/tbb/examples/parallel_for/polygon_overlay/msvs/pover.icproj b/src/tbb/examples/parallel_for/polygon_overlay/msvs/pover.icproj new file mode 100644 index 0000000..d8886d7 --- /dev/null +++ b/src/tbb/examples/parallel_for/polygon_overlay/msvs/pover.icproj @@ -0,0 +1,11 @@ + + + + + diff --git a/src/tbb/examples/parallel_for/polygon_overlay/msvs/pover.rc b/src/tbb/examples/parallel_for/polygon_overlay/msvs/pover.rc new file mode 100644 index 0000000..3eee795 --- /dev/null +++ b/src/tbb/examples/parallel_for/polygon_overlay/msvs/pover.rc @@ -0,0 +1,61 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE 9, 1 +#pragma code_page(1252) + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/tbb/examples/parallel_for/polygon_overlay/msvs/pover.vcproj b/src/tbb/examples/parallel_for/polygon_overlay/msvs/pover.vcproj new file mode 100644 index 0000000..ac773e3 --- /dev/null +++ b/src/tbb/examples/parallel_for/polygon_overlay/msvs/pover.vcproj @@ -0,0 +1,832 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/parallel_for/polygon_overlay/msvs/pover_cl.sln b/src/tbb/examples/parallel_for/polygon_overlay/msvs/pover_cl.sln new file mode 100644 index 0000000..50f9b86 --- /dev/null +++ b/src/tbb/examples/parallel_for/polygon_overlay/msvs/pover_cl.sln @@ -0,0 +1,37 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pover", "pover.vcproj", "{4BB7B455-1E09-41D3-BC89-6E67C9032F8C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + DD Debug|Win32 = DD Debug|Win32 + DD Debug|x64 = DD Debug|x64 + DD Release|Win32 = DD Release|Win32 + DD Release|x64 = DD Release|x64 + GDI Debug|Win32 = GDI Debug|Win32 + GDI Debug|x64 = GDI Debug|x64 + _GDI Release|Win32 = _GDI Release|Win32 + _GDI Release|x64 = _GDI Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.DD Debug|Win32.ActiveCfg = DD Debug|Win32 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.DD Debug|Win32.Build.0 = DD Debug|Win32 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.DD Debug|x64.ActiveCfg = DD Debug|x64 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.DD Debug|x64.Build.0 = DD Debug|x64 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.DD Release|Win32.ActiveCfg = DD Release|Win32 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.DD Release|Win32.Build.0 = DD Release|Win32 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.DD Release|x64.ActiveCfg = DD Release|x64 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.DD Release|x64.Build.0 = DD Release|x64 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.GDI Debug|Win32.Build.0 = Debug|Win32 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.GDI Debug|x64.ActiveCfg = Debug|x64 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.GDI Debug|x64.Build.0 = Debug|x64 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}._GDI Release|Win32.ActiveCfg = Release|Win32 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}._GDI Release|Win32.Build.0 = Release|Win32 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}._GDI Release|x64.ActiveCfg = Release|x64 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}._GDI Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/parallel_for/polygon_overlay/msvs/pover_icl.sln b/src/tbb/examples/parallel_for/polygon_overlay/msvs/pover_icl.sln new file mode 100644 index 0000000..bf88dd2 --- /dev/null +++ b/src/tbb/examples/parallel_for/polygon_overlay/msvs/pover_icl.sln @@ -0,0 +1,53 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "pover", "pover.icproj", "{B175D396-7260-45F8-9E18-842ED8A32A16}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + DD Debug|Win32 = DD Debug|Win32 + DD Debug|x64 = DD Debug|x64 + DD Release|Win32 = DD Release|Win32 + DD Release|x64 = DD Release|x64 + GDI Debug|Win32 = GDI Debug|Win32 + GDI Debug|x64 = GDI Debug|x64 + _GDI Release|Win32 = _GDI Release|Win32 + _GDI Release|x64 = _GDI Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B175D396-7260-45F8-9E18-842ED8A32A16}.DD Debug|Win32.ActiveCfg = DD Debug|Win32 + {B175D396-7260-45F8-9E18-842ED8A32A16}.DD Debug|Win32.Build.0 = DD Debug|Win32 + {B175D396-7260-45F8-9E18-842ED8A32A16}.DD Debug|x64.ActiveCfg = DD Debug|x64 + {B175D396-7260-45F8-9E18-842ED8A32A16}.DD Debug|x64.Build.0 = DD Debug|x64 + {B175D396-7260-45F8-9E18-842ED8A32A16}.DD Release|Win32.ActiveCfg = DD Release|Win32 + {B175D396-7260-45F8-9E18-842ED8A32A16}.DD Release|Win32.Build.0 = DD Release|Win32 + {B175D396-7260-45F8-9E18-842ED8A32A16}.DD Release|x64.ActiveCfg = DD Release|x64 + {B175D396-7260-45F8-9E18-842ED8A32A16}.DD Release|x64.Build.0 = DD Release|x64 + {B175D396-7260-45F8-9E18-842ED8A32A16}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {B175D396-7260-45F8-9E18-842ED8A32A16}.GDI Debug|Win32.Build.0 = Debug|Win32 + {B175D396-7260-45F8-9E18-842ED8A32A16}.GDI Debug|x64.ActiveCfg = Debug|x64 + {B175D396-7260-45F8-9E18-842ED8A32A16}.GDI Debug|x64.Build.0 = Debug|x64 + {B175D396-7260-45F8-9E18-842ED8A32A16}._GDI Release|Win32.ActiveCfg = Release|Win32 + {B175D396-7260-45F8-9E18-842ED8A32A16}._GDI Release|Win32.Build.0 = Release|Win32 + {B175D396-7260-45F8-9E18-842ED8A32A16}._GDI Release|x64.ActiveCfg = Release|x64 + {B175D396-7260-45F8-9E18-842ED8A32A16}._GDI Release|x64.Build.0 = Release|x64 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}._GDI Release|x64.Build.0 = Release|x64 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}._GDI Release|x64.ActiveCfg = Release|x64 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}._GDI Release|Win32.Build.0 = Release|Win32 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}._GDI Release|Win32.ActiveCfg = Release|Win32 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.GDI Debug|x64.Build.0 = Debug|x64 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.GDI Debug|x64.ActiveCfg = Debug|x64 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.GDI Debug|Win32.Build.0 = Debug|Win32 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.DD Release|x64.Build.0 = DD Release|x64 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.DD Release|x64.ActiveCfg = DD Release|x64 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.DD Release|Win32.Build.0 = DD Release|Win32 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.DD Release|Win32.ActiveCfg = DD Release|Win32 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.DD Debug|x64.Build.0 = DD Debug|x64 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.DD Debug|x64.ActiveCfg = DD Debug|x64 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.DD Debug|Win32.Build.0 = DD Debug|Win32 + {4BB7B455-1E09-41D3-BC89-6E67C9032F8C}.DD Debug|Win32.ActiveCfg = DD Debug|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/parallel_for/polygon_overlay/msvs/resource.h b/src/tbb/examples/parallel_for/polygon_overlay/msvs/resource.h new file mode 100644 index 0000000..e70b4ea --- /dev/null +++ b/src/tbb/examples/parallel_for/polygon_overlay/msvs/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by pover.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/tbb/examples/parallel_for/polygon_overlay/polymain.cpp b/src/tbb/examples/parallel_for/polygon_overlay/polymain.cpp new file mode 100644 index 0000000..6cb1257 --- /dev/null +++ b/src/tbb/examples/parallel_for/polygon_overlay/polymain.cpp @@ -0,0 +1,628 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Polygon overlay +// +// Don't want warnings about deprecated sscanf, getenv +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE +#endif +#define _MAIN_C_ 1 +#include +#include +#include +#include + +#include "tbb/tick_count.h" +#include "tbb/task_scheduler_init.h" +#include "pover_global.h" +#include "polyover.h" +#include "pover_video.h" +#include "polymain.h" + +using namespace std; + +#if _DEBUG +const char *faceNames[] = { "North", "East", "South", "West" }; +#endif + +/** +**/ +int main( int argc, char **argv) { + pover_video poly; + poly.threaded = true; + gVideo = &poly; + + if(!initializeVideo(argc, argv)) { + return 1; + } + + gIsGraphicalVersion = poly.graphic_display(); + if(argc > 1) { + if(!ParseCmdLine(argc, argv)) { + if(gIsGraphicalVersion) rt_sleep(10000); + // if graphical, we haven't opened the console window so all the error messages we + // so carefully wrote out disappeared into the ether. :( + exit(1); + } + } + + if(gCsvFilename != NULL) { +#define BUFLEN 1000 + std::string fname_buf = gCsvFilename; + fname_buf += ".csv"; + gCsvFile.open(fname_buf.c_str()); + } + + // we have gMapXSize and gMapYSize determining the number of "squares" + // we have g_xwinsize and g_ywinsize the total size of the window + // we also have BORDER_SIZE the size of the border between maps + // we need to determine + // g_polyBoxSize -- the number of pixels on each size of each square + + if(gIsGraphicalVersion) { + int xpixelsPerMap = (g_xwinsize - 4*BORDER_SIZE) / 3; // three maps, with borders between and outside + gMapXSize = xpixelsPerMap; // make the boxes one per pixel + gPolyXBoxSize = xpixelsPerMap / gMapXSize; + int ypixelsPerMap = (g_ywinsize - 2*BORDER_SIZE); // one map vertically + gMapYSize = ypixelsPerMap; // one pixel per box, rather. + + gPolyYBoxSize = ypixelsPerMap / gMapYSize; + if((gPolyXBoxSize == 0) || (gPolyYBoxSize == 0)) { + cout << "The display window is not large enough to show the maps" << std::endl; + int minxSize = 4*BORDER_SIZE + 3*gMapXSize; + int minySize = 2*BORDER_SIZE + gMapYSize; + cout << " Should be at least " << minxSize << " x " << minySize << "." << std::endl; + return 1; + } + map2XLoc = 2*BORDER_SIZE + gMapXSize * gPolyXBoxSize; + maprXLoc = 3*BORDER_SIZE + 2 * gMapXSize * gPolyXBoxSize; + + } + else { // not gIsGraphicalVersion + // gMapXSize, gMapYSize, gNPolygons defined in pover_global.h + } + + // create two polygon maps + SetRandomSeed(gMyRandomSeed); // for repeatability + + gVideo->main_loop(); +} + +void Usage(int argc, char **argv) { + char *cmdTail = strrchr(*argv, '\\'); + if(cmdTail == NULL) { + cmdTail = *argv; + } + else { + cmdTail++; + } + cout << cmdTail << " [threads[:threads2]] [--polys npolys] [--size nnnxnnn] [--seed nnn]" << std::endl; + cout << "Create polygon maps and overlay them." << std::endl << std::endl; + cout << "Parameters:" << std::endl; + cout << " threads[:threads2] - number of threads to run" << std::endl; + cout << " --polys npolys - number of polygons in each map" << std::endl; + cout << " --size nnnxnnn - size of each map (X x Y)" << std::endl; + cout << " --seed nnn - initial value of random number generator" << std::endl; + cout << " --csv filename - write timing data to CSV-format file" << std::endl; + cout << " --grainsize n - set grainsize to n" << std::endl; + cout << " --use_malloc - allocate polygons with malloc instead of scalable allocator" << std::endl; + cout << std::endl; + cout << "npolys must be smaller than the size of the map" << std::endl; + cout << std::endl; + exit(1); +} + +bool ParseCmdLine(int argc, char **argv ) { + bool error_found = false; + bool nPolysSpecified = false; + bool nMapSizeSpecified = false; + bool nSeedSpecified = false; + bool csvSpecified = false; + bool grainsizeSpecified = false; + bool mallocSpecified = false; + int origArgc = argc; + char** origArgv = argv; + unsigned int newnPolygons = gNPolygons; + unsigned int newSeed = gMyRandomSeed; + unsigned int newX = gMapXSize; + unsigned int newY = gMapYSize; + unsigned int newGrainSize = gGrainSize; + argc--; argv++; + if(argc > 0 && isdigit((*argv)[0])) { + // first argument is one or two numbers, specifying how mny threads to run + char* end; gThreadsHigh = gThreadsLow = (int)strtol(argv[0],&end,0); + switch( *end) { + case ':': gThreadsHigh = (int)strtol(end+1,0,0); break; + case '\0': break; + default: cout << "Unexpected character in thread specifier: " << *end << std::endl; break; + } + if(gThreadsLow > gThreadsHigh) { + int t = gThreadsLow; + gThreadsLow = gThreadsHigh; + gThreadsHigh = t; + } + argv++; argc--; + } + while(argc > 0) { + // format 1: --size nnnxnnn, where nnn in {0 .. 9}+ -- size of map in "squares" + if(!strncmp("--size", *argv, (size_t)6)) { + if(nMapSizeSpecified) { + cout << " Error: map size multiply specified" << std::endl; + error_found = true; + } + else { + argv++; argc--; + if(argc == 0) { + error_found = true; + cout << " Error: --size must have a value" << std::endl; + } + if(strchr(*argv, 'x') != strrchr(*argv,'x')) { + // more than one 'x' + cout << "Error: map size should be nnnxnnn (" << *argv << ")" << std::endl; + error_found = true; + } + else { + int rval; + rval = sscanf(*argv, "%ux%u", &newX, &newY); + if(rval != 2) { + cout << "Error parsing map size (format should be nnnxnnn (" << *argv << ")" << std::endl; + error_found = true; + } + if(newX == 0 || newY == 0) { + cout << "Error: size of map should be greater than 0 (" << *argv << ")" << std::endl; + error_found = true; + } + } + } + argc--; argv++; + } + // format 2: --seed nnn -- initial random number seed + else if(!strncmp("--seed", *argv, (size_t)6)) { + argv++; argc--; + if(nSeedSpecified) { + cout << "Error: new seed multiply specified" << std::endl; + error_found = true; + } + else { + nSeedSpecified = true; + int rtval = sscanf(*argv, "%u", &newSeed); + if(rtval == 0) { + cout << "Error: --seed should be an unsigned number (instead of " << *argv << ")" << std::endl; + error_found = true; + } + } + argv++; argc--; + } + // format 3: --polys n[n] -- number of polygons in each map + else if(!strncmp("--polys", *argv, (size_t)7)) { + //unsigned int newnPolygons; + argv++; argc--; + if(nPolysSpecified) { + cout << "Error: number of polygons multiply-specified" << std::endl; + error_found = true; + }else { + int rtval = sscanf(*argv, "%u", &newnPolygons); + if(newnPolygons == 0) { + cout << "Error: number of polygons must be greater than 0 (" << *argv << ")" << std::endl; + } + } + argv++; argc--; + } + // format 4: --csv -- name of CSV output file ("xxx" for "xxx.csv") + else if(!strncmp("--csv", *argv, (size_t)5)) { + argv++; argc--; + if(csvSpecified) { + cout << "Error: Multiple specification of CSV file" << std::endl; + error_found = true; + } + else { + gCsvFilename = *argv; + argv++; argc--; + csvSpecified = true; + } + } + else if(!strncmp("--grainsize", *argv, (size_t)11)) { + argv++; argc--; + if(grainsizeSpecified) { + cout << "Error: Multiple specification of grainsize" << std::endl; + error_found = true; + } + else { + int grval = sscanf(*argv, "%u", &newGrainSize); + grainsizeSpecified = true; + if(newGrainSize == 0) { + cout << "Error: grainsize must be greater than 0" << std::endl; + error_found = true; + } + } + argv++; argc--; + } + else if(!strncmp("--use_malloc", *argv, (size_t)12)) { + argv++; argc--; + if(mallocSpecified) { + cout << "Error: --use_malloc multiply-specified" << std::endl; + error_found = true; + } + else { + mallocSpecified = true; + gMBehavior = UseMalloc; + } + } + else { + cout << "Error: unrecognized argument: " << *argv << std::endl; + error_found = true; + argv++; argc--; + } + } + if(!error_found) { + if(newX * newY < newnPolygons) { + error_found = true; + cout << "Error: map size should not be smaller than the number of polygons (gNPolygons = " << newnPolygons << ", map size " << newX << "x" << newY << ")" << std::endl; + } + } + if(!error_found) { + gMapXSize = newX; + gMapYSize = newY; + gNPolygons = newnPolygons; + gMyRandomSeed = newSeed; + gGrainSize = (int)newGrainSize; + } + else { + Usage(origArgc, origArgv); + } + return !error_found; +} + +// create a polygon map with at least gNPolygons polygons. +// Usually more than gNPolygons polygons will be generated, because the +// process of growing the polygons results in holes. +bool GenerateMap(Polygon_map_t **newMap, int xSize, int ySize, int gNPolygons, colorcomp_t maxR, colorcomp_t maxG, colorcomp_t maxB) { + bool error_found = false; + int *validPolys; + int *validSide; + int maxSides; + RPolygon *newPoly; + + if(xSize <= 0) { + cout << "xSize (" << xSize << ") should be > 0." << std::endl; + error_found = true; + } + if(ySize <= 0) { + cout << "ySize (" << ySize << ") should be > 0." << std::endl; + error_found = true; + } + if(gNPolygons > (xSize * ySize)) { + cout << "gNPolygons (" << gNPolygons << ") should be less than " << (xSize * ySize) << std::endl; + error_found = true; + } + if(error_found) return false; + // the whole map is [xSize x ySize] squares + // the way we create the map is to + // 1) pick nPolygon discrete squares on an [xSize x ySize] grid + // 2) while there are unused squares on the grid + // 3) pick a polygon with a side that has unused squares on a side + // 4) expand the polygon by 1 to occupy the unused squares + // + // Continue until every square on the grid is occupied by a polygon + int *tempMap; + tempMap = (int *)malloc(xSize * ySize * sizeof(int)); + for(int i=0;i < xSize; i++) { + for(int j=0;j < ySize; j++) { + tempMap[i*ySize + j] = 0; + } + } + + // *newMap = new vector; + *newMap = new Polygon_map_t; + (*newMap)->reserve(gNPolygons + 1); // how much bigger does this need to be on average? + (*newMap)->push_back(RPolygon(0,0,xSize-1, ySize-1)); + for(int i=0; i < gNPolygons; i++) { + int nX; + int nY; + do { // look for an empty square. + nX = NextRan(xSize); + nY = NextRan(ySize); + } while(tempMap[nX * ySize + nY] != 0); + int nR = (maxR * NextRan(1000)) / 999; + int nG = (maxG * NextRan(1000)) / 999; + int nB = (maxB * NextRan(1000)) / 999; + (*newMap)->push_back(RPolygon(nX,nY,nX,nY,nR,nG,nB)); + tempMap[nX * ySize + nY] = i+1; // index of this polygon + 1 + } + // now have to grow polygons to fill the space. + validPolys = (int *)malloc(4*gNPolygons * sizeof(int)); + validSide = (int *)malloc(4*gNPolygons * sizeof(int)); + for(int i=0;i 0) { + int indx = NextRan(maxSides); + int polyIndx = validPolys[indx]; + int checkSide = validSide[indx]; + int xlow, xhigh, ylow, yhigh; + int xlnew, xhnew, ylnew, yhnew; + (**newMap)[polyIndx].get(&xlow,&ylow,&xhigh,&yhigh); + xlnew = xlow; + xhnew = xhigh; + ylnew = ylow; + yhnew = yhigh; + // can this polygon be expanded along the chosen side? + switch(checkSide) { + case NORTH_SIDE: + // y-1 from xlow to xhigh + ylow = yhigh = (ylow - 1); + ylnew--; + break; + case EAST_SIDE: + // x+1 from ylow to yhigh + xlow = xhigh = (xhigh + 1); + xhnew++; + break; + case SOUTH_SIDE: + // y+1 from xlow to xhigh + ylow = yhigh = (yhigh+1); + yhnew++; + break; + case WEST_SIDE: + // x-1 from ylow to yhigh + xlow = xhigh = (xlow - 1); + xlnew--; + break; + } + bool okay_to_extend = !(((xlow < 0) || (xlow >= xSize)) || ((ylow < 0) || (ylow >= ySize))); + for(int ii = xlow; (ii <= xhigh) && okay_to_extend; ii++) { + for(int jj=ylow; (jj <= yhigh) && okay_to_extend; jj++) { + okay_to_extend = tempMap[ii*ySize + jj] == 0; + } + } + if(okay_to_extend) { + (**newMap)[polyIndx].set(xlnew,ylnew,xhnew,yhnew); + for(int ii = xlow; ii <= xhigh; ii++) { + for(int jj=ylow; jj <= yhigh && okay_to_extend; jj++) { + tempMap[ii*ySize + jj] = polyIndx; + } + } + } + else { + // once we cannot expand along a side, we will never be able to; remove from the list. + for(int i=indx + 1; i < maxSides; i++) { + validPolys[i-1] = validPolys[i]; + validSide[i-1] = validSide[i]; + } + maxSides--; + } + } + + // Once no polygons can be grown, look for unused squares, and fill them with polygons. + for(int j=0;jpush_back(RPolygon(i,j,ilen,jlen,nR,nG,nB)); + gNPolygons++; + for(int ii=i; ii<=ilen;ii++) { + for(int jj=j;jj<=jlen;jj++) { + tempMap[ii*ySize + jj] = gNPolygons; + } + } + } + } + } + +#if _DEBUG + if(!gIsGraphicalVersion) { + cout << std::endl << "Final Map:" << std::endl; + for(int j=0; j < ySize; j++ ) { + cout << "Row " << setw(2) << j << ":"; + for(int i=0;i=limit)) {cout << "checkMap error: " << str << " out of range (" << n << ")" << std::endl;anError=true;} +#define xRangeCheck(str,n) rangeCheck(str,n,gMapXSize) +#define yRangeCheck(str,n) rangeCheck(str,n,gMapYSize) + // The first polygon is the whole map. + bool anError = false; + int *cArray; + if(checkMap->size() <= 0) { + cout << "checkMap error: no polygons in map" << std::endl; + return; + } + // mapXhigh and mapYhigh are inclusive, that is, if the map is 5x5, those values would be 4. + int mapXhigh, mapYhigh, mapLowX, mapLowY; + int gMapXSize, gMapYSize; + (*checkMap)[0].get(&mapLowX, &mapLowY, &mapXhigh, &mapYhigh); + if((mapLowX !=0) || (mapLowY != 0)) { + cout << "checkMap error: map origin not (0,0) (X=" << mapLowX << ", Y=" << mapLowY << ")" << std::endl; + anError = true; + } + if((mapXhigh < 0) || (mapYhigh < 0)) { + cout << "checkMap error: no area in map (X=" << mapXhigh << ", Y=" << mapYhigh << ")" << std::endl; + anError = true; + } + if(anError) return; + // bounds for array. + gMapXSize = mapXhigh + 1; + gMapYSize = mapYhigh + 1; + cArray = (int *)malloc(sizeof(int)*(gMapXSize*gMapYSize)); + + for(int i=0; isize()) && !anError; p++) { + (*checkMap)[p].get(&xlow, &ylow, &xhigh, &yhigh); + xRangeCheck("xlow", xlow); + yRangeCheck("ylow", ylow); + xRangeCheck("xhigh", xhigh); + yRangeCheck("yhigh", yhigh); + if(xlow>xhigh) { + cout << "checkMap error: xlow > xhigh (" << xlow << "," << xhigh << ")" << std::endl; + anError = true; + } + if(ylow>yhigh) { + cout << "checkMap error: ylow > yhigh (" << ylow << "," << yhigh << ")" << std::endl; + anError = true; + } + for(int ii = xlow; ii <= xhigh; ii++) { + for(int jj = ylow; jj <= yhigh; jj++) { + if(cArray[indx(ii,jj)] != 0) { + cout << "checkMap error: polygons " << cArray[indx(ii,jj)] << " and " << p << " intersect" << std::endl; + anError = true; + } + cArray[indx(ii,jj)] = p; + } + } + } + for(int ii=0; ii < gMapXSize; ii++) { + for(int jj=0; jj < gMapYSize; jj++) { + if(cArray[indx(ii,jj)] == 0) { + cout << "checkMap error: block(" << ii << ", " << jj << ") not in any polygon" << std::endl; + anError = true; + } + } + } + free(cArray); +} + +bool CompOnePolygon(RPolygon &p1, RPolygon &p2) { + int xl1, xh1, yl1, yh1; + int xl2, xh2, yl2, yh2; + p1.get(&xl1, &yl1, &xh1, &yh1); + p2.get(&xl2, &yl2, &xh2, &yh2); + if(yl1>yl2) return true; + if(yl1 xl2); +} + +bool PolygonsEqual(RPolygon *p1, RPolygon *p2) { + int xl1, xh1, yl1, yh1; + int xl2, xh2, yl2, yh2; + p1->get(&xl1, &yl1, &xh1, &yh1); + p2->get(&xl2, &yl2, &xh2, &yh2); + return ((xl1 == xl2) && (yl1==yl2) && (xh1 == xh2) && (yh1 == yh2)); +} + +bool ComparePolygonMaps(Polygon_map_t *map1, Polygon_map_t *map2) { + // create two new polygon maps, copy the pointers from the original to these. + // we have to skip the first polygon, which is the size of the whole map + Polygon_map_t *t1, *t2; + bool is_ok = true; + t1 = new Polygon_map_t; + t1->reserve(map1->size()); + for(unsigned int i=1;isize(); i++) { + t1->push_back(map1->at(i)); + } + t2 = new Polygon_map_t; + t2->reserve(map2->size()); + for(unsigned int i=1;isize();i++) { + t2->push_back(map2->at(i)); + } + // sort the two created maps by (xlow, ylow) + sort(t1->begin(), t1->end()); + sort(t2->begin(), t2->end()); + // compare each element of both maps. + if(t1->size() != t2->size()) { + cout << "Error: maps not the same size ( " << int(t1->size()) << " vs " << int(t2->size()) << ")." << std::endl; + } + int maxSize = (int)((t1->size() < t2->size()) ? t1->size() : t2->size()); + for(int i=0; i < maxSize; i++) { + if(!PolygonsEqual(&((*t1)[i]), &((*t2)[i]))) { + cout << "Error: polygons unequal (" << (*t1)[i] << " vs " << (*t2)[i] << std::endl; + is_ok = false; + } + } + delete t1; + delete t2; + return is_ok; +} + +void SetRandomSeed(int newSeed) { + srand((unsigned)newSeed); +} + +int NextRan(int n) { + // assert(n > 1); + // if we are given 1, we will just return 0 + //assert(n < RAND_MAX); + int rrand = rand() << 15 | rand(); + if(rrand < 0) rrand = -rrand; + return rrand % n; +} + +std::ostream& operator<<(std::ostream& s, const RPolygon &p) { + int xl, yl, xh, yh; + p.get(&xl, &yl, &xh, &yh); + return s << "[(" << xl << "," << yl << ")-(" << xh << "," << yh << ")] "; +} diff --git a/src/tbb/examples/parallel_for/polygon_overlay/polymain.h b/src/tbb/examples/parallel_for/polygon_overlay/polymain.h new file mode 100644 index 0000000..97f0545 --- /dev/null +++ b/src/tbb/examples/parallel_for/polygon_overlay/polymain.h @@ -0,0 +1,53 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "pover_global.h" // for declaration of DEFINE and INIT + +DEFINE Polygon_map_t *gPolymap1 INIT(0); +DEFINE Polygon_map_t *gPolymap2 INIT(0); +DEFINE Polygon_map_t *gResultMap INIT(0); + +extern void Usage(int argc, char **argv); + +extern bool ParseCmdLine(int argc, char **argv ); + +extern bool GenerateMap(Polygon_map_t **newMap, int xSize, int ySize, int gNPolygons, colorcomp_t maxR, colorcomp_t maxG, colorcomp_t maxB); + +extern bool PolygonsOverlap(RPolygon *p1, RPolygon *p2, int &xl, int &yl, int &xh, int &yh); + +extern void CheckPolygonMap(Polygon_map_t *checkMap); + +extern bool CompOnePolygon(RPolygon *p1, RPolygon *p2); + +extern bool PolygonsEqual(RPolygon *p1, RPolygon *p2); + +extern bool ComparePolygonMaps(Polygon_map_t *map1, Polygon_map_t *map2); + +extern void SetRandomSeed(int newSeed); + +extern int NextRan(int n); diff --git a/src/tbb/examples/parallel_for/polygon_overlay/polyover.cpp b/src/tbb/examples/parallel_for/polygon_overlay/polyover.cpp new file mode 100644 index 0000000..d249446 --- /dev/null +++ b/src/tbb/examples/parallel_for/polygon_overlay/polyover.cpp @@ -0,0 +1,676 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Polygon overlay +// +#include +#include +#include +#include +#include +#include "tbb/tick_count.h" +#include "tbb/blocked_range.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/parallel_for.h" +#include "tbb/mutex.h" +#include "tbb/spin_mutex.h" +#include "polyover.h" +#include "polymain.h" +#include "pover_video.h" + +using namespace std; + +/*! +* @brief intersects a polygon with a map, adding any results to output map +* +* @param[out] resultMap output map (must be allocated) +* @param[in] polygon to be intersected +* @param[in] map intersected against +* @param[in] lock to use when adding output polygons to result map +* +*/ +void OverlayOnePolygonWithMap(Polygon_map_t *resultMap, RPolygon *myPoly, Polygon_map_t *map2, tbb::spin_mutex *rMutex) { + int r1, g1, b1, r2, g2, b2; + int myr=0; + int myg=0; + int myb=0; + int p1Area = myPoly->area(); + for(unsigned int j=1; (j < map2->size()) && (p1Area > 0); j++) { + RPolygon *p2 = &((*map2)[j]); + RPolygon *pnew; + int newxMin, newxMax, newyMin, newyMax; + myPoly->getColor(&r1, &g1, &b1); + if(PolygonsOverlap(myPoly, p2, newxMin, newyMin, newxMax, newyMax)) { + p2->getColor(&r2, &g2, &b2); + myr = r1 + r2; + myg = g1 + g2; + myb = b1 + b2; + p1Area -= (newxMax-newxMin+1)*(newyMax - newyMin + 1); + if(rMutex) { + tbb::spin_mutex::scoped_lock lock(*rMutex); + resultMap->push_back(RPolygon(newxMin, newyMin, newxMax, newyMax, myr, myg, myb)); + } + else { + resultMap->push_back(RPolygon(newxMin, newyMin, newxMax, newyMax, myr, myg, myb)); + } + } + } +} + +/*! +* @brief Serial version of polygon overlay +* @param[out] output map +* @param[in] first map (map that individual polygons are taken from) +* @param[in] second map (map passed to OverlayOnePolygonWithMap) +*/ +void SerialOverlayMaps(Polygon_map_t **resultMap, Polygon_map_t *map1, Polygon_map_t *map2) { + cout << "SerialOverlayMaps called" << std::endl; + *resultMap = new Polygon_map_t; + + RPolygon *p0 = &((*map1)[0]); + int mapxSize, mapySize, ignore1, ignore2; + p0->get(&ignore1, &ignore2, &mapxSize, &mapySize); + (*resultMap)->reserve(mapxSize*mapySize); // can't be any bigger than this + // push the map size as the first polygon, + (*resultMap)->push_back(RPolygon(0,0,mapxSize, mapySize)); + for(unsigned int i=1; i < map1->size(); i++) { + RPolygon *p1 = &((*map1)[i]); + OverlayOnePolygonWithMap(*resultMap, p1, map2, NULL); + } +} + +/*! +* @class ApplyOverlay +* @brief Simple version of parallel overlay (make parallel on polygons in map1) +*/ +class ApplyOverlay { + Polygon_map_t *m_map1, *m_map2, *m_resultMap; + tbb::spin_mutex *m_rMutex; +public: + /*! + * @brief functor to apply + * @param[in] r range of polygons to intersect from map1 + */ + void operator()( const tbb::blocked_range & r) const { + PRINT_DEBUG("From " << r.begin() << " to " << r.end()); + for(int i=r.begin(); i != r.end(); i++) { + RPolygon *myPoly = &((*m_map1)[i]); + OverlayOnePolygonWithMap(m_resultMap, myPoly, m_map2, m_rMutex); + } + } + ApplyOverlay(Polygon_map_t *resultMap, Polygon_map_t *map1, Polygon_map_t *map2, tbb::spin_mutex *rmutex) : + m_resultMap(resultMap), m_map1(map1), m_map2(map2), m_rMutex(rmutex) {} +}; + +/*! +* @brief apply the parallel algorithm +* @param[out] result_map generated map +* @param[in] polymap1 first map to be applied (algorithm is parallel on this map) +* @param[in] polymap2 second map. +*/ +void NaiveParallelOverlay(Polygon_map_t *&result_map, Polygon_map_t &polymap1, Polygon_map_t &polymap2) { +// ----------------------------------- + bool automatic_threadcount = false; + + if(gThreadsLow == THREADS_UNSET || gThreadsLow == tbb::task_scheduler_init::automatic) { + gThreadsLow = gThreadsHigh = tbb::task_scheduler_init::automatic; + automatic_threadcount = true; + } + result_map = new Polygon_map_t; + + RPolygon *p0 = &(polymap1[0]); + int mapxSize, mapySize, ignore1, ignore2; + p0->get(&ignore1, &ignore2, &mapxSize, &mapySize); + result_map->reserve(mapxSize*mapySize); // can't be any bigger than this + // push the map size as the first polygon, + tbb::spin_mutex *resultMutex = new tbb::spin_mutex(); + int grain_size = gGrainSize; + + for(int nthreads = gThreadsLow; nthreads <= gThreadsHigh; nthreads++) { + tbb::task_scheduler_init init(nthreads); + if(gIsGraphicalVersion) { + RPolygon *xp = new RPolygon(0, 0, gMapXSize-1, gMapYSize-1, 0, 0, 0); // Clear the output space + delete xp; + } + // put size polygon in result map + result_map->push_back(RPolygon(0,0,mapxSize, mapySize)); + + tbb::tick_count t0 = tbb::tick_count::now(); + tbb::parallel_for (tbb::blocked_range(1,(int)(polymap1.size()),grain_size), ApplyOverlay(result_map, &polymap1, &polymap2, resultMutex)); + tbb::tick_count t1 = tbb::tick_count::now(); + + double naiveParallelTime = (t1-t0).seconds() * 1000; + cout << "Naive parallel with spin lock and "; + if(automatic_threadcount) cout << "automatic"; + else cout << nthreads; + cout << ((nthreads == 1) ? " thread" : " threads"); + cout << " took " << naiveParallelTime << " msec : speedup over serial " << (gSerialTime / naiveParallelTime) << std::endl; + if(gCsvFile.is_open()) { + gCsvFile << "," << naiveParallelTime; + } +#if _DEBUG + CheckPolygonMap(result_map); + ComparePolygonMaps(result_map, gResultMap); +#endif + result_map->clear(); + } + delete resultMutex; + if(gCsvFile.is_open()) { + gCsvFile << std::endl; + } +// ----------------------------------- +} + +template +void split_at( Flagged_map_t& in_map, Flagged_map_t &left_out, Flagged_map_t &right_out, const T median) { + left_out.reserve(in_map.size()); + right_out.reserve(in_map.size()); + for(Flagged_map_t::iterator i = in_map.begin(); i != in_map.end(); ++i ) { + RPolygon *p = i->p(); + if(p->xmax() < median) { + // in left map + left_out.push_back(*i); + } + else if(p->xmin() >= median) { + right_out.push_back(*i); + // in right map + } + else { + // in both maps. + left_out.push_back(*i); + right_out.push_back(RPolygon_flagged(p, true)); + } + } +} + +// range that splits the maps as well as the range. the flagged_map_t are +// vectors of pointers, and each range owns its maps (has to free them on destruction.) +template +class blocked_range_with_maps { + + typedef blocked_range my_range_type; + +private: + + my_range_type my_range; + Flagged_map_t my_map1; + Flagged_map_t my_map2; + +public: + + blocked_range_with_maps( + T begin, T end, typename my_range_type::size_type my_grainsize, + Polygon_map_t *p1, Polygon_map_t *p2 + ) + : my_range(begin, end, my_grainsize) + { + my_map1.reserve(p1->size()); + my_map2.reserve(p2->size()); + for(int i=1; i < p1->size(); ++i) { + my_map1.push_back(RPolygon_flagged(&((*p1)[i]), false)); + } + for(int i=1; i < p2->size(); ++i) { + my_map2.push_back(RPolygon_flagged(&(p2->at(i)), false)); + } + } + + // copy-constructor required for deep copy of flagged maps. One copy is done at the start of the + // parallel for. + blocked_range_with_maps(const blocked_range_with_maps& other): my_range(other.my_range), my_map1(other.my_map1), my_map2(other.my_map2) { } + bool empty() const { return my_range.empty(); } + bool is_divisible() const { return my_range.is_divisible(); } + +#if _DEBUG + void check_my_map() { + assert(my_range.begin() <= my_range.end()); + for(Flagged_map_t::iterator ci = my_map1.begin(); ci != my_map1.end(); ++ci) { + RPolygon *rp = ci->p(); + assert(rp->xmax() >= my_range.begin()); + assert(rp->xmin() < my_range.end()); + } + for(Flagged_map_t::iterator ci = my_map2.begin(); ci != my_map2.end(); ++ci) { + RPolygon *rp = ci->p(); + assert(rp->xmax() >= my_range.begin()); + assert(rp->xmin() < my_range.end()); + } + } + + void dump_map( Flagged_map_t& mapx) { + cout << " ** MAP **\n"; + for( Flagged_map_t::iterator ci = mapx.begin(); ci != mapx.end(); ++ci) { + cout << *(ci->p()); + if(ci->isDuplicate()) { + cout << " -- is_duplicate"; + } + cout << "\n"; + } + cout << "\n"; + } +#endif + + blocked_range_with_maps(blocked_range_with_maps& lhs_r, split ) : my_range(my_range_type(lhs_r.my_range, split())) { + // lhs_r.my_range makes my_range from [median, high) and rhs_r.my_range from [low, median) + Flagged_map_t original_map1 = lhs_r.my_map1; + Flagged_map_t original_map2 = lhs_r.my_map2; + lhs_r.my_map1.clear(); + lhs_r.my_map2.clear(); + split_at(original_map1, lhs_r.my_map1, my_map1, my_range.begin()); + split_at(original_map2, lhs_r.my_map2, my_map2, my_range.begin()); +#if _DEBUG + this->check_my_map(); + lhs_r.check_my_map(); +#endif + } + + const my_range_type& range() const { return my_range; } + Flagged_map_t& map1() { return my_map1; } + Flagged_map_t& map2() { return my_map2; } +}; + +/*! +* @class ApplySplitOverlay +* @brief parallel by columnar strip +*/ +class ApplySplitOverlay { + Polygon_map_t *m_map1, *m_map2, *m_resultMap; + tbb::spin_mutex *m_rMutex; +public: + /*! + * @brief functor for columnar parallel version + * @param[in] r range of map to be operated on + */ + void operator()(/*const*/ blocked_range_with_maps & r) const { +#ifdef _DEBUG + // if we are debugging, serialize the method. That way we can + // see what is happening in each strip without the interleaving + // confusing things. + tbb::spin_mutex::scoped_lock lock(*m_rMutex); + cout << unitbuf << "From " << r.range().begin() << " to " << r.range().end()-1 << std::endl; +#endif + // get yMapSize + int r1, g1, b1, r2, g2, b2; + int myr=-1; + int myg=-1; + int myb=-1; + int i1, i2, i3, yMapSize; + (*m_map1)[0].get(&i1, &i2, &i3, &yMapSize); + + Flagged_map_t &fmap1 = r.map1(); + Flagged_map_t &fmap2 = r.map2(); + + // When intersecting polygons from fmap1 and fmap2, if BOTH are flagged + // as duplicate, don't add the result to the output map. We can still + // intersect them, because we are keeping track of how much of the polygon + // is left over from intersecting, and quitting when the polygon is + // used up. + + for(unsigned int ii=0; ii < fmap1.size(); ii++) { + RPolygon *p1 = fmap1[ii].p(); + bool is_dup = fmap1[ii].isDuplicate(); + int parea = p1->area(); + p1->getColor(&r1, &g1, &b1); + for(unsigned int jj=0;(jj < fmap2.size()) && (parea > 0); jj++) { + int xl, yl, xh, yh; + RPolygon *p2 = fmap2[jj].p(); + if(PolygonsOverlap(p1, p2, xl, yl, xh, yh)) { + if(!(is_dup && fmap2[jj].isDuplicate())) { + p2->getColor(&r2, &g2, &b2); + myr = r1 + r2; + myg = g1 + g2; + myb = b1 + b2; +#ifdef _DEBUG +#else + tbb::spin_mutex::scoped_lock lock(*m_rMutex); +#endif + (*m_resultMap).push_back(RPolygon(xl, yl, xh, yh, myr, myg, myb)); + } + parea -= (xh-xl+1)*(yh-yl+1); + } + } + } + } + + ApplySplitOverlay(Polygon_map_t *resultMap, Polygon_map_t *map1, Polygon_map_t *map2, tbb::spin_mutex *rmutex) : + m_resultMap(resultMap), m_map1(map1), m_map2(map2), m_rMutex(rmutex) {} +}; + + +/*! +* @brief intersects two maps strip-wise +* +* @param[out] resultMap output map (must be allocated) +* @param[in] polymap1 map to be intersected +* @param[in] polymap2 map to be intersected +*/ +void SplitParallelOverlay(Polygon_map_t **result_map, Polygon_map_t *polymap1, Polygon_map_t *polymap2) { + int nthreads; + bool automatic_threadcount = false; + double domainSplitParallelTime; + tbb::tick_count t0, t1; + tbb::spin_mutex *resultMutex; + if(gThreadsLow == THREADS_UNSET || gThreadsLow == tbb::task_scheduler_init::automatic ) { + gThreadsLow = gThreadsHigh = tbb::task_scheduler_init::automatic; + automatic_threadcount = true; + } + *result_map = new Polygon_map_t; + + RPolygon *p0 = &((*polymap1)[0]); + int mapxSize, mapySize, ignore1, ignore2; + p0->get(&ignore1, &ignore2, &mapxSize, &mapySize); + (*result_map)->reserve(mapxSize*mapySize); // can't be any bigger than this + resultMutex = new tbb::spin_mutex(); + + int grain_size; +#ifdef _DEBUG + grain_size = gMapXSize / 4; +#else + grain_size = gGrainSize; +#endif + for(nthreads = gThreadsLow; nthreads <= gThreadsHigh; nthreads++) { + tbb::task_scheduler_init init(nthreads); + if(gIsGraphicalVersion) { + RPolygon *xp = new RPolygon(0, 0, gMapXSize-1, gMapYSize-1, 0, 0, 0); // Clear the output space + delete xp; + } + // push the map size as the first polygon, + (*result_map)->push_back(RPolygon(0,0,mapxSize, mapySize)); + t0 = tbb::tick_count::now(); + tbb::parallel_for (blocked_range_with_maps(0,(int)(mapxSize+1),grain_size, polymap1, polymap2), ApplySplitOverlay((*result_map), polymap1, polymap2, resultMutex)); + t1 = tbb::tick_count::now(); + domainSplitParallelTime = (t1-t0).seconds()*1000; + cout << "Splitting parallel with spin lock and "; + if(automatic_threadcount) cout << "automatic"; + else cout << nthreads; + cout << ((nthreads == 1) ? " thread" : " threads"); + cout << " took " << domainSplitParallelTime << " msec : speedup over serial " << (gSerialTime / domainSplitParallelTime) << std::endl; + if(gCsvFile.is_open()) { + gCsvFile << "," << domainSplitParallelTime; + } +#if _DEBUG + CheckPolygonMap(*result_map); + ComparePolygonMaps(*result_map, gResultMap); +#endif + (*result_map)->clear(); + + } + delete resultMutex; + if(gCsvFile.is_open()) { + gCsvFile << std::endl; + } +} + +class ApplySplitOverlayCV { + Polygon_map_t *m_map1, *m_map2; + concurrent_Polygon_map_t *m_resultMap; +public: + /*! + * @brief functor for columnar parallel version + * @param[in] r range of map to be operated on + */ + void operator()(blocked_range_with_maps & r) const { + // get yMapSize + int r1, g1, b1, r2, g2, b2; + int myr=-1; + int myg=-1; + int myb=-1; + int i1, i2, i3, yMapSize; + (*m_map1)[0].get(&i1, &i2, &i3, &yMapSize); + + Flagged_map_t &fmap1 = r.map1(); + Flagged_map_t &fmap2 = r.map2(); + + // When intersecting polygons from fmap1 and fmap2, if BOTH are flagged + // as duplicate, don't add the result to the output map. We can still + // intersect them, because we are keeping track of how much of the polygon + // is left over from intersecting, and quitting when the polygon is + // used up. + + for(unsigned int ii=0; ii < fmap1.size(); ii++) { + RPolygon *p1 = fmap1[ii].p(); + bool is_dup = fmap1[ii].isDuplicate(); + int parea = p1->area(); + p1->getColor(&r1, &g1, &b1); + for(unsigned int jj=0;(jj < fmap2.size()) && (parea > 0); jj++) { + int xl, yl, xh, yh; + RPolygon *p2 = fmap2[jj].p(); + if(PolygonsOverlap(p1, p2, xl, yl, xh, yh)) { + if(!(is_dup && fmap2[jj].isDuplicate())) { + p2->getColor(&r2, &g2, &b2); + myr = r1 + r2; + myg = g1 + g2; + myb = b1 + b2; + (*m_resultMap).push_back(RPolygon(xl, yl, xh, yh, myr, myg, myb)); + } + parea -= (xh-xl+1)*(yh-yl+1); + } + } + } + } + + ApplySplitOverlayCV(concurrent_Polygon_map_t *resultMap, Polygon_map_t *map1, Polygon_map_t *map2 ) : + m_resultMap(resultMap), m_map1(map1), m_map2(map2) {} +}; + + +/*! +* @brief intersects two maps strip-wise, accumulating into a concurrent_vector +* +* @param[out] resultMap output map (must be allocated) +* @param[in] polymap1 map to be intersected +* @param[in] polymap2 map to be intersected +*/ +void SplitParallelOverlayCV(concurrent_Polygon_map_t **result_map, Polygon_map_t *polymap1, Polygon_map_t *polymap2) { + int nthreads; + bool automatic_threadcount = false; + double domainSplitParallelTime; + tbb::tick_count t0, t1; + if(gThreadsLow == THREADS_UNSET || gThreadsLow == tbb::task_scheduler_init::automatic ) { + gThreadsLow = gThreadsHigh = tbb::task_scheduler_init::automatic; + automatic_threadcount = true; + } + *result_map = new concurrent_Polygon_map_t; + + RPolygon *p0 = &((*polymap1)[0]); + int mapxSize, mapySize, ignore1, ignore2; + p0->get(&ignore1, &ignore2, &mapxSize, &mapySize); + // (*result_map)->reserve(mapxSize*mapySize); // can't be any bigger than this + + int grain_size; +#ifdef _DEBUG + grain_size = gMapXSize / 4; +#else + grain_size = gGrainSize; +#endif + for(nthreads = gThreadsLow; nthreads <= gThreadsHigh; nthreads++) { + tbb::task_scheduler_init init(nthreads); + if(gIsGraphicalVersion) { + RPolygon *xp = new RPolygon(0, 0, gMapXSize-1, gMapYSize-1, 0, 0, 0); // Clear the output space + delete xp; + } + // push the map size as the first polygon, + (*result_map)->push_back(RPolygon(0,0,mapxSize, mapySize)); + t0 = tbb::tick_count::now(); + tbb::parallel_for (blocked_range_with_maps(0,(int)(mapxSize+1),grain_size, polymap1, polymap2), ApplySplitOverlayCV((*result_map), polymap1, polymap2)); + t1 = tbb::tick_count::now(); + domainSplitParallelTime = (t1-t0).seconds()*1000; + cout << "Splitting parallel with concurrent_vector and "; + if(automatic_threadcount) cout << "automatic"; + else cout << nthreads; + cout << ((nthreads == 1) ? " thread" : " threads"); + cout << " took " << domainSplitParallelTime << " msec : speedup over serial " << (gSerialTime / domainSplitParallelTime) << std::endl; + if(gCsvFile.is_open()) { + gCsvFile << "," << domainSplitParallelTime; + } +#if _DEBUG + { + + Polygon_map_t s_result_map; + for(concurrent_Polygon_map_t::const_iterator ci = (*result_map)->begin(); ci != (*result_map)->end(); ++ci) { + s_result_map.push_back(*ci); + } + CheckPolygonMap(&s_result_map); + ComparePolygonMaps(&s_result_map, gResultMap); + } +#endif + (*result_map)->clear(); + + } + + if(gCsvFile.is_open()) { + gCsvFile << std::endl; + } + +} + +// ------------------------------------------------------ + +class ApplySplitOverlayETS { + Polygon_map_t *m_map1, *m_map2; + ETS_Polygon_map_t *m_resultMap; +public: + /*! + * @brief functor for columnar parallel version + * @param[in] r range of map to be operated on + */ + void operator()(blocked_range_with_maps & r) const { + // get yMapSize + int r1, g1, b1, r2, g2, b2; + int myr=-1; + int myg=-1; + int myb=-1; + int i1, i2, i3, yMapSize; + (*m_map1)[0].get(&i1, &i2, &i3, &yMapSize); + + Flagged_map_t &fmap1 = r.map1(); + Flagged_map_t &fmap2 = r.map2(); + + // When intersecting polygons from fmap1 and fmap2, if BOTH are flagged + // as duplicate, don't add the result to the output map. We can still + // intersect them, because we are keeping track of how much of the polygon + // is left over from intersecting, and quitting when the polygon is + // used up. + + for(unsigned int ii=0; ii < fmap1.size(); ii++) { + RPolygon *p1 = fmap1[ii].p(); + bool is_dup = fmap1[ii].isDuplicate(); + int parea = p1->area(); + p1->getColor(&r1, &g1, &b1); + for(unsigned int jj=0;(jj < fmap2.size()) && (parea > 0); jj++) { + int xl, yl, xh, yh; + RPolygon *p2 = fmap2[jj].p(); + if(PolygonsOverlap(p1, p2, xl, yl, xh, yh)) { + if(!(is_dup && fmap2[jj].isDuplicate())) { + p2->getColor(&r2, &g2, &b2); + myr = r1 + r2; + myg = g1 + g2; + myb = b1 + b2; + (*m_resultMap).local().push_back(RPolygon(xl, yl, xh, yh, myr, myg, myb)); + } + parea -= (xh-xl+1)*(yh-yl+1); + } + } + } + } + + ApplySplitOverlayETS(ETS_Polygon_map_t *resultMap, Polygon_map_t *map1, Polygon_map_t *map2 ) : + m_resultMap(resultMap), m_map1(map1), m_map2(map2) {} +}; + + +/*! +* @brief intersects two maps strip-wise, accumulating into an ets variable +* +* @param[out] resultMap output map (must be allocated) +* @param[in] polymap1 map to be intersected +* @param[in] polymap2 map to be intersected +*/ +void SplitParallelOverlayETS(ETS_Polygon_map_t **result_map, Polygon_map_t *polymap1, Polygon_map_t *polymap2) { + int nthreads; + bool automatic_threadcount = false; + double domainSplitParallelTime; + tbb::tick_count t0, t1; + if(gThreadsLow == THREADS_UNSET || gThreadsLow == tbb::task_scheduler_init::automatic ) { + gThreadsLow = gThreadsHigh = tbb::task_scheduler_init::automatic; + automatic_threadcount = true; + } + *result_map = new ETS_Polygon_map_t; + + RPolygon *p0 = &((*polymap1)[0]); + int mapxSize, mapySize, ignore1, ignore2; + p0->get(&ignore1, &ignore2, &mapxSize, &mapySize); + // (*result_map)->reserve(mapxSize*mapySize); // can't be any bigger than this + + int grain_size; +#ifdef _DEBUG + grain_size = gMapXSize / 4; +#else + grain_size = gGrainSize; +#endif + for(nthreads = gThreadsLow; nthreads <= gThreadsHigh; nthreads++) { + tbb::task_scheduler_init init(nthreads); + if(gIsGraphicalVersion) { + RPolygon *xp = new RPolygon(0, 0, gMapXSize-1, gMapYSize-1, 0, 0, 0); // Clear the output space + delete xp; + } + // push the map size as the first polygon, + // This polygon needs to be first, so we can push it at the start of a combine. + // (*result_map)->local.push_back(RPolygon(0,0,mapxSize, mapySize)); + t0 = tbb::tick_count::now(); + tbb::parallel_for (blocked_range_with_maps(0,(int)(mapxSize+1),grain_size, polymap1, polymap2), ApplySplitOverlayETS((*result_map), polymap1, polymap2)); + t1 = tbb::tick_count::now(); + domainSplitParallelTime = (t1-t0).seconds()*1000; + cout << "Splitting parallel with ETS and "; + if(automatic_threadcount) cout << "automatic"; + else cout << nthreads; + cout << ((nthreads == 1) ? " thread" : " threads"); + cout << " took " << domainSplitParallelTime << " msec : speedup over serial " << (gSerialTime / domainSplitParallelTime) << std::endl; + if(gCsvFile.is_open()) { + gCsvFile << "," << domainSplitParallelTime; + } +#if _DEBUG + { + + Polygon_map_t s_result_map; + flattened2d psv = flatten2d(**result_map); + s_result_map.push_back(RPolygon(0,0,mapxSize, mapySize)); + for(flattened2d::const_iterator ci = psv.begin(); ci != psv.end(); ++ci) { + s_result_map.push_back(*ci); + } + CheckPolygonMap(&s_result_map); + ComparePolygonMaps(&s_result_map, gResultMap); + } +#endif + (*result_map)->clear(); + + } + + if(gCsvFile.is_open()) { + gCsvFile << std::endl; + } + +} diff --git a/src/tbb/examples/parallel_for/polygon_overlay/polyover.h b/src/tbb/examples/parallel_for/polygon_overlay/polyover.h new file mode 100644 index 0000000..a7a0c3d --- /dev/null +++ b/src/tbb/examples/parallel_for/polygon_overlay/polyover.h @@ -0,0 +1,49 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/*! + * polyover.h : extern declarations for polyover.cpp +*/ +#include "rpolygon.h" +#include "tbb/mutex.h" +#include "tbb/spin_mutex.h" + +extern void OverlayOnePolygonWithMap(Polygon_map_t *resultMap, RPolygon *myPoly, Polygon_map_t *map2, tbb::spin_mutex *rMutex); + +extern void SerialOverlayMaps(Polygon_map_t **resultMap, Polygon_map_t *map1, Polygon_map_t *map2); + +// extern void NaiveParallelOverlay(Polygon_map_t **result_map, Polygon_map_t *polymap1, Polygon_map_t *polymap2); +extern void NaiveParallelOverlay(Polygon_map_t *&result_map, Polygon_map_t &polymap1, Polygon_map_t &polymap2); + +extern void SplitParallelOverlay(Polygon_map_t **result_map, Polygon_map_t *polymap1, Polygon_map_t *polymap2); +extern void SplitParallelOverlayCV(concurrent_Polygon_map_t **result_map, Polygon_map_t *polymap1, Polygon_map_t *polymap2); +extern void SplitParallelOverlayETS(ETS_Polygon_map_t **result_map, Polygon_map_t *polymap1, Polygon_map_t *polymap2); + +extern void CheckPolygonMap(Polygon_map_t *checkMap); +extern bool ComparePolygonMaps(Polygon_map_t *map1, Polygon_map_t *map2); + diff --git a/src/tbb/examples/parallel_for/polygon_overlay/pover_global.h b/src/tbb/examples/parallel_for/polygon_overlay/pover_global.h new file mode 100644 index 0000000..8024d30 --- /dev/null +++ b/src/tbb/examples/parallel_for/polygon_overlay/pover_global.h @@ -0,0 +1,101 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// +// pover_global.h +// +#ifndef _POVER_GLOBAL_H_ +#define _POVER_GLOBAL_H_ + +#ifdef _MAIN_C_ +#define DEFINE // nothing +#define STATIC static +#define INIT(n) = n +#else // not in main file +#define DEFINE extern +#define STATIC // nothing +#define INIT(n) // nothing +#endif // _MAIN_C_ + +#include +#include + +#ifdef _WINDOWS +#include +#endif + +// this Polygon class only supports rectangles +DEFINE int gDrawXOffset INIT(0); // used for drawing polygons +DEFINE int gDrawYOffset INIT(0); +DEFINE int gPolyXBoxSize INIT(0); // number of pixels orresponding to one "square" (x) +DEFINE int gPolyYBoxSize INIT(0); // number of pixels orresponding to one "square" (y) +DEFINE bool gDoDraw INIT(false); // render the boxes + +#define THREADS_UNSET 0 +DEFINE int gThreadsLow INIT(THREADS_UNSET); +DEFINE int gThreadsHigh INIT(THREADS_UNSET); + +DEFINE std::ofstream gCsvFile; +DEFINE double gSerialTime; +DEFINE char *gCsvFilename INIT(NULL); + +#define BORDER_SIZE 10 // number of pixels between maps + +// The map size and the number of polygons depends on the version we are compiling. +// If DEBUG then it is small; else it is large. + +#ifdef _DEBUG +DEFINE int gNPolygons INIT(30); // default number of polygons in map +DEFINE int gMapXSize INIT(30); +DEFINE int gMapYSize INIT(30); +DEFINE int gGrainSize INIT(5); +#else +DEFINE int gNPolygons INIT(50000); // default number of polygons in map +DEFINE int gMapXSize INIT(1000); +DEFINE int gMapYSize INIT(1000); +DEFINE int gGrainSize INIT(20); +#endif +DEFINE int gMyRandomSeed INIT(2453185); + +DEFINE bool gIsGraphicalVersion INIT(false); + +typedef enum { + NORTH_SIDE, + EAST_SIDE, + SOUTH_SIDE, + WEST_SIDE +} allSides; + +#if _DEBUG +#define PRINT_DEBUG(x) (cout << x << std::endl) +#else +#define PRINT_DEBUG(x) +#endif + + +#endif // _POVER_GLOBAL_H_ diff --git a/src/tbb/examples/parallel_for/polygon_overlay/pover_video.cpp b/src/tbb/examples/parallel_for/polygon_overlay/pover_video.cpp new file mode 100644 index 0000000..b75aa03 --- /dev/null +++ b/src/tbb/examples/parallel_for/polygon_overlay/pover_video.cpp @@ -0,0 +1,178 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Support for GUI display for Polygon overlay demo + +#define VIDEO_WINMAIN_ARGS +#include +#include "polyover.h" +#include "polymain.h" +#include "pover_video.h" +#include "tbb/tick_count.h" +#include "tbb/task_scheduler_init.h" +#ifndef _WIN32 +#include +#include + +void rt_sleep(int msec) { + usleep(msec*1000); +} + +#else //_WIN32 + +#undef OLDUNIXTIME +#undef STDTIME + +#include + +void rt_sleep(int msec) { + Sleep(msec); +} + +#endif /* _WIN32 */ + +using namespace std; + +bool g_next_frame() { + if(++n_next_frame_calls >= frame_skips) { // the data race here is benign + n_next_frame_calls = 0; + return gVideo->next_frame(); + } + return gVideo->running; +} + +bool g_last_frame() { + if(n_next_frame_calls) return gVideo->next_frame(); + return gVideo->running; +} + +bool initializeVideo(int argc, char **argv) { + //pover_video *l_video = new pover_video(); + //gVideo = l_video; + gVideo->init_console(); // don't check return code. + gVideo->title = g_windowTitle; + g_useGraphics = gVideo->init_window(g_xwinsize, g_ywinsize); + return true; +} + +void pover_video::on_process() { + tbb::tick_count t0, t1; + double naiveParallelTime, domainSplitParallelTime; + // create map1 These could be done in parallel, if the pseudorandom number generator were re-seeded. + GenerateMap(&gPolymap1, gMapXSize, gMapYSize, gNPolygons, /*red*/255, /*green*/0, /*blue*/127); + // create map2 + GenerateMap(&gPolymap2, gMapXSize, gMapYSize, gNPolygons, /*red*/0, /*green*/255, /*blue*/127); + // + // Draw source maps + gDrawXOffset = map1XLoc; + gDrawYOffset = map1YLoc; + for(int i=0; i < int(gPolymap1->size()); i++) { + (*gPolymap1)[i].drawPoly(); + } + gDrawXOffset = map2XLoc; + gDrawYOffset = map2YLoc; + for(int i=0; i < int(gPolymap2->size()) ;i++) { + (*gPolymap2)[i].drawPoly(); + } + gDoDraw = true; + + // run serial map generation + gDrawXOffset = maprXLoc; + gDrawYOffset = maprYLoc; + { + RPolygon *xp = new RPolygon(0, 0, gMapXSize-1, gMapYSize-1, 0, 0, 0); // Clear the output space + delete xp; + t0 = tbb::tick_count::now(); + SerialOverlayMaps(&gResultMap, gPolymap1, gPolymap2); + t1 = tbb::tick_count::now(); + cout << "Serial overlay took " << (t1-t0).seconds()*1000 << " msec" << std::endl; + gSerialTime = (t1-t0).seconds()*1000; +#if _DEBUG + CheckPolygonMap(gResultMap); + // keep the map for comparison purposes. +#else + delete gResultMap; +#endif + if(gCsvFile.is_open()) { + gCsvFile << "Serial Time," << gSerialTime << std::endl; + gCsvFile << "Threads,"; + if(gThreadsLow == THREADS_UNSET || gThreadsLow == tbb::task_scheduler_init::automatic) { + gCsvFile << "Threads,Automatic"; + } + else { + for(int i=gThreadsLow; i <= gThreadsHigh; i++) { + gCsvFile << i; + if(i < gThreadsHigh) gCsvFile << ","; + } + } + gCsvFile << std::endl; + } + if(gIsGraphicalVersion) rt_sleep(2000); + } + // run naive parallel map generation + { + Polygon_map_t *resultMap; + if(gCsvFile.is_open()) { + gCsvFile << "Naive Time"; + } + NaiveParallelOverlay(resultMap, *gPolymap1, *gPolymap2); + delete resultMap; + if(gIsGraphicalVersion) rt_sleep(2000); + } + // run split map generation + { + Polygon_map_t *resultMap; + if(gCsvFile.is_open()) { + gCsvFile << "Split Time"; + } + SplitParallelOverlay(&resultMap, gPolymap1, gPolymap2); + delete resultMap; + if(gIsGraphicalVersion) rt_sleep(2000); + } + // split, accumulating into concurrent vector + { + concurrent_Polygon_map_t *cresultMap; + if(gCsvFile.is_open()) { + gCsvFile << "Split CV time"; + } + SplitParallelOverlayCV(&cresultMap, gPolymap1, gPolymap2); + delete cresultMap; + if(gIsGraphicalVersion) rt_sleep(2000); + } + // split, accumulating into ETS + { + ETS_Polygon_map_t *cresultMap; + if(gCsvFile.is_open()) { + gCsvFile << "Split ETS time"; + } + SplitParallelOverlayETS(&cresultMap, gPolymap1, gPolymap2); + delete cresultMap; + if(gIsGraphicalVersion) rt_sleep(2000); + } + if(gIsGraphicalVersion) rt_sleep(8000); +} diff --git a/src/tbb/examples/parallel_for/polygon_overlay/pover_video.h b/src/tbb/examples/parallel_for/polygon_overlay/pover_video.h new file mode 100644 index 0000000..5a543e5 --- /dev/null +++ b/src/tbb/examples/parallel_for/polygon_overlay/pover_video.h @@ -0,0 +1,72 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// support for GUI for polygon overlay demo +// +#ifndef _POVER_VIDEO_H_ +#define _POVER_VIDEO_H_ +#include "../../common/gui/video.h" + +#include "pover_global.h" // for declaration of DEFINE and INIT + +DEFINE class video *gVideo INIT(0); + +DEFINE int n_next_frame_calls INIT(0); +DEFINE int frame_skips INIT(10); +extern bool g_next_frame(); +extern bool g_last_frame(); + +class pover_video: public video { + void on_process(); +public: +#ifdef _WINDOWS + bool graphic_display(){return video::win_hInstance != (HINSTANCE)NULL;} +#else + bool graphic_display() { return true;} // fix this for Linux +#endif + //void on_key(int key); +}; + +DEFINE int g_xwinsize INIT(1024); +DEFINE int g_ywinsize INIT(768); + +DEFINE int map1XLoc INIT(10); +DEFINE int map1YLoc INIT(10); +DEFINE int map2XLoc INIT(270); +DEFINE int map2YLoc INIT(10); +DEFINE int maprXLoc INIT(530); +DEFINE int maprYLoc INIT(10); + +DEFINE const char *g_windowTitle INIT("Polygon Overlay"); +DEFINE bool g_useGraphics INIT(true); + +extern bool initializeVideo(int argc, char **argv); + +extern void rt_sleep(int msec); + +#endif // _POVER_VIDEO_H_ diff --git a/src/tbb/examples/parallel_for/polygon_overlay/rpolygon.h b/src/tbb/examples/parallel_for/polygon_overlay/rpolygon.h new file mode 100644 index 0000000..daba51c --- /dev/null +++ b/src/tbb/examples/parallel_for/polygon_overlay/rpolygon.h @@ -0,0 +1,163 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// rpolygon.h +// +#ifndef _RPOLYGON_H_ +#define _RPOLYGON_H_ +#include +#include +#include "pover_video.h" + +#include "tbb/scalable_allocator.h" +#include "tbb/concurrent_vector.h" +#include "tbb/enumerable_thread_specific.h" + +using namespace std; + +using namespace tbb; + +class RPolygon; +typedef scalable_allocator RPolygon_allocator; +DEFINE RPolygon_allocator rAlloc; + +enum MallocBehavior { + UseMalloc, + UseScalableAllocator +}; + +DEFINE MallocBehavior gMBehavior INIT(UseScalableAllocator); + +class RPolygon { +public: + RPolygon() {m_XMin = m_YMin = m_XMax = m_YMax = 0; + m_r = m_g = m_b = 0; + } + RPolygon(int xMin, int yMin, int xMax, int yMax, int r=-1, int g=-1, int b=-1) : m_XMin(xMin), m_YMin(yMin), m_XMax(xMax), m_YMax(yMax) { + if( r >= 0) { + m_r=(colorcomp_t)r; m_g=(colorcomp_t)g; m_b=(colorcomp_t)b; + if(gDoDraw) drawPoly(); + } + } + + void set_nodraw(int xMin, int yMin, int xMax, int yMax) {m_XMin=xMin; m_YMin=yMin; m_XMax=xMax; m_YMax=yMax;} + + RPolygon &intersect(RPolygon &otherPoly); + void set(int xMin, int yMin, int xMax, int yMax) { + set_nodraw(xMin,yMin,xMax,yMax); + if(gDoDraw) { + drawPoly(); + } + } + void get(int *xMin, int *yMin, int *xMax, int *yMax) const {*xMin=m_XMin;*yMin=m_YMin;*xMax=m_XMax;*yMax=m_YMax;} + int xmax() const { return m_XMax; } + int xmin() const { return m_XMin; } + int ymax() const { return m_YMax; } + int ymin() const { return m_YMin; } + void setColor(colorcomp_t newr, colorcomp_t newg, colorcomp_t newb) {m_r = newr; m_g=newg; m_b=newb;} + void getColor(int *myr, int *myg, int *myb) {*myr=m_r; *myg=m_g; *myb=m_b;} + color_t myColor() {return gVideo->get_color(m_r, m_g, m_b);} + void drawPoly() { + if(gVideo->running) { + if(g_next_frame()) { // Shouldn't call next_frame each time + drawing_area ldrawing( + gDrawXOffset+m_XMin*gPolyXBoxSize, //x + gDrawYOffset+m_YMin*gPolyYBoxSize, //y + (m_XMax-m_XMin+1)*gPolyXBoxSize, //sizex + (m_YMax-m_YMin+1)*gPolyYBoxSize); //sizey + for(int y=0; y b.ymin()) return false; + if(a.ymin() < b.ymin()) return true; + return a.xmin() < b.xmin(); +} +#else +extern bool operator<(const RPolygon& a, const RPolygon& b); +#endif + +extern ostream& operator<<(ostream& s, const RPolygon &p); + +class RPolygon_flagged { + RPolygon *myPoly; + bool is_duplicate; +public: + RPolygon_flagged() {myPoly = NULL; is_duplicate = false;} + RPolygon_flagged(RPolygon* _p, bool _is_duplicate) : myPoly(_p), is_duplicate(_is_duplicate) { } + bool isDuplicate() {return is_duplicate;} + void setDuplicate(bool newValue) {is_duplicate = newValue;} + RPolygon *p() {return myPoly;} + void setp(RPolygon *newp) {myPoly = newp;} +}; + +typedef class vector Polygon_map_t; +typedef class concurrent_vector concurrent_Polygon_map_t; +typedef class enumerable_thread_specific ETS_Polygon_map_t; +typedef class vector > Flagged_map_t; // we'll make shallow copies + +inline bool PolygonsOverlap(RPolygon *p1, RPolygon *p2, int &xl, int &yl, int &xh, int &yh) { + int xl1, yl1, xh1, yh1, xl2, yl2, xh2, yh2; +#if _DEBUG + rt_sleep(1); // slow down the process so we can see it. +#endif + p1->get(&xl1, &yl1, &xh1, &yh1); + p2->get(&xl2, &yl2, &xh2, &yh2); + if(xl1 > xh2) return false; + if(xh1 < xl2) return false; + if(yl1 > yh2) return false; + if(yh1 < yl2) return false; + xl = (xl1 < xl2) ? xl2 : xl1; + xh = (xh1 < xh2) ? xh1 : xh2; + yl = (yl1 < yl2) ? yl2 : yl1; + yh = (yh1 < yh2) ? yh1 : yh2; + return true; +} + +#endif // _RPOLYGON_H_ diff --git a/src/tbb/examples/parallel_for/polygon_overlay/speedup.gif b/src/tbb/examples/parallel_for/polygon_overlay/speedup.gif new file mode 100644 index 0000000000000000000000000000000000000000..04d6d876896e1e73a8452dc3bc4c6fa3771c98b5 GIT binary patch literal 7162 zcmVfPjsSjg^&^o12@Nng6G! zr?a!Oy}iA_z`)1H$I#Hw+1c6Q;o<4&>GARL_4W1o`uhL>{{R30000000000000000 z000000000000000A^sIZa%Ew3Wn>_CX>@2HRA^-&M@dak03rDV0SW*g04x9i003J9 zM*;u^{-7m}WNDsgs;+G7zHlthbZy^wuJ1ez{J@@YNGuwU$fR<~WC5DcsB}uLTCdow zcFXO0zu>TVOfH+x=(KvxZoA*`xO`5p+wb_ie$Vgw|A2vlgM@{Khlq)ai;RtqkC2g) zla!T~mzbHFo1C4VpP-?lqok##r>Lo_tE{cAuduPQv$VCgx45~wyS%-=zrex5!^FkL z$H>Xb%goKr&(P7*)6~`0*CY@GKLiX%KUmt_-YekP=jiD=4?sW*M&?!Q?Evp8@oo_Y z>iqqk0stb2Z~#C6yeC!w3ba7b;5~$I@cEla5fVUhC4M{*Am9Os2Lk{MfbcQoND>bI zIL;Fh&zwe;CLjPnFaiMpk`lH7Fd#w2#S<+Nz7*hK#LEE^HX;=v!2q|O7KVB}u@QiR zY$i#vgy`~SNCG|SRUAt;(SjcW7EB;P@1_Wu?H0lXvT$Cztwx2?(@G+wQHLRc5KwWp zpjx(E^|qTzPp3!`jvq(e8?zm`xj(c9-P&%j*s`EQ17gtb>ej0Y01URUO<;tXkONwH zO_Oy!3x)CO{()MxiL*rs+WWD#1!*9rC+FSz?(FIx4kkdCAd$M>-m6KpramAxcHPP+ zUxf=^wE6RS7yz`ob**&8KpeJ}55Rrb<&*7093g%1w&I0#cE?K5DB7=DPM zIqWQ8ore?ln3#bhnz-SRM4kaqQL`1a6-~~?wvcwRm9R~3dXbcxUQGICf?ZQ(lwt`- zitrkJR(9o0lR}y(0eO>U*EUXgtEsl{=NaR!7|nCqZ@!laoj*O~z}NCZvYz1UBsi)r2m_%Ga+01WPNY;r>YwBXw6zyCp!l zLXg!6&`SHG1y#xD>bdAj!7LK%%F%AR@WxBWyG76&(UTttntPickJ=UAcrjS$Rw9+^2sQttn$h%x9sxE zFvl$O%rw_*^UXNttn^?y zthes^>#)aeIVpb|eoq6q=dSziy!Y<=@4yEy{P4sVZ~XDdC$IeS%s21+^Uy~x{q)pV zZ~gVyXRrPCzZXEe;@|_t{rKdUZ~pn{r?39{?6>d!`|xk?y(f0teS7@)=db_%{P*ww z{{Rf20J{f@w}A*>85y7g7s$W{I`DxIjGzRMH@{i{V1gLTpawU{!47)xgAJ%4EiMSc z5}NRYC`_RWR~S4I&Vqz2jG+u?NW&W1FnunR1q^Sm!qhqF_+2AP$E+l%50`Ir}@Zdh9a8O%%(Q;Xw3p{^PAv= zWH&2XCYoLU?w{m{wIcDhlWohYX}=Sj~S!jlv7tfxNrnZkQ+BA@&Ws6aR9PfY-H zpa@N90}GmogDUi)5M8A$92(JzTC{x(#RUFEFUrx5jxVE^*r-QGO48|p)Dj{ssY+Lx zypvWUr7Vr9ObIyAncDQG)pIE&V2ab8s#K?w;HgiC+EJiNLa0PdYDA4138X6ZsR(5% zB%BJ>s_s*&kD#hmx9U!;Izp>l4XZi5+6b_U^{mh-U&L0P>x0efJw%QXJrb>@^C12VBPVngPGI^AZpU%;4Md zu^bJKa1{-#h5$!J!WfPsg~>nxz>zn@AWq_j$zZ?_hxo)m9Pu2=i{ciSPsQ$Xv5con z+!@<=g)oi-i*L+h>E##>JMOWNoA=|04Ee|%EHb~4%;XFz8DLG0as;2uh9FD%%DkiU z8mx@vE{CwjUJf(=v|M2^n|Xg^P6L|t{CqU2)6cIQHT?Rwjn9q*Rw5B(`X-KaR(LY$UrPB%K zJev;yoKCf>SIucpLl4xbX7#8iTxwH~FV?KiwXSy!XjkhQ)Vy}|tfxq665INGxDK|m zmn~~dGh5ZemSVBT5N!}A``Osewzjoh?cvt+*tg!cxW`TITz7ktwFbBKu3heSyZhbe zM&h)?tM2Ww``!4?H@4$_#CeB--vhq4z6VZlT?0JD>8^M51YYolJ3P|||DnIttMGL{ z{Nfnbbi{i&@h@!rybRB{$RGZ3dnUZ%%nSL*S5EMf)A-vce>KZzo^hAcu;X5^xpY-d z^Pam~=bJov%#FwXbDtZ1+(6H+(1$*}q96U~+-4@uyO8waIvwg*XLi+5ICU;;owrxd zy4ZRBbrW`d3uUiu*vHOxa~t#QT1fkA*WUKJr&{jlT{_c!M|ZpX9pc4=dlv9c+P?q& z@S+a9-uJFM!z2FjeB7KJ%I%CgrcN`N)1A^p7w7lsnJ# z)1yB1z#P35R9{%vzaH_lccAR6kbAw_{`R>4?HgKnQh0C_h9fWkz^}PnU$+!-L;|a!u%jPv}ZgSPq19Ku$n~R``XF zhK1y`H}+#<^;U&oXmn7hN8eM1D6obPg@$S9b8whbZRlZdc!qPBhIMFCcbH&#Sblpr zhkY15S=a(XfrojqV1hV^U|5L3bWMP0VUV~_a_ER^cuI$O4|qt4$99RBNQatOKpCNk z68=(up}2>Y$UK|KIB!#8fp}f8MpdAgiaocA%hQTNfQyM#bh8L*!c&X3c#F=ogqQbo zz&4D8Sd1{oT*9b~%lJvU*aN(HNY4n3kJwnoXnNS#jrdlL#WRgO0FHokjoxU5@_~MizOI7&%!B>3bkqlFLSs8)*X_Nk$)Ok|Kzb zBWZjtIg`5vkttaNE9pfoNs|z0lQH>xJQQX znPJ#?l1Xk`7nm+t@o%m>T+^JvO2%hFyZsKX3Ab6ha36N-{o-y^E?dgp!H=br#p7WXhpU+lu_8E(e zC7=3N*w=#wJd7uzllOUvjjAAbSB3T9+p~JXw`bQKazz*>6 zpc*=&(Dp(4_W;SE0K~G3B1)nzs&RQ&R(p1#iOrBu45e#UPz$N*2mqa?|tWSW^y zHVM`erDIyAWEyWz+71pu1h5%HOUkC%c&0K61ks|VGHIt}dTvO1ifihpTMDQ`8c}sh zsCOzs>Qn(hHltaZSBa{q@i;-ux1*6dSCdMqmAZP3fTAP704x4VjeW|gZEC5GFaSux z5OFG|O=+rZ8g2UL6zyQ4EDDsc`lpQg2n$*exWb8xNH24GLYtbaPB?5Ei4PXW7PxAx zrwTy>$N+w^6rAXW-TA7{s;dvAe}z#uw)%#EsGL)ot+5KNU*!=`Kplt}tjjvAAXKd6 znvdK1RYmax1hKA*6Rv{dt{w!h@d|{arhmzT9QZ0B*BX}pTCNMls|@<9j>Q%72i6J2z#;$yL{)WH|miBaunt;PL94VOIY5D$KsPJ3 z&&sriN>5RXwJFGDP3x;qo0?vmv)ktg70Rc#S+*RjwTVSUxxBv5|f_tlUTex;Re|Q<4jBB_O#h85?xsvO+iIApo%PnJj zftKs1EXI5`Att54w>H(apZm3UdskZF6y32ArYlpZo4PN#x_w2uQR1^WNw~BNx|53t z0w54yaVW7{puJ0|+{JuX@&gM28*?kW$BVpU#t5mgry@YDa_YI!>${j+nWwwGiV9s- z%dFoEzTBHX<11k6X};2nzFSL8v&+7!>%Nam{!;NPzw;YE>B|z(i@)uwzwg^j_v^p4 z3&8c;Q3FiC8K_(Pdto-Hz?@234NS88lfV$%lLkz=BW1xCjKS|S!6n7P9gKjk1;X|_ z!V&zz0X$41jKWYkfh+t=E$qTC%swW}Q8P@#_a|C6d{H^9!(M5_F`P?348-ThSv`!X zMhvT#mBewl#7r#22aHff48=#xfkPZiRcysHnyidS$v$b?+Tvc$)rL$dg>j*=kmpj82sPtjU(VgN&R>pA5>k2UeYIPNi(hr_4R63{I=e z%B1PaqZ~=GEX%VTg|!Sxw~Wi6M^&$^O}*^PzpTrWyiLPQ%*Bj7!8}dLtjwXu%)5+2 zKY%~a49$=yR4GX}TX>)D7-)?6Y1o{wJe90mVTxAkNB7na=yT2EoXu=FhUcuW>HN*Y z7S8te&g5)8+l;XhTaeI(&(-73`V4z^D2e%+(Ee#hj>pc^L(m0n(0+)};DaxAc}KSA z&~g^h8!J-%tk9l_(c7lc$OF+F9efi_iXfe_ZghYo9gHX4(J4KKEB()Ggn}>4J0=~| zC~b%r8?55`Mpc;8JI&KQtxNvXtU-C@yhZOAYECWFk*L9E)YMg7k_Xky zQ>4{f4Uz!m)lmf2VXd3aL)J@V)@O~@teDgg#MW)?kolz6u{qbcEKhcQL~@PSbp6&* zO_+Y2*MN=HT-4Wt{nyH~*FS{ViG7^82-gba*pCg_EhX6kMA?;X*%XA?0i@ZRO`XWY z*f#{)p)K0RL)tZD+NX`$#G~3X#M-T`ot+)njXm4gY)Y_Ar??Hxy6xE&+}pVwj=-Hi zvMt=MeN4q2KgW&Sw5^WI{XWg@+|S)Y(d|CdP2KS5NV`p}+WpRk)ZHbN-QOLa)@|Fd zUEccKN8;VD>Rr%u)c)QaMBeXR-3p1`EJWY+z1{ohy+)+p`_12jbls;G;1MlG@{K_N zZr}pGI|(j93(nvTo;wd7K@l$D^m*TgZ9^B1;Tay01fI_x&e26w;SJQ`BmUtU8RFQ3 z;wi4;CcZ!}{^9~k;Vf=(G#=9=6yuql<3@c!JPtrJ?&IAEi)G$PDMZz6 z&eLyRO4K~(RbA(_9|Abo^I)z9^9j@>4y&Jr;h5h1B-%c;j6yYksef^3E{CW z>z!2VaeeE!PD_Hh>%7kD(B$f`F5{ve?3g&~O@+=EJ=w?}*2?};EG^{E4($(S(@kFO z*6!={Oujv??Y&M*-MrA84({8Y>c(yE=kDL-uI}N^?iGCO?w;(PE${PA@1@Q?_I~e1 zD%tza?}Hfa-lRYO4)Cg&)CF(wggDI!ukd`h%MI`Fk66nQFY#X}@Z==j6>stA$j2Mc z@g1M<3kULTjq&Rw&Ln@^g*OH$T@ak52`@^Cf?% zG7t3rG%xbUGxS8CkML>pNsseHB;rjU^hQtUQ7`rAe&tn<*FFDFEuQsSkD5&H^-k|Z z11r_z1~@c(3?+A4Y5L_=%174fXbtKiHJ7QAdCIlV5#_&-sfV)r}AOkFQ2eNBWPQ z`5{I1sPFez|M{&S`sfb(v5&F|H~O_-`g8PsxnJ3;k5ZW4`>9`Qv@iU&-;Bj?{1{1G zxUc-W&qsIf{G0vzFO~e#zx)$*{nO7%+VA_^-~FAR{os%J-#`9eFaGAw^W~rZD!=~z z?EmgB^!`>qLh|4Kr8Mq9QU5Pb(fP#|`VapgV2LAHnkSm7E8Dv72#~T0BsZSxJKy_1 zFen@ni^d}|sa!If&L=b~ol>jTD>ke3(O}*$I4pj3E#;GKt6sC)?l(LxpVRC1d-gou z^ZWkT%t{&_VWHt6Vxr}oZLRGsZm#YwZ)rg#a4_(tpm0m1abR-Iatd;@88n*oG_|rdAhyVJGk3E0xAwO9 zIJvnnF*7+hx;cCBJN&x)e7$!3u>HM0HvaiPnQNBliStLvpd^F|`B_uw$Nu3%hSVVP zp;%F(G>ZT?&d|g{;~0=(M2^G=jpP@UDNS}`xlAPtm@!?3<7o3H&YU`T^6csJC(xim zhY~Gn^eED#N|!Qi>hvkps8Xj=t!niu)~s5$a_#E%E7-7N$C52;_AJ`8YS*%D>-H_& zxN_&xt!wu#-n@GE^6l&QFW|s}2NN!A_%LEIGLLyIcyCj~#u+EvZw zY>CEl=E0*4I}RxNL+j;W66=mUck>e1!B3Ylex&wj-lqdL|Ic|1{`k%uvu~GP{`K$e zsGo$cf6^J}(Z=6;#YKdSf5y0%UwwZhSl($63h2dx{Hdqhe}3WjQ9l-*q|b)IO_ zBu+$Ki5H2N;eZBK=wU?D;P)bp^5~IbKr1q6AbAB|*x+9ws&k@{sQqT#k)7dqAd4j8 zR>^`(Di&IkJz@wXc`MeIkB^I)MjfE9i&51C+R3(6LMp$M@XSRf< zg4@Zd*p)oSc_y7MU}EQ=U5;jGjAZudW=Vi9x+YhU?pf$LMFwhRm<~etCYy&6`sSrM z;u&f&I+~!;eRw7(8YZcqNWKQ#hncRb>VBX8N_Q$~kdX>Tnxn<4E3u{m z8{x6FW~pVX0llhXvp+hkA$8QFCB6se)vNBt( zNQS~&oW14FC21$wPIRk+0RQ@ALR%7CaA*SmsoIRO!FP$n#`eoF!m>qNv1YuXq_L6A za%>x|iHSTi$t9b7GRi5dyfVuzyZkcDG0QwN%{AM6GtN2dyfe=|`}{M|K?^-J(M215 zG}1{cy)@HJJN-1&QA<5F)m2-4HP%^cy*1Zed;PW60*D}X3l9hY00Clxy*ArzyAXi^ z7QpSo+32}_H{N$Muz&@73#w3(c?&)`)f1Pnz}fzMQ#^tM1Y}}>1fFfSnF9jEy_wkp zFu;HS0z4ps1O{X>00fu|khTSlKOQ;Zt-HSR03yV00s{az-~a#&Oisc8GDv{7M8DfuLe)jd-ADH2!nSX}anRqTd{LZ&O5j+3@2>4w9WzatW{O^7aeBfO+*Eijn z;ClcFUnC%)00sikeCZot2ZcvA3uuso5Ii9Y-C}?USYU-GsNL;yx4RKIP6Eh_UGF4N zJM}4`fW`}erxnt6q6BQycx1faO!jbH)@$OHi*XSM-E;Cv7` zo&G|YxdoiBfS0o(7Fox{HL@{hfomfi<5;sd%CU}iTp1njsK-6>v5$WIBOn7Q$Uzda wkcK=YA`_{|MKZFHj(j8}BPq#AQnHekyd)+wsmV=pvXh?tBq&39zYqWbJLRl{3;+NC literal 0 HcmV?d00001 diff --git a/src/tbb/examples/parallel_for/polygon_overlay/xcode/polygon_overlay.xcodeproj/project.pbxproj b/src/tbb/examples/parallel_for/polygon_overlay/xcode/polygon_overlay.xcodeproj/project.pbxproj new file mode 100644 index 0000000..4ada999 --- /dev/null +++ b/src/tbb/examples/parallel_for/polygon_overlay/xcode/polygon_overlay.xcodeproj/project.pbxproj @@ -0,0 +1,355 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 84011603152CB4AD00B07E4D /* libtbbmalloc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 84011602152CB4AD00B07E4D /* libtbbmalloc.dylib */; }; + 84B8DA19152C9AC600D59B95 /* libtbb.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 84B8DA13152C9AC600D59B95 /* libtbb.dylib */; }; + 84B8DA77152CA90100D59B95 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA6F152CA90100D59B95 /* main.m */; }; + 84B8DA78152CA90100D59B95 /* OpenGLView.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA71152CA90100D59B95 /* OpenGLView.m */; }; + 84B8DA79152CA90100D59B95 /* tbbAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA73152CA90100D59B95 /* tbbAppDelegate.m */; }; + 84B8DA7A152CA90100D59B95 /* (null) in Resources */ = {isa = PBXBuildFile; }; + 84B8DA80152CA97B00D59B95 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 84B8DA7C152CA97B00D59B95 /* InfoPlist.strings */; }; + 84B8DA81152CA97B00D59B95 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 84B8DA7E152CA97B00D59B95 /* MainMenu.xib */; }; + 84B8DA9A152CADF400D59B95 /* macvideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA99152CADF400D59B95 /* macvideo.cpp */; }; + 84B8DAAC152CB05200D59B95 /* polymain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DAA4152CB05200D59B95 /* polymain.cpp */; }; + 84B8DAAD152CB05200D59B95 /* polyover.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DAA6152CB05200D59B95 /* polyover.cpp */; }; + 84B8DAAE152CB05200D59B95 /* pover_video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DAA9152CB05200D59B95 /* pover_video.cpp */; }; + 84D017561527431F0008A4E0 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84D017551527431F0008A4E0 /* Cocoa.framework */; }; + 84D01776152744BD0008A4E0 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84D01775152744BD0008A4E0 /* OpenGL.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 84011602152CB4AD00B07E4D /* libtbbmalloc.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtbbmalloc.dylib; path = ../../../../lib/libtbbmalloc.dylib; sourceTree = ""; }; + 84B8DA13152C9AC600D59B95 /* libtbb.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtbb.dylib; path = ../../../../lib/libtbb.dylib; sourceTree = ""; }; + 84B8DA6F152CA90100D59B95 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = ../../../common/gui/xcode/tbbExample/main.m; sourceTree = ""; }; + 84B8DA70152CA90100D59B95 /* OpenGLView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenGLView.h; path = ../../../common/gui/xcode/tbbExample/OpenGLView.h; sourceTree = ""; }; + 84B8DA71152CA90100D59B95 /* OpenGLView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OpenGLView.m; path = ../../../common/gui/xcode/tbbExample/OpenGLView.m; sourceTree = ""; }; + 84B8DA72152CA90100D59B95 /* tbbAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tbbAppDelegate.h; path = ../../../common/gui/xcode/tbbExample/tbbAppDelegate.h; sourceTree = ""; }; + 84B8DA73152CA90100D59B95 /* tbbAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = tbbAppDelegate.m; path = ../../../common/gui/xcode/tbbExample/tbbAppDelegate.m; sourceTree = ""; }; + 84B8DA75152CA90100D59B95 /* tbbExample-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "tbbExample-Prefix.pch"; path = "../../../common/gui/xcode/tbbExample/tbbExample-Prefix.pch"; sourceTree = ""; }; + 84B8DA7D152CA97B00D59B95 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = InfoPlist.strings; sourceTree = ""; }; + 84B8DA7F152CA97B00D59B95 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = MainMenu.xib; sourceTree = ""; }; + 84B8DA99152CADF400D59B95 /* macvideo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = macvideo.cpp; path = ../../../common/gui/macvideo.cpp; sourceTree = ""; }; + 84B8DAA4152CB05200D59B95 /* polymain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = polymain.cpp; path = ../polymain.cpp; sourceTree = ""; }; + 84B8DAA5152CB05200D59B95 /* polymain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = polymain.h; path = ../polymain.h; sourceTree = ""; }; + 84B8DAA6152CB05200D59B95 /* polyover.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = polyover.cpp; path = ../polyover.cpp; sourceTree = ""; }; + 84B8DAA7152CB05200D59B95 /* polyover.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = polyover.h; path = ../polyover.h; sourceTree = ""; }; + 84B8DAA8152CB05200D59B95 /* pover_global.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pover_global.h; path = ../pover_global.h; sourceTree = ""; }; + 84B8DAA9152CB05200D59B95 /* pover_video.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = pover_video.cpp; path = ../pover_video.cpp; sourceTree = ""; }; + 84B8DAAA152CB05200D59B95 /* pover_video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pover_video.h; path = ../pover_video.h; sourceTree = ""; }; + 84B8DAAB152CB05200D59B95 /* rpolygon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = rpolygon.h; path = ../rpolygon.h; sourceTree = ""; }; + 84D017511527431F0008A4E0 /* tbbExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = tbbExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 84D017551527431F0008A4E0 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + 84D017581527431F0008A4E0 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + 84D017591527431F0008A4E0 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; + 84D0175A1527431F0008A4E0 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 84D01775152744BD0008A4E0 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 84D0174E1527431F0008A4E0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 84D01776152744BD0008A4E0 /* OpenGL.framework in Frameworks */, + 84D017561527431F0008A4E0 /* Cocoa.framework in Frameworks */, + 84B8DA19152C9AC600D59B95 /* libtbb.dylib in Frameworks */, + 84011603152CB4AD00B07E4D /* libtbbmalloc.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 84B8DA6C152CA8D900D59B95 /* tbbExample */ = { + isa = PBXGroup; + children = ( + 84B8DAA4152CB05200D59B95 /* polymain.cpp */, + 84B8DAA5152CB05200D59B95 /* polymain.h */, + 84B8DAA6152CB05200D59B95 /* polyover.cpp */, + 84B8DAA7152CB05200D59B95 /* polyover.h */, + 84B8DAA8152CB05200D59B95 /* pover_global.h */, + 84B8DAA9152CB05200D59B95 /* pover_video.cpp */, + 84B8DAAA152CB05200D59B95 /* pover_video.h */, + 84B8DAAB152CB05200D59B95 /* rpolygon.h */, + 84B8DA98152CAD8600D59B95 /* Gui layer */, + 84B8DA7B152CA97B00D59B95 /* Resources */, + ); + name = tbbExample; + sourceTree = ""; + }; + 84B8DA7B152CA97B00D59B95 /* Resources */ = { + isa = PBXGroup; + children = ( + 84B8DA7C152CA97B00D59B95 /* InfoPlist.strings */, + 84B8DA7E152CA97B00D59B95 /* MainMenu.xib */, + ); + name = Resources; + path = ../../../common/gui/xcode/tbbExample/en.lproj; + sourceTree = ""; + }; + 84B8DA98152CAD8600D59B95 /* Gui layer */ = { + isa = PBXGroup; + children = ( + 84B8DA99152CADF400D59B95 /* macvideo.cpp */, + 84B8DA6F152CA90100D59B95 /* main.m */, + 84B8DA70152CA90100D59B95 /* OpenGLView.h */, + 84B8DA71152CA90100D59B95 /* OpenGLView.m */, + 84B8DA72152CA90100D59B95 /* tbbAppDelegate.h */, + 84B8DA73152CA90100D59B95 /* tbbAppDelegate.m */, + 84B8DA75152CA90100D59B95 /* tbbExample-Prefix.pch */, + ); + name = "Gui layer"; + sourceTree = ""; + }; + 84D017461527431F0008A4E0 = { + isa = PBXGroup; + children = ( + 84B8DA6C152CA8D900D59B95 /* tbbExample */, + 84D017541527431F0008A4E0 /* Frameworks */, + 84D017521527431F0008A4E0 /* Products */, + ); + sourceTree = ""; + }; + 84D017521527431F0008A4E0 /* Products */ = { + isa = PBXGroup; + children = ( + 84D017511527431F0008A4E0 /* tbbExample.app */, + ); + name = Products; + sourceTree = ""; + }; + 84D017541527431F0008A4E0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 84D01775152744BD0008A4E0 /* OpenGL.framework */, + 84D017551527431F0008A4E0 /* Cocoa.framework */, + 84D017571527431F0008A4E0 /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; + 84D017571527431F0008A4E0 /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 84011602152CB4AD00B07E4D /* libtbbmalloc.dylib */, + 84B8DA13152C9AC600D59B95 /* libtbb.dylib */, + 84D017581527431F0008A4E0 /* AppKit.framework */, + 84D017591527431F0008A4E0 /* CoreData.framework */, + 84D0175A1527431F0008A4E0 /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 84D017501527431F0008A4E0 /* tbbExample */ = { + isa = PBXNativeTarget; + buildConfigurationList = 84D01772152743200008A4E0 /* Build configuration list for PBXNativeTarget "tbbExample" */; + buildPhases = ( + 84D0174D1527431F0008A4E0 /* Sources */, + 84D0174E1527431F0008A4E0 /* Frameworks */, + 84D0174F1527431F0008A4E0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = tbbExample; + productName = tbbExample; + productReference = 84D017511527431F0008A4E0 /* tbbExample.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 84D017481527431F0008A4E0 /* Project object */ = { + isa = PBXProject; + attributes = { + CLASSPREFIX = tbb; + LastUpgradeCheck = 0430; + }; + buildConfigurationList = 84D0174B1527431F0008A4E0 /* Build configuration list for PBXProject "polygon_overlay" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 84D017461527431F0008A4E0; + productRefGroup = 84D017521527431F0008A4E0 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 84D017501527431F0008A4E0 /* tbbExample */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 84D0174F1527431F0008A4E0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 84B8DA7A152CA90100D59B95 /* (null) in Resources */, + 84B8DA80152CA97B00D59B95 /* InfoPlist.strings in Resources */, + 84B8DA81152CA97B00D59B95 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 84D0174D1527431F0008A4E0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 84B8DA77152CA90100D59B95 /* main.m in Sources */, + 84B8DA78152CA90100D59B95 /* OpenGLView.m in Sources */, + 84B8DA79152CA90100D59B95 /* tbbAppDelegate.m in Sources */, + 84B8DA9A152CADF400D59B95 /* macvideo.cpp in Sources */, + 84B8DAAC152CB05200D59B95 /* polymain.cpp in Sources */, + 84B8DAAD152CB05200D59B95 /* polyover.cpp in Sources */, + 84B8DAAE152CB05200D59B95 /* pover_video.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 84B8DA7C152CA97B00D59B95 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 84B8DA7D152CA97B00D59B95 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 84B8DA7E152CA97B00D59B95 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 84B8DA7F152CA97B00D59B95 /* en */, + ); + name = MainMenu.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 84D01770152743200008A4E0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 84D01771152743200008A4E0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + SDKROOT = macosx; + }; + name = Release; + }; + 84D01773152743200008A4E0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "../../../common/gui/xcode/tbbExample/tbbExample-Prefix.pch"; + HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../include\""; + INFOPLIST_FILE = "../../../common/gui/xcode/tbbExample/tbbExample-Info.plist"; + LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/../../../../lib\""; + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_NAME = "$(TARGET_NAME)"; + RUN_CLANG_STATIC_ANALYZER = YES; + USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../include\""; + VERSION_INFO_BUILDER = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 84D01774152743200008A4E0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "../../../common/gui/xcode/tbbExample/tbbExample-Prefix.pch"; + HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../include\""; + INFOPLIST_FILE = "../../../common/gui/xcode/tbbExample/tbbExample-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "\"$(SRCROOT)/../../../../lib\"", + "\"$(SRCROOT)\"", + ); + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_NAME = "$(TARGET_NAME)"; + RUN_CLANG_STATIC_ANALYZER = YES; + USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../include\""; + VERSION_INFO_BUILDER = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 84D0174B1527431F0008A4E0 /* Build configuration list for PBXProject "polygon_overlay" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 84D01770152743200008A4E0 /* Debug */, + 84D01771152743200008A4E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 84D01772152743200008A4E0 /* Build configuration list for PBXNativeTarget "tbbExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 84D01773152743200008A4E0 /* Debug */, + 84D01774152743200008A4E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 84D017481527431F0008A4E0 /* Project object */; +} diff --git a/src/tbb/examples/parallel_for/polygon_overlay/xcode/polygon_overlay.xcodeproj/xcshareddata/xcschemes/tbbExample.xcscheme b/src/tbb/examples/parallel_for/polygon_overlay/xcode/polygon_overlay.xcodeproj/xcshareddata/xcschemes/tbbExample.xcscheme new file mode 100644 index 0000000..37d4ac6 --- /dev/null +++ b/src/tbb/examples/parallel_for/polygon_overlay/xcode/polygon_overlay.xcodeproj/xcshareddata/xcschemes/tbbExample.xcscheme @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/parallel_for/seismic/Makefile b/src/tbb/examples/parallel_for/seismic/Makefile new file mode 100644 index 0000000..414b570 --- /dev/null +++ b/src/tbb/examples/parallel_for/seismic/Makefile @@ -0,0 +1,112 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# GNU Makefile that builds and runs example. +NAME=seismic +ARGS=0:4 300 +PERF_RUN_ARGS=auto 10000 silent +LIGHT_ARGS=1:2 100 + +# The C++ compiler +ifneq (,$(shell which icc 2>/dev/null)) +CXX=icc +endif # icc + +ifeq ($(offload), mic) +override CXXFLAGS += -D__TBB_MIC=1 +# Currently only console mode is supported in offload version +override UI=con +SOURCES = $(UI)video.o universe.cpp seismic_video.cpp main.cpp +OFFLOAD_SOURCES = ../../common/gui/$(UI)video.cpp +else +SOURCES = ../../common/gui/$(UI)video.cpp universe.cpp seismic_video.cpp main.cpp +PERFFLAGS=-msse2 +endif + +ifeq ($(CXX), icc) +TBBLIB = -tbb +TBBLIB_DEBUG = -tbb +else +TBBLIB = -ltbb +TBBLIB_DEBUG = -ltbb_debug +endif + +include ../../common/gui/Makefile.gmake +override CXXFLAGS += $(UI_CXXFLAGS) + +ifeq ($(shell uname), Linux) +LIBS+= -lrt +endif + +all: release test + +resources: +ifeq ($(UI),mac) + mkdir -p $(APPRES)/en.lproj $(NAME).app/Contents/MacOS + cp ../../common/gui/xcode/tbbExample/Info.plist $(NAME).app/Contents + cp ../../common/gui/xcode/tbbExample/PkgInfo $(NAME).app/Contents + cp ../../common/gui/xcode/tbbExample/en.lproj/* $(APPRES)/en.lproj +endif # Mac + +release: $(SOURCES) resources +ifeq ($(offload), mic) + $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -c -offload-attribute-target=mic $(OFFLOAD_SOURCES) +endif +ifeq ($(UI),mac) + $(CXX_UI) -O2 -DNDEBUG $(CXXFLAGS) -c $(MACUISOURCES) +endif # Mac + $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(EXE) $(SOURCES) $(MACUIOBJS) $(TBBLIB) $(LIBS) + +debug: resources +ifeq ($(offload), mic) + $(CXX) -g -O0 -DTBB_USE_DEBUG $(CXXFLAGS) -c -offload-attribute-target=mic $(OFFLOAD_SOURCES) +endif +ifeq ($(UI),mac) + $(CXX_UI) -g -O0 -DTBB_USE_DEBUG $(CXXFLAGS) -c $(MACUISOURCES) +endif # Mac + $(CXX) -g -O0 -DTBB_USE_DEBUG $(CXXFLAGS) -o $(EXE) $(SOURCES) $(MACUIOBJS) $(TBBLIB_DEBUG) $(LIBS) + +clean: + $(RM) $(EXE) *.o *.d +ifeq ($(UI),mac) + rm -rf $(NAME).app +endif + +test: +ifeq ($(UI),mac) + export DYLD_LIBRARY_PATH="$(DYLD_LIBRARY_PATH):$(TBBLIBSPATH)"; ./$(EXE) $(ARGS) +else + ./$(EXE) $(ARGS) +endif + +perf_build: override CXXFLAGS+=$(PERFFLAGS) +perf_build: release + +perf_run: + ./$(EXE) $(PERF_RUN_ARGS) + +light_test: + ./$(EXE) $(LIGHT_ARGS) diff --git a/src/tbb/examples/parallel_for/seismic/Makefile.windows b/src/tbb/examples/parallel_for/seismic/Makefile.windows new file mode 100644 index 0000000..f973982 --- /dev/null +++ b/src/tbb/examples/parallel_for/seismic/Makefile.windows @@ -0,0 +1,75 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Common Makefile that builds and runs example. + +# Just specify your program basename +PROG=Seismic +ARGS=0:4 300 +PERF_RUN_ARGS=auto 10000 silent +LIGHT_ARGS=1:2 100 + +# Trying ot find if icl.exe is set +CXX1 = $(TBB_CXX)- +CXX2 = $(CXX1:icl.exe-=icl.exe) +CXX = $(CXX2:-=cl.exe) + +# Uncomment one of next lines to choose user interface type (console, gdiplus, direct draw) +#UI = con +UI = gdi +#UI = dd + +# Machine architecture, auto-detected from TBB_TARGET_ARCH by default +# Use XARCH variable to change it. See index.html for more information +ARCH0 = $(TBB_TARGET_ARCH)- +ARCH1 = $(ARCH0:ia32-=x86) +ARCH2 = $(ARCH1:intel64-=AMD64) +XARCH = $(ARCH2:-=x86) + +MAKEINC = ../../common/gui/Makefile.win +SOURCES = seismic_video.cpp universe.cpp main.cpp + +all: release test +release: compiler_check + @$(MAKE) -f $(MAKEINC) UI=$(UI) CXX="$(CXX)" CXXFLAGS="$(CXXFLAGS)" LFLAGS="$(LDFLAGS) tbb.lib $(LIBS)" XARCH=$(XARCH) RCNAME=SeismicSimulation SOURCE="$(SOURCES)" EXE=$(PROG).exe build_one +debug: compiler_check + @$(MAKE) -f $(MAKEINC) UI=$(UI) DEBUG=_debug CXX="$(CXX)" CXXFLAGS="$(CXXFLAGS) /D TBB_USE_DEBUG" LFLAGS="$(LDFLAGS) tbb_debug.lib $(LIBS)" XARCH=$(XARCH) RCNAME=SeismicSimulation SOURCE="$(SOURCES)" EXE=$(PROG).exe build_one +clean: + @cmd.exe /C del $(PROG).exe *.obj *.?db *.manifest msvs\SeismicSimulation.res >nul 2>&1 +test: + $(PROG) $(ARGS) + +perf_build: compiler_check + @$(MAKE) -f $(MAKEINC) UI=con CXX="$(CXX)" CXXFLAGS="$(CXXFLAGS)" LFLAGS="$(LDFLAGS) tbb.lib $(LIBS)" XARCH=$(XARCH) RCNAME=SeismicSimulation SOURCE="$(SOURCES) " EXE=$(PROG).exe build_one +perf_run: + $(PROG) $(PERF_RUN_ARGS) + +light_test: + $(PROG) $(LIGHT_ARGS) + +compiler_check: + @echo compiler_test>compiler_test && @$(CXX) /E compiler_test >nul 2>&1 || echo "$(CXX) command not found. Check if CXX=$(CXX) is set properly" + @cmd.exe /C del compiler_test diff --git a/src/tbb/examples/parallel_for/seismic/index.html b/src/tbb/examples/parallel_for/seismic/index.html new file mode 100644 index 0000000..49d11be --- /dev/null +++ b/src/tbb/examples/parallel_for/seismic/index.html @@ -0,0 +1,113 @@ + + + +

    Overview

    +
    +
    Parallel seismic wave simulation that demonstrates use of parallel_for and affinity_partitioner. +
    The example can be built in the offload version to run on Intel® Many Integrated Core (Intel® MIC) Architecture based coprocessor (see build instructions). +NOTE: Currently, the offload version does not support GUI and can only be used with console mode. +
    + +

    Files

    +
    +
    main.cpp +
    Main program which parses command line options and runs the algorithm with different numbers of threads. +
    universe.h +
    Wave propagation methods interface. +
    universe.cpp +
    Wave propagation methods implementation. +
    seismic_video.h +
    GUI mode support interface. +
    seismic_video.cpp +
    GUI mode support implementation. +
    Makefile +
    Makefile for building example. +
    + +

    Directories

    +
    +
    msvs +
    Contains Microsoft* Visual Studio* 2005 workspace for building and running the + example (Windows* systems only).
    xcode +
    Contains Xcode* IDE workspace for building and running the example (Mac OS* X + systems only).
    + +

    To Build

    +General build directions can be found here. +The following additional options are supported: +
    +
    make [(general targets: {release, debug} [test])] UI={con, gdi, dd, d2d, x, mac} +
    Build and run as usual, but build with the specified GUI driver: console, GDI+*, DirectDraw*, + Direct2D*, X11, or OpenGL* + (see the description of the common GUI code + for more information on available graphics support). + For Linux* and Mac OS* X systems, the best available driver is detected automatically by the Makefile. + For Windows* systems, UI=gdi is the default GUI driver; compiling with UI=dd or + UI=d2d may offer superior + performance, but can only be used if the Microsoft* DirectX* SDK is installed on your system + and if overlay is supported by your graphics card. + Use UI=con to build without the GUI for use in making performance measurements + (strongly recommended when measuring performance or scalability; see note below). +
    make [(above options or targets)] XARCH=x64 +
    Build and run as above, but also specify XARCH=x64 + (or XARCH=AMD64 for older compilers) when building the example on Windows* as a 64-bit binary. +
    make [(above options or targets)] DDLIB_DIR=<specify path to library directory of Direct Draw* SDK here> +
    If you experience ddraw.lib linking problems, specify the correct library directory via this option. +
    make [(above options or targets)] CXXFLAGS=-DX_FULLSYNC +
    Build and run as above, but enable full X11 synchronization if you experience "tearing" of motion on slower video systems. +
    + +

    Usage

    +
    +
    seismic -h +
    Prints the help for command line options +
    seismic [n-of-threads=value] [n-of-frames=value] [silent] [serial] +
    seismic [n-of-threads [n-of-frames]] [silent] [serial] +
    n-of-threads is the number of threads to use; a range of the form low[:high], where low and optional high are non-negative integers or 'auto' for the TBB default.
    + n-of-frames is a number of frames the example processes internally.
    + silent - no output except elapsed time.
    + serial - in GUI mode start with serial version of algorithm.
    + +
    To run a short version of this example, e.g., for use with Intel® Parallel Inspector:: +
    Build a debug version of the example + (see the build directions). +
    Run it with the desired number of threads and smaller number of frames, e.g., seismic 4 5. +
    + +

    Hot keys

    +The following hot keys can be used in interactive execution mode when the example is compiled with the graphical +user interface: +
    +
    <left mouse button> +
    Starts new seismic wave in place specified by mouse cursor. +
    <space> +
    Toggles between parallel and serial execution modes. +
    <p> +
    Enables parallel execution mode. +
    <s> +
    Enables serial execution mode. +
    <e> +
    Enables screen updates. +
    <d> +
    Disables screen updates (strongly recommended when measuring performance or scalability; see note below). +
    <esc> +
    Stops execution. +
    + +

    Notes

    +
      +
    • While running with the GUI display turned on should yield reasonable performance in most cases, running with the GUI + display turned off is strongly recommended in order to demonstrate the full performance and scalability of the example. +
    + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + diff --git a/src/tbb/examples/parallel_for/seismic/main.cpp b/src/tbb/examples/parallel_for/seismic/main.cpp new file mode 100644 index 0000000..8f33720 --- /dev/null +++ b/src/tbb/examples/parallel_for/seismic/main.cpp @@ -0,0 +1,161 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#define VIDEO_WINMAIN_ARGS + +#include +#include "tbb/tick_count.h" +#include "../../common/utility/utility.h" + +#if __TBB_MIC +#pragma offload_attribute (push,target(mic)) +#endif // __TBB_MIC +#include "seismic_video.h" +#include "universe.h" +#include "tbb/task_scheduler_init.h" + +Universe u; +#if __TBB_MIC +#pragma offload_attribute (pop) +#endif // __TBB_MIC + +struct RunOptions { + //! It is used for console mode for test with different number of threads and also has + //! meaning for GUI: threads.first - use separate event/updating loop thread (>0) or not (0). + //! threads.second - initialization value for scheduler + utility::thread_number_range threads; + int numberOfFrames; + bool silent; + bool parallel; + RunOptions(utility::thread_number_range threads_ , int number_of_frames_ , bool silent_ , bool parallel_ ) + : threads(threads_),numberOfFrames(number_of_frames_), silent(silent_), parallel(parallel_) + { + } +}; + +int do_get_default_num_threads() { + int threads; + #if __TBB_MIC + #pragma offload target(mic) out(threads) + #endif // __TBB_MIC + threads = tbb::task_scheduler_init::default_num_threads(); + return threads; +} + +int get_default_num_threads() { + static int threads = do_get_default_num_threads(); + return threads; +} + +RunOptions ParseCommandLine(int argc, char *argv[]){ + // zero number of threads means to run serial version + utility::thread_number_range threads(get_default_num_threads,0,get_default_num_threads()); + + int numberOfFrames = 1000; + bool silent = false; + bool serial = false; + + utility::parse_cli_arguments(argc,argv, + utility::cli_argument_pack() + //"-h" option for for displaying help is present implicitly + .positional_arg(threads,"n-of-threads","number of threads to use; a range of the form low[:high], where low and optional high are non-negative integers or 'auto' for the TBB default.") + .positional_arg(numberOfFrames,"n-of-frames","number of frames the example processes internally") + .arg(silent,"silent","no output except elapsed time") + .arg(serial,"serial","in GUI mode start with serial version of algorithm") + ); + return RunOptions(threads,numberOfFrames,silent,!serial); +} + +int main(int argc, char *argv[]) +{ + try{ + tbb::tick_count mainStartTime = tbb::tick_count::now(); + RunOptions options = ParseCommandLine(argc,argv); + SeismicVideo video(u,options.numberOfFrames,options.threads.last,options.parallel); + + // video layer init + if(video.init_window(u.UniverseWidth, u.UniverseHeight)) { + video.calc_fps = true; + video.threaded = options.threads.first > 0; + // video is ok, init Universe + u.InitializeUniverse(video); + // main loop + video.main_loop(); + } + else if(video.init_console()) { + // do console mode + for(int p = options.threads.first; p <= options.threads.last; ++p ) { + tbb::tick_count xwayParallelismStartTime = tbb::tick_count::now(); + u.InitializeUniverse(video); + int numberOfFrames = options.numberOfFrames; + #if __TBB_MIC + drawing_memory dmem = video.get_drawing_memory(); + char *pMem = dmem.get_address(); + size_t memSize = dmem.get_size(); + + #pragma offload target(mic) in(u, numberOfFrames, p, dmem), out(pMem:length(memSize)) + { + // It is necessary to update the pointer on mic + // since the address spaces on host and on target are different + dmem.set_address(pMem); + u.SetDrawingMemory(dmem); + #endif // __TBB_MIC + if (p==0){ + //run a serial version + for( int i=0; i_N=+wHsYe$U#6ePmShD&p^B>2uySylbs@uYIPy&-w#c zpc-6UYC)x+ErDgUwQ8BlZ7hIURRB*7exZ#T}AXG2* z=^weGTI5~Inq#r?3QZRh5>Vvy7AqDy*^i;1p6BY7;LQSXZ{;g>M z?fm5AM!1uJ~14CP5-;mbWJGeF0 z_iurN!(6GBI54yo4h(CB{j~e(6Em$hj*V=Fqpvo{5$e#07L+U2`wvFkn8s8S#Efo= z^|!}o{tozLT1|Z7UlaSMxZ(5FgK^Rilm(Khv|vko7i5X}36?lI))Ggklas69 zVxSe$=33+10BfA^v%)uXY;b;dHGCaV4e6oPadwt1PEE7L#SjO4G`kKy33kG#^P1yK zcx(J^Ra<Ti+?95-JJvGIWK0JnTs;vs^DcXy)=jK$w z=lme~e0CM~SM61i7E+Zy6!Vv8(?YCpX|5H%3$bS21{dbq;8I96Tne>C8jm-9o*mM| z?2r~#1K&~U^BwT@ygK+I#1UDG8sIO%&iE*}A+E1$jbGNa!S(fRas9ovxba>)TBY{5 zxxo`Rq9|oIDtY0?rjE#1t!!u9+}s5>w|2#i&D55z%y+}h?JrQ>af9~O4zA^n9=Nr$ z7jEt9gPXg&@$23JxV49(y|Q~4emOiI-)H_6dH=qKoBYhlq5e+&PW_AegZf|U-_)N} z9@RJC3MS7vp?yXL1qC4>AOQaU{+Kjr5++WZhzS!Wz}MFoW5Wxo&I+1!G$zZHn#$;`!98-<yjHIyy#~ zd!^|5sm6LSF)_!K%8;V#rWzZU(N_%@(#Q5Ewg{KRHI95 zY?=LIo2D9@#Ky*zb^O>SmHu~IE44l?Dgh-;K81z)WLJ`;4wqn z_ZrZ%LmzL?wy3kD_lL%jZ@l`n*YIJJ=8o?=KVm^dc=tK8XTNSrUK1xwofb5!|4WPJ z4;&O=5uecStt8`&$o&U)@7lX>*XEsj-g|fBj_upFZrx%^n^vq{{r0M5OP8-%`Odni z4ek1_pUw~WS3(xf3w~KkBmDdVRSL~dfr0)bOf7sI@n%@?lm1=c0pd4Z&T02Hm@RH2 z)we;5{I7(S*0d0%twR;wLsA|##n-X4buN70s`TsBg@MbpxknH6!QPjfV-K~P+VA6v z_lLE?{$Xwi?eB?&gE}IlpC>|?5A<%2&;edpIl33d4IhkA?7Qcs#@NdnYWsbf({dao zjuAS*69M!eGt37G)4CyX#*2ub-V>ij1>vuo!mzs+z)KgL@b7{zHqOE48v-$!zJ3#Y zv6uJbc6$T6dQ*KU=65px!K_Y5n$a2Cr*_9zn`Ys&O+gqt+y{pT0q+l>1_JwOKM87w zj|1D|zXCjwI@=4Ewok|DRTFSw+Z#B)bq3CDnTav%mol33yacQq;D9qB?)YqOTV(8< zhO{02IO`82u>Hs|UYpK$#ksIn_%f8&v3sW=YtK}ip9y^Z1~r3H`B~I#;2iDQ=@jeE zsP;Kl_%^%|E=9QF`(^IPTIr6TH*`S`ui5^ww+}9?dJfr}dg8{OA;>xEhiiu?LYUzwb+T)8Ci=PAZtkjWKvm68X{|HBivlm3|Y&X;^sP6+GhB5eJk92w>5I2 z+$j(Ix}hC1827D>9dK(?2jp()h@8zG@!QT$$l2N%x3+e|?QJ|JOre?J8PhnJ%Ni~CLrzWB&44|iS%zyB8@if zn`DaR3m@|O^QyPhwX#dzrgIKY+OQIBHLeiIw|EP z&VT0+jvL~&)rdRJe}-vnAIJ6*Q-ZDH1N-*w-gRv2&ZLw99b3D3xO=#{xw*T!wQ+Oz@bGBcd0?|n&$#sN_2S8-lrFX#RqEa{~iIg60Iwp0)kazxeJo zgX#N&>G3k(9Zpk`k46?8yGp_NR9<~gx%0b2>EBc6h6N*s;*a0{2Wy6O#7ZA8q(u55 zXmAg#9`ZC+QBk9x#nSQpa4CKpR!sCp#>stnXRBl-)qQFW^fsryy=(Z?FI2AS<5;lV$HB*W zpm$$$hhFu3THa~z+qYL;AE$u>2QZl)2G;Ru)3f^vUAny3rOUHDp6~jct50i}CXE|6 zZPK7&qvp+?vT*b1+^M5y`wmZgdAPT0`%H^xiXL6DvWOu*60xx;u6V#Q2{0r8adCy( zEn;IuV&g28p4jI>W#CW53OF&!CsAr~RottogHM>&s@S>DKq|7h|3SD9 zqF9XiYwfgmNUJRFhY%(1o6xLY)@?;QKJMM%9Zv1};>0~2!r#}0zp0zW`xNH9UeDj( zg}=XRQtjm}{_d~Eq+;bB6m$ICmr^L!lH$^jp`^CQQOEr>=J>f^rrg)^KRssd^D)QI zeLuo|80KTp^Sb>{=X%)v)pLRSmCW&T|B@EJinpT1Tyzb%m&zPJ_g4w`z?hFg`Rd1_ z>Wj7&9jm;{DmLy1Gsn+8Vp@!PtSTNouWWh8cdz+W{M_4Sj-PwjDs;R>k4LR3_uiS~ z=YBll{weJklr8FC(aI`*?jJPA&pn00ytW2@1pNNmFr)z)}MRaMZIsT^P*Jr zd{v~ficiI=V%Fb3xlf-prc}}2|5bcSDrP-?@&@_Qn~c8Rs-)*Df-M*%`H0H+%lZ72 zvi{EGQOr#h;dxS84CWx2AwMJBn{b$~fyU%&3N}@!=X}9qDHtRuG5tUm68j-~fkG1sqOUyGmYlwPgb z2OYaS`ssnHnDzL{f$7y1HvU2ZvOsRl96y=1qRkb)O#V)fzZuy)A>;K#iJYK%{YIx)`7mahDM1B1t%cm9kaZNYkD4X_DC9qd+$8->B5TQhB} zPLpFP(T5^y$$V8IA1dTRh5V#84>?gGBg(O=3b|S#mnh^Cg)FI%vsB;THmdl^aSGW> zA@3;U9fcgEkcSj)tKX)y|CMyJ9 zWMGAisgNZVGNwZIRLI7bES?uKuA0cIN->306SAtME58p}SdPK5N}H!(y?QQ$SPR)# zEw=cH;9p8myVEOE~ZJrY}3iIg?0rP&%LTBp=}8h@I%TXv<9-xUO`%}-uWt5a*E=2Z6^)Nip$4?6}mrb=W3r9pMm{N(?%I<=0f{ZX!iK0oKQ1d^EdG#^%`N>O4Lp#&)lc_BC`N?cbBh&ou z$Ha>#mE4>Z3XbJ2L!+Nt++W%XmzCnEDKwe#1XEVN#&9kX7z*Ba>aDt~p(O7d58 ztNMbLMIj4qo}V1Gs?t)?V|bWl{j*<9L>}8bKN)V*HyMT)&Xn7jpKpqbGz6zmVk@{(S%;moMb= zg`B=PIy$QPUCF}>xq2agFXZoq+`W*w*DN`FAuBIr%G&-D!IW`F9}` zFJ#_@jJ%MQmz-@~sV+i3UdYL7B1xFE+kg*rC_sn}}eaYVo*?J*YFZ>$;!oOJ{ z{QCgB-)1FF4i?imzkPZz{4Rvr{h7I>sgUu{%LsSK%b0JUml0-1RnN;GSP!(-+jpO%JopO`B((dnpK-(&yRaUJ6F; zchnE_k$Wv1f4{oG;*T$8Vx5|ss!Wf01@yO_$nuNBLZ4Gvb)Vu6x9f7RD3t3{RPFna z@~=**zWfUs8kYPPZCSL4e)B1xT|TXnSM+U>y|{O?8%m4vtzIr_BVKg5vCP}`*3dR} z&a!{N#n>%>kU18z!$Q_q$meQ#RW3=oZ=knFmg=8&V&`qOUg~p1N&lWwnpHmPb9YW3 zw+z)kIP(xwOMAJX5{|A*v__uZdtvV;w2rOkgeCCc1i z#a5Q%Amc3IgIa3+fBIm(x&OWTs_~Un|HxNN{coH$#m{POUDev^Dy>e{FMhe1Y5iiu zZ + + + + diff --git a/src/tbb/examples/parallel_for/seismic/msvs/SeismicSimulation.rc b/src/tbb/examples/parallel_for/seismic/msvs/SeismicSimulation.rc new file mode 100644 index 0000000..c200334 --- /dev/null +++ b/src/tbb/examples/parallel_for/seismic/msvs/SeismicSimulation.rc @@ -0,0 +1,145 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_SEISMICSIMULATION ICON "SeismicSimulation.ico" +IDI_SMALL ICON "small.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDC_SEISMICSIMULATION MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Parallel", ID_FILE_PARALLEL + MENUITEM "&Serial", ID_FILE_SERIAL + MENUITEM SEPARATOR + MENUITEM "&Enable GUI", ID_FILE_ENABLEGUI + MENUITEM "&Disable GUI", ID_FILE_DISABLEGUI + MENUITEM SEPARATOR + MENUITEM "E&xit", IDM_EXIT + END + POPUP "&Help" + BEGIN + MENUITEM "&About ...", IDM_ABOUT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDC_SEISMICSIMULATION ACCELERATORS +BEGIN + VK_OEM_2, IDM_ABOUT, VIRTKEY, ALT, NOINVERT + "P", ID_FILE_PARALLEL, VIRTKEY, ALT, NOINVERT + "S", ID_FILE_SERIAL, VIRTKEY, ALT, NOINVERT + "D", ID_FILE_DISABLEGUI, VIRTKEY, ALT, NOINVERT + "E", ID_FILE_ENABLEGUI, VIRTKEY, ALT, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOG 22, 17, 230, 75 +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "About" +FONT 8, "System" +BEGIN + ICON IDI_SEISMICSIMULATION,IDC_MYICON,14,9,16,16 + LTEXT "SeismicSimulation Version 1.1",IDC_STATIC,49,10,119,8,SS_NOPREFIX + LTEXT "Copyright (C) 2005-2008",IDC_STATIC,49,20,119,8 + DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_APP_TITLE "SeismicSimulation" + IDC_SEISMICSIMULATION "SEISMICSIMULATION" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/tbb/examples/parallel_for/seismic/msvs/SeismicSimulation.vcproj b/src/tbb/examples/parallel_for/seismic/msvs/SeismicSimulation.vcproj new file mode 100644 index 0000000..61e7535 --- /dev/null +++ b/src/tbb/examples/parallel_for/seismic/msvs/SeismicSimulation.vcproj @@ -0,0 +1,836 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/parallel_for/seismic/msvs/SeismicSimulation_cl.sln b/src/tbb/examples/parallel_for/seismic/msvs/SeismicSimulation_cl.sln new file mode 100644 index 0000000..a953c4a --- /dev/null +++ b/src/tbb/examples/parallel_for/seismic/msvs/SeismicSimulation_cl.sln @@ -0,0 +1,37 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SeismicSimulation", "SeismicSimulation.vcproj", "{3AA40693-F93D-4D4B-B32E-068F511A2527}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + DD Debug|Win32 = DD Debug|Win32 + DD Debug|x64 = DD Debug|x64 + DD Release|Win32 = DD Release|Win32 + DD Release|x64 = DD Release|x64 + GDI Debug|Win32 = GDI Debug|Win32 + GDI Debug|x64 = GDI Debug|x64 + _GDI Release|Win32 = _GDI Release|Win32 + _GDI Release|x64 = _GDI Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Debug|Win32.Build.0 = DDDebug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Debug|x64.Build.0 = DDDebug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Release|Win32.Build.0 = DDRelease|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Release|x64.ActiveCfg = DDRelease|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Release|x64.Build.0 = DDRelease|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.GDI Debug|Win32.Build.0 = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.GDI Debug|x64.ActiveCfg = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.GDI Debug|x64.Build.0 = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}._GDI Release|Win32.ActiveCfg = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}._GDI Release|Win32.Build.0 = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}._GDI Release|x64.ActiveCfg = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}._GDI Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/parallel_for/seismic/msvs/SeismicSimulation_icl.sln b/src/tbb/examples/parallel_for/seismic/msvs/SeismicSimulation_icl.sln new file mode 100644 index 0000000..6bca0c1 --- /dev/null +++ b/src/tbb/examples/parallel_for/seismic/msvs/SeismicSimulation_icl.sln @@ -0,0 +1,53 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "SeismicSimulation", "SeismicSimulation.icproj", "{87C5A3E0-E1C8-457F-AA2F-B3E455214E76}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + DD Debug|Win32 = DD Debug|Win32 + DD Debug|x64 = DD Debug|x64 + DD Release|Win32 = DD Release|Win32 + DD Release|x64 = DD Release|x64 + GDI Debug|Win32 = GDI Debug|Win32 + GDI Debug|x64 = GDI Debug|x64 + _GDI Release|Win32 = _GDI Release|Win32 + _GDI Release|x64 = _GDI Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {87C5A3E0-E1C8-457F-AA2F-B3E455214E76}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + {87C5A3E0-E1C8-457F-AA2F-B3E455214E76}.DD Debug|Win32.Build.0 = DDDebug|Win32 + {87C5A3E0-E1C8-457F-AA2F-B3E455214E76}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {87C5A3E0-E1C8-457F-AA2F-B3E455214E76}.DD Debug|x64.Build.0 = DDDebug|x64 + {87C5A3E0-E1C8-457F-AA2F-B3E455214E76}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {87C5A3E0-E1C8-457F-AA2F-B3E455214E76}.DD Release|Win32.Build.0 = DDRelease|Win32 + {87C5A3E0-E1C8-457F-AA2F-B3E455214E76}.DD Release|x64.ActiveCfg = DDRelease|x64 + {87C5A3E0-E1C8-457F-AA2F-B3E455214E76}.DD Release|x64.Build.0 = DDRelease|x64 + {87C5A3E0-E1C8-457F-AA2F-B3E455214E76}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {87C5A3E0-E1C8-457F-AA2F-B3E455214E76}.GDI Debug|Win32.Build.0 = Debug|Win32 + {87C5A3E0-E1C8-457F-AA2F-B3E455214E76}.GDI Debug|x64.ActiveCfg = Debug|x64 + {87C5A3E0-E1C8-457F-AA2F-B3E455214E76}.GDI Debug|x64.Build.0 = Debug|x64 + {87C5A3E0-E1C8-457F-AA2F-B3E455214E76}._GDI Release|Win32.ActiveCfg = Release|Win32 + {87C5A3E0-E1C8-457F-AA2F-B3E455214E76}._GDI Release|Win32.Build.0 = Release|Win32 + {87C5A3E0-E1C8-457F-AA2F-B3E455214E76}._GDI Release|x64.ActiveCfg = Release|x64 + {87C5A3E0-E1C8-457F-AA2F-B3E455214E76}._GDI Release|x64.Build.0 = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}._GDI Release|x64.Build.0 = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}._GDI Release|x64.ActiveCfg = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}._GDI Release|Win32.Build.0 = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}._GDI Release|Win32.ActiveCfg = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.GDI Debug|x64.Build.0 = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.GDI Debug|x64.ActiveCfg = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.GDI Debug|Win32.Build.0 = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Release|x64.Build.0 = DDRelease|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Release|x64.ActiveCfg = DDRelease|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Release|Win32.Build.0 = DDRelease|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Debug|x64.Build.0 = DDDebug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Debug|Win32.Build.0 = DDDebug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/parallel_for/seismic/msvs/resource.h b/src/tbb/examples/parallel_for/seismic/msvs/resource.h new file mode 100644 index 0000000..44453d7 --- /dev/null +++ b/src/tbb/examples/parallel_for/seismic/msvs/resource.h @@ -0,0 +1,32 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by SeismicSimulation.rc +// +#define IDC_MYICON 2 +#define IDD_SEISMICSIMULATION_DIALOG 102 +#define IDS_APP_TITLE 103 +#define IDD_ABOUTBOX 103 +#define IDM_ABOUT 104 +#define IDM_EXIT 105 +#define IDI_SEISMICSIMULATION 107 +#define IDI_SMALL 108 +#define IDC_SEISMICSIMULATION 109 +#define IDR_MAINFRAME 128 +#define ID_FILE_PARALLEL 32771 +#define ID_FILE_SERIAL 32772 +#define IDM_PARALLEL 32773 +#define ID_FILE_ENABLEGUI 32774 +#define ID_FILE_DISABLEGUI 32775 +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32782 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/src/tbb/examples/parallel_for/seismic/msvs/small.ico b/src/tbb/examples/parallel_for/seismic/msvs/small.ico new file mode 100644 index 0000000000000000000000000000000000000000..d551aa3aaf80adf9b7760e2eb8de95a5c3e53df6 GIT binary patch literal 23558 zcmeI430zgx+QuJHKtxbe5gbu*030B5$VyGcDGSFOalkY&2LuvC5pp(7&2XNl96=@z zNXGH2`|DO#nx)3nwUq43A>_N=+wHsYe$U#6ePmShD&p^B>2uySylbs@uYIPy&-w#c zpc-6UYC)x+ErDgUwQ8BlZ7hIURRB*7exZ#T}AXG2* z=^weGTI5~Inq#r?3QZRh5>Vvy7AqDy*^i;1p6BY7;LQSXZ{;g>M z?fm5AM!1uJ~14CP5-;mbWJGeF0 z_iurN!(6GBI54yo4h(CB{j~e(6Em$hj*V=Fqpvo{5$e#07L+U2`wvFkn8s8S#Efo= z^|!}o{tozLT1|Z7UlaSMxZ(5FgK^Rilm(Khv|vko7i5X}36?lI))Ggklas69 zVxSe$=33+10BfA^v%)uXY;b;dHGCaV4e6oPadwt1PEE7L#SjO4G`kKy33kG#^P1yK zcx(J^Ra<Ti+?95-JJvGIWK0JnTs;vs^DcXy)=jK$w z=lme~e0CM~SM61i7E+Zy6!Vv8(?YCpX|5H%3$bS21{dbq;8I96Tne>C8jm-9o*mM| z?2r~#1K&~U^BwT@ygK+I#1UDG8sIO%&iE*}A+E1$jbGNa!S(fRas9ovxba>)TBY{5 zxxo`Rq9|oIDtY0?rjE#1t!!u9+}s5>w|2#i&D55z%y+}h?JrQ>af9~O4zA^n9=Nr$ z7jEt9gPXg&@$23JxV49(y|Q~4emOiI-)H_6dH=qKoBYhlq5e+&PW_AegZf|U-_)N} z9@RJC3MS7vp?yXL1qC4>AOQaU{+Kjr5++WZhzS!Wz}MFoW5Wxo&I+1!G$zZHn#$;`!98-<yjHIyy#~ zd!^|5sm6LSF)_!K%8;V#rWzZU(N_%@(#Q5Ewg{KRHI95 zY?=LIo2D9@#Ky*zb^O>SmHu~IE44l?Dgh-;K81z)WLJ`;4wqn z_ZrZ%LmzL?wy3kD_lL%jZ@l`n*YIJJ=8o?=KVm^dc=tK8XTNSrUK1xwofb5!|4WPJ z4;&O=5uecStt8`&$o&U)@7lX>*XEsj-g|fBj_upFZrx%^n^vq{{r0M5OP8-%`Odni z4ek1_pUw~WS3(xf3w~KkBmDdVRSL~dfr0)bOf7sI@n%@?lm1=c0pd4Z&T02Hm@RH2 z)we;5{I7(S*0d0%twR;wLsA|##n-X4buN70s`TsBg@MbpxknH6!QPjfV-K~P+VA6v z_lLE?{$Xwi?eB?&gE}IlpC>|?5A<%2&;edpIl33d4IhkA?7Qcs#@NdnYWsbf({dao zjuAS*69M!eGt37G)4CyX#*2ub-V>ij1>vuo!mzs+z)KgL@b7{zHqOE48v-$!zJ3#Y zv6uJbc6$T6dQ*KU=65px!K_Y5n$a2Cr*_9zn`Ys&O+gqt+y{pT0q+l>1_JwOKM87w zj|1D|zXCjwI@=4Ewok|DRTFSw+Z#B)bq3CDnTav%mol33yacQq;D9qB?)YqOTV(8< zhO{02IO`82u>Hs|UYpK$#ksIn_%f8&v3sW=YtK}ip9y^Z1~r3H`B~I#;2iDQ=@jeE zsP;Kl_%^%|E=9QF`(^IPTIr6TH*`S`ui5^ww+}9?dJfr}dg8{OA;>xEhiiu?LYUzwb+T)8Ci=PAZtkjWKvm68X{|HBivlm3|Y&X;^sP6+GhB5eJk92w>5I2 z+$j(Ix}hC1827D>9dK(?2jp()h@8zG@!QT$$l2N%x3+e|?QJ|JOre?J8PhnJ%Ni~CLrzWB&44|iS%zyB8@if zn`DaR3m@|O^QyPhwX#dzrgIKY+OQIBHLeiIw|EP z&VT0+jvL~&)rdRJe}-vnAIJ6*Q-ZDH1N-*w-gRv2&ZLw99b3D3xO=#{xw*T!wQ+Oz@bGBcd0?|n&$#sN_2S8-lrFX#RqEa{~iIg60Iwp0)kazxeJo zgX#N&>G3k(9Zpk`k46?8yGp_NR9<~gx%0b2>EBc6h6N*s;*a0{2Wy6O#7ZA8q(u55 zXmAg#9`ZC+QBk9x#nSQpa4CKpR!sCp#>stnXRBl-)qQFW^fsryy=(Z?FI2AS<5;lV$HB*W zpm$$$hhFu3THa~z+qYL;AE$u>2QZl)2G;Ru)3f^vUAny3rOUHDp6~jct50i}CXE|6 zZPK7&qvp+?vT*b1+^M5y`wmZgdAPT0`%H^xiXL6DvWOu*60xx;u6V#Q2{0r8adCy( zEn;IuV&g28p4jI>W#CW53OF&!CsAr~RottogHM>&s@S>DKq|7h|3SD9 zqF9XiYwfgmNUJRFhY%(1o6xLY)@?;QKJMM%9Zv1};>0~2!r#}0zp0zW`xNH9UeDj( zg}=XRQtjm}{_d~Eq+;bB6m$ICmr^L!lH$^jp`^CQQOEr>=J>f^rrg)^KRssd^D)QI zeLuo|80KTp^Sb>{=X%)v)pLRSmCW&T|B@EJinpT1Tyzb%m&zPJ_g4w`z?hFg`Rd1_ z>Wj7&9jm;{DmLy1Gsn+8Vp@!PtSTNouWWh8cdz+W{M_4Sj-PwjDs;R>k4LR3_uiS~ z=YBll{weJklr8FC(aI`*?jJPA&pn00ytW2@1pNNmFr)z)}MRaMZIsT^P*Jr zd{v~ficiI=V%Fb3xlf-prc}}2|5bcSDrP-?@&@_Qn~c8Rs-)*Df-M*%`H0H+%lZ72 zvi{EGQOr#h;dxS84CWx2AwMJBn{b$~fyU%&3N}@!=X}9qDHtRuG5tUm68j-~fkG1sqOUyGmYlwPgb z2OYaS`ssnHnDzL{f$7y1HvU2ZvOsRl96y=1qRkb)O#V)fzZuy)A>;K#iJYK%{YIx)`7mahDM1B1t%cm9kaZNYkD4X_DC9qd+$8->B5TQhB} zPLpFP(T5^y$$V8IA1dTRh5V#84>?gGBg(O=3b|S#mnh^Cg)FI%vsB;THmdl^aSGW> zA@3;U9fcgEkcSj)tKX)y|CMyJ9 zWMGAisgNZVGNwZIRLI7bES?uKuA0cIN->306SAtME58p}SdPK5N}H!(y?QQ$SPR)# zEw=cH;9p8myVEOE~ZJrY}3iIg?0rP&%LTBp=}8h@I%TXv<9-xUO`%}-uWt5a*E=2Z6^)Nip$4?6}mrb=W3r9pMm{N(?%I<=0f{ZX!iK0oKQ1d^EdG#^%`N>O4Lp#&)lc_BC`N?cbBh&ou z$Ha>#mE4>Z3XbJ2L!+Nt++W%XmzCnEDKwe#1XEVN#&9kX7z*Ba>aDt~p(O7d58 ztNMbLMIj4qo}V1Gs?t)?V|bWl{j*<9L>}8bKN)V*HyMT)&Xn7jpKpqbGz6zmVk@{(S%;moMb= zg`B=PIy$QPUCF}>xq2agFXZoq+`W*w*DN`FAuBIr%G&-D!IW`F9}` zFJ#_@jJ%MQmz-@~sV+i3UdYL7B1xFE+kg*rC_sn}}eaYVo*?J*YFZ>$;!oOJ{ z{QCgB-)1FF4i?imzkPZz{4Rvr{h7I>sgUu{%LsSK%b0JUml0-1RnN;GSP!(-+jpO%JopO`B((dnpK-(&yRaUJ6F; zchnE_k$Wv1f4{oG;*T$8Vx5|ss!Wf01@yO_$nuNBLZ4Gvb)Vu6x9f7RD3t3{RPFna z@~=**zWfUs8kYPPZCSL4e)B1xT|TXnSM+U>y|{O?8%m4vtzIr_BVKg5vCP}`*3dR} z&a!{N#n>%>kU18z!$Q_q$meQ#RW3=oZ=knFmg=8&V&`qOUg~p1N&lWwnpHmPb9YW3 zw+z)kIP(xwOMAJX5{|A*v__uZdtvV;w2rOkgeCCc1i z#a5Q%Amc3IgIa3+fBIm(x&OWTs_~Un|HxNN{coH$#m{POUDev^Dy>e{FMhe1Y5iiu zZ 0 ) --numberOfFrames_; + } while(next_frame() && numberOfFrames_); +} + +#ifdef _WINDOWS +#include "msvs/resource.h" +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); +SeismicVideo * gVideo = NULL; +#endif + +SeismicVideo::SeismicVideo( Universe &u, int number_of_frames, int threads_high, bool init_is_parallel) + :numberOfFrames_(number_of_frames),initIsParallel(init_is_parallel),u_(u),threadsHigh(threads_high) +{ + title = initIsParallel?titles[1]:titles[0]; +#ifdef _WINDOWS + gVideo = this; + LoadStringA(video::win_hInstance, IDC_SEISMICSIMULATION, szWindowClass, MAX_LOADSTRING); + memset(&wcex, 0, sizeof(wcex)); + wcex.lpfnWndProc = (WNDPROC)WndProc; + wcex.hIcon = LoadIcon(video::win_hInstance, MAKEINTRESOURCE(IDI_SEISMICSIMULATION)); + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wcex.lpszMenuName = LPCTSTR(IDC_SEISMICSIMULATION); + wcex.lpszClassName = szWindowClass; + wcex.hIconSm = LoadIcon(video::win_hInstance, MAKEINTRESOURCE(IDI_SMALL)); + win_set_class(wcex); // ascii convention here + win_load_accelerators(IDC_SEISMICSIMULATION); +#endif + +} + + + + + +#ifdef _WINDOWS +// +// FUNCTION: WndProc(HWND, unsigned, WORD, LONG) +// +// PURPOSE: Processes messages for the main window. +// +// WM_COMMAND - process the application menu +// WM_PAINT - Paint the main window +// WM_DESTROY - post a quit message and return +// +// +LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_INITDIALOG: return TRUE; + case WM_COMMAND: + if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, LOWORD(wParam)); + return TRUE; + } + break; + } + return FALSE; +} + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int wmId; + switch (message) { + case WM_COMMAND: + wmId = LOWORD(wParam); + // Parse the menu selections: + switch (wmId) + { + case IDM_ABOUT: + DialogBox(video::win_hInstance, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, (DLGPROC)About); + break; + case IDM_EXIT: + PostQuitMessage(0); + break; + case ID_FILE_PARALLEL: + gVideo->on_key('p'); + break; + case ID_FILE_SERIAL: + gVideo->on_key('s'); + break; + case ID_FILE_ENABLEGUI: + gVideo->on_key('e'); + break; + case ID_FILE_DISABLEGUI: + gVideo->on_key('d'); + break; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + break; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; +} + +#endif diff --git a/src/tbb/examples/parallel_for/seismic/seismic_video.h b/src/tbb/examples/parallel_for/seismic/seismic_video.h new file mode 100644 index 0000000..3e5ba1d --- /dev/null +++ b/src/tbb/examples/parallel_for/seismic/seismic_video.h @@ -0,0 +1,62 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef SEISMIC_VIDEO_H_ +#define SEISMIC_VIDEO_H_ + +#include "../../common/gui/video.h" + +class Universe; + +class SeismicVideo : public video +{ +#ifdef _WINDOWS + #define MAX_LOADSTRING 100 + TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name + WNDCLASSEX wcex; +#endif + static const char * const titles[2]; + + bool initIsParallel ; + + Universe &u_; + int numberOfFrames_; + int threadsHigh; +private: + void on_mouse(int x, int y, int key); + void on_process(); + +#ifdef _WINDOWS +public: +#endif + void on_key(int key); + +public: + SeismicVideo( Universe &u,int numberOfFrames, int threadsHigh, bool initIsParallel=true); +}; +#endif /* SEISMIC_VIDEO_H_ */ diff --git a/src/tbb/examples/parallel_for/seismic/universe.cpp b/src/tbb/examples/parallel_for/seismic/universe.cpp new file mode 100644 index 0000000..78557d4 --- /dev/null +++ b/src/tbb/examples/parallel_for/seismic/universe.cpp @@ -0,0 +1,233 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if __TBB_MIC +#pragma offload_attribute (target(mic)) +#endif // __TBB_MIC + +#include "../../common/gui/video.h" +#include +#include "tbb/blocked_range.h" +#include "tbb/parallel_for.h" + + +using namespace std; + +#ifdef _MSC_VER +// warning C4068: unknown pragma +#pragma warning(disable: 4068) +// warning C4351: new behavior: elements of array 'array' will be default initialized +#pragma warning(disable: 4351) +#endif + +#include "universe.h" + +const colorcomp_t MaterialColor[4][3] = { // BGR + {96,0,0}, // WATER + {0,48,48}, // SANDSTONE + {32,32,23} // SHALE +}; + +void Universe::InitializeUniverse(video const& colorizer) { + + pulseCounter = pulseTime = 100; + pulseX = UniverseWidth/3; + pulseY = UniverseHeight/4; + // Initialize V, S, and T to slightly non-zero values, in order to avoid denormal waves. + for( int i=0; i0 ? t : 0; + ValueType b = t<0 ? -t : 0; + ValueType g = 0.5f*fabs(t); + memcpy(c, MaterialColor[k], sizeof(c)); + c[2] = colorcomp_t(r*(255-c[2])+c[2]); + c[1] = colorcomp_t(g*(255-c[1])+c[1]); + c[0] = colorcomp_t(b*(255-c[0])+c[0]); + ColorMap[k][i] = colorizer.get_color(c[2], c[1], c[0]); + } + } + // Set damping coefficients around border to reduce reflections from boundaries. + ValueType d = 1.0; + for( int k=DamperSize-1; k>0; --k ) { + d *= 1-1.0f/(DamperSize*DamperSize); + for( int j=1; j0 ) { + ValueType t = (pulseCounter-pulseTime/2)*0.05f; + V[pulseY][pulseX] += 64*sqrt(M[pulseY][pulseX])*exp(-t*t); + --pulseCounter; + } +} + +struct Universe::Rectangle { + struct std::pair xRange; + struct std::pair yRange; + Rectangle (int startX, int startY, int width, int height):xRange(startX,width),yRange(startY,height){} + int StartX() const {return xRange.first;} + int StartY() const {return yRange.first;} + int Width() const {return xRange.second;} + int Height() const {return yRange.second;} + int EndX() const {return xRange.first + xRange.second;} + int EndY() const {return yRange.first + yRange.second;} + +}; + +void Universe::UpdateStress(Rectangle const& r ) { + drawing_area drawing(r.StartX(),r.StartY(),r.Width(),r.Height(),drawingMemory); + for( int i=r.StartY(); i=ColorMapSize ) index = ColorMapSize-1; + color_t* c = ColorMap[material[i][j]]; + drawing.put_pixel(c[index]); + } + } +} + +void Universe::SerialUpdateStress() { + Rectangle area(0, 0, UniverseWidth-1, UniverseHeight-1); + UpdateStress(area); +} + +struct UpdateStressBody { + Universe & u_; + UpdateStressBody(Universe & u):u_(u){} + void operator()( const tbb::blocked_range& range ) const { + Universe::Rectangle area(0, range.begin(), u_.UniverseWidth-1, range.size()); + u_.UpdateStress(area); + } +}; + +void Universe::ParallelUpdateStress(tbb::affinity_partitioner &affinity) { + tbb::parallel_for( tbb::blocked_range( 0, UniverseHeight-1 ), // Index space for loop + UpdateStressBody(*this), // Body of loop + affinity ); // Affinity hint +} + +void Universe::UpdateVelocity(Rectangle const& r) { + for( int i=r.StartY(); i& y_range ) const { + u_.UpdateVelocity(Universe::Rectangle(0,y_range.begin(),u_.UniverseWidth-1,y_range.size())); + } +}; + +void Universe::ParallelUpdateVelocity(tbb::affinity_partitioner &affinity) { + tbb::parallel_for( tbb::blocked_range( 0, UniverseHeight-1 ), // Index space for loop + UpdateVelocityBody(*this), // Body of loop + affinity ); // Affinity hint +} + +void Universe::SerialUpdateUniverse() { + UpdatePulse(); + SerialUpdateStress(); + SerialUpdateVelocity(); +} + +void Universe::ParallelUpdateUniverse() { + /** Affinity is an argument to parallel_for to hint that an iteration of a loop + is best replayed on the same processor for each execution of the loop. + It is a static object because it must remember where the iterations happened + in previous executions. */ + static tbb::affinity_partitioner affinity; + UpdatePulse(); + ParallelUpdateStress(affinity); + ParallelUpdateVelocity(affinity); +} + +bool Universe::TryPutNewPulseSource(int x, int y){ + if(pulseCounter == 0) { + pulseCounter = pulseTime; + pulseX = x; pulseY = y; + return true; + } + return false; +} + +void Universe::SetDrawingMemory(const drawing_memory &dmem) { + drawingMemory = dmem; +} diff --git a/src/tbb/examples/parallel_for/seismic/universe.h b/src/tbb/examples/parallel_for/seismic/universe.h new file mode 100644 index 0000000..54cadfd --- /dev/null +++ b/src/tbb/examples/parallel_for/seismic/universe.h @@ -0,0 +1,120 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef UNIVERSE_H_ +#define UNIVERSE_H_ + +#include "../../common/gui/video.h" +#include "tbb/partitioner.h" + + +class Universe { +public: + enum { + UniverseWidth = 1024 + ,UniverseHeight = 512 + }; +private: + //in order to avoid performance degradation due to cache aliasing issue + //some padding is needed after each row in array, and between array themselves. + //the padding is achieved by adjusting number of rows and columns. + //as the compiler is forced to place class members of the same clause in order of the + //declaration this seems to be the right way of padding. + + //magic constants what are being added bellow are chosen experimentally. + enum { + MaxWidth = UniverseWidth+1, + MaxHeight = UniverseHeight+3 + }; + + typedef float ValueType; + + //! Horizontal stress + ValueType S[MaxHeight][MaxWidth]; + + //! Velocity at each grid point + ValueType V[MaxHeight][MaxWidth]; + + //! Vertical stress + ValueType T[MaxHeight][MaxWidth]; + + //! Coefficient related to modulus + ValueType M[MaxHeight][MaxWidth]; + + //! Damping coefficients + ValueType D[MaxHeight][MaxWidth]; + + //! Coefficient related to lightness + ValueType L[MaxHeight][MaxWidth]; + + enum { ColorMapSize = 1024}; + color_t ColorMap[4][ColorMapSize]; + + enum MaterialType { + WATER=0, + SANDSTONE=1, + SHALE=2 + }; + + //! Values are MaterialType, cast to an unsigned char to save space. + unsigned char material[MaxHeight][MaxWidth]; + +private: + enum { DamperSize = 32}; + + int pulseTime; + int pulseCounter; + int pulseX; + int pulseY; + + drawing_memory drawingMemory; + +public: + void InitializeUniverse(video const& colorizer); + + void SerialUpdateUniverse(); + void ParallelUpdateUniverse(); + bool TryPutNewPulseSource(int x, int y); + void SetDrawingMemory(const drawing_memory &dmem); +private: + struct Rectangle; + void UpdatePulse(); + void UpdateStress(Rectangle const& r ); + + void SerialUpdateStress() ; + friend struct UpdateStressBody; + friend struct UpdateVelocityBody; + void ParallelUpdateStress(tbb::affinity_partitioner &affinity); + + void UpdateVelocity(Rectangle const& r); + + void SerialUpdateVelocity() ; + void ParallelUpdateVelocity(tbb::affinity_partitioner &affinity); +}; + +#endif /* UNIVERSE_H_ */ diff --git a/src/tbb/examples/parallel_for/seismic/xcode/seismic.xcodeproj/project.pbxproj b/src/tbb/examples/parallel_for/seismic/xcode/seismic.xcodeproj/project.pbxproj new file mode 100644 index 0000000..ff39465 --- /dev/null +++ b/src/tbb/examples/parallel_for/seismic/xcode/seismic.xcodeproj/project.pbxproj @@ -0,0 +1,345 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 84B8DA19152C9AC600D59B95 /* libtbb.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 84B8DA13152C9AC600D59B95 /* libtbb.dylib */; }; + 84B8DA77152CA90100D59B95 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA6F152CA90100D59B95 /* main.m */; }; + 84B8DA78152CA90100D59B95 /* OpenGLView.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA71152CA90100D59B95 /* OpenGLView.m */; }; + 84B8DA79152CA90100D59B95 /* tbbAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA73152CA90100D59B95 /* tbbAppDelegate.m */; }; + 84B8DA7A152CA90100D59B95 /* (null) in Resources */ = {isa = PBXBuildFile; }; + 84B8DA80152CA97B00D59B95 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 84B8DA7C152CA97B00D59B95 /* InfoPlist.strings */; }; + 84B8DA81152CA97B00D59B95 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 84B8DA7E152CA97B00D59B95 /* MainMenu.xib */; }; + 84B8DA87152CA99C00D59B95 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA82152CA99C00D59B95 /* main.cpp */; }; + 84B8DA88152CA99C00D59B95 /* seismic_video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA83152CA99C00D59B95 /* seismic_video.cpp */; }; + 84B8DA89152CA99C00D59B95 /* universe.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA85152CA99C00D59B95 /* universe.cpp */; }; + 84B8DA9A152CADF400D59B95 /* macvideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA99152CADF400D59B95 /* macvideo.cpp */; }; + 84D017561527431F0008A4E0 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84D017551527431F0008A4E0 /* Cocoa.framework */; }; + 84D01776152744BD0008A4E0 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84D01775152744BD0008A4E0 /* OpenGL.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 84B8DA13152C9AC600D59B95 /* libtbb.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtbb.dylib; path = ../../../../lib/libtbb.dylib; sourceTree = ""; }; + 84B8DA6F152CA90100D59B95 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = ../../../common/gui/xcode/tbbExample/main.m; sourceTree = ""; }; + 84B8DA70152CA90100D59B95 /* OpenGLView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenGLView.h; path = ../../../common/gui/xcode/tbbExample/OpenGLView.h; sourceTree = ""; }; + 84B8DA71152CA90100D59B95 /* OpenGLView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OpenGLView.m; path = ../../../common/gui/xcode/tbbExample/OpenGLView.m; sourceTree = ""; }; + 84B8DA72152CA90100D59B95 /* tbbAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tbbAppDelegate.h; path = ../../../common/gui/xcode/tbbExample/tbbAppDelegate.h; sourceTree = ""; }; + 84B8DA73152CA90100D59B95 /* tbbAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = tbbAppDelegate.m; path = ../../../common/gui/xcode/tbbExample/tbbAppDelegate.m; sourceTree = ""; }; + 84B8DA75152CA90100D59B95 /* tbbExample-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "tbbExample-Prefix.pch"; path = "../../../common/gui/xcode/tbbExample/tbbExample-Prefix.pch"; sourceTree = ""; }; + 84B8DA7D152CA97B00D59B95 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = InfoPlist.strings; sourceTree = ""; }; + 84B8DA7F152CA97B00D59B95 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = MainMenu.xib; sourceTree = ""; }; + 84B8DA82152CA99C00D59B95 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = ../main.cpp; sourceTree = ""; }; + 84B8DA83152CA99C00D59B95 /* seismic_video.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = seismic_video.cpp; path = ../seismic_video.cpp; sourceTree = ""; }; + 84B8DA84152CA99C00D59B95 /* seismic_video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = seismic_video.h; path = ../seismic_video.h; sourceTree = ""; }; + 84B8DA85152CA99C00D59B95 /* universe.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = universe.cpp; path = ../universe.cpp; sourceTree = ""; }; + 84B8DA86152CA99C00D59B95 /* universe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = universe.h; path = ../universe.h; sourceTree = ""; }; + 84B8DA99152CADF400D59B95 /* macvideo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = macvideo.cpp; path = ../../../common/gui/macvideo.cpp; sourceTree = ""; }; + 84D017511527431F0008A4E0 /* tbbExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = tbbExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 84D017551527431F0008A4E0 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + 84D017581527431F0008A4E0 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + 84D017591527431F0008A4E0 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; + 84D0175A1527431F0008A4E0 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 84D01775152744BD0008A4E0 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 84D0174E1527431F0008A4E0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 84D01776152744BD0008A4E0 /* OpenGL.framework in Frameworks */, + 84D017561527431F0008A4E0 /* Cocoa.framework in Frameworks */, + 84B8DA19152C9AC600D59B95 /* libtbb.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 84B8DA6C152CA8D900D59B95 /* tbbExample */ = { + isa = PBXGroup; + children = ( + 84B8DA98152CAD8600D59B95 /* Gui layer */, + 84B8DA7B152CA97B00D59B95 /* Resources */, + 84B8DA82152CA99C00D59B95 /* main.cpp */, + 84B8DA83152CA99C00D59B95 /* seismic_video.cpp */, + 84B8DA84152CA99C00D59B95 /* seismic_video.h */, + 84B8DA85152CA99C00D59B95 /* universe.cpp */, + 84B8DA86152CA99C00D59B95 /* universe.h */, + ); + name = tbbExample; + sourceTree = ""; + }; + 84B8DA7B152CA97B00D59B95 /* Resources */ = { + isa = PBXGroup; + children = ( + 84B8DA7C152CA97B00D59B95 /* InfoPlist.strings */, + 84B8DA7E152CA97B00D59B95 /* MainMenu.xib */, + ); + name = Resources; + path = ../../../common/gui/xcode/tbbExample/en.lproj; + sourceTree = ""; + }; + 84B8DA98152CAD8600D59B95 /* Gui layer */ = { + isa = PBXGroup; + children = ( + 84B8DA99152CADF400D59B95 /* macvideo.cpp */, + 84B8DA6F152CA90100D59B95 /* main.m */, + 84B8DA70152CA90100D59B95 /* OpenGLView.h */, + 84B8DA71152CA90100D59B95 /* OpenGLView.m */, + 84B8DA72152CA90100D59B95 /* tbbAppDelegate.h */, + 84B8DA73152CA90100D59B95 /* tbbAppDelegate.m */, + 84B8DA75152CA90100D59B95 /* tbbExample-Prefix.pch */, + ); + name = "Gui layer"; + sourceTree = ""; + }; + 84D017461527431F0008A4E0 = { + isa = PBXGroup; + children = ( + 84B8DA6C152CA8D900D59B95 /* tbbExample */, + 84D017541527431F0008A4E0 /* Frameworks */, + 84D017521527431F0008A4E0 /* Products */, + ); + sourceTree = ""; + }; + 84D017521527431F0008A4E0 /* Products */ = { + isa = PBXGroup; + children = ( + 84D017511527431F0008A4E0 /* tbbExample.app */, + ); + name = Products; + sourceTree = ""; + }; + 84D017541527431F0008A4E0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 84D01775152744BD0008A4E0 /* OpenGL.framework */, + 84D017551527431F0008A4E0 /* Cocoa.framework */, + 84D017571527431F0008A4E0 /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; + 84D017571527431F0008A4E0 /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 84B8DA13152C9AC600D59B95 /* libtbb.dylib */, + 84D017581527431F0008A4E0 /* AppKit.framework */, + 84D017591527431F0008A4E0 /* CoreData.framework */, + 84D0175A1527431F0008A4E0 /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 84D017501527431F0008A4E0 /* tbbExample */ = { + isa = PBXNativeTarget; + buildConfigurationList = 84D01772152743200008A4E0 /* Build configuration list for PBXNativeTarget "tbbExample" */; + buildPhases = ( + 84D0174D1527431F0008A4E0 /* Sources */, + 84D0174E1527431F0008A4E0 /* Frameworks */, + 84D0174F1527431F0008A4E0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = tbbExample; + productName = tbbExample; + productReference = 84D017511527431F0008A4E0 /* tbbExample.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 84D017481527431F0008A4E0 /* Project object */ = { + isa = PBXProject; + attributes = { + CLASSPREFIX = tbb; + LastUpgradeCheck = 0430; + }; + buildConfigurationList = 84D0174B1527431F0008A4E0 /* Build configuration list for PBXProject "tbbExample" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 84D017461527431F0008A4E0; + productRefGroup = 84D017521527431F0008A4E0 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 84D017501527431F0008A4E0 /* tbbExample */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 84D0174F1527431F0008A4E0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 84B8DA7A152CA90100D59B95 /* (null) in Resources */, + 84B8DA80152CA97B00D59B95 /* InfoPlist.strings in Resources */, + 84B8DA81152CA97B00D59B95 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 84D0174D1527431F0008A4E0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 84B8DA77152CA90100D59B95 /* main.m in Sources */, + 84B8DA78152CA90100D59B95 /* OpenGLView.m in Sources */, + 84B8DA79152CA90100D59B95 /* tbbAppDelegate.m in Sources */, + 84B8DA87152CA99C00D59B95 /* main.cpp in Sources */, + 84B8DA88152CA99C00D59B95 /* seismic_video.cpp in Sources */, + 84B8DA89152CA99C00D59B95 /* universe.cpp in Sources */, + 84B8DA9A152CADF400D59B95 /* macvideo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 84B8DA7C152CA97B00D59B95 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 84B8DA7D152CA97B00D59B95 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 84B8DA7E152CA97B00D59B95 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 84B8DA7F152CA97B00D59B95 /* en */, + ); + name = MainMenu.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 84D01770152743200008A4E0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 84D01771152743200008A4E0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + SDKROOT = macosx; + }; + name = Release; + }; + 84D01773152743200008A4E0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "../../../common/gui/xcode/tbbExample/tbbExample-Prefix.pch"; + HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../include\""; + INFOPLIST_FILE = "../../../common/gui/xcode/tbbExample/tbbExample-Info.plist"; + LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/../../../../lib\""; + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_NAME = "$(TARGET_NAME)"; + RUN_CLANG_STATIC_ANALYZER = YES; + USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../include\""; + VERSION_INFO_BUILDER = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 84D01774152743200008A4E0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "../../../common/gui/xcode/tbbExample/tbbExample-Prefix.pch"; + HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../include\""; + INFOPLIST_FILE = "../../../common/gui/xcode/tbbExample/tbbExample-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "\"$(SRCROOT)/../../../../lib\"", + "\"$(SRCROOT)\"", + ); + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_NAME = "$(TARGET_NAME)"; + RUN_CLANG_STATIC_ANALYZER = YES; + USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../include\""; + VERSION_INFO_BUILDER = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 84D0174B1527431F0008A4E0 /* Build configuration list for PBXProject "tbbExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 84D01770152743200008A4E0 /* Debug */, + 84D01771152743200008A4E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 84D01772152743200008A4E0 /* Build configuration list for PBXNativeTarget "tbbExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 84D01773152743200008A4E0 /* Debug */, + 84D01774152743200008A4E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 84D017481527431F0008A4E0 /* Project object */; +} diff --git a/src/tbb/examples/parallel_for/seismic/xcode/seismic.xcodeproj/xcshareddata/xcschemes/tbbExample.xcscheme b/src/tbb/examples/parallel_for/seismic/xcode/seismic.xcodeproj/xcshareddata/xcschemes/tbbExample.xcscheme new file mode 100644 index 0000000..1dd33ab --- /dev/null +++ b/src/tbb/examples/parallel_for/seismic/xcode/seismic.xcodeproj/xcshareddata/xcschemes/tbbExample.xcscheme @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/parallel_for/tachyon/Makefile b/src/tbb/examples/parallel_for/tachyon/Makefile new file mode 100644 index 0000000..88d7458 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/Makefile @@ -0,0 +1,190 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# The original source for this example is +# Copyright (c) 1994-2008 John E. Stone +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +# GNU Makefile that builds and runs example. +NAME:=tachyon + +# The C++ compiler +ifneq (,$(shell which icc 2>/dev/null)) +CXX=icc +endif # icc + +# The default runtime arguments +export ARGS = dat/balls.dat +export PERF_RUN_ARGS = silent dat/balls3.dat +export LIGHT_ARGS= dat/model2.dat + +# define name suffix +SUFFIX = .$(VERSION) + +LIBS ?= -lm + +include ../../common/gui/Makefile.gmake + +ifeq ($(UI),x) +UI_CXXFLAGS += -DX_FULLSYNC +ifneq (,$(findstring -lXext,$(LIBS))) +UI_CXXFLAGS += -DX_NOSHMPIX +endif +endif # X + +MYCXXFLAGS = $(CXXFLAGS) $(UI_CXXFLAGS) + +all: build run +release: build +debug: build_debug +test: run + +build: build_serial build_tbb1d build_tbb +build_debug: build_serial_debug build_tbb1d_debug build_tbb_debug +run: run_serial run_tbb1d run_tbb + +serial: build_serial run_serial +serial_debug: build_serial_debug run_serial +tbb: build_tbb run_tbb +tbb_debug: build_tbb_debug run_tbb +tbb1d: build_tbb1d run_tbb1d +tbb1d_debug: build_tbb1d_debug run_tbb1d + +build_serial: + $(MAKE) VERSION=serial build_one +build_serial_debug: + $(MAKE) VERSION=serial ADD_DEBUG=1 build_one +run_serial: + $(MAKE) VERSION=serial run_one + +build_tbb: + $(MAKE) VERSION=tbb ADD_TBB=1 build_one +build_tbb_debug: + $(MAKE) VERSION=tbb ADD_TBB=1 ADD_DEBUG=1 build_one +run_tbb: + $(MAKE) VERSION=tbb run_one + +build_tbb1d: + $(MAKE) VERSION=tbb1d ADD_TBB=1 build_one +build_tbb1d_debug: + $(MAKE) VERSION=tbb1d ADD_TBB=1 ADD_DEBUG=1 build_one +run_tbb1d: + $(MAKE) VERSION=tbb1d run_one + + +perf_build: + $(MAKE) UI=con VERSION=tbb ADD_TBB=1 build_one +perf_run: + $(MAKE) UI=con VERSION=tbb run_perf_one + +light_test: + $(MAKE) UI=con VERSION=tbb light_test_one + + +# +# Per-build Makefile rules (for recursive $(MAKE) calls from above) +# + +SVERSION = $(VERSION) + +ifeq ($(ADD_DEBUG),1) +MYCXXFLAGS += -O0 -g -D_DEBUG +else +MYCXXFLAGS += -O2 -DNDEBUG +endif + + +ifeq ($(ADD_TBB),1) +MYCXXFLAGS += +ifeq ($(ADD_DEBUG),1) +MYCXXFLAGS += -DTBB_USE_DEBUG +LIBS += -ltbb_debug +else +LIBS += -ltbb +endif +endif + +ifeq ($(shell uname), Linux) +LIBS += -lrt +endif + +SOURCE = ../../common/gui/$(UI)video.cpp src/trace.$(SVERSION).cpp src/main.cpp src/pthread.cpp src/tachyon_video.cpp src/api.cpp src/apigeom.cpp src/apitrigeom.cpp src/bndbox.cpp src/box.cpp src/camera.cpp src/coordsys.cpp src/cylinder.cpp src/extvol.cpp src/global.cpp src/grid.cpp src/imageio.cpp src/imap.cpp src/intersect.cpp src/jpeg.cpp src/light.cpp src/objbound.cpp src/parse.cpp src/plane.cpp src/ppm.cpp src/quadric.cpp src/render.cpp src/ring.cpp src/shade.cpp src/sphere.cpp src/texture.cpp src/tgafile.cpp src/trace_rest.cpp src/triangle.cpp src/ui.cpp src/util.cpp src/vector.cpp src/vol.cpp + +build_one: $(EXE) + +run_one: +ifeq ($(UI),mac) + export DYLD_LIBRARY_PATH="$(DYLD_LIBRARY_PATH):$(TBBLIBSPATH)"; ./$(EXE) $(ARGS) +else + ./$(EXE) $(ARGS) +endif + +run_perf_one: + ./$(EXE) $(PERF_RUN_ARGS) + +light_test_one: + ./$(EXE) $(LIGHT_ARGS) + +$(EXE): $(SOURCE) +ifeq ($(UI),mac) + mkdir -p $(APPRES)/en.lproj $(NAME)$(SUFFIX).app/Contents/MacOS + cp ../../common/gui/xcode/tbbExample/Info.plist $(NAME)$(SUFFIX).app/Contents + cp ../../common/gui/xcode/tbbExample/PkgInfo $(NAME)$(SUFFIX).app/Contents + cp ../../common/gui/xcode/tbbExample/en.lproj/* $(APPRES)/en.lproj + $(CXX_UI) $(MYCXXFLAGS) $(CXXFLAGS) -c $(MACUISOURCES) +endif # Mac + $(CXX) $(MYCXXFLAGS) -o $@ $(SOURCE) $(MACUIOBJS) $(LIBS) + $(RM) *.o + +clean: VERSION = * +clean: +ifeq ($(UI),mac) + rm -rf $(NAME).* +endif + $(RM) $(EXE) *.o *.d diff --git a/src/tbb/examples/parallel_for/tachyon/Makefile.windows b/src/tbb/examples/parallel_for/tachyon/Makefile.windows new file mode 100644 index 0000000..4449216 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/Makefile.windows @@ -0,0 +1,139 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# The original source for this example is +# Copyright (c) 1994-2008 John E. Stone +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +# Common Makefile that builds and runs example. + +# Trying to find if icl.exe is set +CXX1 = $(TBB_CXX)- +CXX2 = $(CXX1:icl.exe-=icl.exe) +CXX = $(CXX2:-=cl.exe) + +# Uncomment one of next lines to choose user interface type (console, gdiplus, direct draw) +#UI = con +UI = gdi +#UI = dd + +# Machine architecture, auto-detected from TBB_TARGET_ARCH by default +# Use XARCH variable to change it. See index.html for more information +ARCH0 = $(TBB_TARGET_ARCH)- +ARCH1 = $(ARCH0:ia32-=x86) +ARCH2 = $(ARCH1:intel64-=AMD64) +XARCH = $(ARCH2:-=x86) + +# The default runtime arguments +ARGS = dat\balls.dat +PERF_RUN_ARGS = silent dat\balls3.dat +LIGHT_ARGS=dat\model2.dat + +# Add these for tbb/tbb1d release builds +# /GL is a workaround to prevent run-time crash when built by VS2010 +CXXFLAGS_TBB_NDEBUG = $(CXXFLAGS) /GL +LIBS_TBB_NDEBUG = tbb.lib $(LIBS) + +# Add these for tbb/tbb1d debug builds +CXXFLAGS_TBB_DEBUG = $(CXXFLAGS) /D TBB_USE_DEBUG +LIBS_TBB_DEBUG = tbb_debug.lib $(LIBS) + + +MAKEINC = ../../common/gui/Makefile.win +SOURCE = src/main.cpp src/pthread.cpp src/tachyon_video.cpp src/api.cpp src/apigeom.cpp src/apitrigeom.cpp src/bndbox.cpp src/box.cpp src/camera.cpp src/coordsys.cpp src/cylinder.cpp src/extvol.cpp src/global.cpp src/grid.cpp src/imageio.cpp src/imap.cpp src/intersect.cpp src/jpeg.cpp src/light.cpp src/objbound.cpp src/parse.cpp src/plane.cpp src/ppm.cpp src/quadric.cpp src/render.cpp src/ring.cpp src/shade.cpp src/sphere.cpp src/texture.cpp src/tgafile.cpp src/trace_rest.cpp src/triangle.cpp src/ui.cpp src/util.cpp src/vector.cpp src/vol.cpp + +# Targets +all: build run +release: build +debug: build_debug +test: run + +build: build_serial build_tbb1d build_tbb +build_debug: build_serial_debug build_tbb1d_debug build_tbb_debug +run: run_serial run_tbb1d run_tbb + +serial: build_serial run_serial +serial_debug: build_serial_debug run_serial +tbb: build_tbb run_tbb +tbb_debug: build_tbb_debug run_tbb +tbb1d: build_tbb1d run_tbb1d +tbb1d_debug: build_tbb1d_debug run_tbb1d + +build_serial: + @$(MAKE) -f $(MAKEINC) SOURCE="src/trace.serial.cpp $(SOURCE)" EXE=tachyon.serial.exe RCNAME=gui UI=$(UI) CXX="$(CXX)" CXXFLAGS=$(CXXFLAGS) XARCH=$(XARCH) build_one +build_serial_debug: + @$(MAKE) -f $(MAKEINC) SOURCE="src/trace.serial.cpp $(SOURCE)" EXE=tachyon.serial.exe RCNAME=gui UI=$(UI) DEBUG=_debug CXX="$(CXX)" CXXFLAGS=$(CXXFLAGS) XARCH=$(XARCH) build_one +run_serial: + -.\tachyon.serial.exe $(ARGS) + +build_tbb: + @$(MAKE) -f $(MAKEINC) SOURCE="src/trace.tbb.cpp $(SOURCE)" EXE=tachyon.tbb.exe RCNAME=gui UI=$(UI) CXX="$(CXX)" CXXFLAGS="$(CXXFLAGS_TBB_NDEBUG)" LFLAGS="$(LIBS_TBB_NDEBUG)" XARCH=$(XARCH) build_one +build_tbb_debug: + @$(MAKE) -f $(MAKEINC) SOURCE="src/trace.tbb.cpp $(SOURCE)" EXE=tachyon.tbb.exe RCNAME=gui UI=$(UI) DEBUG=_debug CXX="$(CXX)" CXXFLAGS="$(CXXFLAGS_TBB_DEBUG)" LFLAGS="$(LIBS_TBB_DEBUG)" XARCH=$(XARCH) build_one +run_tbb: + -.\tachyon.tbb.exe $(ARGS) + +build_tbb1d: + @$(MAKE) -f $(MAKEINC) SOURCE="src/trace.tbb1d.cpp $(SOURCE)" EXE=tachyon.tbb1d.exe RCNAME=gui UI=$(UI) CXX="$(CXX)" CXXFLAGS="$(CXXFLAGS_TBB_NDEBUG)" LFLAGS="$(LIBS_TBB_NDEBUG)" XARCH=$(XARCH) build_one +build_tbb1d_debug: + @$(MAKE) -f $(MAKEINC) SOURCE="src/trace.tbb1d.cpp $(SOURCE)" EXE=tachyon.tbb1d.exe RCNAME=gui UI=$(UI) DEBUG=_debug CXX="$(CXX)" CXXFLAGS="$(CXXFLAGS_TBB_DEBUG)" LFLAGS="$(LIBS_TBB_DEBUG)" XARCH=$(XARCH) build_one +run_tbb1d: + -.\tachyon.tbb1d.exe $(ARGS) + + +clean: + @cmd.exe /C del tachyon.* *.manifest *.obj msvs\gui.res *.?db + +perf_build: + @$(MAKE) -f $(MAKEINC) SOURCE="src/trace.tbb.cpp $(SOURCE)" EXE=tachyon.tbb.exe RCNAME=gui UI=con CXX="$(CXX)" CXXFLAGS="$(CXXFLAGS_TBB_NDEBUG)" LFLAGS="$(LIBS_TBB_NDEBUG)" XARCH=$(XARCH) build_one +perf_run: + -.\tachyon.tbb.exe $(PERF_RUN_ARGS) + +light_test: + -.\tachyon.tbb.exe $(LIGHT_ARGS) diff --git a/src/tbb/examples/parallel_for/tachyon/dat/820spheres.dat b/src/tbb/examples/parallel_for/tachyon/dat/820spheres.dat new file mode 100644 index 0000000..5d5a430 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/dat/820spheres.dat @@ -0,0 +1,1671 @@ +BEGIN_SCENE + OUTFILE /dev/null + RESOLUTION 512 512 + VERBOSE 0 + +CAMERA + ZOOM 1.0 + ASPECTRATIO 1.0 + ANTIALIASING 0 + RAYDEPTH 12 + CENTER 0.0 0.0 2.0 + VIEWDIR 0 0 -1 + UPDIR 0 1 0 + +END_CAMERA + +LIGHT CENTER 4 3 2 RAD 0.2 COLOR 0.5 0.5 0.5 + +LIGHT CENTER 1 -4 4 RAD 0.2 COLOR 0.5 0.5 0.5 + +LIGHT CENTER -3 1 5 RAD 0.2 COLOR 0.5 0.5 0.5 + +TEXDEF txt001 AMBIENT 0.2 DIFFUSE 0.8 SPECULAR 0 OPACITY 1 + COLOR 1 0.75 0.33 + TEXFUNC 0 + +TEXDEF txt002 AMBIENT 0.1 DIFFUSE 0.9 SPECULAR 0.0 OPACITY 1.0 + COLOR 1.0 1.0 1.0 TEXFUNC 0 + + SPHERE CENTER 0 0 0 RAD 0.5 + txt002 + SPHERE CENTER 0.272166 0.272166 0.544331 RAD 0.166667 + txt002 + SPHERE CENTER 0.420314 0.420314 0.618405 RAD 0.0555556 + txt002 + SPHERE CENTER 0.470715 0.470715 0.598245 RAD 0.0185185 + txt002 + SPHERE CENTER 0.461623 0.409245 0.557924 RAD 0.0185185 + txt002 + SPHERE CENTER 0.409245 0.461623 0.557924 RAD 0.0185185 + txt002 + SPHERE CENTER 0.429405 0.481784 0.658726 RAD 0.0185185 + txt002 + SPHERE CENTER 0.367935 0.472692 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.379004 0.431383 0.678886 RAD 0.0185185 + txt002 + SPHERE CENTER 0.481784 0.429405 0.658726 RAD 0.0185185 + txt002 + SPHERE CENTER 0.431383 0.379004 0.678886 RAD 0.0185185 + txt002 + SPHERE CENTER 0.472692 0.367935 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.461844 0.304709 0.43322 RAD 0.0555556 + txt002 + SPHERE CENTER 0.492085 0.33495 0.372739 RAD 0.0185185 + txt002 + SPHERE CENTER 0.424345 0.305171 0.369341 RAD 0.0185185 + txt002 + SPHERE CENTER 0.435193 0.368397 0.406378 RAD 0.0185185 + txt002 + SPHERE CENTER 0.529584 0.334488 0.436618 RAD 0.0185185 + txt002 + SPHERE CENTER 0.472692 0.367935 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER 0.499343 0.304247 0.497099 RAD 0.0185185 + txt002 + SPHERE CENTER 0.518736 0.271262 0.399581 RAD 0.0185185 + txt002 + SPHERE CENTER 0.488495 0.241021 0.460062 RAD 0.0185185 + txt002 + SPHERE CENTER 0.450996 0.241483 0.396183 RAD 0.0185185 + txt002 + SPHERE CENTER 0.304709 0.461844 0.43322 RAD 0.0555556 + txt002 + SPHERE CENTER 0.33495 0.492085 0.372739 RAD 0.0185185 + txt002 + SPHERE CENTER 0.368397 0.435193 0.406378 RAD 0.0185185 + txt002 + SPHERE CENTER 0.305171 0.424345 0.369341 RAD 0.0185185 + txt002 + SPHERE CENTER 0.271262 0.518736 0.399581 RAD 0.0185185 + txt002 + SPHERE CENTER 0.241483 0.450996 0.396183 RAD 0.0185185 + txt002 + SPHERE CENTER 0.241021 0.488495 0.460062 RAD 0.0185185 + txt002 + SPHERE CENTER 0.334488 0.529584 0.436618 RAD 0.0185185 + txt002 + SPHERE CENTER 0.304247 0.499343 0.497099 RAD 0.0185185 + txt002 + SPHERE CENTER 0.367935 0.472692 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER 0.230635 0.38777 0.729516 RAD 0.0555556 + txt002 + SPHERE CENTER 0.2506 0.446614 0.769837 RAD 0.0185185 + txt002 + SPHERE CENTER 0.301839 0.407906 0.732914 RAD 0.0185185 + txt002 + SPHERE CENTER 0.253236 0.449775 0.695877 RAD 0.0185185 + txt002 + SPHERE CENTER 0.179397 0.426478 0.766439 RAD 0.0185185 + txt002 + SPHERE CENTER 0.182032 0.429639 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER 0.159431 0.367634 0.726118 RAD 0.0185185 + txt002 + SPHERE CENTER 0.227999 0.384609 0.803476 RAD 0.0185185 + txt002 + SPHERE CENTER 0.208034 0.325765 0.763155 RAD 0.0185185 + txt002 + SPHERE CENTER 0.279238 0.345901 0.766553 RAD 0.0185185 + txt002 + SPHERE CENTER 0.115031 0.4293 0.544331 RAD 0.0555556 + txt002 + SPHERE CENTER 0.102505 0.502308 0.544331 RAD 0.0185185 + txt002 + SPHERE CENTER 0.160392 0.474661 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.160392 0.474661 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0571437 0.456947 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.115031 0.4293 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0696698 0.383939 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0571437 0.456947 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0696698 0.383939 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.115031 0.4293 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.082487 0.239622 0.655442 RAD 0.0555556 + txt002 + SPHERE CENTER 0.0438957 0.258053 0.715923 RAD 0.0185185 + txt002 + SPHERE CENTER 0.117687 0.252557 0.719322 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0863845 0.308551 0.682285 RAD 0.0185185 + txt002 + SPHERE CENTER 0.00869528 0.245118 0.652044 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0511841 0.295616 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0472866 0.226687 0.591563 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0399982 0.189123 0.689081 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0785895 0.170692 0.6286 RAD 0.0185185 + txt002 + SPHERE CENTER 0.11379 0.183628 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER 0.38777 0.230635 0.729516 RAD 0.0555556 + txt002 + SPHERE CENTER 0.446614 0.2506 0.769837 RAD 0.0185185 + txt002 + SPHERE CENTER 0.449775 0.253236 0.695877 RAD 0.0185185 + txt002 + SPHERE CENTER 0.407906 0.301839 0.732914 RAD 0.0185185 + txt002 + SPHERE CENTER 0.384609 0.227999 0.803476 RAD 0.0185185 + txt002 + SPHERE CENTER 0.345901 0.279238 0.766553 RAD 0.0185185 + txt002 + SPHERE CENTER 0.325765 0.208034 0.763155 RAD 0.0185185 + txt002 + SPHERE CENTER 0.426478 0.179397 0.766439 RAD 0.0185185 + txt002 + SPHERE CENTER 0.367634 0.159431 0.726118 RAD 0.0185185 + txt002 + SPHERE CENTER 0.429639 0.182032 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER 0.239622 0.082487 0.655442 RAD 0.0555556 + txt002 + SPHERE CENTER 0.258053 0.0438957 0.715923 RAD 0.0185185 + txt002 + SPHERE CENTER 0.308551 0.0863845 0.682285 RAD 0.0185185 + txt002 + SPHERE CENTER 0.252557 0.117687 0.719322 RAD 0.0185185 + txt002 + SPHERE CENTER 0.189123 0.0399982 0.689081 RAD 0.0185185 + txt002 + SPHERE CENTER 0.183628 0.11379 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER 0.170692 0.0785895 0.6286 RAD 0.0185185 + txt002 + SPHERE CENTER 0.245118 0.00869528 0.652044 RAD 0.0185185 + txt002 + SPHERE CENTER 0.226687 0.0472866 0.591563 RAD 0.0185185 + txt002 + SPHERE CENTER 0.295616 0.0511841 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.4293 0.115031 0.544331 RAD 0.0555556 + txt002 + SPHERE CENTER 0.502308 0.102505 0.544331 RAD 0.0185185 + txt002 + SPHERE CENTER 0.474661 0.160392 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.474661 0.160392 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.456947 0.0571437 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.4293 0.115031 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.383939 0.0696698 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.456947 0.0571437 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.383939 0.0696698 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.4293 0.115031 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER 0.643951 0.172546 1.11022e-16 RAD 0.166667 + txt002 + SPHERE CENTER 0.802608 0.281471 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.824035 0.30566 -0.177765 RAD 0.0185185 + txt002 + SPHERE CENTER 0.787796 0.241352 -0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER 0.752156 0.305221 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.838847 0.34578 -0.117284 RAD 0.0185185 + txt002 + SPHERE CENTER 0.766968 0.345341 -0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.817421 0.321591 -0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER 0.874487 0.28191 -0.129006 RAD 0.0185185 + txt002 + SPHERE CENTER 0.853061 0.257721 -0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER 0.838248 0.217602 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.643951 0.172546 -0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER 0.61371 0.202787 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.5724 0.191718 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.624779 0.244096 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.68526 0.183615 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.696329 0.224924 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.715501 0.153374 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.632882 0.131237 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.663122 0.100996 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.591572 0.120168 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.594141 0.358439 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.619127 0.408291 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.665691 0.37761 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.638217 0.337042 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.547576 0.389119 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.566667 0.317871 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.522591 0.339267 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.57505 0.429687 -0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER 0.550064 0.379835 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.621614 0.399007 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.802608 0.281471 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.858698 0.329459 0.104938 RAD 0.0185185 + txt002 + SPHERE CENTER 0.845371 0.280879 0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER 0.798572 0.337088 0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER 0.815936 0.330051 0.165419 RAD 0.0185185 + txt002 + SPHERE CENTER 0.75581 0.33768 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.759846 0.282063 0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER 0.862735 0.273842 0.153697 RAD 0.0185185 + txt002 + SPHERE CENTER 0.806645 0.225855 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.849407 0.225263 0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.594141 0.358439 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.613592 0.428945 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.665691 0.37761 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.621614 0.399007 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.542042 0.409774 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.550064 0.379835 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.522591 0.339267 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.586119 0.388377 0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.566667 0.317871 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.638217 0.337042 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.643951 0.172546 0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER 0.674191 0.202787 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.715501 0.191718 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.663122 0.244096 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.602641 0.183615 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.591572 0.224924 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.5724 0.153374 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.655019 0.131237 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.624779 0.100996 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.696329 0.120168 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.852418 0.0955788 2.30268e-16 RAD 0.0555556 + txt002 + SPHERE CENTER 0.922609 0.11107 -0.0178949 RAD 0.0185185 + txt002 + SPHERE CENTER 0.867231 0.135698 -0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER 0.877966 0.164775 0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER 0.907797 0.0709499 0.0425863 RAD 0.0185185 + txt002 + SPHERE CENTER 0.863153 0.124655 0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER 0.837606 0.0554592 0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER 0.897062 0.0418734 -0.0246914 RAD 0.0185185 + txt002 + SPHERE CENTER 0.826871 0.0263827 -0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER 0.841683 0.0665023 -0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER 0.69376 -0.0133465 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.740325 -0.0440268 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.76531 0.0058253 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.721234 0.0272215 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.668775 -0.0631985 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.649684 0.00804971 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.62221 -0.0325183 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.712851 -0.0845947 0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER 0.666287 -0.0539145 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.737837 -0.0347427 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.69376 -0.0133465 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.745859 -0.0646815 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.76531 0.0058253 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.737837 -0.0347427 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.674309 -0.0838533 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.666287 -0.0539145 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.62221 -0.0325183 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.701782 -0.0432853 -0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.649684 0.00804971 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.721234 0.0272215 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.172546 0.643951 1.11022e-16 RAD 0.166667 + txt002 + SPHERE CENTER 0.281471 0.802608 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.30566 0.824035 -0.177765 RAD 0.0185185 + txt002 + SPHERE CENTER 0.305221 0.752156 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.241352 0.787796 -0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER 0.28191 0.874487 -0.129006 RAD 0.0185185 + txt002 + SPHERE CENTER 0.217602 0.838248 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.257721 0.853061 -0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER 0.34578 0.838847 -0.117284 RAD 0.0185185 + txt002 + SPHERE CENTER 0.321591 0.817421 -0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER 0.345341 0.766968 -0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.358439 0.594141 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.408291 0.619127 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.337042 0.638217 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.37761 0.665691 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.429687 0.57505 -0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER 0.399007 0.621614 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.379835 0.550064 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.389119 0.547576 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.339267 0.522591 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.317871 0.566667 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.172546 0.643951 -0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER 0.142305 0.674191 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.100996 0.663122 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.153374 0.715501 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.213855 0.655019 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.224924 0.696329 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.244096 0.624779 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.161477 0.602641 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.191718 0.5724 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.120168 0.591572 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0955788 0.852418 1.31582e-16 RAD 0.0555556 + txt002 + SPHERE CENTER 0.11107 0.922609 -0.0178949 RAD 0.0185185 + txt002 + SPHERE CENTER 0.164775 0.877966 0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER 0.135698 0.867231 -0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0418734 0.897062 -0.0246914 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0665023 0.841683 -0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0263827 0.826871 -0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0709499 0.907797 0.0425863 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0554592 0.837606 0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER 0.124655 0.863153 0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0133465 0.69376 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.0646815 0.745859 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0347427 0.737837 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0058253 0.76531 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0432853 0.701782 -0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0272215 0.721234 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.00804971 0.649684 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0838533 0.674309 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0325183 0.62221 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0539145 0.666287 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0133465 0.69376 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.0440268 0.740325 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0272215 0.721234 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0058253 0.76531 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0845947 0.712851 0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0347427 0.737837 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0539145 0.666287 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0631985 0.668775 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0325183 0.62221 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.00804971 0.649684 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.281471 0.802608 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.329459 0.858698 0.104938 RAD 0.0185185 + txt002 + SPHERE CENTER 0.337088 0.798572 0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER 0.280879 0.845371 0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER 0.273842 0.862735 0.153697 RAD 0.0185185 + txt002 + SPHERE CENTER 0.225263 0.849407 0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.225855 0.806645 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.330051 0.815936 0.165419 RAD 0.0185185 + txt002 + SPHERE CENTER 0.282063 0.759846 0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER 0.33768 0.75581 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.172546 0.643951 0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER 0.202787 0.674191 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.244096 0.663122 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.191718 0.715501 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.131237 0.655019 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.120168 0.696329 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.100996 0.624779 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.183615 0.602641 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.153374 0.5724 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.224924 0.591572 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.358439 0.594141 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.428945 0.613592 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.399007 0.621614 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.37761 0.665691 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.388377 0.586119 0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.337042 0.638217 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.317871 0.566667 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.409774 0.542042 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.339267 0.522591 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.379835 0.550064 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.371785 0.0996195 0.544331 RAD 0.166667 + txt002 + SPHERE CENTER -0.393621 0.220501 0.729516 RAD 0.0555556 + txt002 + SPHERE CENTER -0.368601 0.279642 0.766439 RAD 0.0185185 + txt002 + SPHERE CENTER -0.321889 0.238665 0.726118 RAD 0.0185185 + txt002 + SPHERE CENTER -0.372464 0.281062 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER -0.440333 0.261479 0.769837 RAD 0.0185185 + txt002 + SPHERE CENTER -0.444196 0.262898 0.695877 RAD 0.0185185 + txt002 + SPHERE CENTER -0.465353 0.202338 0.732914 RAD 0.0185185 + txt002 + SPHERE CENTER -0.389758 0.219082 0.803476 RAD 0.0185185 + txt002 + SPHERE CENTER -0.414778 0.15994 0.766553 RAD 0.0185185 + txt002 + SPHERE CENTER -0.343046 0.178104 0.763155 RAD 0.0185185 + txt002 + SPHERE CENTER -0.191247 0.166275 0.655442 RAD 0.0555556 + txt002 + SPHERE CENTER -0.130089 0.20793 0.652044 RAD 0.0185185 + txt002 + SPHERE CENTER -0.154295 0.172673 0.591563 RAD 0.0185185 + txt002 + SPHERE CENTER -0.192135 0.230419 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.167041 0.201532 0.715923 RAD 0.0185185 + txt002 + SPHERE CENTER -0.229087 0.224021 0.682285 RAD 0.0185185 + txt002 + SPHERE CENTER -0.228199 0.159877 0.719322 RAD 0.0185185 + txt002 + SPHERE CENTER -0.129201 0.143787 0.689081 RAD 0.0185185 + txt002 + SPHERE CENTER -0.190359 0.102131 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER -0.153407 0.108529 0.6286 RAD 0.0185185 + txt002 + SPHERE CENTER -0.31427 0.31427 0.544331 RAD 0.0555556 + txt002 + SPHERE CENTER -0.277961 0.367156 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.252306 0.297666 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.31427 0.31427 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER -0.339925 0.383759 0.544331 RAD 0.0185185 + txt002 + SPHERE CENTER -0.376234 0.330873 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.376234 0.330873 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.277961 0.367156 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.31427 0.31427 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.252306 0.297666 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.574159 0.153845 0.618405 RAD 0.0555556 + txt002 + SPHERE CENTER -0.612768 0.202534 0.658726 RAD 0.0185185 + txt002 + SPHERE CENTER -0.543919 0.184086 0.678886 RAD 0.0185185 + txt002 + SPHERE CENTER -0.554987 0.225396 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.643008 0.172294 0.598245 RAD 0.0185185 + txt002 + SPHERE CENTER -0.585228 0.195155 0.557924 RAD 0.0185185 + txt002 + SPHERE CENTER -0.6044 0.123605 0.557924 RAD 0.0185185 + txt002 + SPHERE CENTER -0.631939 0.130984 0.658726 RAD 0.0185185 + txt002 + SPHERE CENTER -0.593331 0.0822954 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.56309 0.112536 0.678886 RAD 0.0185185 + txt002 + SPHERE CENTER -0.494808 0.247614 0.43322 RAD 0.0555556 + txt002 + SPHERE CENTER -0.494287 0.313607 0.399581 RAD 0.0185185 + txt002 + SPHERE CENTER -0.452978 0.302539 0.460062 RAD 0.0185185 + txt002 + SPHERE CENTER -0.434629 0.269833 0.396183 RAD 0.0185185 + txt002 + SPHERE CENTER -0.536117 0.258683 0.372739 RAD 0.0185185 + txt002 + SPHERE CENTER -0.476459 0.214908 0.369341 RAD 0.0185185 + txt002 + SPHERE CENTER -0.536638 0.19269 0.406378 RAD 0.0185185 + txt002 + SPHERE CENTER -0.554467 0.291389 0.436618 RAD 0.0185185 + txt002 + SPHERE CENTER -0.554987 0.225396 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER -0.513157 0.28032 0.497099 RAD 0.0185185 + txt002 + SPHERE CENTER -0.552323 0.0329639 0.43322 RAD 0.0555556 + txt002 + SPHERE CENTER -0.625877 0.0248832 0.436618 RAD 0.0185185 + txt002 + SPHERE CENTER -0.584567 0.0138144 0.497099 RAD 0.0185185 + txt002 + SPHERE CENTER -0.593331 0.0822954 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER -0.593633 0.0440327 0.372739 RAD 0.0185185 + txt002 + SPHERE CENTER -0.561087 0.101445 0.406378 RAD 0.0185185 + txt002 + SPHERE CENTER -0.520079 0.0521134 0.369341 RAD 0.0185185 + txt002 + SPHERE CENTER -0.584869 -0.0244483 0.399581 RAD 0.0185185 + txt002 + SPHERE CENTER -0.511316 -0.0163676 0.396183 RAD 0.0185185 + txt002 + SPHERE CENTER -0.54356 -0.0355172 0.460062 RAD 0.0185185 + txt002 + SPHERE CENTER -0.451136 0.0058509 0.729516 RAD 0.0555556 + txt002 + SPHERE CENTER -0.447081 0.0051487 0.803476 RAD 0.0185185 + txt002 + SPHERE CENTER -0.386138 0.0172804 0.763155 RAD 0.0185185 + txt002 + SPHERE CENTER -0.439178 0.0688765 0.766553 RAD 0.0185185 + txt002 + SPHERE CENTER -0.512079 -0.00628079 0.769837 RAD 0.0185185 + txt002 + SPHERE CENTER -0.504176 0.0574471 0.732914 RAD 0.0185185 + txt002 + SPHERE CENTER -0.516134 -0.00557859 0.695877 RAD 0.0185185 + txt002 + SPHERE CENTER -0.459039 -0.0578769 0.766439 RAD 0.0185185 + txt002 + SPHERE CENTER -0.463094 -0.0571747 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER -0.398096 -0.0457452 0.726118 RAD 0.0185185 + txt002 + SPHERE CENTER -0.4293 -0.115031 0.544331 RAD 0.0555556 + txt002 + SPHERE CENTER -0.424299 -0.178985 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.367336 -0.131634 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.4293 -0.115031 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.486264 -0.162382 0.544331 RAD 0.0185185 + txt002 + SPHERE CENTER -0.491265 -0.0984274 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.491265 -0.0984274 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.424299 -0.178985 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.4293 -0.115031 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER -0.367336 -0.131634 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.248762 -0.0483751 0.655442 RAD 0.0555556 + txt002 + SPHERE CENTER -0.183785 -0.0599222 0.689081 RAD 0.0185185 + txt002 + SPHERE CENTER -0.187119 -0.0172857 0.6286 RAD 0.0185185 + txt002 + SPHERE CENTER -0.215921 0.00673113 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER -0.245428 -0.0910116 0.715923 RAD 0.0185185 + txt002 + SPHERE CENTER -0.277564 -0.0243582 0.719322 RAD 0.0185185 + txt002 + SPHERE CENTER -0.310405 -0.0794645 0.682285 RAD 0.0185185 + txt002 + SPHERE CENTER -0.216626 -0.115028 0.652044 RAD 0.0185185 + txt002 + SPHERE CENTER -0.281603 -0.103481 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.21996 -0.0723919 0.591563 RAD 0.0185185 + txt002 + SPHERE CENTER -0.471405 0.471405 1.11022e-16 RAD 0.166667 + txt002 + SPHERE CENTER -0.508983 0.690426 1.25414e-16 RAD 0.0555556 + txt002 + SPHERE CENTER -0.484794 0.755941 -0.0246914 RAD 0.0185185 + txt002 + SPHERE CENTER -0.436283 0.7029 -0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER -0.478434 0.695668 -0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER -0.557494 0.743468 -0.0178949 RAD 0.0185185 + txt002 + SPHERE CENTER -0.551134 0.683194 -0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER -0.581682 0.677953 0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER -0.515343 0.7507 0.0425863 RAD 0.0185185 + txt002 + SPHERE CENTER -0.539531 0.685185 0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER -0.466832 0.697658 0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER -0.335322 0.607487 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.283164 0.659645 0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER -0.286452 0.603979 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.33883 0.656357 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.332034 0.663153 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.3877 0.659866 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.384191 0.610996 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.279656 0.610775 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.331813 0.558618 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.282943 0.555109 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.335322 0.607487 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.313405 0.629404 -0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.331813 0.558618 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.384191 0.610996 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.316914 0.678274 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.3877 0.659866 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.33883 0.656357 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.264535 0.625895 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.286452 0.603979 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.282943 0.555109 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.645066 0.554344 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.681385 0.616373 -0.129006 RAD 0.0185185 + txt002 + SPHERE CENTER -0.649723 0.609912 -0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER -0.607573 0.617144 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.676727 0.560805 -0.177765 RAD 0.0185185 + txt002 + SPHERE CENTER -0.602915 0.561576 -0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER -0.640408 0.498776 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.718878 0.553573 -0.117284 RAD 0.0185185 + txt002 + SPHERE CENTER -0.682558 0.491544 -0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.687216 0.547112 -0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER -0.471405 0.471405 -0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER -0.501645 0.501645 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.542955 0.490576 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.490576 0.542955 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.430095 0.482473 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.419026 0.523783 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.399854 0.452233 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.482473 0.430095 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.452233 0.399854 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.523783 0.419026 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.607487 0.335322 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.659645 0.283164 -0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER -0.603979 0.286452 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.656357 0.33883 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.663153 0.332034 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.659866 0.3877 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.610996 0.384191 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.610775 0.279656 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.558618 0.331813 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.555109 0.282943 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.645066 0.554344 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.668521 0.610229 0.153697 RAD 0.0185185 + txt002 + SPHERE CENTER -0.598918 0.585648 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.619787 0.622977 0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.714669 0.578925 0.104938 RAD 0.0185185 + txt002 + SPHERE CENTER -0.665934 0.591673 0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER -0.691213 0.52304 0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER -0.6938 0.541596 0.165419 RAD 0.0185185 + txt002 + SPHERE CENTER -0.670344 0.48571 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.624197 0.517014 0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER -0.607487 0.335322 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.629404 0.313405 0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.558618 0.331813 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.610996 0.384191 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.678274 0.316914 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.659866 0.3877 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.656357 0.33883 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.625895 0.264535 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.603979 0.286452 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.555109 0.282943 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.471405 0.471405 0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER -0.441164 0.501645 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.399854 0.490576 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.452233 0.542955 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.512714 0.482473 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.523783 0.523783 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.542955 0.452233 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.460336 0.430095 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.490576 0.399854 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.419026 0.419026 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.643951 -0.172546 1.11022e-16 RAD 0.166667 + txt002 + SPHERE CENTER -0.835815 -0.157543 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.871646 -0.122136 0.165419 RAD 0.0185185 + txt002 + SPHERE CENTER -0.799077 -0.135649 0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER -0.82339 -0.0854653 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.908384 -0.14403 0.104938 RAD 0.0185185 + txt002 + SPHERE CENTER -0.860128 -0.107359 0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER -0.872552 -0.179437 0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER -0.884071 -0.194213 0.153697 RAD 0.0185185 + txt002 + SPHERE CENTER -0.84824 -0.229621 0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.811502 -0.207727 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.643951 -0.172546 0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER -0.61371 -0.142305 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.5724 -0.153374 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.624779 -0.100996 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.68526 -0.161477 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.696329 -0.120168 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.715501 -0.191718 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.632882 -0.213855 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.663122 -0.244096 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.591572 -0.224924 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.69376 0.0133465 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.674309 0.0838533 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.62221 0.0325183 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.666287 0.0539145 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.745859 0.0646815 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.737837 0.0347427 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.76531 -0.0058253 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.701782 0.0432853 0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.721234 -0.0272215 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.649684 -0.00804971 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.835815 -0.157543 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.899353 -0.119969 -0.117284 RAD 0.0185185 + txt002 + SPHERE CENTER -0.868703 -0.130205 -0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER -0.836885 -0.0844101 -0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.866465 -0.147308 -0.177765 RAD 0.0185185 + txt002 + SPHERE CENTER -0.803997 -0.111748 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.802927 -0.184881 -0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER -0.898283 -0.193102 -0.129006 RAD 0.0185185 + txt002 + SPHERE CENTER -0.834745 -0.230676 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.867633 -0.203337 -0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER -0.69376 0.0133465 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.668775 0.0631985 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.62221 0.0325183 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.649684 -0.00804971 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.740325 0.0440268 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.721234 -0.0272215 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.76531 -0.0058253 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.712851 0.0845947 -0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER -0.737837 0.0347427 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.666287 0.0539145 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.643951 -0.172546 -0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER -0.674191 -0.142305 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.715501 -0.153374 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.663122 -0.100996 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.602641 -0.161477 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.591572 -0.120168 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.5724 -0.191718 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.655019 -0.213855 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.624779 -0.244096 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.696329 -0.224924 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.786005 -0.343435 1.25414e-16 RAD 0.0555556 + txt002 + SPHERE CENTER -0.82165 -0.392454 0.0425863 RAD 0.0185185 + txt002 + SPHERE CENTER -0.753118 -0.370774 0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER -0.80984 -0.323622 0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER -0.854538 -0.365116 -0.0178949 RAD 0.0185185 + txt002 + SPHERE CENTER -0.842728 -0.296284 0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER -0.818893 -0.316097 -0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER -0.797815 -0.412267 -0.0246914 RAD 0.0185185 + txt002 + SPHERE CENTER -0.76217 -0.363249 -0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER -0.729282 -0.390587 -0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER -0.594141 -0.358439 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.542042 -0.409774 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.522591 -0.339267 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.550064 -0.379835 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.613592 -0.428945 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.621614 -0.399007 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.665691 -0.37761 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.586119 -0.388377 -0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.638217 -0.337042 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.566667 -0.317871 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.594141 -0.358439 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.547576 -0.389119 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.522591 -0.339267 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.566667 -0.317871 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.619127 -0.408291 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.638217 -0.337042 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.665691 -0.37761 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.57505 -0.429687 0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER -0.621614 -0.399007 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.550064 -0.379835 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0996195 -0.371785 0.544331 RAD 0.166667 + txt002 + SPHERE CENTER 0.220501 -0.393621 0.729516 RAD 0.0555556 + txt002 + SPHERE CENTER 0.279642 -0.368601 0.766439 RAD 0.0185185 + txt002 + SPHERE CENTER 0.281062 -0.372464 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER 0.238665 -0.321889 0.726118 RAD 0.0185185 + txt002 + SPHERE CENTER 0.219082 -0.389758 0.803476 RAD 0.0185185 + txt002 + SPHERE CENTER 0.178104 -0.343046 0.763155 RAD 0.0185185 + txt002 + SPHERE CENTER 0.15994 -0.414778 0.766553 RAD 0.0185185 + txt002 + SPHERE CENTER 0.261479 -0.440333 0.769837 RAD 0.0185185 + txt002 + SPHERE CENTER 0.202338 -0.465353 0.732914 RAD 0.0185185 + txt002 + SPHERE CENTER 0.262898 -0.444196 0.695877 RAD 0.0185185 + txt002 + SPHERE CENTER 0.31427 -0.31427 0.544331 RAD 0.0555556 + txt002 + SPHERE CENTER 0.367156 -0.277961 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.31427 -0.31427 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER 0.297666 -0.252306 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.367156 -0.277961 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.297666 -0.252306 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.31427 -0.31427 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.383759 -0.339925 0.544331 RAD 0.0185185 + txt002 + SPHERE CENTER 0.330873 -0.376234 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.330873 -0.376234 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.166275 -0.191247 0.655442 RAD 0.0555556 + txt002 + SPHERE CENTER 0.20793 -0.130089 0.652044 RAD 0.0185185 + txt002 + SPHERE CENTER 0.230419 -0.192135 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.172673 -0.154295 0.591563 RAD 0.0185185 + txt002 + SPHERE CENTER 0.143787 -0.129201 0.689081 RAD 0.0185185 + txt002 + SPHERE CENTER 0.108529 -0.153407 0.6286 RAD 0.0185185 + txt002 + SPHERE CENTER 0.102131 -0.190359 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER 0.201532 -0.167041 0.715923 RAD 0.0185185 + txt002 + SPHERE CENTER 0.159877 -0.228199 0.719322 RAD 0.0185185 + txt002 + SPHERE CENTER 0.224021 -0.229087 0.682285 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0058509 -0.451136 0.729516 RAD 0.0555556 + txt002 + SPHERE CENTER 0.0051487 -0.447081 0.803476 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0688765 -0.439178 0.766553 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0172804 -0.386138 0.763155 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0578769 -0.459039 0.766439 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0457452 -0.398096 0.726118 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0571747 -0.463094 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER -0.00628079 -0.512079 0.769837 RAD 0.0185185 + txt002 + SPHERE CENTER -0.00557859 -0.516134 0.695877 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0574471 -0.504176 0.732914 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0483751 -0.248762 0.655442 RAD 0.0555556 + txt002 + SPHERE CENTER -0.0599222 -0.183785 0.689081 RAD 0.0185185 + txt002 + SPHERE CENTER 0.00673113 -0.215921 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0172857 -0.187119 0.6286 RAD 0.0185185 + txt002 + SPHERE CENTER -0.115028 -0.216626 0.652044 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0723919 -0.21996 0.591563 RAD 0.0185185 + txt002 + SPHERE CENTER -0.103481 -0.281603 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0910116 -0.245428 0.715923 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0794645 -0.310405 0.682285 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0243582 -0.277564 0.719322 RAD 0.0185185 + txt002 + SPHERE CENTER -0.115031 -0.4293 0.544331 RAD 0.0555556 + txt002 + SPHERE CENTER -0.178985 -0.424299 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.115031 -0.4293 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.131634 -0.367336 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.178985 -0.424299 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.131634 -0.367336 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.115031 -0.4293 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER -0.162382 -0.486264 0.544331 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0984274 -0.491265 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0984274 -0.491265 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.153845 -0.574159 0.618405 RAD 0.0555556 + txt002 + SPHERE CENTER 0.202534 -0.612768 0.658726 RAD 0.0185185 + txt002 + SPHERE CENTER 0.225396 -0.554987 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.184086 -0.543919 0.678886 RAD 0.0185185 + txt002 + SPHERE CENTER 0.130984 -0.631939 0.658726 RAD 0.0185185 + txt002 + SPHERE CENTER 0.112536 -0.56309 0.678886 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0822954 -0.593331 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.172294 -0.643008 0.598245 RAD 0.0185185 + txt002 + SPHERE CENTER 0.123605 -0.6044 0.557924 RAD 0.0185185 + txt002 + SPHERE CENTER 0.195155 -0.585228 0.557924 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0329639 -0.552323 0.43322 RAD 0.0555556 + txt002 + SPHERE CENTER 0.0248832 -0.625877 0.436618 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0822954 -0.593331 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0138144 -0.584567 0.497099 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0244483 -0.584869 0.399581 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0355172 -0.54356 0.460062 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0163676 -0.511316 0.396183 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0440327 -0.593633 0.372739 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0521134 -0.520079 0.369341 RAD 0.0185185 + txt002 + SPHERE CENTER 0.101445 -0.561087 0.406378 RAD 0.0185185 + txt002 + SPHERE CENTER 0.247614 -0.494808 0.43322 RAD 0.0555556 + txt002 + SPHERE CENTER 0.313607 -0.494287 0.399581 RAD 0.0185185 + txt002 + SPHERE CENTER 0.269833 -0.434629 0.396183 RAD 0.0185185 + txt002 + SPHERE CENTER 0.302539 -0.452978 0.460062 RAD 0.0185185 + txt002 + SPHERE CENTER 0.291389 -0.554467 0.436618 RAD 0.0185185 + txt002 + SPHERE CENTER 0.28032 -0.513157 0.497099 RAD 0.0185185 + txt002 + SPHERE CENTER 0.225396 -0.554987 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER 0.258683 -0.536117 0.372739 RAD 0.0185185 + txt002 + SPHERE CENTER 0.19269 -0.536638 0.406378 RAD 0.0185185 + txt002 + SPHERE CENTER 0.214908 -0.476459 0.369341 RAD 0.0185185 + txt002 + SPHERE CENTER -0.172546 -0.643951 1.11022e-16 RAD 0.166667 + txt002 + SPHERE CENTER -0.157543 -0.835815 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.122136 -0.871646 0.165419 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0854653 -0.82339 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.135649 -0.799077 0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER -0.194213 -0.884071 0.153697 RAD 0.0185185 + txt002 + SPHERE CENTER -0.207727 -0.811502 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.229621 -0.84824 0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.14403 -0.908384 0.104938 RAD 0.0185185 + txt002 + SPHERE CENTER -0.179437 -0.872552 0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER -0.107359 -0.860128 0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0133465 -0.69376 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.0838533 -0.674309 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0539145 -0.666287 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0325183 -0.62221 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0432853 -0.701782 0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.00804971 -0.649684 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0272215 -0.721234 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0646815 -0.745859 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0058253 -0.76531 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0347427 -0.737837 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.172546 -0.643951 0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER -0.142305 -0.61371 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.100996 -0.624779 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.153374 -0.5724 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.213855 -0.632882 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.224924 -0.591572 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.244096 -0.663122 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.161477 -0.68526 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.191718 -0.715501 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.120168 -0.696329 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.343435 -0.786005 1.25414e-16 RAD 0.0555556 + txt002 + SPHERE CENTER -0.392454 -0.82165 0.0425863 RAD 0.0185185 + txt002 + SPHERE CENTER -0.323622 -0.80984 0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER -0.370774 -0.753118 0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER -0.412267 -0.797815 -0.0246914 RAD 0.0185185 + txt002 + SPHERE CENTER -0.390587 -0.729282 -0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER -0.363249 -0.76217 -0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER -0.365116 -0.854538 -0.0178949 RAD 0.0185185 + txt002 + SPHERE CENTER -0.316097 -0.818893 -0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER -0.296284 -0.842728 0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER -0.358439 -0.594141 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.389119 -0.547576 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.317871 -0.566667 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.339267 -0.522591 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.429687 -0.57505 0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER -0.379835 -0.550064 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.399007 -0.621614 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.408291 -0.619127 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.37761 -0.665691 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.337042 -0.638217 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.358439 -0.594141 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.409774 -0.542042 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.379835 -0.550064 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.339267 -0.522591 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.388377 -0.586119 -0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.317871 -0.566667 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.337042 -0.638217 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.428945 -0.613592 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.37761 -0.665691 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.399007 -0.621614 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.157543 -0.835815 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.119969 -0.899353 -0.117284 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0844101 -0.836885 -0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.130205 -0.868703 -0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER -0.193102 -0.898283 -0.129006 RAD 0.0185185 + txt002 + SPHERE CENTER -0.203337 -0.867633 -0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER -0.230676 -0.834745 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.147308 -0.866465 -0.177765 RAD 0.0185185 + txt002 + SPHERE CENTER -0.184881 -0.802927 -0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER -0.111748 -0.803997 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.172546 -0.643951 -0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER -0.202787 -0.61371 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.244096 -0.624779 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.191718 -0.5724 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.131237 -0.632882 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.120168 -0.591572 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.100996 -0.663122 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.183615 -0.68526 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.153374 -0.715501 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.224924 -0.696329 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0133465 -0.69376 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.0631985 -0.668775 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.00804971 -0.649684 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0325183 -0.62221 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0845947 -0.712851 -0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0539145 -0.666287 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0347427 -0.737837 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0440268 -0.740325 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0058253 -0.76531 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0272215 -0.721234 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.471405 -0.471405 1.11022e-16 RAD 0.166667 + txt002 + SPHERE CENTER 0.690426 -0.508983 2.241e-16 RAD 0.0555556 + txt002 + SPHERE CENTER 0.755941 -0.484794 -0.0246914 RAD 0.0185185 + txt002 + SPHERE CENTER 0.695668 -0.478434 -0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER 0.7029 -0.436283 -0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER 0.7507 -0.515343 0.0425863 RAD 0.0185185 + txt002 + SPHERE CENTER 0.697658 -0.466832 0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER 0.685185 -0.539531 0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER 0.743468 -0.557494 -0.0178949 RAD 0.0185185 + txt002 + SPHERE CENTER 0.677953 -0.581682 0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER 0.683194 -0.551134 -0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER 0.607487 -0.335322 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.629404 -0.313405 -0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.610996 -0.384191 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.558618 -0.331813 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.625895 -0.264535 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.555109 -0.282943 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.603979 -0.286452 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.678274 -0.316914 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.656357 -0.33883 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.659866 -0.3877 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.607487 -0.335322 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.659645 -0.283164 0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER 0.656357 -0.33883 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.603979 -0.286452 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.610775 -0.279656 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.555109 -0.282943 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.558618 -0.331813 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.663153 -0.332034 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.610996 -0.384191 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.659866 -0.3877 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.554344 -0.645066 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.610229 -0.668521 0.153697 RAD 0.0185185 + txt002 + SPHERE CENTER 0.622977 -0.619787 0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.585648 -0.598918 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.541596 -0.6938 0.165419 RAD 0.0185185 + txt002 + SPHERE CENTER 0.517014 -0.624197 0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER 0.48571 -0.670344 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.578925 -0.714669 0.104938 RAD 0.0185185 + txt002 + SPHERE CENTER 0.52304 -0.691213 0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER 0.591673 -0.665934 0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER 0.471405 -0.471405 0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER 0.501645 -0.441164 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.542955 -0.452233 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.490576 -0.399854 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.430095 -0.460336 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.419026 -0.419026 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.399854 -0.490576 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.482473 -0.512714 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.452233 -0.542955 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.523783 -0.523783 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.335322 -0.607487 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.313405 -0.629404 0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.384191 -0.610996 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.331813 -0.558618 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.264535 -0.625895 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.282943 -0.555109 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.286452 -0.603979 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.316914 -0.678274 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.33883 -0.656357 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.3877 -0.659866 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.554344 -0.645066 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.616373 -0.681385 -0.129006 RAD 0.0185185 + txt002 + SPHERE CENTER 0.617144 -0.607573 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.609912 -0.649723 -0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER 0.553573 -0.718878 -0.117284 RAD 0.0185185 + txt002 + SPHERE CENTER 0.547112 -0.687216 -0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER 0.491544 -0.682558 -0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.560805 -0.676727 -0.177765 RAD 0.0185185 + txt002 + SPHERE CENTER 0.498776 -0.640408 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.561576 -0.602915 -0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER 0.335322 -0.607487 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.283164 -0.659645 -0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER 0.33883 -0.656357 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.286452 -0.603979 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.279656 -0.610775 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.282943 -0.555109 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.331813 -0.558618 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.332034 -0.663153 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.384191 -0.610996 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.3877 -0.659866 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.471405 -0.471405 -0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER 0.441164 -0.441164 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.399854 -0.452233 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.452233 -0.399854 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.512714 -0.460336 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.523783 -0.419026 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.542955 -0.490576 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.460336 -0.512714 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.490576 -0.542955 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.419026 -0.523783 -0.222222 RAD 0.0185185 + txt002 + +END_SCENE diff --git a/src/tbb/examples/parallel_for/tachyon/dat/balls.dat b/src/tbb/examples/parallel_for/tachyon/dat/balls.dat new file mode 100644 index 0000000..0d4bbb1 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/dat/balls.dat @@ -0,0 +1,14804 @@ +BEGIN_SCENE + OUTFILE /dev/null + RESOLUTION 512 512 + VERBOSE 0 + +CAMERA + ZOOM 1.20711 +ASPECTRATIO 1.0 + ANTIALIASING 0 + RAYDEPTH 5 + CENTER 2.1 1.3 1.7 + VIEWDIR -0.700389 -0.433574 -0.566982 + UPDIR -0.482085 -0.298433 0.82373 + +END_CAMERA + +BACKGROUND 0.078 0.361 0.753 + +LIGHT CENTER 4 3 2 RAD 0.002 COLOR 0.5 0.5 0.5 + +LIGHT CENTER 1 -4 4 RAD 0.002 COLOR 0.5 0.5 0.5 + +LIGHT CENTER -3 1 5 RAD 0.002 COLOR 0.5 0.5 0.5 + +TEXDEF txt001 AMBIENT 0.2 DIFFUSE 0.8 SPECULAR 0 OPACITY 1 +PHONG PLASTIC 0 PHONG_SIZE 100000 + COLOR 1 0.75 0.33 + TEXFUNC 0 + +TRI + V0 12 12 -0.5 V1 -12 -12 -0.5 V2 12 -12 -0.5 + txt001 +TRI + V0 12 12 -0.5 V1 -12 12 -0.5 V2 -12 -12 -0.5 + txt001 +TEXDEF txt002 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 +PHONG PLASTIC 0.5 PHONG_SIZE 45.2776 + COLOR 1 0.9 0.7 + TEXFUNC 0 + + SPHERE CENTER 0 0 0 RAD 0.5 + txt002 + SPHERE CENTER 0.272166 0.272166 0.544331 RAD 0.166667 + txt002 + SPHERE CENTER 0.420314 0.420314 0.618405 RAD 0.0555556 + txt002 + SPHERE CENTER 0.470715 0.470715 0.598245 RAD 0.0185185 + txt002 + SPHERE CENTER 0.481689 0.481689 0.57904 RAD 0.00617284 + txt002 + SPHERE CENTER 0.475329 0.45787 0.577669 RAD 0.00617284 + txt002 + SPHERE CENTER 0.45787 0.475329 0.577669 RAD 0.00617284 + txt002 + SPHERE CENTER 0.477074 0.494534 0.599616 RAD 0.00617284 + txt002 + SPHERE CENTER 0.453255 0.488174 0.598245 RAD 0.00617284 + txt002 + SPHERE CENTER 0.4661 0.48356 0.618821 RAD 0.00617284 + txt002 + SPHERE CENTER 0.494534 0.477074 0.599616 RAD 0.00617284 + txt002 + SPHERE CENTER 0.48356 0.4661 0.618821 RAD 0.00617284 + txt002 + SPHERE CENTER 0.488174 0.453255 0.598245 RAD 0.00617284 + txt002 + SPHERE CENTER 0.461623 0.409245 0.557924 RAD 0.0185185 + txt002 + SPHERE CENTER 0.47044 0.419664 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER 0.447954 0.425689 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.468014 0.433095 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER 0.484109 0.40322 0.549693 RAD 0.00617284 + txt002 + SPHERE CENTER 0.481683 0.416651 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER 0.475292 0.392801 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER 0.464049 0.395814 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER 0.455233 0.385395 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER 0.441563 0.401839 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.409245 0.461623 0.557924 RAD 0.0185185 + txt002 + SPHERE CENTER 0.419664 0.47044 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER 0.433095 0.468014 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER 0.425689 0.447954 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.395814 0.464049 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER 0.401839 0.441563 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.385395 0.455233 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER 0.40322 0.484109 0.549693 RAD 0.00617284 + txt002 + SPHERE CENTER 0.392801 0.475292 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER 0.416651 0.481683 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER 0.429405 0.481784 0.658726 RAD 0.0185185 + txt002 + SPHERE CENTER 0.441197 0.503434 0.660098 RAD 0.00617284 + txt002 + SPHERE CENTER 0.452601 0.483752 0.650495 RAD 0.00617284 + txt002 + SPHERE CENTER 0.434161 0.494577 0.63815 RAD 0.00617284 + txt002 + SPHERE CENTER 0.418001 0.501466 0.668328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.410965 0.492609 0.64638 RAD 0.00617284 + txt002 + SPHERE CENTER 0.406209 0.479816 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER 0.436441 0.490641 0.680674 RAD 0.00617284 + txt002 + SPHERE CENTER 0.42465 0.46899 0.679302 RAD 0.00617284 + txt002 + SPHERE CENTER 0.447846 0.470958 0.671072 RAD 0.00617284 + txt002 + SPHERE CENTER 0.367935 0.472692 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.36376 0.497028 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.383056 0.487812 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.383056 0.487812 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.34864 0.481907 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.367935 0.472692 0.593714 RAD 0.00617284 + txt002 + SPHERE CENTER 0.352815 0.457572 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.34864 0.481907 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.352815 0.457572 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.367935 0.472692 0.643096 RAD 0.00617284 + txt002 + SPHERE CENTER 0.379004 0.431383 0.678886 RAD 0.0185185 + txt002 + SPHERE CENTER 0.376578 0.444814 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399064 0.438789 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER 0.385395 0.455233 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356518 0.437408 0.687117 RAD 0.00617284 + txt002 + SPHERE CENTER 0.365335 0.447826 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.358944 0.423976 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.370187 0.420964 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.372614 0.407532 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER 0.392673 0.414939 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER 0.481784 0.429405 0.658726 RAD 0.0185185 + txt002 + SPHERE CENTER 0.503434 0.441197 0.660098 RAD 0.00617284 + txt002 + SPHERE CENTER 0.494577 0.434161 0.63815 RAD 0.00617284 + txt002 + SPHERE CENTER 0.483752 0.452601 0.650495 RAD 0.00617284 + txt002 + SPHERE CENTER 0.490641 0.436441 0.680674 RAD 0.00617284 + txt002 + SPHERE CENTER 0.470958 0.447846 0.671072 RAD 0.00617284 + txt002 + SPHERE CENTER 0.46899 0.42465 0.679302 RAD 0.00617284 + txt002 + SPHERE CENTER 0.501466 0.418001 0.668328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.479816 0.406209 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER 0.492609 0.410965 0.64638 RAD 0.00617284 + txt002 + SPHERE CENTER 0.431383 0.379004 0.678886 RAD 0.0185185 + txt002 + SPHERE CENTER 0.444814 0.376578 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.455233 0.385395 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER 0.438789 0.399064 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER 0.420964 0.370187 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.414939 0.392673 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER 0.407532 0.372614 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER 0.437408 0.356518 0.687117 RAD 0.00617284 + txt002 + SPHERE CENTER 0.423976 0.358944 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.447826 0.365335 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.472692 0.367935 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.497028 0.36376 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.487812 0.383056 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.487812 0.383056 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.481907 0.34864 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.472692 0.367935 0.643096 RAD 0.00617284 + txt002 + SPHERE CENTER 0.457572 0.352815 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.481907 0.34864 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.457572 0.352815 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.472692 0.367935 0.593714 RAD 0.00617284 + txt002 + SPHERE CENTER 0.461844 0.304709 0.43322 RAD 0.0555556 + txt002 + SPHERE CENTER 0.492085 0.33495 0.372739 RAD 0.0185185 + txt002 + SPHERE CENTER 0.492085 0.33495 0.348047 RAD 0.00617284 + txt002 + SPHERE CENTER 0.488469 0.313874 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.471009 0.331334 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.495701 0.356025 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.474625 0.352409 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER 0.495701 0.356025 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.51316 0.338566 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.51316 0.338566 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.509544 0.31749 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER 0.424345 0.305171 0.369341 RAD 0.0185185 + txt002 + SPHERE CENTER 0.40568 0.315605 0.356995 RAD 0.00617284 + txt002 + SPHERE CENTER 0.403931 0.312107 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER 0.419383 0.329161 0.372427 RAD 0.00617284 + txt002 + SPHERE CENTER 0.426095 0.30867 0.344961 RAD 0.00617284 + txt002 + SPHERE CENTER 0.439797 0.322225 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.444759 0.298235 0.357307 RAD 0.00617284 + txt002 + SPHERE CENTER 0.410643 0.291616 0.353908 RAD 0.00617284 + txt002 + SPHERE CENTER 0.429307 0.281181 0.366254 RAD 0.00617284 + txt002 + SPHERE CENTER 0.408893 0.288117 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.435193 0.368397 0.406378 RAD 0.0185185 + txt002 + SPHERE CENTER 0.440864 0.389015 0.394032 RAD 0.00617284 + txt002 + SPHERE CENTER 0.457301 0.37895 0.409464 RAD 0.00617284 + txt002 + SPHERE CENTER 0.451857 0.367697 0.388171 RAD 0.00617284 + txt002 + SPHERE CENTER 0.418755 0.378463 0.390945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.429748 0.357145 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.413085 0.357845 0.403291 RAD 0.00617284 + txt002 + SPHERE CENTER 0.4242 0.389715 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.418529 0.369098 0.424584 RAD 0.00617284 + txt002 + SPHERE CENTER 0.440637 0.37965 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER 0.529584 0.334488 0.436618 RAD 0.0185185 + txt002 + SPHERE CENTER 0.546497 0.347572 0.424272 RAD 0.00617284 + txt002 + SPHERE CENTER 0.532117 0.331508 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.522481 0.352406 0.421186 RAD 0.00617284 + txt002 + SPHERE CENTER 0.543964 0.350552 0.448652 RAD 0.00617284 + txt002 + SPHERE CENTER 0.519948 0.355387 0.445566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.52705 0.337468 0.460998 RAD 0.00617284 + txt002 + SPHERE CENTER 0.5536 0.329654 0.439705 RAD 0.00617284 + txt002 + SPHERE CENTER 0.536686 0.31657 0.45205 RAD 0.00617284 + txt002 + SPHERE CENTER 0.53922 0.313589 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER 0.472692 0.367935 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER 0.48474 0.389488 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.495668 0.369235 0.46131 RAD 0.00617284 + txt002 + SPHERE CENTER 0.477004 0.379669 0.448964 RAD 0.00617284 + txt002 + SPHERE CENTER 0.461764 0.388188 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER 0.454027 0.37837 0.457911 RAD 0.00617284 + txt002 + SPHERE CENTER 0.449715 0.366636 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER 0.480429 0.377754 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.46838 0.356202 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.491357 0.357501 0.482603 RAD 0.00617284 + txt002 + SPHERE CENTER 0.499343 0.304247 0.497099 RAD 0.0185185 + txt002 + SPHERE CENTER 0.518259 0.314219 0.509445 RAD 0.00617284 + txt002 + SPHERE CENTER 0.519922 0.310678 0.485065 RAD 0.00617284 + txt002 + SPHERE CENTER 0.504895 0.328108 0.494013 RAD 0.00617284 + txt002 + SPHERE CENTER 0.49768 0.307788 0.521479 RAD 0.00617284 + txt002 + SPHERE CENTER 0.484316 0.321677 0.506047 RAD 0.00617284 + txt002 + SPHERE CENTER 0.478764 0.297816 0.509133 RAD 0.00617284 + txt002 + SPHERE CENTER 0.512708 0.290358 0.512531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.493791 0.280387 0.500186 RAD 0.00617284 + txt002 + SPHERE CENTER 0.51437 0.286818 0.488152 RAD 0.00617284 + txt002 + SPHERE CENTER 0.518736 0.271262 0.399581 RAD 0.0185185 + txt002 + SPHERE CENTER 0.539811 0.274878 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.520873 0.290418 0.384149 RAD 0.00617284 + txt002 + SPHERE CENTER 0.533373 0.290264 0.405442 RAD 0.00617284 + txt002 + SPHERE CENTER 0.537674 0.255722 0.402668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.531235 0.271108 0.420874 RAD 0.00617284 + txt002 + SPHERE CENTER 0.516598 0.252106 0.415013 RAD 0.00617284 + txt002 + SPHERE CENTER 0.525174 0.255876 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER 0.504099 0.25226 0.39372 RAD 0.00617284 + txt002 + SPHERE CENTER 0.506236 0.271416 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.488495 0.241021 0.460062 RAD 0.0185185 + txt002 + SPHERE CENTER 0.50716 0.230587 0.472408 RAD 0.00617284 + txt002 + SPHERE CENTER 0.51153 0.24936 0.456976 RAD 0.00617284 + txt002 + SPHERE CENTER 0.499694 0.253381 0.478269 RAD 0.00617284 + txt002 + SPHERE CENTER 0.484125 0.222248 0.475494 RAD 0.00617284 + txt002 + SPHERE CENTER 0.476659 0.245042 0.481355 RAD 0.00617284 + txt002 + SPHERE CENTER 0.46546 0.232683 0.463149 RAD 0.00617284 + txt002 + SPHERE CENTER 0.495961 0.218227 0.454201 RAD 0.00617284 + txt002 + SPHERE CENTER 0.477296 0.228661 0.441856 RAD 0.00617284 + txt002 + SPHERE CENTER 0.500331 0.237 0.438769 RAD 0.00617284 + txt002 + SPHERE CENTER 0.450996 0.241483 0.396183 RAD 0.0185185 + txt002 + SPHERE CENTER 0.455172 0.217147 0.396183 RAD 0.00617284 + txt002 + SPHERE CENTER 0.472226 0.232599 0.40513 RAD 0.00617284 + txt002 + SPHERE CENTER 0.45115 0.228983 0.417476 RAD 0.00617284 + txt002 + SPHERE CENTER 0.433942 0.226031 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.429921 0.237867 0.408529 RAD 0.00617284 + txt002 + SPHERE CENTER 0.429767 0.250367 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.455018 0.229647 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER 0.450842 0.253983 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER 0.472072 0.245099 0.383837 RAD 0.00617284 + txt002 + SPHERE CENTER 0.304709 0.461844 0.43322 RAD 0.0555556 + txt002 + SPHERE CENTER 0.33495 0.492085 0.372739 RAD 0.0185185 + txt002 + SPHERE CENTER 0.33495 0.492085 0.348047 RAD 0.00617284 + txt002 + SPHERE CENTER 0.331334 0.471009 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.313874 0.488469 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.338566 0.51316 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31749 0.509544 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER 0.338566 0.51316 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356025 0.495701 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356025 0.495701 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.352409 0.474625 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER 0.368397 0.435193 0.406378 RAD 0.0185185 + txt002 + SPHERE CENTER 0.389015 0.440864 0.394032 RAD 0.00617284 + txt002 + SPHERE CENTER 0.367697 0.451857 0.388171 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37895 0.457301 0.409464 RAD 0.00617284 + txt002 + SPHERE CENTER 0.389715 0.4242 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37965 0.440637 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER 0.369098 0.418529 0.424584 RAD 0.00617284 + txt002 + SPHERE CENTER 0.378463 0.418755 0.390945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.357845 0.413085 0.403291 RAD 0.00617284 + txt002 + SPHERE CENTER 0.357145 0.429748 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.305171 0.424345 0.369341 RAD 0.0185185 + txt002 + SPHERE CENTER 0.315605 0.40568 0.356995 RAD 0.00617284 + txt002 + SPHERE CENTER 0.329161 0.419383 0.372427 RAD 0.00617284 + txt002 + SPHERE CENTER 0.312107 0.403931 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER 0.291616 0.410643 0.353908 RAD 0.00617284 + txt002 + SPHERE CENTER 0.288117 0.408893 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.281181 0.429307 0.366254 RAD 0.00617284 + txt002 + SPHERE CENTER 0.30867 0.426095 0.344961 RAD 0.00617284 + txt002 + SPHERE CENTER 0.298235 0.444759 0.357307 RAD 0.00617284 + txt002 + SPHERE CENTER 0.322225 0.439797 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.271262 0.518736 0.399581 RAD 0.0185185 + txt002 + SPHERE CENTER 0.274878 0.539811 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.290264 0.533373 0.405442 RAD 0.00617284 + txt002 + SPHERE CENTER 0.290418 0.520873 0.384149 RAD 0.00617284 + txt002 + SPHERE CENTER 0.255876 0.525174 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER 0.271416 0.506236 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.25226 0.504099 0.39372 RAD 0.00617284 + txt002 + SPHERE CENTER 0.255722 0.537674 0.402668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.252106 0.516598 0.415013 RAD 0.00617284 + txt002 + SPHERE CENTER 0.271108 0.531235 0.420874 RAD 0.00617284 + txt002 + SPHERE CENTER 0.241483 0.450996 0.396183 RAD 0.0185185 + txt002 + SPHERE CENTER 0.217147 0.455172 0.396183 RAD 0.00617284 + txt002 + SPHERE CENTER 0.228983 0.45115 0.417476 RAD 0.00617284 + txt002 + SPHERE CENTER 0.232599 0.472226 0.40513 RAD 0.00617284 + txt002 + SPHERE CENTER 0.229647 0.455018 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER 0.245099 0.472072 0.383837 RAD 0.00617284 + txt002 + SPHERE CENTER 0.253983 0.450842 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER 0.226031 0.433942 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.250367 0.429767 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.237867 0.429921 0.408529 RAD 0.00617284 + txt002 + SPHERE CENTER 0.241021 0.488495 0.460062 RAD 0.0185185 + txt002 + SPHERE CENTER 0.230587 0.50716 0.472408 RAD 0.00617284 + txt002 + SPHERE CENTER 0.253381 0.499694 0.478269 RAD 0.00617284 + txt002 + SPHERE CENTER 0.24936 0.51153 0.456976 RAD 0.00617284 + txt002 + SPHERE CENTER 0.218227 0.495961 0.454201 RAD 0.00617284 + txt002 + SPHERE CENTER 0.237 0.500331 0.438769 RAD 0.00617284 + txt002 + SPHERE CENTER 0.228661 0.477296 0.441856 RAD 0.00617284 + txt002 + SPHERE CENTER 0.222248 0.484125 0.475494 RAD 0.00617284 + txt002 + SPHERE CENTER 0.232683 0.46546 0.463149 RAD 0.00617284 + txt002 + SPHERE CENTER 0.245042 0.476659 0.481355 RAD 0.00617284 + txt002 + SPHERE CENTER 0.334488 0.529584 0.436618 RAD 0.0185185 + txt002 + SPHERE CENTER 0.347572 0.546497 0.424272 RAD 0.00617284 + txt002 + SPHERE CENTER 0.352406 0.522481 0.421186 RAD 0.00617284 + txt002 + SPHERE CENTER 0.331508 0.532117 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.329654 0.5536 0.439705 RAD 0.00617284 + txt002 + SPHERE CENTER 0.313589 0.53922 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31657 0.536686 0.45205 RAD 0.00617284 + txt002 + SPHERE CENTER 0.350552 0.543964 0.448652 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337468 0.52705 0.460998 RAD 0.00617284 + txt002 + SPHERE CENTER 0.355387 0.519948 0.445566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.304247 0.499343 0.497099 RAD 0.0185185 + txt002 + SPHERE CENTER 0.314219 0.518259 0.509445 RAD 0.00617284 + txt002 + SPHERE CENTER 0.328108 0.504895 0.494013 RAD 0.00617284 + txt002 + SPHERE CENTER 0.310678 0.519922 0.485065 RAD 0.00617284 + txt002 + SPHERE CENTER 0.290358 0.512708 0.512531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.286818 0.51437 0.488152 RAD 0.00617284 + txt002 + SPHERE CENTER 0.280387 0.493791 0.500186 RAD 0.00617284 + txt002 + SPHERE CENTER 0.307788 0.49768 0.521479 RAD 0.00617284 + txt002 + SPHERE CENTER 0.297816 0.478764 0.509133 RAD 0.00617284 + txt002 + SPHERE CENTER 0.321677 0.484316 0.506047 RAD 0.00617284 + txt002 + SPHERE CENTER 0.367935 0.472692 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER 0.389488 0.48474 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.379669 0.477004 0.448964 RAD 0.00617284 + txt002 + SPHERE CENTER 0.369235 0.495668 0.46131 RAD 0.00617284 + txt002 + SPHERE CENTER 0.377754 0.480429 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.357501 0.491357 0.482603 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356202 0.46838 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.388188 0.461764 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER 0.366636 0.449715 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37837 0.454027 0.457911 RAD 0.00617284 + txt002 + SPHERE CENTER 0.230635 0.38777 0.729516 RAD 0.0555556 + txt002 + SPHERE CENTER 0.2506 0.446614 0.769837 RAD 0.0185185 + txt002 + SPHERE CENTER 0.264242 0.467193 0.770086 RAD 0.00617284 + txt002 + SPHERE CENTER 0.272442 0.447086 0.758332 RAD 0.00617284 + txt002 + SPHERE CENTER 0.253384 0.459832 0.749168 RAD 0.00617284 + txt002 + SPHERE CENTER 0.2424 0.46672 0.781591 RAD 0.00617284 + txt002 + SPHERE CENTER 0.231541 0.459359 0.760673 RAD 0.00617284 + txt002 + SPHERE CENTER 0.228758 0.446141 0.781342 RAD 0.00617284 + txt002 + SPHERE CENTER 0.261459 0.453974 0.790755 RAD 0.00617284 + txt002 + SPHERE CENTER 0.247817 0.433396 0.790506 RAD 0.00617284 + txt002 + SPHERE CENTER 0.269659 0.433868 0.779001 RAD 0.00617284 + txt002 + SPHERE CENTER 0.301839 0.407906 0.732914 RAD 0.0185185 + txt002 + SPHERE CENTER 0.319874 0.420236 0.72141 RAD 0.00617284 + txt002 + SPHERE CENTER 0.303021 0.407886 0.708251 RAD 0.00617284 + txt002 + SPHERE CENTER 0.296625 0.428474 0.720288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.318692 0.420256 0.746073 RAD 0.00617284 + txt002 + SPHERE CENTER 0.295442 0.428494 0.744951 RAD 0.00617284 + txt002 + SPHERE CENTER 0.300656 0.407926 0.757577 RAD 0.00617284 + txt002 + SPHERE CENTER 0.325088 0.399668 0.734036 RAD 0.00617284 + txt002 + SPHERE CENTER 0.307053 0.387338 0.745541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.308235 0.387318 0.720878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.253236 0.449775 0.695877 RAD 0.0185185 + txt002 + SPHERE CENTER 0.263032 0.459076 0.675209 RAD 0.00617284 + txt002 + SPHERE CENTER 0.270029 0.436804 0.683251 RAD 0.00617284 + txt002 + SPHERE CENTER 0.247378 0.440021 0.673964 RAD 0.00617284 + txt002 + SPHERE CENTER 0.246239 0.472047 0.687835 RAD 0.00617284 + txt002 + SPHERE CENTER 0.230585 0.452992 0.68659 RAD 0.00617284 + txt002 + SPHERE CENTER 0.236443 0.462746 0.708504 RAD 0.00617284 + txt002 + SPHERE CENTER 0.26889 0.468829 0.697123 RAD 0.00617284 + txt002 + SPHERE CENTER 0.259094 0.459528 0.717791 RAD 0.00617284 + txt002 + SPHERE CENTER 0.275887 0.446557 0.705165 RAD 0.00617284 + txt002 + SPHERE CENTER 0.179397 0.426478 0.766439 RAD 0.0185185 + txt002 + SPHERE CENTER 0.174744 0.447688 0.778193 RAD 0.00617284 + txt002 + SPHERE CENTER 0.197172 0.437457 0.779597 RAD 0.00617284 + txt002 + SPHERE CENTER 0.1895 0.447523 0.758396 RAD 0.00617284 + txt002 + SPHERE CENTER 0.156968 0.436708 0.765035 RAD 0.00617284 + txt002 + SPHERE CENTER 0.171724 0.436544 0.745238 RAD 0.00617284 + txt002 + SPHERE CENTER 0.161621 0.415499 0.753281 RAD 0.00617284 + txt002 + SPHERE CENTER 0.164641 0.426642 0.786236 RAD 0.00617284 + txt002 + SPHERE CENTER 0.169293 0.405432 0.774481 RAD 0.00617284 + txt002 + SPHERE CENTER 0.187069 0.416412 0.787639 RAD 0.00617284 + txt002 + SPHERE CENTER 0.182032 0.429639 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER 0.177682 0.45215 0.683315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.190087 0.449636 0.704516 RAD 0.00617284 + txt002 + SPHERE CENTER 0.200611 0.44299 0.683192 RAD 0.00617284 + txt002 + SPHERE CENTER 0.169628 0.432153 0.671279 RAD 0.00617284 + txt002 + SPHERE CENTER 0.192556 0.422992 0.671155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.173978 0.409641 0.680442 RAD 0.00617284 + txt002 + SPHERE CENTER 0.159104 0.438799 0.692603 RAD 0.00617284 + txt002 + SPHERE CENTER 0.163454 0.416288 0.701767 RAD 0.00617284 + txt002 + SPHERE CENTER 0.171508 0.436286 0.713804 RAD 0.00617284 + txt002 + SPHERE CENTER 0.159431 0.367634 0.726118 RAD 0.0185185 + txt002 + SPHERE CENTER 0.13761 0.368692 0.737623 RAD 0.00617284 + txt002 + SPHERE CENTER 0.158434 0.366998 0.750781 RAD 0.00617284 + txt002 + SPHERE CENTER 0.153102 0.387887 0.738744 RAD 0.00617284 + txt002 + SPHERE CENTER 0.138607 0.369329 0.71296 RAD 0.00617284 + txt002 + SPHERE CENTER 0.154099 0.388523 0.714081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.160429 0.36827 0.701455 RAD 0.00617284 + txt002 + SPHERE CENTER 0.14394 0.34844 0.724997 RAD 0.00617284 + txt002 + SPHERE CENTER 0.165761 0.347381 0.713492 RAD 0.00617284 + txt002 + SPHERE CENTER 0.164764 0.346745 0.738155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.227999 0.384609 0.803476 RAD 0.0185185 + txt002 + SPHERE CENTER 0.237348 0.393812 0.824394 RAD 0.00617284 + txt002 + SPHERE CENTER 0.251829 0.390976 0.804597 RAD 0.00617284 + txt002 + SPHERE CENTER 0.234368 0.408432 0.804721 RAD 0.00617284 + txt002 + SPHERE CENTER 0.213518 0.387445 0.823273 RAD 0.00617284 + txt002 + SPHERE CENTER 0.210538 0.402066 0.8036 RAD 0.00617284 + txt002 + SPHERE CENTER 0.204169 0.378242 0.802355 RAD 0.00617284 + txt002 + SPHERE CENTER 0.23098 0.369989 0.823149 RAD 0.00617284 + txt002 + SPHERE CENTER 0.221631 0.360786 0.802231 RAD 0.00617284 + txt002 + SPHERE CENTER 0.245461 0.367152 0.803352 RAD 0.00617284 + txt002 + SPHERE CENTER 0.208034 0.325765 0.763155 RAD 0.0185185 + txt002 + SPHERE CENTER 0.209548 0.312342 0.783824 RAD 0.00617284 + txt002 + SPHERE CENTER 0.229235 0.324887 0.775781 RAD 0.00617284 + txt002 + SPHERE CENTER 0.209827 0.337 0.785069 RAD 0.00617284 + txt002 + SPHERE CENTER 0.188347 0.31322 0.771198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.188626 0.337878 0.772443 RAD 0.00617284 + txt002 + SPHERE CENTER 0.186834 0.326643 0.750529 RAD 0.00617284 + txt002 + SPHERE CENTER 0.207755 0.301107 0.76191 RAD 0.00617284 + txt002 + SPHERE CENTER 0.206242 0.31453 0.741241 RAD 0.00617284 + txt002 + SPHERE CENTER 0.227442 0.313652 0.753867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.279238 0.345901 0.766553 RAD 0.0185185 + txt002 + SPHERE CENTER 0.302145 0.344931 0.775717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.297823 0.356827 0.754517 RAD 0.00617284 + txt002 + SPHERE CENTER 0.289691 0.366251 0.775841 RAD 0.00617284 + txt002 + SPHERE CENTER 0.28356 0.334005 0.787754 RAD 0.00617284 + txt002 + SPHERE CENTER 0.271106 0.355325 0.787878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.260653 0.334975 0.77859 RAD 0.00617284 + txt002 + SPHERE CENTER 0.291692 0.324581 0.766429 RAD 0.00617284 + txt002 + SPHERE CENTER 0.268785 0.325551 0.757266 RAD 0.00617284 + txt002 + SPHERE CENTER 0.28737 0.336477 0.745229 RAD 0.00617284 + txt002 + SPHERE CENTER 0.115031 0.4293 0.544331 RAD 0.0555556 + txt002 + SPHERE CENTER 0.102505 0.502308 0.544331 RAD 0.0185185 + txt002 + SPHERE CENTER 0.110567 0.524146 0.536101 RAD 0.00617284 + txt002 + SPHERE CENTER 0.126738 0.506465 0.542066 RAD 0.00617284 + txt002 + SPHERE CENTER 0.112687 0.504055 0.521905 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0863343 0.519988 0.538366 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0884544 0.499897 0.524171 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0782715 0.49815 0.546597 RAD 0.00617284 + txt002 + SPHERE CENTER 0.100385 0.522399 0.558526 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0923218 0.500561 0.566757 RAD 0.00617284 + txt002 + SPHERE CENTER 0.116555 0.504718 0.564491 RAD 0.00617284 + txt002 + SPHERE CENTER 0.160392 0.474661 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.177777 0.492047 0.579103 RAD 0.00617284 + txt002 + SPHERE CENTER 0.176681 0.473492 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.159222 0.490951 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.161488 0.493217 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER 0.142932 0.492121 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.144102 0.475831 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.178947 0.475757 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER 0.161561 0.458371 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.177851 0.457202 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.160392 0.474661 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.167697 0.481967 0.484868 RAD 0.00617284 + txt002 + SPHERE CENTER 0.161561 0.458371 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.144102 0.475831 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.166528 0.498257 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.142932 0.492121 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.159222 0.490951 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.183987 0.480797 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.176681 0.473492 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.177851 0.457202 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0571437 0.456947 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0450372 0.477623 0.501329 RAD 0.00617284 + txt002 + SPHERE CENTER 0.055591 0.475469 0.523547 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0696413 0.47788 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0465898 0.4591 0.485076 RAD 0.00617284 + txt002 + SPHERE CENTER 0.071194 0.459357 0.487134 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0586963 0.438424 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0325396 0.45669 0.505236 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0446461 0.436013 0.511201 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0430934 0.454536 0.527454 RAD 0.00617284 + txt002 + SPHERE CENTER 0.115031 0.4293 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER 0.10495 0.439381 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0911807 0.435691 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.10864 0.45315 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.128801 0.43299 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER 0.13249 0.44676 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.138881 0.42291 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.111341 0.415531 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER 0.121421 0.40545 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0975713 0.411841 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0696698 0.383939 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.052284 0.366554 0.509559 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0708393 0.36765 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0533799 0.385109 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0511144 0.382844 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0522103 0.401399 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0685002 0.400229 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0685739 0.365384 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0859596 0.38277 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0871292 0.36648 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0571437 0.456947 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0493251 0.475575 0.595564 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0725262 0.467381 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER 0.06557 0.479825 0.577461 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0339426 0.465141 0.57931 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0501875 0.46939 0.561208 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0417612 0.446512 0.565115 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0408988 0.452697 0.599471 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0487174 0.434069 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0640999 0.444504 0.601529 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0696698 0.383939 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0623642 0.376634 0.603794 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0859596 0.38277 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0685002 0.400229 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0460743 0.377803 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0522103 0.401399 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0533799 0.385109 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0635337 0.360344 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0708393 0.36765 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0871292 0.36648 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.115031 0.4293 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.125111 0.439381 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.138881 0.435691 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.121421 0.45315 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.101261 0.43299 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0975713 0.44676 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0911807 0.42291 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.11872 0.415531 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.10864 0.40545 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.13249 0.411841 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.082487 0.239622 0.655442 RAD 0.0555556 + txt002 + SPHERE CENTER 0.0438957 0.258053 0.715923 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0426858 0.273525 0.735128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.064638 0.265928 0.726759 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0510334 0.281546 0.713318 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0219434 0.26565 0.724292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.030291 0.273671 0.702483 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0231533 0.250178 0.705088 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0355481 0.250032 0.737733 RAD 0.00617284 + txt002 + SPHERE CENTER 0.036758 0.23456 0.718528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0575003 0.242434 0.729364 RAD 0.00617284 + txt002 + SPHERE CENTER 0.117687 0.252557 0.719322 RAD 0.0185185 + txt002 + SPHERE CENTER 0.135677 0.265544 0.730157 RAD 0.00617284 + txt002 + SPHERE CENTER 0.138361 0.25778 0.706872 RAD 0.00617284 + txt002 + SPHERE CENTER 0.12224 0.275732 0.71212 RAD 0.00617284 + txt002 + SPHERE CENTER 0.115003 0.26032 0.742607 RAD 0.00617284 + txt002 + SPHERE CENTER 0.101567 0.270508 0.72457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.097014 0.247334 0.731771 RAD 0.00617284 + txt002 + SPHERE CENTER 0.131123 0.242369 0.737359 RAD 0.00617284 + txt002 + SPHERE CENTER 0.113134 0.229382 0.726523 RAD 0.00617284 + txt002 + SPHERE CENTER 0.133808 0.234605 0.714074 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0863845 0.308551 0.682285 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0971427 0.330622 0.67968 RAD 0.00617284 + txt002 + SPHERE CENTER 0.109956 0.310023 0.675083 RAD 0.00617284 + txt002 + SPHERE CENTER 0.091905 0.317013 0.659755 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0735708 0.329151 0.686881 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0683331 0.315541 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0628126 0.30708 0.689486 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0916222 0.322161 0.702209 RAD 0.00617284 + txt002 + SPHERE CENTER 0.080864 0.30009 0.704814 RAD 0.00617284 + txt002 + SPHERE CENTER 0.104436 0.301561 0.697613 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00869528 0.245118 0.652044 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0110117 0.257416 0.660413 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00823377 0.253319 0.675329 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0102865 0.269325 0.656641 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0105502 0.249215 0.637128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.010748 0.261124 0.633356 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00915679 0.236916 0.628759 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0126029 0.233209 0.655816 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00710408 0.22091 0.647447 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00664257 0.229111 0.670732 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0511841 0.295616 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0555846 0.315856 0.604965 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0705987 0.309941 0.623653 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0705297 0.296292 0.603077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.03617 0.301531 0.599717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0511152 0.281968 0.597829 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0317696 0.281291 0.613157 RAD 0.00617284 + txt002 + SPHERE CENTER 0.036239 0.31518 0.620293 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0318385 0.29494 0.633733 RAD 0.00617284 + txt002 + SPHERE CENTER 0.051253 0.309265 0.638981 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0472866 0.226687 0.591563 RAD 0.0185185 + txt002 + SPHERE CENTER 0.025169 0.224935 0.580727 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0281502 0.217281 0.604012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0288111 0.241399 0.598764 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0443054 0.234341 0.568278 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0479475 0.250805 0.586315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.066423 0.236092 0.579113 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0436445 0.210223 0.573526 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0657621 0.211974 0.584361 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0466257 0.202569 0.596811 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0399982 0.189123 0.689081 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0335228 0.179527 0.71089 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0567332 0.187058 0.707118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0385291 0.203632 0.709006 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0167878 0.181593 0.692853 RAD 0.00617284 + txt002 + SPHERE CENTER 0.021794 0.205698 0.690969 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0232631 0.191189 0.671044 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0349919 0.165018 0.690965 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0414672 0.174615 0.669156 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0582023 0.172549 0.687193 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0785895 0.170692 0.6286 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0867911 0.147549 0.631205 RAD 0.00617284 + txt002 + SPHERE CENTER 0.101845 0.166573 0.635801 RAD 0.00617284 + txt002 + SPHERE CENTER 0.083121 0.161663 0.65113 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0635354 0.151669 0.624003 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0598652 0.165782 0.643928 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0553337 0.174812 0.621398 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0822597 0.156579 0.608675 RAD 0.00617284 + txt002 + SPHERE CENTER 0.074058 0.179722 0.60607 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0973138 0.175603 0.613272 RAD 0.00617284 + txt002 + SPHERE CENTER 0.11379 0.183628 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER 0.133336 0.176775 0.705919 RAD 0.00617284 + txt002 + SPHERE CENTER 0.136161 0.192663 0.687231 RAD 0.00617284 + txt002 + SPHERE CENTER 0.124499 0.199753 0.707807 RAD 0.00617284 + txt002 + SPHERE CENTER 0.110965 0.167739 0.711167 RAD 0.00617284 + txt002 + SPHERE CENTER 0.102127 0.190718 0.713055 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0914184 0.174592 0.697727 RAD 0.00617284 + txt002 + SPHERE CENTER 0.122627 0.160649 0.690591 RAD 0.00617284 + txt002 + SPHERE CENTER 0.103081 0.167502 0.677151 RAD 0.00617284 + txt002 + SPHERE CENTER 0.125452 0.176537 0.671903 RAD 0.00617284 + txt002 + SPHERE CENTER 0.38777 0.230635 0.729516 RAD 0.0555556 + txt002 + SPHERE CENTER 0.446614 0.2506 0.769837 RAD 0.0185185 + txt002 + SPHERE CENTER 0.467193 0.264242 0.770086 RAD 0.00617284 + txt002 + SPHERE CENTER 0.459832 0.253384 0.749168 RAD 0.00617284 + txt002 + SPHERE CENTER 0.447086 0.272442 0.758332 RAD 0.00617284 + txt002 + SPHERE CENTER 0.453974 0.261459 0.790755 RAD 0.00617284 + txt002 + SPHERE CENTER 0.433868 0.269659 0.779001 RAD 0.00617284 + txt002 + SPHERE CENTER 0.433396 0.247817 0.790506 RAD 0.00617284 + txt002 + SPHERE CENTER 0.46672 0.2424 0.781591 RAD 0.00617284 + txt002 + SPHERE CENTER 0.446141 0.228758 0.781342 RAD 0.00617284 + txt002 + SPHERE CENTER 0.459359 0.231541 0.760673 RAD 0.00617284 + txt002 + SPHERE CENTER 0.449775 0.253236 0.695877 RAD 0.0185185 + txt002 + SPHERE CENTER 0.459076 0.263032 0.675209 RAD 0.00617284 + txt002 + SPHERE CENTER 0.440021 0.247378 0.673964 RAD 0.00617284 + txt002 + SPHERE CENTER 0.436804 0.270029 0.683251 RAD 0.00617284 + txt002 + SPHERE CENTER 0.468829 0.26889 0.697123 RAD 0.00617284 + txt002 + SPHERE CENTER 0.446557 0.275887 0.705165 RAD 0.00617284 + txt002 + SPHERE CENTER 0.459528 0.259094 0.717791 RAD 0.00617284 + txt002 + SPHERE CENTER 0.472047 0.246239 0.687835 RAD 0.00617284 + txt002 + SPHERE CENTER 0.462746 0.236443 0.708504 RAD 0.00617284 + txt002 + SPHERE CENTER 0.452992 0.230585 0.68659 RAD 0.00617284 + txt002 + SPHERE CENTER 0.407906 0.301839 0.732914 RAD 0.0185185 + txt002 + SPHERE CENTER 0.420236 0.319874 0.72141 RAD 0.00617284 + txt002 + SPHERE CENTER 0.428474 0.296625 0.720288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.407886 0.303021 0.708251 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399668 0.325088 0.734036 RAD 0.00617284 + txt002 + SPHERE CENTER 0.387318 0.308235 0.720878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.387338 0.307053 0.745541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.420256 0.318692 0.746073 RAD 0.00617284 + txt002 + SPHERE CENTER 0.407926 0.300656 0.757577 RAD 0.00617284 + txt002 + SPHERE CENTER 0.428494 0.295442 0.744951 RAD 0.00617284 + txt002 + SPHERE CENTER 0.384609 0.227999 0.803476 RAD 0.0185185 + txt002 + SPHERE CENTER 0.393812 0.237348 0.824394 RAD 0.00617284 + txt002 + SPHERE CENTER 0.408432 0.234368 0.804721 RAD 0.00617284 + txt002 + SPHERE CENTER 0.390976 0.251829 0.804597 RAD 0.00617284 + txt002 + SPHERE CENTER 0.369989 0.23098 0.823149 RAD 0.00617284 + txt002 + SPHERE CENTER 0.367152 0.245461 0.803352 RAD 0.00617284 + txt002 + SPHERE CENTER 0.360786 0.221631 0.802231 RAD 0.00617284 + txt002 + SPHERE CENTER 0.387445 0.213518 0.823273 RAD 0.00617284 + txt002 + SPHERE CENTER 0.378242 0.204169 0.802355 RAD 0.00617284 + txt002 + SPHERE CENTER 0.402066 0.210538 0.8036 RAD 0.00617284 + txt002 + SPHERE CENTER 0.345901 0.279238 0.766553 RAD 0.0185185 + txt002 + SPHERE CENTER 0.344931 0.302145 0.775717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.366251 0.289691 0.775841 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356827 0.297823 0.754517 RAD 0.00617284 + txt002 + SPHERE CENTER 0.324581 0.291692 0.766429 RAD 0.00617284 + txt002 + SPHERE CENTER 0.336477 0.28737 0.745229 RAD 0.00617284 + txt002 + SPHERE CENTER 0.325551 0.268785 0.757266 RAD 0.00617284 + txt002 + SPHERE CENTER 0.334005 0.28356 0.787754 RAD 0.00617284 + txt002 + SPHERE CENTER 0.334975 0.260653 0.77859 RAD 0.00617284 + txt002 + SPHERE CENTER 0.355325 0.271106 0.787878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.325765 0.208034 0.763155 RAD 0.0185185 + txt002 + SPHERE CENTER 0.312342 0.209548 0.783824 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337 0.209827 0.785069 RAD 0.00617284 + txt002 + SPHERE CENTER 0.324887 0.229235 0.775781 RAD 0.00617284 + txt002 + SPHERE CENTER 0.301107 0.207755 0.76191 RAD 0.00617284 + txt002 + SPHERE CENTER 0.313652 0.227442 0.753867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31453 0.206242 0.741241 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31322 0.188347 0.771198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.326643 0.186834 0.750529 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337878 0.188626 0.772443 RAD 0.00617284 + txt002 + SPHERE CENTER 0.426478 0.179397 0.766439 RAD 0.0185185 + txt002 + SPHERE CENTER 0.447688 0.174744 0.778193 RAD 0.00617284 + txt002 + SPHERE CENTER 0.447523 0.1895 0.758396 RAD 0.00617284 + txt002 + SPHERE CENTER 0.437457 0.197172 0.779597 RAD 0.00617284 + txt002 + SPHERE CENTER 0.426642 0.164641 0.786236 RAD 0.00617284 + txt002 + SPHERE CENTER 0.416412 0.187069 0.787639 RAD 0.00617284 + txt002 + SPHERE CENTER 0.405432 0.169293 0.774481 RAD 0.00617284 + txt002 + SPHERE CENTER 0.436708 0.156968 0.765035 RAD 0.00617284 + txt002 + SPHERE CENTER 0.415499 0.161621 0.753281 RAD 0.00617284 + txt002 + SPHERE CENTER 0.436544 0.171724 0.745238 RAD 0.00617284 + txt002 + SPHERE CENTER 0.367634 0.159431 0.726118 RAD 0.0185185 + txt002 + SPHERE CENTER 0.368692 0.13761 0.737623 RAD 0.00617284 + txt002 + SPHERE CENTER 0.387887 0.153102 0.738744 RAD 0.00617284 + txt002 + SPHERE CENTER 0.366998 0.158434 0.750781 RAD 0.00617284 + txt002 + SPHERE CENTER 0.34844 0.14394 0.724997 RAD 0.00617284 + txt002 + SPHERE CENTER 0.346745 0.164764 0.738155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.347381 0.165761 0.713492 RAD 0.00617284 + txt002 + SPHERE CENTER 0.369329 0.138607 0.71296 RAD 0.00617284 + txt002 + SPHERE CENTER 0.36827 0.160429 0.701455 RAD 0.00617284 + txt002 + SPHERE CENTER 0.388523 0.154099 0.714081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.429639 0.182032 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER 0.45215 0.177682 0.683315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.44299 0.200611 0.683192 RAD 0.00617284 + txt002 + SPHERE CENTER 0.449636 0.190087 0.704516 RAD 0.00617284 + txt002 + SPHERE CENTER 0.438799 0.159104 0.692603 RAD 0.00617284 + txt002 + SPHERE CENTER 0.436286 0.171508 0.713804 RAD 0.00617284 + txt002 + SPHERE CENTER 0.416288 0.163454 0.701767 RAD 0.00617284 + txt002 + SPHERE CENTER 0.432153 0.169628 0.671279 RAD 0.00617284 + txt002 + SPHERE CENTER 0.409641 0.173978 0.680442 RAD 0.00617284 + txt002 + SPHERE CENTER 0.422992 0.192556 0.671155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.239622 0.082487 0.655442 RAD 0.0555556 + txt002 + SPHERE CENTER 0.258053 0.0438957 0.715923 RAD 0.0185185 + txt002 + SPHERE CENTER 0.273525 0.0426858 0.735128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.281546 0.0510334 0.713318 RAD 0.00617284 + txt002 + SPHERE CENTER 0.265928 0.064638 0.726759 RAD 0.00617284 + txt002 + SPHERE CENTER 0.250032 0.0355481 0.737733 RAD 0.00617284 + txt002 + SPHERE CENTER 0.242434 0.0575003 0.729364 RAD 0.00617284 + txt002 + SPHERE CENTER 0.23456 0.036758 0.718528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.26565 0.0219434 0.724292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.250178 0.0231533 0.705088 RAD 0.00617284 + txt002 + SPHERE CENTER 0.273671 0.030291 0.702483 RAD 0.00617284 + txt002 + SPHERE CENTER 0.308551 0.0863845 0.682285 RAD 0.0185185 + txt002 + SPHERE CENTER 0.330622 0.0971427 0.67968 RAD 0.00617284 + txt002 + SPHERE CENTER 0.317013 0.091905 0.659755 RAD 0.00617284 + txt002 + SPHERE CENTER 0.310023 0.109956 0.675083 RAD 0.00617284 + txt002 + SPHERE CENTER 0.322161 0.0916222 0.702209 RAD 0.00617284 + txt002 + SPHERE CENTER 0.301561 0.104436 0.697613 RAD 0.00617284 + txt002 + SPHERE CENTER 0.30009 0.080864 0.704814 RAD 0.00617284 + txt002 + SPHERE CENTER 0.329151 0.0735708 0.686881 RAD 0.00617284 + txt002 + SPHERE CENTER 0.30708 0.0628126 0.689486 RAD 0.00617284 + txt002 + SPHERE CENTER 0.315541 0.0683331 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER 0.252557 0.117687 0.719322 RAD 0.0185185 + txt002 + SPHERE CENTER 0.265544 0.135677 0.730157 RAD 0.00617284 + txt002 + SPHERE CENTER 0.275732 0.12224 0.71212 RAD 0.00617284 + txt002 + SPHERE CENTER 0.25778 0.138361 0.706872 RAD 0.00617284 + txt002 + SPHERE CENTER 0.242369 0.131123 0.737359 RAD 0.00617284 + txt002 + SPHERE CENTER 0.234605 0.133808 0.714074 RAD 0.00617284 + txt002 + SPHERE CENTER 0.229382 0.113134 0.726523 RAD 0.00617284 + txt002 + SPHERE CENTER 0.26032 0.115003 0.742607 RAD 0.00617284 + txt002 + SPHERE CENTER 0.247334 0.097014 0.731771 RAD 0.00617284 + txt002 + SPHERE CENTER 0.270508 0.101567 0.72457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.189123 0.0399982 0.689081 RAD 0.0185185 + txt002 + SPHERE CENTER 0.179527 0.0335228 0.71089 RAD 0.00617284 + txt002 + SPHERE CENTER 0.203632 0.0385291 0.709006 RAD 0.00617284 + txt002 + SPHERE CENTER 0.187058 0.0567332 0.707118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.165018 0.0349919 0.690965 RAD 0.00617284 + txt002 + SPHERE CENTER 0.172549 0.0582023 0.687193 RAD 0.00617284 + txt002 + SPHERE CENTER 0.174615 0.0414672 0.669156 RAD 0.00617284 + txt002 + SPHERE CENTER 0.181593 0.0167878 0.692853 RAD 0.00617284 + txt002 + SPHERE CENTER 0.191189 0.0232631 0.671044 RAD 0.00617284 + txt002 + SPHERE CENTER 0.205698 0.021794 0.690969 RAD 0.00617284 + txt002 + SPHERE CENTER 0.183628 0.11379 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER 0.176775 0.133336 0.705919 RAD 0.00617284 + txt002 + SPHERE CENTER 0.199753 0.124499 0.707807 RAD 0.00617284 + txt002 + SPHERE CENTER 0.192663 0.136161 0.687231 RAD 0.00617284 + txt002 + SPHERE CENTER 0.160649 0.122627 0.690591 RAD 0.00617284 + txt002 + SPHERE CENTER 0.176537 0.125452 0.671903 RAD 0.00617284 + txt002 + SPHERE CENTER 0.167502 0.103081 0.677151 RAD 0.00617284 + txt002 + SPHERE CENTER 0.167739 0.110965 0.711167 RAD 0.00617284 + txt002 + SPHERE CENTER 0.174592 0.0914184 0.697727 RAD 0.00617284 + txt002 + SPHERE CENTER 0.190718 0.102127 0.713055 RAD 0.00617284 + txt002 + SPHERE CENTER 0.170692 0.0785895 0.6286 RAD 0.0185185 + txt002 + SPHERE CENTER 0.147549 0.0867911 0.631205 RAD 0.00617284 + txt002 + SPHERE CENTER 0.161663 0.083121 0.65113 RAD 0.00617284 + txt002 + SPHERE CENTER 0.166573 0.101845 0.635801 RAD 0.00617284 + txt002 + SPHERE CENTER 0.156579 0.0822597 0.608675 RAD 0.00617284 + txt002 + SPHERE CENTER 0.175603 0.0973138 0.613272 RAD 0.00617284 + txt002 + SPHERE CENTER 0.179722 0.074058 0.60607 RAD 0.00617284 + txt002 + SPHERE CENTER 0.151669 0.0635354 0.624003 RAD 0.00617284 + txt002 + SPHERE CENTER 0.174812 0.0553337 0.621398 RAD 0.00617284 + txt002 + SPHERE CENTER 0.165782 0.0598652 0.643928 RAD 0.00617284 + txt002 + SPHERE CENTER 0.245118 0.00869528 0.652044 RAD 0.0185185 + txt002 + SPHERE CENTER 0.257416 -0.0110117 0.660413 RAD 0.00617284 + txt002 + SPHERE CENTER 0.269325 0.0102865 0.656641 RAD 0.00617284 + txt002 + SPHERE CENTER 0.253319 0.00823377 0.675329 RAD 0.00617284 + txt002 + SPHERE CENTER 0.233209 -0.0126029 0.655816 RAD 0.00617284 + txt002 + SPHERE CENTER 0.229111 0.00664257 0.670732 RAD 0.00617284 + txt002 + SPHERE CENTER 0.22091 0.00710408 0.647447 RAD 0.00617284 + txt002 + SPHERE CENTER 0.249215 -0.0105502 0.637128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.236916 0.00915679 0.628759 RAD 0.00617284 + txt002 + SPHERE CENTER 0.261124 0.010748 0.633356 RAD 0.00617284 + txt002 + SPHERE CENTER 0.226687 0.0472866 0.591563 RAD 0.0185185 + txt002 + SPHERE CENTER 0.224935 0.025169 0.580727 RAD 0.00617284 + txt002 + SPHERE CENTER 0.241399 0.0288111 0.598764 RAD 0.00617284 + txt002 + SPHERE CENTER 0.217281 0.0281502 0.604012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.210223 0.0436445 0.573526 RAD 0.00617284 + txt002 + SPHERE CENTER 0.202569 0.0466257 0.596811 RAD 0.00617284 + txt002 + SPHERE CENTER 0.211974 0.0657621 0.584361 RAD 0.00617284 + txt002 + SPHERE CENTER 0.234341 0.0443054 0.568278 RAD 0.00617284 + txt002 + SPHERE CENTER 0.236092 0.066423 0.579113 RAD 0.00617284 + txt002 + SPHERE CENTER 0.250805 0.0479475 0.586315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.295616 0.0511841 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.315856 0.0555846 0.604965 RAD 0.00617284 + txt002 + SPHERE CENTER 0.296292 0.0705297 0.603077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.309941 0.0705987 0.623653 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31518 0.036239 0.620293 RAD 0.00617284 + txt002 + SPHERE CENTER 0.309265 0.051253 0.638981 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29494 0.0318385 0.633733 RAD 0.00617284 + txt002 + SPHERE CENTER 0.301531 0.03617 0.599717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.281291 0.0317696 0.613157 RAD 0.00617284 + txt002 + SPHERE CENTER 0.281968 0.0511152 0.597829 RAD 0.00617284 + txt002 + SPHERE CENTER 0.4293 0.115031 0.544331 RAD 0.0555556 + txt002 + SPHERE CENTER 0.502308 0.102505 0.544331 RAD 0.0185185 + txt002 + SPHERE CENTER 0.524146 0.110567 0.536101 RAD 0.00617284 + txt002 + SPHERE CENTER 0.504055 0.112687 0.521905 RAD 0.00617284 + txt002 + SPHERE CENTER 0.506465 0.126738 0.542066 RAD 0.00617284 + txt002 + SPHERE CENTER 0.522399 0.100385 0.558526 RAD 0.00617284 + txt002 + SPHERE CENTER 0.504718 0.116555 0.564491 RAD 0.00617284 + txt002 + SPHERE CENTER 0.500561 0.0923218 0.566757 RAD 0.00617284 + txt002 + SPHERE CENTER 0.519988 0.0863343 0.538366 RAD 0.00617284 + txt002 + SPHERE CENTER 0.49815 0.0782715 0.546597 RAD 0.00617284 + txt002 + SPHERE CENTER 0.499897 0.0884544 0.524171 RAD 0.00617284 + txt002 + SPHERE CENTER 0.474661 0.160392 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.481967 0.167697 0.484868 RAD 0.00617284 + txt002 + SPHERE CENTER 0.475831 0.144102 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.458371 0.161561 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.480797 0.183987 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.457202 0.177851 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.473492 0.176681 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.498257 0.166528 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.490951 0.159222 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.492121 0.142932 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.474661 0.160392 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.492047 0.177777 0.579103 RAD 0.00617284 + txt002 + SPHERE CENTER 0.490951 0.159222 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.473492 0.176681 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.475757 0.178947 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER 0.457202 0.177851 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.458371 0.161561 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.493217 0.161488 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER 0.475831 0.144102 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.492121 0.142932 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.456947 0.0571437 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.475575 0.0493251 0.595564 RAD 0.00617284 + txt002 + SPHERE CENTER 0.479825 0.06557 0.577461 RAD 0.00617284 + txt002 + SPHERE CENTER 0.467381 0.0725262 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER 0.452697 0.0408988 0.599471 RAD 0.00617284 + txt002 + SPHERE CENTER 0.444504 0.0640999 0.601529 RAD 0.00617284 + txt002 + SPHERE CENTER 0.434069 0.0487174 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER 0.465141 0.0339426 0.57931 RAD 0.00617284 + txt002 + SPHERE CENTER 0.446512 0.0417612 0.565115 RAD 0.00617284 + txt002 + SPHERE CENTER 0.46939 0.0501875 0.561208 RAD 0.00617284 + txt002 + SPHERE CENTER 0.4293 0.115031 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.439381 0.125111 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.45315 0.121421 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.435691 0.138881 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.415531 0.11872 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.411841 0.13249 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.40545 0.10864 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.43299 0.101261 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.42291 0.0911807 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.44676 0.0975713 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.383939 0.0696698 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.376634 0.0623642 0.603794 RAD 0.00617284 + txt002 + SPHERE CENTER 0.400229 0.0685002 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.38277 0.0859596 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.360344 0.0635337 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER 0.36648 0.0871292 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.36765 0.0708393 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.377803 0.0460743 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER 0.385109 0.0533799 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.401399 0.0522103 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.456947 0.0571437 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.477623 0.0450372 0.501329 RAD 0.00617284 + txt002 + SPHERE CENTER 0.47788 0.0696413 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.475469 0.055591 0.523547 RAD 0.00617284 + txt002 + SPHERE CENTER 0.45669 0.0325396 0.505236 RAD 0.00617284 + txt002 + SPHERE CENTER 0.454536 0.0430934 0.527454 RAD 0.00617284 + txt002 + SPHERE CENTER 0.436013 0.0446461 0.511201 RAD 0.00617284 + txt002 + SPHERE CENTER 0.4591 0.0465898 0.485076 RAD 0.00617284 + txt002 + SPHERE CENTER 0.438424 0.0586963 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER 0.459357 0.071194 0.487134 RAD 0.00617284 + txt002 + SPHERE CENTER 0.383939 0.0696698 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.366554 0.052284 0.509559 RAD 0.00617284 + txt002 + SPHERE CENTER 0.385109 0.0533799 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.36765 0.0708393 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.365384 0.0685739 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER 0.36648 0.0871292 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.38277 0.0859596 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.382844 0.0511144 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER 0.400229 0.0685002 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.401399 0.0522103 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.4293 0.115031 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER 0.41922 0.125111 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER 0.40545 0.121421 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.42291 0.138881 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.44307 0.11872 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER 0.44676 0.13249 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.45315 0.10864 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.425611 0.101261 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER 0.435691 0.0911807 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.411841 0.0975713 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.643951 0.172546 1.11022e-16 RAD 0.166667 + txt002 + SPHERE CENTER 0.802608 0.281471 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.824035 0.30566 -0.177765 RAD 0.0185185 + txt002 + SPHERE CENTER 0.822021 0.302088 -0.202114 RAD 0.00617284 + txt002 + SPHERE CENTER 0.821938 0.282758 -0.186751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.802598 0.298094 -0.187402 RAD 0.00617284 + txt002 + SPHERE CENTER 0.824119 0.32499 -0.193128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.804695 0.320997 -0.178416 RAD 0.00617284 + txt002 + SPHERE CENTER 0.826132 0.328563 -0.16878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.843459 0.309654 -0.192477 RAD 0.00617284 + txt002 + SPHERE CENTER 0.845472 0.313227 -0.168128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.843375 0.290324 -0.177114 RAD 0.00617284 + txt002 + SPHERE CENTER 0.787796 0.241352 -0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER 0.785699 0.218449 -0.180578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.802677 0.22345 -0.163362 RAD 0.00617284 + txt002 + SPHERE CENTER 0.778718 0.223304 -0.157397 RAD 0.00617284 + txt002 + SPHERE CENTER 0.770818 0.236351 -0.188808 RAD 0.00617284 + txt002 + SPHERE CENTER 0.763837 0.241205 -0.165627 RAD 0.00617284 + txt002 + SPHERE CENTER 0.772915 0.259253 -0.179823 RAD 0.00617284 + txt002 + SPHERE CENTER 0.794777 0.236497 -0.194773 RAD 0.00617284 + txt002 + SPHERE CENTER 0.796874 0.2594 -0.185788 RAD 0.00617284 + txt002 + SPHERE CENTER 0.811756 0.241498 -0.177557 RAD 0.00617284 + txt002 + SPHERE CENTER 0.752156 0.305221 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.741263 0.325175 -0.169507 RAD 0.00617284 + txt002 + SPHERE CENTER 0.747715 0.32493 -0.145675 RAD 0.00617284 + txt002 + SPHERE CENTER 0.765112 0.325981 -0.163165 RAD 0.00617284 + txt002 + SPHERE CENTER 0.745704 0.305466 -0.183703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.769553 0.306272 -0.17736 RAD 0.00617284 + txt002 + SPHERE CENTER 0.756597 0.285513 -0.174066 RAD 0.00617284 + txt002 + SPHERE CENTER 0.728307 0.304415 -0.166213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.7392 0.284462 -0.156576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.734759 0.304171 -0.142381 RAD 0.00617284 + txt002 + SPHERE CENTER 0.838847 0.34578 -0.117284 RAD 0.0185185 + txt002 + SPHERE CENTER 0.851488 0.360404 -0.132647 RAD 0.00617284 + txt002 + SPHERE CENTER 0.853509 0.335865 -0.1345 RAD 0.00617284 + txt002 + SPHERE CENTER 0.832518 0.347059 -0.141116 RAD 0.00617284 + txt002 + SPHERE CENTER 0.836826 0.370319 -0.115431 RAD 0.00617284 + txt002 + SPHERE CENTER 0.817857 0.356973 -0.1239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.824185 0.355695 -0.100068 RAD 0.00617284 + txt002 + SPHERE CENTER 0.857816 0.359125 -0.108814 RAD 0.00617284 + txt002 + SPHERE CENTER 0.845176 0.344501 -0.0934517 RAD 0.00617284 + txt002 + SPHERE CENTER 0.859838 0.334587 -0.110668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.766968 0.345341 -0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.768944 0.369945 -0.10004 RAD 0.00617284 + txt002 + SPHERE CENTER 0.788341 0.356172 -0.093424 RAD 0.00617284 + txt002 + SPHERE CENTER 0.780624 0.356171 -0.116879 RAD 0.00617284 + txt002 + SPHERE CENTER 0.747572 0.359113 -0.106005 RAD 0.00617284 + txt002 + SPHERE CENTER 0.759252 0.34534 -0.122844 RAD 0.00617284 + txt002 + SPHERE CENTER 0.745596 0.33451 -0.105354 RAD 0.00617284 + txt002 + SPHERE CENTER 0.755289 0.359115 -0.0825505 RAD 0.00617284 + txt002 + SPHERE CENTER 0.753313 0.334511 -0.0818993 RAD 0.00617284 + txt002 + SPHERE CENTER 0.774685 0.345342 -0.0759343 RAD 0.00617284 + txt002 + SPHERE CENTER 0.817421 0.321591 -0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER 0.83071 0.340361 -0.0416443 RAD 0.00617284 + txt002 + SPHERE CENTER 0.840365 0.325527 -0.0588603 RAD 0.00617284 + txt002 + SPHERE CENTER 0.822249 0.341208 -0.0648253 RAD 0.00617284 + txt002 + SPHERE CENTER 0.807766 0.336425 -0.0334138 RAD 0.00617284 + txt002 + SPHERE CENTER 0.799305 0.337272 -0.0565949 RAD 0.00617284 + txt002 + SPHERE CENTER 0.794477 0.317654 -0.0423994 RAD 0.00617284 + txt002 + SPHERE CENTER 0.825882 0.320744 -0.0274488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.812593 0.301973 -0.0364345 RAD 0.00617284 + txt002 + SPHERE CENTER 0.835537 0.30591 -0.0446649 RAD 0.00617284 + txt002 + SPHERE CENTER 0.874487 0.28191 -0.129006 RAD 0.0185185 + txt002 + SPHERE CENTER 0.891539 0.292033 -0.143718 RAD 0.00617284 + txt002 + SPHERE CENTER 0.868678 0.28812 -0.152187 RAD 0.00617284 + txt002 + SPHERE CENTER 0.872763 0.305711 -0.135349 RAD 0.00617284 + txt002 + SPHERE CENTER 0.897348 0.285824 -0.120537 RAD 0.00617284 + txt002 + SPHERE CENTER 0.878572 0.299501 -0.112168 RAD 0.00617284 + txt002 + SPHERE CENTER 0.880296 0.275701 -0.105825 RAD 0.00617284 + txt002 + SPHERE CENTER 0.893263 0.268233 -0.137375 RAD 0.00617284 + txt002 + SPHERE CENTER 0.876212 0.25811 -0.122663 RAD 0.00617284 + txt002 + SPHERE CENTER 0.870402 0.264319 -0.145845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.853061 0.257721 -0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER 0.87538 0.26204 -0.0527151 RAD 0.00617284 + txt002 + SPHERE CENTER 0.87108 0.266856 -0.0765474 RAD 0.00617284 + txt002 + SPHERE CENTER 0.860805 0.280934 -0.0590577 RAD 0.00617284 + txt002 + SPHERE CENTER 0.857361 0.252905 -0.0385197 RAD 0.00617284 + txt002 + SPHERE CENTER 0.842785 0.271799 -0.0448623 RAD 0.00617284 + txt002 + SPHERE CENTER 0.835041 0.248586 -0.0481565 RAD 0.00617284 + txt002 + SPHERE CENTER 0.867636 0.238827 -0.0560094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.845317 0.234508 -0.0656463 RAD 0.00617284 + txt002 + SPHERE CENTER 0.863337 0.243643 -0.0798417 RAD 0.00617284 + txt002 + SPHERE CENTER 0.838248 0.217602 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.860225 0.206363 -0.122182 RAD 0.00617284 + txt002 + SPHERE CENTER 0.858689 0.230102 -0.128798 RAD 0.00617284 + txt002 + SPHERE CENTER 0.854636 0.223536 -0.105343 RAD 0.00617284 + txt002 + SPHERE CENTER 0.839784 0.193863 -0.116217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.834196 0.211035 -0.0993785 RAD 0.00617284 + txt002 + SPHERE CENTER 0.817808 0.205101 -0.116868 RAD 0.00617284 + txt002 + SPHERE CENTER 0.843837 0.200429 -0.139672 RAD 0.00617284 + txt002 + SPHERE CENTER 0.821861 0.211667 -0.140323 RAD 0.00617284 + txt002 + SPHERE CENTER 0.842301 0.224168 -0.146288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.643951 0.172546 -0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER 0.61371 0.202787 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.61556 0.221097 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.621702 0.225035 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.635958 0.210779 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.607567 0.198849 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.627965 0.188531 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER 0.605717 0.180539 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.593312 0.213105 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER 0.591462 0.194794 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.599454 0.217042 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER 0.5724 0.191718 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.556122 0.208861 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.575596 0.203643 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.578791 0.215568 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.552927 0.196936 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER 0.575596 0.203643 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.569205 0.179793 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.549732 0.185011 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.56601 0.167868 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.569205 0.179793 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.624779 0.244096 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.631486 0.266765 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.648629 0.250487 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.636704 0.247291 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.607636 0.260374 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.612854 0.240901 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.600929 0.237705 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.619561 0.26357 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.612854 0.240901 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.636704 0.247291 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.68526 0.183615 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.684921 0.190903 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.665787 0.178397 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669989 0.201661 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.704395 0.196121 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER 0.689462 0.206879 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.704733 0.188833 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER 0.700193 0.172858 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.700531 0.165569 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.681058 0.160351 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.696329 0.224924 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.710584 0.23918 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER 0.705059 0.216195 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.687599 0.233654 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.701855 0.24791 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.678869 0.242384 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.687599 0.233654 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.719314 0.23045 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.705059 0.216195 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.713788 0.207465 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.715501 0.153374 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.738169 0.160081 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.718696 0.165299 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.721891 0.177224 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.734974 0.148156 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.718696 0.165299 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.712305 0.141449 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.731779 0.136231 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.70911 0.129524 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.712305 0.141449 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.632882 0.131237 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.634145 0.108412 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER 0.650927 0.115965 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.627664 0.111763 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER 0.616099 0.123683 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.609618 0.127034 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.614836 0.146508 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.639363 0.127886 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.6381 0.15071 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER 0.656145 0.135439 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.663122 0.100996 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.680265 0.0847178 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.686972 0.107387 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.675047 0.104191 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.656415 0.0783272 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.651197 0.0978007 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.639272 0.0946054 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.66834 0.0815225 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER 0.651197 0.0978007 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.675047 0.104191 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.591572 0.120168 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.577317 0.105912 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.600302 0.111438 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.582843 0.128897 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.568587 0.114642 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.574113 0.137627 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.582843 0.128897 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.586046 0.0971825 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.600302 0.111438 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.609032 0.102708 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.594141 0.358439 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.619127 0.408291 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.625955 0.411883 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.630791 0.390369 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.607547 0.396287 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.61429 0.429805 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.595882 0.414208 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.607462 0.426212 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.637535 0.423887 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.630706 0.420295 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.642371 0.402373 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.665691 0.37761 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.68332 0.389713 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.665691 0.37761 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.660156 0.398265 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.68332 0.389713 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.660156 0.398265 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.665691 0.37761 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.688854 0.369058 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.671225 0.356956 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.671225 0.356956 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.638217 0.337042 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.652948 0.344865 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.632683 0.357697 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.651954 0.357326 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.658482 0.324211 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.657489 0.336672 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.643752 0.316388 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.639211 0.324581 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.624481 0.316758 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.618946 0.337413 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.547576 0.389119 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.541008 0.410169 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.548718 0.410472 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.564748 0.405866 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539866 0.388816 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.563607 0.384513 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.546435 0.367766 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.523836 0.393422 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.530405 0.372372 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.531546 0.393725 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.566667 0.317871 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.555534 0.296626 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.572202 0.297216 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.550163 0.307914 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.549999 0.31728 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.544629 0.328569 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.561133 0.338525 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.572037 0.306582 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.583171 0.327827 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.588706 0.307172 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.522591 0.339267 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.501272 0.340934 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.522591 0.339267 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.517056 0.359921 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.501272 0.340934 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.517056 0.359921 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.522591 0.339267 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.506807 0.320279 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.528125 0.318612 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.528125 0.318612 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.57505 0.429687 -0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER 0.58161 0.452905 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.5989 0.436077 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.586467 0.434777 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.55776 0.446515 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.562617 0.428387 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.5512 0.423296 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.570193 0.447815 -0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER 0.563633 0.424596 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.587483 0.430987 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.550064 0.379835 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.547099 0.396248 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.569716 0.388263 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.557504 0.403175 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.527447 0.387819 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.537852 0.394747 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.530412 0.371406 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539659 0.372907 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.542624 0.356494 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.562276 0.364922 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.621614 0.399007 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.637209 0.41723 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.642848 0.401533 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.624734 0.418027 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.615976 0.414703 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.603501 0.4155 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.600381 0.39648 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.634089 0.39821 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.618494 0.379986 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.639728 0.382513 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.802608 0.281471 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.858698 0.329459 0.104938 RAD 0.0185185 + txt002 + SPHERE CENTER 0.872345 0.34259 0.0890951 RAD 0.00617284 + txt002 + SPHERE CENTER 0.86421 0.32016 0.0827387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.848329 0.338969 0.0846485 RAD 0.00617284 + txt002 + SPHERE CENTER 0.866833 0.351888 0.111295 RAD 0.00617284 + txt002 + SPHERE CENTER 0.842817 0.348268 0.106848 RAD 0.00617284 + txt002 + SPHERE CENTER 0.853186 0.338757 0.127138 RAD 0.00617284 + txt002 + SPHERE CENTER 0.882715 0.333079 0.109385 RAD 0.00617284 + txt002 + SPHERE CENTER 0.869068 0.319948 0.125228 RAD 0.00617284 + txt002 + SPHERE CENTER 0.87458 0.310649 0.103028 RAD 0.00617284 + txt002 + SPHERE CENTER 0.845371 0.280879 0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER 0.849036 0.291048 0.0284303 RAD 0.00617284 + txt002 + SPHERE CENTER 0.826067 0.287867 0.0369125 RAD 0.00617284 + txt002 + SPHERE CENTER 0.840755 0.304882 0.0471312 RAD 0.00617284 + txt002 + SPHERE CENTER 0.868341 0.28406 0.0421477 RAD 0.00617284 + txt002 + SPHERE CENTER 0.86006 0.297894 0.0608487 RAD 0.00617284 + txt002 + SPHERE CENTER 0.864676 0.273891 0.0643473 RAD 0.00617284 + txt002 + SPHERE CENTER 0.853652 0.267046 0.0319289 RAD 0.00617284 + txt002 + SPHERE CENTER 0.849987 0.256877 0.0541285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.830683 0.263865 0.0404111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.798572 0.337088 0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER 0.808673 0.346884 0.0420622 RAD 0.00617284 + txt002 + SPHERE CENTER 0.82298 0.335792 0.0588533 RAD 0.00617284 + txt002 + SPHERE CENTER 0.807762 0.322361 0.044793 RAD 0.00617284 + txt002 + SPHERE CENTER 0.784265 0.34818 0.0455609 RAD 0.00617284 + txt002 + SPHERE CENTER 0.783355 0.323657 0.0482916 RAD 0.00617284 + txt002 + SPHERE CENTER 0.774164 0.338384 0.0658506 RAD 0.00617284 + txt002 + SPHERE CENTER 0.799483 0.361611 0.0596212 RAD 0.00617284 + txt002 + SPHERE CENTER 0.789382 0.351815 0.079911 RAD 0.00617284 + txt002 + SPHERE CENTER 0.81379 0.350519 0.0764123 RAD 0.00617284 + txt002 + SPHERE CENTER 0.815936 0.330051 0.165419 RAD 0.0185185 + txt002 + SPHERE CENTER 0.828769 0.350165 0.171776 RAD 0.00617284 + txt002 + SPHERE CENTER 0.838905 0.333232 0.156937 RAD 0.00617284 + txt002 + SPHERE CENTER 0.820583 0.347547 0.148628 RAD 0.00617284 + txt002 + SPHERE CENTER 0.805799 0.346984 0.180258 RAD 0.00617284 + txt002 + SPHERE CENTER 0.797614 0.344366 0.157111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.792966 0.32687 0.173902 RAD 0.00617284 + txt002 + SPHERE CENTER 0.824121 0.332668 0.188567 RAD 0.00617284 + txt002 + SPHERE CENTER 0.811288 0.312554 0.182211 RAD 0.00617284 + txt002 + SPHERE CENTER 0.834258 0.315735 0.173728 RAD 0.00617284 + txt002 + SPHERE CENTER 0.75581 0.33768 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.753851 0.362219 0.124743 RAD 0.00617284 + txt002 + SPHERE CENTER 0.774086 0.350765 0.133052 RAD 0.00617284 + txt002 + SPHERE CENTER 0.76987 0.352319 0.108773 RAD 0.00617284 + txt002 + SPHERE CENTER 0.735575 0.349134 0.114524 RAD 0.00617284 + txt002 + SPHERE CENTER 0.751594 0.339233 0.0985541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.737534 0.324595 0.112614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.739791 0.347581 0.138803 RAD 0.00617284 + txt002 + SPHERE CENTER 0.74175 0.323042 0.136894 RAD 0.00617284 + txt002 + SPHERE CENTER 0.760026 0.336127 0.147112 RAD 0.00617284 + txt002 + SPHERE CENTER 0.759846 0.282063 0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER 0.756464 0.29233 0.193792 RAD 0.00617284 + txt002 + SPHERE CENTER 0.779336 0.288514 0.18531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.765125 0.305929 0.175091 RAD 0.00617284 + txt002 + SPHERE CENTER 0.736973 0.285879 0.180075 RAD 0.00617284 + txt002 + SPHERE CENTER 0.745634 0.299478 0.161374 RAD 0.00617284 + txt002 + SPHERE CENTER 0.740355 0.275612 0.157875 RAD 0.00617284 + txt002 + SPHERE CENTER 0.751185 0.268464 0.190293 RAD 0.00617284 + txt002 + SPHERE CENTER 0.754567 0.258198 0.168094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.774058 0.264649 0.181811 RAD 0.00617284 + txt002 + SPHERE CENTER 0.862735 0.273842 0.153697 RAD 0.0185185 + txt002 + SPHERE CENTER 0.885497 0.282313 0.158144 RAD 0.00617284 + txt002 + SPHERE CENTER 0.876946 0.281455 0.134996 RAD 0.00617284 + txt002 + SPHERE CENTER 0.867718 0.29787 0.150967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.871286 0.274699 0.176845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.853506 0.290257 0.169668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.848523 0.266228 0.172398 RAD 0.00617284 + txt002 + SPHERE CENTER 0.880514 0.258284 0.160875 RAD 0.00617284 + txt002 + SPHERE CENTER 0.857752 0.249813 0.156428 RAD 0.00617284 + txt002 + SPHERE CENTER 0.871963 0.257427 0.137727 RAD 0.00617284 + txt002 + SPHERE CENTER 0.806645 0.225855 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.818054 0.21762 0.18016 RAD 0.00617284 + txt002 + SPHERE CENTER 0.83061 0.230661 0.163369 RAD 0.00617284 + txt002 + SPHERE CENTER 0.813612 0.241754 0.177429 RAD 0.00617284 + txt002 + SPHERE CENTER 0.794089 0.212813 0.176661 RAD 0.00617284 + txt002 + SPHERE CENTER 0.789647 0.236948 0.173931 RAD 0.00617284 + txt002 + SPHERE CENTER 0.78268 0.221048 0.156372 RAD 0.00617284 + txt002 + SPHERE CENTER 0.811087 0.20172 0.162601 RAD 0.00617284 + txt002 + SPHERE CENTER 0.799677 0.209955 0.142311 RAD 0.00617284 + txt002 + SPHERE CENTER 0.823642 0.214761 0.14581 RAD 0.00617284 + txt002 + SPHERE CENTER 0.849407 0.225263 0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.873186 0.21889 0.0974792 RAD 0.00617284 + txt002 + SPHERE CENTER 0.865588 0.240865 0.0891702 RAD 0.00617284 + txt002 + SPHERE CENTER 0.866351 0.236437 0.113449 RAD 0.00617284 + txt002 + SPHERE CENTER 0.857005 0.203288 0.107698 RAD 0.00617284 + txt002 + SPHERE CENTER 0.850171 0.220835 0.123668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.833227 0.20966 0.109608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.856242 0.207715 0.0834188 RAD 0.00617284 + txt002 + SPHERE CENTER 0.832464 0.214088 0.0853287 RAD 0.00617284 + txt002 + SPHERE CENTER 0.848644 0.22969 0.0751099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.594141 0.358439 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.613592 0.428945 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.626191 0.448155 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.634643 0.42519 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.614455 0.43276 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.60514 0.45191 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.593404 0.436515 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.592541 0.4327 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.625328 0.44434 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.612729 0.42513 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.63378 0.421375 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.665691 0.37761 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.68332 0.389713 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.665691 0.37761 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.660156 0.398265 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.68332 0.389713 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.660156 0.398265 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.665691 0.37761 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.688854 0.369058 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.671225 0.356956 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.671225 0.356956 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.621614 0.399007 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.625435 0.399844 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.627149 0.378352 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.60511 0.38905 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.619901 0.420499 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.599576 0.409705 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.61608 0.419661 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.641939 0.409801 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.638118 0.408963 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.643653 0.388308 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.542042 0.409774 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.53788 0.433888 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.558395 0.423551 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.55574 0.426423 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.521526 0.42011 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539387 0.412646 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.525689 0.395996 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.524182 0.417238 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.528344 0.393124 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.544697 0.406901 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.550064 0.379835 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.540802 0.399304 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.54453 0.400489 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.563801 0.400119 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.546337 0.37865 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.569335 0.379464 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.555599 0.35918 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.527065 0.37902 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.536327 0.359551 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.530793 0.380205 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.522591 0.339267 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.501272 0.340934 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.522591 0.339267 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.517056 0.359921 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.501272 0.340934 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.517056 0.359921 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.522591 0.339267 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.506807 0.320279 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.528125 0.318612 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.528125 0.318612 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.586119 0.388377 0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.594185 0.405974 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.609969 0.394768 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.593017 0.410332 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.570335 0.399584 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.569167 0.403942 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.562269 0.381987 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.587286 0.384019 0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.57922 0.366422 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.60307 0.372813 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.566667 0.317871 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.567308 0.314012 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.587901 0.320398 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.569787 0.336891 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.546074 0.311485 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.548554 0.334364 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.545434 0.315344 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.564188 0.294991 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.563547 0.29885 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.584781 0.301377 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.638217 0.337042 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.659244 0.341809 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.65787 0.345471 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.645657 0.360383 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.639592 0.33338 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.626005 0.351955 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.618565 0.328614 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.651804 0.318468 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.630777 0.313702 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.65043 0.32213 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.643951 0.172546 0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER 0.674191 0.202787 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.690652 0.219248 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER 0.695267 0.206403 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.677807 0.223862 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669577 0.215632 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.656732 0.220246 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.653116 0.199171 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.687036 0.198172 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.670575 0.181711 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.691651 0.185327 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.715501 0.191718 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.733129 0.203821 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.715501 0.191718 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.709966 0.212373 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.733129 0.203821 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.709966 0.212373 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.715501 0.191718 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.738664 0.183166 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.721035 0.171063 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.721035 0.171063 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.663122 0.244096 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.675225 0.261725 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.683777 0.238562 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.663122 0.244096 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.65457 0.267259 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.642468 0.249631 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.642468 0.249631 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.675225 0.261725 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.663122 0.244096 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.683777 0.238562 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.602641 0.183615 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.600215 0.197046 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.622701 0.191021 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.609032 0.207465 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.580155 0.18964 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER 0.588972 0.200059 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.582581 0.176209 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.593824 0.173196 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.596251 0.159765 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.61631 0.167171 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.591572 0.224924 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.587397 0.24926 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.606693 0.240045 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.606693 0.240045 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.572277 0.23414 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.591572 0.224924 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.576452 0.209804 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.572277 0.23414 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.576452 0.209804 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.591572 0.224924 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.5724 0.153374 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.551082 0.155041 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.5724 0.153374 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.566866 0.174029 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.551082 0.155041 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.566866 0.174029 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.5724 0.153374 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.556617 0.134387 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.577935 0.13272 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.577935 0.13272 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.655019 0.131237 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.668451 0.12881 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.678869 0.137627 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.662426 0.151296 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.644601 0.12242 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.638576 0.144906 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.631169 0.124846 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.661044 0.108751 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER 0.647613 0.111177 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.671463 0.117567 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.624779 0.100996 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.626446 0.0796777 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.645433 0.0954616 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.624779 0.100996 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.605791 0.0852121 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.604124 0.10653 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.604124 0.10653 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.626446 0.0796777 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.624779 0.100996 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.645433 0.0954616 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.696329 0.120168 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.720665 0.115992 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.711449 0.135288 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.711449 0.135288 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.705544 0.100872 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.696329 0.120168 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.681209 0.105047 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.705544 0.100872 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.681209 0.105047 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.696329 0.120168 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.852418 0.0955788 1.89979e-16 RAD 0.0555556 + txt002 + SPHERE CENTER 0.922609 0.11107 -0.0178949 RAD 0.0185185 + txt002 + SPHERE CENTER 0.937225 0.122151 -0.0344251 RAD 0.00617284 + txt002 + SPHERE CENTER 0.916553 0.11086 -0.0418311 RAD 0.00617284 + txt002 + SPHERE CENTER 0.915202 0.131874 -0.0289382 RAD 0.00617284 + txt002 + SPHERE CENTER 0.943281 0.12236 -0.0104889 RAD 0.00617284 + txt002 + SPHERE CENTER 0.921258 0.132084 -0.00500196 RAD 0.00617284 + txt002 + SPHERE CENTER 0.928665 0.111279 0.00604126 RAD 0.00617284 + txt002 + SPHERE CENTER 0.944632 0.101346 -0.0233819 RAD 0.00617284 + txt002 + SPHERE CENTER 0.930016 0.0902645 -0.00685171 RAD 0.00617284 + txt002 + SPHERE CENTER 0.92396 0.090055 -0.0307879 RAD 0.00617284 + txt002 + SPHERE CENTER 0.867231 0.135698 -0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER 0.873196 0.134634 -0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER 0.882112 0.117797 -0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER 0.858152 0.11765 -0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER 0.858315 0.152536 -0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER 0.843271 0.135552 -0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.852349 0.1536 -0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER 0.882275 0.152682 -0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.876309 0.153747 -0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER 0.89119 0.135845 -0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER 0.877966 0.164775 0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER 0.890926 0.182656 -0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER 0.897331 0.159019 -0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER 0.876622 0.167676 -0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER 0.871561 0.188412 0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER 0.857256 0.173431 -0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.8586 0.17053 0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER 0.89227 0.179755 0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER 0.87931 0.161874 0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.898675 0.156118 0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.907797 0.0709499 0.0425863 RAD 0.0185185 + txt002 + SPHERE CENTER 0.930963 0.0752104 0.0499923 RAD 0.00617284 + txt002 + SPHERE CENTER 0.924191 0.0806562 0.0268805 RAD 0.00617284 + txt002 + SPHERE CENTER 0.915684 0.0941344 0.0457385 RAD 0.00617284 + txt002 + SPHERE CENTER 0.914568 0.0655041 0.065698 RAD 0.00617284 + txt002 + SPHERE CENTER 0.899289 0.0844281 0.0614442 RAD 0.00617284 + txt002 + SPHERE CENTER 0.891402 0.0612436 0.058292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.923076 0.0520258 0.0468401 RAD 0.00617284 + txt002 + SPHERE CENTER 0.89991 0.0477654 0.0394341 RAD 0.00617284 + txt002 + SPHERE CENTER 0.916304 0.0574717 0.0237283 RAD 0.00617284 + txt002 + SPHERE CENTER 0.863153 0.124655 0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER 0.875744 0.141535 0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER 0.88655 0.129819 0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.868763 0.146389 0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER 0.852347 0.136371 0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER 0.845366 0.141225 0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER 0.839756 0.119492 0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER 0.870135 0.119801 0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER 0.857544 0.102922 0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER 0.880941 0.108085 0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER 0.837606 0.0554592 0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER 0.842832 0.0523913 0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER 0.86055 0.0593957 0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER 0.842434 0.0750766 0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER 0.819888 0.0484547 0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER 0.81949 0.07114 0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.814662 0.0515226 0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER 0.838004 0.0327739 0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.832778 0.0358417 0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER 0.855722 0.0397783 0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER 0.897062 0.0418734 -0.0246914 RAD 0.0185185 + txt002 + SPHERE CENTER 0.920407 0.0359958 -0.0301783 RAD 0.00617284 + txt002 + SPHERE CENTER 0.912106 0.0588574 -0.0344321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.915603 0.0511067 -0.0112511 RAD 0.00617284 + txt002 + SPHERE CENTER 0.905363 0.0190117 -0.0204376 RAD 0.00617284 + txt002 + SPHERE CENTER 0.900559 0.0341227 -0.00151032 RAD 0.00617284 + txt002 + SPHERE CENTER 0.882018 0.0248894 -0.0149506 RAD 0.00617284 + txt002 + SPHERE CENTER 0.901866 0.0267625 -0.0436186 RAD 0.00617284 + txt002 + SPHERE CENTER 0.878521 0.0326401 -0.0381316 RAD 0.00617284 + txt002 + SPHERE CENTER 0.893565 0.0496241 -0.0478724 RAD 0.00617284 + txt002 + SPHERE CENTER 0.826871 0.0263827 -0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER 0.825102 0.00436945 0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER 0.84533 0.018173 0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER 0.823964 0.025051 0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER 0.806642 0.0125791 -0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER 0.805505 0.0332607 0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.808411 0.0345923 -0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER 0.828008 0.00570109 -0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER 0.829777 0.0277143 -0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.848237 0.0195047 -0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.841683 0.0665023 -0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER 0.840284 0.0454909 -0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER 0.856111 0.0473735 -0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.831823 0.0463379 -0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER 0.825856 0.0646197 -0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER 0.817395 0.0654667 -0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER 0.827255 0.0856311 -0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER 0.850144 0.0656554 -0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER 0.851543 0.0866667 -0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER 0.865971 0.0675379 -0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER 0.69376 -0.0133465 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.740325 -0.0440268 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.762259 -0.0417568 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.759495 -0.0345526 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.748937 -0.0216407 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.743089 -0.051231 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.729767 -0.0311149 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.721155 -0.053501 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.753646 -0.0641429 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.731712 -0.0664129 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.750882 -0.0569387 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.76531 0.0058253 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.782939 0.0179281 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.76531 0.0058253 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.759776 0.02648 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.782939 0.0179281 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.759776 0.02648 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.76531 0.0058253 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.788473 -0.00272662 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.770845 -0.0148294 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.770845 -0.0148294 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.721234 0.0272215 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.736829 0.0454452 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.742467 0.0297485 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.724354 0.046242 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.715595 0.0429182 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.70312 0.043715 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.7 0.0246945 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.733709 0.0264247 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.718114 0.00820099 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.739347 0.010728 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.668775 -0.0631985 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.669983 -0.0708196 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.690113 -0.0618185 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.671462 -0.0467378 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.648644 -0.0721997 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.650123 -0.0481178 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.647436 -0.0645786 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.667296 -0.0872804 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.666087 -0.0796593 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.687426 -0.0782793 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.649684 0.00804971 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.646718 0.0244627 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669336 0.016478 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.657124 0.0313903 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.627066 0.0160343 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.637471 0.022962 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.630031 -0.000378614 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.639278 0.00112207 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.642244 -0.0152909 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.661896 -0.00686255 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.62221 -0.0325183 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.600892 -0.0308513 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.62221 -0.0325183 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.616676 -0.0118635 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.600892 -0.0308513 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.616676 -0.0118635 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.62221 -0.0325183 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.606426 -0.051506 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.627745 -0.053173 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.627745 -0.053173 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.712851 -0.0845947 0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER 0.730141 -0.101422 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.736701 -0.0782041 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.725284 -0.0832945 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.706291 -0.107813 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.701434 -0.0896851 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.689001 -0.0909853 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.717709 -0.102723 0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER 0.700418 -0.0858949 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.724268 -0.0795043 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.666287 -0.0539145 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.655153 -0.0751594 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.671821 -0.0745692 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.649783 -0.0638711 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.649619 -0.0545047 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.644249 -0.0432164 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.660752 -0.0332597 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.671657 -0.0652028 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.682791 -0.0439578 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.688325 -0.0646126 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.737837 -0.0347427 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.752567 -0.0269197 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.732303 -0.014088 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.751574 -0.0144587 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.758102 -0.0475745 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.757108 -0.0351134 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.743371 -0.0553974 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.73883 -0.0472037 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.7241 -0.0550267 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.718566 -0.0343719 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.69376 -0.0133465 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.745859 -0.0646815 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.770032 -0.0684873 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.759394 -0.0481266 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.762305 -0.0507391 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.756497 -0.0850422 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.74877 -0.067294 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.732325 -0.0812364 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.753586 -0.0824297 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.729413 -0.0786239 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.742948 -0.062069 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.76531 0.0058253 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.782939 0.0179281 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.76531 0.0058253 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.759776 0.02648 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.782939 0.0179281 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.759776 0.02648 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.76531 0.0058253 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.788473 -0.00272662 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.770845 -0.0148294 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.770845 -0.0148294 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.737837 -0.0347427 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.758864 -0.0299763 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.757489 -0.0263144 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.745277 -0.0114021 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.739212 -0.0384047 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.725625 -0.0198304 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.718185 -0.043171 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.751424 -0.0533169 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.730397 -0.0580833 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.750049 -0.0496549 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.674309 -0.0838533 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.675276 -0.106805 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.694308 -0.091423 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.673094 -0.0875713 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.655278 -0.0992356 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.653095 -0.0800016 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.65431 -0.0762835 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.676491 -0.103087 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.675524 -0.0801352 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.695522 -0.0877049 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.666287 -0.0539145 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.666927 -0.0577732 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.68752 -0.0513875 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669407 -0.034894 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.645694 -0.0603001 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.648173 -0.0374209 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.645053 -0.0564414 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.663807 -0.0767937 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.663167 -0.072935 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.6844 -0.070408 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.62221 -0.0325183 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.600892 -0.0308513 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.62221 -0.0325183 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.616676 -0.0118635 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.600892 -0.0308513 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.616676 -0.0118635 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.62221 -0.0325183 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.606426 -0.051506 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.627745 -0.053173 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.627745 -0.053173 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.701782 -0.0432853 -0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.717566 -0.0544915 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.725632 -0.0368947 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.718734 -0.0588496 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.693716 -0.0608821 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.694884 -0.0652402 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.677932 -0.0496759 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.700615 -0.0389272 -0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.684831 -0.027721 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.708681 -0.0213304 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.649684 0.00804971 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.640422 0.0275193 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.644149 0.0287044 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.66342 0.0283337 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.645956 0.00686453 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.668955 0.00767898 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.655218 -0.012605 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.626685 0.00723527 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.635947 -0.0122343 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.630413 0.00842045 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.721234 0.0272215 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.725055 0.0280589 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.726768 0.00656677 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.70473 0.0172649 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.71952 0.0487136 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.699195 0.0379196 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.715699 0.0478762 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.741558 0.0380155 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.737738 0.0371781 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.743272 0.0165234 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.172546 0.643951 1.11022e-16 RAD 0.166667 + txt002 + SPHERE CENTER 0.281471 0.802608 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.30566 0.824035 -0.177765 RAD 0.0185185 + txt002 + SPHERE CENTER 0.302088 0.822021 -0.202114 RAD 0.00617284 + txt002 + SPHERE CENTER 0.298094 0.802598 -0.187402 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282758 0.821938 -0.186751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.309654 0.843459 -0.192477 RAD 0.00617284 + txt002 + SPHERE CENTER 0.290324 0.843375 -0.177114 RAD 0.00617284 + txt002 + SPHERE CENTER 0.313227 0.845472 -0.168128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.32499 0.824119 -0.193128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.328563 0.826132 -0.16878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.320997 0.804695 -0.178416 RAD 0.00617284 + txt002 + SPHERE CENTER 0.305221 0.752156 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.325175 0.741263 -0.169507 RAD 0.00617284 + txt002 + SPHERE CENTER 0.325981 0.765112 -0.163165 RAD 0.00617284 + txt002 + SPHERE CENTER 0.32493 0.747715 -0.145675 RAD 0.00617284 + txt002 + SPHERE CENTER 0.304415 0.728307 -0.166213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.304171 0.734759 -0.142381 RAD 0.00617284 + txt002 + SPHERE CENTER 0.284462 0.7392 -0.156576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.305466 0.745704 -0.183703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.285513 0.756597 -0.174066 RAD 0.00617284 + txt002 + SPHERE CENTER 0.306272 0.769553 -0.17736 RAD 0.00617284 + txt002 + SPHERE CENTER 0.241352 0.787796 -0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER 0.218449 0.785699 -0.180578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.223304 0.778718 -0.157397 RAD 0.00617284 + txt002 + SPHERE CENTER 0.22345 0.802677 -0.163362 RAD 0.00617284 + txt002 + SPHERE CENTER 0.236497 0.794777 -0.194773 RAD 0.00617284 + txt002 + SPHERE CENTER 0.241498 0.811756 -0.177557 RAD 0.00617284 + txt002 + SPHERE CENTER 0.2594 0.796874 -0.185788 RAD 0.00617284 + txt002 + SPHERE CENTER 0.236351 0.770818 -0.188808 RAD 0.00617284 + txt002 + SPHERE CENTER 0.259253 0.772915 -0.179823 RAD 0.00617284 + txt002 + SPHERE CENTER 0.241205 0.763837 -0.165627 RAD 0.00617284 + txt002 + SPHERE CENTER 0.28191 0.874487 -0.129006 RAD 0.0185185 + txt002 + SPHERE CENTER 0.292033 0.891539 -0.143718 RAD 0.00617284 + txt002 + SPHERE CENTER 0.305711 0.872763 -0.135349 RAD 0.00617284 + txt002 + SPHERE CENTER 0.28812 0.868678 -0.152187 RAD 0.00617284 + txt002 + SPHERE CENTER 0.268233 0.893263 -0.137375 RAD 0.00617284 + txt002 + SPHERE CENTER 0.264319 0.870402 -0.145845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.25811 0.876212 -0.122663 RAD 0.00617284 + txt002 + SPHERE CENTER 0.285824 0.897348 -0.120537 RAD 0.00617284 + txt002 + SPHERE CENTER 0.275701 0.880296 -0.105825 RAD 0.00617284 + txt002 + SPHERE CENTER 0.299501 0.878572 -0.112168 RAD 0.00617284 + txt002 + SPHERE CENTER 0.217602 0.838248 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.206363 0.860225 -0.122182 RAD 0.00617284 + txt002 + SPHERE CENTER 0.223536 0.854636 -0.105343 RAD 0.00617284 + txt002 + SPHERE CENTER 0.230102 0.858689 -0.128798 RAD 0.00617284 + txt002 + SPHERE CENTER 0.200429 0.843837 -0.139672 RAD 0.00617284 + txt002 + SPHERE CENTER 0.224168 0.842301 -0.146288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.211667 0.821861 -0.140323 RAD 0.00617284 + txt002 + SPHERE CENTER 0.193863 0.839784 -0.116217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.205101 0.817808 -0.116868 RAD 0.00617284 + txt002 + SPHERE CENTER 0.211035 0.834196 -0.0993785 RAD 0.00617284 + txt002 + SPHERE CENTER 0.257721 0.853061 -0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER 0.26204 0.87538 -0.0527151 RAD 0.00617284 + txt002 + SPHERE CENTER 0.280934 0.860805 -0.0590577 RAD 0.00617284 + txt002 + SPHERE CENTER 0.266856 0.87108 -0.0765474 RAD 0.00617284 + txt002 + SPHERE CENTER 0.238827 0.867636 -0.0560094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.243643 0.863337 -0.0798417 RAD 0.00617284 + txt002 + SPHERE CENTER 0.234508 0.845317 -0.0656463 RAD 0.00617284 + txt002 + SPHERE CENTER 0.252905 0.857361 -0.0385197 RAD 0.00617284 + txt002 + SPHERE CENTER 0.248586 0.835041 -0.0481565 RAD 0.00617284 + txt002 + SPHERE CENTER 0.271799 0.842785 -0.0448623 RAD 0.00617284 + txt002 + SPHERE CENTER 0.34578 0.838847 -0.117284 RAD 0.0185185 + txt002 + SPHERE CENTER 0.360404 0.851488 -0.132647 RAD 0.00617284 + txt002 + SPHERE CENTER 0.347059 0.832518 -0.141116 RAD 0.00617284 + txt002 + SPHERE CENTER 0.335865 0.853509 -0.1345 RAD 0.00617284 + txt002 + SPHERE CENTER 0.359125 0.857816 -0.108814 RAD 0.00617284 + txt002 + SPHERE CENTER 0.334587 0.859838 -0.110668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.344501 0.845176 -0.0934517 RAD 0.00617284 + txt002 + SPHERE CENTER 0.370319 0.836826 -0.115431 RAD 0.00617284 + txt002 + SPHERE CENTER 0.355695 0.824185 -0.100068 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356973 0.817857 -0.1239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.321591 0.817421 -0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER 0.340361 0.83071 -0.0416443 RAD 0.00617284 + txt002 + SPHERE CENTER 0.341208 0.822249 -0.0648253 RAD 0.00617284 + txt002 + SPHERE CENTER 0.325527 0.840365 -0.0588603 RAD 0.00617284 + txt002 + SPHERE CENTER 0.320744 0.825882 -0.0274488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.30591 0.835537 -0.0446649 RAD 0.00617284 + txt002 + SPHERE CENTER 0.301973 0.812593 -0.0364345 RAD 0.00617284 + txt002 + SPHERE CENTER 0.336425 0.807766 -0.0334138 RAD 0.00617284 + txt002 + SPHERE CENTER 0.317654 0.794477 -0.0423994 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337272 0.799305 -0.0565949 RAD 0.00617284 + txt002 + SPHERE CENTER 0.345341 0.766968 -0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.369945 0.768944 -0.10004 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356171 0.780624 -0.116879 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356172 0.788341 -0.093424 RAD 0.00617284 + txt002 + SPHERE CENTER 0.359115 0.755289 -0.0825505 RAD 0.00617284 + txt002 + SPHERE CENTER 0.345342 0.774685 -0.0759343 RAD 0.00617284 + txt002 + SPHERE CENTER 0.334511 0.753313 -0.0818993 RAD 0.00617284 + txt002 + SPHERE CENTER 0.359113 0.747572 -0.106005 RAD 0.00617284 + txt002 + SPHERE CENTER 0.33451 0.745596 -0.105354 RAD 0.00617284 + txt002 + SPHERE CENTER 0.34534 0.759252 -0.122844 RAD 0.00617284 + txt002 + SPHERE CENTER 0.358439 0.594141 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.408291 0.619127 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.411883 0.625955 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.396287 0.607547 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.390369 0.630791 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.423887 0.637535 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.402373 0.642371 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.420295 0.630706 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.429805 0.61429 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.426212 0.607462 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.414208 0.595882 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337042 0.638217 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.344865 0.652948 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.357326 0.651954 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.357697 0.632683 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.324581 0.639211 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337413 0.618946 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.316758 0.624481 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.324211 0.658482 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.316388 0.643752 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.336672 0.657489 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37761 0.665691 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.389713 0.68332 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.398265 0.660156 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37761 0.665691 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.369058 0.688854 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356956 0.671225 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356956 0.671225 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.389713 0.68332 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37761 0.665691 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.398265 0.660156 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.429687 0.57505 -0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER 0.452905 0.58161 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.434777 0.586467 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.436077 0.5989 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.447815 0.570193 -0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER 0.430987 0.587483 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.424596 0.563633 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.446515 0.55776 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.423296 0.5512 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.428387 0.562617 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399007 0.621614 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.41723 0.637209 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.418027 0.624734 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.401533 0.642848 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.39821 0.634089 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.382513 0.639728 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.379986 0.618494 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.414703 0.615976 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.39648 0.600381 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.4155 0.603501 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.379835 0.550064 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.396248 0.547099 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.403175 0.557504 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.388263 0.569716 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.372907 0.539659 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.364922 0.562276 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356494 0.542624 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.387819 0.527447 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.371406 0.530412 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.394747 0.537852 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.389119 0.547576 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.410169 0.541008 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.405866 0.564748 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.410472 0.548718 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.393422 0.523836 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.393725 0.531546 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.372372 0.530405 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.388816 0.539866 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.367766 0.546435 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.384513 0.563607 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.339267 0.522591 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.340934 0.501272 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.359921 0.517056 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.339267 0.522591 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.320279 0.506807 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.318612 0.528125 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.318612 0.528125 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.340934 0.501272 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.339267 0.522591 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.359921 0.517056 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.317871 0.566667 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.296626 0.555534 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.307914 0.550163 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.297216 0.572202 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.306582 0.572037 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.307172 0.588706 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.327827 0.583171 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31728 0.549999 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.338525 0.561133 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.328569 0.544629 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.172546 0.643951 -0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER 0.142305 0.674191 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.144155 0.692502 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.150298 0.696439 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.164554 0.682184 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.136163 0.670254 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.156561 0.659936 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER 0.134313 0.651943 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.121907 0.684509 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER 0.120057 0.666199 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.12805 0.688447 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER 0.100996 0.663122 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0847178 0.680265 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.104191 0.675047 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.107387 0.686972 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0815225 0.66834 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER 0.104191 0.675047 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0978007 0.651197 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0783272 0.656415 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0946054 0.639272 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0978007 0.651197 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.153374 0.715501 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.160081 0.738169 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.177224 0.721891 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.165299 0.718696 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.136231 0.731779 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.141449 0.712305 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.129524 0.70911 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.148156 0.734974 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.141449 0.712305 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.165299 0.718696 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.213855 0.655019 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.213517 0.662308 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.194382 0.649801 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER 0.198584 0.673065 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.23299 0.667526 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER 0.218058 0.678283 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.233329 0.660237 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER 0.228788 0.644262 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.229127 0.636974 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.209653 0.631756 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.224924 0.696329 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.23918 0.710584 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER 0.233654 0.687599 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.216195 0.705059 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.23045 0.719314 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.207465 0.713788 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.216195 0.705059 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.24791 0.701855 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.233654 0.687599 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.242384 0.678869 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.244096 0.624779 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.266765 0.631486 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.247291 0.636704 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.250487 0.648629 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.26357 0.619561 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.247291 0.636704 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.240901 0.612854 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.260374 0.607636 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.237705 0.600929 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.240901 0.612854 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.161477 0.602641 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.162741 0.579817 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER 0.179523 0.58737 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.156259 0.583168 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER 0.144695 0.595088 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.138214 0.598439 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.143431 0.617912 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.167958 0.59929 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.166695 0.622115 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER 0.184741 0.606843 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.191718 0.5724 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.208861 0.556122 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.215568 0.578791 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.203643 0.575596 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.185011 0.549732 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.179793 0.569205 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.167868 0.56601 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.196936 0.552927 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER 0.179793 0.569205 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.203643 0.575596 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.120168 0.591572 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.105912 0.577317 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.128897 0.582843 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.111438 0.600302 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0971825 0.586046 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.102708 0.609032 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.111438 0.600302 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.114642 0.568587 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.128897 0.582843 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.137627 0.574113 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0955788 0.852418 9.1293e-17 RAD 0.0555556 + txt002 + SPHERE CENTER 0.11107 0.922609 -0.0178949 RAD 0.0185185 + txt002 + SPHERE CENTER 0.122151 0.937225 -0.0344251 RAD 0.00617284 + txt002 + SPHERE CENTER 0.131874 0.915202 -0.0289382 RAD 0.00617284 + txt002 + SPHERE CENTER 0.11086 0.916553 -0.0418311 RAD 0.00617284 + txt002 + SPHERE CENTER 0.101346 0.944632 -0.0233819 RAD 0.00617284 + txt002 + SPHERE CENTER 0.090055 0.92396 -0.0307879 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0902645 0.930016 -0.00685171 RAD 0.00617284 + txt002 + SPHERE CENTER 0.12236 0.943281 -0.0104889 RAD 0.00617284 + txt002 + SPHERE CENTER 0.111279 0.928665 0.00604126 RAD 0.00617284 + txt002 + SPHERE CENTER 0.132084 0.921258 -0.00500196 RAD 0.00617284 + txt002 + SPHERE CENTER 0.164775 0.877966 0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER 0.182656 0.890926 -0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER 0.167676 0.876622 -0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER 0.159019 0.897331 -0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER 0.179755 0.89227 0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER 0.156118 0.898675 0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.161874 0.87931 0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.188412 0.871561 0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER 0.17053 0.8586 0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER 0.173431 0.857256 -0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.135698 0.867231 -0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER 0.134634 0.873196 -0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER 0.11765 0.858152 -0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER 0.117797 0.882112 -0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER 0.152682 0.882275 -0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.135845 0.89119 -0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER 0.153747 0.876309 -0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER 0.152536 0.858315 -0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER 0.1536 0.852349 -0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER 0.135552 0.843271 -0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0418734 0.897062 -0.0246914 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0359958 0.920407 -0.0301783 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0511067 0.915603 -0.0112511 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0588574 0.912106 -0.0344321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0267625 0.901866 -0.0436186 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0496241 0.893565 -0.0478724 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0326401 0.878521 -0.0381316 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0190117 0.905363 -0.0204376 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0248894 0.882018 -0.0149506 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0341227 0.900559 -0.00151032 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0665023 0.841683 -0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0454909 0.840284 -0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0463379 0.831823 -0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0473735 0.856111 -0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0656554 0.850144 -0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0675379 0.865971 -0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0866667 0.851543 -0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0646197 0.825856 -0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0856311 0.827255 -0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0654667 0.817395 -0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0263827 0.826871 -0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER 0.00436945 0.825102 0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER 0.025051 0.823964 0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER 0.018173 0.84533 0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00570109 0.828008 -0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0195047 0.848237 -0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0277143 0.829777 -0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0125791 0.806642 -0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0345923 0.808411 -0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0332607 0.805505 0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0709499 0.907797 0.0425863 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0752104 0.930963 0.0499923 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0941344 0.915684 0.0457385 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0806562 0.924191 0.0268805 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0520258 0.923076 0.0468401 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0574717 0.916304 0.0237283 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0477654 0.89991 0.0394341 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0655041 0.914568 0.065698 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0612436 0.891402 0.058292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0844281 0.899289 0.0614442 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0554592 0.837606 0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0523913 0.842832 0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0750766 0.842434 0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0593957 0.86055 0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0327739 0.838004 0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0397783 0.855722 0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0358417 0.832778 0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0484547 0.819888 0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0515226 0.814662 0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER 0.07114 0.81949 0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.124655 0.863153 0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER 0.141535 0.875744 0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER 0.146389 0.868763 0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER 0.129819 0.88655 0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.119801 0.870135 0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER 0.108085 0.880941 0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER 0.102922 0.857544 0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER 0.136371 0.852347 0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER 0.119492 0.839756 0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER 0.141225 0.845366 0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0133465 0.69376 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.0646815 0.745859 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0684873 0.770032 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0507391 0.762305 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0481266 0.759394 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0824297 0.753586 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.062069 0.742948 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0786239 0.729413 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0850422 0.756497 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0812364 0.732325 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.067294 0.74877 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0347427 0.737837 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0299763 0.758864 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0114021 0.745277 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0263144 0.757489 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0533169 0.751424 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0496549 0.750049 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0580833 0.730397 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0384047 0.739212 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.043171 0.718185 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0198304 0.725625 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0058253 0.76531 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0179281 0.782939 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.02648 0.759776 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0058253 0.76531 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00272662 0.788473 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0148294 0.770845 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0148294 0.770845 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0179281 0.782939 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0058253 0.76531 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.02648 0.759776 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0432853 0.701782 -0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0544915 0.717566 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0588496 0.718734 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0368947 0.725632 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0389272 0.700615 -0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0213304 0.708681 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.027721 0.684831 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0608821 0.693716 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0496759 0.677932 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0652402 0.694884 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0272215 0.721234 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0280589 0.725055 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0172649 0.70473 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00656677 0.726768 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0380155 0.741558 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0165234 0.743272 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0371781 0.737738 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0487136 0.71952 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0478762 0.715699 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0379196 0.699195 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00804971 0.649684 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0275193 0.640422 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0283337 0.66342 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0287044 0.644149 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00723527 0.626685 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00842045 0.630413 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0122343 0.635947 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00686453 0.645956 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.012605 0.655218 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00767898 0.668955 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0838533 0.674309 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.106805 0.675276 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0875713 0.673094 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.091423 0.694308 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.103087 0.676491 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0877049 0.695522 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0801352 0.675524 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0992356 0.655278 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0762835 0.65431 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0800016 0.653095 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0325183 0.62221 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0308513 0.600892 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0118635 0.616676 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0325183 0.62221 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.051506 0.606426 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.053173 0.627745 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.053173 0.627745 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0308513 0.600892 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0325183 0.62221 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0118635 0.616676 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0539145 0.666287 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0577732 0.666927 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.034894 0.669407 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0513875 0.68752 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0767937 0.663807 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.070408 0.6844 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.072935 0.663167 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0603001 0.645694 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0564414 0.645053 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0374209 0.648173 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0133465 0.69376 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.0440268 0.740325 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0417568 0.762259 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0216407 0.748937 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0345526 0.759495 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0641429 0.753646 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0569387 0.750882 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0664129 0.731712 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.051231 0.743089 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.053501 0.721155 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0311149 0.729767 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0272215 0.721234 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0454452 0.736829 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.046242 0.724354 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0297485 0.742467 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0264247 0.733709 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.010728 0.739347 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00820099 0.718114 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0429182 0.715595 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0246945 0.7 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.043715 0.70312 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0058253 0.76531 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0179281 0.782939 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.02648 0.759776 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0058253 0.76531 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00272662 0.788473 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0148294 0.770845 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0148294 0.770845 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0179281 0.782939 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0058253 0.76531 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.02648 0.759776 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0845947 0.712851 0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER -0.101422 0.730141 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0832945 0.725284 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0782041 0.736701 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.102723 0.717709 0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0795043 0.724268 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0858949 0.700418 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.107813 0.706291 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0909853 0.689001 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0896851 0.701434 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0347427 0.737837 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0269197 0.752567 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0144587 0.751574 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.014088 0.732303 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0472037 0.73883 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0343719 0.718566 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0550267 0.7241 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0475745 0.758102 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0553974 0.743371 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0351134 0.757108 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0539145 0.666287 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0751594 0.655153 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0638711 0.649783 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0745692 0.671821 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0652028 0.671657 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0646126 0.688325 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0439578 0.682791 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0545047 0.649619 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0332597 0.660752 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0432164 0.644249 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0631985 0.668775 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0708196 0.669983 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0467378 0.671462 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0618185 0.690113 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0872804 0.667296 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0782793 0.687426 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0796593 0.666087 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0721997 0.648644 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0645786 0.647436 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0481178 0.650123 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0325183 0.62221 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0308513 0.600892 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0118635 0.616676 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0325183 0.62221 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.051506 0.606426 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.053173 0.627745 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.053173 0.627745 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0308513 0.600892 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0325183 0.62221 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0118635 0.616676 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00804971 0.649684 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0244627 0.646718 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0313903 0.657124 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.016478 0.669336 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00112207 0.639278 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00686255 0.661896 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0152909 0.642244 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0160343 0.627066 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.000378614 0.630031 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.022962 0.637471 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.281471 0.802608 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.329459 0.858698 0.104938 RAD 0.0185185 + txt002 + SPHERE CENTER 0.34259 0.872345 0.0890951 RAD 0.00617284 + txt002 + SPHERE CENTER 0.338969 0.848329 0.0846485 RAD 0.00617284 + txt002 + SPHERE CENTER 0.32016 0.86421 0.0827387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.333079 0.882715 0.109385 RAD 0.00617284 + txt002 + SPHERE CENTER 0.310649 0.87458 0.103028 RAD 0.00617284 + txt002 + SPHERE CENTER 0.319948 0.869068 0.125228 RAD 0.00617284 + txt002 + SPHERE CENTER 0.351888 0.866833 0.111295 RAD 0.00617284 + txt002 + SPHERE CENTER 0.338757 0.853186 0.127138 RAD 0.00617284 + txt002 + SPHERE CENTER 0.348268 0.842817 0.106848 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337088 0.798572 0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER 0.346884 0.808673 0.0420622 RAD 0.00617284 + txt002 + SPHERE CENTER 0.322361 0.807762 0.044793 RAD 0.00617284 + txt002 + SPHERE CENTER 0.335792 0.82298 0.0588533 RAD 0.00617284 + txt002 + SPHERE CENTER 0.361611 0.799483 0.0596212 RAD 0.00617284 + txt002 + SPHERE CENTER 0.350519 0.81379 0.0764123 RAD 0.00617284 + txt002 + SPHERE CENTER 0.351815 0.789382 0.079911 RAD 0.00617284 + txt002 + SPHERE CENTER 0.34818 0.784265 0.0455609 RAD 0.00617284 + txt002 + SPHERE CENTER 0.338384 0.774164 0.0658506 RAD 0.00617284 + txt002 + SPHERE CENTER 0.323657 0.783355 0.0482916 RAD 0.00617284 + txt002 + SPHERE CENTER 0.280879 0.845371 0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER 0.291048 0.849036 0.0284303 RAD 0.00617284 + txt002 + SPHERE CENTER 0.304882 0.840755 0.0471312 RAD 0.00617284 + txt002 + SPHERE CENTER 0.287867 0.826067 0.0369125 RAD 0.00617284 + txt002 + SPHERE CENTER 0.267046 0.853652 0.0319289 RAD 0.00617284 + txt002 + SPHERE CENTER 0.263865 0.830683 0.0404111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.256877 0.849987 0.0541285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.28406 0.868341 0.0421477 RAD 0.00617284 + txt002 + SPHERE CENTER 0.273891 0.864676 0.0643473 RAD 0.00617284 + txt002 + SPHERE CENTER 0.297894 0.86006 0.0608487 RAD 0.00617284 + txt002 + SPHERE CENTER 0.273842 0.862735 0.153697 RAD 0.0185185 + txt002 + SPHERE CENTER 0.282313 0.885497 0.158144 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29787 0.867718 0.150967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.281455 0.876946 0.134996 RAD 0.00617284 + txt002 + SPHERE CENTER 0.258284 0.880514 0.160875 RAD 0.00617284 + txt002 + SPHERE CENTER 0.257427 0.871963 0.137727 RAD 0.00617284 + txt002 + SPHERE CENTER 0.249813 0.857752 0.156428 RAD 0.00617284 + txt002 + SPHERE CENTER 0.274699 0.871286 0.176845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.266228 0.848523 0.172398 RAD 0.00617284 + txt002 + SPHERE CENTER 0.290257 0.853506 0.169668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.225263 0.849407 0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.21889 0.873186 0.0974792 RAD 0.00617284 + txt002 + SPHERE CENTER 0.236437 0.866351 0.113449 RAD 0.00617284 + txt002 + SPHERE CENTER 0.240865 0.865588 0.0891702 RAD 0.00617284 + txt002 + SPHERE CENTER 0.207715 0.856242 0.0834188 RAD 0.00617284 + txt002 + SPHERE CENTER 0.22969 0.848644 0.0751099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.214088 0.832464 0.0853287 RAD 0.00617284 + txt002 + SPHERE CENTER 0.203288 0.857005 0.107698 RAD 0.00617284 + txt002 + SPHERE CENTER 0.20966 0.833227 0.109608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.220835 0.850171 0.123668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.225855 0.806645 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.21762 0.818054 0.18016 RAD 0.00617284 + txt002 + SPHERE CENTER 0.241754 0.813612 0.177429 RAD 0.00617284 + txt002 + SPHERE CENTER 0.230661 0.83061 0.163369 RAD 0.00617284 + txt002 + SPHERE CENTER 0.20172 0.811087 0.162601 RAD 0.00617284 + txt002 + SPHERE CENTER 0.214761 0.823642 0.14581 RAD 0.00617284 + txt002 + SPHERE CENTER 0.209955 0.799677 0.142311 RAD 0.00617284 + txt002 + SPHERE CENTER 0.212813 0.794089 0.176661 RAD 0.00617284 + txt002 + SPHERE CENTER 0.221048 0.78268 0.156372 RAD 0.00617284 + txt002 + SPHERE CENTER 0.236948 0.789647 0.173931 RAD 0.00617284 + txt002 + SPHERE CENTER 0.330051 0.815936 0.165419 RAD 0.0185185 + txt002 + SPHERE CENTER 0.350165 0.828769 0.171776 RAD 0.00617284 + txt002 + SPHERE CENTER 0.347547 0.820583 0.148628 RAD 0.00617284 + txt002 + SPHERE CENTER 0.333232 0.838905 0.156937 RAD 0.00617284 + txt002 + SPHERE CENTER 0.332668 0.824121 0.188567 RAD 0.00617284 + txt002 + SPHERE CENTER 0.315735 0.834258 0.173728 RAD 0.00617284 + txt002 + SPHERE CENTER 0.312554 0.811288 0.182211 RAD 0.00617284 + txt002 + SPHERE CENTER 0.346984 0.805799 0.180258 RAD 0.00617284 + txt002 + SPHERE CENTER 0.32687 0.792966 0.173902 RAD 0.00617284 + txt002 + SPHERE CENTER 0.344366 0.797614 0.157111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282063 0.759846 0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER 0.29233 0.756464 0.193792 RAD 0.00617284 + txt002 + SPHERE CENTER 0.305929 0.765125 0.175091 RAD 0.00617284 + txt002 + SPHERE CENTER 0.288514 0.779336 0.18531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.268464 0.751185 0.190293 RAD 0.00617284 + txt002 + SPHERE CENTER 0.264649 0.774058 0.181811 RAD 0.00617284 + txt002 + SPHERE CENTER 0.258198 0.754567 0.168094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.285879 0.736973 0.180075 RAD 0.00617284 + txt002 + SPHERE CENTER 0.275612 0.740355 0.157875 RAD 0.00617284 + txt002 + SPHERE CENTER 0.299478 0.745634 0.161374 RAD 0.00617284 + txt002 + SPHERE CENTER 0.33768 0.75581 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.362219 0.753851 0.124743 RAD 0.00617284 + txt002 + SPHERE CENTER 0.352319 0.76987 0.108773 RAD 0.00617284 + txt002 + SPHERE CENTER 0.350765 0.774086 0.133052 RAD 0.00617284 + txt002 + SPHERE CENTER 0.347581 0.739791 0.138803 RAD 0.00617284 + txt002 + SPHERE CENTER 0.336127 0.760026 0.147112 RAD 0.00617284 + txt002 + SPHERE CENTER 0.323042 0.74175 0.136894 RAD 0.00617284 + txt002 + SPHERE CENTER 0.349134 0.735575 0.114524 RAD 0.00617284 + txt002 + SPHERE CENTER 0.324595 0.737534 0.112614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.339233 0.751594 0.0985541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.172546 0.643951 0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER 0.202787 0.674191 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.219248 0.690652 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER 0.223862 0.677807 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.206403 0.695267 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.198172 0.687036 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.185327 0.691651 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.181711 0.670575 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.215632 0.669577 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.199171 0.653116 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.220246 0.656732 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.244096 0.663122 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.261725 0.675225 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.244096 0.663122 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.238562 0.683777 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.261725 0.675225 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.238562 0.683777 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.244096 0.663122 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.267259 0.65457 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.249631 0.642468 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.249631 0.642468 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.191718 0.715501 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.203821 0.733129 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.212373 0.709966 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.191718 0.715501 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.183166 0.738664 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.171063 0.721035 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.171063 0.721035 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.203821 0.733129 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.191718 0.715501 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.212373 0.709966 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.131237 0.655019 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.12881 0.668451 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.151296 0.662426 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.137627 0.678869 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.108751 0.661044 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER 0.117567 0.671463 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.111177 0.647613 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.12242 0.644601 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.124846 0.631169 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.144906 0.638576 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.120168 0.696329 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.115992 0.720665 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.135288 0.711449 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.135288 0.711449 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.100872 0.705544 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.120168 0.696329 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.105047 0.681209 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.100872 0.705544 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.105047 0.681209 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.120168 0.696329 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.100996 0.624779 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0796777 0.626446 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.100996 0.624779 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0954616 0.645433 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0796777 0.626446 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0954616 0.645433 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.100996 0.624779 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0852121 0.605791 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.10653 0.604124 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.10653 0.604124 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.183615 0.602641 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.197046 0.600215 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.207465 0.609032 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.191021 0.622701 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.173196 0.593824 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.167171 0.61631 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.159765 0.596251 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.18964 0.580155 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER 0.176209 0.582581 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.200059 0.588972 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.153374 0.5724 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.155041 0.551082 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.174029 0.566866 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.153374 0.5724 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.134387 0.556617 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.13272 0.577935 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.13272 0.577935 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.155041 0.551082 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.153374 0.5724 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.174029 0.566866 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.224924 0.591572 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.24926 0.587397 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.240045 0.606693 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.240045 0.606693 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.23414 0.572277 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.224924 0.591572 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.209804 0.576452 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.23414 0.572277 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.209804 0.576452 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.224924 0.591572 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.358439 0.594141 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.428945 0.613592 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.448155 0.626191 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.43276 0.614455 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.42519 0.634643 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.44434 0.625328 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.421375 0.63378 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.42513 0.612729 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.45191 0.60514 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.4327 0.592541 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.436515 0.593404 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399007 0.621614 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.399844 0.625435 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.38905 0.60511 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.378352 0.627149 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.409801 0.641939 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.388308 0.643653 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.408963 0.638118 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.420499 0.619901 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.419661 0.61608 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.409705 0.599576 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37761 0.665691 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.389713 0.68332 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.398265 0.660156 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37761 0.665691 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.369058 0.688854 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356956 0.671225 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356956 0.671225 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.389713 0.68332 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37761 0.665691 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.398265 0.660156 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.388377 0.586119 0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.405974 0.594185 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.410332 0.593017 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.394768 0.609969 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.384019 0.587286 0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.372813 0.60307 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.366422 0.57922 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399584 0.570335 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.381987 0.562269 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.403942 0.569167 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337042 0.638217 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.341809 0.659244 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.360383 0.645657 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.345471 0.65787 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.318468 0.651804 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.32213 0.65043 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.313702 0.630777 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.33338 0.639592 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.328614 0.618565 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.351955 0.626005 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.317871 0.566667 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.314012 0.567308 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.336891 0.569787 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.320398 0.587901 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.294991 0.564188 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.301377 0.584781 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29885 0.563547 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.311485 0.546074 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.315344 0.545434 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.334364 0.548554 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.409774 0.542042 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.433888 0.53788 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.426423 0.55574 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.423551 0.558395 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.417238 0.524182 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.406901 0.544697 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.393124 0.528344 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.42011 0.521526 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.395996 0.525689 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.412646 0.539387 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.339267 0.522591 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.340934 0.501272 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.359921 0.517056 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.339267 0.522591 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.320279 0.506807 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.318612 0.528125 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.318612 0.528125 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.340934 0.501272 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.339267 0.522591 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.359921 0.517056 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.379835 0.550064 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.399304 0.540802 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.400119 0.563801 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.400489 0.54453 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37902 0.527065 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.380205 0.530793 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.359551 0.536327 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37865 0.546337 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.35918 0.555599 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.379464 0.569335 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.371785 0.0996195 0.544331 RAD 0.166667 + txt002 + SPHERE CENTER -0.393621 0.220501 0.729516 RAD 0.0555556 + txt002 + SPHERE CENTER -0.368601 0.279642 0.766439 RAD 0.0185185 + txt002 + SPHERE CENTER -0.354293 0.299716 0.765035 RAD 0.00617284 + txt002 + SPHERE CENTER -0.347717 0.279022 0.753281 RAD 0.00617284 + txt002 + SPHERE CENTER -0.366989 0.292196 0.745238 RAD 0.00617284 + txt002 + SPHERE CENTER -0.375177 0.300337 0.778193 RAD 0.00617284 + txt002 + SPHERE CENTER -0.387873 0.292817 0.758396 RAD 0.00617284 + txt002 + SPHERE CENTER -0.389485 0.280263 0.779597 RAD 0.00617284 + txt002 + SPHERE CENTER -0.355904 0.287162 0.786236 RAD 0.00617284 + txt002 + SPHERE CENTER -0.370213 0.267088 0.787639 RAD 0.00617284 + txt002 + SPHERE CENTER -0.349329 0.266468 0.774481 RAD 0.00617284 + txt002 + SPHERE CENTER -0.321889 0.238665 0.726118 RAD 0.0185185 + txt002 + SPHERE CENTER -0.304702 0.250544 0.71296 RAD 0.00617284 + txt002 + SPHERE CENTER -0.32307 0.238717 0.701455 RAD 0.00617284 + txt002 + SPHERE CENTER -0.327715 0.259421 0.714081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.30352 0.250492 0.737623 RAD 0.00617284 + txt002 + SPHERE CENTER -0.326533 0.259369 0.738744 RAD 0.00617284 + txt002 + SPHERE CENTER -0.320707 0.238612 0.750781 RAD 0.00617284 + txt002 + SPHERE CENTER -0.298875 0.229788 0.724997 RAD 0.00617284 + txt002 + SPHERE CENTER -0.316063 0.217908 0.738155 RAD 0.00617284 + txt002 + SPHERE CENTER -0.317244 0.21796 0.713492 RAD 0.00617284 + txt002 + SPHERE CENTER -0.372464 0.281062 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER -0.362978 0.289441 0.671279 RAD 0.00617284 + txt002 + SPHERE CENTER -0.35549 0.267771 0.680442 RAD 0.00617284 + txt002 + SPHERE CENTER -0.378255 0.270044 0.671155 RAD 0.00617284 + txt002 + SPHERE CENTER -0.379952 0.302733 0.683315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.395229 0.283335 0.683192 RAD 0.00617284 + txt002 + SPHERE CENTER -0.389438 0.294353 0.704516 RAD 0.00617284 + txt002 + SPHERE CENTER -0.357187 0.30046 0.692603 RAD 0.00617284 + txt002 + SPHERE CENTER -0.366673 0.29208 0.713804 RAD 0.00617284 + txt002 + SPHERE CENTER -0.349699 0.278789 0.701767 RAD 0.00617284 + txt002 + SPHERE CENTER -0.440333 0.261479 0.769837 RAD 0.0185185 + txt002 + SPHERE CENTER -0.443285 0.282991 0.781591 RAD 0.00617284 + txt002 + SPHERE CENTER -0.421181 0.271991 0.781342 RAD 0.00617284 + txt002 + SPHERE CENTER -0.4302 0.282046 0.760673 RAD 0.00617284 + txt002 + SPHERE CENTER -0.462437 0.27248 0.770086 RAD 0.00617284 + txt002 + SPHERE CENTER -0.449353 0.271534 0.749168 RAD 0.00617284 + txt002 + SPHERE CENTER -0.459485 0.250967 0.758332 RAD 0.00617284 + txt002 + SPHERE CENTER -0.453417 0.262424 0.790755 RAD 0.00617284 + txt002 + SPHERE CENTER -0.450466 0.240911 0.779001 RAD 0.00617284 + txt002 + SPHERE CENTER -0.431313 0.251423 0.790506 RAD 0.00617284 + txt002 + SPHERE CENTER -0.444196 0.262898 0.695877 RAD 0.0185185 + txt002 + SPHERE CENTER -0.449273 0.285685 0.687835 RAD 0.00617284 + txt002 + SPHERE CENTER -0.436139 0.282528 0.708504 RAD 0.00617284 + txt002 + SPHERE CENTER -0.426189 0.27701 0.68659 RAD 0.00617284 + txt002 + SPHERE CENTER -0.45733 0.266055 0.675209 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434246 0.257381 0.673964 RAD 0.00617284 + txt002 + SPHERE CENTER -0.452254 0.243269 0.683251 RAD 0.00617284 + txt002 + SPHERE CENTER -0.46728 0.271573 0.697123 RAD 0.00617284 + txt002 + SPHERE CENTER -0.462204 0.248787 0.705165 RAD 0.00617284 + txt002 + SPHERE CENTER -0.454146 0.268416 0.717791 RAD 0.00617284 + txt002 + SPHERE CENTER -0.465353 0.202338 0.732914 RAD 0.0185185 + txt002 + SPHERE CENTER -0.486123 0.204606 0.746073 RAD 0.00617284 + txt002 + SPHERE CENTER -0.464339 0.202946 0.757577 RAD 0.00617284 + txt002 + SPHERE CENTER -0.470107 0.223366 0.744951 RAD 0.00617284 + txt002 + SPHERE CENTER -0.487137 0.203998 0.72141 RAD 0.00617284 + txt002 + SPHERE CENTER -0.471122 0.222757 0.720288 RAD 0.00617284 + txt002 + SPHERE CENTER -0.466367 0.201729 0.708251 RAD 0.00617284 + txt002 + SPHERE CENTER -0.481368 0.183578 0.734036 RAD 0.00617284 + txt002 + SPHERE CENTER -0.460599 0.18131 0.720878 RAD 0.00617284 + txt002 + SPHERE CENTER -0.459584 0.181918 0.745541 RAD 0.00617284 + txt002 + SPHERE CENTER -0.389758 0.219082 0.803476 RAD 0.0185185 + txt002 + SPHERE CENTER -0.378635 0.228779 0.823273 RAD 0.00617284 + txt002 + SPHERE CENTER -0.365937 0.225483 0.802355 RAD 0.00617284 + txt002 + SPHERE CENTER -0.383364 0.24293 0.8036 RAD 0.00617284 + txt002 + SPHERE CENTER -0.402455 0.222377 0.824394 RAD 0.00617284 + txt002 + SPHERE CENTER -0.407185 0.236529 0.804721 RAD 0.00617284 + txt002 + SPHERE CENTER -0.413578 0.21268 0.804597 RAD 0.00617284 + txt002 + SPHERE CENTER -0.385029 0.20493 0.823149 RAD 0.00617284 + txt002 + SPHERE CENTER -0.396152 0.195233 0.803352 RAD 0.00617284 + txt002 + SPHERE CENTER -0.372331 0.201634 0.802231 RAD 0.00617284 + txt002 + SPHERE CENTER -0.414778 0.15994 0.766553 RAD 0.0185185 + txt002 + SPHERE CENTER -0.412573 0.147477 0.787754 RAD 0.00617284 + txt002 + SPHERE CENTER -0.39322 0.15977 0.77859 RAD 0.00617284 + txt002 + SPHERE CENTER -0.412448 0.172167 0.787878 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434131 0.147647 0.775717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434006 0.172338 0.775841 RAD 0.00617284 + txt002 + SPHERE CENTER -0.436336 0.16011 0.754517 RAD 0.00617284 + txt002 + SPHERE CENTER -0.414903 0.13525 0.766429 RAD 0.00617284 + txt002 + SPHERE CENTER -0.417108 0.147713 0.745229 RAD 0.00617284 + txt002 + SPHERE CENTER -0.39555 0.147543 0.757266 RAD 0.00617284 + txt002 + SPHERE CENTER -0.343046 0.178104 0.763155 RAD 0.0185185 + txt002 + SPHERE CENTER -0.319723 0.177083 0.771198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.325124 0.189464 0.750529 RAD 0.00617284 + txt002 + SPHERE CENTER -0.332294 0.198298 0.772443 RAD 0.00617284 + txt002 + SPHERE CENTER -0.337645 0.165722 0.783824 RAD 0.00617284 + txt002 + SPHERE CENTER -0.350216 0.186938 0.785069 RAD 0.00617284 + txt002 + SPHERE CENTER -0.360967 0.166743 0.775781 RAD 0.00617284 + txt002 + SPHERE CENTER -0.330475 0.156889 0.76191 RAD 0.00617284 + txt002 + SPHERE CENTER -0.353797 0.157909 0.753867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.335876 0.16927 0.741241 RAD 0.00617284 + txt002 + SPHERE CENTER -0.191247 0.166275 0.655442 RAD 0.0555556 + txt002 + SPHERE CENTER -0.130089 0.20793 0.652044 RAD 0.0185185 + txt002 + SPHERE CENTER -0.115471 0.221102 0.637128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.126388 0.200597 0.628759 RAD 0.00617284 + txt002 + SPHERE CENTER -0.13987 0.220766 0.633356 RAD 0.00617284 + txt002 + SPHERE CENTER -0.119172 0.228435 0.660413 RAD 0.00617284 + txt002 + SPHERE CENTER -0.143571 0.228099 0.656641 RAD 0.00617284 + txt002 + SPHERE CENTER -0.13379 0.215264 0.675329 RAD 0.00617284 + txt002 + SPHERE CENTER -0.10569 0.208266 0.655816 RAD 0.00617284 + txt002 + SPHERE CENTER -0.120308 0.195095 0.670732 RAD 0.00617284 + txt002 + SPHERE CENTER -0.116607 0.187762 0.647447 RAD 0.00617284 + txt002 + SPHERE CENTER -0.154295 0.172673 0.591563 RAD 0.0185185 + txt002 + SPHERE CENTER -0.15554 0.180792 0.568278 RAD 0.00617284 + txt002 + SPHERE CENTER -0.17557 0.171251 0.579113 RAD 0.00617284 + txt002 + SPHERE CENTER -0.166926 0.19323 0.586315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.134265 0.182215 0.580727 RAD 0.00617284 + txt002 + SPHERE CENTER -0.145651 0.194652 0.598764 RAD 0.00617284 + txt002 + SPHERE CENTER -0.133019 0.174096 0.604012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.142909 0.160236 0.573526 RAD 0.00617284 + txt002 + SPHERE CENTER -0.141663 0.152117 0.596811 RAD 0.00617284 + txt002 + SPHERE CENTER -0.162939 0.150694 0.584361 RAD 0.00617284 + txt002 + SPHERE CENTER -0.192135 0.230419 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.18209 0.243049 0.599717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.168159 0.227721 0.613157 RAD 0.00617284 + txt002 + SPHERE CENTER -0.185251 0.218634 0.597829 RAD 0.00617284 + txt002 + SPHERE CENTER -0.206066 0.245747 0.604965 RAD 0.00617284 + txt002 + SPHERE CENTER -0.209227 0.221332 0.603077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.216111 0.233117 0.623653 RAD 0.00617284 + txt002 + SPHERE CENTER -0.188974 0.254834 0.620293 RAD 0.00617284 + txt002 + SPHERE CENTER -0.199019 0.242204 0.638981 RAD 0.00617284 + txt002 + SPHERE CENTER -0.175043 0.239506 0.633733 RAD 0.00617284 + txt002 + SPHERE CENTER -0.167041 0.201532 0.715923 RAD 0.0185185 + txt002 + SPHERE CENTER -0.151829 0.219088 0.724292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.14514 0.205084 0.705088 RAD 0.00617284 + txt002 + SPHERE CENTER -0.163068 0.221861 0.702483 RAD 0.00617284 + txt002 + SPHERE CENTER -0.173729 0.215537 0.735128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.184969 0.218309 0.713318 RAD 0.00617284 + txt002 + SPHERE CENTER -0.188942 0.197981 0.726759 RAD 0.00617284 + txt002 + SPHERE CENTER -0.155801 0.19876 0.737733 RAD 0.00617284 + txt002 + SPHERE CENTER -0.171014 0.181204 0.729364 RAD 0.00617284 + txt002 + SPHERE CENTER -0.149113 0.184756 0.718528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.229087 0.224021 0.682285 RAD 0.0185185 + txt002 + SPHERE CENTER -0.22829 0.248268 0.686881 RAD 0.00617284 + txt002 + SPHERE CENTER -0.207937 0.234532 0.689486 RAD 0.00617284 + txt002 + SPHERE CENTER -0.216949 0.2391 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER -0.249439 0.237756 0.67968 RAD 0.00617284 + txt002 + SPHERE CENTER -0.238098 0.228589 0.659755 RAD 0.00617284 + txt002 + SPHERE CENTER -0.250236 0.213509 0.675083 RAD 0.00617284 + txt002 + SPHERE CENTER -0.240428 0.233189 0.702209 RAD 0.00617284 + txt002 + SPHERE CENTER -0.241225 0.208942 0.697613 RAD 0.00617284 + txt002 + SPHERE CENTER -0.220075 0.219453 0.704814 RAD 0.00617284 + txt002 + SPHERE CENTER -0.228199 0.159877 0.719322 RAD 0.0185185 + txt002 + SPHERE CENTER -0.229756 0.167942 0.742607 RAD 0.00617284 + txt002 + SPHERE CENTER -0.207683 0.16569 0.731771 RAD 0.00617284 + txt002 + SPHERE CENTER -0.223214 0.183484 0.72457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.250271 0.162129 0.730157 RAD 0.00617284 + txt002 + SPHERE CENTER -0.243729 0.177671 0.71212 RAD 0.00617284 + txt002 + SPHERE CENTER -0.248714 0.154064 0.706872 RAD 0.00617284 + txt002 + SPHERE CENTER -0.234741 0.144336 0.737359 RAD 0.00617284 + txt002 + SPHERE CENTER -0.233184 0.13627 0.714074 RAD 0.00617284 + txt002 + SPHERE CENTER -0.212668 0.142084 0.726523 RAD 0.00617284 + txt002 + SPHERE CENTER -0.129201 0.143787 0.689081 RAD 0.0185185 + txt002 + SPHERE CENTER -0.105335 0.14887 0.692853 RAD 0.00617284 + txt002 + SPHERE CENTER -0.115741 0.153943 0.671044 RAD 0.00617284 + txt002 + SPHERE CENTER -0.121723 0.167242 0.690969 RAD 0.00617284 + txt002 + SPHERE CENTER -0.118795 0.138714 0.71089 RAD 0.00617284 + txt002 + SPHERE CENTER -0.135183 0.157086 0.709006 RAD 0.00617284 + txt002 + SPHERE CENTER -0.142661 0.13363 0.707118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.112813 0.125414 0.690965 RAD 0.00617284 + txt002 + SPHERE CENTER -0.136679 0.120331 0.687193 RAD 0.00617284 + txt002 + SPHERE CENTER -0.123219 0.130487 0.669156 RAD 0.00617284 + txt002 + SPHERE CENTER -0.190359 0.102131 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER -0.179968 0.0897843 0.711167 RAD 0.00617284 + txt002 + SPHERE CENTER -0.166467 0.105492 0.697727 RAD 0.00617284 + txt002 + SPHERE CENTER -0.183804 0.114103 0.713055 RAD 0.00617284 + txt002 + SPHERE CENTER -0.20386 0.0864233 0.705919 RAD 0.00617284 + txt002 + SPHERE CENTER -0.207696 0.110742 0.707807 RAD 0.00617284 + txt002 + SPHERE CENTER -0.214251 0.0987702 0.687231 RAD 0.00617284 + txt002 + SPHERE CENTER -0.186523 0.0778128 0.690591 RAD 0.00617284 + txt002 + SPHERE CENTER -0.196914 0.0901597 0.671903 RAD 0.00617284 + txt002 + SPHERE CENTER -0.173022 0.0935207 0.677151 RAD 0.00617284 + txt002 + SPHERE CENTER -0.153407 0.108529 0.6286 RAD 0.0185185 + txt002 + SPHERE CENTER -0.130858 0.0995811 0.624003 RAD 0.00617284 + txt002 + SPHERE CENTER -0.135326 0.123725 0.621398 RAD 0.00617284 + txt002 + SPHERE CENTER -0.134736 0.113639 0.643928 RAD 0.00617284 + txt002 + SPHERE CENTER -0.148938 0.0843858 0.631205 RAD 0.00617284 + txt002 + SPHERE CENTER -0.152816 0.0984435 0.65113 RAD 0.00617284 + txt002 + SPHERE CENTER -0.171487 0.0933338 0.635801 RAD 0.00617284 + txt002 + SPHERE CENTER -0.149528 0.0944715 0.608675 RAD 0.00617284 + txt002 + SPHERE CENTER -0.172078 0.10342 0.613272 RAD 0.00617284 + txt002 + SPHERE CENTER -0.153997 0.118615 0.60607 RAD 0.00617284 + txt002 + SPHERE CENTER -0.31427 0.31427 0.544331 RAD 0.0555556 + txt002 + SPHERE CENTER -0.277961 0.367156 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.269898 0.374298 0.485076 RAD 0.00617284 + txt002 + SPHERE CENTER -0.270045 0.350338 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER -0.291334 0.362218 0.487134 RAD 0.00617284 + txt002 + SPHERE CENTER -0.277815 0.391115 0.501329 RAD 0.00617284 + txt002 + SPHERE CENTER -0.299251 0.379036 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.285878 0.383973 0.523547 RAD 0.00617284 + txt002 + SPHERE CENTER -0.256525 0.379235 0.505236 RAD 0.00617284 + txt002 + SPHERE CENTER -0.264588 0.372093 0.527454 RAD 0.00617284 + txt002 + SPHERE CENTER -0.256671 0.355276 0.511201 RAD 0.00617284 + txt002 + SPHERE CENTER -0.252306 0.297666 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.235688 0.305995 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER -0.259438 0.312359 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.245915 0.321516 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.228556 0.291303 0.509559 RAD 0.00617284 + txt002 + SPHERE CENTER -0.238783 0.306824 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.245173 0.282974 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.242079 0.282145 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER -0.258696 0.273816 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.265828 0.288509 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.31427 0.31427 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER -0.32435 0.32435 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER -0.33812 0.32066 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.32066 0.33812 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.3005 0.317959 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER -0.29681 0.331729 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.29042 0.307879 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.317959 0.3005 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER -0.307879 0.29042 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.331729 0.29681 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.339925 0.383759 0.544331 RAD 0.0185185 + txt002 + SPHERE CENTER -0.334762 0.407156 0.538366 RAD 0.00617284 + txt002 + SPHERE CENTER -0.31686 0.392275 0.546597 RAD 0.00617284 + txt002 + SPHERE CENTER -0.326552 0.388696 0.524171 RAD 0.00617284 + txt002 + SPHERE CENTER -0.357827 0.39864 0.536101 RAD 0.00617284 + txt002 + SPHERE CENTER -0.349618 0.380181 0.521905 RAD 0.00617284 + txt002 + SPHERE CENTER -0.362991 0.375243 0.542066 RAD 0.00617284 + txt002 + SPHERE CENTER -0.348135 0.402218 0.558526 RAD 0.00617284 + txt002 + SPHERE CENTER -0.353299 0.378821 0.564491 RAD 0.00617284 + txt002 + SPHERE CENTER -0.330233 0.387337 0.566757 RAD 0.00617284 + txt002 + SPHERE CENTER -0.376234 0.330873 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.393346 0.348239 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.383366 0.345565 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.369843 0.354723 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.386213 0.333547 0.484868 RAD 0.00617284 + txt002 + SPHERE CENTER -0.362711 0.340031 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.369102 0.316181 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399736 0.324389 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.382624 0.307023 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.389757 0.321715 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.376234 0.330873 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.386461 0.346394 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER -0.362711 0.340031 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.369843 0.354723 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399983 0.337237 0.579103 RAD 0.00617284 + txt002 + SPHERE CENTER -0.383366 0.345565 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.389757 0.321715 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.392851 0.322544 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER -0.382624 0.307023 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.369102 0.316181 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.277961 0.367156 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.261966 0.385852 0.57931 RAD 0.00617284 + txt002 + SPHERE CENTER -0.259422 0.36581 0.565115 RAD 0.00617284 + txt002 + SPHERE CENTER -0.278159 0.38141 0.561208 RAD 0.00617284 + txt002 + SPHERE CENTER -0.280504 0.387198 0.595564 RAD 0.00617284 + txt002 + SPHERE CENTER -0.296698 0.382755 0.577461 RAD 0.00617284 + txt002 + SPHERE CENTER -0.2965 0.368501 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER -0.261768 0.371598 0.599471 RAD 0.00617284 + txt002 + SPHERE CENTER -0.277764 0.352901 0.601529 RAD 0.00617284 + txt002 + SPHERE CENTER -0.259225 0.351556 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER -0.31427 0.31427 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.304189 0.32435 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.29042 0.32066 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.307879 0.33812 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.328039 0.317959 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.331729 0.331729 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.33812 0.307879 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.31058 0.3005 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.32066 0.29042 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.29681 0.29681 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.252306 0.297666 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.228803 0.30415 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER -0.238783 0.306824 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.245915 0.321516 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.242326 0.294992 0.603794 RAD 0.00617284 + txt002 + SPHERE CENTER -0.259438 0.312359 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.265828 0.288509 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.235194 0.2803 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER -0.258696 0.273816 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.245173 0.282974 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.574159 0.153845 0.618405 RAD 0.0555556 + txt002 + SPHERE CENTER -0.612768 0.202534 0.658726 RAD 0.0185185 + txt002 + SPHERE CENTER -0.612732 0.225282 0.668328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.591695 0.212428 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER -0.60221 0.22113 0.64638 RAD 0.00617284 + txt002 + SPHERE CENTER -0.633805 0.215388 0.660098 RAD 0.00617284 + txt002 + SPHERE CENTER -0.623283 0.211236 0.63815 RAD 0.00617284 + txt002 + SPHERE CENTER -0.63384 0.192641 0.650495 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62329 0.206686 0.680674 RAD 0.00617284 + txt002 + SPHERE CENTER -0.623325 0.183939 0.671072 RAD 0.00617284 + txt002 + SPHERE CENTER -0.602253 0.193832 0.679302 RAD 0.00617284 + txt002 + SPHERE CENTER -0.543919 0.184086 0.678886 RAD 0.0185185 + txt002 + SPHERE CENTER -0.527458 0.200547 0.687117 RAD 0.00617284 + txt002 + SPHERE CENTER -0.522843 0.187702 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER -0.540303 0.205161 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER -0.548533 0.196931 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER -0.561378 0.201546 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER -0.564994 0.18047 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER -0.531074 0.179472 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER -0.547535 0.163011 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER -0.526459 0.166627 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER -0.554987 0.225396 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.542885 0.243024 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER -0.534333 0.219861 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER -0.554987 0.225396 0.593714 RAD 0.00617284 + txt002 + SPHERE CENTER -0.563539 0.248559 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.575642 0.23093 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER -0.575642 0.23093 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER -0.542885 0.243024 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER -0.554987 0.225396 0.643096 RAD 0.00617284 + txt002 + SPHERE CENTER -0.534333 0.219861 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER -0.643008 0.172294 0.598245 RAD 0.0185185 + txt002 + SPHERE CENTER -0.660425 0.189742 0.599616 RAD 0.00617284 + txt002 + SPHERE CENTER -0.645434 0.185725 0.618821 RAD 0.00617284 + txt002 + SPHERE CENTER -0.636618 0.196144 0.598245 RAD 0.00617284 + txt002 + SPHERE CENTER -0.657999 0.17631 0.57904 RAD 0.00617284 + txt002 + SPHERE CENTER -0.634191 0.182712 0.577669 RAD 0.00617284 + txt002 + SPHERE CENTER -0.640582 0.158862 0.577669 RAD 0.00617284 + txt002 + SPHERE CENTER -0.666816 0.165892 0.599616 RAD 0.00617284 + txt002 + SPHERE CENTER -0.649399 0.148444 0.598245 RAD 0.00617284 + txt002 + SPHERE CENTER -0.651825 0.161875 0.618821 RAD 0.00617284 + txt002 + SPHERE CENTER -0.585228 0.195155 0.557924 RAD 0.0185185 + txt002 + SPHERE CENTER -0.574809 0.203972 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER -0.561378 0.201546 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER -0.568784 0.181486 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER -0.598659 0.197581 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER -0.592634 0.175095 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER -0.609078 0.188764 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER -0.591253 0.217641 0.549693 RAD 0.00617284 + txt002 + SPHERE CENTER -0.601672 0.208824 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER -0.577822 0.215215 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER -0.6044 0.123605 0.557924 RAD 0.0185185 + txt002 + SPHERE CENTER -0.620861 0.107144 0.549693 RAD 0.00617284 + txt002 + SPHERE CENTER -0.608016 0.102529 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER -0.625475 0.119989 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER -0.617245 0.128219 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER -0.621859 0.141064 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER -0.600784 0.14468 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER -0.599785 0.11076 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER -0.583324 0.127221 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER -0.58694 0.106145 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER -0.631939 0.130984 0.658726 RAD 0.0185185 + txt002 + SPHERE CENTER -0.643128 0.132649 0.680674 RAD 0.00617284 + txt002 + SPHERE CENTER -0.618482 0.133263 0.679302 RAD 0.00617284 + txt002 + SPHERE CENTER -0.631785 0.152367 0.671072 RAD 0.00617284 + txt002 + SPHERE CENTER -0.656585 0.130371 0.660098 RAD 0.00617284 + txt002 + SPHERE CENTER -0.645242 0.150088 0.650495 RAD 0.00617284 + txt002 + SPHERE CENTER -0.645397 0.128706 0.63815 RAD 0.00617284 + txt002 + SPHERE CENTER -0.643283 0.111266 0.668328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.632094 0.109601 0.64638 RAD 0.00617284 + txt002 + SPHERE CENTER -0.618637 0.11188 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER -0.593331 0.0822954 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.591664 0.0609772 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER -0.572676 0.076761 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER -0.593331 0.0822954 0.643096 RAD 0.00617284 + txt002 + SPHERE CENTER -0.612319 0.0665116 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.613986 0.0878298 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER -0.613986 0.0878298 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER -0.591664 0.0609772 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER -0.593331 0.0822954 0.593714 RAD 0.00617284 + txt002 + SPHERE CENTER -0.572676 0.076761 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER -0.56309 0.112536 0.678886 RAD 0.0185185 + txt002 + SPHERE CENTER -0.549659 0.11011 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER -0.53924 0.118927 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555684 0.132596 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER -0.573509 0.103719 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER -0.579534 0.126205 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER -0.58694 0.106145 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER -0.557065 0.09005 0.687117 RAD 0.00617284 + txt002 + SPHERE CENTER -0.570497 0.0924762 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER -0.546646 0.0988668 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER -0.494808 0.247614 0.43322 RAD 0.0555556 + txt002 + SPHERE CENTER -0.494287 0.313607 0.399581 RAD 0.0185185 + txt002 + SPHERE CENTER -0.484182 0.326876 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER -0.470513 0.310432 0.39372 RAD 0.00617284 + txt002 + SPHERE CENTER -0.488171 0.302705 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER -0.507957 0.330051 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.511946 0.305881 0.384149 RAD 0.00617284 + txt002 + SPHERE CENTER -0.518062 0.316783 0.405442 RAD 0.00617284 + txt002 + SPHERE CENTER -0.490299 0.337778 0.402668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.500404 0.324509 0.420874 RAD 0.00617284 + txt002 + SPHERE CENTER -0.476629 0.321334 0.415013 RAD 0.00617284 + txt002 + SPHERE CENTER -0.452978 0.302539 0.460062 RAD 0.0185185 + txt002 + SPHERE CENTER -0.436971 0.320401 0.454201 RAD 0.00617284 + txt002 + SPHERE CENTER -0.436675 0.29902 0.441856 RAD 0.00617284 + txt002 + SPHERE CENTER -0.455413 0.3148 0.438769 RAD 0.00617284 + txt002 + SPHERE CENTER -0.453274 0.32392 0.472408 RAD 0.00617284 + txt002 + SPHERE CENTER -0.471717 0.318318 0.456976 RAD 0.00617284 + txt002 + SPHERE CENTER -0.469281 0.306057 0.478269 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434535 0.30814 0.475494 RAD 0.00617284 + txt002 + SPHERE CENTER -0.450543 0.290278 0.481355 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434239 0.286759 0.463149 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434629 0.269833 0.396183 RAD 0.0185185 + txt002 + SPHERE CENTER -0.426389 0.279233 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER -0.445377 0.263449 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER -0.448298 0.286276 0.383837 RAD 0.00617284 + txt002 + SPHERE CENTER -0.415641 0.285616 0.396183 RAD 0.00617284 + txt002 + SPHERE CENTER -0.43755 0.29266 0.40513 RAD 0.00617284 + txt002 + SPHERE CENTER -0.42388 0.276216 0.417476 RAD 0.00617284 + txt002 + SPHERE CENTER -0.41272 0.262789 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.420959 0.253389 0.408529 RAD 0.00617284 + txt002 + SPHERE CENTER -0.431707 0.247006 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.536117 0.258683 0.372739 RAD 0.0185185 + txt002 + SPHERE CENTER -0.549787 0.275127 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER -0.549787 0.275127 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER -0.529727 0.282533 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER -0.536117 0.258683 0.348047 RAD 0.00617284 + txt002 + SPHERE CENTER -0.516058 0.266089 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER -0.522448 0.242239 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER -0.556177 0.251277 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER -0.542508 0.234833 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER -0.556177 0.251277 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER -0.476459 0.214908 0.369341 RAD 0.0185185 + txt002 + SPHERE CENTER -0.457868 0.209819 0.353908 RAD 0.00617284 + txt002 + SPHERE CENTER -0.458164 0.2312 0.366254 RAD 0.00617284 + txt002 + SPHERE CENTER -0.453963 0.210053 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER -0.476163 0.193527 0.356995 RAD 0.00617284 + txt002 + SPHERE CENTER -0.472258 0.193761 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER -0.494753 0.198616 0.372427 RAD 0.00617284 + txt002 + SPHERE CENTER -0.480363 0.214674 0.344961 RAD 0.00617284 + txt002 + SPHERE CENTER -0.498954 0.219763 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER -0.480659 0.236055 0.357307 RAD 0.00617284 + txt002 + SPHERE CENTER -0.536638 0.19269 0.406378 RAD 0.0185185 + txt002 + SPHERE CENTER -0.549603 0.17251 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER -0.528912 0.177908 0.424584 RAD 0.00617284 + txt002 + SPHERE CENTER -0.549105 0.191778 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER -0.557329 0.187292 0.394032 RAD 0.00617284 + txt002 + SPHERE CENTER -0.556831 0.20656 0.409464 RAD 0.00617284 + txt002 + SPHERE CENTER -0.544363 0.207471 0.388171 RAD 0.00617284 + txt002 + SPHERE CENTER -0.537136 0.173421 0.390945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.524171 0.193601 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER -0.516445 0.178819 0.403291 RAD 0.00617284 + txt002 + SPHERE CENTER -0.554467 0.291389 0.436618 RAD 0.0185185 + txt002 + SPHERE CENTER -0.562288 0.314604 0.439705 RAD 0.00617284 + txt002 + SPHERE CENTER -0.542501 0.306499 0.45205 RAD 0.00617284 + txt002 + SPHERE CENTER -0.541186 0.310183 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER -0.574255 0.299494 0.424272 RAD 0.00617284 + txt002 + SPHERE CENTER -0.553152 0.295073 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER -0.566433 0.276279 0.421186 RAD 0.00617284 + txt002 + SPHERE CENTER -0.575569 0.29581 0.448652 RAD 0.00617284 + txt002 + SPHERE CENTER -0.567748 0.272595 0.445566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555781 0.287705 0.460998 RAD 0.00617284 + txt002 + SPHERE CENTER -0.554987 0.225396 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER -0.567359 0.227186 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER -0.54267 0.227528 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555283 0.246777 0.482603 RAD 0.00617284 + txt002 + SPHERE CENTER -0.579676 0.225054 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.567601 0.244644 0.46131 RAD 0.00617284 + txt002 + SPHERE CENTER -0.567305 0.223263 0.448964 RAD 0.00617284 + txt002 + SPHERE CENTER -0.567063 0.205805 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER -0.554691 0.204014 0.457911 RAD 0.00617284 + txt002 + SPHERE CENTER -0.542374 0.206147 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER -0.513157 0.28032 0.497099 RAD 0.0185185 + txt002 + SPHERE CENTER -0.507811 0.298839 0.512531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.489718 0.287442 0.500186 RAD 0.00617284 + txt002 + SPHERE CENTER -0.505577 0.302049 0.488152 RAD 0.00617284 + txt002 + SPHERE CENTER -0.531251 0.291716 0.509445 RAD 0.00617284 + txt002 + SPHERE CENTER -0.529016 0.294927 0.485065 RAD 0.00617284 + txt002 + SPHERE CENTER -0.536597 0.273198 0.494013 RAD 0.00617284 + txt002 + SPHERE CENTER -0.515392 0.27711 0.521479 RAD 0.00617284 + txt002 + SPHERE CENTER -0.520738 0.258591 0.506047 RAD 0.00617284 + txt002 + SPHERE CENTER -0.497299 0.265714 0.509133 RAD 0.00617284 + txt002 + SPHERE CENTER -0.552323 0.0329639 0.43322 RAD 0.0555556 + txt002 + SPHERE CENTER -0.625877 0.0248832 0.436618 RAD 0.0185185 + txt002 + SPHERE CENTER -0.646362 0.0316054 0.448652 RAD 0.00617284 + txt002 + SPHERE CENTER -0.625173 0.0287309 0.460998 RAD 0.00617284 + txt002 + SPHERE CENTER -0.627981 0.0478 0.445566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.647066 0.0277577 0.424272 RAD 0.00617284 + txt002 + SPHERE CENTER -0.628685 0.0439523 0.421186 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62658 0.0210355 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER -0.644258 0.00868865 0.439705 RAD 0.00617284 + txt002 + SPHERE CENTER -0.623773 0.00196644 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER -0.623069 0.00581415 0.45205 RAD 0.00617284 + txt002 + SPHERE CENTER -0.584567 0.0138144 0.497099 RAD 0.0185185 + txt002 + SPHERE CENTER -0.584898 0.0177119 0.521479 RAD 0.00617284 + txt002 + SPHERE CENTER -0.56353 0.0185345 0.509133 RAD 0.00617284 + txt002 + SPHERE CENTER -0.580268 0.0364224 0.506047 RAD 0.00617284 + txt002 + SPHERE CENTER -0.605935 0.0129918 0.509445 RAD 0.00617284 + txt002 + SPHERE CENTER -0.601305 0.0317022 0.494013 RAD 0.00617284 + txt002 + SPHERE CENTER -0.605605 0.00909422 0.485065 RAD 0.00617284 + txt002 + SPHERE CENTER -0.589197 -0.00489609 0.512531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.588867 -0.00879364 0.488152 RAD 0.00617284 + txt002 + SPHERE CENTER -0.567829 -0.00407348 0.500186 RAD 0.00617284 + txt002 + SPHERE CENTER -0.593331 0.0822954 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER -0.593994 0.105299 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER -0.572783 0.0926585 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER -0.582384 0.100664 0.457911 RAD 0.00617284 + txt002 + SPHERE CENTER -0.614541 0.0949359 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.602932 0.090301 0.448964 RAD 0.00617284 + txt002 + SPHERE CENTER -0.613879 0.0719323 0.46131 RAD 0.00617284 + txt002 + SPHERE CENTER -0.604941 0.0869303 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER -0.604278 0.0639267 0.482603 RAD 0.00617284 + txt002 + SPHERE CENTER -0.58373 0.0742898 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER -0.593633 0.0440327 0.372739 RAD 0.0185185 + txt002 + SPHERE CENTER -0.607302 0.0604766 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER -0.607302 0.0604766 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER -0.587242 0.0678827 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER -0.593633 0.0440327 0.348047 RAD 0.00617284 + txt002 + SPHERE CENTER -0.573573 0.0514389 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER -0.579964 0.0275889 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER -0.613693 0.0366265 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER -0.600023 0.0201827 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER -0.613693 0.0366265 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER -0.561087 0.101445 0.406378 RAD 0.0185185 + txt002 + SPHERE CENTER -0.551884 0.118381 0.390945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.536664 0.103361 0.403291 RAD 0.00617284 + txt002 + SPHERE CENTER -0.550745 0.0944221 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER -0.576307 0.116465 0.394032 RAD 0.00617284 + txt002 + SPHERE CENTER -0.575168 0.0925065 0.388171 RAD 0.00617284 + txt002 + SPHERE CENTER -0.58551 0.0995293 0.409464 RAD 0.00617284 + txt002 + SPHERE CENTER -0.562225 0.125404 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER -0.571428 0.108468 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER -0.547006 0.110383 0.424584 RAD 0.00617284 + txt002 + SPHERE CENTER -0.520079 0.0521134 0.369341 RAD 0.0185185 + txt002 + SPHERE CENTER -0.523344 0.0542684 0.344961 RAD 0.00617284 + txt002 + SPHERE CENTER -0.534291 0.0358996 0.357307 RAD 0.00617284 + txt002 + SPHERE CENTER -0.541988 0.0591566 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER -0.509132 0.0704822 0.356995 RAD 0.00617284 + txt002 + SPHERE CENTER -0.527777 0.0753703 0.372427 RAD 0.00617284 + txt002 + SPHERE CENTER -0.505868 0.0683272 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER -0.501435 0.0472252 0.353908 RAD 0.00617284 + txt002 + SPHERE CENTER -0.49817 0.0450702 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER -0.512382 0.0288565 0.366254 RAD 0.00617284 + txt002 + SPHERE CENTER -0.584869 -0.0244483 0.399581 RAD 0.0185185 + txt002 + SPHERE CENTER -0.5935 -0.0473753 0.402668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.57344 -0.0399691 0.415013 RAD 0.00617284 + txt002 + SPHERE CENTER -0.595617 -0.0308315 0.420874 RAD 0.00617284 + txt002 + SPHERE CENTER -0.604929 -0.0318545 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.607046 -0.0153107 0.405442 RAD 0.00617284 + txt002 + SPHERE CENTER -0.596298 -0.00892756 0.384149 RAD 0.00617284 + txt002 + SPHERE CENTER -0.582752 -0.0409921 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER -0.574121 -0.0180651 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER -0.562692 -0.0335859 0.39372 RAD 0.00617284 + txt002 + SPHERE CENTER -0.511316 -0.0163676 0.396183 RAD 0.0185185 + txt002 + SPHERE CENTER -0.48882 -0.0212225 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.497372 0.00194055 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.491256 -0.00896145 0.408529 RAD 0.00617284 + txt002 + SPHERE CENTER -0.502764 -0.0395307 0.396183 RAD 0.00617284 + txt002 + SPHERE CENTER -0.505199 -0.0272696 0.417476 RAD 0.00617284 + txt002 + SPHERE CENTER -0.525259 -0.0346758 0.40513 RAD 0.00617284 + txt002 + SPHERE CENTER -0.50888 -0.0286287 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER -0.531375 -0.0237738 0.383837 RAD 0.00617284 + txt002 + SPHERE CENTER -0.517432 -0.00546563 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER -0.54356 -0.0355172 0.460062 RAD 0.0185185 + txt002 + SPHERE CENTER -0.530389 -0.0495897 0.475494 RAD 0.00617284 + txt002 + SPHERE CENTER -0.519442 -0.031221 0.463149 RAD 0.00617284 + txt002 + SPHERE CENTER -0.53532 -0.0261165 0.481355 RAD 0.00617284 + txt002 + SPHERE CENTER -0.554507 -0.0538859 0.472408 RAD 0.00617284 + txt002 + SPHERE CENTER -0.559438 -0.0304127 0.478269 RAD 0.00617284 + txt002 + SPHERE CENTER -0.567678 -0.0398133 0.456976 RAD 0.00617284 + txt002 + SPHERE CENTER -0.538628 -0.0589904 0.454201 RAD 0.00617284 + txt002 + SPHERE CENTER -0.551799 -0.0449178 0.438769 RAD 0.00617284 + txt002 + SPHERE CENTER -0.527681 -0.0406217 0.441856 RAD 0.00617284 + txt002 + SPHERE CENTER -0.451136 0.0058509 0.729516 RAD 0.0555556 + txt002 + SPHERE CENTER -0.447081 0.0051487 0.803476 RAD 0.0185185 + txt002 + SPHERE CENTER -0.435909 0.01504 0.823149 RAD 0.00617284 + txt002 + SPHERE CENTER -0.423265 0.0115452 0.802231 RAD 0.00617284 + txt002 + SPHERE CENTER -0.440694 0.0289993 0.803352 RAD 0.00617284 + txt002 + SPHERE CENTER -0.459725 0.00864346 0.824394 RAD 0.00617284 + txt002 + SPHERE CENTER -0.46451 0.0226028 0.804597 RAD 0.00617284 + txt002 + SPHERE CENTER -0.470897 -0.0012478 0.804721 RAD 0.00617284 + txt002 + SPHERE CENTER -0.442297 -0.00881065 0.823273 RAD 0.00617284 + txt002 + SPHERE CENTER -0.453468 -0.0187019 0.8036 RAD 0.00617284 + txt002 + SPHERE CENTER -0.429652 -0.0123054 0.802355 RAD 0.00617284 + txt002 + SPHERE CENTER -0.386138 0.0172804 0.763155 RAD 0.0185185 + txt002 + SPHERE CENTER -0.364644 0.0293677 0.76191 RAD 0.00617284 + txt002 + SPHERE CENTER -0.375512 0.0213457 0.741241 RAD 0.00617284 + txt002 + SPHERE CENTER -0.385352 0.0401449 0.753867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37527 0.0253024 0.783824 RAD 0.00617284 + txt002 + SPHERE CENTER -0.395978 0.0360796 0.775781 RAD 0.00617284 + txt002 + SPHERE CENTER -0.396764 0.0132151 0.785069 RAD 0.00617284 + txt002 + SPHERE CENTER -0.36543 0.0065032 0.771198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.386924 -0.00558411 0.772443 RAD 0.00617284 + txt002 + SPHERE CENTER -0.376298 -0.00151881 0.750529 RAD 0.00617284 + txt002 + SPHERE CENTER -0.439178 0.0688765 0.766553 RAD 0.0185185 + txt002 + SPHERE CENTER -0.426942 0.0903221 0.766429 RAD 0.00617284 + txt002 + SPHERE CENTER -0.416328 0.0699989 0.757266 RAD 0.00617284 + txt002 + SPHERE CENTER -0.435083 0.0806307 0.745229 RAD 0.00617284 + txt002 + SPHERE CENTER -0.449792 0.0891998 0.775717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.457933 0.0795084 0.754517 RAD 0.00617284 + txt002 + SPHERE CENTER -0.462029 0.0677542 0.775841 RAD 0.00617284 + txt002 + SPHERE CENTER -0.431037 0.078568 0.787754 RAD 0.00617284 + txt002 + SPHERE CENTER -0.443274 0.0571224 0.787878 RAD 0.00617284 + txt002 + SPHERE CENTER -0.420423 0.0582447 0.77859 RAD 0.00617284 + txt002 + SPHERE CENTER -0.512079 -0.00628079 0.769837 RAD 0.0185185 + txt002 + SPHERE CENTER -0.523883 -0.000557006 0.790755 RAD 0.00617284 + txt002 + SPHERE CENTER -0.49924 -0.00208214 0.790506 RAD 0.00617284 + txt002 + SPHERE CENTER -0.51057 0.0165974 0.779001 RAD 0.00617284 + txt002 + SPHERE CENTER -0.536722 -0.00475566 0.770086 RAD 0.00617284 + txt002 + SPHERE CENTER -0.523409 0.0123987 0.758332 RAD 0.00617284 + txt002 + SPHERE CENTER -0.524918 -0.0104794 0.749168 RAD 0.00617284 + txt002 + SPHERE CENTER -0.525392 -0.0234352 0.781591 RAD 0.00617284 + txt002 + SPHERE CENTER -0.513588 -0.029159 0.760673 RAD 0.00617284 + txt002 + SPHERE CENTER -0.500749 -0.0249603 0.781342 RAD 0.00617284 + txt002 + SPHERE CENTER -0.504176 0.0574471 0.732914 RAD 0.0185185 + txt002 + SPHERE CENTER -0.508666 0.0817008 0.734036 RAD 0.00617284 + txt002 + SPHERE CENTER -0.488971 0.0722467 0.745541 RAD 0.00617284 + txt002 + SPHERE CENTER -0.489545 0.0732807 0.720878 RAD 0.00617284 + txt002 + SPHERE CENTER -0.523872 0.0669012 0.72141 RAD 0.00617284 + txt002 + SPHERE CENTER -0.504751 0.058481 0.708251 RAD 0.00617284 + txt002 + SPHERE CENTER -0.519382 0.0426474 0.720288 RAD 0.00617284 + txt002 + SPHERE CENTER -0.523298 0.0658672 0.746073 RAD 0.00617284 + txt002 + SPHERE CENTER -0.518808 0.0416134 0.744951 RAD 0.00617284 + txt002 + SPHERE CENTER -0.503602 0.0564131 0.757577 RAD 0.00617284 + txt002 + SPHERE CENTER -0.516134 -0.00557859 0.695877 RAD 0.0185185 + txt002 + SPHERE CENTER -0.540463 -0.00154892 0.697123 RAD 0.00617284 + txt002 + SPHERE CENTER -0.52751 -0.00538221 0.717791 RAD 0.00617284 + txt002 + SPHERE CENTER -0.524673 0.0156462 0.705165 RAD 0.00617284 + txt002 + SPHERE CENTER -0.529087 -0.00174531 0.675209 RAD 0.00617284 + txt002 + SPHERE CENTER -0.513298 0.0154498 0.683251 RAD 0.00617284 + txt002 + SPHERE CENTER -0.504759 -0.00577498 0.673964 RAD 0.00617284 + txt002 + SPHERE CENTER -0.531924 -0.0227737 0.687835 RAD 0.00617284 + txt002 + SPHERE CENTER -0.507596 -0.0268034 0.68659 RAD 0.00617284 + txt002 + SPHERE CENTER -0.518971 -0.026607 0.708504 RAD 0.00617284 + txt002 + SPHERE CENTER -0.459039 -0.0578769 0.766439 RAD 0.0185185 + txt002 + SPHERE CENTER -0.451803 -0.0707378 0.786236 RAD 0.00617284 + txt002 + SPHERE CENTER -0.435761 -0.0561039 0.774481 RAD 0.00617284 + txt002 + SPHERE CENTER -0.454158 -0.0461991 0.787639 RAD 0.00617284 + txt002 + SPHERE CENTER -0.475081 -0.0725109 0.778193 RAD 0.00617284 + txt002 + SPHERE CENTER -0.477435 -0.0479721 0.779597 RAD 0.00617284 + txt002 + SPHERE CENTER -0.482316 -0.05965 0.758396 RAD 0.00617284 + txt002 + SPHERE CENTER -0.456685 -0.0824157 0.765035 RAD 0.00617284 + txt002 + SPHERE CENTER -0.46392 -0.0695548 0.745238 RAD 0.00617284 + txt002 + SPHERE CENTER -0.440643 -0.0677817 0.753281 RAD 0.00617284 + txt002 + SPHERE CENTER -0.463094 -0.0571747 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER -0.459563 -0.081612 0.692603 RAD 0.00617284 + txt002 + SPHERE CENTER -0.442243 -0.0665888 0.701767 RAD 0.00617284 + txt002 + SPHERE CENTER -0.463589 -0.0696122 0.713804 RAD 0.00617284 + txt002 + SPHERE CENTER -0.480415 -0.0721979 0.683315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.48444 -0.0601982 0.704516 RAD 0.00617284 + txt002 + SPHERE CENTER -0.483946 -0.0477607 0.683192 RAD 0.00617284 + txt002 + SPHERE CENTER -0.459069 -0.0691745 0.671279 RAD 0.00617284 + txt002 + SPHERE CENTER -0.4626 -0.0447373 0.671155 RAD 0.00617284 + txt002 + SPHERE CENTER -0.441749 -0.0541513 0.680442 RAD 0.00617284 + txt002 + SPHERE CENTER -0.398096 -0.0457452 0.726118 RAD 0.0185185 + txt002 + SPHERE CENTER -0.373728 -0.0495643 0.724997 RAD 0.00617284 + txt002 + SPHERE CENTER -0.383722 -0.030137 0.713492 RAD 0.00617284 + txt002 + SPHERE CENTER -0.382672 -0.0306825 0.738155 RAD 0.00617284 + txt002 + SPHERE CENTER -0.388102 -0.0651725 0.737623 RAD 0.00617284 + txt002 + SPHERE CENTER -0.397047 -0.0462908 0.750781 RAD 0.00617284 + txt002 + SPHERE CENTER -0.41247 -0.0613535 0.738744 RAD 0.00617284 + txt002 + SPHERE CENTER -0.389151 -0.064627 0.71296 RAD 0.00617284 + txt002 + SPHERE CENTER -0.41352 -0.060808 0.714081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399146 -0.0451997 0.701455 RAD 0.00617284 + txt002 + SPHERE CENTER -0.4293 -0.115031 0.544331 RAD 0.0555556 + txt002 + SPHERE CENTER -0.424299 -0.178985 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.412497 -0.190929 0.599471 RAD 0.00617284 + txt002 + SPHERE CENTER -0.400273 -0.174844 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER -0.417001 -0.16674 0.601529 RAD 0.00617284 + txt002 + SPHERE CENTER -0.436523 -0.195071 0.595564 RAD 0.00617284 + txt002 + SPHERE CENTER -0.441027 -0.170881 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER -0.448325 -0.183127 0.577461 RAD 0.00617284 + txt002 + SPHERE CENTER -0.419795 -0.203175 0.57931 RAD 0.00617284 + txt002 + SPHERE CENTER -0.431597 -0.191231 0.561208 RAD 0.00617284 + txt002 + SPHERE CENTER -0.407571 -0.18709 0.565115 RAD 0.00617284 + txt002 + SPHERE CENTER -0.367336 -0.131634 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.343834 -0.12515 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER -0.353814 -0.122476 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.360946 -0.107784 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.357357 -0.134308 0.603794 RAD 0.00617284 + txt002 + SPHERE CENTER -0.374468 -0.116942 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.380859 -0.140792 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.350225 -0.149 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER -0.373727 -0.155484 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.360204 -0.146326 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.4293 -0.115031 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.41922 -0.10495 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.40545 -0.10864 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.42291 -0.0911807 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.44307 -0.111341 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.44676 -0.0975713 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.45315 -0.121421 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.425611 -0.128801 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.435691 -0.138881 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.411841 -0.13249 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.486264 -0.162382 0.544331 RAD 0.0185185 + txt002 + SPHERE CENTER -0.502603 -0.174264 0.558526 RAD 0.00617284 + txt002 + SPHERE CENTER -0.479659 -0.170327 0.566757 RAD 0.00617284 + txt002 + SPHERE CENTER -0.495376 -0.15142 0.564491 RAD 0.00617284 + txt002 + SPHERE CENTER -0.509207 -0.166319 0.536101 RAD 0.00617284 + txt002 + SPHERE CENTER -0.501981 -0.143475 0.542066 RAD 0.00617284 + txt002 + SPHERE CENTER -0.492868 -0.154437 0.521905 RAD 0.00617284 + txt002 + SPHERE CENTER -0.49349 -0.185226 0.538366 RAD 0.00617284 + txt002 + SPHERE CENTER -0.477151 -0.173345 0.524171 RAD 0.00617284 + txt002 + SPHERE CENTER -0.470546 -0.18129 0.546597 RAD 0.00617284 + txt002 + SPHERE CENTER -0.491265 -0.0984274 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.501491 -0.082906 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER -0.477742 -0.0892696 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.484874 -0.0745774 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.515014 -0.0920638 0.579103 RAD 0.00617284 + txt002 + SPHERE CENTER -0.498397 -0.0837352 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.504787 -0.107585 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.507882 -0.106756 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER -0.497655 -0.122277 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.484132 -0.11312 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.491265 -0.0984274 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.508376 -0.0810612 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.498397 -0.0837352 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.484874 -0.0745774 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.501244 -0.0957534 0.484868 RAD 0.00617284 + txt002 + SPHERE CENTER -0.477742 -0.0892696 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.484132 -0.11312 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.514767 -0.104911 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.497655 -0.122277 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.504787 -0.107585 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.424299 -0.178985 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.411775 -0.200165 0.505236 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399922 -0.179342 0.511201 RAD 0.00617284 + txt002 + SPHERE CENTER -0.415187 -0.189948 0.527454 RAD 0.00617284 + txt002 + SPHERE CENTER -0.436152 -0.199808 0.501329 RAD 0.00617284 + txt002 + SPHERE CENTER -0.439564 -0.189591 0.523547 RAD 0.00617284 + txt002 + SPHERE CENTER -0.448677 -0.178629 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.420888 -0.189202 0.485076 RAD 0.00617284 + txt002 + SPHERE CENTER -0.433412 -0.168023 0.487134 RAD 0.00617284 + txt002 + SPHERE CENTER -0.409035 -0.168379 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER -0.4293 -0.115031 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER -0.439381 -0.10495 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER -0.45315 -0.10864 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.435691 -0.0911807 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.415531 -0.111341 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER -0.411841 -0.0975713 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.40545 -0.121421 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.43299 -0.128801 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER -0.42291 -0.138881 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.44676 -0.13249 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.367336 -0.131634 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.350719 -0.123305 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER -0.374468 -0.116942 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.360946 -0.107784 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.343587 -0.137998 0.509559 RAD 0.00617284 + txt002 + SPHERE CENTER -0.353814 -0.122476 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.360204 -0.146326 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.357109 -0.147155 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER -0.373727 -0.155484 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.380859 -0.140792 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.248762 -0.0483751 0.655442 RAD 0.0555556 + txt002 + SPHERE CENTER -0.183785 -0.0599222 0.689081 RAD 0.0185185 + txt002 + SPHERE CENTER -0.160406 -0.0522053 0.690965 RAD 0.00617284 + txt002 + SPHERE CENTER -0.171954 -0.0513956 0.669156 RAD 0.00617284 + txt002 + SPHERE CENTER -0.178533 -0.0358698 0.687193 RAD 0.00617284 + txt002 + SPHERE CENTER -0.172236 -0.0607319 0.71089 RAD 0.00617284 + txt002 + SPHERE CENTER -0.190363 -0.0443964 0.707118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.195615 -0.0684488 0.709006 RAD 0.00617284 + txt002 + SPHERE CENTER -0.165658 -0.0762577 0.692853 RAD 0.00617284 + txt002 + SPHERE CENTER -0.189036 -0.0839747 0.690969 RAD 0.00617284 + txt002 + SPHERE CENTER -0.177206 -0.075448 0.671044 RAD 0.00617284 + txt002 + SPHERE CENTER -0.187119 -0.0172857 0.6286 RAD 0.0185185 + txt002 + SPHERE CENTER -0.176731 -0.00705049 0.608675 RAD 0.00617284 + txt002 + SPHERE CENTER -0.192673 -0.025725 0.60607 RAD 0.00617284 + txt002 + SPHERE CENTER -0.200733 -0.00352517 0.613272 RAD 0.00617284 + txt002 + SPHERE CENTER -0.171177 0.00138875 0.631205 RAD 0.00617284 + txt002 + SPHERE CENTER -0.195179 0.00491406 0.635801 RAD 0.00617284 + txt002 + SPHERE CENTER -0.181564 -0.00884647 0.65113 RAD 0.00617284 + txt002 + SPHERE CENTER -0.163117 -0.020811 0.624003 RAD 0.00617284 + txt002 + SPHERE CENTER -0.173504 -0.0310463 0.643928 RAD 0.00617284 + txt002 + SPHERE CENTER -0.179058 -0.0394855 0.621398 RAD 0.00617284 + txt002 + SPHERE CENTER -0.215921 0.00673113 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER -0.20044 0.0258737 0.690591 RAD 0.00617284 + txt002 + SPHERE CENTER -0.196602 0.00551963 0.677151 RAD 0.00617284 + txt002 + SPHERE CENTER -0.215612 0.0203763 0.671903 RAD 0.00617284 + txt002 + SPHERE CENTER -0.21976 0.0270852 0.705919 RAD 0.00617284 + txt002 + SPHERE CENTER -0.234932 0.0215878 0.687231 RAD 0.00617284 + txt002 + SPHERE CENTER -0.235241 0.00794264 0.707807 RAD 0.00617284 + txt002 + SPHERE CENTER -0.200749 0.0122285 0.711167 RAD 0.00617284 + txt002 + SPHERE CENTER -0.21623 -0.00691403 0.713055 RAD 0.00617284 + txt002 + SPHERE CENTER -0.196911 -0.00812553 0.697727 RAD 0.00617284 + txt002 + SPHERE CENTER -0.245428 -0.0910116 0.715923 RAD 0.0185185 + txt002 + SPHERE CENTER -0.234308 -0.0942304 0.737733 RAD 0.00617284 + txt002 + SPHERE CENTER -0.221514 -0.0854464 0.718528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.238704 -0.0714204 0.729364 RAD 0.00617284 + txt002 + SPHERE CENTER -0.258223 -0.0997955 0.735128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.262619 -0.0769856 0.726759 RAD 0.00617284 + txt002 + SPHERE CENTER -0.269343 -0.0965768 0.713318 RAD 0.00617284 + txt002 + SPHERE CENTER -0.241032 -0.113822 0.724292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.252152 -0.110603 0.702483 RAD 0.00617284 + txt002 + SPHERE CENTER -0.228237 -0.105038 0.705088 RAD 0.00617284 + txt002 + SPHERE CENTER -0.277564 -0.0243582 0.719322 RAD 0.0185185 + txt002 + SPHERE CENTER -0.275459 -0.0076281 0.737359 RAD 0.00617284 + txt002 + SPHERE CENTER -0.255218 -0.0167139 0.726523 RAD 0.00617284 + txt002 + SPHERE CENTER -0.270078 -0.00142185 0.714074 RAD 0.00617284 + txt002 + SPHERE CENTER -0.297806 -0.0152725 0.730157 RAD 0.00617284 + txt002 + SPHERE CENTER -0.292425 -0.00906621 0.706872 RAD 0.00617284 + txt002 + SPHERE CENTER -0.299911 -0.0320026 0.71212 RAD 0.00617284 + txt002 + SPHERE CENTER -0.282946 -0.0305645 0.742607 RAD 0.00617284 + txt002 + SPHERE CENTER -0.285051 -0.0472946 0.72457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.262704 -0.0396503 0.731771 RAD 0.00617284 + txt002 + SPHERE CENTER -0.310405 -0.0794645 0.682285 RAD 0.0185185 + txt002 + SPHERE CENTER -0.324811 -0.0817333 0.702209 RAD 0.00617284 + txt002 + SPHERE CENTER -0.300317 -0.0800146 0.704814 RAD 0.00617284 + txt002 + SPHERE CENTER -0.313378 -0.0603366 0.697613 RAD 0.00617284 + txt002 + SPHERE CENTER -0.334899 -0.0811832 0.67968 RAD 0.00617284 + txt002 + SPHERE CENTER -0.323466 -0.0597864 0.675083 RAD 0.00617284 + txt002 + SPHERE CENTER -0.320493 -0.0789143 0.659755 RAD 0.00617284 + txt002 + SPHERE CENTER -0.321838 -0.100861 0.686881 RAD 0.00617284 + txt002 + SPHERE CENTER -0.307433 -0.0985923 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER -0.297345 -0.0991425 0.689486 RAD 0.00617284 + txt002 + SPHERE CENTER -0.216626 -0.115028 0.652044 RAD 0.0185185 + txt002 + SPHERE CENTER -0.195663 -0.127519 0.655816 RAD 0.00617284 + txt002 + SPHERE CENTER -0.194866 -0.104303 0.647447 RAD 0.00617284 + txt002 + SPHERE CENTER -0.201738 -0.108803 0.670732 RAD 0.00617284 + txt002 + SPHERE CENTER -0.217423 -0.138245 0.660413 RAD 0.00617284 + txt002 + SPHERE CENTER -0.223497 -0.119529 0.675329 RAD 0.00617284 + txt002 + SPHERE CENTER -0.238386 -0.125754 0.656641 RAD 0.00617284 + txt002 + SPHERE CENTER -0.210551 -0.133744 0.637128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.231514 -0.121254 0.633356 RAD 0.00617284 + txt002 + SPHERE CENTER -0.209754 -0.110528 0.628759 RAD 0.00617284 + txt002 + SPHERE CENTER -0.281603 -0.103481 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.291073 -0.126206 0.620293 RAD 0.00617284 + txt002 + SPHERE CENTER -0.271345 -0.119897 0.633733 RAD 0.00617284 + txt002 + SPHERE CENTER -0.293457 -0.110246 0.638981 RAD 0.00617284 + txt002 + SPHERE CENTER -0.301332 -0.10979 0.604965 RAD 0.00617284 + txt002 + SPHERE CENTER -0.303716 -0.0938302 0.623653 RAD 0.00617284 + txt002 + SPHERE CENTER -0.291862 -0.0870656 0.603077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.279219 -0.119442 0.599717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.269749 -0.0967168 0.597829 RAD 0.00617284 + txt002 + SPHERE CENTER -0.25949 -0.113132 0.613157 RAD 0.00617284 + txt002 + SPHERE CENTER -0.21996 -0.0723919 0.591563 RAD 0.0185185 + txt002 + SPHERE CENTER -0.20388 -0.0673141 0.573526 RAD 0.00617284 + txt002 + SPHERE CENTER -0.216456 -0.0490355 0.584361 RAD 0.00617284 + txt002 + SPHERE CENTER -0.198742 -0.0609052 0.596811 RAD 0.00617284 + txt002 + SPHERE CENTER -0.207384 -0.0906706 0.580727 RAD 0.00617284 + txt002 + SPHERE CENTER -0.202246 -0.0842617 0.604012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.223463 -0.0957484 0.598764 RAD 0.00617284 + txt002 + SPHERE CENTER -0.225098 -0.0788008 0.568278 RAD 0.00617284 + txt002 + SPHERE CENTER -0.241177 -0.0838786 0.586315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.237674 -0.0605222 0.579113 RAD 0.00617284 + txt002 + SPHERE CENTER -0.471405 0.471405 1.11022e-16 RAD 0.166667 + txt002 + SPHERE CENTER -0.508983 0.690426 8.51251e-17 RAD 0.0555556 + txt002 + SPHERE CENTER -0.484794 0.755941 -0.0246914 RAD 0.0185185 + txt002 + SPHERE CENTER -0.47411 0.767658 -0.0436186 RAD 0.00617284 + txt002 + SPHERE CENTER -0.467528 0.744501 -0.0381316 RAD 0.00617284 + txt002 + SPHERE CENTER -0.489758 0.749038 -0.0478724 RAD 0.00617284 + txt002 + SPHERE CENTER -0.491377 0.779098 -0.0301783 RAD 0.00617284 + txt002 + SPHERE CENTER -0.507025 0.760478 -0.0344321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.502061 0.767382 -0.0112511 RAD 0.00617284 + txt002 + SPHERE CENTER -0.469146 0.774562 -0.0204376 RAD 0.00617284 + txt002 + SPHERE CENTER -0.47983 0.762845 -0.00151032 RAD 0.00617284 + txt002 + SPHERE CENTER -0.462564 0.751405 -0.0149506 RAD 0.00617284 + txt002 + SPHERE CENTER -0.436283 0.7029 -0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER -0.418941 0.714226 -0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER -0.43889 0.704751 -0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.44101 0.724842 -0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.416335 0.712374 0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER -0.438403 0.722991 0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER -0.433677 0.701048 0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER -0.414215 0.692283 -0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER -0.431557 0.680957 0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434163 0.682808 -0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER -0.478434 0.695668 -0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER -0.481931 0.703418 -0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER -0.500827 0.694124 -0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER -0.491475 0.716184 -0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER -0.459538 0.704962 -0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER -0.469082 0.717727 -0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.456041 0.697211 -0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER -0.46889 0.682902 -0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER -0.465393 0.675152 -0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER -0.487786 0.673608 -0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER -0.557494 0.743468 -0.0178949 RAD 0.0185185 + txt002 + SPHERE CENTER -0.560084 0.767402 -0.0233819 RAD 0.00617284 + txt002 + SPHERE CENTER -0.543179 0.760285 -0.00685171 RAD 0.00617284 + txt002 + SPHERE CENTER -0.53997 0.755145 -0.0307879 RAD 0.00617284 + txt002 + SPHERE CENTER -0.574398 0.750585 -0.0344251 RAD 0.00617284 + txt002 + SPHERE CENTER -0.554284 0.738328 -0.0418311 RAD 0.00617284 + txt002 + SPHERE CENTER -0.571808 0.726651 -0.0289382 RAD 0.00617284 + txt002 + SPHERE CENTER -0.577608 0.755725 -0.0104889 RAD 0.00617284 + txt002 + SPHERE CENTER -0.575017 0.731791 -0.00500196 RAD 0.00617284 + txt002 + SPHERE CENTER -0.560703 0.748608 0.00604126 RAD 0.00617284 + txt002 + SPHERE CENTER -0.551134 0.683194 -0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER -0.573364 0.687731 -0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.571303 0.682033 -0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER -0.56324 0.703871 -0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER -0.553195 0.688893 -0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER -0.543071 0.705033 -0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER -0.530964 0.684356 -0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER -0.561258 0.667055 -0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER -0.539027 0.662518 -0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER -0.559196 0.661356 -0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER -0.581682 0.677953 0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER -0.601808 0.682851 0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER -0.579842 0.680568 0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.58454 0.700216 0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.603648 0.680237 -0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER -0.58638 0.697602 -0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER -0.583522 0.675339 -0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER -0.59895 0.660588 0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER -0.578824 0.65569 -0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.576984 0.658304 0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER -0.515343 0.7507 0.0425863 RAD 0.0185185 + txt002 + SPHERE CENTER -0.506594 0.773394 0.0468401 RAD 0.00617284 + txt002 + SPHERE CENTER -0.491321 0.755462 0.0394341 RAD 0.00617284 + txt002 + SPHERE CENTER -0.507924 0.764807 0.0237283 RAD 0.00617284 + txt002 + SPHERE CENTER -0.530616 0.768632 0.0499923 RAD 0.00617284 + txt002 + SPHERE CENTER -0.531946 0.760045 0.0268805 RAD 0.00617284 + txt002 + SPHERE CENTER -0.539365 0.745938 0.0457385 RAD 0.00617284 + txt002 + SPHERE CENTER -0.514012 0.759287 0.065698 RAD 0.00617284 + txt002 + SPHERE CENTER -0.522762 0.736593 0.0614442 RAD 0.00617284 + txt002 + SPHERE CENTER -0.49874 0.741355 0.058292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.539531 0.685185 0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER -0.538818 0.693658 0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER -0.517905 0.691194 0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER -0.534075 0.708875 0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER -0.560445 0.687649 0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555702 0.702866 0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.561158 0.679176 0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER -0.544274 0.669969 0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER -0.544988 0.661495 0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER -0.523361 0.667505 0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER -0.466832 0.697658 0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER -0.447385 0.709346 0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.447429 0.703286 0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER -0.46231 0.721188 0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER -0.466788 0.703718 0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER -0.481713 0.71556 0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER -0.486235 0.692031 0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER -0.451907 0.685816 0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER -0.471354 0.674129 0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER -0.451951 0.679757 0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER -0.335322 0.607487 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.283164 0.659645 0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER -0.269894 0.672915 0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER -0.275822 0.649528 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.293281 0.666987 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.277236 0.683032 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.300624 0.677104 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.290507 0.669762 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.259777 0.665573 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.273047 0.652302 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.265705 0.642185 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.286452 0.603979 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.279361 0.614273 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.303327 0.613293 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.288206 0.628413 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.262487 0.604959 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.271332 0.619099 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.269578 0.594664 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.277607 0.589839 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.284698 0.579544 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.301572 0.588858 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.33883 0.656357 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.328536 0.663448 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.314396 0.654603 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.329516 0.639482 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.35297 0.665202 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.353951 0.641237 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.363265 0.658111 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.33785 0.680322 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.348145 0.673232 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.32371 0.671477 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.332034 0.663153 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.321274 0.684748 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.308341 0.666888 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.326131 0.678752 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.344967 0.681014 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.349824 0.675018 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.355727 0.659419 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.327177 0.669149 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.337937 0.647554 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.314244 0.651289 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.3877 0.659866 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.391875 0.684201 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37258 0.674986 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37258 0.674986 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.406996 0.669081 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.3877 0.659866 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.40282 0.644745 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.406996 0.669081 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.40282 0.644745 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.3877 0.659866 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.384191 0.610996 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.389739 0.622198 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.366159 0.617804 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.378964 0.63493 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.407771 0.61539 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.396997 0.628121 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.402224 0.604188 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.394966 0.598265 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.389418 0.587062 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.371386 0.593871 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.279656 0.610775 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.258061 0.621535 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.264057 0.616678 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.275921 0.634468 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.27366 0.615632 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.29152 0.628565 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.295255 0.604872 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.261795 0.597842 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.28339 0.587082 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.267791 0.592985 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.331813 0.558618 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.320611 0.55307 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.30788 0.563845 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.325005 0.57665 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.344544 0.547843 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.348938 0.571423 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.355747 0.553391 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.327419 0.535038 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.338621 0.540585 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.314688 0.545813 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.282943 0.555109 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.258608 0.550934 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.267823 0.570229 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.267823 0.570229 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.273728 0.535813 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.282943 0.555109 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.298064 0.539989 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.273728 0.535813 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.298064 0.539989 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.282943 0.555109 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.335322 0.607487 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.313405 0.629404 -0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.316595 0.626214 -0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.318408 0.606941 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.335868 0.624401 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.311592 0.648676 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.330864 0.646863 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.308402 0.651867 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.294133 0.631217 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.290942 0.634407 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.295946 0.611945 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.331813 0.558618 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.319608 0.539107 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.307378 0.556863 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.322499 0.541743 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.344043 0.540862 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.346933 0.543497 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.356248 0.560372 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.328923 0.555982 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.341128 0.575492 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.316693 0.573738 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.384191 0.610996 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.403702 0.623201 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.401066 0.62031 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.385946 0.635431 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.386827 0.613886 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.369071 0.626116 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.367317 0.601681 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.401947 0.598766 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.382437 0.586561 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399312 0.595876 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.316914 0.678274 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.305407 0.69384 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.296616 0.671002 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.317721 0.674446 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.325704 0.701111 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.338018 0.681717 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.337211 0.685545 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.3046 0.697667 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.316107 0.682101 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.295809 0.67483 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.3877 0.659866 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.391875 0.684201 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37258 0.674986 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37258 0.674986 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.406996 0.669081 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.3877 0.659866 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.40282 0.644745 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.406996 0.669081 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.40282 0.644745 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.3877 0.659866 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.33883 0.656357 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.329538 0.677411 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.314897 0.661584 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.332022 0.674389 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.353472 0.672184 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.355956 0.669162 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.362764 0.65113 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.336346 0.659378 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.345639 0.638325 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.321705 0.643552 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.264535 0.625895 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.248969 0.637402 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.268363 0.625088 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.271807 0.646193 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.245142 0.638209 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.267979 0.647 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.260708 0.626702 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.241698 0.617105 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.257264 0.605598 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.261092 0.604791 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.286452 0.603979 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.265398 0.613271 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.26842 0.610787 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.281225 0.627912 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.283431 0.606463 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.299257 0.621104 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.304484 0.59717 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.270625 0.589337 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.291679 0.580045 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.273647 0.586853 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.282943 0.555109 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.258608 0.550934 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.267823 0.570229 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.267823 0.570229 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.273728 0.535813 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.282943 0.555109 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.298064 0.539989 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.273728 0.535813 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.298064 0.539989 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.282943 0.555109 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.645066 0.554344 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.681385 0.616373 -0.129006 RAD 0.0185185 + txt002 + SPHERE CENTER -0.678928 0.639472 -0.137375 RAD 0.00617284 + txt002 + SPHERE CENTER -0.661636 0.629767 -0.122663 RAD 0.00617284 + txt002 + SPHERE CENTER -0.664108 0.621631 -0.145845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.698678 0.626079 -0.143718 RAD 0.00617284 + txt002 + SPHERE CENTER -0.683858 0.608237 -0.152187 RAD 0.00617284 + txt002 + SPHERE CENTER -0.701135 0.602979 -0.135349 RAD 0.00617284 + txt002 + SPHERE CENTER -0.696205 0.634214 -0.120537 RAD 0.00617284 + txt002 + SPHERE CENTER -0.698662 0.611115 -0.112168 RAD 0.00617284 + txt002 + SPHERE CENTER -0.678912 0.624508 -0.105825 RAD 0.00617284 + txt002 + SPHERE CENTER -0.649723 0.609912 -0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER -0.640648 0.631982 -0.0560094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.625749 0.614812 -0.0656463 RAD 0.00617284 + txt002 + SPHERE CENTER -0.64267 0.62585 -0.0798417 RAD 0.00617284 + txt002 + SPHERE CENTER -0.664623 0.627081 -0.0527151 RAD 0.00617284 + txt002 + SPHERE CENTER -0.666645 0.620949 -0.0765474 RAD 0.00617284 + txt002 + SPHERE CENTER -0.673698 0.605012 -0.0590577 RAD 0.00617284 + txt002 + SPHERE CENTER -0.647702 0.616044 -0.0385197 RAD 0.00617284 + txt002 + SPHERE CENTER -0.656777 0.593974 -0.0448623 RAD 0.00617284 + txt002 + SPHERE CENTER -0.632802 0.598874 -0.0481565 RAD 0.00617284 + txt002 + SPHERE CENTER -0.607573 0.617144 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.595495 0.63057 -0.139672 RAD 0.00617284 + txt002 + SPHERE CENTER -0.594239 0.605919 -0.140323 RAD 0.00617284 + txt002 + SPHERE CENTER -0.615286 0.617371 -0.146288 RAD 0.00617284 + txt002 + SPHERE CENTER -0.608828 0.641795 -0.122182 RAD 0.00617284 + txt002 + SPHERE CENTER -0.628619 0.628595 -0.128798 RAD 0.00617284 + txt002 + SPHERE CENTER -0.620906 0.628369 -0.105343 RAD 0.00617284 + txt002 + SPHERE CENTER -0.587782 0.630343 -0.116217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.59986 0.616917 -0.0993785 RAD 0.00617284 + txt002 + SPHERE CENTER -0.586526 0.605692 -0.116868 RAD 0.00617284 + txt002 + SPHERE CENTER -0.676727 0.560805 -0.177765 RAD 0.0185185 + txt002 + SPHERE CENTER -0.689897 0.57563 -0.192477 RAD 0.00617284 + txt002 + SPHERE CENTER -0.693998 0.575587 -0.168128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.673115 0.585222 -0.177114 RAD 0.00617284 + txt002 + SPHERE CENTER -0.672626 0.560848 -0.202114 RAD 0.00617284 + txt002 + SPHERE CENTER -0.655844 0.57044 -0.186751 RAD 0.00617284 + txt002 + SPHERE CENTER -0.659456 0.546023 -0.187402 RAD 0.00617284 + txt002 + SPHERE CENTER -0.693509 0.551213 -0.193128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.680339 0.536388 -0.178416 RAD 0.00617284 + txt002 + SPHERE CENTER -0.69761 0.55117 -0.16878 RAD 0.00617284 + txt002 + SPHERE CENTER -0.602915 0.561576 -0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER -0.602201 0.570049 -0.194773 RAD 0.00617284 + txt002 + SPHERE CENTER -0.623084 0.560414 -0.185788 RAD 0.00617284 + txt002 + SPHERE CENTER -0.615021 0.582252 -0.177557 RAD 0.00617284 + txt002 + SPHERE CENTER -0.582032 0.571211 -0.180578 RAD 0.00617284 + txt002 + SPHERE CENTER -0.594852 0.583414 -0.163362 RAD 0.00617284 + txt002 + SPHERE CENTER -0.582745 0.562738 -0.157397 RAD 0.00617284 + txt002 + SPHERE CENTER -0.590095 0.549372 -0.188808 RAD 0.00617284 + txt002 + SPHERE CENTER -0.590808 0.540899 -0.165627 RAD 0.00617284 + txt002 + SPHERE CENTER -0.610978 0.539737 -0.179823 RAD 0.00617284 + txt002 + SPHERE CENTER -0.640408 0.498776 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.627785 0.478525 -0.166213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.615951 0.497935 -0.156576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.630799 0.484234 -0.142381 RAD 0.00617284 + txt002 + SPHERE CENTER -0.652241 0.479365 -0.169507 RAD 0.00617284 + txt002 + SPHERE CENTER -0.655255 0.485075 -0.145675 RAD 0.00617284 + txt002 + SPHERE CENTER -0.664864 0.499616 -0.163165 RAD 0.00617284 + txt002 + SPHERE CENTER -0.637394 0.493066 -0.183703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.650016 0.513317 -0.17736 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62556 0.512476 -0.174066 RAD 0.00617284 + txt002 + SPHERE CENTER -0.718878 0.553573 -0.117284 RAD 0.0185185 + txt002 + SPHERE CENTER -0.73992 0.563328 -0.108814 RAD 0.00617284 + txt002 + SPHERE CENTER -0.720935 0.559693 -0.0934517 RAD 0.00617284 + txt002 + SPHERE CENTER -0.719679 0.577348 -0.110668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.737863 0.557208 -0.132647 RAD 0.00617284 + txt002 + SPHERE CENTER -0.717623 0.571228 -0.1345 RAD 0.00617284 + txt002 + SPHERE CENTER -0.716821 0.547453 -0.141116 RAD 0.00617284 + txt002 + SPHERE CENTER -0.739118 0.539553 -0.115431 RAD 0.00617284 + txt002 + SPHERE CENTER -0.718076 0.529798 -0.1239 RAD 0.00617284 + txt002 + SPHERE CENTER -0.720133 0.535918 -0.100068 RAD 0.00617284 + txt002 + SPHERE CENTER -0.682558 0.491544 -0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.688647 0.474542 -0.0825505 RAD 0.00617284 + txt002 + SPHERE CENTER -0.666351 0.485132 -0.0818993 RAD 0.00617284 + txt002 + SPHERE CENTER -0.686417 0.498226 -0.0759343 RAD 0.00617284 + txt002 + SPHERE CENTER -0.704854 0.480953 -0.10004 RAD 0.00617284 + txt002 + SPHERE CENTER -0.702624 0.504637 -0.093424 RAD 0.00617284 + txt002 + SPHERE CENTER -0.698765 0.497955 -0.116879 RAD 0.00617284 + txt002 + SPHERE CENTER -0.684788 0.46786 -0.106005 RAD 0.00617284 + txt002 + SPHERE CENTER -0.678699 0.484862 -0.122844 RAD 0.00617284 + txt002 + SPHERE CENTER -0.662492 0.47845 -0.105354 RAD 0.00617284 + txt002 + SPHERE CENTER -0.687216 0.547112 -0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER -0.690713 0.554862 -0.0274488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.667813 0.552739 -0.0364345 RAD 0.00617284 + txt002 + SPHERE CENTER -0.682694 0.570641 -0.0446649 RAD 0.00617284 + txt002 + SPHERE CENTER -0.710116 0.549235 -0.0416443 RAD 0.00617284 + txt002 + SPHERE CENTER -0.702097 0.565014 -0.0588603 RAD 0.00617284 + txt002 + SPHERE CENTER -0.706619 0.541484 -0.0648253 RAD 0.00617284 + txt002 + SPHERE CENTER -0.695235 0.531333 -0.0334138 RAD 0.00617284 + txt002 + SPHERE CENTER -0.691738 0.523582 -0.0565949 RAD 0.00617284 + txt002 + SPHERE CENTER -0.672335 0.52921 -0.0423994 RAD 0.00617284 + txt002 + SPHERE CENTER -0.471405 0.471405 -0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER -0.501645 0.501645 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.499795 0.519956 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.493653 0.523893 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.479397 0.509638 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.507788 0.497708 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.48739 0.48739 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER -0.509638 0.479397 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.522043 0.511963 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER -0.523893 0.493653 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.515901 0.515901 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER -0.542955 0.490576 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.559233 0.507719 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.539759 0.502501 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.536564 0.514426 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.562428 0.495794 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER -0.539759 0.502501 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.54615 0.478651 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.565623 0.483869 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.549345 0.466726 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.54615 0.478651 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.490576 0.542955 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.483869 0.565623 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.466726 0.549345 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.478651 0.54615 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.507719 0.559233 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.502501 0.539759 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.514426 0.536564 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.495794 0.562428 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.502501 0.539759 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.478651 0.54615 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.430095 0.482473 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.430434 0.489762 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.449569 0.477255 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER -0.445366 0.500519 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.41096 0.49498 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER -0.425893 0.505737 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.410622 0.487691 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER -0.415162 0.471716 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.414824 0.464428 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434297 0.45921 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.419026 0.523783 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.404771 0.538038 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER -0.410297 0.515053 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.427756 0.532513 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.4135 0.546768 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.436486 0.541242 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.427756 0.532513 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.396041 0.529309 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.410297 0.515053 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.401567 0.506323 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399854 0.452233 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.377186 0.45894 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.396659 0.464158 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.393464 0.476083 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.380381 0.447015 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.396659 0.464158 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.40305 0.440308 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.383576 0.43509 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.406245 0.428383 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.40305 0.440308 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.482473 0.430095 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.48121 0.407271 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER -0.464428 0.414824 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.487691 0.410622 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER -0.499256 0.422542 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.505737 0.425893 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.500519 0.445366 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.475992 0.426744 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.477255 0.449569 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER -0.45921 0.434297 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.452233 0.399854 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.43509 0.383576 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.428383 0.406245 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.440308 0.40305 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.45894 0.377186 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.464158 0.396659 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.476083 0.393464 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.447015 0.380381 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER -0.464158 0.396659 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.440308 0.40305 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.523783 0.419026 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.538038 0.404771 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.515053 0.410297 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.532513 0.427756 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.546768 0.4135 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.541242 0.436486 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.532513 0.427756 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.529309 0.396041 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.515053 0.410297 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.506323 0.401567 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.607487 0.335322 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.659645 0.283164 -0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER -0.672915 0.269894 -0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER -0.649528 0.275822 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.666987 0.293281 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.683032 0.277236 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.677104 0.300624 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.669762 0.290507 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.665573 0.259777 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.652302 0.273047 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.642185 0.265705 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.603979 0.286452 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.592776 0.280905 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.580045 0.291679 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.59717 0.304484 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.61671 0.275678 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.621104 0.299257 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.627912 0.281225 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.599585 0.262872 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.610787 0.26842 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.586853 0.273647 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.656357 0.33883 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.661904 0.350033 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.638325 0.345639 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.65113 0.362764 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.679937 0.343224 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.669162 0.355956 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.674389 0.332022 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.667131 0.326099 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.661584 0.314897 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.643552 0.321705 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.663153 0.332034 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.685865 0.340177 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.679339 0.33606 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.669651 0.355123 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.669679 0.336151 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.653465 0.351097 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.646968 0.328008 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.679367 0.317089 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.656656 0.308945 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.672841 0.312971 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.659866 0.3877 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.664041 0.412036 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.644745 0.40282 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.644745 0.40282 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.679161 0.396915 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.659866 0.3877 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.674986 0.37258 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.679161 0.396915 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.674986 0.37258 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.659866 0.3877 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.610996 0.384191 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.600701 0.391282 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.586561 0.382437 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.601681 0.367317 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.625136 0.393037 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.626116 0.369071 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.635431 0.385946 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.610016 0.408157 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62031 0.401066 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.595876 0.399312 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.610775 0.279656 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.602632 0.256944 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.587686 0.273158 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.606749 0.26347 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62572 0.263442 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.629838 0.269968 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.633864 0.286153 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.606658 0.27313 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.614801 0.295841 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.591712 0.289344 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.558618 0.331813 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.551527 0.342108 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.575492 0.341128 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.560372 0.356248 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.534652 0.332793 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.543497 0.346933 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.541743 0.322499 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.549772 0.317673 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.556863 0.307378 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.573738 0.316693 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555109 0.282943 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.530773 0.278768 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.539989 0.298064 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.539989 0.298064 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.545894 0.263648 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555109 0.282943 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.570229 0.267823 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.545894 0.263648 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.570229 0.267823 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555109 0.282943 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.645066 0.554344 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.668521 0.610229 0.153697 RAD 0.0185185 + txt002 + SPHERE CENTER -0.663938 0.633406 0.160875 RAD 0.00617284 + txt002 + SPHERE CENTER -0.64522 0.617928 0.156428 RAD 0.00617284 + txt002 + SPHERE CENTER -0.65892 0.626429 0.137727 RAD 0.00617284 + txt002 + SPHERE CENTER -0.687239 0.625707 0.158144 RAD 0.00617284 + txt002 + SPHERE CENTER -0.682221 0.61873 0.134996 RAD 0.00617284 + txt002 + SPHERE CENTER -0.691822 0.602531 0.150967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.673539 0.617206 0.176845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.678123 0.59403 0.169668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.654822 0.601728 0.172398 RAD 0.00617284 + txt002 + SPHERE CENTER -0.598918 0.585648 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.580238 0.601562 0.162601 RAD 0.00617284 + txt002 + SPHERE CENTER -0.581665 0.587563 0.142311 RAD 0.00617284 + txt002 + SPHERE CENTER -0.59781 0.605914 0.14581 RAD 0.00617284 + txt002 + SPHERE CENTER -0.597491 0.599646 0.18016 RAD 0.00617284 + txt002 + SPHERE CENTER -0.615063 0.603999 0.163369 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616171 0.583732 0.177429 RAD 0.00617284 + txt002 + SPHERE CENTER -0.581346 0.581295 0.176661 RAD 0.00617284 + txt002 + SPHERE CENTER -0.600026 0.565381 0.173931 RAD 0.00617284 + txt002 + SPHERE CENTER -0.582773 0.567297 0.156372 RAD 0.00617284 + txt002 + SPHERE CENTER -0.619787 0.622977 0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.608008 0.63767 0.0834188 RAD 0.00617284 + txt002 + SPHERE CENTER -0.601637 0.613891 0.0853287 RAD 0.00617284 + txt002 + SPHERE CENTER -0.623239 0.620102 0.0751099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.626157 0.646756 0.0974792 RAD 0.00617284 + txt002 + SPHERE CENTER -0.641389 0.629188 0.0891702 RAD 0.00617284 + txt002 + SPHERE CENTER -0.637936 0.632063 0.113449 RAD 0.00617284 + txt002 + SPHERE CENTER -0.604555 0.640545 0.107698 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616334 0.625852 0.123668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.598184 0.616766 0.109608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.714669 0.578925 0.104938 RAD 0.0185185 + txt002 + SPHERE CENTER -0.729812 0.597914 0.109385 RAD 0.00617284 + txt002 + SPHERE CENTER -0.711617 0.592661 0.125228 RAD 0.00617284 + txt002 + SPHERE CENTER -0.70632 0.602084 0.103028 RAD 0.00617284 + txt002 + SPHERE CENTER -0.732864 0.584178 0.0890951 RAD 0.00617284 + txt002 + SPHERE CENTER -0.709372 0.588348 0.0827387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.71772 0.565189 0.0846485 RAD 0.00617284 + txt002 + SPHERE CENTER -0.738161 0.574755 0.111295 RAD 0.00617284 + txt002 + SPHERE CENTER -0.723017 0.555767 0.106848 RAD 0.00617284 + txt002 + SPHERE CENTER -0.719965 0.569503 0.127138 RAD 0.00617284 + txt002 + SPHERE CENTER -0.665934 0.591673 0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER -0.658095 0.605761 0.0319289 RAD 0.00617284 + txt002 + SPHERE CENTER -0.647455 0.607672 0.0541285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.643855 0.58746 0.0404111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.676573 0.589763 0.0284303 RAD 0.00617284 + txt002 + SPHERE CENTER -0.662334 0.571461 0.0369125 RAD 0.00617284 + txt002 + SPHERE CENTER -0.684413 0.575674 0.0471312 RAD 0.00617284 + txt002 + SPHERE CENTER -0.680174 0.609975 0.0421477 RAD 0.00617284 + txt002 + SPHERE CENTER -0.688013 0.595887 0.0608487 RAD 0.00617284 + txt002 + SPHERE CENTER -0.669535 0.611885 0.0643473 RAD 0.00617284 + txt002 + SPHERE CENTER -0.691213 0.52304 0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER -0.712906 0.511567 0.0596212 RAD 0.00617284 + txt002 + SPHERE CENTER -0.699372 0.507717 0.079911 RAD 0.00617284 + txt002 + SPHERE CENTER -0.710453 0.529503 0.0764123 RAD 0.00617284 + txt002 + SPHERE CENTER -0.704747 0.526889 0.0420622 RAD 0.00617284 + txt002 + SPHERE CENTER -0.702295 0.544826 0.0588533 RAD 0.00617284 + txt002 + SPHERE CENTER -0.683054 0.538362 0.044793 RAD 0.00617284 + txt002 + SPHERE CENTER -0.693665 0.505104 0.0455609 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671972 0.516576 0.0482916 RAD 0.00617284 + txt002 + SPHERE CENTER -0.680131 0.501254 0.0658506 RAD 0.00617284 + txt002 + SPHERE CENTER -0.6938 0.541596 0.165419 RAD 0.0185185 + txt002 + SPHERE CENTER -0.70016 0.547376 0.188567 RAD 0.00617284 + txt002 + SPHERE CENTER -0.676324 0.546319 0.182211 RAD 0.00617284 + txt002 + SPHERE CENTER -0.690564 0.564621 0.173728 RAD 0.00617284 + txt002 + SPHERE CENTER -0.717636 0.542652 0.171776 RAD 0.00617284 + txt002 + SPHERE CENTER -0.70804 0.559898 0.156937 RAD 0.00617284 + txt002 + SPHERE CENTER -0.711276 0.536873 0.148628 RAD 0.00617284 + txt002 + SPHERE CENTER -0.703396 0.524351 0.180258 RAD 0.00617284 + txt002 + SPHERE CENTER -0.697037 0.518571 0.157111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.679561 0.523294 0.173902 RAD 0.00617284 + txt002 + SPHERE CENTER -0.670344 0.48571 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.67091 0.466887 0.138803 RAD 0.00617284 + txt002 + SPHERE CENTER -0.650637 0.480853 0.136894 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671107 0.490138 0.147112 RAD 0.00617284 + txt002 + SPHERE CENTER -0.690617 0.471745 0.124743 RAD 0.00617284 + txt002 + SPHERE CENTER -0.690815 0.494995 0.133052 RAD 0.00617284 + txt002 + SPHERE CENTER -0.690052 0.490567 0.108773 RAD 0.00617284 + txt002 + SPHERE CENTER -0.670147 0.46246 0.114524 RAD 0.00617284 + txt002 + SPHERE CENTER -0.669581 0.481283 0.0985541 RAD 0.00617284 + txt002 + SPHERE CENTER -0.649874 0.476425 0.112614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624197 0.517014 0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER -0.60809 0.516313 0.190293 RAD 0.00617284 + txt002 + SPHERE CENTER -0.60089 0.524375 0.168094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616221 0.538029 0.181811 RAD 0.00617284 + txt002 + SPHERE CENTER -0.631397 0.508952 0.193792 RAD 0.00617284 + txt002 + SPHERE CENTER -0.639529 0.530668 0.18531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.647504 0.509653 0.175091 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616065 0.495298 0.180075 RAD 0.00617284 + txt002 + SPHERE CENTER -0.632172 0.495999 0.161374 RAD 0.00617284 + txt002 + SPHERE CENTER -0.608865 0.50336 0.157875 RAD 0.00617284 + txt002 + SPHERE CENTER -0.607487 0.335322 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.629404 0.313405 0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.626214 0.316595 0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.606941 0.318408 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624401 0.335868 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.648676 0.311592 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.646863 0.330864 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.651867 0.308402 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.631217 0.294133 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.634407 0.290942 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.611945 0.295946 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.558618 0.331813 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.537564 0.341105 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.540585 0.338621 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.553391 0.355747 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555596 0.334297 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.571423 0.348938 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.57665 0.325005 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.542791 0.317172 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.563845 0.30788 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.545813 0.314688 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.610996 0.384191 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.601704 0.405245 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.587062 0.389418 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.604188 0.402224 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.625637 0.400018 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.628121 0.396997 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.63493 0.378964 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.608512 0.387213 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.617804 0.366159 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.593871 0.371386 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.678274 0.316914 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.697473 0.31938 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.674538 0.318074 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.681812 0.338182 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.701209 0.31822 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.685547 0.337022 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.682009 0.315754 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.693935 0.298112 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.674736 0.295646 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671 0.296805 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.659866 0.3877 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.664041 0.412036 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.644745 0.40282 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.644745 0.40282 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.679161 0.396915 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.659866 0.3877 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.674986 0.37258 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.679161 0.396915 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.674986 0.37258 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.659866 0.3877 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.656357 0.33883 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.675867 0.351035 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.673232 0.348145 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.658111 0.363265 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.658993 0.341721 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.641237 0.353951 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.639482 0.329516 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.674113 0.3266 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.654603 0.314396 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671477 0.32371 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.625895 0.264535 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.623429 0.245336 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.604627 0.260997 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624736 0.268271 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.644697 0.248874 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.646004 0.271809 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.647163 0.268073 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624589 0.2416 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.627055 0.2608 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.605787 0.257262 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.603979 0.286452 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.591774 0.266942 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.579544 0.284698 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.594664 0.269578 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616209 0.268696 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.619099 0.271332 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.628413 0.288206 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.601088 0.283817 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.613293 0.303327 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.588858 0.301572 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555109 0.282943 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.530773 0.278768 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.539989 0.298064 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.539989 0.298064 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.545894 0.263648 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555109 0.282943 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.570229 0.267823 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.545894 0.263648 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.570229 0.267823 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555109 0.282943 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.471405 0.471405 0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER -0.441164 0.501645 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.424703 0.518106 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER -0.420089 0.505261 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.437548 0.522721 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.445778 0.51449 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.458623 0.519105 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.462239 0.498029 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.428319 0.497031 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.44478 0.48057 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.423704 0.484186 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399854 0.490576 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.382226 0.502679 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399854 0.490576 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.405389 0.511231 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.382226 0.502679 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.405389 0.511231 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399854 0.490576 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.376691 0.482024 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.39432 0.469922 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.39432 0.469922 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.452233 0.542955 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.44013 0.560583 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.431578 0.53742 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.452233 0.542955 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.460785 0.566118 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.472887 0.548489 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.472887 0.548489 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.44013 0.560583 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.452233 0.542955 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.431578 0.53742 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.512714 0.482473 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.51514 0.495905 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.492654 0.48988 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.506323 0.506323 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.5352 0.488498 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER -0.526383 0.498917 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.532774 0.475067 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.521531 0.472055 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.519105 0.458623 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.499045 0.46603 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.523783 0.523783 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.527958 0.548119 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.508662 0.538903 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.508662 0.538903 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.543078 0.532998 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.523783 0.523783 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.538903 0.508662 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.543078 0.532998 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.538903 0.508662 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.523783 0.523783 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.542955 0.452233 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.564273 0.4539 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.542955 0.452233 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.548489 0.472887 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.564273 0.4539 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.548489 0.472887 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.542955 0.452233 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.558738 0.433245 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.53742 0.431578 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.53742 0.431578 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.460336 0.430095 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.446904 0.427669 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.436486 0.436486 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.45293 0.450155 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.470754 0.421278 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.47678 0.443764 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.484186 0.423704 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.454311 0.407609 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER -0.467742 0.410035 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.443892 0.416426 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.490576 0.399854 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.488909 0.378536 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.469922 0.39432 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.490576 0.399854 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.509564 0.384071 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.511231 0.405389 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.511231 0.405389 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.488909 0.378536 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.490576 0.399854 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.469922 0.39432 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.419026 0.419026 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.39469 0.414851 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.403906 0.434147 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.403906 0.434147 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.409811 0.399731 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.419026 0.419026 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434147 0.403906 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.409811 0.399731 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434147 0.403906 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.419026 0.419026 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.643951 -0.172546 1.11022e-16 RAD 0.166667 + txt002 + SPHERE CENTER -0.835815 -0.157543 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.871646 -0.122136 0.165419 RAD 0.0185185 + txt002 + SPHERE CENTER -0.871334 -0.102403 0.180258 RAD 0.00617284 + txt002 + SPHERE CENTER -0.850164 -0.113406 0.173902 RAD 0.00617284 + txt002 + SPHERE CENTER -0.862937 -0.100577 0.157111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.892817 -0.111133 0.171776 RAD 0.00617284 + txt002 + SPHERE CENTER -0.884419 -0.109307 0.148628 RAD 0.00617284 + txt002 + SPHERE CENTER -0.893129 -0.130866 0.156937 RAD 0.00617284 + txt002 + SPHERE CENTER -0.880044 -0.123961 0.188567 RAD 0.00617284 + txt002 + SPHERE CENTER -0.880356 -0.143694 0.173728 RAD 0.00617284 + txt002 + SPHERE CENTER -0.858873 -0.134964 0.182211 RAD 0.00617284 + txt002 + SPHERE CENTER -0.799077 -0.135649 0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER -0.781177 -0.120908 0.180075 RAD 0.00617284 + txt002 + SPHERE CENTER -0.778973 -0.13149 0.157875 RAD 0.00617284 + txt002 + SPHERE CENTER -0.795477 -0.113462 0.161374 RAD 0.00617284 + txt002 + SPHERE CENTER -0.801282 -0.125067 0.193792 RAD 0.00617284 + txt002 + SPHERE CENTER -0.815582 -0.11762 0.175091 RAD 0.00617284 + txt002 + SPHERE CENTER -0.819182 -0.139808 0.18531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.784778 -0.143095 0.190293 RAD 0.00617284 + txt002 + SPHERE CENTER -0.802678 -0.157836 0.181811 RAD 0.00617284 + txt002 + SPHERE CENTER -0.782573 -0.153678 0.168094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.82339 -0.0854653 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.811594 -0.0654286 0.114524 RAD 0.00617284 + txt002 + SPHERE CENTER -0.80102 -0.0876595 0.112614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.820516 -0.0820122 0.0985541 RAD 0.00617284 + txt002 + SPHERE CENTER -0.833964 -0.0632344 0.124743 RAD 0.00617284 + txt002 + SPHERE CENTER -0.842886 -0.079818 0.108773 RAD 0.00617284 + txt002 + SPHERE CENTER -0.845761 -0.083271 0.133052 RAD 0.00617284 + txt002 + SPHERE CENTER -0.814468 -0.0688817 0.138803 RAD 0.00617284 + txt002 + SPHERE CENTER -0.826265 -0.0889183 0.147112 RAD 0.00617284 + txt002 + SPHERE CENTER -0.803895 -0.0911125 0.136894 RAD 0.00617284 + txt002 + SPHERE CENTER -0.908384 -0.14403 0.104938 RAD 0.0185185 + txt002 + SPHERE CENTER -0.926643 -0.128672 0.111295 RAD 0.00617284 + txt002 + SPHERE CENTER -0.90826 -0.133221 0.127138 RAD 0.00617284 + txt002 + SPHERE CENTER -0.904034 -0.1198 0.106848 RAD 0.00617284 + txt002 + SPHERE CENTER -0.926768 -0.139481 0.0890951 RAD 0.00617284 + txt002 + SPHERE CENTER -0.904159 -0.130608 0.0846485 RAD 0.00617284 + txt002 + SPHERE CENTER -0.908508 -0.154838 0.0827387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.930993 -0.152902 0.109385 RAD 0.00617284 + txt002 + SPHERE CENTER -0.912733 -0.16826 0.103028 RAD 0.00617284 + txt002 + SPHERE CENTER -0.912609 -0.157451 0.125228 RAD 0.00617284 + txt002 + SPHERE CENTER -0.860128 -0.107359 0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER -0.853284 -0.0905999 0.0455609 RAD 0.00617284 + txt002 + SPHERE CENTER -0.839638 -0.0940331 0.0658506 RAD 0.00617284 + txt002 + SPHERE CENTER -0.840233 -0.111382 0.0482916 RAD 0.00617284 + txt002 + SPHERE CENTER -0.873773 -0.103926 0.0420622 RAD 0.00617284 + txt002 + SPHERE CENTER -0.860723 -0.124708 0.044793 RAD 0.00617284 + txt002 + SPHERE CENTER -0.880618 -0.120685 0.0588533 RAD 0.00617284 + txt002 + SPHERE CENTER -0.873178 -0.086577 0.0596212 RAD 0.00617284 + txt002 + SPHERE CENTER -0.880022 -0.103336 0.0764123 RAD 0.00617284 + txt002 + SPHERE CENTER -0.859532 -0.0900102 0.079911 RAD 0.00617284 + txt002 + SPHERE CENTER -0.872552 -0.179437 0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER -0.894035 -0.188167 0.0421477 RAD 0.00617284 + txt002 + SPHERE CENTER -0.885777 -0.195141 0.0643473 RAD 0.00617284 + txt002 + SPHERE CENTER -0.89378 -0.172046 0.0608487 RAD 0.00617284 + txt002 + SPHERE CENTER -0.880811 -0.172463 0.0284303 RAD 0.00617284 + txt002 + SPHERE CENTER -0.880556 -0.156342 0.0471312 RAD 0.00617284 + txt002 + SPHERE CENTER -0.859328 -0.163733 0.0369125 RAD 0.00617284 + txt002 + SPHERE CENTER -0.872807 -0.195558 0.0319289 RAD 0.00617284 + txt002 + SPHERE CENTER -0.851325 -0.186828 0.0404111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.864549 -0.202532 0.0541285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.884071 -0.194213 0.153697 RAD 0.0185185 + txt002 + SPHERE CENTER -0.891905 -0.197746 0.176845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.867957 -0.193701 0.172398 RAD 0.00617284 + txt002 + SPHERE CENTER -0.884286 -0.175383 0.169668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.908019 -0.198259 0.158144 RAD 0.00617284 + txt002 + SPHERE CENTER -0.900401 -0.175896 0.150967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.900186 -0.194726 0.134996 RAD 0.00617284 + txt002 + SPHERE CENTER -0.89169 -0.216576 0.160875 RAD 0.00617284 + txt002 + SPHERE CENTER -0.883856 -0.213043 0.137727 RAD 0.00617284 + txt002 + SPHERE CENTER -0.867741 -0.212531 0.156428 RAD 0.00617284 + txt002 + SPHERE CENTER -0.84824 -0.229621 0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.843832 -0.25245 0.107698 RAD 0.00617284 + txt002 + SPHERE CENTER -0.826426 -0.235043 0.109608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.846687 -0.233837 0.123668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.865646 -0.247028 0.0974792 RAD 0.00617284 + txt002 + SPHERE CENTER -0.868501 -0.228415 0.113449 RAD 0.00617284 + txt002 + SPHERE CENTER -0.870053 -0.224198 0.0891702 RAD 0.00617284 + txt002 + SPHERE CENTER -0.845385 -0.248234 0.0834188 RAD 0.00617284 + txt002 + SPHERE CENTER -0.849792 -0.225404 0.0751099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.827978 -0.230827 0.0853287 RAD 0.00617284 + txt002 + SPHERE CENTER -0.811502 -0.207727 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.794108 -0.212743 0.176661 RAD 0.00617284 + txt002 + SPHERE CENTER -0.788345 -0.199907 0.156372 RAD 0.00617284 + txt002 + SPHERE CENTER -0.802328 -0.189621 0.173931 RAD 0.00617284 + txt002 + SPHERE CENTER -0.817265 -0.220563 0.18016 RAD 0.00617284 + txt002 + SPHERE CENTER -0.825486 -0.197441 0.177429 RAD 0.00617284 + txt002 + SPHERE CENTER -0.83466 -0.215547 0.163369 RAD 0.00617284 + txt002 + SPHERE CENTER -0.803282 -0.230849 0.162601 RAD 0.00617284 + txt002 + SPHERE CENTER -0.820676 -0.225832 0.14581 RAD 0.00617284 + txt002 + SPHERE CENTER -0.797518 -0.218012 0.142311 RAD 0.00617284 + txt002 + SPHERE CENTER -0.643951 -0.172546 0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER -0.61371 -0.142305 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.597249 -0.125845 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER -0.592635 -0.138689 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.610094 -0.12123 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.618324 -0.12946 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.631169 -0.124846 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.634785 -0.145921 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.600865 -0.14692 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.617326 -0.163381 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.596251 -0.159765 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.5724 -0.153374 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.554772 -0.141271 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.5724 -0.153374 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.577935 -0.13272 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.554772 -0.141271 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.577935 -0.13272 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.5724 -0.153374 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.549237 -0.161926 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.566866 -0.174029 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.566866 -0.174029 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624779 -0.100996 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.612676 -0.0833673 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.604124 -0.10653 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624779 -0.100996 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.633331 -0.0778329 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.645433 -0.0954616 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.645433 -0.0954616 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.612676 -0.0833673 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624779 -0.100996 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.604124 -0.10653 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.68526 -0.161477 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.687686 -0.148046 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.6652 -0.154071 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.678869 -0.137627 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.707746 -0.155452 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER -0.698929 -0.145033 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.70532 -0.168883 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.694077 -0.171896 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.691651 -0.185327 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671591 -0.177921 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.696329 -0.120168 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.700504 -0.095832 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.681209 -0.105047 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.681209 -0.105047 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.715624 -0.110952 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.696329 -0.120168 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.711449 -0.135288 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.715624 -0.110952 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.711449 -0.135288 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.696329 -0.120168 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.715501 -0.191718 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.736819 -0.190051 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.715501 -0.191718 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.721035 -0.171063 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.736819 -0.190051 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.721035 -0.171063 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.715501 -0.191718 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.731284 -0.210706 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.709966 -0.212373 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.709966 -0.212373 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.632882 -0.213855 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.61945 -0.216282 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.609032 -0.207465 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.625476 -0.193796 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.6433 -0.222672 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.649326 -0.200186 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.656732 -0.220246 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.626857 -0.236341 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER -0.640288 -0.233915 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616438 -0.227525 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.663122 -0.244096 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.661455 -0.265414 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.642468 -0.249631 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.663122 -0.244096 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.68211 -0.25988 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.683777 -0.238562 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.683777 -0.238562 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.661455 -0.265414 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.663122 -0.244096 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.642468 -0.249631 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.591572 -0.224924 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.567237 -0.2291 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.576452 -0.209804 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.576452 -0.209804 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.582357 -0.24422 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.591572 -0.224924 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.606693 -0.240045 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.582357 -0.24422 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.606693 -0.240045 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.591572 -0.224924 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.69376 0.0133465 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.674309 0.0838533 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.66171 0.103063 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.653258 0.0800983 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.673446 0.0876683 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.682761 0.106818 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.694497 0.0914233 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.69536 0.0876083 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.662574 0.0992478 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.675172 0.0800382 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.654121 0.0762832 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62221 0.0325183 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.604582 0.0446211 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62221 0.0325183 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.627745 0.053173 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.604582 0.0446211 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.627745 0.053173 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62221 0.0325183 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.599047 0.0239663 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616676 0.0118635 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616676 0.0118635 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.666287 0.0539145 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.662466 0.0547519 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.660752 0.0332597 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.682791 0.0439578 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.668 0.0754066 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.688325 0.0646126 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671821 0.0745692 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.645962 0.0647085 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.649783 0.0638711 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.644249 0.0432164 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.745859 0.0646815 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.750021 0.0887955 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.729506 0.078459 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.732161 0.0813312 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.766375 0.075018 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.748514 0.0675537 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.762212 0.050904 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.763719 0.0721458 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.759557 0.0480318 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.743204 0.0618093 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.737837 0.0347427 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.747099 0.0542122 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.743371 0.0553974 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.7241 0.0550267 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.741565 0.0335575 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.718566 0.0343719 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.732303 0.014088 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.760836 0.0339282 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.751574 0.0144587 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.757108 0.0351134 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.76531 -0.0058253 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.786629 -0.00415829 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.76531 -0.0058253 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.770845 0.0148294 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.786629 -0.00415829 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.770845 0.0148294 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.76531 -0.0058253 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.781094 -0.024813 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.759776 -0.02648 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.759776 -0.02648 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.701782 0.0432853 0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.693716 0.0608821 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.677932 0.0496759 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.694884 0.0652402 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.717566 0.0544915 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.718734 0.0588496 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.725632 0.0368947 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.700615 0.0389272 0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.708681 0.0213304 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.684831 0.027721 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.721234 -0.0272215 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.720593 -0.0310802 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.7 -0.0246945 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.718114 -0.00820099 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.741827 -0.0336072 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.739347 -0.010728 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.742467 -0.0297485 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.723713 -0.0501007 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.724354 -0.046242 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.70312 -0.043715 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.649684 -0.00804971 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.628657 -0.00328338 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.630031 0.000378614 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.642244 0.0152909 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.648309 -0.0117117 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.661896 0.00686255 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.669336 -0.016478 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.636097 -0.026624 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.657124 -0.0313903 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.637471 -0.022962 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.835815 -0.157543 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.899353 -0.119969 -0.117284 RAD 0.0185185 + txt002 + SPHERE CENTER -0.909872 -0.0977075 -0.115431 RAD 0.00617284 + txt002 + SPHERE CENTER -0.891613 -0.104052 -0.100068 RAD 0.00617284 + txt002 + SPHERE CENTER -0.886771 -0.0997803 -0.1239 RAD 0.00617284 + txt002 + SPHERE CENTER -0.917612 -0.113625 -0.132647 RAD 0.00617284 + txt002 + SPHERE CENTER -0.894512 -0.115698 -0.141116 RAD 0.00617284 + txt002 + SPHERE CENTER -0.907093 -0.135886 -0.1345 RAD 0.00617284 + txt002 + SPHERE CENTER -0.922453 -0.117896 -0.108814 RAD 0.00617284 + txt002 + SPHERE CENTER -0.911935 -0.140158 -0.110668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.904194 -0.124241 -0.0934517 RAD 0.00617284 + txt002 + SPHERE CENTER -0.868703 -0.130205 -0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER -0.867758 -0.11253 -0.0334138 RAD 0.00617284 + txt002 + SPHERE CENTER -0.846864 -0.122142 -0.0423994 RAD 0.00617284 + txt002 + SPHERE CENTER -0.860854 -0.107566 -0.0565949 RAD 0.00617284 + txt002 + SPHERE CENTER -0.889596 -0.120593 -0.0416443 RAD 0.00617284 + txt002 + SPHERE CENTER -0.882692 -0.115629 -0.0648253 RAD 0.00617284 + txt002 + SPHERE CENTER -0.890541 -0.138267 -0.0588603 RAD 0.00617284 + txt002 + SPHERE CENTER -0.875606 -0.135168 -0.0274488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.876551 -0.152843 -0.0446649 RAD 0.00617284 + txt002 + SPHERE CENTER -0.854713 -0.14478 -0.0364345 RAD 0.00617284 + txt002 + SPHERE CENTER -0.836885 -0.0844101 -0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.826973 -0.0627848 -0.106005 RAD 0.00617284 + txt002 + SPHERE CENTER -0.81296 -0.083104 -0.105354 RAD 0.00617284 + txt002 + SPHERE CENTER -0.830202 -0.0805529 -0.122844 RAD 0.00617284 + txt002 + SPHERE CENTER -0.850898 -0.0640908 -0.10004 RAD 0.00617284 + txt002 + SPHERE CENTER -0.854126 -0.0818589 -0.116879 RAD 0.00617284 + txt002 + SPHERE CENTER -0.860809 -0.0857161 -0.093424 RAD 0.00617284 + txt002 + SPHERE CENTER -0.833656 -0.0666419 -0.0825505 RAD 0.00617284 + txt002 + SPHERE CENTER -0.843568 -0.0882673 -0.0759343 RAD 0.00617284 + txt002 + SPHERE CENTER -0.819643 -0.0869612 -0.0818993 RAD 0.00617284 + txt002 + SPHERE CENTER -0.866465 -0.147308 -0.177765 RAD 0.0185185 + txt002 + SPHERE CENTER -0.876203 -0.130609 -0.193128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.879733 -0.128522 -0.16878 RAD 0.00617284 + txt002 + SPHERE CENTER -0.857385 -0.124356 -0.178416 RAD 0.00617284 + txt002 + SPHERE CENTER -0.862935 -0.149395 -0.202114 RAD 0.00617284 + txt002 + SPHERE CENTER -0.844117 -0.143141 -0.187402 RAD 0.00617284 + txt002 + SPHERE CENTER -0.853198 -0.166093 -0.186751 RAD 0.00617284 + txt002 + SPHERE CENTER -0.885283 -0.153561 -0.192477 RAD 0.00617284 + txt002 + SPHERE CENTER -0.875546 -0.170259 -0.177114 RAD 0.00617284 + txt002 + SPHERE CENTER -0.888813 -0.151474 -0.168128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.803997 -0.111748 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.798532 -0.108311 -0.183703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.797989 -0.131037 -0.174066 RAD 0.00617284 + txt002 + SPHERE CENTER -0.819589 -0.119537 -0.17736 RAD 0.00617284 + txt002 + SPHERE CENTER -0.80454 -0.0890219 -0.169507 RAD 0.00617284 + txt002 + SPHERE CENTER -0.825597 -0.100248 -0.163165 RAD 0.00617284 + txt002 + SPHERE CENTER -0.810005 -0.0924597 -0.145675 RAD 0.00617284 + txt002 + SPHERE CENTER -0.78294 -0.100522 -0.166213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.788405 -0.10396 -0.142381 RAD 0.00617284 + txt002 + SPHERE CENTER -0.782397 -0.123249 -0.156576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.802927 -0.184881 -0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER -0.785723 -0.180723 -0.188808 RAD 0.00617284 + txt002 + SPHERE CENTER -0.798991 -0.161937 -0.179823 RAD 0.00617284 + txt002 + SPHERE CENTER -0.782104 -0.173028 -0.165627 RAD 0.00617284 + txt002 + SPHERE CENTER -0.78966 -0.203667 -0.180578 RAD 0.00617284 + txt002 + SPHERE CENTER -0.786041 -0.195972 -0.157397 RAD 0.00617284 + txt002 + SPHERE CENTER -0.806864 -0.207825 -0.163362 RAD 0.00617284 + txt002 + SPHERE CENTER -0.806546 -0.192576 -0.194773 RAD 0.00617284 + txt002 + SPHERE CENTER -0.82375 -0.196734 -0.177557 RAD 0.00617284 + txt002 + SPHERE CENTER -0.819813 -0.17379 -0.185788 RAD 0.00617284 + txt002 + SPHERE CENTER -0.898283 -0.193102 -0.129006 RAD 0.0185185 + txt002 + SPHERE CENTER -0.920038 -0.201143 -0.120537 RAD 0.00617284 + txt002 + SPHERE CENTER -0.900209 -0.201384 -0.105825 RAD 0.00617284 + txt002 + SPHERE CENTER -0.910616 -0.17991 -0.112168 RAD 0.00617284 + txt002 + SPHERE CENTER -0.918112 -0.192861 -0.143718 RAD 0.00617284 + txt002 + SPHERE CENTER -0.90869 -0.171628 -0.135349 RAD 0.00617284 + txt002 + SPHERE CENTER -0.896357 -0.18482 -0.152187 RAD 0.00617284 + txt002 + SPHERE CENTER -0.907705 -0.214335 -0.137375 RAD 0.00617284 + txt002 + SPHERE CENTER -0.88595 -0.206294 -0.145845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.887876 -0.214576 -0.122663 RAD 0.00617284 + txt002 + SPHERE CENTER -0.834745 -0.230676 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.824206 -0.252002 -0.116217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.810793 -0.231282 -0.116868 RAD 0.00617284 + txt002 + SPHERE CENTER -0.827952 -0.234336 -0.0993785 RAD 0.00617284 + txt002 + SPHERE CENTER -0.848158 -0.251396 -0.122182 RAD 0.00617284 + txt002 + SPHERE CENTER -0.851905 -0.23373 -0.105343 RAD 0.00617284 + txt002 + SPHERE CENTER -0.858698 -0.23007 -0.128798 RAD 0.00617284 + txt002 + SPHERE CENTER -0.830999 -0.248342 -0.139672 RAD 0.00617284 + txt002 + SPHERE CENTER -0.841538 -0.227016 -0.146288 RAD 0.00617284 + txt002 + SPHERE CENTER -0.817586 -0.227621 -0.140323 RAD 0.00617284 + txt002 + SPHERE CENTER -0.867633 -0.203337 -0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER -0.868948 -0.209658 -0.0385197 RAD 0.00617284 + txt002 + SPHERE CENTER -0.84746 -0.202239 -0.0481565 RAD 0.00617284 + txt002 + SPHERE CENTER -0.865773 -0.186008 -0.0448623 RAD 0.00617284 + txt002 + SPHERE CENTER -0.889121 -0.210757 -0.0527151 RAD 0.00617284 + txt002 + SPHERE CENTER -0.885946 -0.187106 -0.0590577 RAD 0.00617284 + txt002 + SPHERE CENTER -0.887806 -0.204436 -0.0765474 RAD 0.00617284 + txt002 + SPHERE CENTER -0.870808 -0.226988 -0.0560094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.869493 -0.220667 -0.0798417 RAD 0.00617284 + txt002 + SPHERE CENTER -0.84932 -0.219569 -0.0656463 RAD 0.00617284 + txt002 + SPHERE CENTER -0.69376 0.0133465 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.668775 0.0631985 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.661946 0.0667914 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.65711 0.0452771 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.680354 0.0511945 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.673611 0.0847128 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.692019 0.069116 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.680439 0.08112 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.650366 0.0787954 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.657195 0.0752026 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.64553 0.0572811 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62221 0.0325183 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.604582 0.0446211 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62221 0.0325183 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.627745 0.053173 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.604582 0.0446211 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.627745 0.053173 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62221 0.0325183 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.599047 0.0239663 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616676 0.0118635 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616676 0.0118635 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.649684 -0.00804971 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.634953 -0.000226782 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.655218 0.012605 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.635947 0.0122343 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.629419 -0.0208815 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.630413 -0.00842045 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.644149 -0.0287044 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.64869 -0.0205108 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.66342 -0.0283337 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.668955 -0.00767898 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.740325 0.0440268 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.746894 0.0650768 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.739183 0.0653796 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.723153 0.0607735 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.748035 0.0437239 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.724295 0.0394207 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.741466 0.0226739 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.764065 0.04833 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.757496 0.02728 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.756355 0.0486329 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.721234 -0.0272215 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.732368 -0.0484665 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.715699 -0.0478762 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.737738 -0.0371781 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.737902 -0.0278118 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.743272 -0.0165234 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.726768 -0.00656677 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.715864 -0.0385099 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.70473 -0.0172649 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.699195 -0.0379196 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.76531 -0.0058253 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.786629 -0.00415829 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.76531 -0.0058253 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.770845 0.0148294 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.786629 -0.00415829 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.770845 0.0148294 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.76531 -0.0058253 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.781094 -0.024813 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.759776 -0.02648 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.759776 -0.02648 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.712851 0.0845947 -0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER -0.706291 0.107813 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.689001 0.0909853 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.701434 0.0896851 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.730141 0.101422 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.725284 0.0832945 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.736701 0.0782041 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.717709 0.102723 -0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER -0.724268 0.0795043 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.700418 0.0858949 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.737837 0.0347427 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.740802 0.0511556 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.718185 0.043171 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.730397 0.0580833 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.760455 0.0427273 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.750049 0.0496549 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.757489 0.0263144 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.748242 0.027815 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.745277 0.0114021 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.725625 0.0198304 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.666287 0.0539145 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.650692 0.0721382 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.645053 0.0564414 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.663167 0.072935 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671925 0.0696112 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.6844 0.070408 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.68752 0.0513875 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.653812 0.0531177 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.669407 0.034894 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.648173 0.0374209 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.643951 -0.172546 -0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER -0.674191 -0.142305 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.672341 -0.123995 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.666199 -0.120057 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.651943 -0.134313 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.680334 -0.146243 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.659936 -0.156561 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER -0.682184 -0.164554 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.69459 -0.131987 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER -0.696439 -0.150298 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.688447 -0.12805 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER -0.715501 -0.153374 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.731779 -0.136231 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.712305 -0.141449 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.70911 -0.129524 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.734974 -0.148156 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER -0.712305 -0.141449 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.718696 -0.165299 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.738169 -0.160081 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.721891 -0.177224 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.718696 -0.165299 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.663122 -0.100996 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.656415 -0.0783272 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.639272 -0.0946054 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.651197 -0.0978007 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.680265 -0.0847178 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.675047 -0.104191 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.686972 -0.107387 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.66834 -0.0815225 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.675047 -0.104191 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.651197 -0.0978007 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.602641 -0.161477 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.60298 -0.154189 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.622115 -0.166695 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER -0.617912 -0.143431 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.583506 -0.148971 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER -0.598439 -0.138214 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.583168 -0.156259 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER -0.587708 -0.172234 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.58737 -0.179523 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.606843 -0.184741 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.591572 -0.120168 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.577317 -0.105912 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER -0.582843 -0.128897 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.600302 -0.111438 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.586046 -0.0971825 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.609032 -0.102708 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.600302 -0.111438 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.568587 -0.114642 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.582843 -0.128897 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.574113 -0.137627 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.5724 -0.191718 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.549732 -0.185011 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.569205 -0.179793 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.56601 -0.167868 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.552927 -0.196936 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.569205 -0.179793 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.575596 -0.203643 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.556122 -0.208861 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.578791 -0.215568 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.575596 -0.203643 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.655019 -0.213855 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.653756 -0.23668 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER -0.636974 -0.229127 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.660237 -0.233329 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671802 -0.221409 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.678283 -0.218058 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.673065 -0.198584 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.648538 -0.217207 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.649801 -0.194382 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER -0.631756 -0.209653 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624779 -0.244096 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.607636 -0.260374 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.600929 -0.237705 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.612854 -0.240901 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.631486 -0.266765 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.636704 -0.247291 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.648629 -0.250487 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.619561 -0.26357 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER -0.636704 -0.247291 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.612854 -0.240901 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.696329 -0.224924 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.710584 -0.23918 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.687599 -0.233654 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.705059 -0.216195 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.719314 -0.23045 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.713788 -0.207465 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.705059 -0.216195 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.701855 -0.24791 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.687599 -0.233654 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.678869 -0.242384 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.786005 -0.343435 8.51251e-17 RAD 0.0555556 + txt002 + SPHERE CENTER -0.82165 -0.392454 0.0425863 RAD 0.0185185 + txt002 + SPHERE CENTER -0.824791 -0.400556 0.065698 RAD 0.00617284 + txt002 + SPHERE CENTER -0.802599 -0.392663 0.058292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.821021 -0.376528 0.0614442 RAD 0.00617284 + txt002 + SPHERE CENTER -0.843843 -0.400347 0.0499923 RAD 0.00617284 + txt002 + SPHERE CENTER -0.840073 -0.376319 0.0457385 RAD 0.00617284 + txt002 + SPHERE CENTER -0.840701 -0.392245 0.0268805 RAD 0.00617284 + txt002 + SPHERE CENTER -0.82542 -0.416482 0.0468401 RAD 0.00617284 + txt002 + SPHERE CENTER -0.822279 -0.40838 0.0237283 RAD 0.00617284 + txt002 + SPHERE CENTER -0.803228 -0.408589 0.0394341 RAD 0.00617284 + txt002 + SPHERE CENTER -0.753118 -0.370774 0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER -0.734271 -0.367981 0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER -0.731279 -0.362711 0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER -0.745269 -0.348136 0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER -0.756109 -0.376044 0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER -0.767107 -0.356199 0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER -0.774956 -0.378837 0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER -0.74212 -0.390619 0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.760966 -0.393412 0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER -0.739128 -0.385349 0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER -0.80984 -0.323622 0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER -0.80634 -0.308073 0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER -0.786996 -0.316395 0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER -0.802721 -0.300378 0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER -0.829184 -0.315299 0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER -0.825565 -0.307605 0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER -0.832685 -0.330849 0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.813459 -0.331317 0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER -0.81696 -0.346866 0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER -0.794116 -0.339639 0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER -0.854538 -0.365116 -0.0178949 RAD 0.0185185 + txt002 + SPHERE CENTER -0.878086 -0.365674 -0.0104889 RAD 0.00617284 + txt002 + SPHERE CENTER -0.859887 -0.367962 0.00604126 RAD 0.00617284 + txt002 + SPHERE CENTER -0.863875 -0.346241 -0.00500196 RAD 0.00617284 + txt002 + SPHERE CENTER -0.872736 -0.362827 -0.0344251 RAD 0.00617284 + txt002 + SPHERE CENTER -0.858526 -0.343394 -0.0289382 RAD 0.00617284 + txt002 + SPHERE CENTER -0.849188 -0.362269 -0.0418311 RAD 0.00617284 + txt002 + SPHERE CENTER -0.868748 -0.384548 -0.0233819 RAD 0.00617284 + txt002 + SPHERE CENTER -0.8452 -0.38399 -0.0307879 RAD 0.00617284 + txt002 + SPHERE CENTER -0.85055 -0.386837 -0.00685171 RAD 0.00617284 + txt002 + SPHERE CENTER -0.842728 -0.296284 0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER -0.848999 -0.272611 0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER -0.828835 -0.281616 0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER -0.829121 -0.278432 -0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.862893 -0.287278 -0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER -0.843015 -0.293099 -0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER -0.856621 -0.310951 -0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER -0.862606 -0.290462 0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER -0.856335 -0.314135 0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.842441 -0.299468 0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.818893 -0.316097 -0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER -0.819591 -0.297057 -0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER -0.814956 -0.293153 -0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER -0.79807 -0.304244 -0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER -0.823527 -0.320001 -0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER -0.802007 -0.327188 -0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER -0.822829 -0.339041 -0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER -0.840413 -0.30891 -0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.839716 -0.32795 -0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER -0.835779 -0.305006 -0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER -0.797815 -0.412267 -0.0246914 RAD 0.0185185 + txt002 + SPHERE CENTER -0.793573 -0.436217 -0.0204376 RAD 0.00617284 + txt002 + SPHERE CENTER -0.776294 -0.419454 -0.0149506 RAD 0.00617284 + txt002 + SPHERE CENTER -0.796968 -0.420728 -0.00151032 RAD 0.00617284 + txt002 + SPHERE CENTER -0.815094 -0.42903 -0.0301783 RAD 0.00617284 + txt002 + SPHERE CENTER -0.818489 -0.413542 -0.0112511 RAD 0.00617284 + txt002 + SPHERE CENTER -0.819335 -0.405081 -0.0344321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.79442 -0.427756 -0.0436186 RAD 0.00617284 + txt002 + SPHERE CENTER -0.798662 -0.403807 -0.0478724 RAD 0.00617284 + txt002 + SPHERE CENTER -0.777141 -0.410993 -0.0381316 RAD 0.00617284 + txt002 + SPHERE CENTER -0.76217 -0.363249 -0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER -0.747522 -0.356966 -0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER -0.759239 -0.339469 -0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER -0.740618 -0.352002 -0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER -0.750453 -0.380746 -0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER -0.743549 -0.375782 -0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER -0.765101 -0.387029 -0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.769074 -0.368213 -0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER -0.783722 -0.374496 -0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER -0.780791 -0.350716 -0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER -0.729282 -0.390587 -0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER -0.704862 -0.392427 -0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER -0.717401 -0.374248 -0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER -0.714218 -0.373948 0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.716744 -0.408767 0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER -0.726099 -0.390287 0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER -0.741164 -0.406927 0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER -0.719927 -0.409067 -0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER -0.744347 -0.407227 -0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.732465 -0.390887 -0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.594141 -0.358439 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.542042 -0.409774 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.517869 -0.413579 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.528508 -0.393219 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.525596 -0.395831 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.531404 -0.430134 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.539131 -0.412386 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555577 -0.426328 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.534315 -0.427522 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.558488 -0.423716 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.544953 -0.407161 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.522591 -0.339267 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.504962 -0.327164 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.522591 -0.339267 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.528125 -0.318612 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.504962 -0.327164 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.528125 -0.318612 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.522591 -0.339267 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.499428 -0.347819 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.517056 -0.359921 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.517056 -0.359921 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.550064 -0.379835 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.529037 -0.375068 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.530412 -0.371406 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.542624 -0.356494 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.548689 -0.383497 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.562276 -0.364922 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.569716 -0.388263 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.536477 -0.398409 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.557504 -0.403175 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.537852 -0.394747 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.613592 -0.428945 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.612625 -0.451897 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.593593 -0.436515 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.614807 -0.432663 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.632624 -0.444328 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.634806 -0.425094 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.633591 -0.421376 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.61141 -0.448179 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.612377 -0.425227 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.592379 -0.432797 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.621614 -0.399007 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.620974 -0.402865 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.600381 -0.39648 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.618494 -0.379986 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.642207 -0.405392 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.639728 -0.382513 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.642848 -0.401533 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624094 -0.421886 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624734 -0.418027 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.603501 -0.4155 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.665691 -0.37761 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.687009 -0.375943 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.665691 -0.37761 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671225 -0.356956 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.687009 -0.375943 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671225 -0.356956 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.665691 -0.37761 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.681475 -0.396598 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.660156 -0.398265 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.660156 -0.398265 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.586119 -0.388377 -0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.570335 -0.399584 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.562269 -0.381987 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.569167 -0.403942 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.594185 -0.405974 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.593017 -0.410332 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.609969 -0.394768 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.587286 -0.384019 -0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.60307 -0.372813 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.57922 -0.366422 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.638217 -0.337042 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.64748 -0.317573 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.643752 -0.316388 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624481 -0.316758 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.641945 -0.338228 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.618946 -0.337413 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.632683 -0.357697 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.661216 -0.337857 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.651954 -0.357326 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.657489 -0.336672 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.566667 -0.317871 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.562847 -0.317033 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.561133 -0.338525 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.583171 -0.327827 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.568381 -0.296378 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.588706 -0.307172 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.572202 -0.297216 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.546343 -0.307077 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.550163 -0.307914 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.544629 -0.328569 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.594141 -0.358439 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.547576 -0.389119 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.525642 -0.386849 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.528407 -0.379645 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.538964 -0.366733 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.544812 -0.396323 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.558134 -0.376207 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.566746 -0.398593 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.534255 -0.409235 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.556189 -0.411505 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.537019 -0.402031 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.522591 -0.339267 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.504962 -0.327164 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.522591 -0.339267 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.528125 -0.318612 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.504962 -0.327164 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.528125 -0.318612 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.522591 -0.339267 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.499428 -0.347819 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.517056 -0.359921 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.517056 -0.359921 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.566667 -0.317871 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.551072 -0.299647 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.545434 -0.315344 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.563547 -0.29885 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.572306 -0.302174 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.584781 -0.301377 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.587901 -0.320398 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.554192 -0.318667 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.569787 -0.336891 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.548554 -0.334364 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.619127 -0.408291 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.617918 -0.415912 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.597788 -0.406911 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616439 -0.39183 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.639257 -0.417292 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.637778 -0.39321 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.640465 -0.409671 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.620605 -0.432372 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.621814 -0.424751 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.600475 -0.423371 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.638217 -0.337042 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.641183 -0.320629 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.618565 -0.328614 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.630777 -0.313702 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.660835 -0.329058 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.65043 -0.32213 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.65787 -0.345471 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.648623 -0.34397 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.645657 -0.360383 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.626005 -0.351955 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.665691 -0.37761 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.687009 -0.375943 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.665691 -0.37761 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671225 -0.356956 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.687009 -0.375943 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671225 -0.356956 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.665691 -0.37761 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.681475 -0.396598 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.660156 -0.398265 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.660156 -0.398265 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.57505 -0.429687 0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER -0.55776 -0.446515 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.5512 -0.423296 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.562617 -0.428387 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.58161 -0.452905 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.586467 -0.434777 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.5989 -0.436077 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.570193 -0.447815 0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER -0.587483 -0.430987 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.563633 -0.424596 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.621614 -0.399007 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.632748 -0.420252 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.61608 -0.419661 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.638118 -0.408963 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.638282 -0.399597 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.643653 -0.388308 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.627149 -0.378352 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616244 -0.410295 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.60511 -0.38905 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.599576 -0.409705 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.550064 -0.379835 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.535334 -0.372012 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555599 -0.35918 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.536327 -0.359551 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.529799 -0.392667 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.530793 -0.380205 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.54453 -0.400489 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.549071 -0.392296 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.563801 -0.400119 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.569335 -0.379464 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0996195 -0.371785 0.544331 RAD 0.166667 + txt002 + SPHERE CENTER 0.220501 -0.393621 0.729516 RAD 0.0555556 + txt002 + SPHERE CENTER 0.279642 -0.368601 0.766439 RAD 0.0185185 + txt002 + SPHERE CENTER 0.299716 -0.354293 0.765035 RAD 0.00617284 + txt002 + SPHERE CENTER 0.292196 -0.366989 0.745238 RAD 0.00617284 + txt002 + SPHERE CENTER 0.279022 -0.347717 0.753281 RAD 0.00617284 + txt002 + SPHERE CENTER 0.287162 -0.355904 0.786236 RAD 0.00617284 + txt002 + SPHERE CENTER 0.266468 -0.349329 0.774481 RAD 0.00617284 + txt002 + SPHERE CENTER 0.267088 -0.370213 0.787639 RAD 0.00617284 + txt002 + SPHERE CENTER 0.300337 -0.375177 0.778193 RAD 0.00617284 + txt002 + SPHERE CENTER 0.280263 -0.389485 0.779597 RAD 0.00617284 + txt002 + SPHERE CENTER 0.292817 -0.387873 0.758396 RAD 0.00617284 + txt002 + SPHERE CENTER 0.281062 -0.372464 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER 0.289441 -0.362978 0.671279 RAD 0.00617284 + txt002 + SPHERE CENTER 0.270044 -0.378255 0.671155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.267771 -0.35549 0.680442 RAD 0.00617284 + txt002 + SPHERE CENTER 0.30046 -0.357187 0.692603 RAD 0.00617284 + txt002 + SPHERE CENTER 0.278789 -0.349699 0.701767 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29208 -0.366673 0.713804 RAD 0.00617284 + txt002 + SPHERE CENTER 0.302733 -0.379952 0.683315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.294353 -0.389438 0.704516 RAD 0.00617284 + txt002 + SPHERE CENTER 0.283335 -0.395229 0.683192 RAD 0.00617284 + txt002 + SPHERE CENTER 0.238665 -0.321889 0.726118 RAD 0.0185185 + txt002 + SPHERE CENTER 0.250544 -0.304702 0.71296 RAD 0.00617284 + txt002 + SPHERE CENTER 0.259421 -0.327715 0.714081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.238717 -0.32307 0.701455 RAD 0.00617284 + txt002 + SPHERE CENTER 0.229788 -0.298875 0.724997 RAD 0.00617284 + txt002 + SPHERE CENTER 0.21796 -0.317244 0.713492 RAD 0.00617284 + txt002 + SPHERE CENTER 0.217908 -0.316063 0.738155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.250492 -0.30352 0.737623 RAD 0.00617284 + txt002 + SPHERE CENTER 0.238612 -0.320707 0.750781 RAD 0.00617284 + txt002 + SPHERE CENTER 0.259369 -0.326533 0.738744 RAD 0.00617284 + txt002 + SPHERE CENTER 0.219082 -0.389758 0.803476 RAD 0.0185185 + txt002 + SPHERE CENTER 0.228779 -0.378635 0.823273 RAD 0.00617284 + txt002 + SPHERE CENTER 0.24293 -0.383364 0.8036 RAD 0.00617284 + txt002 + SPHERE CENTER 0.225483 -0.365937 0.802355 RAD 0.00617284 + txt002 + SPHERE CENTER 0.20493 -0.385029 0.823149 RAD 0.00617284 + txt002 + SPHERE CENTER 0.201634 -0.372331 0.802231 RAD 0.00617284 + txt002 + SPHERE CENTER 0.195233 -0.396152 0.803352 RAD 0.00617284 + txt002 + SPHERE CENTER 0.222377 -0.402455 0.824394 RAD 0.00617284 + txt002 + SPHERE CENTER 0.21268 -0.413578 0.804597 RAD 0.00617284 + txt002 + SPHERE CENTER 0.236529 -0.407185 0.804721 RAD 0.00617284 + txt002 + SPHERE CENTER 0.178104 -0.343046 0.763155 RAD 0.0185185 + txt002 + SPHERE CENTER 0.177083 -0.319723 0.771198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.198298 -0.332294 0.772443 RAD 0.00617284 + txt002 + SPHERE CENTER 0.189464 -0.325124 0.750529 RAD 0.00617284 + txt002 + SPHERE CENTER 0.156889 -0.330475 0.76191 RAD 0.00617284 + txt002 + SPHERE CENTER 0.16927 -0.335876 0.741241 RAD 0.00617284 + txt002 + SPHERE CENTER 0.157909 -0.353797 0.753867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.165722 -0.337645 0.783824 RAD 0.00617284 + txt002 + SPHERE CENTER 0.166743 -0.360967 0.775781 RAD 0.00617284 + txt002 + SPHERE CENTER 0.186938 -0.350216 0.785069 RAD 0.00617284 + txt002 + SPHERE CENTER 0.15994 -0.414778 0.766553 RAD 0.0185185 + txt002 + SPHERE CENTER 0.147477 -0.412573 0.787754 RAD 0.00617284 + txt002 + SPHERE CENTER 0.172167 -0.412448 0.787878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.15977 -0.39322 0.77859 RAD 0.00617284 + txt002 + SPHERE CENTER 0.13525 -0.414903 0.766429 RAD 0.00617284 + txt002 + SPHERE CENTER 0.147543 -0.39555 0.757266 RAD 0.00617284 + txt002 + SPHERE CENTER 0.147713 -0.417108 0.745229 RAD 0.00617284 + txt002 + SPHERE CENTER 0.147647 -0.434131 0.775717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.16011 -0.436336 0.754517 RAD 0.00617284 + txt002 + SPHERE CENTER 0.172338 -0.434006 0.775841 RAD 0.00617284 + txt002 + SPHERE CENTER 0.261479 -0.440333 0.769837 RAD 0.0185185 + txt002 + SPHERE CENTER 0.282991 -0.443285 0.781591 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282046 -0.4302 0.760673 RAD 0.00617284 + txt002 + SPHERE CENTER 0.271991 -0.421181 0.781342 RAD 0.00617284 + txt002 + SPHERE CENTER 0.262424 -0.453417 0.790755 RAD 0.00617284 + txt002 + SPHERE CENTER 0.251423 -0.431313 0.790506 RAD 0.00617284 + txt002 + SPHERE CENTER 0.240911 -0.450466 0.779001 RAD 0.00617284 + txt002 + SPHERE CENTER 0.27248 -0.462437 0.770086 RAD 0.00617284 + txt002 + SPHERE CENTER 0.250967 -0.459485 0.758332 RAD 0.00617284 + txt002 + SPHERE CENTER 0.271534 -0.449353 0.749168 RAD 0.00617284 + txt002 + SPHERE CENTER 0.202338 -0.465353 0.732914 RAD 0.0185185 + txt002 + SPHERE CENTER 0.204606 -0.486123 0.746073 RAD 0.00617284 + txt002 + SPHERE CENTER 0.223366 -0.470107 0.744951 RAD 0.00617284 + txt002 + SPHERE CENTER 0.202946 -0.464339 0.757577 RAD 0.00617284 + txt002 + SPHERE CENTER 0.183578 -0.481368 0.734036 RAD 0.00617284 + txt002 + SPHERE CENTER 0.181918 -0.459584 0.745541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.18131 -0.460599 0.720878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.203998 -0.487137 0.72141 RAD 0.00617284 + txt002 + SPHERE CENTER 0.201729 -0.466367 0.708251 RAD 0.00617284 + txt002 + SPHERE CENTER 0.222757 -0.471122 0.720288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.262898 -0.444196 0.695877 RAD 0.0185185 + txt002 + SPHERE CENTER 0.285685 -0.449273 0.687835 RAD 0.00617284 + txt002 + SPHERE CENTER 0.27701 -0.426189 0.68659 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282528 -0.436139 0.708504 RAD 0.00617284 + txt002 + SPHERE CENTER 0.271573 -0.46728 0.697123 RAD 0.00617284 + txt002 + SPHERE CENTER 0.268416 -0.454146 0.717791 RAD 0.00617284 + txt002 + SPHERE CENTER 0.248787 -0.462204 0.705165 RAD 0.00617284 + txt002 + SPHERE CENTER 0.266055 -0.45733 0.675209 RAD 0.00617284 + txt002 + SPHERE CENTER 0.243269 -0.452254 0.683251 RAD 0.00617284 + txt002 + SPHERE CENTER 0.257381 -0.434246 0.673964 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31427 -0.31427 0.544331 RAD 0.0555556 + txt002 + SPHERE CENTER 0.367156 -0.277961 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.374298 -0.269898 0.485076 RAD 0.00617284 + txt002 + SPHERE CENTER 0.362218 -0.291334 0.487134 RAD 0.00617284 + txt002 + SPHERE CENTER 0.350338 -0.270045 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER 0.379235 -0.256525 0.505236 RAD 0.00617284 + txt002 + SPHERE CENTER 0.355276 -0.256671 0.511201 RAD 0.00617284 + txt002 + SPHERE CENTER 0.372093 -0.264588 0.527454 RAD 0.00617284 + txt002 + SPHERE CENTER 0.391115 -0.277815 0.501329 RAD 0.00617284 + txt002 + SPHERE CENTER 0.383973 -0.285878 0.523547 RAD 0.00617284 + txt002 + SPHERE CENTER 0.379036 -0.299251 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31427 -0.31427 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER 0.304189 -0.304189 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29042 -0.307879 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.307879 -0.29042 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.328039 -0.31058 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER 0.331729 -0.29681 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.33812 -0.32066 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31058 -0.328039 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER 0.32066 -0.33812 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29681 -0.331729 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.297666 -0.252306 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.305995 -0.235688 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER 0.321516 -0.245915 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.312359 -0.259438 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282145 -0.242079 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER 0.288509 -0.265828 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.273816 -0.258696 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.291303 -0.228556 0.509559 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282974 -0.245173 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.306824 -0.238783 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.367156 -0.277961 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.385852 -0.261966 0.57931 RAD 0.00617284 + txt002 + SPHERE CENTER 0.38141 -0.278159 0.561208 RAD 0.00617284 + txt002 + SPHERE CENTER 0.36581 -0.259422 0.565115 RAD 0.00617284 + txt002 + SPHERE CENTER 0.371598 -0.261768 0.599471 RAD 0.00617284 + txt002 + SPHERE CENTER 0.351556 -0.259225 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER 0.352901 -0.277764 0.601529 RAD 0.00617284 + txt002 + SPHERE CENTER 0.387198 -0.280504 0.595564 RAD 0.00617284 + txt002 + SPHERE CENTER 0.368501 -0.2965 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER 0.382755 -0.296698 0.577461 RAD 0.00617284 + txt002 + SPHERE CENTER 0.297666 -0.252306 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.30415 -0.228803 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER 0.321516 -0.245915 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.306824 -0.238783 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.2803 -0.235194 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282974 -0.245173 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.273816 -0.258696 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.294992 -0.242326 0.603794 RAD 0.00617284 + txt002 + SPHERE CENTER 0.288509 -0.265828 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.312359 -0.259438 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31427 -0.31427 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.32435 -0.304189 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.33812 -0.307879 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.32066 -0.29042 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.3005 -0.31058 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29681 -0.29681 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29042 -0.32066 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.317959 -0.328039 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.307879 -0.33812 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.331729 -0.331729 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.383759 -0.339925 0.544331 RAD 0.0185185 + txt002 + SPHERE CENTER 0.407156 -0.334762 0.538366 RAD 0.00617284 + txt002 + SPHERE CENTER 0.388696 -0.326552 0.524171 RAD 0.00617284 + txt002 + SPHERE CENTER 0.392275 -0.31686 0.546597 RAD 0.00617284 + txt002 + SPHERE CENTER 0.402218 -0.348135 0.558526 RAD 0.00617284 + txt002 + SPHERE CENTER 0.387337 -0.330233 0.566757 RAD 0.00617284 + txt002 + SPHERE CENTER 0.378821 -0.353299 0.564491 RAD 0.00617284 + txt002 + SPHERE CENTER 0.39864 -0.357827 0.536101 RAD 0.00617284 + txt002 + SPHERE CENTER 0.375243 -0.362991 0.542066 RAD 0.00617284 + txt002 + SPHERE CENTER 0.380181 -0.349618 0.521905 RAD 0.00617284 + txt002 + SPHERE CENTER 0.330873 -0.376234 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.346394 -0.386461 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER 0.354723 -0.369843 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.340031 -0.362711 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.322544 -0.392851 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER 0.316181 -0.369102 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.307023 -0.382624 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337237 -0.399983 0.579103 RAD 0.00617284 + txt002 + SPHERE CENTER 0.321715 -0.389757 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.345565 -0.383366 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.330873 -0.376234 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.348239 -0.393346 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.354723 -0.369843 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.345565 -0.383366 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.324389 -0.399736 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.321715 -0.389757 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.307023 -0.382624 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.333547 -0.386213 0.484868 RAD 0.00617284 + txt002 + SPHERE CENTER 0.316181 -0.369102 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.340031 -0.362711 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.166275 -0.191247 0.655442 RAD 0.0555556 + txt002 + SPHERE CENTER 0.20793 -0.130089 0.652044 RAD 0.0185185 + txt002 + SPHERE CENTER 0.221102 -0.115471 0.637128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.220766 -0.13987 0.633356 RAD 0.00617284 + txt002 + SPHERE CENTER 0.200597 -0.126388 0.628759 RAD 0.00617284 + txt002 + SPHERE CENTER 0.208266 -0.10569 0.655816 RAD 0.00617284 + txt002 + SPHERE CENTER 0.187762 -0.116607 0.647447 RAD 0.00617284 + txt002 + SPHERE CENTER 0.195095 -0.120308 0.670732 RAD 0.00617284 + txt002 + SPHERE CENTER 0.228435 -0.119172 0.660413 RAD 0.00617284 + txt002 + SPHERE CENTER 0.215264 -0.13379 0.675329 RAD 0.00617284 + txt002 + SPHERE CENTER 0.228099 -0.143571 0.656641 RAD 0.00617284 + txt002 + SPHERE CENTER 0.230419 -0.192135 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.243049 -0.18209 0.599717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.218634 -0.185251 0.597829 RAD 0.00617284 + txt002 + SPHERE CENTER 0.227721 -0.168159 0.613157 RAD 0.00617284 + txt002 + SPHERE CENTER 0.254834 -0.188974 0.620293 RAD 0.00617284 + txt002 + SPHERE CENTER 0.239506 -0.175043 0.633733 RAD 0.00617284 + txt002 + SPHERE CENTER 0.242204 -0.199019 0.638981 RAD 0.00617284 + txt002 + SPHERE CENTER 0.245747 -0.206066 0.604965 RAD 0.00617284 + txt002 + SPHERE CENTER 0.233117 -0.216111 0.623653 RAD 0.00617284 + txt002 + SPHERE CENTER 0.221332 -0.209227 0.603077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.172673 -0.154295 0.591563 RAD 0.0185185 + txt002 + SPHERE CENTER 0.180792 -0.15554 0.568278 RAD 0.00617284 + txt002 + SPHERE CENTER 0.19323 -0.166926 0.586315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.171251 -0.17557 0.579113 RAD 0.00617284 + txt002 + SPHERE CENTER 0.160236 -0.142909 0.573526 RAD 0.00617284 + txt002 + SPHERE CENTER 0.150694 -0.162939 0.584361 RAD 0.00617284 + txt002 + SPHERE CENTER 0.152117 -0.141663 0.596811 RAD 0.00617284 + txt002 + SPHERE CENTER 0.182215 -0.134265 0.580727 RAD 0.00617284 + txt002 + SPHERE CENTER 0.174096 -0.133019 0.604012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.194652 -0.145651 0.598764 RAD 0.00617284 + txt002 + SPHERE CENTER 0.143787 -0.129201 0.689081 RAD 0.0185185 + txt002 + SPHERE CENTER 0.14887 -0.105335 0.692853 RAD 0.00617284 + txt002 + SPHERE CENTER 0.167242 -0.121723 0.690969 RAD 0.00617284 + txt002 + SPHERE CENTER 0.153943 -0.115741 0.671044 RAD 0.00617284 + txt002 + SPHERE CENTER 0.125414 -0.112813 0.690965 RAD 0.00617284 + txt002 + SPHERE CENTER 0.130487 -0.123219 0.669156 RAD 0.00617284 + txt002 + SPHERE CENTER 0.120331 -0.136679 0.687193 RAD 0.00617284 + txt002 + SPHERE CENTER 0.138714 -0.118795 0.71089 RAD 0.00617284 + txt002 + SPHERE CENTER 0.13363 -0.142661 0.707118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.157086 -0.135183 0.709006 RAD 0.00617284 + txt002 + SPHERE CENTER 0.108529 -0.153407 0.6286 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0995811 -0.130858 0.624003 RAD 0.00617284 + txt002 + SPHERE CENTER 0.113639 -0.134736 0.643928 RAD 0.00617284 + txt002 + SPHERE CENTER 0.123725 -0.135326 0.621398 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0944715 -0.149528 0.608675 RAD 0.00617284 + txt002 + SPHERE CENTER 0.118615 -0.153997 0.60607 RAD 0.00617284 + txt002 + SPHERE CENTER 0.10342 -0.172078 0.613272 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0843858 -0.148938 0.631205 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0933338 -0.171487 0.635801 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0984435 -0.152816 0.65113 RAD 0.00617284 + txt002 + SPHERE CENTER 0.102131 -0.190359 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0897843 -0.179968 0.711167 RAD 0.00617284 + txt002 + SPHERE CENTER 0.114103 -0.183804 0.713055 RAD 0.00617284 + txt002 + SPHERE CENTER 0.105492 -0.166467 0.697727 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0778128 -0.186523 0.690591 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0935207 -0.173022 0.677151 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0901597 -0.196914 0.671903 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0864233 -0.20386 0.705919 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0987702 -0.214251 0.687231 RAD 0.00617284 + txt002 + SPHERE CENTER 0.110742 -0.207696 0.707807 RAD 0.00617284 + txt002 + SPHERE CENTER 0.201532 -0.167041 0.715923 RAD 0.0185185 + txt002 + SPHERE CENTER 0.219088 -0.151829 0.724292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.221861 -0.163068 0.702483 RAD 0.00617284 + txt002 + SPHERE CENTER 0.205084 -0.14514 0.705088 RAD 0.00617284 + txt002 + SPHERE CENTER 0.19876 -0.155801 0.737733 RAD 0.00617284 + txt002 + SPHERE CENTER 0.184756 -0.149113 0.718528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.181204 -0.171014 0.729364 RAD 0.00617284 + txt002 + SPHERE CENTER 0.215537 -0.173729 0.735128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.197981 -0.188942 0.726759 RAD 0.00617284 + txt002 + SPHERE CENTER 0.218309 -0.184969 0.713318 RAD 0.00617284 + txt002 + SPHERE CENTER 0.159877 -0.228199 0.719322 RAD 0.0185185 + txt002 + SPHERE CENTER 0.167942 -0.229756 0.742607 RAD 0.00617284 + txt002 + SPHERE CENTER 0.183484 -0.223214 0.72457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.16569 -0.207683 0.731771 RAD 0.00617284 + txt002 + SPHERE CENTER 0.144336 -0.234741 0.737359 RAD 0.00617284 + txt002 + SPHERE CENTER 0.142084 -0.212668 0.726523 RAD 0.00617284 + txt002 + SPHERE CENTER 0.13627 -0.233184 0.714074 RAD 0.00617284 + txt002 + SPHERE CENTER 0.162129 -0.250271 0.730157 RAD 0.00617284 + txt002 + SPHERE CENTER 0.154064 -0.248714 0.706872 RAD 0.00617284 + txt002 + SPHERE CENTER 0.177671 -0.243729 0.71212 RAD 0.00617284 + txt002 + SPHERE CENTER 0.224021 -0.229087 0.682285 RAD 0.0185185 + txt002 + SPHERE CENTER 0.248268 -0.22829 0.686881 RAD 0.00617284 + txt002 + SPHERE CENTER 0.2391 -0.216949 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER 0.234532 -0.207937 0.689486 RAD 0.00617284 + txt002 + SPHERE CENTER 0.233189 -0.240428 0.702209 RAD 0.00617284 + txt002 + SPHERE CENTER 0.219453 -0.220075 0.704814 RAD 0.00617284 + txt002 + SPHERE CENTER 0.208942 -0.241225 0.697613 RAD 0.00617284 + txt002 + SPHERE CENTER 0.237756 -0.249439 0.67968 RAD 0.00617284 + txt002 + SPHERE CENTER 0.213509 -0.250236 0.675083 RAD 0.00617284 + txt002 + SPHERE CENTER 0.228589 -0.238098 0.659755 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0058509 -0.451136 0.729516 RAD 0.0555556 + txt002 + SPHERE CENTER 0.0051487 -0.447081 0.803476 RAD 0.0185185 + txt002 + SPHERE CENTER 0.01504 -0.435909 0.823149 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0289993 -0.440694 0.803352 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0115452 -0.423265 0.802231 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00881065 -0.442297 0.823273 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0123054 -0.429652 0.802355 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0187019 -0.453468 0.8036 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00864346 -0.459725 0.824394 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0012478 -0.470897 0.804721 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0226028 -0.46451 0.804597 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0688765 -0.439178 0.766553 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0903221 -0.426942 0.766429 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0806307 -0.435083 0.745229 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0699989 -0.416328 0.757266 RAD 0.00617284 + txt002 + SPHERE CENTER 0.078568 -0.431037 0.787754 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0582447 -0.420423 0.77859 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0571224 -0.443274 0.787878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0891998 -0.449792 0.775717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0677542 -0.462029 0.775841 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0795084 -0.457933 0.754517 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0172804 -0.386138 0.763155 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0293677 -0.364644 0.76191 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0401449 -0.385352 0.753867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0213457 -0.375512 0.741241 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0065032 -0.36543 0.771198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00151881 -0.376298 0.750529 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00558411 -0.386924 0.772443 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0253024 -0.37527 0.783824 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0132151 -0.396764 0.785069 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0360796 -0.395978 0.775781 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0578769 -0.459039 0.766439 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0707378 -0.451803 0.786236 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0461991 -0.454158 0.787639 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0561039 -0.435761 0.774481 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0824157 -0.456685 0.765035 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0677817 -0.440643 0.753281 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0695548 -0.46392 0.745238 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0725109 -0.475081 0.778193 RAD 0.00617284 + txt002 + SPHERE CENTER -0.05965 -0.482316 0.758396 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0479721 -0.477435 0.779597 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0457452 -0.398096 0.726118 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0495643 -0.373728 0.724997 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0306825 -0.382672 0.738155 RAD 0.00617284 + txt002 + SPHERE CENTER -0.030137 -0.383722 0.713492 RAD 0.00617284 + txt002 + SPHERE CENTER -0.064627 -0.389151 0.71296 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0451997 -0.399146 0.701455 RAD 0.00617284 + txt002 + SPHERE CENTER -0.060808 -0.41352 0.714081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0651725 -0.388102 0.737623 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0613535 -0.41247 0.738744 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0462908 -0.397047 0.750781 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0571747 -0.463094 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER -0.081612 -0.459563 0.692603 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0696122 -0.463589 0.713804 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0665888 -0.442243 0.701767 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0691745 -0.459069 0.671279 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0541513 -0.441749 0.680442 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0447373 -0.4626 0.671155 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0721979 -0.480415 0.683315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0477607 -0.483946 0.683192 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0601982 -0.48444 0.704516 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00628079 -0.512079 0.769837 RAD 0.0185185 + txt002 + SPHERE CENTER -0.000557006 -0.523883 0.790755 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0165974 -0.51057 0.779001 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00208214 -0.49924 0.790506 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0234352 -0.525392 0.781591 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0249603 -0.500749 0.781342 RAD 0.00617284 + txt002 + SPHERE CENTER -0.029159 -0.513588 0.760673 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00475566 -0.536722 0.770086 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0104794 -0.524918 0.749168 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0123987 -0.523409 0.758332 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00557859 -0.516134 0.695877 RAD 0.0185185 + txt002 + SPHERE CENTER -0.00154892 -0.540463 0.697123 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0156462 -0.524673 0.705165 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00538221 -0.52751 0.717791 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0227737 -0.531924 0.687835 RAD 0.00617284 + txt002 + SPHERE CENTER -0.026607 -0.518971 0.708504 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0268034 -0.507596 0.68659 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00174531 -0.529087 0.675209 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00577498 -0.504759 0.673964 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0154498 -0.513298 0.683251 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0574471 -0.504176 0.732914 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0817008 -0.508666 0.734036 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0732807 -0.489545 0.720878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0722467 -0.488971 0.745541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0658672 -0.523298 0.746073 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0564131 -0.503602 0.757577 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0416134 -0.518808 0.744951 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0669012 -0.523872 0.72141 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0426474 -0.519382 0.720288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.058481 -0.504751 0.708251 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0483751 -0.248762 0.655442 RAD 0.0555556 + txt002 + SPHERE CENTER -0.0599222 -0.183785 0.689081 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0522053 -0.160406 0.690965 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0358698 -0.178533 0.687193 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0513956 -0.171954 0.669156 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0762577 -0.165658 0.692853 RAD 0.00617284 + txt002 + SPHERE CENTER -0.075448 -0.177206 0.671044 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0839747 -0.189036 0.690969 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0607319 -0.172236 0.71089 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0684488 -0.195615 0.709006 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0443964 -0.190363 0.707118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00673113 -0.215921 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0258737 -0.20044 0.690591 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0203763 -0.215612 0.671903 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00551963 -0.196602 0.677151 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0122285 -0.200749 0.711167 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00812553 -0.196911 0.697727 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00691403 -0.21623 0.713055 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0270852 -0.21976 0.705919 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00794264 -0.235241 0.707807 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0215878 -0.234932 0.687231 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0172857 -0.187119 0.6286 RAD 0.0185185 + txt002 + SPHERE CENTER -0.00705049 -0.176731 0.608675 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00352517 -0.200733 0.613272 RAD 0.00617284 + txt002 + SPHERE CENTER -0.025725 -0.192673 0.60607 RAD 0.00617284 + txt002 + SPHERE CENTER -0.020811 -0.163117 0.624003 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0394855 -0.179058 0.621398 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0310463 -0.173504 0.643928 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00138875 -0.171177 0.631205 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00884647 -0.181564 0.65113 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00491406 -0.195179 0.635801 RAD 0.00617284 + txt002 + SPHERE CENTER -0.115028 -0.216626 0.652044 RAD 0.0185185 + txt002 + SPHERE CENTER -0.127519 -0.195663 0.655816 RAD 0.00617284 + txt002 + SPHERE CENTER -0.108803 -0.201738 0.670732 RAD 0.00617284 + txt002 + SPHERE CENTER -0.104303 -0.194866 0.647447 RAD 0.00617284 + txt002 + SPHERE CENTER -0.133744 -0.210551 0.637128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.110528 -0.209754 0.628759 RAD 0.00617284 + txt002 + SPHERE CENTER -0.121254 -0.231514 0.633356 RAD 0.00617284 + txt002 + SPHERE CENTER -0.138245 -0.217423 0.660413 RAD 0.00617284 + txt002 + SPHERE CENTER -0.125754 -0.238386 0.656641 RAD 0.00617284 + txt002 + SPHERE CENTER -0.119529 -0.223497 0.675329 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0723919 -0.21996 0.591563 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0673141 -0.20388 0.573526 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0609052 -0.198742 0.596811 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0490355 -0.216456 0.584361 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0788008 -0.225098 0.568278 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0605222 -0.237674 0.579113 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0838786 -0.241177 0.586315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0906706 -0.207384 0.580727 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0957484 -0.223463 0.598764 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0842617 -0.202246 0.604012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.103481 -0.281603 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.126206 -0.291073 0.620293 RAD 0.00617284 + txt002 + SPHERE CENTER -0.110246 -0.293457 0.638981 RAD 0.00617284 + txt002 + SPHERE CENTER -0.119897 -0.271345 0.633733 RAD 0.00617284 + txt002 + SPHERE CENTER -0.119442 -0.279219 0.599717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.113132 -0.25949 0.613157 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0967168 -0.269749 0.597829 RAD 0.00617284 + txt002 + SPHERE CENTER -0.10979 -0.301332 0.604965 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0870656 -0.291862 0.603077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0938302 -0.303716 0.623653 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0910116 -0.245428 0.715923 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0942304 -0.234308 0.737733 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0714204 -0.238704 0.729364 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0854464 -0.221514 0.718528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.113822 -0.241032 0.724292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.105038 -0.228237 0.705088 RAD 0.00617284 + txt002 + SPHERE CENTER -0.110603 -0.252152 0.702483 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0997955 -0.258223 0.735128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0965768 -0.269343 0.713318 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0769856 -0.262619 0.726759 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0794645 -0.310405 0.682285 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0817333 -0.324811 0.702209 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0603366 -0.313378 0.697613 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0800146 -0.300317 0.704814 RAD 0.00617284 + txt002 + SPHERE CENTER -0.100861 -0.321838 0.686881 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0991425 -0.297345 0.689486 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0985923 -0.307433 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0811832 -0.334899 0.67968 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0789143 -0.320493 0.659755 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0597864 -0.323466 0.675083 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0243582 -0.277564 0.719322 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0076281 -0.275459 0.737359 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00142185 -0.270078 0.714074 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0167139 -0.255218 0.726523 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0305645 -0.282946 0.742607 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0396503 -0.262704 0.731771 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0472946 -0.285051 0.72457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0152725 -0.297806 0.730157 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0320026 -0.299911 0.71212 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00906621 -0.292425 0.706872 RAD 0.00617284 + txt002 + SPHERE CENTER -0.115031 -0.4293 0.544331 RAD 0.0555556 + txt002 + SPHERE CENTER -0.178985 -0.424299 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.190929 -0.412497 0.599471 RAD 0.00617284 + txt002 + SPHERE CENTER -0.16674 -0.417001 0.601529 RAD 0.00617284 + txt002 + SPHERE CENTER -0.174844 -0.400273 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER -0.203175 -0.419795 0.57931 RAD 0.00617284 + txt002 + SPHERE CENTER -0.18709 -0.407571 0.565115 RAD 0.00617284 + txt002 + SPHERE CENTER -0.191231 -0.431597 0.561208 RAD 0.00617284 + txt002 + SPHERE CENTER -0.195071 -0.436523 0.595564 RAD 0.00617284 + txt002 + SPHERE CENTER -0.183127 -0.448325 0.577461 RAD 0.00617284 + txt002 + SPHERE CENTER -0.170881 -0.441027 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER -0.115031 -0.4293 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.10495 -0.41922 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0911807 -0.42291 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.10864 -0.40545 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.128801 -0.425611 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.13249 -0.411841 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.138881 -0.435691 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.111341 -0.44307 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.121421 -0.45315 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0975713 -0.44676 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.131634 -0.367336 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.12515 -0.343834 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER -0.107784 -0.360946 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.122476 -0.353814 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.149 -0.350225 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER -0.146326 -0.360204 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.155484 -0.373727 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.134308 -0.357357 0.603794 RAD 0.00617284 + txt002 + SPHERE CENTER -0.140792 -0.380859 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.116942 -0.374468 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.178985 -0.424299 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.200165 -0.411775 0.505236 RAD 0.00617284 + txt002 + SPHERE CENTER -0.189948 -0.415187 0.527454 RAD 0.00617284 + txt002 + SPHERE CENTER -0.179342 -0.399922 0.511201 RAD 0.00617284 + txt002 + SPHERE CENTER -0.189202 -0.420888 0.485076 RAD 0.00617284 + txt002 + SPHERE CENTER -0.168379 -0.409035 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER -0.168023 -0.433412 0.487134 RAD 0.00617284 + txt002 + SPHERE CENTER -0.199808 -0.436152 0.501329 RAD 0.00617284 + txt002 + SPHERE CENTER -0.178629 -0.448677 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.189591 -0.439564 0.523547 RAD 0.00617284 + txt002 + SPHERE CENTER -0.131634 -0.367336 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.123305 -0.350719 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER -0.107784 -0.360946 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.116942 -0.374468 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.147155 -0.357109 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER -0.140792 -0.380859 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.155484 -0.373727 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.137998 -0.343587 0.509559 RAD 0.00617284 + txt002 + SPHERE CENTER -0.146326 -0.360204 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.122476 -0.353814 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.115031 -0.4293 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER -0.125111 -0.41922 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER -0.138881 -0.42291 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.121421 -0.40545 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.101261 -0.425611 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0975713 -0.411841 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0911807 -0.435691 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.11872 -0.44307 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER -0.10864 -0.45315 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.13249 -0.44676 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.162382 -0.486264 0.544331 RAD 0.0185185 + txt002 + SPHERE CENTER -0.174264 -0.502603 0.558526 RAD 0.00617284 + txt002 + SPHERE CENTER -0.15142 -0.495376 0.564491 RAD 0.00617284 + txt002 + SPHERE CENTER -0.170327 -0.479659 0.566757 RAD 0.00617284 + txt002 + SPHERE CENTER -0.185226 -0.49349 0.538366 RAD 0.00617284 + txt002 + SPHERE CENTER -0.18129 -0.470546 0.546597 RAD 0.00617284 + txt002 + SPHERE CENTER -0.173345 -0.477151 0.524171 RAD 0.00617284 + txt002 + SPHERE CENTER -0.166319 -0.509207 0.536101 RAD 0.00617284 + txt002 + SPHERE CENTER -0.154437 -0.492868 0.521905 RAD 0.00617284 + txt002 + SPHERE CENTER -0.143475 -0.501981 0.542066 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0984274 -0.491265 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0810612 -0.508376 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0745774 -0.484874 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0837352 -0.498397 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.104911 -0.514767 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.107585 -0.504787 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.122277 -0.497655 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0957534 -0.501244 0.484868 RAD 0.00617284 + txt002 + SPHERE CENTER -0.11312 -0.484132 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0892696 -0.477742 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0984274 -0.491265 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.082906 -0.501491 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0745774 -0.484874 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0892696 -0.477742 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.106756 -0.507882 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER -0.11312 -0.484132 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.122277 -0.497655 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0920638 -0.515014 0.579103 RAD 0.00617284 + txt002 + SPHERE CENTER -0.107585 -0.504787 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0837352 -0.498397 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.153845 -0.574159 0.618405 RAD 0.0555556 + txt002 + SPHERE CENTER 0.202534 -0.612768 0.658726 RAD 0.0185185 + txt002 + SPHERE CENTER 0.225282 -0.612732 0.668328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.22113 -0.60221 0.64638 RAD 0.00617284 + txt002 + SPHERE CENTER 0.212428 -0.591695 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER 0.206686 -0.62329 0.680674 RAD 0.00617284 + txt002 + SPHERE CENTER 0.193832 -0.602253 0.679302 RAD 0.00617284 + txt002 + SPHERE CENTER 0.183939 -0.623325 0.671072 RAD 0.00617284 + txt002 + SPHERE CENTER 0.215388 -0.633805 0.660098 RAD 0.00617284 + txt002 + SPHERE CENTER 0.192641 -0.63384 0.650495 RAD 0.00617284 + txt002 + SPHERE CENTER 0.211236 -0.623283 0.63815 RAD 0.00617284 + txt002 + SPHERE CENTER 0.225396 -0.554987 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.243024 -0.542885 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.225396 -0.554987 0.593714 RAD 0.00617284 + txt002 + SPHERE CENTER 0.219861 -0.534333 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.243024 -0.542885 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.219861 -0.534333 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.225396 -0.554987 0.643096 RAD 0.00617284 + txt002 + SPHERE CENTER 0.248559 -0.563539 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.23093 -0.575642 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.23093 -0.575642 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.184086 -0.543919 0.678886 RAD 0.0185185 + txt002 + SPHERE CENTER 0.200547 -0.527458 0.687117 RAD 0.00617284 + txt002 + SPHERE CENTER 0.205161 -0.540303 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.187702 -0.522843 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.179472 -0.531074 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.166627 -0.526459 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER 0.163011 -0.547535 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER 0.196931 -0.548533 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.18047 -0.564994 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER 0.201546 -0.561378 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER 0.130984 -0.631939 0.658726 RAD 0.0185185 + txt002 + SPHERE CENTER 0.132649 -0.643128 0.680674 RAD 0.00617284 + txt002 + SPHERE CENTER 0.152367 -0.631785 0.671072 RAD 0.00617284 + txt002 + SPHERE CENTER 0.133263 -0.618482 0.679302 RAD 0.00617284 + txt002 + SPHERE CENTER 0.111266 -0.643283 0.668328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.11188 -0.618637 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER 0.109601 -0.632094 0.64638 RAD 0.00617284 + txt002 + SPHERE CENTER 0.130371 -0.656585 0.660098 RAD 0.00617284 + txt002 + SPHERE CENTER 0.128706 -0.645397 0.63815 RAD 0.00617284 + txt002 + SPHERE CENTER 0.150088 -0.645242 0.650495 RAD 0.00617284 + txt002 + SPHERE CENTER 0.112536 -0.56309 0.678886 RAD 0.0185185 + txt002 + SPHERE CENTER 0.11011 -0.549659 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.132596 -0.555684 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER 0.118927 -0.53924 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER 0.09005 -0.557065 0.687117 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0988668 -0.546646 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0924762 -0.570497 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.103719 -0.573509 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.106145 -0.58694 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER 0.126205 -0.579534 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0822954 -0.593331 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0609772 -0.591664 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0822954 -0.593331 0.643096 RAD 0.00617284 + txt002 + SPHERE CENTER 0.076761 -0.572676 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0609772 -0.591664 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.076761 -0.572676 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0822954 -0.593331 0.593714 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0665116 -0.612319 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0878298 -0.613986 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0878298 -0.613986 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.172294 -0.643008 0.598245 RAD 0.0185185 + txt002 + SPHERE CENTER 0.189742 -0.660425 0.599616 RAD 0.00617284 + txt002 + SPHERE CENTER 0.196144 -0.636618 0.598245 RAD 0.00617284 + txt002 + SPHERE CENTER 0.185725 -0.645434 0.618821 RAD 0.00617284 + txt002 + SPHERE CENTER 0.165892 -0.666816 0.599616 RAD 0.00617284 + txt002 + SPHERE CENTER 0.161875 -0.651825 0.618821 RAD 0.00617284 + txt002 + SPHERE CENTER 0.148444 -0.649399 0.598245 RAD 0.00617284 + txt002 + SPHERE CENTER 0.17631 -0.657999 0.57904 RAD 0.00617284 + txt002 + SPHERE CENTER 0.158862 -0.640582 0.577669 RAD 0.00617284 + txt002 + SPHERE CENTER 0.182712 -0.634191 0.577669 RAD 0.00617284 + txt002 + SPHERE CENTER 0.123605 -0.6044 0.557924 RAD 0.0185185 + txt002 + SPHERE CENTER 0.107144 -0.620861 0.549693 RAD 0.00617284 + txt002 + SPHERE CENTER 0.119989 -0.625475 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER 0.102529 -0.608016 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER 0.11076 -0.599785 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER 0.106145 -0.58694 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER 0.127221 -0.583324 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.128219 -0.617245 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER 0.14468 -0.600784 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.141064 -0.621859 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER 0.195155 -0.585228 0.557924 RAD 0.0185185 + txt002 + SPHERE CENTER 0.203972 -0.574809 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER 0.181486 -0.568784 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.201546 -0.561378 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER 0.217641 -0.591253 0.549693 RAD 0.00617284 + txt002 + SPHERE CENTER 0.215215 -0.577822 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER 0.208824 -0.601672 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER 0.197581 -0.598659 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER 0.188764 -0.609078 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER 0.175095 -0.592634 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0329639 -0.552323 0.43322 RAD 0.0555556 + txt002 + SPHERE CENTER 0.0248832 -0.625877 0.436618 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0316054 -0.646362 0.448652 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0478 -0.627981 0.445566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0287309 -0.625173 0.460998 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00868865 -0.644258 0.439705 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00581415 -0.623069 0.45205 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00196644 -0.623773 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0277577 -0.647066 0.424272 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0210355 -0.62658 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0439523 -0.628685 0.421186 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0822954 -0.593331 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER 0.105299 -0.593994 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER 0.100664 -0.582384 0.457911 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0926585 -0.572783 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0869303 -0.604941 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0742898 -0.58373 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0639267 -0.604278 0.482603 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0949359 -0.614541 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0719323 -0.613879 0.46131 RAD 0.00617284 + txt002 + SPHERE CENTER 0.090301 -0.602932 0.448964 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0138144 -0.584567 0.497099 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0177119 -0.584898 0.521479 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0364224 -0.580268 0.506047 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0185345 -0.56353 0.509133 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00489609 -0.589197 0.512531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00407348 -0.567829 0.500186 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00879364 -0.588867 0.488152 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0129918 -0.605935 0.509445 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00909422 -0.605605 0.485065 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0317022 -0.601305 0.494013 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0244483 -0.584869 0.399581 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0473753 -0.5935 0.402668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0308315 -0.595617 0.420874 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0399691 -0.57344 0.415013 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0409921 -0.582752 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0335859 -0.562692 0.39372 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0180651 -0.574121 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0318545 -0.604929 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00892756 -0.596298 0.384149 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0153107 -0.607046 0.405442 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0355172 -0.54356 0.460062 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0495897 -0.530389 0.475494 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0261165 -0.53532 0.481355 RAD 0.00617284 + txt002 + SPHERE CENTER -0.031221 -0.519442 0.463149 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0589904 -0.538628 0.454201 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0406217 -0.527681 0.441856 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0449178 -0.551799 0.438769 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0538859 -0.554507 0.472408 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0398133 -0.567678 0.456976 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0304127 -0.559438 0.478269 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0163676 -0.511316 0.396183 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0212225 -0.48882 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00896145 -0.491256 0.408529 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00194055 -0.497372 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0286287 -0.50888 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00546563 -0.517432 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0237738 -0.531375 0.383837 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0395307 -0.502764 0.396183 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0346758 -0.525259 0.40513 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0272696 -0.505199 0.417476 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0440327 -0.593633 0.372739 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0604766 -0.607302 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0678827 -0.587242 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0604766 -0.607302 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0366265 -0.613693 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0366265 -0.613693 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0201827 -0.600023 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0440327 -0.593633 0.348047 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0275889 -0.579964 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0514389 -0.573573 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0521134 -0.520079 0.369341 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0542684 -0.523344 0.344961 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0591566 -0.541988 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0358996 -0.534291 0.357307 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0472252 -0.501435 0.353908 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0288565 -0.512382 0.366254 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0450702 -0.49817 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0704822 -0.509132 0.356995 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0683272 -0.505868 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0753703 -0.527777 0.372427 RAD 0.00617284 + txt002 + SPHERE CENTER 0.101445 -0.561087 0.406378 RAD 0.0185185 + txt002 + SPHERE CENTER 0.118381 -0.551884 0.390945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0944221 -0.550745 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.103361 -0.536664 0.403291 RAD 0.00617284 + txt002 + SPHERE CENTER 0.125404 -0.562225 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.110383 -0.547006 0.424584 RAD 0.00617284 + txt002 + SPHERE CENTER 0.108468 -0.571428 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER 0.116465 -0.576307 0.394032 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0995293 -0.58551 0.409464 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0925065 -0.575168 0.388171 RAD 0.00617284 + txt002 + SPHERE CENTER 0.247614 -0.494808 0.43322 RAD 0.0555556 + txt002 + SPHERE CENTER 0.313607 -0.494287 0.399581 RAD 0.0185185 + txt002 + SPHERE CENTER 0.326876 -0.484182 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER 0.302705 -0.488171 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.310432 -0.470513 0.39372 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337778 -0.490299 0.402668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.321334 -0.476629 0.415013 RAD 0.00617284 + txt002 + SPHERE CENTER 0.324509 -0.500404 0.420874 RAD 0.00617284 + txt002 + SPHERE CENTER 0.330051 -0.507957 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.316783 -0.518062 0.405442 RAD 0.00617284 + txt002 + SPHERE CENTER 0.305881 -0.511946 0.384149 RAD 0.00617284 + txt002 + SPHERE CENTER 0.269833 -0.434629 0.396183 RAD 0.0185185 + txt002 + SPHERE CENTER 0.279233 -0.426389 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER 0.286276 -0.448298 0.383837 RAD 0.00617284 + txt002 + SPHERE CENTER 0.263449 -0.445377 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER 0.262789 -0.41272 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.247006 -0.431707 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.253389 -0.420959 0.408529 RAD 0.00617284 + txt002 + SPHERE CENTER 0.285616 -0.415641 0.396183 RAD 0.00617284 + txt002 + SPHERE CENTER 0.276216 -0.42388 0.417476 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29266 -0.43755 0.40513 RAD 0.00617284 + txt002 + SPHERE CENTER 0.302539 -0.452978 0.460062 RAD 0.0185185 + txt002 + SPHERE CENTER 0.320401 -0.436971 0.454201 RAD 0.00617284 + txt002 + SPHERE CENTER 0.3148 -0.455413 0.438769 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29902 -0.436675 0.441856 RAD 0.00617284 + txt002 + SPHERE CENTER 0.30814 -0.434535 0.475494 RAD 0.00617284 + txt002 + SPHERE CENTER 0.286759 -0.434239 0.463149 RAD 0.00617284 + txt002 + SPHERE CENTER 0.290278 -0.450543 0.481355 RAD 0.00617284 + txt002 + SPHERE CENTER 0.32392 -0.453274 0.472408 RAD 0.00617284 + txt002 + SPHERE CENTER 0.306057 -0.469281 0.478269 RAD 0.00617284 + txt002 + SPHERE CENTER 0.318318 -0.471717 0.456976 RAD 0.00617284 + txt002 + SPHERE CENTER 0.291389 -0.554467 0.436618 RAD 0.0185185 + txt002 + SPHERE CENTER 0.314604 -0.562288 0.439705 RAD 0.00617284 + txt002 + SPHERE CENTER 0.310183 -0.541186 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER 0.306499 -0.542501 0.45205 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29581 -0.575569 0.448652 RAD 0.00617284 + txt002 + SPHERE CENTER 0.287705 -0.555781 0.460998 RAD 0.00617284 + txt002 + SPHERE CENTER 0.272595 -0.567748 0.445566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.299494 -0.574255 0.424272 RAD 0.00617284 + txt002 + SPHERE CENTER 0.276279 -0.566433 0.421186 RAD 0.00617284 + txt002 + SPHERE CENTER 0.295073 -0.553152 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.28032 -0.513157 0.497099 RAD 0.0185185 + txt002 + SPHERE CENTER 0.298839 -0.507811 0.512531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.302049 -0.505577 0.488152 RAD 0.00617284 + txt002 + SPHERE CENTER 0.287442 -0.489718 0.500186 RAD 0.00617284 + txt002 + SPHERE CENTER 0.27711 -0.515392 0.521479 RAD 0.00617284 + txt002 + SPHERE CENTER 0.265714 -0.497299 0.509133 RAD 0.00617284 + txt002 + SPHERE CENTER 0.258591 -0.520738 0.506047 RAD 0.00617284 + txt002 + SPHERE CENTER 0.291716 -0.531251 0.509445 RAD 0.00617284 + txt002 + SPHERE CENTER 0.273198 -0.536597 0.494013 RAD 0.00617284 + txt002 + SPHERE CENTER 0.294927 -0.529016 0.485065 RAD 0.00617284 + txt002 + SPHERE CENTER 0.225396 -0.554987 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER 0.227186 -0.567359 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.246777 -0.555283 0.482603 RAD 0.00617284 + txt002 + SPHERE CENTER 0.227528 -0.54267 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.205805 -0.567063 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER 0.206147 -0.542374 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER 0.204014 -0.554691 0.457911 RAD 0.00617284 + txt002 + SPHERE CENTER 0.225054 -0.579676 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.223263 -0.567305 0.448964 RAD 0.00617284 + txt002 + SPHERE CENTER 0.244644 -0.567601 0.46131 RAD 0.00617284 + txt002 + SPHERE CENTER 0.258683 -0.536117 0.372739 RAD 0.0185185 + txt002 + SPHERE CENTER 0.275127 -0.549787 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282533 -0.529727 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER 0.275127 -0.549787 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.251277 -0.556177 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.251277 -0.556177 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.234833 -0.542508 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER 0.258683 -0.536117 0.348047 RAD 0.00617284 + txt002 + SPHERE CENTER 0.242239 -0.522448 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.266089 -0.516058 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.19269 -0.536638 0.406378 RAD 0.0185185 + txt002 + SPHERE CENTER 0.17251 -0.549603 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.191778 -0.549105 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER 0.177908 -0.528912 0.424584 RAD 0.00617284 + txt002 + SPHERE CENTER 0.173421 -0.537136 0.390945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.178819 -0.516445 0.403291 RAD 0.00617284 + txt002 + SPHERE CENTER 0.193601 -0.524171 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.187292 -0.557329 0.394032 RAD 0.00617284 + txt002 + SPHERE CENTER 0.207471 -0.544363 0.388171 RAD 0.00617284 + txt002 + SPHERE CENTER 0.20656 -0.556831 0.409464 RAD 0.00617284 + txt002 + SPHERE CENTER 0.214908 -0.476459 0.369341 RAD 0.0185185 + txt002 + SPHERE CENTER 0.209819 -0.457868 0.353908 RAD 0.00617284 + txt002 + SPHERE CENTER 0.210053 -0.453963 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.2312 -0.458164 0.366254 RAD 0.00617284 + txt002 + SPHERE CENTER 0.214674 -0.480363 0.344961 RAD 0.00617284 + txt002 + SPHERE CENTER 0.236055 -0.480659 0.357307 RAD 0.00617284 + txt002 + SPHERE CENTER 0.219763 -0.498954 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.193527 -0.476163 0.356995 RAD 0.00617284 + txt002 + SPHERE CENTER 0.198616 -0.494753 0.372427 RAD 0.00617284 + txt002 + SPHERE CENTER 0.193761 -0.472258 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER -0.172546 -0.643951 1.11022e-16 RAD 0.166667 + txt002 + SPHERE CENTER -0.157543 -0.835815 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.122136 -0.871646 0.165419 RAD 0.0185185 + txt002 + SPHERE CENTER -0.102403 -0.871334 0.180258 RAD 0.00617284 + txt002 + SPHERE CENTER -0.100577 -0.862937 0.157111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.113406 -0.850164 0.173902 RAD 0.00617284 + txt002 + SPHERE CENTER -0.123961 -0.880044 0.188567 RAD 0.00617284 + txt002 + SPHERE CENTER -0.134964 -0.858873 0.182211 RAD 0.00617284 + txt002 + SPHERE CENTER -0.143694 -0.880356 0.173728 RAD 0.00617284 + txt002 + SPHERE CENTER -0.111133 -0.892817 0.171776 RAD 0.00617284 + txt002 + SPHERE CENTER -0.130866 -0.893129 0.156937 RAD 0.00617284 + txt002 + SPHERE CENTER -0.109307 -0.884419 0.148628 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0854653 -0.82339 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0654286 -0.811594 0.114524 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0820122 -0.820516 0.0985541 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0876595 -0.80102 0.112614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0688817 -0.814468 0.138803 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0911125 -0.803895 0.136894 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0889183 -0.826265 0.147112 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0632344 -0.833964 0.124743 RAD 0.00617284 + txt002 + SPHERE CENTER -0.083271 -0.845761 0.133052 RAD 0.00617284 + txt002 + SPHERE CENTER -0.079818 -0.842886 0.108773 RAD 0.00617284 + txt002 + SPHERE CENTER -0.135649 -0.799077 0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER -0.120908 -0.781177 0.180075 RAD 0.00617284 + txt002 + SPHERE CENTER -0.113462 -0.795477 0.161374 RAD 0.00617284 + txt002 + SPHERE CENTER -0.13149 -0.778973 0.157875 RAD 0.00617284 + txt002 + SPHERE CENTER -0.143095 -0.784778 0.190293 RAD 0.00617284 + txt002 + SPHERE CENTER -0.153678 -0.782573 0.168094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.157836 -0.802678 0.181811 RAD 0.00617284 + txt002 + SPHERE CENTER -0.125067 -0.801282 0.193792 RAD 0.00617284 + txt002 + SPHERE CENTER -0.139808 -0.819182 0.18531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.11762 -0.815582 0.175091 RAD 0.00617284 + txt002 + SPHERE CENTER -0.194213 -0.884071 0.153697 RAD 0.0185185 + txt002 + SPHERE CENTER -0.197746 -0.891905 0.176845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.175383 -0.884286 0.169668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.193701 -0.867957 0.172398 RAD 0.00617284 + txt002 + SPHERE CENTER -0.216576 -0.89169 0.160875 RAD 0.00617284 + txt002 + SPHERE CENTER -0.212531 -0.867741 0.156428 RAD 0.00617284 + txt002 + SPHERE CENTER -0.213043 -0.883856 0.137727 RAD 0.00617284 + txt002 + SPHERE CENTER -0.198259 -0.908019 0.158144 RAD 0.00617284 + txt002 + SPHERE CENTER -0.194726 -0.900186 0.134996 RAD 0.00617284 + txt002 + SPHERE CENTER -0.175896 -0.900401 0.150967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.207727 -0.811502 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.212743 -0.794108 0.176661 RAD 0.00617284 + txt002 + SPHERE CENTER -0.189621 -0.802328 0.173931 RAD 0.00617284 + txt002 + SPHERE CENTER -0.199907 -0.788345 0.156372 RAD 0.00617284 + txt002 + SPHERE CENTER -0.230849 -0.803282 0.162601 RAD 0.00617284 + txt002 + SPHERE CENTER -0.218012 -0.797518 0.142311 RAD 0.00617284 + txt002 + SPHERE CENTER -0.225832 -0.820676 0.14581 RAD 0.00617284 + txt002 + SPHERE CENTER -0.220563 -0.817265 0.18016 RAD 0.00617284 + txt002 + SPHERE CENTER -0.215547 -0.83466 0.163369 RAD 0.00617284 + txt002 + SPHERE CENTER -0.197441 -0.825486 0.177429 RAD 0.00617284 + txt002 + SPHERE CENTER -0.229621 -0.84824 0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.25245 -0.843832 0.107698 RAD 0.00617284 + txt002 + SPHERE CENTER -0.233837 -0.846687 0.123668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.235043 -0.826426 0.109608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.248234 -0.845385 0.0834188 RAD 0.00617284 + txt002 + SPHERE CENTER -0.230827 -0.827978 0.0853287 RAD 0.00617284 + txt002 + SPHERE CENTER -0.225404 -0.849792 0.0751099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.247028 -0.865646 0.0974792 RAD 0.00617284 + txt002 + SPHERE CENTER -0.224198 -0.870053 0.0891702 RAD 0.00617284 + txt002 + SPHERE CENTER -0.228415 -0.868501 0.113449 RAD 0.00617284 + txt002 + SPHERE CENTER -0.14403 -0.908384 0.104938 RAD 0.0185185 + txt002 + SPHERE CENTER -0.128672 -0.926643 0.111295 RAD 0.00617284 + txt002 + SPHERE CENTER -0.1198 -0.904034 0.106848 RAD 0.00617284 + txt002 + SPHERE CENTER -0.133221 -0.90826 0.127138 RAD 0.00617284 + txt002 + SPHERE CENTER -0.152902 -0.930993 0.109385 RAD 0.00617284 + txt002 + SPHERE CENTER -0.157451 -0.912609 0.125228 RAD 0.00617284 + txt002 + SPHERE CENTER -0.16826 -0.912733 0.103028 RAD 0.00617284 + txt002 + SPHERE CENTER -0.139481 -0.926768 0.0890951 RAD 0.00617284 + txt002 + SPHERE CENTER -0.154838 -0.908508 0.0827387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.130608 -0.904159 0.0846485 RAD 0.00617284 + txt002 + SPHERE CENTER -0.179437 -0.872552 0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER -0.188167 -0.894035 0.0421477 RAD 0.00617284 + txt002 + SPHERE CENTER -0.172046 -0.89378 0.0608487 RAD 0.00617284 + txt002 + SPHERE CENTER -0.195141 -0.885777 0.0643473 RAD 0.00617284 + txt002 + SPHERE CENTER -0.195558 -0.872807 0.0319289 RAD 0.00617284 + txt002 + SPHERE CENTER -0.202532 -0.864549 0.0541285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.186828 -0.851325 0.0404111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.172463 -0.880811 0.0284303 RAD 0.00617284 + txt002 + SPHERE CENTER -0.163733 -0.859328 0.0369125 RAD 0.00617284 + txt002 + SPHERE CENTER -0.156342 -0.880556 0.0471312 RAD 0.00617284 + txt002 + SPHERE CENTER -0.107359 -0.860128 0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0905999 -0.853284 0.0455609 RAD 0.00617284 + txt002 + SPHERE CENTER -0.111382 -0.840233 0.0482916 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0940331 -0.839638 0.0658506 RAD 0.00617284 + txt002 + SPHERE CENTER -0.086577 -0.873178 0.0596212 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0900102 -0.859532 0.079911 RAD 0.00617284 + txt002 + SPHERE CENTER -0.103336 -0.880022 0.0764123 RAD 0.00617284 + txt002 + SPHERE CENTER -0.103926 -0.873773 0.0420622 RAD 0.00617284 + txt002 + SPHERE CENTER -0.120685 -0.880618 0.0588533 RAD 0.00617284 + txt002 + SPHERE CENTER -0.124708 -0.860723 0.044793 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0133465 -0.69376 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.0838533 -0.674309 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.103063 -0.66171 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0876683 -0.673446 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0800983 -0.653258 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0992478 -0.662574 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0762832 -0.654121 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0800382 -0.675172 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.106818 -0.682761 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0876083 -0.69536 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0914233 -0.694497 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0539145 -0.666287 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0547519 -0.662466 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0439578 -0.682791 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0332597 -0.660752 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0647085 -0.645962 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0432164 -0.644249 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0638711 -0.649783 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0754066 -0.668 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0745692 -0.671821 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0646126 -0.688325 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0325183 -0.62221 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0446211 -0.604582 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.053173 -0.627745 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0325183 -0.62221 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0239663 -0.599047 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0118635 -0.616676 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0118635 -0.616676 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0446211 -0.604582 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0325183 -0.62221 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.053173 -0.627745 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0432853 -0.701782 0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0608821 -0.693716 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0652402 -0.694884 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0496759 -0.677932 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0389272 -0.700615 0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.027721 -0.684831 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0213304 -0.708681 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0544915 -0.717566 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0368947 -0.725632 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0588496 -0.718734 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00804971 -0.649684 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.00328338 -0.628657 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0152909 -0.642244 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.000378614 -0.630031 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.026624 -0.636097 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.022962 -0.637471 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0313903 -0.657124 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0117117 -0.648309 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.016478 -0.669336 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00686255 -0.661896 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0272215 -0.721234 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0310802 -0.720593 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00820099 -0.718114 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0246945 -0.7 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0501007 -0.723713 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.043715 -0.70312 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.046242 -0.724354 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0336072 -0.741827 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0297485 -0.742467 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.010728 -0.739347 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0646815 -0.745859 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0887955 -0.750021 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0813312 -0.732161 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.078459 -0.729506 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0721458 -0.763719 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0618093 -0.743204 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0480318 -0.759557 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.075018 -0.766375 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.050904 -0.762212 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0675537 -0.748514 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0058253 -0.76531 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.00415829 -0.786629 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0148294 -0.770845 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0058253 -0.76531 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.024813 -0.781094 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.02648 -0.759776 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.02648 -0.759776 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00415829 -0.786629 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0058253 -0.76531 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0148294 -0.770845 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0347427 -0.737837 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0542122 -0.747099 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0550267 -0.7241 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0553974 -0.743371 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0339282 -0.760836 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0351134 -0.757108 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0144587 -0.751574 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0335575 -0.741565 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.014088 -0.732303 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0343719 -0.718566 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.172546 -0.643951 0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER -0.142305 -0.61371 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.125845 -0.597249 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER -0.12123 -0.610094 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.138689 -0.592635 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.14692 -0.600865 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.159765 -0.596251 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.163381 -0.617326 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.12946 -0.618324 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.145921 -0.634785 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.124846 -0.631169 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.100996 -0.624779 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0833673 -0.612676 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.100996 -0.624779 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.10653 -0.604124 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0833673 -0.612676 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.10653 -0.604124 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.100996 -0.624779 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0778329 -0.633331 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0954616 -0.645433 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0954616 -0.645433 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.153374 -0.5724 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.141271 -0.554772 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.13272 -0.577935 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.153374 -0.5724 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.161926 -0.549237 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.174029 -0.566866 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.174029 -0.566866 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.141271 -0.554772 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.153374 -0.5724 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.13272 -0.577935 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.213855 -0.632882 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.216282 -0.61945 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.193796 -0.625476 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.207465 -0.609032 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.236341 -0.626857 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER -0.227525 -0.616438 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.233915 -0.640288 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.222672 -0.6433 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.220246 -0.656732 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.200186 -0.649326 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.224924 -0.591572 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.2291 -0.567237 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.209804 -0.576452 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.209804 -0.576452 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.24422 -0.582357 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.224924 -0.591572 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.240045 -0.606693 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.24422 -0.582357 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.240045 -0.606693 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.224924 -0.591572 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.244096 -0.663122 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.265414 -0.661455 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.244096 -0.663122 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.249631 -0.642468 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.265414 -0.661455 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.249631 -0.642468 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.244096 -0.663122 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.25988 -0.68211 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.238562 -0.683777 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.238562 -0.683777 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.161477 -0.68526 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.148046 -0.687686 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.137627 -0.678869 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.154071 -0.6652 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.171896 -0.694077 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.177921 -0.671591 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.185327 -0.691651 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.155452 -0.707746 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER -0.168883 -0.70532 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.145033 -0.698929 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.191718 -0.715501 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.190051 -0.736819 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.171063 -0.721035 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.191718 -0.715501 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.210706 -0.731284 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.212373 -0.709966 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.212373 -0.709966 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.190051 -0.736819 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.191718 -0.715501 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.171063 -0.721035 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.120168 -0.696329 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.095832 -0.700504 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.105047 -0.681209 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.105047 -0.681209 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.110952 -0.715624 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.120168 -0.696329 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.135288 -0.711449 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.110952 -0.715624 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.135288 -0.711449 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.120168 -0.696329 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.343435 -0.786005 8.51251e-17 RAD 0.0555556 + txt002 + SPHERE CENTER -0.392454 -0.82165 0.0425863 RAD 0.0185185 + txt002 + SPHERE CENTER -0.400556 -0.824791 0.065698 RAD 0.00617284 + txt002 + SPHERE CENTER -0.376528 -0.821021 0.0614442 RAD 0.00617284 + txt002 + SPHERE CENTER -0.392663 -0.802599 0.058292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.416482 -0.82542 0.0468401 RAD 0.00617284 + txt002 + SPHERE CENTER -0.408589 -0.803228 0.0394341 RAD 0.00617284 + txt002 + SPHERE CENTER -0.40838 -0.822279 0.0237283 RAD 0.00617284 + txt002 + SPHERE CENTER -0.400347 -0.843843 0.0499923 RAD 0.00617284 + txt002 + SPHERE CENTER -0.392245 -0.840701 0.0268805 RAD 0.00617284 + txt002 + SPHERE CENTER -0.376319 -0.840073 0.0457385 RAD 0.00617284 + txt002 + SPHERE CENTER -0.323622 -0.80984 0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER -0.308073 -0.80634 0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER -0.300378 -0.802721 0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER -0.316395 -0.786996 0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER -0.331317 -0.813459 0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER -0.339639 -0.794116 0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER -0.346866 -0.81696 0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER -0.315299 -0.829184 0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER -0.330849 -0.832685 0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.307605 -0.825565 0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER -0.370774 -0.753118 0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER -0.367981 -0.734271 0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER -0.348136 -0.745269 0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER -0.362711 -0.731279 0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER -0.390619 -0.74212 0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.385349 -0.739128 0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER -0.393412 -0.760966 0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER -0.376044 -0.756109 0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER -0.378837 -0.774956 0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER -0.356199 -0.767107 0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER -0.412267 -0.797815 -0.0246914 RAD 0.0185185 + txt002 + SPHERE CENTER -0.436217 -0.793573 -0.0204376 RAD 0.00617284 + txt002 + SPHERE CENTER -0.420728 -0.796968 -0.00151032 RAD 0.00617284 + txt002 + SPHERE CENTER -0.419454 -0.776294 -0.0149506 RAD 0.00617284 + txt002 + SPHERE CENTER -0.427756 -0.79442 -0.0436186 RAD 0.00617284 + txt002 + SPHERE CENTER -0.410993 -0.777141 -0.0381316 RAD 0.00617284 + txt002 + SPHERE CENTER -0.403807 -0.798662 -0.0478724 RAD 0.00617284 + txt002 + SPHERE CENTER -0.42903 -0.815094 -0.0301783 RAD 0.00617284 + txt002 + SPHERE CENTER -0.405081 -0.819335 -0.0344321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.413542 -0.818489 -0.0112511 RAD 0.00617284 + txt002 + SPHERE CENTER -0.390587 -0.729282 -0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER -0.392427 -0.704862 -0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER -0.373948 -0.714218 0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.374248 -0.717401 -0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER -0.409067 -0.719927 -0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER -0.390887 -0.732465 -0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.407227 -0.744347 -0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.408767 -0.716744 0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER -0.406927 -0.741164 0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER -0.390287 -0.726099 0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER -0.363249 -0.76217 -0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER -0.356966 -0.747522 -0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER -0.352002 -0.740618 -0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER -0.339469 -0.759239 -0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER -0.368213 -0.769074 -0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER -0.350716 -0.780791 -0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER -0.374496 -0.783722 -0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER -0.380746 -0.750453 -0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER -0.387029 -0.765101 -0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.375782 -0.743549 -0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER -0.365116 -0.854538 -0.0178949 RAD 0.0185185 + txt002 + SPHERE CENTER -0.365674 -0.878086 -0.0104889 RAD 0.00617284 + txt002 + SPHERE CENTER -0.346241 -0.863875 -0.00500196 RAD 0.00617284 + txt002 + SPHERE CENTER -0.367962 -0.859887 0.00604126 RAD 0.00617284 + txt002 + SPHERE CENTER -0.384548 -0.868748 -0.0233819 RAD 0.00617284 + txt002 + SPHERE CENTER -0.386837 -0.85055 -0.00685171 RAD 0.00617284 + txt002 + SPHERE CENTER -0.38399 -0.8452 -0.0307879 RAD 0.00617284 + txt002 + SPHERE CENTER -0.362827 -0.872736 -0.0344251 RAD 0.00617284 + txt002 + SPHERE CENTER -0.362269 -0.849188 -0.0418311 RAD 0.00617284 + txt002 + SPHERE CENTER -0.343394 -0.858526 -0.0289382 RAD 0.00617284 + txt002 + SPHERE CENTER -0.316097 -0.818893 -0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER -0.297057 -0.819591 -0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER -0.304244 -0.79807 -0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER -0.293153 -0.814956 -0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER -0.30891 -0.840413 -0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.305006 -0.835779 -0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER -0.32795 -0.839716 -0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER -0.320001 -0.823527 -0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER -0.339041 -0.822829 -0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER -0.327188 -0.802007 -0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER -0.296284 -0.842728 0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER -0.272611 -0.848999 0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER -0.278432 -0.829121 -0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.281616 -0.828835 0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER -0.290462 -0.862606 0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER -0.299468 -0.842441 0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.314135 -0.856335 0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.287278 -0.862893 -0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER -0.310951 -0.856621 -0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER -0.293099 -0.843015 -0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER -0.358439 -0.594141 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.389119 -0.547576 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.386849 -0.525642 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.366733 -0.538964 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.379645 -0.528407 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.409235 -0.534255 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.402031 -0.537019 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.411505 -0.556189 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.396323 -0.544812 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.398593 -0.566746 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.376207 -0.558134 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.317871 -0.566667 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.299647 -0.551072 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.29885 -0.563547 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.315344 -0.545434 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.318667 -0.554192 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.334364 -0.548554 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.336891 -0.569787 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.302174 -0.572306 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.320398 -0.587901 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.301377 -0.584781 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.339267 -0.522591 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.327164 -0.504962 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.318612 -0.528125 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.339267 -0.522591 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.347819 -0.499428 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.359921 -0.517056 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.359921 -0.517056 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.327164 -0.504962 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.339267 -0.522591 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.318612 -0.528125 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.429687 -0.57505 0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER -0.446515 -0.55776 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.428387 -0.562617 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.423296 -0.5512 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.447815 -0.570193 0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER -0.424596 -0.563633 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.430987 -0.587483 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.452905 -0.58161 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.436077 -0.5989 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434777 -0.586467 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.379835 -0.550064 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.372012 -0.535334 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.359551 -0.536327 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.35918 -0.555599 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.392296 -0.549071 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.379464 -0.569335 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.400119 -0.563801 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.392667 -0.529799 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.400489 -0.54453 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.380205 -0.530793 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399007 -0.621614 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.420252 -0.632748 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.408963 -0.638118 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.419661 -0.61608 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.410295 -0.616244 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.409705 -0.599576 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.38905 -0.60511 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399597 -0.638282 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.378352 -0.627149 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.388308 -0.643653 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.408291 -0.619127 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.415912 -0.617918 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.39183 -0.616439 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.406911 -0.597788 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.432372 -0.620605 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.423371 -0.600475 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.424751 -0.621814 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.417292 -0.639257 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.409671 -0.640465 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.39321 -0.637778 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37761 -0.665691 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.375943 -0.687009 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.356956 -0.671225 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37761 -0.665691 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.396598 -0.681475 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.398265 -0.660156 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.398265 -0.660156 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.375943 -0.687009 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37761 -0.665691 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.356956 -0.671225 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.337042 -0.638217 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.320629 -0.641183 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.313702 -0.630777 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.328614 -0.618565 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.34397 -0.648623 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.351955 -0.626005 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.360383 -0.645657 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.329058 -0.660835 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.345471 -0.65787 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.32213 -0.65043 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.358439 -0.594141 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.409774 -0.542042 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.413579 -0.517869 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.395831 -0.525596 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.393219 -0.528508 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.427522 -0.534315 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.407161 -0.544953 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.423716 -0.558488 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.430134 -0.531404 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.426328 -0.555577 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.412386 -0.539131 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.379835 -0.550064 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.375068 -0.529037 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.356494 -0.542624 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.371406 -0.530412 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.398409 -0.536477 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.394747 -0.537852 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.403175 -0.557504 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.383497 -0.548689 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.388263 -0.569716 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.364922 -0.562276 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.339267 -0.522591 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.327164 -0.504962 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.318612 -0.528125 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.339267 -0.522591 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.347819 -0.499428 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.359921 -0.517056 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.359921 -0.517056 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.327164 -0.504962 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.339267 -0.522591 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.318612 -0.528125 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.388377 -0.586119 -0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.399584 -0.570335 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.403942 -0.569167 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.381987 -0.562269 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.384019 -0.587286 -0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.366422 -0.57922 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.372813 -0.60307 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.405974 -0.594185 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.394768 -0.609969 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.410332 -0.593017 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.317871 -0.566667 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.317033 -0.562847 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.327827 -0.583171 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.338525 -0.561133 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.307077 -0.546343 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.328569 -0.544629 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.307914 -0.550163 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.296378 -0.568381 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.297216 -0.572202 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.307172 -0.588706 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.337042 -0.638217 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.317573 -0.64748 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.316758 -0.624481 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.316388 -0.643752 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.337857 -0.661216 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.336672 -0.657489 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.357326 -0.651954 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.338228 -0.641945 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.357697 -0.632683 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.337413 -0.618946 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.428945 -0.613592 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.451897 -0.612625 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.432663 -0.614807 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.436515 -0.593593 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.448179 -0.61141 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.432797 -0.592379 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.425227 -0.612377 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.444328 -0.632624 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.421376 -0.633591 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.425094 -0.634806 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37761 -0.665691 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.375943 -0.687009 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.356956 -0.671225 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37761 -0.665691 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.396598 -0.681475 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.398265 -0.660156 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.398265 -0.660156 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.375943 -0.687009 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37761 -0.665691 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.356956 -0.671225 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399007 -0.621614 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.402865 -0.620974 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.379986 -0.618494 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.39648 -0.600381 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.421886 -0.624094 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.4155 -0.603501 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.418027 -0.624734 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.405392 -0.642207 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.401533 -0.642848 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.382513 -0.639728 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.157543 -0.835815 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.119969 -0.899353 -0.117284 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0977075 -0.909872 -0.115431 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0997803 -0.886771 -0.1239 RAD 0.00617284 + txt002 + SPHERE CENTER -0.104052 -0.891613 -0.100068 RAD 0.00617284 + txt002 + SPHERE CENTER -0.117896 -0.922453 -0.108814 RAD 0.00617284 + txt002 + SPHERE CENTER -0.124241 -0.904194 -0.0934517 RAD 0.00617284 + txt002 + SPHERE CENTER -0.140158 -0.911935 -0.110668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.113625 -0.917612 -0.132647 RAD 0.00617284 + txt002 + SPHERE CENTER -0.135886 -0.907093 -0.1345 RAD 0.00617284 + txt002 + SPHERE CENTER -0.115698 -0.894512 -0.141116 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0844101 -0.836885 -0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0627848 -0.826973 -0.106005 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0805529 -0.830202 -0.122844 RAD 0.00617284 + txt002 + SPHERE CENTER -0.083104 -0.81296 -0.105354 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0666419 -0.833656 -0.0825505 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0869612 -0.819643 -0.0818993 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0882673 -0.843568 -0.0759343 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0640908 -0.850898 -0.10004 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0857161 -0.860809 -0.093424 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0818589 -0.854126 -0.116879 RAD 0.00617284 + txt002 + SPHERE CENTER -0.130205 -0.868703 -0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER -0.11253 -0.867758 -0.0334138 RAD 0.00617284 + txt002 + SPHERE CENTER -0.107566 -0.860854 -0.0565949 RAD 0.00617284 + txt002 + SPHERE CENTER -0.122142 -0.846864 -0.0423994 RAD 0.00617284 + txt002 + SPHERE CENTER -0.135168 -0.875606 -0.0274488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.14478 -0.854713 -0.0364345 RAD 0.00617284 + txt002 + SPHERE CENTER -0.152843 -0.876551 -0.0446649 RAD 0.00617284 + txt002 + SPHERE CENTER -0.120593 -0.889596 -0.0416443 RAD 0.00617284 + txt002 + SPHERE CENTER -0.138267 -0.890541 -0.0588603 RAD 0.00617284 + txt002 + SPHERE CENTER -0.115629 -0.882692 -0.0648253 RAD 0.00617284 + txt002 + SPHERE CENTER -0.193102 -0.898283 -0.129006 RAD 0.0185185 + txt002 + SPHERE CENTER -0.201143 -0.920038 -0.120537 RAD 0.00617284 + txt002 + SPHERE CENTER -0.17991 -0.910616 -0.112168 RAD 0.00617284 + txt002 + SPHERE CENTER -0.201384 -0.900209 -0.105825 RAD 0.00617284 + txt002 + SPHERE CENTER -0.214335 -0.907705 -0.137375 RAD 0.00617284 + txt002 + SPHERE CENTER -0.214576 -0.887876 -0.122663 RAD 0.00617284 + txt002 + SPHERE CENTER -0.206294 -0.88595 -0.145845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.192861 -0.918112 -0.143718 RAD 0.00617284 + txt002 + SPHERE CENTER -0.18482 -0.896357 -0.152187 RAD 0.00617284 + txt002 + SPHERE CENTER -0.171628 -0.90869 -0.135349 RAD 0.00617284 + txt002 + SPHERE CENTER -0.203337 -0.867633 -0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER -0.209658 -0.868948 -0.0385197 RAD 0.00617284 + txt002 + SPHERE CENTER -0.186008 -0.865773 -0.0448623 RAD 0.00617284 + txt002 + SPHERE CENTER -0.202239 -0.84746 -0.0481565 RAD 0.00617284 + txt002 + SPHERE CENTER -0.226988 -0.870808 -0.0560094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.219569 -0.84932 -0.0656463 RAD 0.00617284 + txt002 + SPHERE CENTER -0.220667 -0.869493 -0.0798417 RAD 0.00617284 + txt002 + SPHERE CENTER -0.210757 -0.889121 -0.0527151 RAD 0.00617284 + txt002 + SPHERE CENTER -0.204436 -0.887806 -0.0765474 RAD 0.00617284 + txt002 + SPHERE CENTER -0.187106 -0.885946 -0.0590577 RAD 0.00617284 + txt002 + SPHERE CENTER -0.230676 -0.834745 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.252002 -0.824206 -0.116217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.234336 -0.827952 -0.0993785 RAD 0.00617284 + txt002 + SPHERE CENTER -0.231282 -0.810793 -0.116868 RAD 0.00617284 + txt002 + SPHERE CENTER -0.248342 -0.830999 -0.139672 RAD 0.00617284 + txt002 + SPHERE CENTER -0.227621 -0.817586 -0.140323 RAD 0.00617284 + txt002 + SPHERE CENTER -0.227016 -0.841538 -0.146288 RAD 0.00617284 + txt002 + SPHERE CENTER -0.251396 -0.848158 -0.122182 RAD 0.00617284 + txt002 + SPHERE CENTER -0.23007 -0.858698 -0.128798 RAD 0.00617284 + txt002 + SPHERE CENTER -0.23373 -0.851905 -0.105343 RAD 0.00617284 + txt002 + SPHERE CENTER -0.147308 -0.866465 -0.177765 RAD 0.0185185 + txt002 + SPHERE CENTER -0.130609 -0.876203 -0.193128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.124356 -0.857385 -0.178416 RAD 0.00617284 + txt002 + SPHERE CENTER -0.128522 -0.879733 -0.16878 RAD 0.00617284 + txt002 + SPHERE CENTER -0.153561 -0.885283 -0.192477 RAD 0.00617284 + txt002 + SPHERE CENTER -0.151474 -0.888813 -0.168128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.170259 -0.875546 -0.177114 RAD 0.00617284 + txt002 + SPHERE CENTER -0.149395 -0.862935 -0.202114 RAD 0.00617284 + txt002 + SPHERE CENTER -0.166093 -0.853198 -0.186751 RAD 0.00617284 + txt002 + SPHERE CENTER -0.143141 -0.844117 -0.187402 RAD 0.00617284 + txt002 + SPHERE CENTER -0.184881 -0.802927 -0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER -0.180723 -0.785723 -0.188808 RAD 0.00617284 + txt002 + SPHERE CENTER -0.173028 -0.782104 -0.165627 RAD 0.00617284 + txt002 + SPHERE CENTER -0.161937 -0.798991 -0.179823 RAD 0.00617284 + txt002 + SPHERE CENTER -0.192576 -0.806546 -0.194773 RAD 0.00617284 + txt002 + SPHERE CENTER -0.17379 -0.819813 -0.185788 RAD 0.00617284 + txt002 + SPHERE CENTER -0.196734 -0.82375 -0.177557 RAD 0.00617284 + txt002 + SPHERE CENTER -0.203667 -0.78966 -0.180578 RAD 0.00617284 + txt002 + SPHERE CENTER -0.207825 -0.806864 -0.163362 RAD 0.00617284 + txt002 + SPHERE CENTER -0.195972 -0.786041 -0.157397 RAD 0.00617284 + txt002 + SPHERE CENTER -0.111748 -0.803997 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.108311 -0.798532 -0.183703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.119537 -0.819589 -0.17736 RAD 0.00617284 + txt002 + SPHERE CENTER -0.131037 -0.797989 -0.174066 RAD 0.00617284 + txt002 + SPHERE CENTER -0.100522 -0.78294 -0.166213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.123249 -0.782397 -0.156576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.10396 -0.788405 -0.142381 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0890219 -0.80454 -0.169507 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0924597 -0.810005 -0.145675 RAD 0.00617284 + txt002 + SPHERE CENTER -0.100248 -0.825597 -0.163165 RAD 0.00617284 + txt002 + SPHERE CENTER -0.172546 -0.643951 -0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER -0.202787 -0.61371 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.200937 -0.595399 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.194794 -0.591462 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.180539 -0.605717 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.208929 -0.617647 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.188531 -0.627965 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER -0.210779 -0.635958 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.223185 -0.603392 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER -0.225035 -0.621702 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.217042 -0.599454 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER -0.244096 -0.624779 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.260374 -0.607636 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.240901 -0.612854 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.237705 -0.600929 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.26357 -0.619561 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER -0.240901 -0.612854 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.247291 -0.636704 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.266765 -0.631486 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.250487 -0.648629 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.247291 -0.636704 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.191718 -0.5724 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.185011 -0.549732 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.167868 -0.56601 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.179793 -0.569205 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.208861 -0.556122 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.203643 -0.575596 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.215568 -0.578791 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.196936 -0.552927 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.203643 -0.575596 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.179793 -0.569205 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.131237 -0.632882 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.131575 -0.625593 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.15071 -0.6381 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER -0.146508 -0.614836 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.112102 -0.620375 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER -0.127034 -0.609618 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.111763 -0.627664 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER -0.116304 -0.643639 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.115965 -0.650927 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.135439 -0.656145 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.120168 -0.591572 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.105912 -0.577317 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER -0.111438 -0.600302 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.128897 -0.582843 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.114642 -0.568587 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.137627 -0.574113 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.128897 -0.582843 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0971825 -0.586046 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.111438 -0.600302 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.102708 -0.609032 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.100996 -0.663122 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0783272 -0.656415 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0978007 -0.651197 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0946054 -0.639272 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0815225 -0.66834 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0978007 -0.651197 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.104191 -0.675047 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0847178 -0.680265 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.107387 -0.686972 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.104191 -0.675047 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.183615 -0.68526 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.182351 -0.708085 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER -0.165569 -0.700531 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.188833 -0.704733 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER -0.200397 -0.692813 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.206879 -0.689462 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.201661 -0.669989 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.177134 -0.688611 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.178397 -0.665787 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER -0.160351 -0.681058 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.153374 -0.715501 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.136231 -0.731779 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.129524 -0.70911 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.141449 -0.712305 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.160081 -0.738169 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.165299 -0.718696 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.177224 -0.721891 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.148156 -0.734974 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER -0.165299 -0.718696 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.141449 -0.712305 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.224924 -0.696329 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.23918 -0.710584 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.216195 -0.705059 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.233654 -0.687599 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.24791 -0.701855 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.242384 -0.678869 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.233654 -0.687599 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.23045 -0.719314 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.216195 -0.705059 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.207465 -0.713788 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0133465 -0.69376 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.0631985 -0.668775 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0667914 -0.661946 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0511945 -0.680354 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0452771 -0.65711 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0787954 -0.650366 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0572811 -0.64553 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0752026 -0.657195 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0847128 -0.673611 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.08112 -0.680439 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.069116 -0.692019 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00804971 -0.649684 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.000226782 -0.634953 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0122343 -0.635947 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.012605 -0.655218 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0205108 -0.64869 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00767898 -0.668955 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0283337 -0.66342 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0208815 -0.629419 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0287044 -0.644149 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00842045 -0.630413 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0325183 -0.62221 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0446211 -0.604582 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.053173 -0.627745 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0325183 -0.62221 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0239663 -0.599047 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0118635 -0.616676 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0118635 -0.616676 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0446211 -0.604582 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0325183 -0.62221 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.053173 -0.627745 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0845947 -0.712851 -0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER 0.107813 -0.706291 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0896851 -0.701434 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0909853 -0.689001 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.102723 -0.717709 -0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0858949 -0.700418 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0795043 -0.724268 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.101422 -0.730141 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0782041 -0.736701 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0832945 -0.725284 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0539145 -0.666287 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0721382 -0.650692 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.072935 -0.663167 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0564414 -0.645053 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0531177 -0.653812 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0374209 -0.648173 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.034894 -0.669407 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0696112 -0.671925 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0513875 -0.68752 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.070408 -0.6844 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0347427 -0.737837 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0511556 -0.740802 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0580833 -0.730397 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.043171 -0.718185 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.027815 -0.748242 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0198304 -0.725625 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0114021 -0.745277 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0427273 -0.760455 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0263144 -0.757489 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0496549 -0.750049 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0440268 -0.740325 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0650768 -0.746894 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0607735 -0.723153 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0653796 -0.739183 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.04833 -0.764065 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0486329 -0.756355 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.02728 -0.757496 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0437239 -0.748035 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0226739 -0.741466 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0394207 -0.724295 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0058253 -0.76531 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.00415829 -0.786629 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0148294 -0.770845 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0058253 -0.76531 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.024813 -0.781094 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.02648 -0.759776 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.02648 -0.759776 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00415829 -0.786629 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0058253 -0.76531 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0148294 -0.770845 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0272215 -0.721234 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0484665 -0.732368 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0371781 -0.737738 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0478762 -0.715699 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0385099 -0.715864 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0379196 -0.699195 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0172649 -0.70473 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0278118 -0.737902 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00656677 -0.726768 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0165234 -0.743272 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.471405 -0.471405 1.11022e-16 RAD 0.166667 + txt002 + SPHERE CENTER 0.690426 -0.508983 1.83812e-16 RAD 0.0555556 + txt002 + SPHERE CENTER 0.755941 -0.484794 -0.0246914 RAD 0.0185185 + txt002 + SPHERE CENTER 0.767658 -0.47411 -0.0436186 RAD 0.00617284 + txt002 + SPHERE CENTER 0.749038 -0.489758 -0.0478724 RAD 0.00617284 + txt002 + SPHERE CENTER 0.744501 -0.467528 -0.0381316 RAD 0.00617284 + txt002 + SPHERE CENTER 0.774562 -0.469146 -0.0204376 RAD 0.00617284 + txt002 + SPHERE CENTER 0.751405 -0.462564 -0.0149506 RAD 0.00617284 + txt002 + SPHERE CENTER 0.762845 -0.47983 -0.00151032 RAD 0.00617284 + txt002 + SPHERE CENTER 0.779098 -0.491377 -0.0301783 RAD 0.00617284 + txt002 + SPHERE CENTER 0.767382 -0.502061 -0.0112511 RAD 0.00617284 + txt002 + SPHERE CENTER 0.760478 -0.507025 -0.0344321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.695668 -0.478434 -0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER 0.703418 -0.481931 -0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER 0.716184 -0.491475 -0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER 0.694124 -0.500827 -0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER 0.682902 -0.46889 -0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER 0.673608 -0.487786 -0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER 0.675152 -0.465393 -0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER 0.704962 -0.459538 -0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER 0.697211 -0.456041 -0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER 0.717727 -0.469082 -0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.7029 -0.436283 -0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER 0.714226 -0.418941 -0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER 0.724842 -0.44101 -0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.704751 -0.43889 -0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.692283 -0.414215 -0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER 0.682808 -0.434163 -0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER 0.680957 -0.431557 0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.712374 -0.416335 0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER 0.701048 -0.433677 0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER 0.722991 -0.438403 0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER 0.7507 -0.515343 0.0425863 RAD 0.0185185 + txt002 + SPHERE CENTER 0.773394 -0.506594 0.0468401 RAD 0.00617284 + txt002 + SPHERE CENTER 0.764807 -0.507924 0.0237283 RAD 0.00617284 + txt002 + SPHERE CENTER 0.755462 -0.491321 0.0394341 RAD 0.00617284 + txt002 + SPHERE CENTER 0.759287 -0.514012 0.065698 RAD 0.00617284 + txt002 + SPHERE CENTER 0.741355 -0.49874 0.058292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.736593 -0.522762 0.0614442 RAD 0.00617284 + txt002 + SPHERE CENTER 0.768632 -0.530616 0.0499923 RAD 0.00617284 + txt002 + SPHERE CENTER 0.745938 -0.539365 0.0457385 RAD 0.00617284 + txt002 + SPHERE CENTER 0.760045 -0.531946 0.0268805 RAD 0.00617284 + txt002 + SPHERE CENTER 0.697658 -0.466832 0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER 0.709346 -0.447385 0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.721188 -0.46231 0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER 0.703286 -0.447429 0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER 0.685816 -0.451907 0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER 0.679757 -0.451951 0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER 0.674129 -0.471354 0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.703718 -0.466788 0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER 0.692031 -0.486235 0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER 0.71556 -0.481713 0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER 0.685185 -0.539531 0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER 0.693658 -0.538818 0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER 0.708875 -0.534075 0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER 0.691194 -0.517905 0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669969 -0.544274 0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER 0.667505 -0.523361 0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER 0.661495 -0.544988 0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER 0.687649 -0.560445 0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER 0.679176 -0.561158 0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER 0.702866 -0.555702 0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.743468 -0.557494 -0.0178949 RAD 0.0185185 + txt002 + SPHERE CENTER 0.767402 -0.560084 -0.0233819 RAD 0.00617284 + txt002 + SPHERE CENTER 0.755145 -0.53997 -0.0307879 RAD 0.00617284 + txt002 + SPHERE CENTER 0.760285 -0.543179 -0.00685171 RAD 0.00617284 + txt002 + SPHERE CENTER 0.755725 -0.577608 -0.0104889 RAD 0.00617284 + txt002 + SPHERE CENTER 0.748608 -0.560703 0.00604126 RAD 0.00617284 + txt002 + SPHERE CENTER 0.731791 -0.575017 -0.00500196 RAD 0.00617284 + txt002 + SPHERE CENTER 0.750585 -0.574398 -0.0344251 RAD 0.00617284 + txt002 + SPHERE CENTER 0.726651 -0.571808 -0.0289382 RAD 0.00617284 + txt002 + SPHERE CENTER 0.738328 -0.554284 -0.0418311 RAD 0.00617284 + txt002 + SPHERE CENTER 0.677953 -0.581682 0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER 0.682851 -0.601808 0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER 0.700216 -0.58454 0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.680568 -0.579842 0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.660588 -0.59895 0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER 0.658304 -0.576984 0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER 0.65569 -0.578824 -0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.680237 -0.603648 -0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER 0.675339 -0.583522 -0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER 0.697602 -0.58638 -0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER 0.683194 -0.551134 -0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER 0.687731 -0.573364 -0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.703871 -0.56324 -0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER 0.682033 -0.571303 -0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER 0.667055 -0.561258 -0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER 0.661356 -0.559196 -0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER 0.662518 -0.539027 -0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.688893 -0.553195 -0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER 0.684356 -0.530964 -0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER 0.705033 -0.543071 -0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER 0.607487 -0.335322 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.629404 -0.313405 -0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.626214 -0.316595 -0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.624401 -0.335868 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.606941 -0.318408 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.631217 -0.294133 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.611945 -0.295946 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.634407 -0.290942 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.648676 -0.311592 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.651867 -0.308402 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.646863 -0.330864 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.610996 -0.384191 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.623201 -0.403702 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.635431 -0.385946 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.62031 -0.401066 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.598766 -0.401947 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.595876 -0.399312 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.586561 -0.382437 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.613886 -0.386827 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.601681 -0.367317 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.626116 -0.369071 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.558618 -0.331813 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.539107 -0.319608 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.541743 -0.322499 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.556863 -0.307378 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.555982 -0.328923 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.573738 -0.316693 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.575492 -0.341128 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.540862 -0.344043 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.560372 -0.356248 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.543497 -0.346933 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.625895 -0.264535 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.637402 -0.248969 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.646193 -0.271807 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.625088 -0.268363 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.617105 -0.241698 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.604791 -0.261092 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.605598 -0.257264 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.638209 -0.245142 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.626702 -0.260708 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.647 -0.267979 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.555109 -0.282943 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.550934 -0.258608 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.570229 -0.267823 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.570229 -0.267823 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.535813 -0.273728 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.555109 -0.282943 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539989 -0.298064 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.535813 -0.273728 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539989 -0.298064 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.555109 -0.282943 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.603979 -0.286452 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.613271 -0.265398 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.627912 -0.281225 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.610787 -0.26842 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.589337 -0.270625 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.586853 -0.273647 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.580045 -0.291679 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.606463 -0.283431 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.59717 -0.304484 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.621104 -0.299257 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.678274 -0.316914 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.69384 -0.305407 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.674446 -0.317721 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.671002 -0.296616 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.697667 -0.3046 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.67483 -0.295809 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.682101 -0.316107 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.701111 -0.325704 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.685545 -0.337211 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.681717 -0.338018 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.656357 -0.33883 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.677411 -0.329538 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.674389 -0.332022 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.661584 -0.314897 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.659378 -0.336346 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.643552 -0.321705 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.638325 -0.345639 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.672184 -0.353472 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.65113 -0.362764 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669162 -0.355956 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.659866 -0.3877 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.684201 -0.391875 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.674986 -0.37258 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.674986 -0.37258 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669081 -0.406996 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.659866 -0.3877 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.644745 -0.40282 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669081 -0.406996 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.644745 -0.40282 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.659866 -0.3877 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.607487 -0.335322 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.659645 -0.283164 0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER 0.672915 -0.269894 0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER 0.666987 -0.293281 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.649528 -0.275822 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.665573 -0.259777 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.642185 -0.265705 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.652302 -0.273047 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.683032 -0.277236 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669762 -0.290507 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.677104 -0.300624 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.656357 -0.33883 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.663448 -0.328536 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.639482 -0.329516 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.654603 -0.314396 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.680322 -0.33785 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.671477 -0.32371 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.673232 -0.348145 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.665202 -0.35297 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.658111 -0.363265 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.641237 -0.353951 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.603979 -0.286452 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.614273 -0.279361 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.628413 -0.288206 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.613293 -0.303327 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.589839 -0.277607 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.588858 -0.301572 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.579544 -0.284698 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.604959 -0.262487 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.594664 -0.269578 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.619099 -0.271332 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.610775 -0.279656 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.621535 -0.258061 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.634468 -0.275921 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.616678 -0.264057 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.597842 -0.261795 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.592985 -0.267791 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.587082 -0.28339 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.615632 -0.27366 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.604872 -0.295255 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.628565 -0.29152 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.555109 -0.282943 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.550934 -0.258608 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.570229 -0.267823 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.570229 -0.267823 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.535813 -0.273728 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.555109 -0.282943 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539989 -0.298064 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.535813 -0.273728 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539989 -0.298064 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.555109 -0.282943 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.558618 -0.331813 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.55307 -0.320611 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.57665 -0.325005 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.563845 -0.30788 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.535038 -0.327419 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.545813 -0.314688 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.540585 -0.338621 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.547843 -0.344544 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.553391 -0.355747 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.571423 -0.348938 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.663153 -0.332034 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.684748 -0.321274 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.678752 -0.326131 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.666888 -0.308341 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669149 -0.327177 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.651289 -0.314244 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.647554 -0.337937 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.681014 -0.344967 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.659419 -0.355727 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.675018 -0.349824 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.610996 -0.384191 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.622198 -0.389739 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.63493 -0.378964 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.617804 -0.366159 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.598265 -0.394966 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.593871 -0.371386 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.587062 -0.389418 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.61539 -0.407771 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.604188 -0.402224 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.628121 -0.396997 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.659866 -0.3877 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.684201 -0.391875 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.674986 -0.37258 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.674986 -0.37258 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669081 -0.406996 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.659866 -0.3877 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.644745 -0.40282 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669081 -0.406996 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.644745 -0.40282 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.659866 -0.3877 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.554344 -0.645066 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.610229 -0.668521 0.153697 RAD 0.0185185 + txt002 + SPHERE CENTER 0.633406 -0.663938 0.160875 RAD 0.00617284 + txt002 + SPHERE CENTER 0.626429 -0.65892 0.137727 RAD 0.00617284 + txt002 + SPHERE CENTER 0.617928 -0.64522 0.156428 RAD 0.00617284 + txt002 + SPHERE CENTER 0.617206 -0.673539 0.176845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.601728 -0.654822 0.172398 RAD 0.00617284 + txt002 + SPHERE CENTER 0.59403 -0.678123 0.169668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.625707 -0.687239 0.158144 RAD 0.00617284 + txt002 + SPHERE CENTER 0.602531 -0.691822 0.150967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.61873 -0.682221 0.134996 RAD 0.00617284 + txt002 + SPHERE CENTER 0.622977 -0.619787 0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.63767 -0.608008 0.0834188 RAD 0.00617284 + txt002 + SPHERE CENTER 0.620102 -0.623239 0.0751099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.613891 -0.601637 0.0853287 RAD 0.00617284 + txt002 + SPHERE CENTER 0.640545 -0.604555 0.107698 RAD 0.00617284 + txt002 + SPHERE CENTER 0.616766 -0.598184 0.109608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.625852 -0.616334 0.123668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.646756 -0.626157 0.0974792 RAD 0.00617284 + txt002 + SPHERE CENTER 0.632063 -0.637936 0.113449 RAD 0.00617284 + txt002 + SPHERE CENTER 0.629188 -0.641389 0.0891702 RAD 0.00617284 + txt002 + SPHERE CENTER 0.585648 -0.598918 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.601562 -0.580238 0.162601 RAD 0.00617284 + txt002 + SPHERE CENTER 0.605914 -0.59781 0.14581 RAD 0.00617284 + txt002 + SPHERE CENTER 0.587563 -0.581665 0.142311 RAD 0.00617284 + txt002 + SPHERE CENTER 0.581295 -0.581346 0.176661 RAD 0.00617284 + txt002 + SPHERE CENTER 0.567297 -0.582773 0.156372 RAD 0.00617284 + txt002 + SPHERE CENTER 0.565381 -0.600026 0.173931 RAD 0.00617284 + txt002 + SPHERE CENTER 0.599646 -0.597491 0.18016 RAD 0.00617284 + txt002 + SPHERE CENTER 0.583732 -0.616171 0.177429 RAD 0.00617284 + txt002 + SPHERE CENTER 0.603999 -0.615063 0.163369 RAD 0.00617284 + txt002 + SPHERE CENTER 0.541596 -0.6938 0.165419 RAD 0.0185185 + txt002 + SPHERE CENTER 0.547376 -0.70016 0.188567 RAD 0.00617284 + txt002 + SPHERE CENTER 0.564621 -0.690564 0.173728 RAD 0.00617284 + txt002 + SPHERE CENTER 0.546319 -0.676324 0.182211 RAD 0.00617284 + txt002 + SPHERE CENTER 0.524351 -0.703396 0.180258 RAD 0.00617284 + txt002 + SPHERE CENTER 0.523294 -0.679561 0.173902 RAD 0.00617284 + txt002 + SPHERE CENTER 0.518571 -0.697037 0.157111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.542652 -0.717636 0.171776 RAD 0.00617284 + txt002 + SPHERE CENTER 0.536873 -0.711276 0.148628 RAD 0.00617284 + txt002 + SPHERE CENTER 0.559898 -0.70804 0.156937 RAD 0.00617284 + txt002 + SPHERE CENTER 0.517014 -0.624197 0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER 0.516313 -0.60809 0.190293 RAD 0.00617284 + txt002 + SPHERE CENTER 0.538029 -0.616221 0.181811 RAD 0.00617284 + txt002 + SPHERE CENTER 0.524375 -0.60089 0.168094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.495298 -0.616065 0.180075 RAD 0.00617284 + txt002 + SPHERE CENTER 0.50336 -0.608865 0.157875 RAD 0.00617284 + txt002 + SPHERE CENTER 0.495999 -0.632172 0.161374 RAD 0.00617284 + txt002 + SPHERE CENTER 0.508952 -0.631397 0.193792 RAD 0.00617284 + txt002 + SPHERE CENTER 0.509653 -0.647504 0.175091 RAD 0.00617284 + txt002 + SPHERE CENTER 0.530668 -0.639529 0.18531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.48571 -0.670344 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.466887 -0.67091 0.138803 RAD 0.00617284 + txt002 + SPHERE CENTER 0.490138 -0.671107 0.147112 RAD 0.00617284 + txt002 + SPHERE CENTER 0.480853 -0.650637 0.136894 RAD 0.00617284 + txt002 + SPHERE CENTER 0.46246 -0.670147 0.114524 RAD 0.00617284 + txt002 + SPHERE CENTER 0.476425 -0.649874 0.112614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.481283 -0.669581 0.0985541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.471745 -0.690617 0.124743 RAD 0.00617284 + txt002 + SPHERE CENTER 0.490567 -0.690052 0.108773 RAD 0.00617284 + txt002 + SPHERE CENTER 0.494995 -0.690815 0.133052 RAD 0.00617284 + txt002 + SPHERE CENTER 0.578925 -0.714669 0.104938 RAD 0.0185185 + txt002 + SPHERE CENTER 0.597914 -0.729812 0.109385 RAD 0.00617284 + txt002 + SPHERE CENTER 0.602084 -0.70632 0.103028 RAD 0.00617284 + txt002 + SPHERE CENTER 0.592661 -0.711617 0.125228 RAD 0.00617284 + txt002 + SPHERE CENTER 0.574755 -0.738161 0.111295 RAD 0.00617284 + txt002 + SPHERE CENTER 0.569503 -0.719965 0.127138 RAD 0.00617284 + txt002 + SPHERE CENTER 0.555767 -0.723017 0.106848 RAD 0.00617284 + txt002 + SPHERE CENTER 0.584178 -0.732864 0.0890951 RAD 0.00617284 + txt002 + SPHERE CENTER 0.565189 -0.71772 0.0846485 RAD 0.00617284 + txt002 + SPHERE CENTER 0.588348 -0.709372 0.0827387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.52304 -0.691213 0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER 0.511567 -0.712906 0.0596212 RAD 0.00617284 + txt002 + SPHERE CENTER 0.529503 -0.710453 0.0764123 RAD 0.00617284 + txt002 + SPHERE CENTER 0.507717 -0.699372 0.079911 RAD 0.00617284 + txt002 + SPHERE CENTER 0.505104 -0.693665 0.0455609 RAD 0.00617284 + txt002 + SPHERE CENTER 0.501254 -0.680131 0.0658506 RAD 0.00617284 + txt002 + SPHERE CENTER 0.516576 -0.671972 0.0482916 RAD 0.00617284 + txt002 + SPHERE CENTER 0.526889 -0.704747 0.0420622 RAD 0.00617284 + txt002 + SPHERE CENTER 0.538362 -0.683054 0.044793 RAD 0.00617284 + txt002 + SPHERE CENTER 0.544826 -0.702295 0.0588533 RAD 0.00617284 + txt002 + SPHERE CENTER 0.591673 -0.665934 0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER 0.605761 -0.658095 0.0319289 RAD 0.00617284 + txt002 + SPHERE CENTER 0.58746 -0.643855 0.0404111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.607672 -0.647455 0.0541285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.609975 -0.680174 0.0421477 RAD 0.00617284 + txt002 + SPHERE CENTER 0.611885 -0.669535 0.0643473 RAD 0.00617284 + txt002 + SPHERE CENTER 0.595887 -0.688013 0.0608487 RAD 0.00617284 + txt002 + SPHERE CENTER 0.589763 -0.676573 0.0284303 RAD 0.00617284 + txt002 + SPHERE CENTER 0.575674 -0.684413 0.0471312 RAD 0.00617284 + txt002 + SPHERE CENTER 0.571461 -0.662334 0.0369125 RAD 0.00617284 + txt002 + SPHERE CENTER 0.471405 -0.471405 0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER 0.501645 -0.441164 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.518106 -0.424703 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER 0.522721 -0.437548 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.505261 -0.420089 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.497031 -0.428319 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.484186 -0.423704 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.48057 -0.44478 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.51449 -0.445778 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.498029 -0.462239 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.519105 -0.458623 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.542955 -0.452233 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.560583 -0.44013 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.542955 -0.452233 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.53742 -0.431578 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.560583 -0.44013 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.53742 -0.431578 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.542955 -0.452233 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.566118 -0.460785 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.548489 -0.472887 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.548489 -0.472887 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.490576 -0.399854 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.502679 -0.382226 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.511231 -0.405389 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.490576 -0.399854 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.482024 -0.376691 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.469922 -0.39432 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.469922 -0.39432 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.502679 -0.382226 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.490576 -0.399854 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.511231 -0.405389 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.430095 -0.460336 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.427669 -0.446904 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.450155 -0.45293 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.436486 -0.436486 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.407609 -0.454311 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER 0.416426 -0.443892 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.410035 -0.467742 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.421278 -0.470754 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.423704 -0.484186 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.443764 -0.47678 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.419026 -0.419026 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.414851 -0.39469 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.434147 -0.403906 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.434147 -0.403906 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399731 -0.409811 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.419026 -0.419026 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.403906 -0.434147 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399731 -0.409811 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.403906 -0.434147 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.419026 -0.419026 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399854 -0.490576 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.378536 -0.488909 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399854 -0.490576 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.39432 -0.469922 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.378536 -0.488909 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.39432 -0.469922 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399854 -0.490576 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.384071 -0.509564 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.405389 -0.511231 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.405389 -0.511231 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.482473 -0.512714 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.495905 -0.51514 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.506323 -0.506323 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.48988 -0.492654 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.472055 -0.521531 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.46603 -0.499045 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.458623 -0.519105 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.488498 -0.5352 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER 0.475067 -0.532774 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.498917 -0.526383 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.452233 -0.542955 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.4539 -0.564273 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.472887 -0.548489 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.452233 -0.542955 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.433245 -0.558738 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.431578 -0.53742 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.431578 -0.53742 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.4539 -0.564273 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.452233 -0.542955 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.472887 -0.548489 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.523783 -0.523783 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.548119 -0.527958 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.538903 -0.508662 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.538903 -0.508662 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.532998 -0.543078 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.523783 -0.523783 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.508662 -0.538903 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.532998 -0.543078 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.508662 -0.538903 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.523783 -0.523783 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.335322 -0.607487 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.313405 -0.629404 0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.316595 -0.626214 0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.335868 -0.624401 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.318408 -0.606941 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.294133 -0.631217 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.295946 -0.611945 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.290942 -0.634407 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.311592 -0.648676 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.308402 -0.651867 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.330864 -0.646863 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.384191 -0.610996 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.405245 -0.601704 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.402224 -0.604188 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.389418 -0.587062 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.387213 -0.608512 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.371386 -0.593871 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.366159 -0.617804 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.400018 -0.625637 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.378964 -0.63493 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.396997 -0.628121 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.331813 -0.558618 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.341105 -0.537564 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.355747 -0.553391 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.338621 -0.540585 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.317172 -0.542791 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.314688 -0.545813 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.30788 -0.563845 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.334297 -0.555596 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.325005 -0.57665 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.348938 -0.571423 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.264535 -0.625895 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.245336 -0.623429 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.268271 -0.624736 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.260997 -0.604627 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.2416 -0.624589 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.257262 -0.605787 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.2608 -0.627055 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.248874 -0.644697 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.268073 -0.647163 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.271809 -0.646004 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282943 -0.555109 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.278768 -0.530773 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.298064 -0.539989 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.298064 -0.539989 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.263648 -0.545894 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282943 -0.555109 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.267823 -0.570229 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.263648 -0.545894 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.267823 -0.570229 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282943 -0.555109 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.286452 -0.603979 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.266942 -0.591774 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.269578 -0.594664 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.284698 -0.579544 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.283817 -0.601088 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.301572 -0.588858 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.303327 -0.613293 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.268696 -0.616209 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.288206 -0.628413 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.271332 -0.619099 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.316914 -0.678274 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.31938 -0.697473 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.338182 -0.681812 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.318074 -0.674538 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.298112 -0.693935 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.296805 -0.671 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.295646 -0.674736 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31822 -0.701209 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.315754 -0.682009 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337022 -0.685547 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.33883 -0.656357 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.351035 -0.675867 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.363265 -0.658111 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.348145 -0.673232 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.3266 -0.674113 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.32371 -0.671477 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.314396 -0.654603 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.341721 -0.658993 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.329516 -0.639482 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.353951 -0.641237 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.3877 -0.659866 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.412036 -0.664041 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.40282 -0.644745 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.40282 -0.644745 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.396915 -0.679161 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.3877 -0.659866 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37258 -0.674986 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.396915 -0.679161 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37258 -0.674986 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.3877 -0.659866 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.554344 -0.645066 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.616373 -0.681385 -0.129006 RAD 0.0185185 + txt002 + SPHERE CENTER 0.639472 -0.678928 -0.137375 RAD 0.00617284 + txt002 + SPHERE CENTER 0.621631 -0.664108 -0.145845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.629767 -0.661636 -0.122663 RAD 0.00617284 + txt002 + SPHERE CENTER 0.634214 -0.696205 -0.120537 RAD 0.00617284 + txt002 + SPHERE CENTER 0.624508 -0.678912 -0.105825 RAD 0.00617284 + txt002 + SPHERE CENTER 0.611115 -0.698662 -0.112168 RAD 0.00617284 + txt002 + SPHERE CENTER 0.626079 -0.698678 -0.143718 RAD 0.00617284 + txt002 + SPHERE CENTER 0.602979 -0.701135 -0.135349 RAD 0.00617284 + txt002 + SPHERE CENTER 0.608237 -0.683858 -0.152187 RAD 0.00617284 + txt002 + SPHERE CENTER 0.617144 -0.607573 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.63057 -0.595495 -0.139672 RAD 0.00617284 + txt002 + SPHERE CENTER 0.617371 -0.615286 -0.146288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.605919 -0.594239 -0.140323 RAD 0.00617284 + txt002 + SPHERE CENTER 0.630343 -0.587782 -0.116217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.605692 -0.586526 -0.116868 RAD 0.00617284 + txt002 + SPHERE CENTER 0.616917 -0.59986 -0.0993785 RAD 0.00617284 + txt002 + SPHERE CENTER 0.641795 -0.608828 -0.122182 RAD 0.00617284 + txt002 + SPHERE CENTER 0.628369 -0.620906 -0.105343 RAD 0.00617284 + txt002 + SPHERE CENTER 0.628595 -0.628619 -0.128798 RAD 0.00617284 + txt002 + SPHERE CENTER 0.609912 -0.649723 -0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER 0.631982 -0.640648 -0.0560094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.62585 -0.64267 -0.0798417 RAD 0.00617284 + txt002 + SPHERE CENTER 0.614812 -0.625749 -0.0656463 RAD 0.00617284 + txt002 + SPHERE CENTER 0.616044 -0.647702 -0.0385197 RAD 0.00617284 + txt002 + SPHERE CENTER 0.598874 -0.632802 -0.0481565 RAD 0.00617284 + txt002 + SPHERE CENTER 0.593974 -0.656777 -0.0448623 RAD 0.00617284 + txt002 + SPHERE CENTER 0.627081 -0.664623 -0.0527151 RAD 0.00617284 + txt002 + SPHERE CENTER 0.605012 -0.673698 -0.0590577 RAD 0.00617284 + txt002 + SPHERE CENTER 0.620949 -0.666645 -0.0765474 RAD 0.00617284 + txt002 + SPHERE CENTER 0.553573 -0.718878 -0.117284 RAD 0.0185185 + txt002 + SPHERE CENTER 0.563328 -0.73992 -0.108814 RAD 0.00617284 + txt002 + SPHERE CENTER 0.577348 -0.719679 -0.110668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.559693 -0.720935 -0.0934517 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539553 -0.739118 -0.115431 RAD 0.00617284 + txt002 + SPHERE CENTER 0.535918 -0.720133 -0.100068 RAD 0.00617284 + txt002 + SPHERE CENTER 0.529798 -0.718076 -0.1239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.557208 -0.737863 -0.132647 RAD 0.00617284 + txt002 + SPHERE CENTER 0.547453 -0.716821 -0.141116 RAD 0.00617284 + txt002 + SPHERE CENTER 0.571228 -0.717623 -0.1345 RAD 0.00617284 + txt002 + SPHERE CENTER 0.547112 -0.687216 -0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER 0.554862 -0.690713 -0.0274488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.570641 -0.682694 -0.0446649 RAD 0.00617284 + txt002 + SPHERE CENTER 0.552739 -0.667813 -0.0364345 RAD 0.00617284 + txt002 + SPHERE CENTER 0.531333 -0.695235 -0.0334138 RAD 0.00617284 + txt002 + SPHERE CENTER 0.52921 -0.672335 -0.0423994 RAD 0.00617284 + txt002 + SPHERE CENTER 0.523582 -0.691738 -0.0565949 RAD 0.00617284 + txt002 + SPHERE CENTER 0.549235 -0.710116 -0.0416443 RAD 0.00617284 + txt002 + SPHERE CENTER 0.541484 -0.706619 -0.0648253 RAD 0.00617284 + txt002 + SPHERE CENTER 0.565014 -0.702097 -0.0588603 RAD 0.00617284 + txt002 + SPHERE CENTER 0.491544 -0.682558 -0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.474542 -0.688647 -0.0825505 RAD 0.00617284 + txt002 + SPHERE CENTER 0.498226 -0.686417 -0.0759343 RAD 0.00617284 + txt002 + SPHERE CENTER 0.485132 -0.666351 -0.0818993 RAD 0.00617284 + txt002 + SPHERE CENTER 0.46786 -0.684788 -0.106005 RAD 0.00617284 + txt002 + SPHERE CENTER 0.47845 -0.662492 -0.105354 RAD 0.00617284 + txt002 + SPHERE CENTER 0.484862 -0.678699 -0.122844 RAD 0.00617284 + txt002 + SPHERE CENTER 0.480953 -0.704854 -0.10004 RAD 0.00617284 + txt002 + SPHERE CENTER 0.497955 -0.698765 -0.116879 RAD 0.00617284 + txt002 + SPHERE CENTER 0.504637 -0.702624 -0.093424 RAD 0.00617284 + txt002 + SPHERE CENTER 0.560805 -0.676727 -0.177765 RAD 0.0185185 + txt002 + SPHERE CENTER 0.57563 -0.689897 -0.192477 RAD 0.00617284 + txt002 + SPHERE CENTER 0.585222 -0.673115 -0.177114 RAD 0.00617284 + txt002 + SPHERE CENTER 0.575587 -0.693998 -0.168128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.551213 -0.693509 -0.193128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.55117 -0.69761 -0.16878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.536388 -0.680339 -0.178416 RAD 0.00617284 + txt002 + SPHERE CENTER 0.560848 -0.672626 -0.202114 RAD 0.00617284 + txt002 + SPHERE CENTER 0.546023 -0.659456 -0.187402 RAD 0.00617284 + txt002 + SPHERE CENTER 0.57044 -0.655844 -0.186751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.498776 -0.640408 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.478525 -0.627785 -0.166213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.484234 -0.630799 -0.142381 RAD 0.00617284 + txt002 + SPHERE CENTER 0.497935 -0.615951 -0.156576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.493066 -0.637394 -0.183703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.512476 -0.62556 -0.174066 RAD 0.00617284 + txt002 + SPHERE CENTER 0.513317 -0.650016 -0.17736 RAD 0.00617284 + txt002 + SPHERE CENTER 0.479365 -0.652241 -0.169507 RAD 0.00617284 + txt002 + SPHERE CENTER 0.499616 -0.664864 -0.163165 RAD 0.00617284 + txt002 + SPHERE CENTER 0.485075 -0.655255 -0.145675 RAD 0.00617284 + txt002 + SPHERE CENTER 0.561576 -0.602915 -0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER 0.570049 -0.602201 -0.194773 RAD 0.00617284 + txt002 + SPHERE CENTER 0.582252 -0.615021 -0.177557 RAD 0.00617284 + txt002 + SPHERE CENTER 0.560414 -0.623084 -0.185788 RAD 0.00617284 + txt002 + SPHERE CENTER 0.549372 -0.590095 -0.188808 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539737 -0.610978 -0.179823 RAD 0.00617284 + txt002 + SPHERE CENTER 0.540899 -0.590808 -0.165627 RAD 0.00617284 + txt002 + SPHERE CENTER 0.571211 -0.582032 -0.180578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.562738 -0.582745 -0.157397 RAD 0.00617284 + txt002 + SPHERE CENTER 0.583414 -0.594852 -0.163362 RAD 0.00617284 + txt002 + SPHERE CENTER 0.335322 -0.607487 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.283164 -0.659645 -0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER 0.269894 -0.672915 -0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER 0.293281 -0.666987 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.275822 -0.649528 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.259777 -0.665573 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.265705 -0.642185 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.273047 -0.652302 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.277236 -0.683032 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.290507 -0.669762 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.300624 -0.677104 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.33883 -0.656357 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.350033 -0.661904 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.362764 -0.65113 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.345639 -0.638325 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.326099 -0.667131 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.321705 -0.643552 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.314897 -0.661584 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.343224 -0.679937 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.332022 -0.674389 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.355956 -0.669162 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.286452 -0.603979 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.280905 -0.592776 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.304484 -0.59717 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.291679 -0.580045 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.262872 -0.599585 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.273647 -0.586853 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.26842 -0.610787 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.275678 -0.61671 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.281225 -0.627912 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.299257 -0.621104 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.279656 -0.610775 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.256944 -0.602632 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.26347 -0.606749 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.273158 -0.587686 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.27313 -0.606658 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.289344 -0.591712 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.295841 -0.614801 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.263442 -0.62572 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.286153 -0.633864 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.269968 -0.629838 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282943 -0.555109 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.278768 -0.530773 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.298064 -0.539989 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.298064 -0.539989 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.263648 -0.545894 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282943 -0.555109 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.267823 -0.570229 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.263648 -0.545894 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.267823 -0.570229 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282943 -0.555109 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.331813 -0.558618 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.342108 -0.551527 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356248 -0.560372 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.341128 -0.575492 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.317673 -0.549772 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.316693 -0.573738 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.307378 -0.556863 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.332793 -0.534652 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.322499 -0.541743 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.346933 -0.543497 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.332034 -0.663153 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.340177 -0.685865 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.355123 -0.669651 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.33606 -0.679339 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.317089 -0.679367 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.312971 -0.672841 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.308945 -0.656656 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.336151 -0.669679 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.328008 -0.646968 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.351097 -0.653465 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.384191 -0.610996 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.391282 -0.600701 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.367317 -0.601681 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.382437 -0.586561 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.408157 -0.610016 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399312 -0.595876 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.401066 -0.62031 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.393037 -0.625136 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.385946 -0.635431 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.369071 -0.626116 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.3877 -0.659866 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.412036 -0.664041 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.40282 -0.644745 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.40282 -0.644745 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.396915 -0.679161 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.3877 -0.659866 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37258 -0.674986 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.396915 -0.679161 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37258 -0.674986 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.3877 -0.659866 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.471405 -0.471405 -0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER 0.441164 -0.441164 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.443014 -0.422853 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.449156 -0.418916 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.463412 -0.433171 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.435021 -0.445101 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.455419 -0.455419 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER 0.433171 -0.463412 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.420766 -0.430846 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER 0.418916 -0.449156 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.426908 -0.426908 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399854 -0.452233 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.383576 -0.43509 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.40305 -0.440308 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.406245 -0.428383 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.380381 -0.447015 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER 0.40305 -0.440308 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.396659 -0.464158 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.377186 -0.45894 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.393464 -0.476083 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.396659 -0.464158 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.452233 -0.399854 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.45894 -0.377186 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.476083 -0.393464 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.464158 -0.396659 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.43509 -0.383576 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.440308 -0.40305 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.428383 -0.406245 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.447015 -0.380381 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.440308 -0.40305 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.464158 -0.396659 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.512714 -0.460336 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.512375 -0.453047 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.493241 -0.465554 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER 0.497443 -0.44229 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.531849 -0.447829 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER 0.516916 -0.437072 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.532187 -0.455118 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER 0.527647 -0.471093 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.527985 -0.478381 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.508512 -0.483599 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.523783 -0.419026 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.538038 -0.404771 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER 0.532513 -0.427756 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.515053 -0.410297 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.529309 -0.396041 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.506323 -0.401567 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.515053 -0.410297 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.546768 -0.4135 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.532513 -0.427756 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.541242 -0.436486 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.542955 -0.490576 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.565623 -0.483869 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.54615 -0.478651 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.549345 -0.466726 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.562428 -0.495794 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.54615 -0.478651 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539759 -0.502501 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.559233 -0.507719 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.536564 -0.514426 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539759 -0.502501 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.460336 -0.512714 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.461599 -0.535539 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER 0.478381 -0.527985 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.455118 -0.532187 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER 0.443553 -0.520267 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.437072 -0.516916 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.44229 -0.497443 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.466817 -0.516065 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.465554 -0.493241 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER 0.483599 -0.508512 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.490576 -0.542955 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.507719 -0.559233 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.514426 -0.536564 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.502501 -0.539759 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.483869 -0.565623 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.478651 -0.54615 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.466726 -0.549345 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.495794 -0.562428 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER 0.478651 -0.54615 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.502501 -0.539759 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.419026 -0.523783 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.404771 -0.538038 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.427756 -0.532513 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.410297 -0.515053 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.396041 -0.529309 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.401567 -0.506323 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.410297 -0.515053 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.4135 -0.546768 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.427756 -0.532513 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.436486 -0.541242 -0.222222 RAD 0.00617284 + txt002 + +END_SCENE diff --git a/src/tbb/examples/parallel_for/tachyon/dat/balls3.dat b/src/tbb/examples/parallel_for/tachyon/dat/balls3.dat new file mode 100644 index 0000000..2837425 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/dat/balls3.dat @@ -0,0 +1,14804 @@ +BEGIN_SCENE + OUTFILE /dev/null + RESOLUTION 1024 768 + VERBOSE 0 + +CAMERA + ZOOM 1.20711 +ASPECTRATIO 1.0 + ANTIALIASING 0 + RAYDEPTH 5 + CENTER 2.1 1.3 1.7 + VIEWDIR -0.700389 -0.433574 -0.566982 + UPDIR -0.482085 -0.298433 0.82373 + +END_CAMERA + +BACKGROUND 0.078 0.361 0.753 + +LIGHT CENTER 4 3 2 RAD 0.002 COLOR 0.5 0.5 0.5 + +LIGHT CENTER 1 -4 4 RAD 0.002 COLOR 0.5 0.5 0.5 + +LIGHT CENTER -3 1 5 RAD 0.002 COLOR 0.5 0.5 0.5 + +TEXDEF txt001 AMBIENT 0.2 DIFFUSE 0.8 SPECULAR 0 OPACITY 1 +PHONG PLASTIC 0 PHONG_SIZE 100000 + COLOR 1 0.75 0.33 + TEXFUNC 0 + +TRI + V0 12 12 -0.5 V1 -12 -12 -0.5 V2 12 -12 -0.5 + txt001 +TRI + V0 12 12 -0.5 V1 -12 12 -0.5 V2 -12 -12 -0.5 + txt001 +TEXDEF txt002 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 +PHONG PLASTIC 0.5 PHONG_SIZE 45.2776 + COLOR 1 0.9 0.7 + TEXFUNC 0 + + SPHERE CENTER 0 0 0 RAD 0.5 + txt002 + SPHERE CENTER 0.272166 0.272166 0.544331 RAD 0.166667 + txt002 + SPHERE CENTER 0.420314 0.420314 0.618405 RAD 0.0555556 + txt002 + SPHERE CENTER 0.470715 0.470715 0.598245 RAD 0.0185185 + txt002 + SPHERE CENTER 0.481689 0.481689 0.57904 RAD 0.00617284 + txt002 + SPHERE CENTER 0.475329 0.45787 0.577669 RAD 0.00617284 + txt002 + SPHERE CENTER 0.45787 0.475329 0.577669 RAD 0.00617284 + txt002 + SPHERE CENTER 0.477074 0.494534 0.599616 RAD 0.00617284 + txt002 + SPHERE CENTER 0.453255 0.488174 0.598245 RAD 0.00617284 + txt002 + SPHERE CENTER 0.4661 0.48356 0.618821 RAD 0.00617284 + txt002 + SPHERE CENTER 0.494534 0.477074 0.599616 RAD 0.00617284 + txt002 + SPHERE CENTER 0.48356 0.4661 0.618821 RAD 0.00617284 + txt002 + SPHERE CENTER 0.488174 0.453255 0.598245 RAD 0.00617284 + txt002 + SPHERE CENTER 0.461623 0.409245 0.557924 RAD 0.0185185 + txt002 + SPHERE CENTER 0.47044 0.419664 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER 0.447954 0.425689 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.468014 0.433095 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER 0.484109 0.40322 0.549693 RAD 0.00617284 + txt002 + SPHERE CENTER 0.481683 0.416651 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER 0.475292 0.392801 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER 0.464049 0.395814 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER 0.455233 0.385395 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER 0.441563 0.401839 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.409245 0.461623 0.557924 RAD 0.0185185 + txt002 + SPHERE CENTER 0.419664 0.47044 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER 0.433095 0.468014 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER 0.425689 0.447954 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.395814 0.464049 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER 0.401839 0.441563 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.385395 0.455233 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER 0.40322 0.484109 0.549693 RAD 0.00617284 + txt002 + SPHERE CENTER 0.392801 0.475292 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER 0.416651 0.481683 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER 0.429405 0.481784 0.658726 RAD 0.0185185 + txt002 + SPHERE CENTER 0.441197 0.503434 0.660098 RAD 0.00617284 + txt002 + SPHERE CENTER 0.452601 0.483752 0.650495 RAD 0.00617284 + txt002 + SPHERE CENTER 0.434161 0.494577 0.63815 RAD 0.00617284 + txt002 + SPHERE CENTER 0.418001 0.501466 0.668328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.410965 0.492609 0.64638 RAD 0.00617284 + txt002 + SPHERE CENTER 0.406209 0.479816 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER 0.436441 0.490641 0.680674 RAD 0.00617284 + txt002 + SPHERE CENTER 0.42465 0.46899 0.679302 RAD 0.00617284 + txt002 + SPHERE CENTER 0.447846 0.470958 0.671072 RAD 0.00617284 + txt002 + SPHERE CENTER 0.367935 0.472692 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.36376 0.497028 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.383056 0.487812 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.383056 0.487812 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.34864 0.481907 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.367935 0.472692 0.593714 RAD 0.00617284 + txt002 + SPHERE CENTER 0.352815 0.457572 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.34864 0.481907 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.352815 0.457572 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.367935 0.472692 0.643096 RAD 0.00617284 + txt002 + SPHERE CENTER 0.379004 0.431383 0.678886 RAD 0.0185185 + txt002 + SPHERE CENTER 0.376578 0.444814 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399064 0.438789 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER 0.385395 0.455233 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356518 0.437408 0.687117 RAD 0.00617284 + txt002 + SPHERE CENTER 0.365335 0.447826 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.358944 0.423976 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.370187 0.420964 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.372614 0.407532 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER 0.392673 0.414939 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER 0.481784 0.429405 0.658726 RAD 0.0185185 + txt002 + SPHERE CENTER 0.503434 0.441197 0.660098 RAD 0.00617284 + txt002 + SPHERE CENTER 0.494577 0.434161 0.63815 RAD 0.00617284 + txt002 + SPHERE CENTER 0.483752 0.452601 0.650495 RAD 0.00617284 + txt002 + SPHERE CENTER 0.490641 0.436441 0.680674 RAD 0.00617284 + txt002 + SPHERE CENTER 0.470958 0.447846 0.671072 RAD 0.00617284 + txt002 + SPHERE CENTER 0.46899 0.42465 0.679302 RAD 0.00617284 + txt002 + SPHERE CENTER 0.501466 0.418001 0.668328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.479816 0.406209 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER 0.492609 0.410965 0.64638 RAD 0.00617284 + txt002 + SPHERE CENTER 0.431383 0.379004 0.678886 RAD 0.0185185 + txt002 + SPHERE CENTER 0.444814 0.376578 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.455233 0.385395 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER 0.438789 0.399064 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER 0.420964 0.370187 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.414939 0.392673 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER 0.407532 0.372614 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER 0.437408 0.356518 0.687117 RAD 0.00617284 + txt002 + SPHERE CENTER 0.423976 0.358944 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.447826 0.365335 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.472692 0.367935 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.497028 0.36376 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.487812 0.383056 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.487812 0.383056 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.481907 0.34864 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.472692 0.367935 0.643096 RAD 0.00617284 + txt002 + SPHERE CENTER 0.457572 0.352815 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.481907 0.34864 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.457572 0.352815 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.472692 0.367935 0.593714 RAD 0.00617284 + txt002 + SPHERE CENTER 0.461844 0.304709 0.43322 RAD 0.0555556 + txt002 + SPHERE CENTER 0.492085 0.33495 0.372739 RAD 0.0185185 + txt002 + SPHERE CENTER 0.492085 0.33495 0.348047 RAD 0.00617284 + txt002 + SPHERE CENTER 0.488469 0.313874 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.471009 0.331334 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.495701 0.356025 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.474625 0.352409 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER 0.495701 0.356025 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.51316 0.338566 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.51316 0.338566 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.509544 0.31749 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER 0.424345 0.305171 0.369341 RAD 0.0185185 + txt002 + SPHERE CENTER 0.40568 0.315605 0.356995 RAD 0.00617284 + txt002 + SPHERE CENTER 0.403931 0.312107 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER 0.419383 0.329161 0.372427 RAD 0.00617284 + txt002 + SPHERE CENTER 0.426095 0.30867 0.344961 RAD 0.00617284 + txt002 + SPHERE CENTER 0.439797 0.322225 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.444759 0.298235 0.357307 RAD 0.00617284 + txt002 + SPHERE CENTER 0.410643 0.291616 0.353908 RAD 0.00617284 + txt002 + SPHERE CENTER 0.429307 0.281181 0.366254 RAD 0.00617284 + txt002 + SPHERE CENTER 0.408893 0.288117 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.435193 0.368397 0.406378 RAD 0.0185185 + txt002 + SPHERE CENTER 0.440864 0.389015 0.394032 RAD 0.00617284 + txt002 + SPHERE CENTER 0.457301 0.37895 0.409464 RAD 0.00617284 + txt002 + SPHERE CENTER 0.451857 0.367697 0.388171 RAD 0.00617284 + txt002 + SPHERE CENTER 0.418755 0.378463 0.390945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.429748 0.357145 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.413085 0.357845 0.403291 RAD 0.00617284 + txt002 + SPHERE CENTER 0.4242 0.389715 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.418529 0.369098 0.424584 RAD 0.00617284 + txt002 + SPHERE CENTER 0.440637 0.37965 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER 0.529584 0.334488 0.436618 RAD 0.0185185 + txt002 + SPHERE CENTER 0.546497 0.347572 0.424272 RAD 0.00617284 + txt002 + SPHERE CENTER 0.532117 0.331508 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.522481 0.352406 0.421186 RAD 0.00617284 + txt002 + SPHERE CENTER 0.543964 0.350552 0.448652 RAD 0.00617284 + txt002 + SPHERE CENTER 0.519948 0.355387 0.445566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.52705 0.337468 0.460998 RAD 0.00617284 + txt002 + SPHERE CENTER 0.5536 0.329654 0.439705 RAD 0.00617284 + txt002 + SPHERE CENTER 0.536686 0.31657 0.45205 RAD 0.00617284 + txt002 + SPHERE CENTER 0.53922 0.313589 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER 0.472692 0.367935 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER 0.48474 0.389488 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.495668 0.369235 0.46131 RAD 0.00617284 + txt002 + SPHERE CENTER 0.477004 0.379669 0.448964 RAD 0.00617284 + txt002 + SPHERE CENTER 0.461764 0.388188 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER 0.454027 0.37837 0.457911 RAD 0.00617284 + txt002 + SPHERE CENTER 0.449715 0.366636 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER 0.480429 0.377754 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.46838 0.356202 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.491357 0.357501 0.482603 RAD 0.00617284 + txt002 + SPHERE CENTER 0.499343 0.304247 0.497099 RAD 0.0185185 + txt002 + SPHERE CENTER 0.518259 0.314219 0.509445 RAD 0.00617284 + txt002 + SPHERE CENTER 0.519922 0.310678 0.485065 RAD 0.00617284 + txt002 + SPHERE CENTER 0.504895 0.328108 0.494013 RAD 0.00617284 + txt002 + SPHERE CENTER 0.49768 0.307788 0.521479 RAD 0.00617284 + txt002 + SPHERE CENTER 0.484316 0.321677 0.506047 RAD 0.00617284 + txt002 + SPHERE CENTER 0.478764 0.297816 0.509133 RAD 0.00617284 + txt002 + SPHERE CENTER 0.512708 0.290358 0.512531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.493791 0.280387 0.500186 RAD 0.00617284 + txt002 + SPHERE CENTER 0.51437 0.286818 0.488152 RAD 0.00617284 + txt002 + SPHERE CENTER 0.518736 0.271262 0.399581 RAD 0.0185185 + txt002 + SPHERE CENTER 0.539811 0.274878 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.520873 0.290418 0.384149 RAD 0.00617284 + txt002 + SPHERE CENTER 0.533373 0.290264 0.405442 RAD 0.00617284 + txt002 + SPHERE CENTER 0.537674 0.255722 0.402668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.531235 0.271108 0.420874 RAD 0.00617284 + txt002 + SPHERE CENTER 0.516598 0.252106 0.415013 RAD 0.00617284 + txt002 + SPHERE CENTER 0.525174 0.255876 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER 0.504099 0.25226 0.39372 RAD 0.00617284 + txt002 + SPHERE CENTER 0.506236 0.271416 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.488495 0.241021 0.460062 RAD 0.0185185 + txt002 + SPHERE CENTER 0.50716 0.230587 0.472408 RAD 0.00617284 + txt002 + SPHERE CENTER 0.51153 0.24936 0.456976 RAD 0.00617284 + txt002 + SPHERE CENTER 0.499694 0.253381 0.478269 RAD 0.00617284 + txt002 + SPHERE CENTER 0.484125 0.222248 0.475494 RAD 0.00617284 + txt002 + SPHERE CENTER 0.476659 0.245042 0.481355 RAD 0.00617284 + txt002 + SPHERE CENTER 0.46546 0.232683 0.463149 RAD 0.00617284 + txt002 + SPHERE CENTER 0.495961 0.218227 0.454201 RAD 0.00617284 + txt002 + SPHERE CENTER 0.477296 0.228661 0.441856 RAD 0.00617284 + txt002 + SPHERE CENTER 0.500331 0.237 0.438769 RAD 0.00617284 + txt002 + SPHERE CENTER 0.450996 0.241483 0.396183 RAD 0.0185185 + txt002 + SPHERE CENTER 0.455172 0.217147 0.396183 RAD 0.00617284 + txt002 + SPHERE CENTER 0.472226 0.232599 0.40513 RAD 0.00617284 + txt002 + SPHERE CENTER 0.45115 0.228983 0.417476 RAD 0.00617284 + txt002 + SPHERE CENTER 0.433942 0.226031 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.429921 0.237867 0.408529 RAD 0.00617284 + txt002 + SPHERE CENTER 0.429767 0.250367 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.455018 0.229647 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER 0.450842 0.253983 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER 0.472072 0.245099 0.383837 RAD 0.00617284 + txt002 + SPHERE CENTER 0.304709 0.461844 0.43322 RAD 0.0555556 + txt002 + SPHERE CENTER 0.33495 0.492085 0.372739 RAD 0.0185185 + txt002 + SPHERE CENTER 0.33495 0.492085 0.348047 RAD 0.00617284 + txt002 + SPHERE CENTER 0.331334 0.471009 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.313874 0.488469 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.338566 0.51316 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31749 0.509544 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER 0.338566 0.51316 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356025 0.495701 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356025 0.495701 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.352409 0.474625 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER 0.368397 0.435193 0.406378 RAD 0.0185185 + txt002 + SPHERE CENTER 0.389015 0.440864 0.394032 RAD 0.00617284 + txt002 + SPHERE CENTER 0.367697 0.451857 0.388171 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37895 0.457301 0.409464 RAD 0.00617284 + txt002 + SPHERE CENTER 0.389715 0.4242 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37965 0.440637 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER 0.369098 0.418529 0.424584 RAD 0.00617284 + txt002 + SPHERE CENTER 0.378463 0.418755 0.390945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.357845 0.413085 0.403291 RAD 0.00617284 + txt002 + SPHERE CENTER 0.357145 0.429748 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.305171 0.424345 0.369341 RAD 0.0185185 + txt002 + SPHERE CENTER 0.315605 0.40568 0.356995 RAD 0.00617284 + txt002 + SPHERE CENTER 0.329161 0.419383 0.372427 RAD 0.00617284 + txt002 + SPHERE CENTER 0.312107 0.403931 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER 0.291616 0.410643 0.353908 RAD 0.00617284 + txt002 + SPHERE CENTER 0.288117 0.408893 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.281181 0.429307 0.366254 RAD 0.00617284 + txt002 + SPHERE CENTER 0.30867 0.426095 0.344961 RAD 0.00617284 + txt002 + SPHERE CENTER 0.298235 0.444759 0.357307 RAD 0.00617284 + txt002 + SPHERE CENTER 0.322225 0.439797 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.271262 0.518736 0.399581 RAD 0.0185185 + txt002 + SPHERE CENTER 0.274878 0.539811 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.290264 0.533373 0.405442 RAD 0.00617284 + txt002 + SPHERE CENTER 0.290418 0.520873 0.384149 RAD 0.00617284 + txt002 + SPHERE CENTER 0.255876 0.525174 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER 0.271416 0.506236 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.25226 0.504099 0.39372 RAD 0.00617284 + txt002 + SPHERE CENTER 0.255722 0.537674 0.402668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.252106 0.516598 0.415013 RAD 0.00617284 + txt002 + SPHERE CENTER 0.271108 0.531235 0.420874 RAD 0.00617284 + txt002 + SPHERE CENTER 0.241483 0.450996 0.396183 RAD 0.0185185 + txt002 + SPHERE CENTER 0.217147 0.455172 0.396183 RAD 0.00617284 + txt002 + SPHERE CENTER 0.228983 0.45115 0.417476 RAD 0.00617284 + txt002 + SPHERE CENTER 0.232599 0.472226 0.40513 RAD 0.00617284 + txt002 + SPHERE CENTER 0.229647 0.455018 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER 0.245099 0.472072 0.383837 RAD 0.00617284 + txt002 + SPHERE CENTER 0.253983 0.450842 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER 0.226031 0.433942 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.250367 0.429767 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.237867 0.429921 0.408529 RAD 0.00617284 + txt002 + SPHERE CENTER 0.241021 0.488495 0.460062 RAD 0.0185185 + txt002 + SPHERE CENTER 0.230587 0.50716 0.472408 RAD 0.00617284 + txt002 + SPHERE CENTER 0.253381 0.499694 0.478269 RAD 0.00617284 + txt002 + SPHERE CENTER 0.24936 0.51153 0.456976 RAD 0.00617284 + txt002 + SPHERE CENTER 0.218227 0.495961 0.454201 RAD 0.00617284 + txt002 + SPHERE CENTER 0.237 0.500331 0.438769 RAD 0.00617284 + txt002 + SPHERE CENTER 0.228661 0.477296 0.441856 RAD 0.00617284 + txt002 + SPHERE CENTER 0.222248 0.484125 0.475494 RAD 0.00617284 + txt002 + SPHERE CENTER 0.232683 0.46546 0.463149 RAD 0.00617284 + txt002 + SPHERE CENTER 0.245042 0.476659 0.481355 RAD 0.00617284 + txt002 + SPHERE CENTER 0.334488 0.529584 0.436618 RAD 0.0185185 + txt002 + SPHERE CENTER 0.347572 0.546497 0.424272 RAD 0.00617284 + txt002 + SPHERE CENTER 0.352406 0.522481 0.421186 RAD 0.00617284 + txt002 + SPHERE CENTER 0.331508 0.532117 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.329654 0.5536 0.439705 RAD 0.00617284 + txt002 + SPHERE CENTER 0.313589 0.53922 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31657 0.536686 0.45205 RAD 0.00617284 + txt002 + SPHERE CENTER 0.350552 0.543964 0.448652 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337468 0.52705 0.460998 RAD 0.00617284 + txt002 + SPHERE CENTER 0.355387 0.519948 0.445566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.304247 0.499343 0.497099 RAD 0.0185185 + txt002 + SPHERE CENTER 0.314219 0.518259 0.509445 RAD 0.00617284 + txt002 + SPHERE CENTER 0.328108 0.504895 0.494013 RAD 0.00617284 + txt002 + SPHERE CENTER 0.310678 0.519922 0.485065 RAD 0.00617284 + txt002 + SPHERE CENTER 0.290358 0.512708 0.512531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.286818 0.51437 0.488152 RAD 0.00617284 + txt002 + SPHERE CENTER 0.280387 0.493791 0.500186 RAD 0.00617284 + txt002 + SPHERE CENTER 0.307788 0.49768 0.521479 RAD 0.00617284 + txt002 + SPHERE CENTER 0.297816 0.478764 0.509133 RAD 0.00617284 + txt002 + SPHERE CENTER 0.321677 0.484316 0.506047 RAD 0.00617284 + txt002 + SPHERE CENTER 0.367935 0.472692 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER 0.389488 0.48474 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.379669 0.477004 0.448964 RAD 0.00617284 + txt002 + SPHERE CENTER 0.369235 0.495668 0.46131 RAD 0.00617284 + txt002 + SPHERE CENTER 0.377754 0.480429 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.357501 0.491357 0.482603 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356202 0.46838 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.388188 0.461764 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER 0.366636 0.449715 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37837 0.454027 0.457911 RAD 0.00617284 + txt002 + SPHERE CENTER 0.230635 0.38777 0.729516 RAD 0.0555556 + txt002 + SPHERE CENTER 0.2506 0.446614 0.769837 RAD 0.0185185 + txt002 + SPHERE CENTER 0.264242 0.467193 0.770086 RAD 0.00617284 + txt002 + SPHERE CENTER 0.272442 0.447086 0.758332 RAD 0.00617284 + txt002 + SPHERE CENTER 0.253384 0.459832 0.749168 RAD 0.00617284 + txt002 + SPHERE CENTER 0.2424 0.46672 0.781591 RAD 0.00617284 + txt002 + SPHERE CENTER 0.231541 0.459359 0.760673 RAD 0.00617284 + txt002 + SPHERE CENTER 0.228758 0.446141 0.781342 RAD 0.00617284 + txt002 + SPHERE CENTER 0.261459 0.453974 0.790755 RAD 0.00617284 + txt002 + SPHERE CENTER 0.247817 0.433396 0.790506 RAD 0.00617284 + txt002 + SPHERE CENTER 0.269659 0.433868 0.779001 RAD 0.00617284 + txt002 + SPHERE CENTER 0.301839 0.407906 0.732914 RAD 0.0185185 + txt002 + SPHERE CENTER 0.319874 0.420236 0.72141 RAD 0.00617284 + txt002 + SPHERE CENTER 0.303021 0.407886 0.708251 RAD 0.00617284 + txt002 + SPHERE CENTER 0.296625 0.428474 0.720288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.318692 0.420256 0.746073 RAD 0.00617284 + txt002 + SPHERE CENTER 0.295442 0.428494 0.744951 RAD 0.00617284 + txt002 + SPHERE CENTER 0.300656 0.407926 0.757577 RAD 0.00617284 + txt002 + SPHERE CENTER 0.325088 0.399668 0.734036 RAD 0.00617284 + txt002 + SPHERE CENTER 0.307053 0.387338 0.745541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.308235 0.387318 0.720878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.253236 0.449775 0.695877 RAD 0.0185185 + txt002 + SPHERE CENTER 0.263032 0.459076 0.675209 RAD 0.00617284 + txt002 + SPHERE CENTER 0.270029 0.436804 0.683251 RAD 0.00617284 + txt002 + SPHERE CENTER 0.247378 0.440021 0.673964 RAD 0.00617284 + txt002 + SPHERE CENTER 0.246239 0.472047 0.687835 RAD 0.00617284 + txt002 + SPHERE CENTER 0.230585 0.452992 0.68659 RAD 0.00617284 + txt002 + SPHERE CENTER 0.236443 0.462746 0.708504 RAD 0.00617284 + txt002 + SPHERE CENTER 0.26889 0.468829 0.697123 RAD 0.00617284 + txt002 + SPHERE CENTER 0.259094 0.459528 0.717791 RAD 0.00617284 + txt002 + SPHERE CENTER 0.275887 0.446557 0.705165 RAD 0.00617284 + txt002 + SPHERE CENTER 0.179397 0.426478 0.766439 RAD 0.0185185 + txt002 + SPHERE CENTER 0.174744 0.447688 0.778193 RAD 0.00617284 + txt002 + SPHERE CENTER 0.197172 0.437457 0.779597 RAD 0.00617284 + txt002 + SPHERE CENTER 0.1895 0.447523 0.758396 RAD 0.00617284 + txt002 + SPHERE CENTER 0.156968 0.436708 0.765035 RAD 0.00617284 + txt002 + SPHERE CENTER 0.171724 0.436544 0.745238 RAD 0.00617284 + txt002 + SPHERE CENTER 0.161621 0.415499 0.753281 RAD 0.00617284 + txt002 + SPHERE CENTER 0.164641 0.426642 0.786236 RAD 0.00617284 + txt002 + SPHERE CENTER 0.169293 0.405432 0.774481 RAD 0.00617284 + txt002 + SPHERE CENTER 0.187069 0.416412 0.787639 RAD 0.00617284 + txt002 + SPHERE CENTER 0.182032 0.429639 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER 0.177682 0.45215 0.683315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.190087 0.449636 0.704516 RAD 0.00617284 + txt002 + SPHERE CENTER 0.200611 0.44299 0.683192 RAD 0.00617284 + txt002 + SPHERE CENTER 0.169628 0.432153 0.671279 RAD 0.00617284 + txt002 + SPHERE CENTER 0.192556 0.422992 0.671155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.173978 0.409641 0.680442 RAD 0.00617284 + txt002 + SPHERE CENTER 0.159104 0.438799 0.692603 RAD 0.00617284 + txt002 + SPHERE CENTER 0.163454 0.416288 0.701767 RAD 0.00617284 + txt002 + SPHERE CENTER 0.171508 0.436286 0.713804 RAD 0.00617284 + txt002 + SPHERE CENTER 0.159431 0.367634 0.726118 RAD 0.0185185 + txt002 + SPHERE CENTER 0.13761 0.368692 0.737623 RAD 0.00617284 + txt002 + SPHERE CENTER 0.158434 0.366998 0.750781 RAD 0.00617284 + txt002 + SPHERE CENTER 0.153102 0.387887 0.738744 RAD 0.00617284 + txt002 + SPHERE CENTER 0.138607 0.369329 0.71296 RAD 0.00617284 + txt002 + SPHERE CENTER 0.154099 0.388523 0.714081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.160429 0.36827 0.701455 RAD 0.00617284 + txt002 + SPHERE CENTER 0.14394 0.34844 0.724997 RAD 0.00617284 + txt002 + SPHERE CENTER 0.165761 0.347381 0.713492 RAD 0.00617284 + txt002 + SPHERE CENTER 0.164764 0.346745 0.738155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.227999 0.384609 0.803476 RAD 0.0185185 + txt002 + SPHERE CENTER 0.237348 0.393812 0.824394 RAD 0.00617284 + txt002 + SPHERE CENTER 0.251829 0.390976 0.804597 RAD 0.00617284 + txt002 + SPHERE CENTER 0.234368 0.408432 0.804721 RAD 0.00617284 + txt002 + SPHERE CENTER 0.213518 0.387445 0.823273 RAD 0.00617284 + txt002 + SPHERE CENTER 0.210538 0.402066 0.8036 RAD 0.00617284 + txt002 + SPHERE CENTER 0.204169 0.378242 0.802355 RAD 0.00617284 + txt002 + SPHERE CENTER 0.23098 0.369989 0.823149 RAD 0.00617284 + txt002 + SPHERE CENTER 0.221631 0.360786 0.802231 RAD 0.00617284 + txt002 + SPHERE CENTER 0.245461 0.367152 0.803352 RAD 0.00617284 + txt002 + SPHERE CENTER 0.208034 0.325765 0.763155 RAD 0.0185185 + txt002 + SPHERE CENTER 0.209548 0.312342 0.783824 RAD 0.00617284 + txt002 + SPHERE CENTER 0.229235 0.324887 0.775781 RAD 0.00617284 + txt002 + SPHERE CENTER 0.209827 0.337 0.785069 RAD 0.00617284 + txt002 + SPHERE CENTER 0.188347 0.31322 0.771198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.188626 0.337878 0.772443 RAD 0.00617284 + txt002 + SPHERE CENTER 0.186834 0.326643 0.750529 RAD 0.00617284 + txt002 + SPHERE CENTER 0.207755 0.301107 0.76191 RAD 0.00617284 + txt002 + SPHERE CENTER 0.206242 0.31453 0.741241 RAD 0.00617284 + txt002 + SPHERE CENTER 0.227442 0.313652 0.753867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.279238 0.345901 0.766553 RAD 0.0185185 + txt002 + SPHERE CENTER 0.302145 0.344931 0.775717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.297823 0.356827 0.754517 RAD 0.00617284 + txt002 + SPHERE CENTER 0.289691 0.366251 0.775841 RAD 0.00617284 + txt002 + SPHERE CENTER 0.28356 0.334005 0.787754 RAD 0.00617284 + txt002 + SPHERE CENTER 0.271106 0.355325 0.787878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.260653 0.334975 0.77859 RAD 0.00617284 + txt002 + SPHERE CENTER 0.291692 0.324581 0.766429 RAD 0.00617284 + txt002 + SPHERE CENTER 0.268785 0.325551 0.757266 RAD 0.00617284 + txt002 + SPHERE CENTER 0.28737 0.336477 0.745229 RAD 0.00617284 + txt002 + SPHERE CENTER 0.115031 0.4293 0.544331 RAD 0.0555556 + txt002 + SPHERE CENTER 0.102505 0.502308 0.544331 RAD 0.0185185 + txt002 + SPHERE CENTER 0.110567 0.524146 0.536101 RAD 0.00617284 + txt002 + SPHERE CENTER 0.126738 0.506465 0.542066 RAD 0.00617284 + txt002 + SPHERE CENTER 0.112687 0.504055 0.521905 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0863343 0.519988 0.538366 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0884544 0.499897 0.524171 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0782715 0.49815 0.546597 RAD 0.00617284 + txt002 + SPHERE CENTER 0.100385 0.522399 0.558526 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0923218 0.500561 0.566757 RAD 0.00617284 + txt002 + SPHERE CENTER 0.116555 0.504718 0.564491 RAD 0.00617284 + txt002 + SPHERE CENTER 0.160392 0.474661 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.177777 0.492047 0.579103 RAD 0.00617284 + txt002 + SPHERE CENTER 0.176681 0.473492 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.159222 0.490951 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.161488 0.493217 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER 0.142932 0.492121 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.144102 0.475831 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.178947 0.475757 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER 0.161561 0.458371 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.177851 0.457202 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.160392 0.474661 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.167697 0.481967 0.484868 RAD 0.00617284 + txt002 + SPHERE CENTER 0.161561 0.458371 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.144102 0.475831 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.166528 0.498257 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.142932 0.492121 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.159222 0.490951 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.183987 0.480797 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.176681 0.473492 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.177851 0.457202 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0571437 0.456947 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0450372 0.477623 0.501329 RAD 0.00617284 + txt002 + SPHERE CENTER 0.055591 0.475469 0.523547 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0696413 0.47788 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0465898 0.4591 0.485076 RAD 0.00617284 + txt002 + SPHERE CENTER 0.071194 0.459357 0.487134 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0586963 0.438424 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0325396 0.45669 0.505236 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0446461 0.436013 0.511201 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0430934 0.454536 0.527454 RAD 0.00617284 + txt002 + SPHERE CENTER 0.115031 0.4293 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER 0.10495 0.439381 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0911807 0.435691 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.10864 0.45315 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.128801 0.43299 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER 0.13249 0.44676 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.138881 0.42291 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.111341 0.415531 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER 0.121421 0.40545 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0975713 0.411841 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0696698 0.383939 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.052284 0.366554 0.509559 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0708393 0.36765 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0533799 0.385109 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0511144 0.382844 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0522103 0.401399 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0685002 0.400229 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0685739 0.365384 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0859596 0.38277 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0871292 0.36648 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0571437 0.456947 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0493251 0.475575 0.595564 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0725262 0.467381 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER 0.06557 0.479825 0.577461 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0339426 0.465141 0.57931 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0501875 0.46939 0.561208 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0417612 0.446512 0.565115 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0408988 0.452697 0.599471 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0487174 0.434069 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0640999 0.444504 0.601529 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0696698 0.383939 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0623642 0.376634 0.603794 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0859596 0.38277 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0685002 0.400229 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0460743 0.377803 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0522103 0.401399 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0533799 0.385109 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0635337 0.360344 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0708393 0.36765 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0871292 0.36648 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.115031 0.4293 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.125111 0.439381 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.138881 0.435691 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.121421 0.45315 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.101261 0.43299 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0975713 0.44676 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0911807 0.42291 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.11872 0.415531 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.10864 0.40545 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.13249 0.411841 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.082487 0.239622 0.655442 RAD 0.0555556 + txt002 + SPHERE CENTER 0.0438957 0.258053 0.715923 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0426858 0.273525 0.735128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.064638 0.265928 0.726759 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0510334 0.281546 0.713318 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0219434 0.26565 0.724292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.030291 0.273671 0.702483 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0231533 0.250178 0.705088 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0355481 0.250032 0.737733 RAD 0.00617284 + txt002 + SPHERE CENTER 0.036758 0.23456 0.718528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0575003 0.242434 0.729364 RAD 0.00617284 + txt002 + SPHERE CENTER 0.117687 0.252557 0.719322 RAD 0.0185185 + txt002 + SPHERE CENTER 0.135677 0.265544 0.730157 RAD 0.00617284 + txt002 + SPHERE CENTER 0.138361 0.25778 0.706872 RAD 0.00617284 + txt002 + SPHERE CENTER 0.12224 0.275732 0.71212 RAD 0.00617284 + txt002 + SPHERE CENTER 0.115003 0.26032 0.742607 RAD 0.00617284 + txt002 + SPHERE CENTER 0.101567 0.270508 0.72457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.097014 0.247334 0.731771 RAD 0.00617284 + txt002 + SPHERE CENTER 0.131123 0.242369 0.737359 RAD 0.00617284 + txt002 + SPHERE CENTER 0.113134 0.229382 0.726523 RAD 0.00617284 + txt002 + SPHERE CENTER 0.133808 0.234605 0.714074 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0863845 0.308551 0.682285 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0971427 0.330622 0.67968 RAD 0.00617284 + txt002 + SPHERE CENTER 0.109956 0.310023 0.675083 RAD 0.00617284 + txt002 + SPHERE CENTER 0.091905 0.317013 0.659755 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0735708 0.329151 0.686881 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0683331 0.315541 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0628126 0.30708 0.689486 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0916222 0.322161 0.702209 RAD 0.00617284 + txt002 + SPHERE CENTER 0.080864 0.30009 0.704814 RAD 0.00617284 + txt002 + SPHERE CENTER 0.104436 0.301561 0.697613 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00869528 0.245118 0.652044 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0110117 0.257416 0.660413 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00823377 0.253319 0.675329 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0102865 0.269325 0.656641 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0105502 0.249215 0.637128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.010748 0.261124 0.633356 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00915679 0.236916 0.628759 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0126029 0.233209 0.655816 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00710408 0.22091 0.647447 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00664257 0.229111 0.670732 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0511841 0.295616 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0555846 0.315856 0.604965 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0705987 0.309941 0.623653 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0705297 0.296292 0.603077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.03617 0.301531 0.599717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0511152 0.281968 0.597829 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0317696 0.281291 0.613157 RAD 0.00617284 + txt002 + SPHERE CENTER 0.036239 0.31518 0.620293 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0318385 0.29494 0.633733 RAD 0.00617284 + txt002 + SPHERE CENTER 0.051253 0.309265 0.638981 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0472866 0.226687 0.591563 RAD 0.0185185 + txt002 + SPHERE CENTER 0.025169 0.224935 0.580727 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0281502 0.217281 0.604012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0288111 0.241399 0.598764 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0443054 0.234341 0.568278 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0479475 0.250805 0.586315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.066423 0.236092 0.579113 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0436445 0.210223 0.573526 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0657621 0.211974 0.584361 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0466257 0.202569 0.596811 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0399982 0.189123 0.689081 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0335228 0.179527 0.71089 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0567332 0.187058 0.707118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0385291 0.203632 0.709006 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0167878 0.181593 0.692853 RAD 0.00617284 + txt002 + SPHERE CENTER 0.021794 0.205698 0.690969 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0232631 0.191189 0.671044 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0349919 0.165018 0.690965 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0414672 0.174615 0.669156 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0582023 0.172549 0.687193 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0785895 0.170692 0.6286 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0867911 0.147549 0.631205 RAD 0.00617284 + txt002 + SPHERE CENTER 0.101845 0.166573 0.635801 RAD 0.00617284 + txt002 + SPHERE CENTER 0.083121 0.161663 0.65113 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0635354 0.151669 0.624003 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0598652 0.165782 0.643928 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0553337 0.174812 0.621398 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0822597 0.156579 0.608675 RAD 0.00617284 + txt002 + SPHERE CENTER 0.074058 0.179722 0.60607 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0973138 0.175603 0.613272 RAD 0.00617284 + txt002 + SPHERE CENTER 0.11379 0.183628 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER 0.133336 0.176775 0.705919 RAD 0.00617284 + txt002 + SPHERE CENTER 0.136161 0.192663 0.687231 RAD 0.00617284 + txt002 + SPHERE CENTER 0.124499 0.199753 0.707807 RAD 0.00617284 + txt002 + SPHERE CENTER 0.110965 0.167739 0.711167 RAD 0.00617284 + txt002 + SPHERE CENTER 0.102127 0.190718 0.713055 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0914184 0.174592 0.697727 RAD 0.00617284 + txt002 + SPHERE CENTER 0.122627 0.160649 0.690591 RAD 0.00617284 + txt002 + SPHERE CENTER 0.103081 0.167502 0.677151 RAD 0.00617284 + txt002 + SPHERE CENTER 0.125452 0.176537 0.671903 RAD 0.00617284 + txt002 + SPHERE CENTER 0.38777 0.230635 0.729516 RAD 0.0555556 + txt002 + SPHERE CENTER 0.446614 0.2506 0.769837 RAD 0.0185185 + txt002 + SPHERE CENTER 0.467193 0.264242 0.770086 RAD 0.00617284 + txt002 + SPHERE CENTER 0.459832 0.253384 0.749168 RAD 0.00617284 + txt002 + SPHERE CENTER 0.447086 0.272442 0.758332 RAD 0.00617284 + txt002 + SPHERE CENTER 0.453974 0.261459 0.790755 RAD 0.00617284 + txt002 + SPHERE CENTER 0.433868 0.269659 0.779001 RAD 0.00617284 + txt002 + SPHERE CENTER 0.433396 0.247817 0.790506 RAD 0.00617284 + txt002 + SPHERE CENTER 0.46672 0.2424 0.781591 RAD 0.00617284 + txt002 + SPHERE CENTER 0.446141 0.228758 0.781342 RAD 0.00617284 + txt002 + SPHERE CENTER 0.459359 0.231541 0.760673 RAD 0.00617284 + txt002 + SPHERE CENTER 0.449775 0.253236 0.695877 RAD 0.0185185 + txt002 + SPHERE CENTER 0.459076 0.263032 0.675209 RAD 0.00617284 + txt002 + SPHERE CENTER 0.440021 0.247378 0.673964 RAD 0.00617284 + txt002 + SPHERE CENTER 0.436804 0.270029 0.683251 RAD 0.00617284 + txt002 + SPHERE CENTER 0.468829 0.26889 0.697123 RAD 0.00617284 + txt002 + SPHERE CENTER 0.446557 0.275887 0.705165 RAD 0.00617284 + txt002 + SPHERE CENTER 0.459528 0.259094 0.717791 RAD 0.00617284 + txt002 + SPHERE CENTER 0.472047 0.246239 0.687835 RAD 0.00617284 + txt002 + SPHERE CENTER 0.462746 0.236443 0.708504 RAD 0.00617284 + txt002 + SPHERE CENTER 0.452992 0.230585 0.68659 RAD 0.00617284 + txt002 + SPHERE CENTER 0.407906 0.301839 0.732914 RAD 0.0185185 + txt002 + SPHERE CENTER 0.420236 0.319874 0.72141 RAD 0.00617284 + txt002 + SPHERE CENTER 0.428474 0.296625 0.720288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.407886 0.303021 0.708251 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399668 0.325088 0.734036 RAD 0.00617284 + txt002 + SPHERE CENTER 0.387318 0.308235 0.720878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.387338 0.307053 0.745541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.420256 0.318692 0.746073 RAD 0.00617284 + txt002 + SPHERE CENTER 0.407926 0.300656 0.757577 RAD 0.00617284 + txt002 + SPHERE CENTER 0.428494 0.295442 0.744951 RAD 0.00617284 + txt002 + SPHERE CENTER 0.384609 0.227999 0.803476 RAD 0.0185185 + txt002 + SPHERE CENTER 0.393812 0.237348 0.824394 RAD 0.00617284 + txt002 + SPHERE CENTER 0.408432 0.234368 0.804721 RAD 0.00617284 + txt002 + SPHERE CENTER 0.390976 0.251829 0.804597 RAD 0.00617284 + txt002 + SPHERE CENTER 0.369989 0.23098 0.823149 RAD 0.00617284 + txt002 + SPHERE CENTER 0.367152 0.245461 0.803352 RAD 0.00617284 + txt002 + SPHERE CENTER 0.360786 0.221631 0.802231 RAD 0.00617284 + txt002 + SPHERE CENTER 0.387445 0.213518 0.823273 RAD 0.00617284 + txt002 + SPHERE CENTER 0.378242 0.204169 0.802355 RAD 0.00617284 + txt002 + SPHERE CENTER 0.402066 0.210538 0.8036 RAD 0.00617284 + txt002 + SPHERE CENTER 0.345901 0.279238 0.766553 RAD 0.0185185 + txt002 + SPHERE CENTER 0.344931 0.302145 0.775717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.366251 0.289691 0.775841 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356827 0.297823 0.754517 RAD 0.00617284 + txt002 + SPHERE CENTER 0.324581 0.291692 0.766429 RAD 0.00617284 + txt002 + SPHERE CENTER 0.336477 0.28737 0.745229 RAD 0.00617284 + txt002 + SPHERE CENTER 0.325551 0.268785 0.757266 RAD 0.00617284 + txt002 + SPHERE CENTER 0.334005 0.28356 0.787754 RAD 0.00617284 + txt002 + SPHERE CENTER 0.334975 0.260653 0.77859 RAD 0.00617284 + txt002 + SPHERE CENTER 0.355325 0.271106 0.787878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.325765 0.208034 0.763155 RAD 0.0185185 + txt002 + SPHERE CENTER 0.312342 0.209548 0.783824 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337 0.209827 0.785069 RAD 0.00617284 + txt002 + SPHERE CENTER 0.324887 0.229235 0.775781 RAD 0.00617284 + txt002 + SPHERE CENTER 0.301107 0.207755 0.76191 RAD 0.00617284 + txt002 + SPHERE CENTER 0.313652 0.227442 0.753867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31453 0.206242 0.741241 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31322 0.188347 0.771198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.326643 0.186834 0.750529 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337878 0.188626 0.772443 RAD 0.00617284 + txt002 + SPHERE CENTER 0.426478 0.179397 0.766439 RAD 0.0185185 + txt002 + SPHERE CENTER 0.447688 0.174744 0.778193 RAD 0.00617284 + txt002 + SPHERE CENTER 0.447523 0.1895 0.758396 RAD 0.00617284 + txt002 + SPHERE CENTER 0.437457 0.197172 0.779597 RAD 0.00617284 + txt002 + SPHERE CENTER 0.426642 0.164641 0.786236 RAD 0.00617284 + txt002 + SPHERE CENTER 0.416412 0.187069 0.787639 RAD 0.00617284 + txt002 + SPHERE CENTER 0.405432 0.169293 0.774481 RAD 0.00617284 + txt002 + SPHERE CENTER 0.436708 0.156968 0.765035 RAD 0.00617284 + txt002 + SPHERE CENTER 0.415499 0.161621 0.753281 RAD 0.00617284 + txt002 + SPHERE CENTER 0.436544 0.171724 0.745238 RAD 0.00617284 + txt002 + SPHERE CENTER 0.367634 0.159431 0.726118 RAD 0.0185185 + txt002 + SPHERE CENTER 0.368692 0.13761 0.737623 RAD 0.00617284 + txt002 + SPHERE CENTER 0.387887 0.153102 0.738744 RAD 0.00617284 + txt002 + SPHERE CENTER 0.366998 0.158434 0.750781 RAD 0.00617284 + txt002 + SPHERE CENTER 0.34844 0.14394 0.724997 RAD 0.00617284 + txt002 + SPHERE CENTER 0.346745 0.164764 0.738155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.347381 0.165761 0.713492 RAD 0.00617284 + txt002 + SPHERE CENTER 0.369329 0.138607 0.71296 RAD 0.00617284 + txt002 + SPHERE CENTER 0.36827 0.160429 0.701455 RAD 0.00617284 + txt002 + SPHERE CENTER 0.388523 0.154099 0.714081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.429639 0.182032 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER 0.45215 0.177682 0.683315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.44299 0.200611 0.683192 RAD 0.00617284 + txt002 + SPHERE CENTER 0.449636 0.190087 0.704516 RAD 0.00617284 + txt002 + SPHERE CENTER 0.438799 0.159104 0.692603 RAD 0.00617284 + txt002 + SPHERE CENTER 0.436286 0.171508 0.713804 RAD 0.00617284 + txt002 + SPHERE CENTER 0.416288 0.163454 0.701767 RAD 0.00617284 + txt002 + SPHERE CENTER 0.432153 0.169628 0.671279 RAD 0.00617284 + txt002 + SPHERE CENTER 0.409641 0.173978 0.680442 RAD 0.00617284 + txt002 + SPHERE CENTER 0.422992 0.192556 0.671155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.239622 0.082487 0.655442 RAD 0.0555556 + txt002 + SPHERE CENTER 0.258053 0.0438957 0.715923 RAD 0.0185185 + txt002 + SPHERE CENTER 0.273525 0.0426858 0.735128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.281546 0.0510334 0.713318 RAD 0.00617284 + txt002 + SPHERE CENTER 0.265928 0.064638 0.726759 RAD 0.00617284 + txt002 + SPHERE CENTER 0.250032 0.0355481 0.737733 RAD 0.00617284 + txt002 + SPHERE CENTER 0.242434 0.0575003 0.729364 RAD 0.00617284 + txt002 + SPHERE CENTER 0.23456 0.036758 0.718528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.26565 0.0219434 0.724292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.250178 0.0231533 0.705088 RAD 0.00617284 + txt002 + SPHERE CENTER 0.273671 0.030291 0.702483 RAD 0.00617284 + txt002 + SPHERE CENTER 0.308551 0.0863845 0.682285 RAD 0.0185185 + txt002 + SPHERE CENTER 0.330622 0.0971427 0.67968 RAD 0.00617284 + txt002 + SPHERE CENTER 0.317013 0.091905 0.659755 RAD 0.00617284 + txt002 + SPHERE CENTER 0.310023 0.109956 0.675083 RAD 0.00617284 + txt002 + SPHERE CENTER 0.322161 0.0916222 0.702209 RAD 0.00617284 + txt002 + SPHERE CENTER 0.301561 0.104436 0.697613 RAD 0.00617284 + txt002 + SPHERE CENTER 0.30009 0.080864 0.704814 RAD 0.00617284 + txt002 + SPHERE CENTER 0.329151 0.0735708 0.686881 RAD 0.00617284 + txt002 + SPHERE CENTER 0.30708 0.0628126 0.689486 RAD 0.00617284 + txt002 + SPHERE CENTER 0.315541 0.0683331 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER 0.252557 0.117687 0.719322 RAD 0.0185185 + txt002 + SPHERE CENTER 0.265544 0.135677 0.730157 RAD 0.00617284 + txt002 + SPHERE CENTER 0.275732 0.12224 0.71212 RAD 0.00617284 + txt002 + SPHERE CENTER 0.25778 0.138361 0.706872 RAD 0.00617284 + txt002 + SPHERE CENTER 0.242369 0.131123 0.737359 RAD 0.00617284 + txt002 + SPHERE CENTER 0.234605 0.133808 0.714074 RAD 0.00617284 + txt002 + SPHERE CENTER 0.229382 0.113134 0.726523 RAD 0.00617284 + txt002 + SPHERE CENTER 0.26032 0.115003 0.742607 RAD 0.00617284 + txt002 + SPHERE CENTER 0.247334 0.097014 0.731771 RAD 0.00617284 + txt002 + SPHERE CENTER 0.270508 0.101567 0.72457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.189123 0.0399982 0.689081 RAD 0.0185185 + txt002 + SPHERE CENTER 0.179527 0.0335228 0.71089 RAD 0.00617284 + txt002 + SPHERE CENTER 0.203632 0.0385291 0.709006 RAD 0.00617284 + txt002 + SPHERE CENTER 0.187058 0.0567332 0.707118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.165018 0.0349919 0.690965 RAD 0.00617284 + txt002 + SPHERE CENTER 0.172549 0.0582023 0.687193 RAD 0.00617284 + txt002 + SPHERE CENTER 0.174615 0.0414672 0.669156 RAD 0.00617284 + txt002 + SPHERE CENTER 0.181593 0.0167878 0.692853 RAD 0.00617284 + txt002 + SPHERE CENTER 0.191189 0.0232631 0.671044 RAD 0.00617284 + txt002 + SPHERE CENTER 0.205698 0.021794 0.690969 RAD 0.00617284 + txt002 + SPHERE CENTER 0.183628 0.11379 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER 0.176775 0.133336 0.705919 RAD 0.00617284 + txt002 + SPHERE CENTER 0.199753 0.124499 0.707807 RAD 0.00617284 + txt002 + SPHERE CENTER 0.192663 0.136161 0.687231 RAD 0.00617284 + txt002 + SPHERE CENTER 0.160649 0.122627 0.690591 RAD 0.00617284 + txt002 + SPHERE CENTER 0.176537 0.125452 0.671903 RAD 0.00617284 + txt002 + SPHERE CENTER 0.167502 0.103081 0.677151 RAD 0.00617284 + txt002 + SPHERE CENTER 0.167739 0.110965 0.711167 RAD 0.00617284 + txt002 + SPHERE CENTER 0.174592 0.0914184 0.697727 RAD 0.00617284 + txt002 + SPHERE CENTER 0.190718 0.102127 0.713055 RAD 0.00617284 + txt002 + SPHERE CENTER 0.170692 0.0785895 0.6286 RAD 0.0185185 + txt002 + SPHERE CENTER 0.147549 0.0867911 0.631205 RAD 0.00617284 + txt002 + SPHERE CENTER 0.161663 0.083121 0.65113 RAD 0.00617284 + txt002 + SPHERE CENTER 0.166573 0.101845 0.635801 RAD 0.00617284 + txt002 + SPHERE CENTER 0.156579 0.0822597 0.608675 RAD 0.00617284 + txt002 + SPHERE CENTER 0.175603 0.0973138 0.613272 RAD 0.00617284 + txt002 + SPHERE CENTER 0.179722 0.074058 0.60607 RAD 0.00617284 + txt002 + SPHERE CENTER 0.151669 0.0635354 0.624003 RAD 0.00617284 + txt002 + SPHERE CENTER 0.174812 0.0553337 0.621398 RAD 0.00617284 + txt002 + SPHERE CENTER 0.165782 0.0598652 0.643928 RAD 0.00617284 + txt002 + SPHERE CENTER 0.245118 0.00869528 0.652044 RAD 0.0185185 + txt002 + SPHERE CENTER 0.257416 -0.0110117 0.660413 RAD 0.00617284 + txt002 + SPHERE CENTER 0.269325 0.0102865 0.656641 RAD 0.00617284 + txt002 + SPHERE CENTER 0.253319 0.00823377 0.675329 RAD 0.00617284 + txt002 + SPHERE CENTER 0.233209 -0.0126029 0.655816 RAD 0.00617284 + txt002 + SPHERE CENTER 0.229111 0.00664257 0.670732 RAD 0.00617284 + txt002 + SPHERE CENTER 0.22091 0.00710408 0.647447 RAD 0.00617284 + txt002 + SPHERE CENTER 0.249215 -0.0105502 0.637128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.236916 0.00915679 0.628759 RAD 0.00617284 + txt002 + SPHERE CENTER 0.261124 0.010748 0.633356 RAD 0.00617284 + txt002 + SPHERE CENTER 0.226687 0.0472866 0.591563 RAD 0.0185185 + txt002 + SPHERE CENTER 0.224935 0.025169 0.580727 RAD 0.00617284 + txt002 + SPHERE CENTER 0.241399 0.0288111 0.598764 RAD 0.00617284 + txt002 + SPHERE CENTER 0.217281 0.0281502 0.604012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.210223 0.0436445 0.573526 RAD 0.00617284 + txt002 + SPHERE CENTER 0.202569 0.0466257 0.596811 RAD 0.00617284 + txt002 + SPHERE CENTER 0.211974 0.0657621 0.584361 RAD 0.00617284 + txt002 + SPHERE CENTER 0.234341 0.0443054 0.568278 RAD 0.00617284 + txt002 + SPHERE CENTER 0.236092 0.066423 0.579113 RAD 0.00617284 + txt002 + SPHERE CENTER 0.250805 0.0479475 0.586315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.295616 0.0511841 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.315856 0.0555846 0.604965 RAD 0.00617284 + txt002 + SPHERE CENTER 0.296292 0.0705297 0.603077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.309941 0.0705987 0.623653 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31518 0.036239 0.620293 RAD 0.00617284 + txt002 + SPHERE CENTER 0.309265 0.051253 0.638981 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29494 0.0318385 0.633733 RAD 0.00617284 + txt002 + SPHERE CENTER 0.301531 0.03617 0.599717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.281291 0.0317696 0.613157 RAD 0.00617284 + txt002 + SPHERE CENTER 0.281968 0.0511152 0.597829 RAD 0.00617284 + txt002 + SPHERE CENTER 0.4293 0.115031 0.544331 RAD 0.0555556 + txt002 + SPHERE CENTER 0.502308 0.102505 0.544331 RAD 0.0185185 + txt002 + SPHERE CENTER 0.524146 0.110567 0.536101 RAD 0.00617284 + txt002 + SPHERE CENTER 0.504055 0.112687 0.521905 RAD 0.00617284 + txt002 + SPHERE CENTER 0.506465 0.126738 0.542066 RAD 0.00617284 + txt002 + SPHERE CENTER 0.522399 0.100385 0.558526 RAD 0.00617284 + txt002 + SPHERE CENTER 0.504718 0.116555 0.564491 RAD 0.00617284 + txt002 + SPHERE CENTER 0.500561 0.0923218 0.566757 RAD 0.00617284 + txt002 + SPHERE CENTER 0.519988 0.0863343 0.538366 RAD 0.00617284 + txt002 + SPHERE CENTER 0.49815 0.0782715 0.546597 RAD 0.00617284 + txt002 + SPHERE CENTER 0.499897 0.0884544 0.524171 RAD 0.00617284 + txt002 + SPHERE CENTER 0.474661 0.160392 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.481967 0.167697 0.484868 RAD 0.00617284 + txt002 + SPHERE CENTER 0.475831 0.144102 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.458371 0.161561 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.480797 0.183987 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.457202 0.177851 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.473492 0.176681 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.498257 0.166528 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.490951 0.159222 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.492121 0.142932 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.474661 0.160392 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.492047 0.177777 0.579103 RAD 0.00617284 + txt002 + SPHERE CENTER 0.490951 0.159222 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.473492 0.176681 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.475757 0.178947 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER 0.457202 0.177851 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.458371 0.161561 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.493217 0.161488 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER 0.475831 0.144102 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.492121 0.142932 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.456947 0.0571437 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.475575 0.0493251 0.595564 RAD 0.00617284 + txt002 + SPHERE CENTER 0.479825 0.06557 0.577461 RAD 0.00617284 + txt002 + SPHERE CENTER 0.467381 0.0725262 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER 0.452697 0.0408988 0.599471 RAD 0.00617284 + txt002 + SPHERE CENTER 0.444504 0.0640999 0.601529 RAD 0.00617284 + txt002 + SPHERE CENTER 0.434069 0.0487174 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER 0.465141 0.0339426 0.57931 RAD 0.00617284 + txt002 + SPHERE CENTER 0.446512 0.0417612 0.565115 RAD 0.00617284 + txt002 + SPHERE CENTER 0.46939 0.0501875 0.561208 RAD 0.00617284 + txt002 + SPHERE CENTER 0.4293 0.115031 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.439381 0.125111 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.45315 0.121421 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.435691 0.138881 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.415531 0.11872 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.411841 0.13249 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.40545 0.10864 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.43299 0.101261 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.42291 0.0911807 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.44676 0.0975713 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.383939 0.0696698 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.376634 0.0623642 0.603794 RAD 0.00617284 + txt002 + SPHERE CENTER 0.400229 0.0685002 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.38277 0.0859596 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.360344 0.0635337 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER 0.36648 0.0871292 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.36765 0.0708393 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.377803 0.0460743 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER 0.385109 0.0533799 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.401399 0.0522103 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.456947 0.0571437 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.477623 0.0450372 0.501329 RAD 0.00617284 + txt002 + SPHERE CENTER 0.47788 0.0696413 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.475469 0.055591 0.523547 RAD 0.00617284 + txt002 + SPHERE CENTER 0.45669 0.0325396 0.505236 RAD 0.00617284 + txt002 + SPHERE CENTER 0.454536 0.0430934 0.527454 RAD 0.00617284 + txt002 + SPHERE CENTER 0.436013 0.0446461 0.511201 RAD 0.00617284 + txt002 + SPHERE CENTER 0.4591 0.0465898 0.485076 RAD 0.00617284 + txt002 + SPHERE CENTER 0.438424 0.0586963 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER 0.459357 0.071194 0.487134 RAD 0.00617284 + txt002 + SPHERE CENTER 0.383939 0.0696698 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.366554 0.052284 0.509559 RAD 0.00617284 + txt002 + SPHERE CENTER 0.385109 0.0533799 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.36765 0.0708393 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.365384 0.0685739 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER 0.36648 0.0871292 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.38277 0.0859596 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.382844 0.0511144 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER 0.400229 0.0685002 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.401399 0.0522103 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.4293 0.115031 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER 0.41922 0.125111 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER 0.40545 0.121421 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.42291 0.138881 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.44307 0.11872 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER 0.44676 0.13249 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.45315 0.10864 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.425611 0.101261 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER 0.435691 0.0911807 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.411841 0.0975713 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.643951 0.172546 1.11022e-16 RAD 0.166667 + txt002 + SPHERE CENTER 0.802608 0.281471 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.824035 0.30566 -0.177765 RAD 0.0185185 + txt002 + SPHERE CENTER 0.822021 0.302088 -0.202114 RAD 0.00617284 + txt002 + SPHERE CENTER 0.821938 0.282758 -0.186751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.802598 0.298094 -0.187402 RAD 0.00617284 + txt002 + SPHERE CENTER 0.824119 0.32499 -0.193128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.804695 0.320997 -0.178416 RAD 0.00617284 + txt002 + SPHERE CENTER 0.826132 0.328563 -0.16878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.843459 0.309654 -0.192477 RAD 0.00617284 + txt002 + SPHERE CENTER 0.845472 0.313227 -0.168128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.843375 0.290324 -0.177114 RAD 0.00617284 + txt002 + SPHERE CENTER 0.787796 0.241352 -0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER 0.785699 0.218449 -0.180578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.802677 0.22345 -0.163362 RAD 0.00617284 + txt002 + SPHERE CENTER 0.778718 0.223304 -0.157397 RAD 0.00617284 + txt002 + SPHERE CENTER 0.770818 0.236351 -0.188808 RAD 0.00617284 + txt002 + SPHERE CENTER 0.763837 0.241205 -0.165627 RAD 0.00617284 + txt002 + SPHERE CENTER 0.772915 0.259253 -0.179823 RAD 0.00617284 + txt002 + SPHERE CENTER 0.794777 0.236497 -0.194773 RAD 0.00617284 + txt002 + SPHERE CENTER 0.796874 0.2594 -0.185788 RAD 0.00617284 + txt002 + SPHERE CENTER 0.811756 0.241498 -0.177557 RAD 0.00617284 + txt002 + SPHERE CENTER 0.752156 0.305221 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.741263 0.325175 -0.169507 RAD 0.00617284 + txt002 + SPHERE CENTER 0.747715 0.32493 -0.145675 RAD 0.00617284 + txt002 + SPHERE CENTER 0.765112 0.325981 -0.163165 RAD 0.00617284 + txt002 + SPHERE CENTER 0.745704 0.305466 -0.183703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.769553 0.306272 -0.17736 RAD 0.00617284 + txt002 + SPHERE CENTER 0.756597 0.285513 -0.174066 RAD 0.00617284 + txt002 + SPHERE CENTER 0.728307 0.304415 -0.166213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.7392 0.284462 -0.156576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.734759 0.304171 -0.142381 RAD 0.00617284 + txt002 + SPHERE CENTER 0.838847 0.34578 -0.117284 RAD 0.0185185 + txt002 + SPHERE CENTER 0.851488 0.360404 -0.132647 RAD 0.00617284 + txt002 + SPHERE CENTER 0.853509 0.335865 -0.1345 RAD 0.00617284 + txt002 + SPHERE CENTER 0.832518 0.347059 -0.141116 RAD 0.00617284 + txt002 + SPHERE CENTER 0.836826 0.370319 -0.115431 RAD 0.00617284 + txt002 + SPHERE CENTER 0.817857 0.356973 -0.1239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.824185 0.355695 -0.100068 RAD 0.00617284 + txt002 + SPHERE CENTER 0.857816 0.359125 -0.108814 RAD 0.00617284 + txt002 + SPHERE CENTER 0.845176 0.344501 -0.0934517 RAD 0.00617284 + txt002 + SPHERE CENTER 0.859838 0.334587 -0.110668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.766968 0.345341 -0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.768944 0.369945 -0.10004 RAD 0.00617284 + txt002 + SPHERE CENTER 0.788341 0.356172 -0.093424 RAD 0.00617284 + txt002 + SPHERE CENTER 0.780624 0.356171 -0.116879 RAD 0.00617284 + txt002 + SPHERE CENTER 0.747572 0.359113 -0.106005 RAD 0.00617284 + txt002 + SPHERE CENTER 0.759252 0.34534 -0.122844 RAD 0.00617284 + txt002 + SPHERE CENTER 0.745596 0.33451 -0.105354 RAD 0.00617284 + txt002 + SPHERE CENTER 0.755289 0.359115 -0.0825505 RAD 0.00617284 + txt002 + SPHERE CENTER 0.753313 0.334511 -0.0818993 RAD 0.00617284 + txt002 + SPHERE CENTER 0.774685 0.345342 -0.0759343 RAD 0.00617284 + txt002 + SPHERE CENTER 0.817421 0.321591 -0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER 0.83071 0.340361 -0.0416443 RAD 0.00617284 + txt002 + SPHERE CENTER 0.840365 0.325527 -0.0588603 RAD 0.00617284 + txt002 + SPHERE CENTER 0.822249 0.341208 -0.0648253 RAD 0.00617284 + txt002 + SPHERE CENTER 0.807766 0.336425 -0.0334138 RAD 0.00617284 + txt002 + SPHERE CENTER 0.799305 0.337272 -0.0565949 RAD 0.00617284 + txt002 + SPHERE CENTER 0.794477 0.317654 -0.0423994 RAD 0.00617284 + txt002 + SPHERE CENTER 0.825882 0.320744 -0.0274488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.812593 0.301973 -0.0364345 RAD 0.00617284 + txt002 + SPHERE CENTER 0.835537 0.30591 -0.0446649 RAD 0.00617284 + txt002 + SPHERE CENTER 0.874487 0.28191 -0.129006 RAD 0.0185185 + txt002 + SPHERE CENTER 0.891539 0.292033 -0.143718 RAD 0.00617284 + txt002 + SPHERE CENTER 0.868678 0.28812 -0.152187 RAD 0.00617284 + txt002 + SPHERE CENTER 0.872763 0.305711 -0.135349 RAD 0.00617284 + txt002 + SPHERE CENTER 0.897348 0.285824 -0.120537 RAD 0.00617284 + txt002 + SPHERE CENTER 0.878572 0.299501 -0.112168 RAD 0.00617284 + txt002 + SPHERE CENTER 0.880296 0.275701 -0.105825 RAD 0.00617284 + txt002 + SPHERE CENTER 0.893263 0.268233 -0.137375 RAD 0.00617284 + txt002 + SPHERE CENTER 0.876212 0.25811 -0.122663 RAD 0.00617284 + txt002 + SPHERE CENTER 0.870402 0.264319 -0.145845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.853061 0.257721 -0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER 0.87538 0.26204 -0.0527151 RAD 0.00617284 + txt002 + SPHERE CENTER 0.87108 0.266856 -0.0765474 RAD 0.00617284 + txt002 + SPHERE CENTER 0.860805 0.280934 -0.0590577 RAD 0.00617284 + txt002 + SPHERE CENTER 0.857361 0.252905 -0.0385197 RAD 0.00617284 + txt002 + SPHERE CENTER 0.842785 0.271799 -0.0448623 RAD 0.00617284 + txt002 + SPHERE CENTER 0.835041 0.248586 -0.0481565 RAD 0.00617284 + txt002 + SPHERE CENTER 0.867636 0.238827 -0.0560094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.845317 0.234508 -0.0656463 RAD 0.00617284 + txt002 + SPHERE CENTER 0.863337 0.243643 -0.0798417 RAD 0.00617284 + txt002 + SPHERE CENTER 0.838248 0.217602 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.860225 0.206363 -0.122182 RAD 0.00617284 + txt002 + SPHERE CENTER 0.858689 0.230102 -0.128798 RAD 0.00617284 + txt002 + SPHERE CENTER 0.854636 0.223536 -0.105343 RAD 0.00617284 + txt002 + SPHERE CENTER 0.839784 0.193863 -0.116217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.834196 0.211035 -0.0993785 RAD 0.00617284 + txt002 + SPHERE CENTER 0.817808 0.205101 -0.116868 RAD 0.00617284 + txt002 + SPHERE CENTER 0.843837 0.200429 -0.139672 RAD 0.00617284 + txt002 + SPHERE CENTER 0.821861 0.211667 -0.140323 RAD 0.00617284 + txt002 + SPHERE CENTER 0.842301 0.224168 -0.146288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.643951 0.172546 -0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER 0.61371 0.202787 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.61556 0.221097 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.621702 0.225035 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.635958 0.210779 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.607567 0.198849 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.627965 0.188531 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER 0.605717 0.180539 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.593312 0.213105 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER 0.591462 0.194794 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.599454 0.217042 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER 0.5724 0.191718 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.556122 0.208861 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.575596 0.203643 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.578791 0.215568 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.552927 0.196936 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER 0.575596 0.203643 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.569205 0.179793 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.549732 0.185011 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.56601 0.167868 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.569205 0.179793 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.624779 0.244096 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.631486 0.266765 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.648629 0.250487 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.636704 0.247291 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.607636 0.260374 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.612854 0.240901 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.600929 0.237705 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.619561 0.26357 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.612854 0.240901 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.636704 0.247291 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.68526 0.183615 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.684921 0.190903 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.665787 0.178397 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669989 0.201661 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.704395 0.196121 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER 0.689462 0.206879 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.704733 0.188833 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER 0.700193 0.172858 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.700531 0.165569 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.681058 0.160351 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.696329 0.224924 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.710584 0.23918 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER 0.705059 0.216195 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.687599 0.233654 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.701855 0.24791 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.678869 0.242384 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.687599 0.233654 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.719314 0.23045 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.705059 0.216195 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.713788 0.207465 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.715501 0.153374 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.738169 0.160081 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.718696 0.165299 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.721891 0.177224 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.734974 0.148156 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.718696 0.165299 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.712305 0.141449 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.731779 0.136231 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.70911 0.129524 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.712305 0.141449 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.632882 0.131237 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.634145 0.108412 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER 0.650927 0.115965 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.627664 0.111763 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER 0.616099 0.123683 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.609618 0.127034 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.614836 0.146508 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.639363 0.127886 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.6381 0.15071 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER 0.656145 0.135439 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.663122 0.100996 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.680265 0.0847178 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.686972 0.107387 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.675047 0.104191 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.656415 0.0783272 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.651197 0.0978007 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.639272 0.0946054 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.66834 0.0815225 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER 0.651197 0.0978007 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.675047 0.104191 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.591572 0.120168 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.577317 0.105912 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.600302 0.111438 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.582843 0.128897 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.568587 0.114642 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.574113 0.137627 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.582843 0.128897 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.586046 0.0971825 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.600302 0.111438 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.609032 0.102708 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.594141 0.358439 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.619127 0.408291 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.625955 0.411883 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.630791 0.390369 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.607547 0.396287 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.61429 0.429805 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.595882 0.414208 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.607462 0.426212 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.637535 0.423887 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.630706 0.420295 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.642371 0.402373 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.665691 0.37761 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.68332 0.389713 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.665691 0.37761 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.660156 0.398265 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.68332 0.389713 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.660156 0.398265 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.665691 0.37761 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.688854 0.369058 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.671225 0.356956 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.671225 0.356956 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.638217 0.337042 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.652948 0.344865 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.632683 0.357697 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.651954 0.357326 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.658482 0.324211 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.657489 0.336672 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.643752 0.316388 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.639211 0.324581 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.624481 0.316758 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.618946 0.337413 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.547576 0.389119 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.541008 0.410169 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.548718 0.410472 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.564748 0.405866 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539866 0.388816 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.563607 0.384513 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.546435 0.367766 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.523836 0.393422 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.530405 0.372372 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.531546 0.393725 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.566667 0.317871 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.555534 0.296626 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.572202 0.297216 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.550163 0.307914 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.549999 0.31728 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.544629 0.328569 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.561133 0.338525 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.572037 0.306582 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.583171 0.327827 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.588706 0.307172 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.522591 0.339267 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.501272 0.340934 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.522591 0.339267 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.517056 0.359921 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.501272 0.340934 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.517056 0.359921 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.522591 0.339267 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.506807 0.320279 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.528125 0.318612 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.528125 0.318612 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.57505 0.429687 -0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER 0.58161 0.452905 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.5989 0.436077 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.586467 0.434777 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.55776 0.446515 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.562617 0.428387 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.5512 0.423296 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.570193 0.447815 -0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER 0.563633 0.424596 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.587483 0.430987 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.550064 0.379835 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.547099 0.396248 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.569716 0.388263 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.557504 0.403175 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.527447 0.387819 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.537852 0.394747 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.530412 0.371406 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539659 0.372907 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.542624 0.356494 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.562276 0.364922 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.621614 0.399007 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.637209 0.41723 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.642848 0.401533 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.624734 0.418027 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.615976 0.414703 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.603501 0.4155 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.600381 0.39648 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.634089 0.39821 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.618494 0.379986 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.639728 0.382513 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.802608 0.281471 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.858698 0.329459 0.104938 RAD 0.0185185 + txt002 + SPHERE CENTER 0.872345 0.34259 0.0890951 RAD 0.00617284 + txt002 + SPHERE CENTER 0.86421 0.32016 0.0827387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.848329 0.338969 0.0846485 RAD 0.00617284 + txt002 + SPHERE CENTER 0.866833 0.351888 0.111295 RAD 0.00617284 + txt002 + SPHERE CENTER 0.842817 0.348268 0.106848 RAD 0.00617284 + txt002 + SPHERE CENTER 0.853186 0.338757 0.127138 RAD 0.00617284 + txt002 + SPHERE CENTER 0.882715 0.333079 0.109385 RAD 0.00617284 + txt002 + SPHERE CENTER 0.869068 0.319948 0.125228 RAD 0.00617284 + txt002 + SPHERE CENTER 0.87458 0.310649 0.103028 RAD 0.00617284 + txt002 + SPHERE CENTER 0.845371 0.280879 0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER 0.849036 0.291048 0.0284303 RAD 0.00617284 + txt002 + SPHERE CENTER 0.826067 0.287867 0.0369125 RAD 0.00617284 + txt002 + SPHERE CENTER 0.840755 0.304882 0.0471312 RAD 0.00617284 + txt002 + SPHERE CENTER 0.868341 0.28406 0.0421477 RAD 0.00617284 + txt002 + SPHERE CENTER 0.86006 0.297894 0.0608487 RAD 0.00617284 + txt002 + SPHERE CENTER 0.864676 0.273891 0.0643473 RAD 0.00617284 + txt002 + SPHERE CENTER 0.853652 0.267046 0.0319289 RAD 0.00617284 + txt002 + SPHERE CENTER 0.849987 0.256877 0.0541285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.830683 0.263865 0.0404111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.798572 0.337088 0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER 0.808673 0.346884 0.0420622 RAD 0.00617284 + txt002 + SPHERE CENTER 0.82298 0.335792 0.0588533 RAD 0.00617284 + txt002 + SPHERE CENTER 0.807762 0.322361 0.044793 RAD 0.00617284 + txt002 + SPHERE CENTER 0.784265 0.34818 0.0455609 RAD 0.00617284 + txt002 + SPHERE CENTER 0.783355 0.323657 0.0482916 RAD 0.00617284 + txt002 + SPHERE CENTER 0.774164 0.338384 0.0658506 RAD 0.00617284 + txt002 + SPHERE CENTER 0.799483 0.361611 0.0596212 RAD 0.00617284 + txt002 + SPHERE CENTER 0.789382 0.351815 0.079911 RAD 0.00617284 + txt002 + SPHERE CENTER 0.81379 0.350519 0.0764123 RAD 0.00617284 + txt002 + SPHERE CENTER 0.815936 0.330051 0.165419 RAD 0.0185185 + txt002 + SPHERE CENTER 0.828769 0.350165 0.171776 RAD 0.00617284 + txt002 + SPHERE CENTER 0.838905 0.333232 0.156937 RAD 0.00617284 + txt002 + SPHERE CENTER 0.820583 0.347547 0.148628 RAD 0.00617284 + txt002 + SPHERE CENTER 0.805799 0.346984 0.180258 RAD 0.00617284 + txt002 + SPHERE CENTER 0.797614 0.344366 0.157111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.792966 0.32687 0.173902 RAD 0.00617284 + txt002 + SPHERE CENTER 0.824121 0.332668 0.188567 RAD 0.00617284 + txt002 + SPHERE CENTER 0.811288 0.312554 0.182211 RAD 0.00617284 + txt002 + SPHERE CENTER 0.834258 0.315735 0.173728 RAD 0.00617284 + txt002 + SPHERE CENTER 0.75581 0.33768 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.753851 0.362219 0.124743 RAD 0.00617284 + txt002 + SPHERE CENTER 0.774086 0.350765 0.133052 RAD 0.00617284 + txt002 + SPHERE CENTER 0.76987 0.352319 0.108773 RAD 0.00617284 + txt002 + SPHERE CENTER 0.735575 0.349134 0.114524 RAD 0.00617284 + txt002 + SPHERE CENTER 0.751594 0.339233 0.0985541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.737534 0.324595 0.112614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.739791 0.347581 0.138803 RAD 0.00617284 + txt002 + SPHERE CENTER 0.74175 0.323042 0.136894 RAD 0.00617284 + txt002 + SPHERE CENTER 0.760026 0.336127 0.147112 RAD 0.00617284 + txt002 + SPHERE CENTER 0.759846 0.282063 0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER 0.756464 0.29233 0.193792 RAD 0.00617284 + txt002 + SPHERE CENTER 0.779336 0.288514 0.18531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.765125 0.305929 0.175091 RAD 0.00617284 + txt002 + SPHERE CENTER 0.736973 0.285879 0.180075 RAD 0.00617284 + txt002 + SPHERE CENTER 0.745634 0.299478 0.161374 RAD 0.00617284 + txt002 + SPHERE CENTER 0.740355 0.275612 0.157875 RAD 0.00617284 + txt002 + SPHERE CENTER 0.751185 0.268464 0.190293 RAD 0.00617284 + txt002 + SPHERE CENTER 0.754567 0.258198 0.168094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.774058 0.264649 0.181811 RAD 0.00617284 + txt002 + SPHERE CENTER 0.862735 0.273842 0.153697 RAD 0.0185185 + txt002 + SPHERE CENTER 0.885497 0.282313 0.158144 RAD 0.00617284 + txt002 + SPHERE CENTER 0.876946 0.281455 0.134996 RAD 0.00617284 + txt002 + SPHERE CENTER 0.867718 0.29787 0.150967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.871286 0.274699 0.176845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.853506 0.290257 0.169668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.848523 0.266228 0.172398 RAD 0.00617284 + txt002 + SPHERE CENTER 0.880514 0.258284 0.160875 RAD 0.00617284 + txt002 + SPHERE CENTER 0.857752 0.249813 0.156428 RAD 0.00617284 + txt002 + SPHERE CENTER 0.871963 0.257427 0.137727 RAD 0.00617284 + txt002 + SPHERE CENTER 0.806645 0.225855 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.818054 0.21762 0.18016 RAD 0.00617284 + txt002 + SPHERE CENTER 0.83061 0.230661 0.163369 RAD 0.00617284 + txt002 + SPHERE CENTER 0.813612 0.241754 0.177429 RAD 0.00617284 + txt002 + SPHERE CENTER 0.794089 0.212813 0.176661 RAD 0.00617284 + txt002 + SPHERE CENTER 0.789647 0.236948 0.173931 RAD 0.00617284 + txt002 + SPHERE CENTER 0.78268 0.221048 0.156372 RAD 0.00617284 + txt002 + SPHERE CENTER 0.811087 0.20172 0.162601 RAD 0.00617284 + txt002 + SPHERE CENTER 0.799677 0.209955 0.142311 RAD 0.00617284 + txt002 + SPHERE CENTER 0.823642 0.214761 0.14581 RAD 0.00617284 + txt002 + SPHERE CENTER 0.849407 0.225263 0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.873186 0.21889 0.0974792 RAD 0.00617284 + txt002 + SPHERE CENTER 0.865588 0.240865 0.0891702 RAD 0.00617284 + txt002 + SPHERE CENTER 0.866351 0.236437 0.113449 RAD 0.00617284 + txt002 + SPHERE CENTER 0.857005 0.203288 0.107698 RAD 0.00617284 + txt002 + SPHERE CENTER 0.850171 0.220835 0.123668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.833227 0.20966 0.109608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.856242 0.207715 0.0834188 RAD 0.00617284 + txt002 + SPHERE CENTER 0.832464 0.214088 0.0853287 RAD 0.00617284 + txt002 + SPHERE CENTER 0.848644 0.22969 0.0751099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.594141 0.358439 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.613592 0.428945 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.626191 0.448155 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.634643 0.42519 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.614455 0.43276 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.60514 0.45191 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.593404 0.436515 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.592541 0.4327 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.625328 0.44434 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.612729 0.42513 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.63378 0.421375 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.665691 0.37761 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.68332 0.389713 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.665691 0.37761 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.660156 0.398265 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.68332 0.389713 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.660156 0.398265 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.665691 0.37761 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.688854 0.369058 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.671225 0.356956 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.671225 0.356956 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.621614 0.399007 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.625435 0.399844 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.627149 0.378352 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.60511 0.38905 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.619901 0.420499 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.599576 0.409705 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.61608 0.419661 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.641939 0.409801 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.638118 0.408963 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.643653 0.388308 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.542042 0.409774 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.53788 0.433888 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.558395 0.423551 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.55574 0.426423 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.521526 0.42011 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539387 0.412646 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.525689 0.395996 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.524182 0.417238 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.528344 0.393124 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.544697 0.406901 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.550064 0.379835 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.540802 0.399304 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.54453 0.400489 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.563801 0.400119 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.546337 0.37865 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.569335 0.379464 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.555599 0.35918 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.527065 0.37902 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.536327 0.359551 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.530793 0.380205 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.522591 0.339267 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.501272 0.340934 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.522591 0.339267 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.517056 0.359921 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.501272 0.340934 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.517056 0.359921 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.522591 0.339267 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.506807 0.320279 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.528125 0.318612 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.528125 0.318612 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.586119 0.388377 0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.594185 0.405974 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.609969 0.394768 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.593017 0.410332 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.570335 0.399584 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.569167 0.403942 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.562269 0.381987 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.587286 0.384019 0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.57922 0.366422 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.60307 0.372813 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.566667 0.317871 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.567308 0.314012 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.587901 0.320398 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.569787 0.336891 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.546074 0.311485 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.548554 0.334364 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.545434 0.315344 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.564188 0.294991 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.563547 0.29885 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.584781 0.301377 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.638217 0.337042 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.659244 0.341809 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.65787 0.345471 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.645657 0.360383 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.639592 0.33338 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.626005 0.351955 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.618565 0.328614 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.651804 0.318468 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.630777 0.313702 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.65043 0.32213 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.643951 0.172546 0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER 0.674191 0.202787 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.690652 0.219248 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER 0.695267 0.206403 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.677807 0.223862 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669577 0.215632 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.656732 0.220246 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.653116 0.199171 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.687036 0.198172 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.670575 0.181711 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.691651 0.185327 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.715501 0.191718 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.733129 0.203821 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.715501 0.191718 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.709966 0.212373 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.733129 0.203821 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.709966 0.212373 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.715501 0.191718 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.738664 0.183166 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.721035 0.171063 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.721035 0.171063 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.663122 0.244096 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.675225 0.261725 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.683777 0.238562 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.663122 0.244096 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.65457 0.267259 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.642468 0.249631 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.642468 0.249631 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.675225 0.261725 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.663122 0.244096 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.683777 0.238562 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.602641 0.183615 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.600215 0.197046 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.622701 0.191021 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.609032 0.207465 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.580155 0.18964 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER 0.588972 0.200059 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.582581 0.176209 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.593824 0.173196 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.596251 0.159765 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.61631 0.167171 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.591572 0.224924 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.587397 0.24926 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.606693 0.240045 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.606693 0.240045 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.572277 0.23414 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.591572 0.224924 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.576452 0.209804 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.572277 0.23414 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.576452 0.209804 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.591572 0.224924 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.5724 0.153374 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.551082 0.155041 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.5724 0.153374 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.566866 0.174029 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.551082 0.155041 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.566866 0.174029 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.5724 0.153374 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.556617 0.134387 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.577935 0.13272 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.577935 0.13272 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.655019 0.131237 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.668451 0.12881 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.678869 0.137627 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.662426 0.151296 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.644601 0.12242 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.638576 0.144906 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.631169 0.124846 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.661044 0.108751 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER 0.647613 0.111177 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.671463 0.117567 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.624779 0.100996 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.626446 0.0796777 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.645433 0.0954616 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.624779 0.100996 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.605791 0.0852121 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.604124 0.10653 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.604124 0.10653 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.626446 0.0796777 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.624779 0.100996 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.645433 0.0954616 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.696329 0.120168 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.720665 0.115992 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.711449 0.135288 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.711449 0.135288 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.705544 0.100872 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.696329 0.120168 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.681209 0.105047 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.705544 0.100872 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.681209 0.105047 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.696329 0.120168 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.852418 0.0955788 1.89979e-16 RAD 0.0555556 + txt002 + SPHERE CENTER 0.922609 0.11107 -0.0178949 RAD 0.0185185 + txt002 + SPHERE CENTER 0.937225 0.122151 -0.0344251 RAD 0.00617284 + txt002 + SPHERE CENTER 0.916553 0.11086 -0.0418311 RAD 0.00617284 + txt002 + SPHERE CENTER 0.915202 0.131874 -0.0289382 RAD 0.00617284 + txt002 + SPHERE CENTER 0.943281 0.12236 -0.0104889 RAD 0.00617284 + txt002 + SPHERE CENTER 0.921258 0.132084 -0.00500196 RAD 0.00617284 + txt002 + SPHERE CENTER 0.928665 0.111279 0.00604126 RAD 0.00617284 + txt002 + SPHERE CENTER 0.944632 0.101346 -0.0233819 RAD 0.00617284 + txt002 + SPHERE CENTER 0.930016 0.0902645 -0.00685171 RAD 0.00617284 + txt002 + SPHERE CENTER 0.92396 0.090055 -0.0307879 RAD 0.00617284 + txt002 + SPHERE CENTER 0.867231 0.135698 -0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER 0.873196 0.134634 -0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER 0.882112 0.117797 -0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER 0.858152 0.11765 -0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER 0.858315 0.152536 -0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER 0.843271 0.135552 -0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.852349 0.1536 -0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER 0.882275 0.152682 -0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.876309 0.153747 -0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER 0.89119 0.135845 -0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER 0.877966 0.164775 0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER 0.890926 0.182656 -0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER 0.897331 0.159019 -0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER 0.876622 0.167676 -0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER 0.871561 0.188412 0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER 0.857256 0.173431 -0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.8586 0.17053 0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER 0.89227 0.179755 0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER 0.87931 0.161874 0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.898675 0.156118 0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.907797 0.0709499 0.0425863 RAD 0.0185185 + txt002 + SPHERE CENTER 0.930963 0.0752104 0.0499923 RAD 0.00617284 + txt002 + SPHERE CENTER 0.924191 0.0806562 0.0268805 RAD 0.00617284 + txt002 + SPHERE CENTER 0.915684 0.0941344 0.0457385 RAD 0.00617284 + txt002 + SPHERE CENTER 0.914568 0.0655041 0.065698 RAD 0.00617284 + txt002 + SPHERE CENTER 0.899289 0.0844281 0.0614442 RAD 0.00617284 + txt002 + SPHERE CENTER 0.891402 0.0612436 0.058292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.923076 0.0520258 0.0468401 RAD 0.00617284 + txt002 + SPHERE CENTER 0.89991 0.0477654 0.0394341 RAD 0.00617284 + txt002 + SPHERE CENTER 0.916304 0.0574717 0.0237283 RAD 0.00617284 + txt002 + SPHERE CENTER 0.863153 0.124655 0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER 0.875744 0.141535 0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER 0.88655 0.129819 0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.868763 0.146389 0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER 0.852347 0.136371 0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER 0.845366 0.141225 0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER 0.839756 0.119492 0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER 0.870135 0.119801 0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER 0.857544 0.102922 0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER 0.880941 0.108085 0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER 0.837606 0.0554592 0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER 0.842832 0.0523913 0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER 0.86055 0.0593957 0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER 0.842434 0.0750766 0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER 0.819888 0.0484547 0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER 0.81949 0.07114 0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.814662 0.0515226 0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER 0.838004 0.0327739 0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.832778 0.0358417 0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER 0.855722 0.0397783 0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER 0.897062 0.0418734 -0.0246914 RAD 0.0185185 + txt002 + SPHERE CENTER 0.920407 0.0359958 -0.0301783 RAD 0.00617284 + txt002 + SPHERE CENTER 0.912106 0.0588574 -0.0344321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.915603 0.0511067 -0.0112511 RAD 0.00617284 + txt002 + SPHERE CENTER 0.905363 0.0190117 -0.0204376 RAD 0.00617284 + txt002 + SPHERE CENTER 0.900559 0.0341227 -0.00151032 RAD 0.00617284 + txt002 + SPHERE CENTER 0.882018 0.0248894 -0.0149506 RAD 0.00617284 + txt002 + SPHERE CENTER 0.901866 0.0267625 -0.0436186 RAD 0.00617284 + txt002 + SPHERE CENTER 0.878521 0.0326401 -0.0381316 RAD 0.00617284 + txt002 + SPHERE CENTER 0.893565 0.0496241 -0.0478724 RAD 0.00617284 + txt002 + SPHERE CENTER 0.826871 0.0263827 -0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER 0.825102 0.00436945 0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER 0.84533 0.018173 0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER 0.823964 0.025051 0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER 0.806642 0.0125791 -0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER 0.805505 0.0332607 0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.808411 0.0345923 -0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER 0.828008 0.00570109 -0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER 0.829777 0.0277143 -0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.848237 0.0195047 -0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.841683 0.0665023 -0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER 0.840284 0.0454909 -0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER 0.856111 0.0473735 -0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.831823 0.0463379 -0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER 0.825856 0.0646197 -0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER 0.817395 0.0654667 -0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER 0.827255 0.0856311 -0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER 0.850144 0.0656554 -0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER 0.851543 0.0866667 -0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER 0.865971 0.0675379 -0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER 0.69376 -0.0133465 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.740325 -0.0440268 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.762259 -0.0417568 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.759495 -0.0345526 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.748937 -0.0216407 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.743089 -0.051231 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.729767 -0.0311149 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.721155 -0.053501 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.753646 -0.0641429 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.731712 -0.0664129 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.750882 -0.0569387 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.76531 0.0058253 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.782939 0.0179281 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.76531 0.0058253 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.759776 0.02648 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.782939 0.0179281 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.759776 0.02648 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.76531 0.0058253 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.788473 -0.00272662 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.770845 -0.0148294 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.770845 -0.0148294 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.721234 0.0272215 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.736829 0.0454452 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.742467 0.0297485 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.724354 0.046242 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.715595 0.0429182 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.70312 0.043715 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.7 0.0246945 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.733709 0.0264247 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.718114 0.00820099 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.739347 0.010728 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.668775 -0.0631985 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.669983 -0.0708196 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.690113 -0.0618185 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.671462 -0.0467378 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.648644 -0.0721997 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.650123 -0.0481178 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.647436 -0.0645786 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.667296 -0.0872804 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.666087 -0.0796593 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.687426 -0.0782793 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.649684 0.00804971 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.646718 0.0244627 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669336 0.016478 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.657124 0.0313903 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.627066 0.0160343 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.637471 0.022962 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.630031 -0.000378614 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.639278 0.00112207 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.642244 -0.0152909 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.661896 -0.00686255 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.62221 -0.0325183 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.600892 -0.0308513 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.62221 -0.0325183 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.616676 -0.0118635 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.600892 -0.0308513 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.616676 -0.0118635 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.62221 -0.0325183 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.606426 -0.051506 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.627745 -0.053173 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.627745 -0.053173 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.712851 -0.0845947 0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER 0.730141 -0.101422 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.736701 -0.0782041 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.725284 -0.0832945 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.706291 -0.107813 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.701434 -0.0896851 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.689001 -0.0909853 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.717709 -0.102723 0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER 0.700418 -0.0858949 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.724268 -0.0795043 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.666287 -0.0539145 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.655153 -0.0751594 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.671821 -0.0745692 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.649783 -0.0638711 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.649619 -0.0545047 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.644249 -0.0432164 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.660752 -0.0332597 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.671657 -0.0652028 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.682791 -0.0439578 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.688325 -0.0646126 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.737837 -0.0347427 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.752567 -0.0269197 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.732303 -0.014088 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.751574 -0.0144587 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.758102 -0.0475745 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.757108 -0.0351134 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.743371 -0.0553974 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.73883 -0.0472037 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.7241 -0.0550267 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.718566 -0.0343719 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.69376 -0.0133465 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.745859 -0.0646815 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.770032 -0.0684873 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.759394 -0.0481266 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.762305 -0.0507391 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.756497 -0.0850422 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.74877 -0.067294 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.732325 -0.0812364 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.753586 -0.0824297 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.729413 -0.0786239 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.742948 -0.062069 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.76531 0.0058253 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.782939 0.0179281 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.76531 0.0058253 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.759776 0.02648 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.782939 0.0179281 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.759776 0.02648 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.76531 0.0058253 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.788473 -0.00272662 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.770845 -0.0148294 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.770845 -0.0148294 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.737837 -0.0347427 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.758864 -0.0299763 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.757489 -0.0263144 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.745277 -0.0114021 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.739212 -0.0384047 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.725625 -0.0198304 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.718185 -0.043171 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.751424 -0.0533169 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.730397 -0.0580833 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.750049 -0.0496549 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.674309 -0.0838533 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.675276 -0.106805 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.694308 -0.091423 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.673094 -0.0875713 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.655278 -0.0992356 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.653095 -0.0800016 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.65431 -0.0762835 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.676491 -0.103087 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.675524 -0.0801352 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.695522 -0.0877049 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.666287 -0.0539145 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.666927 -0.0577732 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.68752 -0.0513875 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669407 -0.034894 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.645694 -0.0603001 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.648173 -0.0374209 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.645053 -0.0564414 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.663807 -0.0767937 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.663167 -0.072935 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.6844 -0.070408 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.62221 -0.0325183 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.600892 -0.0308513 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.62221 -0.0325183 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.616676 -0.0118635 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.600892 -0.0308513 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.616676 -0.0118635 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.62221 -0.0325183 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.606426 -0.051506 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.627745 -0.053173 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.627745 -0.053173 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.701782 -0.0432853 -0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.717566 -0.0544915 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.725632 -0.0368947 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.718734 -0.0588496 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.693716 -0.0608821 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.694884 -0.0652402 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.677932 -0.0496759 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.700615 -0.0389272 -0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.684831 -0.027721 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.708681 -0.0213304 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.649684 0.00804971 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.640422 0.0275193 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.644149 0.0287044 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.66342 0.0283337 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.645956 0.00686453 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.668955 0.00767898 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.655218 -0.012605 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.626685 0.00723527 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.635947 -0.0122343 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.630413 0.00842045 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.721234 0.0272215 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.725055 0.0280589 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.726768 0.00656677 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.70473 0.0172649 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.71952 0.0487136 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.699195 0.0379196 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.715699 0.0478762 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.741558 0.0380155 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.737738 0.0371781 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.743272 0.0165234 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.172546 0.643951 1.11022e-16 RAD 0.166667 + txt002 + SPHERE CENTER 0.281471 0.802608 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.30566 0.824035 -0.177765 RAD 0.0185185 + txt002 + SPHERE CENTER 0.302088 0.822021 -0.202114 RAD 0.00617284 + txt002 + SPHERE CENTER 0.298094 0.802598 -0.187402 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282758 0.821938 -0.186751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.309654 0.843459 -0.192477 RAD 0.00617284 + txt002 + SPHERE CENTER 0.290324 0.843375 -0.177114 RAD 0.00617284 + txt002 + SPHERE CENTER 0.313227 0.845472 -0.168128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.32499 0.824119 -0.193128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.328563 0.826132 -0.16878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.320997 0.804695 -0.178416 RAD 0.00617284 + txt002 + SPHERE CENTER 0.305221 0.752156 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.325175 0.741263 -0.169507 RAD 0.00617284 + txt002 + SPHERE CENTER 0.325981 0.765112 -0.163165 RAD 0.00617284 + txt002 + SPHERE CENTER 0.32493 0.747715 -0.145675 RAD 0.00617284 + txt002 + SPHERE CENTER 0.304415 0.728307 -0.166213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.304171 0.734759 -0.142381 RAD 0.00617284 + txt002 + SPHERE CENTER 0.284462 0.7392 -0.156576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.305466 0.745704 -0.183703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.285513 0.756597 -0.174066 RAD 0.00617284 + txt002 + SPHERE CENTER 0.306272 0.769553 -0.17736 RAD 0.00617284 + txt002 + SPHERE CENTER 0.241352 0.787796 -0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER 0.218449 0.785699 -0.180578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.223304 0.778718 -0.157397 RAD 0.00617284 + txt002 + SPHERE CENTER 0.22345 0.802677 -0.163362 RAD 0.00617284 + txt002 + SPHERE CENTER 0.236497 0.794777 -0.194773 RAD 0.00617284 + txt002 + SPHERE CENTER 0.241498 0.811756 -0.177557 RAD 0.00617284 + txt002 + SPHERE CENTER 0.2594 0.796874 -0.185788 RAD 0.00617284 + txt002 + SPHERE CENTER 0.236351 0.770818 -0.188808 RAD 0.00617284 + txt002 + SPHERE CENTER 0.259253 0.772915 -0.179823 RAD 0.00617284 + txt002 + SPHERE CENTER 0.241205 0.763837 -0.165627 RAD 0.00617284 + txt002 + SPHERE CENTER 0.28191 0.874487 -0.129006 RAD 0.0185185 + txt002 + SPHERE CENTER 0.292033 0.891539 -0.143718 RAD 0.00617284 + txt002 + SPHERE CENTER 0.305711 0.872763 -0.135349 RAD 0.00617284 + txt002 + SPHERE CENTER 0.28812 0.868678 -0.152187 RAD 0.00617284 + txt002 + SPHERE CENTER 0.268233 0.893263 -0.137375 RAD 0.00617284 + txt002 + SPHERE CENTER 0.264319 0.870402 -0.145845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.25811 0.876212 -0.122663 RAD 0.00617284 + txt002 + SPHERE CENTER 0.285824 0.897348 -0.120537 RAD 0.00617284 + txt002 + SPHERE CENTER 0.275701 0.880296 -0.105825 RAD 0.00617284 + txt002 + SPHERE CENTER 0.299501 0.878572 -0.112168 RAD 0.00617284 + txt002 + SPHERE CENTER 0.217602 0.838248 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.206363 0.860225 -0.122182 RAD 0.00617284 + txt002 + SPHERE CENTER 0.223536 0.854636 -0.105343 RAD 0.00617284 + txt002 + SPHERE CENTER 0.230102 0.858689 -0.128798 RAD 0.00617284 + txt002 + SPHERE CENTER 0.200429 0.843837 -0.139672 RAD 0.00617284 + txt002 + SPHERE CENTER 0.224168 0.842301 -0.146288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.211667 0.821861 -0.140323 RAD 0.00617284 + txt002 + SPHERE CENTER 0.193863 0.839784 -0.116217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.205101 0.817808 -0.116868 RAD 0.00617284 + txt002 + SPHERE CENTER 0.211035 0.834196 -0.0993785 RAD 0.00617284 + txt002 + SPHERE CENTER 0.257721 0.853061 -0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER 0.26204 0.87538 -0.0527151 RAD 0.00617284 + txt002 + SPHERE CENTER 0.280934 0.860805 -0.0590577 RAD 0.00617284 + txt002 + SPHERE CENTER 0.266856 0.87108 -0.0765474 RAD 0.00617284 + txt002 + SPHERE CENTER 0.238827 0.867636 -0.0560094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.243643 0.863337 -0.0798417 RAD 0.00617284 + txt002 + SPHERE CENTER 0.234508 0.845317 -0.0656463 RAD 0.00617284 + txt002 + SPHERE CENTER 0.252905 0.857361 -0.0385197 RAD 0.00617284 + txt002 + SPHERE CENTER 0.248586 0.835041 -0.0481565 RAD 0.00617284 + txt002 + SPHERE CENTER 0.271799 0.842785 -0.0448623 RAD 0.00617284 + txt002 + SPHERE CENTER 0.34578 0.838847 -0.117284 RAD 0.0185185 + txt002 + SPHERE CENTER 0.360404 0.851488 -0.132647 RAD 0.00617284 + txt002 + SPHERE CENTER 0.347059 0.832518 -0.141116 RAD 0.00617284 + txt002 + SPHERE CENTER 0.335865 0.853509 -0.1345 RAD 0.00617284 + txt002 + SPHERE CENTER 0.359125 0.857816 -0.108814 RAD 0.00617284 + txt002 + SPHERE CENTER 0.334587 0.859838 -0.110668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.344501 0.845176 -0.0934517 RAD 0.00617284 + txt002 + SPHERE CENTER 0.370319 0.836826 -0.115431 RAD 0.00617284 + txt002 + SPHERE CENTER 0.355695 0.824185 -0.100068 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356973 0.817857 -0.1239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.321591 0.817421 -0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER 0.340361 0.83071 -0.0416443 RAD 0.00617284 + txt002 + SPHERE CENTER 0.341208 0.822249 -0.0648253 RAD 0.00617284 + txt002 + SPHERE CENTER 0.325527 0.840365 -0.0588603 RAD 0.00617284 + txt002 + SPHERE CENTER 0.320744 0.825882 -0.0274488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.30591 0.835537 -0.0446649 RAD 0.00617284 + txt002 + SPHERE CENTER 0.301973 0.812593 -0.0364345 RAD 0.00617284 + txt002 + SPHERE CENTER 0.336425 0.807766 -0.0334138 RAD 0.00617284 + txt002 + SPHERE CENTER 0.317654 0.794477 -0.0423994 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337272 0.799305 -0.0565949 RAD 0.00617284 + txt002 + SPHERE CENTER 0.345341 0.766968 -0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.369945 0.768944 -0.10004 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356171 0.780624 -0.116879 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356172 0.788341 -0.093424 RAD 0.00617284 + txt002 + SPHERE CENTER 0.359115 0.755289 -0.0825505 RAD 0.00617284 + txt002 + SPHERE CENTER 0.345342 0.774685 -0.0759343 RAD 0.00617284 + txt002 + SPHERE CENTER 0.334511 0.753313 -0.0818993 RAD 0.00617284 + txt002 + SPHERE CENTER 0.359113 0.747572 -0.106005 RAD 0.00617284 + txt002 + SPHERE CENTER 0.33451 0.745596 -0.105354 RAD 0.00617284 + txt002 + SPHERE CENTER 0.34534 0.759252 -0.122844 RAD 0.00617284 + txt002 + SPHERE CENTER 0.358439 0.594141 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.408291 0.619127 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.411883 0.625955 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.396287 0.607547 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.390369 0.630791 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.423887 0.637535 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.402373 0.642371 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.420295 0.630706 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.429805 0.61429 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.426212 0.607462 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.414208 0.595882 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337042 0.638217 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.344865 0.652948 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.357326 0.651954 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.357697 0.632683 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.324581 0.639211 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337413 0.618946 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.316758 0.624481 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.324211 0.658482 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.316388 0.643752 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.336672 0.657489 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37761 0.665691 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.389713 0.68332 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.398265 0.660156 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37761 0.665691 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.369058 0.688854 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356956 0.671225 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356956 0.671225 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.389713 0.68332 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37761 0.665691 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.398265 0.660156 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.429687 0.57505 -0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER 0.452905 0.58161 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.434777 0.586467 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.436077 0.5989 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.447815 0.570193 -0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER 0.430987 0.587483 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.424596 0.563633 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.446515 0.55776 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.423296 0.5512 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.428387 0.562617 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399007 0.621614 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.41723 0.637209 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.418027 0.624734 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.401533 0.642848 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.39821 0.634089 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.382513 0.639728 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.379986 0.618494 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.414703 0.615976 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.39648 0.600381 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.4155 0.603501 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.379835 0.550064 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.396248 0.547099 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.403175 0.557504 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.388263 0.569716 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.372907 0.539659 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.364922 0.562276 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356494 0.542624 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.387819 0.527447 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.371406 0.530412 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.394747 0.537852 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.389119 0.547576 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.410169 0.541008 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.405866 0.564748 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.410472 0.548718 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.393422 0.523836 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.393725 0.531546 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.372372 0.530405 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.388816 0.539866 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.367766 0.546435 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.384513 0.563607 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.339267 0.522591 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.340934 0.501272 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.359921 0.517056 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.339267 0.522591 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.320279 0.506807 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.318612 0.528125 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.318612 0.528125 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.340934 0.501272 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.339267 0.522591 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.359921 0.517056 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.317871 0.566667 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.296626 0.555534 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.307914 0.550163 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.297216 0.572202 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.306582 0.572037 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.307172 0.588706 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.327827 0.583171 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31728 0.549999 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.338525 0.561133 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.328569 0.544629 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.172546 0.643951 -0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER 0.142305 0.674191 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.144155 0.692502 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.150298 0.696439 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.164554 0.682184 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.136163 0.670254 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.156561 0.659936 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER 0.134313 0.651943 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.121907 0.684509 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER 0.120057 0.666199 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.12805 0.688447 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER 0.100996 0.663122 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0847178 0.680265 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.104191 0.675047 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.107387 0.686972 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0815225 0.66834 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER 0.104191 0.675047 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0978007 0.651197 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0783272 0.656415 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0946054 0.639272 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0978007 0.651197 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.153374 0.715501 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.160081 0.738169 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.177224 0.721891 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.165299 0.718696 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.136231 0.731779 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.141449 0.712305 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.129524 0.70911 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.148156 0.734974 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.141449 0.712305 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.165299 0.718696 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.213855 0.655019 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.213517 0.662308 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.194382 0.649801 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER 0.198584 0.673065 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.23299 0.667526 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER 0.218058 0.678283 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.233329 0.660237 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER 0.228788 0.644262 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.229127 0.636974 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.209653 0.631756 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.224924 0.696329 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.23918 0.710584 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER 0.233654 0.687599 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.216195 0.705059 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.23045 0.719314 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.207465 0.713788 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.216195 0.705059 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.24791 0.701855 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.233654 0.687599 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.242384 0.678869 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.244096 0.624779 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.266765 0.631486 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.247291 0.636704 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.250487 0.648629 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.26357 0.619561 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.247291 0.636704 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.240901 0.612854 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.260374 0.607636 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.237705 0.600929 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.240901 0.612854 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.161477 0.602641 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.162741 0.579817 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER 0.179523 0.58737 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.156259 0.583168 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER 0.144695 0.595088 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.138214 0.598439 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.143431 0.617912 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.167958 0.59929 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.166695 0.622115 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER 0.184741 0.606843 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.191718 0.5724 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.208861 0.556122 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.215568 0.578791 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.203643 0.575596 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.185011 0.549732 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.179793 0.569205 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.167868 0.56601 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.196936 0.552927 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER 0.179793 0.569205 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.203643 0.575596 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.120168 0.591572 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.105912 0.577317 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.128897 0.582843 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.111438 0.600302 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0971825 0.586046 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.102708 0.609032 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.111438 0.600302 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.114642 0.568587 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.128897 0.582843 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.137627 0.574113 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0955788 0.852418 9.1293e-17 RAD 0.0555556 + txt002 + SPHERE CENTER 0.11107 0.922609 -0.0178949 RAD 0.0185185 + txt002 + SPHERE CENTER 0.122151 0.937225 -0.0344251 RAD 0.00617284 + txt002 + SPHERE CENTER 0.131874 0.915202 -0.0289382 RAD 0.00617284 + txt002 + SPHERE CENTER 0.11086 0.916553 -0.0418311 RAD 0.00617284 + txt002 + SPHERE CENTER 0.101346 0.944632 -0.0233819 RAD 0.00617284 + txt002 + SPHERE CENTER 0.090055 0.92396 -0.0307879 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0902645 0.930016 -0.00685171 RAD 0.00617284 + txt002 + SPHERE CENTER 0.12236 0.943281 -0.0104889 RAD 0.00617284 + txt002 + SPHERE CENTER 0.111279 0.928665 0.00604126 RAD 0.00617284 + txt002 + SPHERE CENTER 0.132084 0.921258 -0.00500196 RAD 0.00617284 + txt002 + SPHERE CENTER 0.164775 0.877966 0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER 0.182656 0.890926 -0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER 0.167676 0.876622 -0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER 0.159019 0.897331 -0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER 0.179755 0.89227 0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER 0.156118 0.898675 0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.161874 0.87931 0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.188412 0.871561 0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER 0.17053 0.8586 0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER 0.173431 0.857256 -0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.135698 0.867231 -0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER 0.134634 0.873196 -0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER 0.11765 0.858152 -0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER 0.117797 0.882112 -0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER 0.152682 0.882275 -0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.135845 0.89119 -0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER 0.153747 0.876309 -0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER 0.152536 0.858315 -0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER 0.1536 0.852349 -0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER 0.135552 0.843271 -0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0418734 0.897062 -0.0246914 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0359958 0.920407 -0.0301783 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0511067 0.915603 -0.0112511 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0588574 0.912106 -0.0344321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0267625 0.901866 -0.0436186 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0496241 0.893565 -0.0478724 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0326401 0.878521 -0.0381316 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0190117 0.905363 -0.0204376 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0248894 0.882018 -0.0149506 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0341227 0.900559 -0.00151032 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0665023 0.841683 -0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0454909 0.840284 -0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0463379 0.831823 -0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0473735 0.856111 -0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0656554 0.850144 -0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0675379 0.865971 -0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0866667 0.851543 -0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0646197 0.825856 -0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0856311 0.827255 -0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0654667 0.817395 -0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0263827 0.826871 -0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER 0.00436945 0.825102 0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER 0.025051 0.823964 0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER 0.018173 0.84533 0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00570109 0.828008 -0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0195047 0.848237 -0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0277143 0.829777 -0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0125791 0.806642 -0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0345923 0.808411 -0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0332607 0.805505 0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0709499 0.907797 0.0425863 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0752104 0.930963 0.0499923 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0941344 0.915684 0.0457385 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0806562 0.924191 0.0268805 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0520258 0.923076 0.0468401 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0574717 0.916304 0.0237283 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0477654 0.89991 0.0394341 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0655041 0.914568 0.065698 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0612436 0.891402 0.058292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0844281 0.899289 0.0614442 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0554592 0.837606 0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0523913 0.842832 0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0750766 0.842434 0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0593957 0.86055 0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0327739 0.838004 0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0397783 0.855722 0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0358417 0.832778 0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0484547 0.819888 0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0515226 0.814662 0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER 0.07114 0.81949 0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.124655 0.863153 0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER 0.141535 0.875744 0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER 0.146389 0.868763 0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER 0.129819 0.88655 0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.119801 0.870135 0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER 0.108085 0.880941 0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER 0.102922 0.857544 0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER 0.136371 0.852347 0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER 0.119492 0.839756 0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER 0.141225 0.845366 0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0133465 0.69376 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.0646815 0.745859 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0684873 0.770032 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0507391 0.762305 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0481266 0.759394 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0824297 0.753586 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.062069 0.742948 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0786239 0.729413 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0850422 0.756497 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0812364 0.732325 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.067294 0.74877 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0347427 0.737837 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0299763 0.758864 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0114021 0.745277 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0263144 0.757489 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0533169 0.751424 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0496549 0.750049 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0580833 0.730397 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0384047 0.739212 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.043171 0.718185 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0198304 0.725625 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0058253 0.76531 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0179281 0.782939 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.02648 0.759776 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0058253 0.76531 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00272662 0.788473 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0148294 0.770845 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0148294 0.770845 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0179281 0.782939 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0058253 0.76531 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.02648 0.759776 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0432853 0.701782 -0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0544915 0.717566 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0588496 0.718734 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0368947 0.725632 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0389272 0.700615 -0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0213304 0.708681 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.027721 0.684831 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0608821 0.693716 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0496759 0.677932 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0652402 0.694884 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0272215 0.721234 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0280589 0.725055 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0172649 0.70473 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00656677 0.726768 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0380155 0.741558 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0165234 0.743272 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0371781 0.737738 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0487136 0.71952 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0478762 0.715699 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0379196 0.699195 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00804971 0.649684 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0275193 0.640422 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0283337 0.66342 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0287044 0.644149 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00723527 0.626685 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00842045 0.630413 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0122343 0.635947 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00686453 0.645956 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.012605 0.655218 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00767898 0.668955 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0838533 0.674309 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.106805 0.675276 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0875713 0.673094 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.091423 0.694308 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.103087 0.676491 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0877049 0.695522 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0801352 0.675524 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0992356 0.655278 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0762835 0.65431 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0800016 0.653095 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0325183 0.62221 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0308513 0.600892 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0118635 0.616676 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0325183 0.62221 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.051506 0.606426 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.053173 0.627745 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.053173 0.627745 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0308513 0.600892 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0325183 0.62221 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0118635 0.616676 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0539145 0.666287 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0577732 0.666927 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.034894 0.669407 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0513875 0.68752 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0767937 0.663807 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.070408 0.6844 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.072935 0.663167 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0603001 0.645694 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0564414 0.645053 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0374209 0.648173 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0133465 0.69376 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.0440268 0.740325 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0417568 0.762259 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0216407 0.748937 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0345526 0.759495 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0641429 0.753646 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0569387 0.750882 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0664129 0.731712 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.051231 0.743089 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.053501 0.721155 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0311149 0.729767 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0272215 0.721234 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0454452 0.736829 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.046242 0.724354 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0297485 0.742467 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0264247 0.733709 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.010728 0.739347 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00820099 0.718114 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0429182 0.715595 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0246945 0.7 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.043715 0.70312 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0058253 0.76531 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0179281 0.782939 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.02648 0.759776 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0058253 0.76531 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00272662 0.788473 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0148294 0.770845 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0148294 0.770845 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0179281 0.782939 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0058253 0.76531 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.02648 0.759776 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0845947 0.712851 0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER -0.101422 0.730141 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0832945 0.725284 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0782041 0.736701 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.102723 0.717709 0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0795043 0.724268 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0858949 0.700418 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.107813 0.706291 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0909853 0.689001 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0896851 0.701434 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0347427 0.737837 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0269197 0.752567 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0144587 0.751574 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.014088 0.732303 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0472037 0.73883 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0343719 0.718566 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0550267 0.7241 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0475745 0.758102 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0553974 0.743371 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0351134 0.757108 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0539145 0.666287 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0751594 0.655153 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0638711 0.649783 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0745692 0.671821 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0652028 0.671657 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0646126 0.688325 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0439578 0.682791 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0545047 0.649619 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0332597 0.660752 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0432164 0.644249 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0631985 0.668775 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0708196 0.669983 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0467378 0.671462 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0618185 0.690113 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0872804 0.667296 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0782793 0.687426 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0796593 0.666087 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0721997 0.648644 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0645786 0.647436 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0481178 0.650123 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0325183 0.62221 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0308513 0.600892 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0118635 0.616676 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0325183 0.62221 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.051506 0.606426 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.053173 0.627745 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.053173 0.627745 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0308513 0.600892 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0325183 0.62221 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0118635 0.616676 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00804971 0.649684 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0244627 0.646718 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0313903 0.657124 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.016478 0.669336 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00112207 0.639278 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00686255 0.661896 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0152909 0.642244 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0160343 0.627066 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.000378614 0.630031 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.022962 0.637471 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.281471 0.802608 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.329459 0.858698 0.104938 RAD 0.0185185 + txt002 + SPHERE CENTER 0.34259 0.872345 0.0890951 RAD 0.00617284 + txt002 + SPHERE CENTER 0.338969 0.848329 0.0846485 RAD 0.00617284 + txt002 + SPHERE CENTER 0.32016 0.86421 0.0827387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.333079 0.882715 0.109385 RAD 0.00617284 + txt002 + SPHERE CENTER 0.310649 0.87458 0.103028 RAD 0.00617284 + txt002 + SPHERE CENTER 0.319948 0.869068 0.125228 RAD 0.00617284 + txt002 + SPHERE CENTER 0.351888 0.866833 0.111295 RAD 0.00617284 + txt002 + SPHERE CENTER 0.338757 0.853186 0.127138 RAD 0.00617284 + txt002 + SPHERE CENTER 0.348268 0.842817 0.106848 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337088 0.798572 0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER 0.346884 0.808673 0.0420622 RAD 0.00617284 + txt002 + SPHERE CENTER 0.322361 0.807762 0.044793 RAD 0.00617284 + txt002 + SPHERE CENTER 0.335792 0.82298 0.0588533 RAD 0.00617284 + txt002 + SPHERE CENTER 0.361611 0.799483 0.0596212 RAD 0.00617284 + txt002 + SPHERE CENTER 0.350519 0.81379 0.0764123 RAD 0.00617284 + txt002 + SPHERE CENTER 0.351815 0.789382 0.079911 RAD 0.00617284 + txt002 + SPHERE CENTER 0.34818 0.784265 0.0455609 RAD 0.00617284 + txt002 + SPHERE CENTER 0.338384 0.774164 0.0658506 RAD 0.00617284 + txt002 + SPHERE CENTER 0.323657 0.783355 0.0482916 RAD 0.00617284 + txt002 + SPHERE CENTER 0.280879 0.845371 0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER 0.291048 0.849036 0.0284303 RAD 0.00617284 + txt002 + SPHERE CENTER 0.304882 0.840755 0.0471312 RAD 0.00617284 + txt002 + SPHERE CENTER 0.287867 0.826067 0.0369125 RAD 0.00617284 + txt002 + SPHERE CENTER 0.267046 0.853652 0.0319289 RAD 0.00617284 + txt002 + SPHERE CENTER 0.263865 0.830683 0.0404111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.256877 0.849987 0.0541285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.28406 0.868341 0.0421477 RAD 0.00617284 + txt002 + SPHERE CENTER 0.273891 0.864676 0.0643473 RAD 0.00617284 + txt002 + SPHERE CENTER 0.297894 0.86006 0.0608487 RAD 0.00617284 + txt002 + SPHERE CENTER 0.273842 0.862735 0.153697 RAD 0.0185185 + txt002 + SPHERE CENTER 0.282313 0.885497 0.158144 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29787 0.867718 0.150967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.281455 0.876946 0.134996 RAD 0.00617284 + txt002 + SPHERE CENTER 0.258284 0.880514 0.160875 RAD 0.00617284 + txt002 + SPHERE CENTER 0.257427 0.871963 0.137727 RAD 0.00617284 + txt002 + SPHERE CENTER 0.249813 0.857752 0.156428 RAD 0.00617284 + txt002 + SPHERE CENTER 0.274699 0.871286 0.176845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.266228 0.848523 0.172398 RAD 0.00617284 + txt002 + SPHERE CENTER 0.290257 0.853506 0.169668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.225263 0.849407 0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.21889 0.873186 0.0974792 RAD 0.00617284 + txt002 + SPHERE CENTER 0.236437 0.866351 0.113449 RAD 0.00617284 + txt002 + SPHERE CENTER 0.240865 0.865588 0.0891702 RAD 0.00617284 + txt002 + SPHERE CENTER 0.207715 0.856242 0.0834188 RAD 0.00617284 + txt002 + SPHERE CENTER 0.22969 0.848644 0.0751099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.214088 0.832464 0.0853287 RAD 0.00617284 + txt002 + SPHERE CENTER 0.203288 0.857005 0.107698 RAD 0.00617284 + txt002 + SPHERE CENTER 0.20966 0.833227 0.109608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.220835 0.850171 0.123668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.225855 0.806645 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.21762 0.818054 0.18016 RAD 0.00617284 + txt002 + SPHERE CENTER 0.241754 0.813612 0.177429 RAD 0.00617284 + txt002 + SPHERE CENTER 0.230661 0.83061 0.163369 RAD 0.00617284 + txt002 + SPHERE CENTER 0.20172 0.811087 0.162601 RAD 0.00617284 + txt002 + SPHERE CENTER 0.214761 0.823642 0.14581 RAD 0.00617284 + txt002 + SPHERE CENTER 0.209955 0.799677 0.142311 RAD 0.00617284 + txt002 + SPHERE CENTER 0.212813 0.794089 0.176661 RAD 0.00617284 + txt002 + SPHERE CENTER 0.221048 0.78268 0.156372 RAD 0.00617284 + txt002 + SPHERE CENTER 0.236948 0.789647 0.173931 RAD 0.00617284 + txt002 + SPHERE CENTER 0.330051 0.815936 0.165419 RAD 0.0185185 + txt002 + SPHERE CENTER 0.350165 0.828769 0.171776 RAD 0.00617284 + txt002 + SPHERE CENTER 0.347547 0.820583 0.148628 RAD 0.00617284 + txt002 + SPHERE CENTER 0.333232 0.838905 0.156937 RAD 0.00617284 + txt002 + SPHERE CENTER 0.332668 0.824121 0.188567 RAD 0.00617284 + txt002 + SPHERE CENTER 0.315735 0.834258 0.173728 RAD 0.00617284 + txt002 + SPHERE CENTER 0.312554 0.811288 0.182211 RAD 0.00617284 + txt002 + SPHERE CENTER 0.346984 0.805799 0.180258 RAD 0.00617284 + txt002 + SPHERE CENTER 0.32687 0.792966 0.173902 RAD 0.00617284 + txt002 + SPHERE CENTER 0.344366 0.797614 0.157111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282063 0.759846 0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER 0.29233 0.756464 0.193792 RAD 0.00617284 + txt002 + SPHERE CENTER 0.305929 0.765125 0.175091 RAD 0.00617284 + txt002 + SPHERE CENTER 0.288514 0.779336 0.18531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.268464 0.751185 0.190293 RAD 0.00617284 + txt002 + SPHERE CENTER 0.264649 0.774058 0.181811 RAD 0.00617284 + txt002 + SPHERE CENTER 0.258198 0.754567 0.168094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.285879 0.736973 0.180075 RAD 0.00617284 + txt002 + SPHERE CENTER 0.275612 0.740355 0.157875 RAD 0.00617284 + txt002 + SPHERE CENTER 0.299478 0.745634 0.161374 RAD 0.00617284 + txt002 + SPHERE CENTER 0.33768 0.75581 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.362219 0.753851 0.124743 RAD 0.00617284 + txt002 + SPHERE CENTER 0.352319 0.76987 0.108773 RAD 0.00617284 + txt002 + SPHERE CENTER 0.350765 0.774086 0.133052 RAD 0.00617284 + txt002 + SPHERE CENTER 0.347581 0.739791 0.138803 RAD 0.00617284 + txt002 + SPHERE CENTER 0.336127 0.760026 0.147112 RAD 0.00617284 + txt002 + SPHERE CENTER 0.323042 0.74175 0.136894 RAD 0.00617284 + txt002 + SPHERE CENTER 0.349134 0.735575 0.114524 RAD 0.00617284 + txt002 + SPHERE CENTER 0.324595 0.737534 0.112614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.339233 0.751594 0.0985541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.172546 0.643951 0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER 0.202787 0.674191 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.219248 0.690652 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER 0.223862 0.677807 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.206403 0.695267 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.198172 0.687036 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.185327 0.691651 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.181711 0.670575 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.215632 0.669577 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.199171 0.653116 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.220246 0.656732 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.244096 0.663122 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.261725 0.675225 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.244096 0.663122 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.238562 0.683777 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.261725 0.675225 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.238562 0.683777 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.244096 0.663122 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.267259 0.65457 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.249631 0.642468 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.249631 0.642468 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.191718 0.715501 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.203821 0.733129 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.212373 0.709966 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.191718 0.715501 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.183166 0.738664 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.171063 0.721035 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.171063 0.721035 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.203821 0.733129 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.191718 0.715501 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.212373 0.709966 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.131237 0.655019 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.12881 0.668451 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.151296 0.662426 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.137627 0.678869 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.108751 0.661044 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER 0.117567 0.671463 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.111177 0.647613 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.12242 0.644601 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.124846 0.631169 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.144906 0.638576 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.120168 0.696329 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.115992 0.720665 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.135288 0.711449 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.135288 0.711449 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.100872 0.705544 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.120168 0.696329 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.105047 0.681209 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.100872 0.705544 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.105047 0.681209 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.120168 0.696329 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.100996 0.624779 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0796777 0.626446 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.100996 0.624779 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0954616 0.645433 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0796777 0.626446 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0954616 0.645433 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.100996 0.624779 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0852121 0.605791 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.10653 0.604124 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.10653 0.604124 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.183615 0.602641 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.197046 0.600215 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.207465 0.609032 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.191021 0.622701 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.173196 0.593824 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.167171 0.61631 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.159765 0.596251 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.18964 0.580155 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER 0.176209 0.582581 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.200059 0.588972 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.153374 0.5724 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.155041 0.551082 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.174029 0.566866 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.153374 0.5724 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.134387 0.556617 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.13272 0.577935 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.13272 0.577935 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.155041 0.551082 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.153374 0.5724 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.174029 0.566866 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.224924 0.591572 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.24926 0.587397 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.240045 0.606693 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.240045 0.606693 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.23414 0.572277 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.224924 0.591572 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.209804 0.576452 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.23414 0.572277 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.209804 0.576452 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.224924 0.591572 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.358439 0.594141 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.428945 0.613592 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.448155 0.626191 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.43276 0.614455 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.42519 0.634643 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.44434 0.625328 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.421375 0.63378 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.42513 0.612729 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.45191 0.60514 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.4327 0.592541 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.436515 0.593404 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399007 0.621614 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.399844 0.625435 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.38905 0.60511 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.378352 0.627149 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.409801 0.641939 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.388308 0.643653 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.408963 0.638118 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.420499 0.619901 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.419661 0.61608 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.409705 0.599576 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37761 0.665691 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.389713 0.68332 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.398265 0.660156 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37761 0.665691 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.369058 0.688854 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356956 0.671225 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356956 0.671225 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.389713 0.68332 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37761 0.665691 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.398265 0.660156 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.388377 0.586119 0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.405974 0.594185 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.410332 0.593017 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.394768 0.609969 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.384019 0.587286 0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.372813 0.60307 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.366422 0.57922 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399584 0.570335 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.381987 0.562269 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.403942 0.569167 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337042 0.638217 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.341809 0.659244 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.360383 0.645657 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.345471 0.65787 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.318468 0.651804 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.32213 0.65043 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.313702 0.630777 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.33338 0.639592 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.328614 0.618565 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.351955 0.626005 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.317871 0.566667 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.314012 0.567308 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.336891 0.569787 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.320398 0.587901 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.294991 0.564188 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.301377 0.584781 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29885 0.563547 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.311485 0.546074 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.315344 0.545434 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.334364 0.548554 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.409774 0.542042 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.433888 0.53788 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.426423 0.55574 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.423551 0.558395 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.417238 0.524182 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.406901 0.544697 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.393124 0.528344 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.42011 0.521526 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.395996 0.525689 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.412646 0.539387 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.339267 0.522591 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.340934 0.501272 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.359921 0.517056 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.339267 0.522591 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.320279 0.506807 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.318612 0.528125 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.318612 0.528125 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.340934 0.501272 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.339267 0.522591 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.359921 0.517056 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.379835 0.550064 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.399304 0.540802 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.400119 0.563801 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.400489 0.54453 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37902 0.527065 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.380205 0.530793 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.359551 0.536327 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37865 0.546337 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.35918 0.555599 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.379464 0.569335 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.371785 0.0996195 0.544331 RAD 0.166667 + txt002 + SPHERE CENTER -0.393621 0.220501 0.729516 RAD 0.0555556 + txt002 + SPHERE CENTER -0.368601 0.279642 0.766439 RAD 0.0185185 + txt002 + SPHERE CENTER -0.354293 0.299716 0.765035 RAD 0.00617284 + txt002 + SPHERE CENTER -0.347717 0.279022 0.753281 RAD 0.00617284 + txt002 + SPHERE CENTER -0.366989 0.292196 0.745238 RAD 0.00617284 + txt002 + SPHERE CENTER -0.375177 0.300337 0.778193 RAD 0.00617284 + txt002 + SPHERE CENTER -0.387873 0.292817 0.758396 RAD 0.00617284 + txt002 + SPHERE CENTER -0.389485 0.280263 0.779597 RAD 0.00617284 + txt002 + SPHERE CENTER -0.355904 0.287162 0.786236 RAD 0.00617284 + txt002 + SPHERE CENTER -0.370213 0.267088 0.787639 RAD 0.00617284 + txt002 + SPHERE CENTER -0.349329 0.266468 0.774481 RAD 0.00617284 + txt002 + SPHERE CENTER -0.321889 0.238665 0.726118 RAD 0.0185185 + txt002 + SPHERE CENTER -0.304702 0.250544 0.71296 RAD 0.00617284 + txt002 + SPHERE CENTER -0.32307 0.238717 0.701455 RAD 0.00617284 + txt002 + SPHERE CENTER -0.327715 0.259421 0.714081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.30352 0.250492 0.737623 RAD 0.00617284 + txt002 + SPHERE CENTER -0.326533 0.259369 0.738744 RAD 0.00617284 + txt002 + SPHERE CENTER -0.320707 0.238612 0.750781 RAD 0.00617284 + txt002 + SPHERE CENTER -0.298875 0.229788 0.724997 RAD 0.00617284 + txt002 + SPHERE CENTER -0.316063 0.217908 0.738155 RAD 0.00617284 + txt002 + SPHERE CENTER -0.317244 0.21796 0.713492 RAD 0.00617284 + txt002 + SPHERE CENTER -0.372464 0.281062 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER -0.362978 0.289441 0.671279 RAD 0.00617284 + txt002 + SPHERE CENTER -0.35549 0.267771 0.680442 RAD 0.00617284 + txt002 + SPHERE CENTER -0.378255 0.270044 0.671155 RAD 0.00617284 + txt002 + SPHERE CENTER -0.379952 0.302733 0.683315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.395229 0.283335 0.683192 RAD 0.00617284 + txt002 + SPHERE CENTER -0.389438 0.294353 0.704516 RAD 0.00617284 + txt002 + SPHERE CENTER -0.357187 0.30046 0.692603 RAD 0.00617284 + txt002 + SPHERE CENTER -0.366673 0.29208 0.713804 RAD 0.00617284 + txt002 + SPHERE CENTER -0.349699 0.278789 0.701767 RAD 0.00617284 + txt002 + SPHERE CENTER -0.440333 0.261479 0.769837 RAD 0.0185185 + txt002 + SPHERE CENTER -0.443285 0.282991 0.781591 RAD 0.00617284 + txt002 + SPHERE CENTER -0.421181 0.271991 0.781342 RAD 0.00617284 + txt002 + SPHERE CENTER -0.4302 0.282046 0.760673 RAD 0.00617284 + txt002 + SPHERE CENTER -0.462437 0.27248 0.770086 RAD 0.00617284 + txt002 + SPHERE CENTER -0.449353 0.271534 0.749168 RAD 0.00617284 + txt002 + SPHERE CENTER -0.459485 0.250967 0.758332 RAD 0.00617284 + txt002 + SPHERE CENTER -0.453417 0.262424 0.790755 RAD 0.00617284 + txt002 + SPHERE CENTER -0.450466 0.240911 0.779001 RAD 0.00617284 + txt002 + SPHERE CENTER -0.431313 0.251423 0.790506 RAD 0.00617284 + txt002 + SPHERE CENTER -0.444196 0.262898 0.695877 RAD 0.0185185 + txt002 + SPHERE CENTER -0.449273 0.285685 0.687835 RAD 0.00617284 + txt002 + SPHERE CENTER -0.436139 0.282528 0.708504 RAD 0.00617284 + txt002 + SPHERE CENTER -0.426189 0.27701 0.68659 RAD 0.00617284 + txt002 + SPHERE CENTER -0.45733 0.266055 0.675209 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434246 0.257381 0.673964 RAD 0.00617284 + txt002 + SPHERE CENTER -0.452254 0.243269 0.683251 RAD 0.00617284 + txt002 + SPHERE CENTER -0.46728 0.271573 0.697123 RAD 0.00617284 + txt002 + SPHERE CENTER -0.462204 0.248787 0.705165 RAD 0.00617284 + txt002 + SPHERE CENTER -0.454146 0.268416 0.717791 RAD 0.00617284 + txt002 + SPHERE CENTER -0.465353 0.202338 0.732914 RAD 0.0185185 + txt002 + SPHERE CENTER -0.486123 0.204606 0.746073 RAD 0.00617284 + txt002 + SPHERE CENTER -0.464339 0.202946 0.757577 RAD 0.00617284 + txt002 + SPHERE CENTER -0.470107 0.223366 0.744951 RAD 0.00617284 + txt002 + SPHERE CENTER -0.487137 0.203998 0.72141 RAD 0.00617284 + txt002 + SPHERE CENTER -0.471122 0.222757 0.720288 RAD 0.00617284 + txt002 + SPHERE CENTER -0.466367 0.201729 0.708251 RAD 0.00617284 + txt002 + SPHERE CENTER -0.481368 0.183578 0.734036 RAD 0.00617284 + txt002 + SPHERE CENTER -0.460599 0.18131 0.720878 RAD 0.00617284 + txt002 + SPHERE CENTER -0.459584 0.181918 0.745541 RAD 0.00617284 + txt002 + SPHERE CENTER -0.389758 0.219082 0.803476 RAD 0.0185185 + txt002 + SPHERE CENTER -0.378635 0.228779 0.823273 RAD 0.00617284 + txt002 + SPHERE CENTER -0.365937 0.225483 0.802355 RAD 0.00617284 + txt002 + SPHERE CENTER -0.383364 0.24293 0.8036 RAD 0.00617284 + txt002 + SPHERE CENTER -0.402455 0.222377 0.824394 RAD 0.00617284 + txt002 + SPHERE CENTER -0.407185 0.236529 0.804721 RAD 0.00617284 + txt002 + SPHERE CENTER -0.413578 0.21268 0.804597 RAD 0.00617284 + txt002 + SPHERE CENTER -0.385029 0.20493 0.823149 RAD 0.00617284 + txt002 + SPHERE CENTER -0.396152 0.195233 0.803352 RAD 0.00617284 + txt002 + SPHERE CENTER -0.372331 0.201634 0.802231 RAD 0.00617284 + txt002 + SPHERE CENTER -0.414778 0.15994 0.766553 RAD 0.0185185 + txt002 + SPHERE CENTER -0.412573 0.147477 0.787754 RAD 0.00617284 + txt002 + SPHERE CENTER -0.39322 0.15977 0.77859 RAD 0.00617284 + txt002 + SPHERE CENTER -0.412448 0.172167 0.787878 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434131 0.147647 0.775717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434006 0.172338 0.775841 RAD 0.00617284 + txt002 + SPHERE CENTER -0.436336 0.16011 0.754517 RAD 0.00617284 + txt002 + SPHERE CENTER -0.414903 0.13525 0.766429 RAD 0.00617284 + txt002 + SPHERE CENTER -0.417108 0.147713 0.745229 RAD 0.00617284 + txt002 + SPHERE CENTER -0.39555 0.147543 0.757266 RAD 0.00617284 + txt002 + SPHERE CENTER -0.343046 0.178104 0.763155 RAD 0.0185185 + txt002 + SPHERE CENTER -0.319723 0.177083 0.771198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.325124 0.189464 0.750529 RAD 0.00617284 + txt002 + SPHERE CENTER -0.332294 0.198298 0.772443 RAD 0.00617284 + txt002 + SPHERE CENTER -0.337645 0.165722 0.783824 RAD 0.00617284 + txt002 + SPHERE CENTER -0.350216 0.186938 0.785069 RAD 0.00617284 + txt002 + SPHERE CENTER -0.360967 0.166743 0.775781 RAD 0.00617284 + txt002 + SPHERE CENTER -0.330475 0.156889 0.76191 RAD 0.00617284 + txt002 + SPHERE CENTER -0.353797 0.157909 0.753867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.335876 0.16927 0.741241 RAD 0.00617284 + txt002 + SPHERE CENTER -0.191247 0.166275 0.655442 RAD 0.0555556 + txt002 + SPHERE CENTER -0.130089 0.20793 0.652044 RAD 0.0185185 + txt002 + SPHERE CENTER -0.115471 0.221102 0.637128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.126388 0.200597 0.628759 RAD 0.00617284 + txt002 + SPHERE CENTER -0.13987 0.220766 0.633356 RAD 0.00617284 + txt002 + SPHERE CENTER -0.119172 0.228435 0.660413 RAD 0.00617284 + txt002 + SPHERE CENTER -0.143571 0.228099 0.656641 RAD 0.00617284 + txt002 + SPHERE CENTER -0.13379 0.215264 0.675329 RAD 0.00617284 + txt002 + SPHERE CENTER -0.10569 0.208266 0.655816 RAD 0.00617284 + txt002 + SPHERE CENTER -0.120308 0.195095 0.670732 RAD 0.00617284 + txt002 + SPHERE CENTER -0.116607 0.187762 0.647447 RAD 0.00617284 + txt002 + SPHERE CENTER -0.154295 0.172673 0.591563 RAD 0.0185185 + txt002 + SPHERE CENTER -0.15554 0.180792 0.568278 RAD 0.00617284 + txt002 + SPHERE CENTER -0.17557 0.171251 0.579113 RAD 0.00617284 + txt002 + SPHERE CENTER -0.166926 0.19323 0.586315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.134265 0.182215 0.580727 RAD 0.00617284 + txt002 + SPHERE CENTER -0.145651 0.194652 0.598764 RAD 0.00617284 + txt002 + SPHERE CENTER -0.133019 0.174096 0.604012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.142909 0.160236 0.573526 RAD 0.00617284 + txt002 + SPHERE CENTER -0.141663 0.152117 0.596811 RAD 0.00617284 + txt002 + SPHERE CENTER -0.162939 0.150694 0.584361 RAD 0.00617284 + txt002 + SPHERE CENTER -0.192135 0.230419 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.18209 0.243049 0.599717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.168159 0.227721 0.613157 RAD 0.00617284 + txt002 + SPHERE CENTER -0.185251 0.218634 0.597829 RAD 0.00617284 + txt002 + SPHERE CENTER -0.206066 0.245747 0.604965 RAD 0.00617284 + txt002 + SPHERE CENTER -0.209227 0.221332 0.603077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.216111 0.233117 0.623653 RAD 0.00617284 + txt002 + SPHERE CENTER -0.188974 0.254834 0.620293 RAD 0.00617284 + txt002 + SPHERE CENTER -0.199019 0.242204 0.638981 RAD 0.00617284 + txt002 + SPHERE CENTER -0.175043 0.239506 0.633733 RAD 0.00617284 + txt002 + SPHERE CENTER -0.167041 0.201532 0.715923 RAD 0.0185185 + txt002 + SPHERE CENTER -0.151829 0.219088 0.724292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.14514 0.205084 0.705088 RAD 0.00617284 + txt002 + SPHERE CENTER -0.163068 0.221861 0.702483 RAD 0.00617284 + txt002 + SPHERE CENTER -0.173729 0.215537 0.735128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.184969 0.218309 0.713318 RAD 0.00617284 + txt002 + SPHERE CENTER -0.188942 0.197981 0.726759 RAD 0.00617284 + txt002 + SPHERE CENTER -0.155801 0.19876 0.737733 RAD 0.00617284 + txt002 + SPHERE CENTER -0.171014 0.181204 0.729364 RAD 0.00617284 + txt002 + SPHERE CENTER -0.149113 0.184756 0.718528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.229087 0.224021 0.682285 RAD 0.0185185 + txt002 + SPHERE CENTER -0.22829 0.248268 0.686881 RAD 0.00617284 + txt002 + SPHERE CENTER -0.207937 0.234532 0.689486 RAD 0.00617284 + txt002 + SPHERE CENTER -0.216949 0.2391 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER -0.249439 0.237756 0.67968 RAD 0.00617284 + txt002 + SPHERE CENTER -0.238098 0.228589 0.659755 RAD 0.00617284 + txt002 + SPHERE CENTER -0.250236 0.213509 0.675083 RAD 0.00617284 + txt002 + SPHERE CENTER -0.240428 0.233189 0.702209 RAD 0.00617284 + txt002 + SPHERE CENTER -0.241225 0.208942 0.697613 RAD 0.00617284 + txt002 + SPHERE CENTER -0.220075 0.219453 0.704814 RAD 0.00617284 + txt002 + SPHERE CENTER -0.228199 0.159877 0.719322 RAD 0.0185185 + txt002 + SPHERE CENTER -0.229756 0.167942 0.742607 RAD 0.00617284 + txt002 + SPHERE CENTER -0.207683 0.16569 0.731771 RAD 0.00617284 + txt002 + SPHERE CENTER -0.223214 0.183484 0.72457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.250271 0.162129 0.730157 RAD 0.00617284 + txt002 + SPHERE CENTER -0.243729 0.177671 0.71212 RAD 0.00617284 + txt002 + SPHERE CENTER -0.248714 0.154064 0.706872 RAD 0.00617284 + txt002 + SPHERE CENTER -0.234741 0.144336 0.737359 RAD 0.00617284 + txt002 + SPHERE CENTER -0.233184 0.13627 0.714074 RAD 0.00617284 + txt002 + SPHERE CENTER -0.212668 0.142084 0.726523 RAD 0.00617284 + txt002 + SPHERE CENTER -0.129201 0.143787 0.689081 RAD 0.0185185 + txt002 + SPHERE CENTER -0.105335 0.14887 0.692853 RAD 0.00617284 + txt002 + SPHERE CENTER -0.115741 0.153943 0.671044 RAD 0.00617284 + txt002 + SPHERE CENTER -0.121723 0.167242 0.690969 RAD 0.00617284 + txt002 + SPHERE CENTER -0.118795 0.138714 0.71089 RAD 0.00617284 + txt002 + SPHERE CENTER -0.135183 0.157086 0.709006 RAD 0.00617284 + txt002 + SPHERE CENTER -0.142661 0.13363 0.707118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.112813 0.125414 0.690965 RAD 0.00617284 + txt002 + SPHERE CENTER -0.136679 0.120331 0.687193 RAD 0.00617284 + txt002 + SPHERE CENTER -0.123219 0.130487 0.669156 RAD 0.00617284 + txt002 + SPHERE CENTER -0.190359 0.102131 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER -0.179968 0.0897843 0.711167 RAD 0.00617284 + txt002 + SPHERE CENTER -0.166467 0.105492 0.697727 RAD 0.00617284 + txt002 + SPHERE CENTER -0.183804 0.114103 0.713055 RAD 0.00617284 + txt002 + SPHERE CENTER -0.20386 0.0864233 0.705919 RAD 0.00617284 + txt002 + SPHERE CENTER -0.207696 0.110742 0.707807 RAD 0.00617284 + txt002 + SPHERE CENTER -0.214251 0.0987702 0.687231 RAD 0.00617284 + txt002 + SPHERE CENTER -0.186523 0.0778128 0.690591 RAD 0.00617284 + txt002 + SPHERE CENTER -0.196914 0.0901597 0.671903 RAD 0.00617284 + txt002 + SPHERE CENTER -0.173022 0.0935207 0.677151 RAD 0.00617284 + txt002 + SPHERE CENTER -0.153407 0.108529 0.6286 RAD 0.0185185 + txt002 + SPHERE CENTER -0.130858 0.0995811 0.624003 RAD 0.00617284 + txt002 + SPHERE CENTER -0.135326 0.123725 0.621398 RAD 0.00617284 + txt002 + SPHERE CENTER -0.134736 0.113639 0.643928 RAD 0.00617284 + txt002 + SPHERE CENTER -0.148938 0.0843858 0.631205 RAD 0.00617284 + txt002 + SPHERE CENTER -0.152816 0.0984435 0.65113 RAD 0.00617284 + txt002 + SPHERE CENTER -0.171487 0.0933338 0.635801 RAD 0.00617284 + txt002 + SPHERE CENTER -0.149528 0.0944715 0.608675 RAD 0.00617284 + txt002 + SPHERE CENTER -0.172078 0.10342 0.613272 RAD 0.00617284 + txt002 + SPHERE CENTER -0.153997 0.118615 0.60607 RAD 0.00617284 + txt002 + SPHERE CENTER -0.31427 0.31427 0.544331 RAD 0.0555556 + txt002 + SPHERE CENTER -0.277961 0.367156 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.269898 0.374298 0.485076 RAD 0.00617284 + txt002 + SPHERE CENTER -0.270045 0.350338 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER -0.291334 0.362218 0.487134 RAD 0.00617284 + txt002 + SPHERE CENTER -0.277815 0.391115 0.501329 RAD 0.00617284 + txt002 + SPHERE CENTER -0.299251 0.379036 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.285878 0.383973 0.523547 RAD 0.00617284 + txt002 + SPHERE CENTER -0.256525 0.379235 0.505236 RAD 0.00617284 + txt002 + SPHERE CENTER -0.264588 0.372093 0.527454 RAD 0.00617284 + txt002 + SPHERE CENTER -0.256671 0.355276 0.511201 RAD 0.00617284 + txt002 + SPHERE CENTER -0.252306 0.297666 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.235688 0.305995 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER -0.259438 0.312359 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.245915 0.321516 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.228556 0.291303 0.509559 RAD 0.00617284 + txt002 + SPHERE CENTER -0.238783 0.306824 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.245173 0.282974 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.242079 0.282145 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER -0.258696 0.273816 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.265828 0.288509 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.31427 0.31427 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER -0.32435 0.32435 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER -0.33812 0.32066 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.32066 0.33812 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.3005 0.317959 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER -0.29681 0.331729 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.29042 0.307879 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.317959 0.3005 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER -0.307879 0.29042 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.331729 0.29681 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.339925 0.383759 0.544331 RAD 0.0185185 + txt002 + SPHERE CENTER -0.334762 0.407156 0.538366 RAD 0.00617284 + txt002 + SPHERE CENTER -0.31686 0.392275 0.546597 RAD 0.00617284 + txt002 + SPHERE CENTER -0.326552 0.388696 0.524171 RAD 0.00617284 + txt002 + SPHERE CENTER -0.357827 0.39864 0.536101 RAD 0.00617284 + txt002 + SPHERE CENTER -0.349618 0.380181 0.521905 RAD 0.00617284 + txt002 + SPHERE CENTER -0.362991 0.375243 0.542066 RAD 0.00617284 + txt002 + SPHERE CENTER -0.348135 0.402218 0.558526 RAD 0.00617284 + txt002 + SPHERE CENTER -0.353299 0.378821 0.564491 RAD 0.00617284 + txt002 + SPHERE CENTER -0.330233 0.387337 0.566757 RAD 0.00617284 + txt002 + SPHERE CENTER -0.376234 0.330873 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.393346 0.348239 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.383366 0.345565 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.369843 0.354723 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.386213 0.333547 0.484868 RAD 0.00617284 + txt002 + SPHERE CENTER -0.362711 0.340031 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.369102 0.316181 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399736 0.324389 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.382624 0.307023 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.389757 0.321715 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.376234 0.330873 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.386461 0.346394 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER -0.362711 0.340031 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.369843 0.354723 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399983 0.337237 0.579103 RAD 0.00617284 + txt002 + SPHERE CENTER -0.383366 0.345565 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.389757 0.321715 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.392851 0.322544 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER -0.382624 0.307023 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.369102 0.316181 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.277961 0.367156 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.261966 0.385852 0.57931 RAD 0.00617284 + txt002 + SPHERE CENTER -0.259422 0.36581 0.565115 RAD 0.00617284 + txt002 + SPHERE CENTER -0.278159 0.38141 0.561208 RAD 0.00617284 + txt002 + SPHERE CENTER -0.280504 0.387198 0.595564 RAD 0.00617284 + txt002 + SPHERE CENTER -0.296698 0.382755 0.577461 RAD 0.00617284 + txt002 + SPHERE CENTER -0.2965 0.368501 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER -0.261768 0.371598 0.599471 RAD 0.00617284 + txt002 + SPHERE CENTER -0.277764 0.352901 0.601529 RAD 0.00617284 + txt002 + SPHERE CENTER -0.259225 0.351556 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER -0.31427 0.31427 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.304189 0.32435 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.29042 0.32066 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.307879 0.33812 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.328039 0.317959 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.331729 0.331729 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.33812 0.307879 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.31058 0.3005 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.32066 0.29042 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.29681 0.29681 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.252306 0.297666 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.228803 0.30415 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER -0.238783 0.306824 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.245915 0.321516 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.242326 0.294992 0.603794 RAD 0.00617284 + txt002 + SPHERE CENTER -0.259438 0.312359 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.265828 0.288509 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.235194 0.2803 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER -0.258696 0.273816 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.245173 0.282974 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.574159 0.153845 0.618405 RAD 0.0555556 + txt002 + SPHERE CENTER -0.612768 0.202534 0.658726 RAD 0.0185185 + txt002 + SPHERE CENTER -0.612732 0.225282 0.668328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.591695 0.212428 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER -0.60221 0.22113 0.64638 RAD 0.00617284 + txt002 + SPHERE CENTER -0.633805 0.215388 0.660098 RAD 0.00617284 + txt002 + SPHERE CENTER -0.623283 0.211236 0.63815 RAD 0.00617284 + txt002 + SPHERE CENTER -0.63384 0.192641 0.650495 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62329 0.206686 0.680674 RAD 0.00617284 + txt002 + SPHERE CENTER -0.623325 0.183939 0.671072 RAD 0.00617284 + txt002 + SPHERE CENTER -0.602253 0.193832 0.679302 RAD 0.00617284 + txt002 + SPHERE CENTER -0.543919 0.184086 0.678886 RAD 0.0185185 + txt002 + SPHERE CENTER -0.527458 0.200547 0.687117 RAD 0.00617284 + txt002 + SPHERE CENTER -0.522843 0.187702 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER -0.540303 0.205161 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER -0.548533 0.196931 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER -0.561378 0.201546 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER -0.564994 0.18047 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER -0.531074 0.179472 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER -0.547535 0.163011 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER -0.526459 0.166627 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER -0.554987 0.225396 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.542885 0.243024 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER -0.534333 0.219861 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER -0.554987 0.225396 0.593714 RAD 0.00617284 + txt002 + SPHERE CENTER -0.563539 0.248559 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.575642 0.23093 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER -0.575642 0.23093 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER -0.542885 0.243024 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER -0.554987 0.225396 0.643096 RAD 0.00617284 + txt002 + SPHERE CENTER -0.534333 0.219861 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER -0.643008 0.172294 0.598245 RAD 0.0185185 + txt002 + SPHERE CENTER -0.660425 0.189742 0.599616 RAD 0.00617284 + txt002 + SPHERE CENTER -0.645434 0.185725 0.618821 RAD 0.00617284 + txt002 + SPHERE CENTER -0.636618 0.196144 0.598245 RAD 0.00617284 + txt002 + SPHERE CENTER -0.657999 0.17631 0.57904 RAD 0.00617284 + txt002 + SPHERE CENTER -0.634191 0.182712 0.577669 RAD 0.00617284 + txt002 + SPHERE CENTER -0.640582 0.158862 0.577669 RAD 0.00617284 + txt002 + SPHERE CENTER -0.666816 0.165892 0.599616 RAD 0.00617284 + txt002 + SPHERE CENTER -0.649399 0.148444 0.598245 RAD 0.00617284 + txt002 + SPHERE CENTER -0.651825 0.161875 0.618821 RAD 0.00617284 + txt002 + SPHERE CENTER -0.585228 0.195155 0.557924 RAD 0.0185185 + txt002 + SPHERE CENTER -0.574809 0.203972 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER -0.561378 0.201546 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER -0.568784 0.181486 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER -0.598659 0.197581 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER -0.592634 0.175095 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER -0.609078 0.188764 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER -0.591253 0.217641 0.549693 RAD 0.00617284 + txt002 + SPHERE CENTER -0.601672 0.208824 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER -0.577822 0.215215 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER -0.6044 0.123605 0.557924 RAD 0.0185185 + txt002 + SPHERE CENTER -0.620861 0.107144 0.549693 RAD 0.00617284 + txt002 + SPHERE CENTER -0.608016 0.102529 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER -0.625475 0.119989 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER -0.617245 0.128219 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER -0.621859 0.141064 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER -0.600784 0.14468 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER -0.599785 0.11076 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER -0.583324 0.127221 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER -0.58694 0.106145 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER -0.631939 0.130984 0.658726 RAD 0.0185185 + txt002 + SPHERE CENTER -0.643128 0.132649 0.680674 RAD 0.00617284 + txt002 + SPHERE CENTER -0.618482 0.133263 0.679302 RAD 0.00617284 + txt002 + SPHERE CENTER -0.631785 0.152367 0.671072 RAD 0.00617284 + txt002 + SPHERE CENTER -0.656585 0.130371 0.660098 RAD 0.00617284 + txt002 + SPHERE CENTER -0.645242 0.150088 0.650495 RAD 0.00617284 + txt002 + SPHERE CENTER -0.645397 0.128706 0.63815 RAD 0.00617284 + txt002 + SPHERE CENTER -0.643283 0.111266 0.668328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.632094 0.109601 0.64638 RAD 0.00617284 + txt002 + SPHERE CENTER -0.618637 0.11188 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER -0.593331 0.0822954 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.591664 0.0609772 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER -0.572676 0.076761 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER -0.593331 0.0822954 0.643096 RAD 0.00617284 + txt002 + SPHERE CENTER -0.612319 0.0665116 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.613986 0.0878298 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER -0.613986 0.0878298 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER -0.591664 0.0609772 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER -0.593331 0.0822954 0.593714 RAD 0.00617284 + txt002 + SPHERE CENTER -0.572676 0.076761 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER -0.56309 0.112536 0.678886 RAD 0.0185185 + txt002 + SPHERE CENTER -0.549659 0.11011 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER -0.53924 0.118927 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555684 0.132596 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER -0.573509 0.103719 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER -0.579534 0.126205 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER -0.58694 0.106145 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER -0.557065 0.09005 0.687117 RAD 0.00617284 + txt002 + SPHERE CENTER -0.570497 0.0924762 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER -0.546646 0.0988668 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER -0.494808 0.247614 0.43322 RAD 0.0555556 + txt002 + SPHERE CENTER -0.494287 0.313607 0.399581 RAD 0.0185185 + txt002 + SPHERE CENTER -0.484182 0.326876 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER -0.470513 0.310432 0.39372 RAD 0.00617284 + txt002 + SPHERE CENTER -0.488171 0.302705 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER -0.507957 0.330051 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.511946 0.305881 0.384149 RAD 0.00617284 + txt002 + SPHERE CENTER -0.518062 0.316783 0.405442 RAD 0.00617284 + txt002 + SPHERE CENTER -0.490299 0.337778 0.402668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.500404 0.324509 0.420874 RAD 0.00617284 + txt002 + SPHERE CENTER -0.476629 0.321334 0.415013 RAD 0.00617284 + txt002 + SPHERE CENTER -0.452978 0.302539 0.460062 RAD 0.0185185 + txt002 + SPHERE CENTER -0.436971 0.320401 0.454201 RAD 0.00617284 + txt002 + SPHERE CENTER -0.436675 0.29902 0.441856 RAD 0.00617284 + txt002 + SPHERE CENTER -0.455413 0.3148 0.438769 RAD 0.00617284 + txt002 + SPHERE CENTER -0.453274 0.32392 0.472408 RAD 0.00617284 + txt002 + SPHERE CENTER -0.471717 0.318318 0.456976 RAD 0.00617284 + txt002 + SPHERE CENTER -0.469281 0.306057 0.478269 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434535 0.30814 0.475494 RAD 0.00617284 + txt002 + SPHERE CENTER -0.450543 0.290278 0.481355 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434239 0.286759 0.463149 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434629 0.269833 0.396183 RAD 0.0185185 + txt002 + SPHERE CENTER -0.426389 0.279233 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER -0.445377 0.263449 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER -0.448298 0.286276 0.383837 RAD 0.00617284 + txt002 + SPHERE CENTER -0.415641 0.285616 0.396183 RAD 0.00617284 + txt002 + SPHERE CENTER -0.43755 0.29266 0.40513 RAD 0.00617284 + txt002 + SPHERE CENTER -0.42388 0.276216 0.417476 RAD 0.00617284 + txt002 + SPHERE CENTER -0.41272 0.262789 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.420959 0.253389 0.408529 RAD 0.00617284 + txt002 + SPHERE CENTER -0.431707 0.247006 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.536117 0.258683 0.372739 RAD 0.0185185 + txt002 + SPHERE CENTER -0.549787 0.275127 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER -0.549787 0.275127 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER -0.529727 0.282533 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER -0.536117 0.258683 0.348047 RAD 0.00617284 + txt002 + SPHERE CENTER -0.516058 0.266089 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER -0.522448 0.242239 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER -0.556177 0.251277 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER -0.542508 0.234833 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER -0.556177 0.251277 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER -0.476459 0.214908 0.369341 RAD 0.0185185 + txt002 + SPHERE CENTER -0.457868 0.209819 0.353908 RAD 0.00617284 + txt002 + SPHERE CENTER -0.458164 0.2312 0.366254 RAD 0.00617284 + txt002 + SPHERE CENTER -0.453963 0.210053 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER -0.476163 0.193527 0.356995 RAD 0.00617284 + txt002 + SPHERE CENTER -0.472258 0.193761 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER -0.494753 0.198616 0.372427 RAD 0.00617284 + txt002 + SPHERE CENTER -0.480363 0.214674 0.344961 RAD 0.00617284 + txt002 + SPHERE CENTER -0.498954 0.219763 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER -0.480659 0.236055 0.357307 RAD 0.00617284 + txt002 + SPHERE CENTER -0.536638 0.19269 0.406378 RAD 0.0185185 + txt002 + SPHERE CENTER -0.549603 0.17251 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER -0.528912 0.177908 0.424584 RAD 0.00617284 + txt002 + SPHERE CENTER -0.549105 0.191778 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER -0.557329 0.187292 0.394032 RAD 0.00617284 + txt002 + SPHERE CENTER -0.556831 0.20656 0.409464 RAD 0.00617284 + txt002 + SPHERE CENTER -0.544363 0.207471 0.388171 RAD 0.00617284 + txt002 + SPHERE CENTER -0.537136 0.173421 0.390945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.524171 0.193601 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER -0.516445 0.178819 0.403291 RAD 0.00617284 + txt002 + SPHERE CENTER -0.554467 0.291389 0.436618 RAD 0.0185185 + txt002 + SPHERE CENTER -0.562288 0.314604 0.439705 RAD 0.00617284 + txt002 + SPHERE CENTER -0.542501 0.306499 0.45205 RAD 0.00617284 + txt002 + SPHERE CENTER -0.541186 0.310183 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER -0.574255 0.299494 0.424272 RAD 0.00617284 + txt002 + SPHERE CENTER -0.553152 0.295073 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER -0.566433 0.276279 0.421186 RAD 0.00617284 + txt002 + SPHERE CENTER -0.575569 0.29581 0.448652 RAD 0.00617284 + txt002 + SPHERE CENTER -0.567748 0.272595 0.445566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555781 0.287705 0.460998 RAD 0.00617284 + txt002 + SPHERE CENTER -0.554987 0.225396 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER -0.567359 0.227186 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER -0.54267 0.227528 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555283 0.246777 0.482603 RAD 0.00617284 + txt002 + SPHERE CENTER -0.579676 0.225054 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.567601 0.244644 0.46131 RAD 0.00617284 + txt002 + SPHERE CENTER -0.567305 0.223263 0.448964 RAD 0.00617284 + txt002 + SPHERE CENTER -0.567063 0.205805 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER -0.554691 0.204014 0.457911 RAD 0.00617284 + txt002 + SPHERE CENTER -0.542374 0.206147 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER -0.513157 0.28032 0.497099 RAD 0.0185185 + txt002 + SPHERE CENTER -0.507811 0.298839 0.512531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.489718 0.287442 0.500186 RAD 0.00617284 + txt002 + SPHERE CENTER -0.505577 0.302049 0.488152 RAD 0.00617284 + txt002 + SPHERE CENTER -0.531251 0.291716 0.509445 RAD 0.00617284 + txt002 + SPHERE CENTER -0.529016 0.294927 0.485065 RAD 0.00617284 + txt002 + SPHERE CENTER -0.536597 0.273198 0.494013 RAD 0.00617284 + txt002 + SPHERE CENTER -0.515392 0.27711 0.521479 RAD 0.00617284 + txt002 + SPHERE CENTER -0.520738 0.258591 0.506047 RAD 0.00617284 + txt002 + SPHERE CENTER -0.497299 0.265714 0.509133 RAD 0.00617284 + txt002 + SPHERE CENTER -0.552323 0.0329639 0.43322 RAD 0.0555556 + txt002 + SPHERE CENTER -0.625877 0.0248832 0.436618 RAD 0.0185185 + txt002 + SPHERE CENTER -0.646362 0.0316054 0.448652 RAD 0.00617284 + txt002 + SPHERE CENTER -0.625173 0.0287309 0.460998 RAD 0.00617284 + txt002 + SPHERE CENTER -0.627981 0.0478 0.445566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.647066 0.0277577 0.424272 RAD 0.00617284 + txt002 + SPHERE CENTER -0.628685 0.0439523 0.421186 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62658 0.0210355 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER -0.644258 0.00868865 0.439705 RAD 0.00617284 + txt002 + SPHERE CENTER -0.623773 0.00196644 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER -0.623069 0.00581415 0.45205 RAD 0.00617284 + txt002 + SPHERE CENTER -0.584567 0.0138144 0.497099 RAD 0.0185185 + txt002 + SPHERE CENTER -0.584898 0.0177119 0.521479 RAD 0.00617284 + txt002 + SPHERE CENTER -0.56353 0.0185345 0.509133 RAD 0.00617284 + txt002 + SPHERE CENTER -0.580268 0.0364224 0.506047 RAD 0.00617284 + txt002 + SPHERE CENTER -0.605935 0.0129918 0.509445 RAD 0.00617284 + txt002 + SPHERE CENTER -0.601305 0.0317022 0.494013 RAD 0.00617284 + txt002 + SPHERE CENTER -0.605605 0.00909422 0.485065 RAD 0.00617284 + txt002 + SPHERE CENTER -0.589197 -0.00489609 0.512531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.588867 -0.00879364 0.488152 RAD 0.00617284 + txt002 + SPHERE CENTER -0.567829 -0.00407348 0.500186 RAD 0.00617284 + txt002 + SPHERE CENTER -0.593331 0.0822954 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER -0.593994 0.105299 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER -0.572783 0.0926585 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER -0.582384 0.100664 0.457911 RAD 0.00617284 + txt002 + SPHERE CENTER -0.614541 0.0949359 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.602932 0.090301 0.448964 RAD 0.00617284 + txt002 + SPHERE CENTER -0.613879 0.0719323 0.46131 RAD 0.00617284 + txt002 + SPHERE CENTER -0.604941 0.0869303 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER -0.604278 0.0639267 0.482603 RAD 0.00617284 + txt002 + SPHERE CENTER -0.58373 0.0742898 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER -0.593633 0.0440327 0.372739 RAD 0.0185185 + txt002 + SPHERE CENTER -0.607302 0.0604766 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER -0.607302 0.0604766 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER -0.587242 0.0678827 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER -0.593633 0.0440327 0.348047 RAD 0.00617284 + txt002 + SPHERE CENTER -0.573573 0.0514389 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER -0.579964 0.0275889 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER -0.613693 0.0366265 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER -0.600023 0.0201827 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER -0.613693 0.0366265 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER -0.561087 0.101445 0.406378 RAD 0.0185185 + txt002 + SPHERE CENTER -0.551884 0.118381 0.390945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.536664 0.103361 0.403291 RAD 0.00617284 + txt002 + SPHERE CENTER -0.550745 0.0944221 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER -0.576307 0.116465 0.394032 RAD 0.00617284 + txt002 + SPHERE CENTER -0.575168 0.0925065 0.388171 RAD 0.00617284 + txt002 + SPHERE CENTER -0.58551 0.0995293 0.409464 RAD 0.00617284 + txt002 + SPHERE CENTER -0.562225 0.125404 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER -0.571428 0.108468 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER -0.547006 0.110383 0.424584 RAD 0.00617284 + txt002 + SPHERE CENTER -0.520079 0.0521134 0.369341 RAD 0.0185185 + txt002 + SPHERE CENTER -0.523344 0.0542684 0.344961 RAD 0.00617284 + txt002 + SPHERE CENTER -0.534291 0.0358996 0.357307 RAD 0.00617284 + txt002 + SPHERE CENTER -0.541988 0.0591566 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER -0.509132 0.0704822 0.356995 RAD 0.00617284 + txt002 + SPHERE CENTER -0.527777 0.0753703 0.372427 RAD 0.00617284 + txt002 + SPHERE CENTER -0.505868 0.0683272 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER -0.501435 0.0472252 0.353908 RAD 0.00617284 + txt002 + SPHERE CENTER -0.49817 0.0450702 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER -0.512382 0.0288565 0.366254 RAD 0.00617284 + txt002 + SPHERE CENTER -0.584869 -0.0244483 0.399581 RAD 0.0185185 + txt002 + SPHERE CENTER -0.5935 -0.0473753 0.402668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.57344 -0.0399691 0.415013 RAD 0.00617284 + txt002 + SPHERE CENTER -0.595617 -0.0308315 0.420874 RAD 0.00617284 + txt002 + SPHERE CENTER -0.604929 -0.0318545 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.607046 -0.0153107 0.405442 RAD 0.00617284 + txt002 + SPHERE CENTER -0.596298 -0.00892756 0.384149 RAD 0.00617284 + txt002 + SPHERE CENTER -0.582752 -0.0409921 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER -0.574121 -0.0180651 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER -0.562692 -0.0335859 0.39372 RAD 0.00617284 + txt002 + SPHERE CENTER -0.511316 -0.0163676 0.396183 RAD 0.0185185 + txt002 + SPHERE CENTER -0.48882 -0.0212225 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.497372 0.00194055 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.491256 -0.00896145 0.408529 RAD 0.00617284 + txt002 + SPHERE CENTER -0.502764 -0.0395307 0.396183 RAD 0.00617284 + txt002 + SPHERE CENTER -0.505199 -0.0272696 0.417476 RAD 0.00617284 + txt002 + SPHERE CENTER -0.525259 -0.0346758 0.40513 RAD 0.00617284 + txt002 + SPHERE CENTER -0.50888 -0.0286287 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER -0.531375 -0.0237738 0.383837 RAD 0.00617284 + txt002 + SPHERE CENTER -0.517432 -0.00546563 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER -0.54356 -0.0355172 0.460062 RAD 0.0185185 + txt002 + SPHERE CENTER -0.530389 -0.0495897 0.475494 RAD 0.00617284 + txt002 + SPHERE CENTER -0.519442 -0.031221 0.463149 RAD 0.00617284 + txt002 + SPHERE CENTER -0.53532 -0.0261165 0.481355 RAD 0.00617284 + txt002 + SPHERE CENTER -0.554507 -0.0538859 0.472408 RAD 0.00617284 + txt002 + SPHERE CENTER -0.559438 -0.0304127 0.478269 RAD 0.00617284 + txt002 + SPHERE CENTER -0.567678 -0.0398133 0.456976 RAD 0.00617284 + txt002 + SPHERE CENTER -0.538628 -0.0589904 0.454201 RAD 0.00617284 + txt002 + SPHERE CENTER -0.551799 -0.0449178 0.438769 RAD 0.00617284 + txt002 + SPHERE CENTER -0.527681 -0.0406217 0.441856 RAD 0.00617284 + txt002 + SPHERE CENTER -0.451136 0.0058509 0.729516 RAD 0.0555556 + txt002 + SPHERE CENTER -0.447081 0.0051487 0.803476 RAD 0.0185185 + txt002 + SPHERE CENTER -0.435909 0.01504 0.823149 RAD 0.00617284 + txt002 + SPHERE CENTER -0.423265 0.0115452 0.802231 RAD 0.00617284 + txt002 + SPHERE CENTER -0.440694 0.0289993 0.803352 RAD 0.00617284 + txt002 + SPHERE CENTER -0.459725 0.00864346 0.824394 RAD 0.00617284 + txt002 + SPHERE CENTER -0.46451 0.0226028 0.804597 RAD 0.00617284 + txt002 + SPHERE CENTER -0.470897 -0.0012478 0.804721 RAD 0.00617284 + txt002 + SPHERE CENTER -0.442297 -0.00881065 0.823273 RAD 0.00617284 + txt002 + SPHERE CENTER -0.453468 -0.0187019 0.8036 RAD 0.00617284 + txt002 + SPHERE CENTER -0.429652 -0.0123054 0.802355 RAD 0.00617284 + txt002 + SPHERE CENTER -0.386138 0.0172804 0.763155 RAD 0.0185185 + txt002 + SPHERE CENTER -0.364644 0.0293677 0.76191 RAD 0.00617284 + txt002 + SPHERE CENTER -0.375512 0.0213457 0.741241 RAD 0.00617284 + txt002 + SPHERE CENTER -0.385352 0.0401449 0.753867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37527 0.0253024 0.783824 RAD 0.00617284 + txt002 + SPHERE CENTER -0.395978 0.0360796 0.775781 RAD 0.00617284 + txt002 + SPHERE CENTER -0.396764 0.0132151 0.785069 RAD 0.00617284 + txt002 + SPHERE CENTER -0.36543 0.0065032 0.771198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.386924 -0.00558411 0.772443 RAD 0.00617284 + txt002 + SPHERE CENTER -0.376298 -0.00151881 0.750529 RAD 0.00617284 + txt002 + SPHERE CENTER -0.439178 0.0688765 0.766553 RAD 0.0185185 + txt002 + SPHERE CENTER -0.426942 0.0903221 0.766429 RAD 0.00617284 + txt002 + SPHERE CENTER -0.416328 0.0699989 0.757266 RAD 0.00617284 + txt002 + SPHERE CENTER -0.435083 0.0806307 0.745229 RAD 0.00617284 + txt002 + SPHERE CENTER -0.449792 0.0891998 0.775717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.457933 0.0795084 0.754517 RAD 0.00617284 + txt002 + SPHERE CENTER -0.462029 0.0677542 0.775841 RAD 0.00617284 + txt002 + SPHERE CENTER -0.431037 0.078568 0.787754 RAD 0.00617284 + txt002 + SPHERE CENTER -0.443274 0.0571224 0.787878 RAD 0.00617284 + txt002 + SPHERE CENTER -0.420423 0.0582447 0.77859 RAD 0.00617284 + txt002 + SPHERE CENTER -0.512079 -0.00628079 0.769837 RAD 0.0185185 + txt002 + SPHERE CENTER -0.523883 -0.000557006 0.790755 RAD 0.00617284 + txt002 + SPHERE CENTER -0.49924 -0.00208214 0.790506 RAD 0.00617284 + txt002 + SPHERE CENTER -0.51057 0.0165974 0.779001 RAD 0.00617284 + txt002 + SPHERE CENTER -0.536722 -0.00475566 0.770086 RAD 0.00617284 + txt002 + SPHERE CENTER -0.523409 0.0123987 0.758332 RAD 0.00617284 + txt002 + SPHERE CENTER -0.524918 -0.0104794 0.749168 RAD 0.00617284 + txt002 + SPHERE CENTER -0.525392 -0.0234352 0.781591 RAD 0.00617284 + txt002 + SPHERE CENTER -0.513588 -0.029159 0.760673 RAD 0.00617284 + txt002 + SPHERE CENTER -0.500749 -0.0249603 0.781342 RAD 0.00617284 + txt002 + SPHERE CENTER -0.504176 0.0574471 0.732914 RAD 0.0185185 + txt002 + SPHERE CENTER -0.508666 0.0817008 0.734036 RAD 0.00617284 + txt002 + SPHERE CENTER -0.488971 0.0722467 0.745541 RAD 0.00617284 + txt002 + SPHERE CENTER -0.489545 0.0732807 0.720878 RAD 0.00617284 + txt002 + SPHERE CENTER -0.523872 0.0669012 0.72141 RAD 0.00617284 + txt002 + SPHERE CENTER -0.504751 0.058481 0.708251 RAD 0.00617284 + txt002 + SPHERE CENTER -0.519382 0.0426474 0.720288 RAD 0.00617284 + txt002 + SPHERE CENTER -0.523298 0.0658672 0.746073 RAD 0.00617284 + txt002 + SPHERE CENTER -0.518808 0.0416134 0.744951 RAD 0.00617284 + txt002 + SPHERE CENTER -0.503602 0.0564131 0.757577 RAD 0.00617284 + txt002 + SPHERE CENTER -0.516134 -0.00557859 0.695877 RAD 0.0185185 + txt002 + SPHERE CENTER -0.540463 -0.00154892 0.697123 RAD 0.00617284 + txt002 + SPHERE CENTER -0.52751 -0.00538221 0.717791 RAD 0.00617284 + txt002 + SPHERE CENTER -0.524673 0.0156462 0.705165 RAD 0.00617284 + txt002 + SPHERE CENTER -0.529087 -0.00174531 0.675209 RAD 0.00617284 + txt002 + SPHERE CENTER -0.513298 0.0154498 0.683251 RAD 0.00617284 + txt002 + SPHERE CENTER -0.504759 -0.00577498 0.673964 RAD 0.00617284 + txt002 + SPHERE CENTER -0.531924 -0.0227737 0.687835 RAD 0.00617284 + txt002 + SPHERE CENTER -0.507596 -0.0268034 0.68659 RAD 0.00617284 + txt002 + SPHERE CENTER -0.518971 -0.026607 0.708504 RAD 0.00617284 + txt002 + SPHERE CENTER -0.459039 -0.0578769 0.766439 RAD 0.0185185 + txt002 + SPHERE CENTER -0.451803 -0.0707378 0.786236 RAD 0.00617284 + txt002 + SPHERE CENTER -0.435761 -0.0561039 0.774481 RAD 0.00617284 + txt002 + SPHERE CENTER -0.454158 -0.0461991 0.787639 RAD 0.00617284 + txt002 + SPHERE CENTER -0.475081 -0.0725109 0.778193 RAD 0.00617284 + txt002 + SPHERE CENTER -0.477435 -0.0479721 0.779597 RAD 0.00617284 + txt002 + SPHERE CENTER -0.482316 -0.05965 0.758396 RAD 0.00617284 + txt002 + SPHERE CENTER -0.456685 -0.0824157 0.765035 RAD 0.00617284 + txt002 + SPHERE CENTER -0.46392 -0.0695548 0.745238 RAD 0.00617284 + txt002 + SPHERE CENTER -0.440643 -0.0677817 0.753281 RAD 0.00617284 + txt002 + SPHERE CENTER -0.463094 -0.0571747 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER -0.459563 -0.081612 0.692603 RAD 0.00617284 + txt002 + SPHERE CENTER -0.442243 -0.0665888 0.701767 RAD 0.00617284 + txt002 + SPHERE CENTER -0.463589 -0.0696122 0.713804 RAD 0.00617284 + txt002 + SPHERE CENTER -0.480415 -0.0721979 0.683315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.48444 -0.0601982 0.704516 RAD 0.00617284 + txt002 + SPHERE CENTER -0.483946 -0.0477607 0.683192 RAD 0.00617284 + txt002 + SPHERE CENTER -0.459069 -0.0691745 0.671279 RAD 0.00617284 + txt002 + SPHERE CENTER -0.4626 -0.0447373 0.671155 RAD 0.00617284 + txt002 + SPHERE CENTER -0.441749 -0.0541513 0.680442 RAD 0.00617284 + txt002 + SPHERE CENTER -0.398096 -0.0457452 0.726118 RAD 0.0185185 + txt002 + SPHERE CENTER -0.373728 -0.0495643 0.724997 RAD 0.00617284 + txt002 + SPHERE CENTER -0.383722 -0.030137 0.713492 RAD 0.00617284 + txt002 + SPHERE CENTER -0.382672 -0.0306825 0.738155 RAD 0.00617284 + txt002 + SPHERE CENTER -0.388102 -0.0651725 0.737623 RAD 0.00617284 + txt002 + SPHERE CENTER -0.397047 -0.0462908 0.750781 RAD 0.00617284 + txt002 + SPHERE CENTER -0.41247 -0.0613535 0.738744 RAD 0.00617284 + txt002 + SPHERE CENTER -0.389151 -0.064627 0.71296 RAD 0.00617284 + txt002 + SPHERE CENTER -0.41352 -0.060808 0.714081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399146 -0.0451997 0.701455 RAD 0.00617284 + txt002 + SPHERE CENTER -0.4293 -0.115031 0.544331 RAD 0.0555556 + txt002 + SPHERE CENTER -0.424299 -0.178985 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.412497 -0.190929 0.599471 RAD 0.00617284 + txt002 + SPHERE CENTER -0.400273 -0.174844 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER -0.417001 -0.16674 0.601529 RAD 0.00617284 + txt002 + SPHERE CENTER -0.436523 -0.195071 0.595564 RAD 0.00617284 + txt002 + SPHERE CENTER -0.441027 -0.170881 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER -0.448325 -0.183127 0.577461 RAD 0.00617284 + txt002 + SPHERE CENTER -0.419795 -0.203175 0.57931 RAD 0.00617284 + txt002 + SPHERE CENTER -0.431597 -0.191231 0.561208 RAD 0.00617284 + txt002 + SPHERE CENTER -0.407571 -0.18709 0.565115 RAD 0.00617284 + txt002 + SPHERE CENTER -0.367336 -0.131634 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.343834 -0.12515 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER -0.353814 -0.122476 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.360946 -0.107784 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.357357 -0.134308 0.603794 RAD 0.00617284 + txt002 + SPHERE CENTER -0.374468 -0.116942 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.380859 -0.140792 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.350225 -0.149 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER -0.373727 -0.155484 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.360204 -0.146326 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.4293 -0.115031 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.41922 -0.10495 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.40545 -0.10864 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.42291 -0.0911807 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.44307 -0.111341 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.44676 -0.0975713 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.45315 -0.121421 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.425611 -0.128801 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.435691 -0.138881 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.411841 -0.13249 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.486264 -0.162382 0.544331 RAD 0.0185185 + txt002 + SPHERE CENTER -0.502603 -0.174264 0.558526 RAD 0.00617284 + txt002 + SPHERE CENTER -0.479659 -0.170327 0.566757 RAD 0.00617284 + txt002 + SPHERE CENTER -0.495376 -0.15142 0.564491 RAD 0.00617284 + txt002 + SPHERE CENTER -0.509207 -0.166319 0.536101 RAD 0.00617284 + txt002 + SPHERE CENTER -0.501981 -0.143475 0.542066 RAD 0.00617284 + txt002 + SPHERE CENTER -0.492868 -0.154437 0.521905 RAD 0.00617284 + txt002 + SPHERE CENTER -0.49349 -0.185226 0.538366 RAD 0.00617284 + txt002 + SPHERE CENTER -0.477151 -0.173345 0.524171 RAD 0.00617284 + txt002 + SPHERE CENTER -0.470546 -0.18129 0.546597 RAD 0.00617284 + txt002 + SPHERE CENTER -0.491265 -0.0984274 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.501491 -0.082906 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER -0.477742 -0.0892696 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.484874 -0.0745774 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.515014 -0.0920638 0.579103 RAD 0.00617284 + txt002 + SPHERE CENTER -0.498397 -0.0837352 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.504787 -0.107585 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.507882 -0.106756 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER -0.497655 -0.122277 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.484132 -0.11312 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.491265 -0.0984274 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.508376 -0.0810612 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.498397 -0.0837352 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.484874 -0.0745774 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.501244 -0.0957534 0.484868 RAD 0.00617284 + txt002 + SPHERE CENTER -0.477742 -0.0892696 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.484132 -0.11312 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.514767 -0.104911 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.497655 -0.122277 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.504787 -0.107585 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.424299 -0.178985 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.411775 -0.200165 0.505236 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399922 -0.179342 0.511201 RAD 0.00617284 + txt002 + SPHERE CENTER -0.415187 -0.189948 0.527454 RAD 0.00617284 + txt002 + SPHERE CENTER -0.436152 -0.199808 0.501329 RAD 0.00617284 + txt002 + SPHERE CENTER -0.439564 -0.189591 0.523547 RAD 0.00617284 + txt002 + SPHERE CENTER -0.448677 -0.178629 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.420888 -0.189202 0.485076 RAD 0.00617284 + txt002 + SPHERE CENTER -0.433412 -0.168023 0.487134 RAD 0.00617284 + txt002 + SPHERE CENTER -0.409035 -0.168379 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER -0.4293 -0.115031 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER -0.439381 -0.10495 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER -0.45315 -0.10864 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.435691 -0.0911807 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.415531 -0.111341 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER -0.411841 -0.0975713 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.40545 -0.121421 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.43299 -0.128801 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER -0.42291 -0.138881 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.44676 -0.13249 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.367336 -0.131634 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.350719 -0.123305 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER -0.374468 -0.116942 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.360946 -0.107784 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.343587 -0.137998 0.509559 RAD 0.00617284 + txt002 + SPHERE CENTER -0.353814 -0.122476 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.360204 -0.146326 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.357109 -0.147155 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER -0.373727 -0.155484 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.380859 -0.140792 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.248762 -0.0483751 0.655442 RAD 0.0555556 + txt002 + SPHERE CENTER -0.183785 -0.0599222 0.689081 RAD 0.0185185 + txt002 + SPHERE CENTER -0.160406 -0.0522053 0.690965 RAD 0.00617284 + txt002 + SPHERE CENTER -0.171954 -0.0513956 0.669156 RAD 0.00617284 + txt002 + SPHERE CENTER -0.178533 -0.0358698 0.687193 RAD 0.00617284 + txt002 + SPHERE CENTER -0.172236 -0.0607319 0.71089 RAD 0.00617284 + txt002 + SPHERE CENTER -0.190363 -0.0443964 0.707118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.195615 -0.0684488 0.709006 RAD 0.00617284 + txt002 + SPHERE CENTER -0.165658 -0.0762577 0.692853 RAD 0.00617284 + txt002 + SPHERE CENTER -0.189036 -0.0839747 0.690969 RAD 0.00617284 + txt002 + SPHERE CENTER -0.177206 -0.075448 0.671044 RAD 0.00617284 + txt002 + SPHERE CENTER -0.187119 -0.0172857 0.6286 RAD 0.0185185 + txt002 + SPHERE CENTER -0.176731 -0.00705049 0.608675 RAD 0.00617284 + txt002 + SPHERE CENTER -0.192673 -0.025725 0.60607 RAD 0.00617284 + txt002 + SPHERE CENTER -0.200733 -0.00352517 0.613272 RAD 0.00617284 + txt002 + SPHERE CENTER -0.171177 0.00138875 0.631205 RAD 0.00617284 + txt002 + SPHERE CENTER -0.195179 0.00491406 0.635801 RAD 0.00617284 + txt002 + SPHERE CENTER -0.181564 -0.00884647 0.65113 RAD 0.00617284 + txt002 + SPHERE CENTER -0.163117 -0.020811 0.624003 RAD 0.00617284 + txt002 + SPHERE CENTER -0.173504 -0.0310463 0.643928 RAD 0.00617284 + txt002 + SPHERE CENTER -0.179058 -0.0394855 0.621398 RAD 0.00617284 + txt002 + SPHERE CENTER -0.215921 0.00673113 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER -0.20044 0.0258737 0.690591 RAD 0.00617284 + txt002 + SPHERE CENTER -0.196602 0.00551963 0.677151 RAD 0.00617284 + txt002 + SPHERE CENTER -0.215612 0.0203763 0.671903 RAD 0.00617284 + txt002 + SPHERE CENTER -0.21976 0.0270852 0.705919 RAD 0.00617284 + txt002 + SPHERE CENTER -0.234932 0.0215878 0.687231 RAD 0.00617284 + txt002 + SPHERE CENTER -0.235241 0.00794264 0.707807 RAD 0.00617284 + txt002 + SPHERE CENTER -0.200749 0.0122285 0.711167 RAD 0.00617284 + txt002 + SPHERE CENTER -0.21623 -0.00691403 0.713055 RAD 0.00617284 + txt002 + SPHERE CENTER -0.196911 -0.00812553 0.697727 RAD 0.00617284 + txt002 + SPHERE CENTER -0.245428 -0.0910116 0.715923 RAD 0.0185185 + txt002 + SPHERE CENTER -0.234308 -0.0942304 0.737733 RAD 0.00617284 + txt002 + SPHERE CENTER -0.221514 -0.0854464 0.718528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.238704 -0.0714204 0.729364 RAD 0.00617284 + txt002 + SPHERE CENTER -0.258223 -0.0997955 0.735128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.262619 -0.0769856 0.726759 RAD 0.00617284 + txt002 + SPHERE CENTER -0.269343 -0.0965768 0.713318 RAD 0.00617284 + txt002 + SPHERE CENTER -0.241032 -0.113822 0.724292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.252152 -0.110603 0.702483 RAD 0.00617284 + txt002 + SPHERE CENTER -0.228237 -0.105038 0.705088 RAD 0.00617284 + txt002 + SPHERE CENTER -0.277564 -0.0243582 0.719322 RAD 0.0185185 + txt002 + SPHERE CENTER -0.275459 -0.0076281 0.737359 RAD 0.00617284 + txt002 + SPHERE CENTER -0.255218 -0.0167139 0.726523 RAD 0.00617284 + txt002 + SPHERE CENTER -0.270078 -0.00142185 0.714074 RAD 0.00617284 + txt002 + SPHERE CENTER -0.297806 -0.0152725 0.730157 RAD 0.00617284 + txt002 + SPHERE CENTER -0.292425 -0.00906621 0.706872 RAD 0.00617284 + txt002 + SPHERE CENTER -0.299911 -0.0320026 0.71212 RAD 0.00617284 + txt002 + SPHERE CENTER -0.282946 -0.0305645 0.742607 RAD 0.00617284 + txt002 + SPHERE CENTER -0.285051 -0.0472946 0.72457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.262704 -0.0396503 0.731771 RAD 0.00617284 + txt002 + SPHERE CENTER -0.310405 -0.0794645 0.682285 RAD 0.0185185 + txt002 + SPHERE CENTER -0.324811 -0.0817333 0.702209 RAD 0.00617284 + txt002 + SPHERE CENTER -0.300317 -0.0800146 0.704814 RAD 0.00617284 + txt002 + SPHERE CENTER -0.313378 -0.0603366 0.697613 RAD 0.00617284 + txt002 + SPHERE CENTER -0.334899 -0.0811832 0.67968 RAD 0.00617284 + txt002 + SPHERE CENTER -0.323466 -0.0597864 0.675083 RAD 0.00617284 + txt002 + SPHERE CENTER -0.320493 -0.0789143 0.659755 RAD 0.00617284 + txt002 + SPHERE CENTER -0.321838 -0.100861 0.686881 RAD 0.00617284 + txt002 + SPHERE CENTER -0.307433 -0.0985923 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER -0.297345 -0.0991425 0.689486 RAD 0.00617284 + txt002 + SPHERE CENTER -0.216626 -0.115028 0.652044 RAD 0.0185185 + txt002 + SPHERE CENTER -0.195663 -0.127519 0.655816 RAD 0.00617284 + txt002 + SPHERE CENTER -0.194866 -0.104303 0.647447 RAD 0.00617284 + txt002 + SPHERE CENTER -0.201738 -0.108803 0.670732 RAD 0.00617284 + txt002 + SPHERE CENTER -0.217423 -0.138245 0.660413 RAD 0.00617284 + txt002 + SPHERE CENTER -0.223497 -0.119529 0.675329 RAD 0.00617284 + txt002 + SPHERE CENTER -0.238386 -0.125754 0.656641 RAD 0.00617284 + txt002 + SPHERE CENTER -0.210551 -0.133744 0.637128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.231514 -0.121254 0.633356 RAD 0.00617284 + txt002 + SPHERE CENTER -0.209754 -0.110528 0.628759 RAD 0.00617284 + txt002 + SPHERE CENTER -0.281603 -0.103481 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.291073 -0.126206 0.620293 RAD 0.00617284 + txt002 + SPHERE CENTER -0.271345 -0.119897 0.633733 RAD 0.00617284 + txt002 + SPHERE CENTER -0.293457 -0.110246 0.638981 RAD 0.00617284 + txt002 + SPHERE CENTER -0.301332 -0.10979 0.604965 RAD 0.00617284 + txt002 + SPHERE CENTER -0.303716 -0.0938302 0.623653 RAD 0.00617284 + txt002 + SPHERE CENTER -0.291862 -0.0870656 0.603077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.279219 -0.119442 0.599717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.269749 -0.0967168 0.597829 RAD 0.00617284 + txt002 + SPHERE CENTER -0.25949 -0.113132 0.613157 RAD 0.00617284 + txt002 + SPHERE CENTER -0.21996 -0.0723919 0.591563 RAD 0.0185185 + txt002 + SPHERE CENTER -0.20388 -0.0673141 0.573526 RAD 0.00617284 + txt002 + SPHERE CENTER -0.216456 -0.0490355 0.584361 RAD 0.00617284 + txt002 + SPHERE CENTER -0.198742 -0.0609052 0.596811 RAD 0.00617284 + txt002 + SPHERE CENTER -0.207384 -0.0906706 0.580727 RAD 0.00617284 + txt002 + SPHERE CENTER -0.202246 -0.0842617 0.604012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.223463 -0.0957484 0.598764 RAD 0.00617284 + txt002 + SPHERE CENTER -0.225098 -0.0788008 0.568278 RAD 0.00617284 + txt002 + SPHERE CENTER -0.241177 -0.0838786 0.586315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.237674 -0.0605222 0.579113 RAD 0.00617284 + txt002 + SPHERE CENTER -0.471405 0.471405 1.11022e-16 RAD 0.166667 + txt002 + SPHERE CENTER -0.508983 0.690426 8.51251e-17 RAD 0.0555556 + txt002 + SPHERE CENTER -0.484794 0.755941 -0.0246914 RAD 0.0185185 + txt002 + SPHERE CENTER -0.47411 0.767658 -0.0436186 RAD 0.00617284 + txt002 + SPHERE CENTER -0.467528 0.744501 -0.0381316 RAD 0.00617284 + txt002 + SPHERE CENTER -0.489758 0.749038 -0.0478724 RAD 0.00617284 + txt002 + SPHERE CENTER -0.491377 0.779098 -0.0301783 RAD 0.00617284 + txt002 + SPHERE CENTER -0.507025 0.760478 -0.0344321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.502061 0.767382 -0.0112511 RAD 0.00617284 + txt002 + SPHERE CENTER -0.469146 0.774562 -0.0204376 RAD 0.00617284 + txt002 + SPHERE CENTER -0.47983 0.762845 -0.00151032 RAD 0.00617284 + txt002 + SPHERE CENTER -0.462564 0.751405 -0.0149506 RAD 0.00617284 + txt002 + SPHERE CENTER -0.436283 0.7029 -0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER -0.418941 0.714226 -0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER -0.43889 0.704751 -0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.44101 0.724842 -0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.416335 0.712374 0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER -0.438403 0.722991 0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER -0.433677 0.701048 0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER -0.414215 0.692283 -0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER -0.431557 0.680957 0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434163 0.682808 -0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER -0.478434 0.695668 -0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER -0.481931 0.703418 -0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER -0.500827 0.694124 -0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER -0.491475 0.716184 -0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER -0.459538 0.704962 -0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER -0.469082 0.717727 -0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.456041 0.697211 -0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER -0.46889 0.682902 -0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER -0.465393 0.675152 -0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER -0.487786 0.673608 -0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER -0.557494 0.743468 -0.0178949 RAD 0.0185185 + txt002 + SPHERE CENTER -0.560084 0.767402 -0.0233819 RAD 0.00617284 + txt002 + SPHERE CENTER -0.543179 0.760285 -0.00685171 RAD 0.00617284 + txt002 + SPHERE CENTER -0.53997 0.755145 -0.0307879 RAD 0.00617284 + txt002 + SPHERE CENTER -0.574398 0.750585 -0.0344251 RAD 0.00617284 + txt002 + SPHERE CENTER -0.554284 0.738328 -0.0418311 RAD 0.00617284 + txt002 + SPHERE CENTER -0.571808 0.726651 -0.0289382 RAD 0.00617284 + txt002 + SPHERE CENTER -0.577608 0.755725 -0.0104889 RAD 0.00617284 + txt002 + SPHERE CENTER -0.575017 0.731791 -0.00500196 RAD 0.00617284 + txt002 + SPHERE CENTER -0.560703 0.748608 0.00604126 RAD 0.00617284 + txt002 + SPHERE CENTER -0.551134 0.683194 -0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER -0.573364 0.687731 -0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.571303 0.682033 -0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER -0.56324 0.703871 -0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER -0.553195 0.688893 -0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER -0.543071 0.705033 -0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER -0.530964 0.684356 -0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER -0.561258 0.667055 -0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER -0.539027 0.662518 -0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER -0.559196 0.661356 -0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER -0.581682 0.677953 0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER -0.601808 0.682851 0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER -0.579842 0.680568 0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.58454 0.700216 0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.603648 0.680237 -0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER -0.58638 0.697602 -0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER -0.583522 0.675339 -0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER -0.59895 0.660588 0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER -0.578824 0.65569 -0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.576984 0.658304 0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER -0.515343 0.7507 0.0425863 RAD 0.0185185 + txt002 + SPHERE CENTER -0.506594 0.773394 0.0468401 RAD 0.00617284 + txt002 + SPHERE CENTER -0.491321 0.755462 0.0394341 RAD 0.00617284 + txt002 + SPHERE CENTER -0.507924 0.764807 0.0237283 RAD 0.00617284 + txt002 + SPHERE CENTER -0.530616 0.768632 0.0499923 RAD 0.00617284 + txt002 + SPHERE CENTER -0.531946 0.760045 0.0268805 RAD 0.00617284 + txt002 + SPHERE CENTER -0.539365 0.745938 0.0457385 RAD 0.00617284 + txt002 + SPHERE CENTER -0.514012 0.759287 0.065698 RAD 0.00617284 + txt002 + SPHERE CENTER -0.522762 0.736593 0.0614442 RAD 0.00617284 + txt002 + SPHERE CENTER -0.49874 0.741355 0.058292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.539531 0.685185 0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER -0.538818 0.693658 0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER -0.517905 0.691194 0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER -0.534075 0.708875 0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER -0.560445 0.687649 0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555702 0.702866 0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.561158 0.679176 0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER -0.544274 0.669969 0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER -0.544988 0.661495 0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER -0.523361 0.667505 0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER -0.466832 0.697658 0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER -0.447385 0.709346 0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.447429 0.703286 0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER -0.46231 0.721188 0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER -0.466788 0.703718 0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER -0.481713 0.71556 0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER -0.486235 0.692031 0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER -0.451907 0.685816 0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER -0.471354 0.674129 0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER -0.451951 0.679757 0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER -0.335322 0.607487 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.283164 0.659645 0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER -0.269894 0.672915 0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER -0.275822 0.649528 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.293281 0.666987 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.277236 0.683032 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.300624 0.677104 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.290507 0.669762 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.259777 0.665573 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.273047 0.652302 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.265705 0.642185 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.286452 0.603979 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.279361 0.614273 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.303327 0.613293 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.288206 0.628413 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.262487 0.604959 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.271332 0.619099 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.269578 0.594664 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.277607 0.589839 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.284698 0.579544 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.301572 0.588858 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.33883 0.656357 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.328536 0.663448 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.314396 0.654603 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.329516 0.639482 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.35297 0.665202 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.353951 0.641237 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.363265 0.658111 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.33785 0.680322 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.348145 0.673232 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.32371 0.671477 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.332034 0.663153 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.321274 0.684748 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.308341 0.666888 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.326131 0.678752 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.344967 0.681014 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.349824 0.675018 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.355727 0.659419 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.327177 0.669149 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.337937 0.647554 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.314244 0.651289 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.3877 0.659866 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.391875 0.684201 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37258 0.674986 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37258 0.674986 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.406996 0.669081 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.3877 0.659866 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.40282 0.644745 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.406996 0.669081 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.40282 0.644745 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.3877 0.659866 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.384191 0.610996 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.389739 0.622198 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.366159 0.617804 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.378964 0.63493 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.407771 0.61539 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.396997 0.628121 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.402224 0.604188 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.394966 0.598265 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.389418 0.587062 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.371386 0.593871 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.279656 0.610775 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.258061 0.621535 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.264057 0.616678 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.275921 0.634468 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.27366 0.615632 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.29152 0.628565 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.295255 0.604872 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.261795 0.597842 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.28339 0.587082 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.267791 0.592985 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.331813 0.558618 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.320611 0.55307 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.30788 0.563845 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.325005 0.57665 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.344544 0.547843 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.348938 0.571423 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.355747 0.553391 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.327419 0.535038 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.338621 0.540585 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.314688 0.545813 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.282943 0.555109 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.258608 0.550934 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.267823 0.570229 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.267823 0.570229 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.273728 0.535813 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.282943 0.555109 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.298064 0.539989 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.273728 0.535813 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.298064 0.539989 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.282943 0.555109 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.335322 0.607487 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.313405 0.629404 -0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.316595 0.626214 -0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.318408 0.606941 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.335868 0.624401 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.311592 0.648676 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.330864 0.646863 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.308402 0.651867 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.294133 0.631217 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.290942 0.634407 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.295946 0.611945 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.331813 0.558618 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.319608 0.539107 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.307378 0.556863 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.322499 0.541743 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.344043 0.540862 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.346933 0.543497 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.356248 0.560372 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.328923 0.555982 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.341128 0.575492 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.316693 0.573738 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.384191 0.610996 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.403702 0.623201 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.401066 0.62031 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.385946 0.635431 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.386827 0.613886 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.369071 0.626116 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.367317 0.601681 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.401947 0.598766 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.382437 0.586561 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399312 0.595876 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.316914 0.678274 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.305407 0.69384 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.296616 0.671002 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.317721 0.674446 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.325704 0.701111 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.338018 0.681717 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.337211 0.685545 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.3046 0.697667 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.316107 0.682101 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.295809 0.67483 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.3877 0.659866 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.391875 0.684201 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37258 0.674986 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37258 0.674986 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.406996 0.669081 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.3877 0.659866 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.40282 0.644745 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.406996 0.669081 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.40282 0.644745 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.3877 0.659866 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.33883 0.656357 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.329538 0.677411 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.314897 0.661584 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.332022 0.674389 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.353472 0.672184 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.355956 0.669162 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.362764 0.65113 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.336346 0.659378 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.345639 0.638325 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.321705 0.643552 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.264535 0.625895 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.248969 0.637402 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.268363 0.625088 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.271807 0.646193 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.245142 0.638209 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.267979 0.647 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.260708 0.626702 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.241698 0.617105 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.257264 0.605598 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.261092 0.604791 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.286452 0.603979 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.265398 0.613271 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.26842 0.610787 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.281225 0.627912 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.283431 0.606463 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.299257 0.621104 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.304484 0.59717 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.270625 0.589337 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.291679 0.580045 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.273647 0.586853 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.282943 0.555109 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.258608 0.550934 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.267823 0.570229 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.267823 0.570229 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.273728 0.535813 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.282943 0.555109 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.298064 0.539989 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.273728 0.535813 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.298064 0.539989 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.282943 0.555109 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.645066 0.554344 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.681385 0.616373 -0.129006 RAD 0.0185185 + txt002 + SPHERE CENTER -0.678928 0.639472 -0.137375 RAD 0.00617284 + txt002 + SPHERE CENTER -0.661636 0.629767 -0.122663 RAD 0.00617284 + txt002 + SPHERE CENTER -0.664108 0.621631 -0.145845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.698678 0.626079 -0.143718 RAD 0.00617284 + txt002 + SPHERE CENTER -0.683858 0.608237 -0.152187 RAD 0.00617284 + txt002 + SPHERE CENTER -0.701135 0.602979 -0.135349 RAD 0.00617284 + txt002 + SPHERE CENTER -0.696205 0.634214 -0.120537 RAD 0.00617284 + txt002 + SPHERE CENTER -0.698662 0.611115 -0.112168 RAD 0.00617284 + txt002 + SPHERE CENTER -0.678912 0.624508 -0.105825 RAD 0.00617284 + txt002 + SPHERE CENTER -0.649723 0.609912 -0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER -0.640648 0.631982 -0.0560094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.625749 0.614812 -0.0656463 RAD 0.00617284 + txt002 + SPHERE CENTER -0.64267 0.62585 -0.0798417 RAD 0.00617284 + txt002 + SPHERE CENTER -0.664623 0.627081 -0.0527151 RAD 0.00617284 + txt002 + SPHERE CENTER -0.666645 0.620949 -0.0765474 RAD 0.00617284 + txt002 + SPHERE CENTER -0.673698 0.605012 -0.0590577 RAD 0.00617284 + txt002 + SPHERE CENTER -0.647702 0.616044 -0.0385197 RAD 0.00617284 + txt002 + SPHERE CENTER -0.656777 0.593974 -0.0448623 RAD 0.00617284 + txt002 + SPHERE CENTER -0.632802 0.598874 -0.0481565 RAD 0.00617284 + txt002 + SPHERE CENTER -0.607573 0.617144 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.595495 0.63057 -0.139672 RAD 0.00617284 + txt002 + SPHERE CENTER -0.594239 0.605919 -0.140323 RAD 0.00617284 + txt002 + SPHERE CENTER -0.615286 0.617371 -0.146288 RAD 0.00617284 + txt002 + SPHERE CENTER -0.608828 0.641795 -0.122182 RAD 0.00617284 + txt002 + SPHERE CENTER -0.628619 0.628595 -0.128798 RAD 0.00617284 + txt002 + SPHERE CENTER -0.620906 0.628369 -0.105343 RAD 0.00617284 + txt002 + SPHERE CENTER -0.587782 0.630343 -0.116217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.59986 0.616917 -0.0993785 RAD 0.00617284 + txt002 + SPHERE CENTER -0.586526 0.605692 -0.116868 RAD 0.00617284 + txt002 + SPHERE CENTER -0.676727 0.560805 -0.177765 RAD 0.0185185 + txt002 + SPHERE CENTER -0.689897 0.57563 -0.192477 RAD 0.00617284 + txt002 + SPHERE CENTER -0.693998 0.575587 -0.168128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.673115 0.585222 -0.177114 RAD 0.00617284 + txt002 + SPHERE CENTER -0.672626 0.560848 -0.202114 RAD 0.00617284 + txt002 + SPHERE CENTER -0.655844 0.57044 -0.186751 RAD 0.00617284 + txt002 + SPHERE CENTER -0.659456 0.546023 -0.187402 RAD 0.00617284 + txt002 + SPHERE CENTER -0.693509 0.551213 -0.193128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.680339 0.536388 -0.178416 RAD 0.00617284 + txt002 + SPHERE CENTER -0.69761 0.55117 -0.16878 RAD 0.00617284 + txt002 + SPHERE CENTER -0.602915 0.561576 -0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER -0.602201 0.570049 -0.194773 RAD 0.00617284 + txt002 + SPHERE CENTER -0.623084 0.560414 -0.185788 RAD 0.00617284 + txt002 + SPHERE CENTER -0.615021 0.582252 -0.177557 RAD 0.00617284 + txt002 + SPHERE CENTER -0.582032 0.571211 -0.180578 RAD 0.00617284 + txt002 + SPHERE CENTER -0.594852 0.583414 -0.163362 RAD 0.00617284 + txt002 + SPHERE CENTER -0.582745 0.562738 -0.157397 RAD 0.00617284 + txt002 + SPHERE CENTER -0.590095 0.549372 -0.188808 RAD 0.00617284 + txt002 + SPHERE CENTER -0.590808 0.540899 -0.165627 RAD 0.00617284 + txt002 + SPHERE CENTER -0.610978 0.539737 -0.179823 RAD 0.00617284 + txt002 + SPHERE CENTER -0.640408 0.498776 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.627785 0.478525 -0.166213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.615951 0.497935 -0.156576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.630799 0.484234 -0.142381 RAD 0.00617284 + txt002 + SPHERE CENTER -0.652241 0.479365 -0.169507 RAD 0.00617284 + txt002 + SPHERE CENTER -0.655255 0.485075 -0.145675 RAD 0.00617284 + txt002 + SPHERE CENTER -0.664864 0.499616 -0.163165 RAD 0.00617284 + txt002 + SPHERE CENTER -0.637394 0.493066 -0.183703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.650016 0.513317 -0.17736 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62556 0.512476 -0.174066 RAD 0.00617284 + txt002 + SPHERE CENTER -0.718878 0.553573 -0.117284 RAD 0.0185185 + txt002 + SPHERE CENTER -0.73992 0.563328 -0.108814 RAD 0.00617284 + txt002 + SPHERE CENTER -0.720935 0.559693 -0.0934517 RAD 0.00617284 + txt002 + SPHERE CENTER -0.719679 0.577348 -0.110668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.737863 0.557208 -0.132647 RAD 0.00617284 + txt002 + SPHERE CENTER -0.717623 0.571228 -0.1345 RAD 0.00617284 + txt002 + SPHERE CENTER -0.716821 0.547453 -0.141116 RAD 0.00617284 + txt002 + SPHERE CENTER -0.739118 0.539553 -0.115431 RAD 0.00617284 + txt002 + SPHERE CENTER -0.718076 0.529798 -0.1239 RAD 0.00617284 + txt002 + SPHERE CENTER -0.720133 0.535918 -0.100068 RAD 0.00617284 + txt002 + SPHERE CENTER -0.682558 0.491544 -0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.688647 0.474542 -0.0825505 RAD 0.00617284 + txt002 + SPHERE CENTER -0.666351 0.485132 -0.0818993 RAD 0.00617284 + txt002 + SPHERE CENTER -0.686417 0.498226 -0.0759343 RAD 0.00617284 + txt002 + SPHERE CENTER -0.704854 0.480953 -0.10004 RAD 0.00617284 + txt002 + SPHERE CENTER -0.702624 0.504637 -0.093424 RAD 0.00617284 + txt002 + SPHERE CENTER -0.698765 0.497955 -0.116879 RAD 0.00617284 + txt002 + SPHERE CENTER -0.684788 0.46786 -0.106005 RAD 0.00617284 + txt002 + SPHERE CENTER -0.678699 0.484862 -0.122844 RAD 0.00617284 + txt002 + SPHERE CENTER -0.662492 0.47845 -0.105354 RAD 0.00617284 + txt002 + SPHERE CENTER -0.687216 0.547112 -0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER -0.690713 0.554862 -0.0274488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.667813 0.552739 -0.0364345 RAD 0.00617284 + txt002 + SPHERE CENTER -0.682694 0.570641 -0.0446649 RAD 0.00617284 + txt002 + SPHERE CENTER -0.710116 0.549235 -0.0416443 RAD 0.00617284 + txt002 + SPHERE CENTER -0.702097 0.565014 -0.0588603 RAD 0.00617284 + txt002 + SPHERE CENTER -0.706619 0.541484 -0.0648253 RAD 0.00617284 + txt002 + SPHERE CENTER -0.695235 0.531333 -0.0334138 RAD 0.00617284 + txt002 + SPHERE CENTER -0.691738 0.523582 -0.0565949 RAD 0.00617284 + txt002 + SPHERE CENTER -0.672335 0.52921 -0.0423994 RAD 0.00617284 + txt002 + SPHERE CENTER -0.471405 0.471405 -0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER -0.501645 0.501645 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.499795 0.519956 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.493653 0.523893 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.479397 0.509638 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.507788 0.497708 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.48739 0.48739 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER -0.509638 0.479397 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.522043 0.511963 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER -0.523893 0.493653 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.515901 0.515901 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER -0.542955 0.490576 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.559233 0.507719 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.539759 0.502501 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.536564 0.514426 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.562428 0.495794 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER -0.539759 0.502501 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.54615 0.478651 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.565623 0.483869 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.549345 0.466726 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.54615 0.478651 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.490576 0.542955 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.483869 0.565623 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.466726 0.549345 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.478651 0.54615 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.507719 0.559233 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.502501 0.539759 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.514426 0.536564 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.495794 0.562428 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.502501 0.539759 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.478651 0.54615 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.430095 0.482473 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.430434 0.489762 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.449569 0.477255 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER -0.445366 0.500519 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.41096 0.49498 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER -0.425893 0.505737 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.410622 0.487691 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER -0.415162 0.471716 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.414824 0.464428 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434297 0.45921 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.419026 0.523783 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.404771 0.538038 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER -0.410297 0.515053 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.427756 0.532513 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.4135 0.546768 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.436486 0.541242 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.427756 0.532513 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.396041 0.529309 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.410297 0.515053 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.401567 0.506323 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399854 0.452233 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.377186 0.45894 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.396659 0.464158 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.393464 0.476083 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.380381 0.447015 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.396659 0.464158 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.40305 0.440308 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.383576 0.43509 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.406245 0.428383 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.40305 0.440308 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.482473 0.430095 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.48121 0.407271 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER -0.464428 0.414824 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.487691 0.410622 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER -0.499256 0.422542 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.505737 0.425893 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.500519 0.445366 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.475992 0.426744 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.477255 0.449569 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER -0.45921 0.434297 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.452233 0.399854 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.43509 0.383576 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.428383 0.406245 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.440308 0.40305 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.45894 0.377186 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.464158 0.396659 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.476083 0.393464 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.447015 0.380381 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER -0.464158 0.396659 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.440308 0.40305 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.523783 0.419026 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.538038 0.404771 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.515053 0.410297 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.532513 0.427756 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.546768 0.4135 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.541242 0.436486 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.532513 0.427756 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.529309 0.396041 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.515053 0.410297 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.506323 0.401567 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.607487 0.335322 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.659645 0.283164 -0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER -0.672915 0.269894 -0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER -0.649528 0.275822 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.666987 0.293281 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.683032 0.277236 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.677104 0.300624 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.669762 0.290507 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.665573 0.259777 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.652302 0.273047 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.642185 0.265705 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.603979 0.286452 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.592776 0.280905 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.580045 0.291679 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.59717 0.304484 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.61671 0.275678 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.621104 0.299257 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.627912 0.281225 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.599585 0.262872 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.610787 0.26842 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.586853 0.273647 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.656357 0.33883 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.661904 0.350033 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.638325 0.345639 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.65113 0.362764 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.679937 0.343224 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.669162 0.355956 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.674389 0.332022 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.667131 0.326099 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.661584 0.314897 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.643552 0.321705 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.663153 0.332034 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.685865 0.340177 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.679339 0.33606 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.669651 0.355123 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.669679 0.336151 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.653465 0.351097 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.646968 0.328008 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.679367 0.317089 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.656656 0.308945 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.672841 0.312971 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.659866 0.3877 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.664041 0.412036 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.644745 0.40282 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.644745 0.40282 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.679161 0.396915 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.659866 0.3877 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.674986 0.37258 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.679161 0.396915 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.674986 0.37258 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.659866 0.3877 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.610996 0.384191 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.600701 0.391282 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.586561 0.382437 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.601681 0.367317 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.625136 0.393037 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.626116 0.369071 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.635431 0.385946 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.610016 0.408157 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62031 0.401066 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.595876 0.399312 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.610775 0.279656 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.602632 0.256944 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.587686 0.273158 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.606749 0.26347 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62572 0.263442 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.629838 0.269968 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.633864 0.286153 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.606658 0.27313 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.614801 0.295841 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.591712 0.289344 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.558618 0.331813 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.551527 0.342108 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.575492 0.341128 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.560372 0.356248 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.534652 0.332793 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.543497 0.346933 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.541743 0.322499 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.549772 0.317673 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.556863 0.307378 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.573738 0.316693 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555109 0.282943 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.530773 0.278768 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.539989 0.298064 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.539989 0.298064 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.545894 0.263648 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555109 0.282943 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.570229 0.267823 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.545894 0.263648 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.570229 0.267823 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555109 0.282943 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.645066 0.554344 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.668521 0.610229 0.153697 RAD 0.0185185 + txt002 + SPHERE CENTER -0.663938 0.633406 0.160875 RAD 0.00617284 + txt002 + SPHERE CENTER -0.64522 0.617928 0.156428 RAD 0.00617284 + txt002 + SPHERE CENTER -0.65892 0.626429 0.137727 RAD 0.00617284 + txt002 + SPHERE CENTER -0.687239 0.625707 0.158144 RAD 0.00617284 + txt002 + SPHERE CENTER -0.682221 0.61873 0.134996 RAD 0.00617284 + txt002 + SPHERE CENTER -0.691822 0.602531 0.150967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.673539 0.617206 0.176845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.678123 0.59403 0.169668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.654822 0.601728 0.172398 RAD 0.00617284 + txt002 + SPHERE CENTER -0.598918 0.585648 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.580238 0.601562 0.162601 RAD 0.00617284 + txt002 + SPHERE CENTER -0.581665 0.587563 0.142311 RAD 0.00617284 + txt002 + SPHERE CENTER -0.59781 0.605914 0.14581 RAD 0.00617284 + txt002 + SPHERE CENTER -0.597491 0.599646 0.18016 RAD 0.00617284 + txt002 + SPHERE CENTER -0.615063 0.603999 0.163369 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616171 0.583732 0.177429 RAD 0.00617284 + txt002 + SPHERE CENTER -0.581346 0.581295 0.176661 RAD 0.00617284 + txt002 + SPHERE CENTER -0.600026 0.565381 0.173931 RAD 0.00617284 + txt002 + SPHERE CENTER -0.582773 0.567297 0.156372 RAD 0.00617284 + txt002 + SPHERE CENTER -0.619787 0.622977 0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.608008 0.63767 0.0834188 RAD 0.00617284 + txt002 + SPHERE CENTER -0.601637 0.613891 0.0853287 RAD 0.00617284 + txt002 + SPHERE CENTER -0.623239 0.620102 0.0751099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.626157 0.646756 0.0974792 RAD 0.00617284 + txt002 + SPHERE CENTER -0.641389 0.629188 0.0891702 RAD 0.00617284 + txt002 + SPHERE CENTER -0.637936 0.632063 0.113449 RAD 0.00617284 + txt002 + SPHERE CENTER -0.604555 0.640545 0.107698 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616334 0.625852 0.123668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.598184 0.616766 0.109608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.714669 0.578925 0.104938 RAD 0.0185185 + txt002 + SPHERE CENTER -0.729812 0.597914 0.109385 RAD 0.00617284 + txt002 + SPHERE CENTER -0.711617 0.592661 0.125228 RAD 0.00617284 + txt002 + SPHERE CENTER -0.70632 0.602084 0.103028 RAD 0.00617284 + txt002 + SPHERE CENTER -0.732864 0.584178 0.0890951 RAD 0.00617284 + txt002 + SPHERE CENTER -0.709372 0.588348 0.0827387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.71772 0.565189 0.0846485 RAD 0.00617284 + txt002 + SPHERE CENTER -0.738161 0.574755 0.111295 RAD 0.00617284 + txt002 + SPHERE CENTER -0.723017 0.555767 0.106848 RAD 0.00617284 + txt002 + SPHERE CENTER -0.719965 0.569503 0.127138 RAD 0.00617284 + txt002 + SPHERE CENTER -0.665934 0.591673 0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER -0.658095 0.605761 0.0319289 RAD 0.00617284 + txt002 + SPHERE CENTER -0.647455 0.607672 0.0541285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.643855 0.58746 0.0404111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.676573 0.589763 0.0284303 RAD 0.00617284 + txt002 + SPHERE CENTER -0.662334 0.571461 0.0369125 RAD 0.00617284 + txt002 + SPHERE CENTER -0.684413 0.575674 0.0471312 RAD 0.00617284 + txt002 + SPHERE CENTER -0.680174 0.609975 0.0421477 RAD 0.00617284 + txt002 + SPHERE CENTER -0.688013 0.595887 0.0608487 RAD 0.00617284 + txt002 + SPHERE CENTER -0.669535 0.611885 0.0643473 RAD 0.00617284 + txt002 + SPHERE CENTER -0.691213 0.52304 0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER -0.712906 0.511567 0.0596212 RAD 0.00617284 + txt002 + SPHERE CENTER -0.699372 0.507717 0.079911 RAD 0.00617284 + txt002 + SPHERE CENTER -0.710453 0.529503 0.0764123 RAD 0.00617284 + txt002 + SPHERE CENTER -0.704747 0.526889 0.0420622 RAD 0.00617284 + txt002 + SPHERE CENTER -0.702295 0.544826 0.0588533 RAD 0.00617284 + txt002 + SPHERE CENTER -0.683054 0.538362 0.044793 RAD 0.00617284 + txt002 + SPHERE CENTER -0.693665 0.505104 0.0455609 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671972 0.516576 0.0482916 RAD 0.00617284 + txt002 + SPHERE CENTER -0.680131 0.501254 0.0658506 RAD 0.00617284 + txt002 + SPHERE CENTER -0.6938 0.541596 0.165419 RAD 0.0185185 + txt002 + SPHERE CENTER -0.70016 0.547376 0.188567 RAD 0.00617284 + txt002 + SPHERE CENTER -0.676324 0.546319 0.182211 RAD 0.00617284 + txt002 + SPHERE CENTER -0.690564 0.564621 0.173728 RAD 0.00617284 + txt002 + SPHERE CENTER -0.717636 0.542652 0.171776 RAD 0.00617284 + txt002 + SPHERE CENTER -0.70804 0.559898 0.156937 RAD 0.00617284 + txt002 + SPHERE CENTER -0.711276 0.536873 0.148628 RAD 0.00617284 + txt002 + SPHERE CENTER -0.703396 0.524351 0.180258 RAD 0.00617284 + txt002 + SPHERE CENTER -0.697037 0.518571 0.157111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.679561 0.523294 0.173902 RAD 0.00617284 + txt002 + SPHERE CENTER -0.670344 0.48571 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.67091 0.466887 0.138803 RAD 0.00617284 + txt002 + SPHERE CENTER -0.650637 0.480853 0.136894 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671107 0.490138 0.147112 RAD 0.00617284 + txt002 + SPHERE CENTER -0.690617 0.471745 0.124743 RAD 0.00617284 + txt002 + SPHERE CENTER -0.690815 0.494995 0.133052 RAD 0.00617284 + txt002 + SPHERE CENTER -0.690052 0.490567 0.108773 RAD 0.00617284 + txt002 + SPHERE CENTER -0.670147 0.46246 0.114524 RAD 0.00617284 + txt002 + SPHERE CENTER -0.669581 0.481283 0.0985541 RAD 0.00617284 + txt002 + SPHERE CENTER -0.649874 0.476425 0.112614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624197 0.517014 0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER -0.60809 0.516313 0.190293 RAD 0.00617284 + txt002 + SPHERE CENTER -0.60089 0.524375 0.168094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616221 0.538029 0.181811 RAD 0.00617284 + txt002 + SPHERE CENTER -0.631397 0.508952 0.193792 RAD 0.00617284 + txt002 + SPHERE CENTER -0.639529 0.530668 0.18531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.647504 0.509653 0.175091 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616065 0.495298 0.180075 RAD 0.00617284 + txt002 + SPHERE CENTER -0.632172 0.495999 0.161374 RAD 0.00617284 + txt002 + SPHERE CENTER -0.608865 0.50336 0.157875 RAD 0.00617284 + txt002 + SPHERE CENTER -0.607487 0.335322 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.629404 0.313405 0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.626214 0.316595 0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.606941 0.318408 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624401 0.335868 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.648676 0.311592 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.646863 0.330864 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.651867 0.308402 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.631217 0.294133 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.634407 0.290942 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.611945 0.295946 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.558618 0.331813 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.537564 0.341105 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.540585 0.338621 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.553391 0.355747 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555596 0.334297 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.571423 0.348938 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.57665 0.325005 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.542791 0.317172 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.563845 0.30788 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.545813 0.314688 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.610996 0.384191 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.601704 0.405245 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.587062 0.389418 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.604188 0.402224 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.625637 0.400018 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.628121 0.396997 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.63493 0.378964 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.608512 0.387213 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.617804 0.366159 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.593871 0.371386 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.678274 0.316914 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.697473 0.31938 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.674538 0.318074 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.681812 0.338182 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.701209 0.31822 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.685547 0.337022 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.682009 0.315754 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.693935 0.298112 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.674736 0.295646 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671 0.296805 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.659866 0.3877 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.664041 0.412036 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.644745 0.40282 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.644745 0.40282 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.679161 0.396915 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.659866 0.3877 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.674986 0.37258 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.679161 0.396915 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.674986 0.37258 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.659866 0.3877 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.656357 0.33883 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.675867 0.351035 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.673232 0.348145 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.658111 0.363265 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.658993 0.341721 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.641237 0.353951 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.639482 0.329516 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.674113 0.3266 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.654603 0.314396 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671477 0.32371 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.625895 0.264535 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.623429 0.245336 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.604627 0.260997 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624736 0.268271 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.644697 0.248874 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.646004 0.271809 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.647163 0.268073 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624589 0.2416 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.627055 0.2608 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.605787 0.257262 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.603979 0.286452 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.591774 0.266942 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.579544 0.284698 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.594664 0.269578 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616209 0.268696 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.619099 0.271332 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.628413 0.288206 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.601088 0.283817 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.613293 0.303327 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.588858 0.301572 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555109 0.282943 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.530773 0.278768 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.539989 0.298064 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.539989 0.298064 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.545894 0.263648 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555109 0.282943 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.570229 0.267823 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.545894 0.263648 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.570229 0.267823 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555109 0.282943 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.471405 0.471405 0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER -0.441164 0.501645 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.424703 0.518106 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER -0.420089 0.505261 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.437548 0.522721 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.445778 0.51449 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.458623 0.519105 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.462239 0.498029 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.428319 0.497031 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.44478 0.48057 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.423704 0.484186 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399854 0.490576 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.382226 0.502679 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399854 0.490576 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.405389 0.511231 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.382226 0.502679 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.405389 0.511231 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399854 0.490576 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.376691 0.482024 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.39432 0.469922 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.39432 0.469922 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.452233 0.542955 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.44013 0.560583 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.431578 0.53742 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.452233 0.542955 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.460785 0.566118 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.472887 0.548489 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.472887 0.548489 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.44013 0.560583 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.452233 0.542955 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.431578 0.53742 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.512714 0.482473 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.51514 0.495905 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.492654 0.48988 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.506323 0.506323 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.5352 0.488498 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER -0.526383 0.498917 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.532774 0.475067 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.521531 0.472055 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.519105 0.458623 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.499045 0.46603 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.523783 0.523783 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.527958 0.548119 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.508662 0.538903 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.508662 0.538903 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.543078 0.532998 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.523783 0.523783 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.538903 0.508662 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.543078 0.532998 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.538903 0.508662 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.523783 0.523783 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.542955 0.452233 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.564273 0.4539 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.542955 0.452233 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.548489 0.472887 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.564273 0.4539 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.548489 0.472887 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.542955 0.452233 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.558738 0.433245 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.53742 0.431578 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.53742 0.431578 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.460336 0.430095 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.446904 0.427669 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.436486 0.436486 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.45293 0.450155 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.470754 0.421278 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.47678 0.443764 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.484186 0.423704 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.454311 0.407609 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER -0.467742 0.410035 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.443892 0.416426 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.490576 0.399854 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.488909 0.378536 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.469922 0.39432 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.490576 0.399854 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.509564 0.384071 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.511231 0.405389 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.511231 0.405389 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.488909 0.378536 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.490576 0.399854 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.469922 0.39432 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.419026 0.419026 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.39469 0.414851 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.403906 0.434147 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.403906 0.434147 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.409811 0.399731 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.419026 0.419026 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434147 0.403906 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.409811 0.399731 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434147 0.403906 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.419026 0.419026 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.643951 -0.172546 1.11022e-16 RAD 0.166667 + txt002 + SPHERE CENTER -0.835815 -0.157543 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.871646 -0.122136 0.165419 RAD 0.0185185 + txt002 + SPHERE CENTER -0.871334 -0.102403 0.180258 RAD 0.00617284 + txt002 + SPHERE CENTER -0.850164 -0.113406 0.173902 RAD 0.00617284 + txt002 + SPHERE CENTER -0.862937 -0.100577 0.157111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.892817 -0.111133 0.171776 RAD 0.00617284 + txt002 + SPHERE CENTER -0.884419 -0.109307 0.148628 RAD 0.00617284 + txt002 + SPHERE CENTER -0.893129 -0.130866 0.156937 RAD 0.00617284 + txt002 + SPHERE CENTER -0.880044 -0.123961 0.188567 RAD 0.00617284 + txt002 + SPHERE CENTER -0.880356 -0.143694 0.173728 RAD 0.00617284 + txt002 + SPHERE CENTER -0.858873 -0.134964 0.182211 RAD 0.00617284 + txt002 + SPHERE CENTER -0.799077 -0.135649 0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER -0.781177 -0.120908 0.180075 RAD 0.00617284 + txt002 + SPHERE CENTER -0.778973 -0.13149 0.157875 RAD 0.00617284 + txt002 + SPHERE CENTER -0.795477 -0.113462 0.161374 RAD 0.00617284 + txt002 + SPHERE CENTER -0.801282 -0.125067 0.193792 RAD 0.00617284 + txt002 + SPHERE CENTER -0.815582 -0.11762 0.175091 RAD 0.00617284 + txt002 + SPHERE CENTER -0.819182 -0.139808 0.18531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.784778 -0.143095 0.190293 RAD 0.00617284 + txt002 + SPHERE CENTER -0.802678 -0.157836 0.181811 RAD 0.00617284 + txt002 + SPHERE CENTER -0.782573 -0.153678 0.168094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.82339 -0.0854653 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.811594 -0.0654286 0.114524 RAD 0.00617284 + txt002 + SPHERE CENTER -0.80102 -0.0876595 0.112614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.820516 -0.0820122 0.0985541 RAD 0.00617284 + txt002 + SPHERE CENTER -0.833964 -0.0632344 0.124743 RAD 0.00617284 + txt002 + SPHERE CENTER -0.842886 -0.079818 0.108773 RAD 0.00617284 + txt002 + SPHERE CENTER -0.845761 -0.083271 0.133052 RAD 0.00617284 + txt002 + SPHERE CENTER -0.814468 -0.0688817 0.138803 RAD 0.00617284 + txt002 + SPHERE CENTER -0.826265 -0.0889183 0.147112 RAD 0.00617284 + txt002 + SPHERE CENTER -0.803895 -0.0911125 0.136894 RAD 0.00617284 + txt002 + SPHERE CENTER -0.908384 -0.14403 0.104938 RAD 0.0185185 + txt002 + SPHERE CENTER -0.926643 -0.128672 0.111295 RAD 0.00617284 + txt002 + SPHERE CENTER -0.90826 -0.133221 0.127138 RAD 0.00617284 + txt002 + SPHERE CENTER -0.904034 -0.1198 0.106848 RAD 0.00617284 + txt002 + SPHERE CENTER -0.926768 -0.139481 0.0890951 RAD 0.00617284 + txt002 + SPHERE CENTER -0.904159 -0.130608 0.0846485 RAD 0.00617284 + txt002 + SPHERE CENTER -0.908508 -0.154838 0.0827387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.930993 -0.152902 0.109385 RAD 0.00617284 + txt002 + SPHERE CENTER -0.912733 -0.16826 0.103028 RAD 0.00617284 + txt002 + SPHERE CENTER -0.912609 -0.157451 0.125228 RAD 0.00617284 + txt002 + SPHERE CENTER -0.860128 -0.107359 0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER -0.853284 -0.0905999 0.0455609 RAD 0.00617284 + txt002 + SPHERE CENTER -0.839638 -0.0940331 0.0658506 RAD 0.00617284 + txt002 + SPHERE CENTER -0.840233 -0.111382 0.0482916 RAD 0.00617284 + txt002 + SPHERE CENTER -0.873773 -0.103926 0.0420622 RAD 0.00617284 + txt002 + SPHERE CENTER -0.860723 -0.124708 0.044793 RAD 0.00617284 + txt002 + SPHERE CENTER -0.880618 -0.120685 0.0588533 RAD 0.00617284 + txt002 + SPHERE CENTER -0.873178 -0.086577 0.0596212 RAD 0.00617284 + txt002 + SPHERE CENTER -0.880022 -0.103336 0.0764123 RAD 0.00617284 + txt002 + SPHERE CENTER -0.859532 -0.0900102 0.079911 RAD 0.00617284 + txt002 + SPHERE CENTER -0.872552 -0.179437 0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER -0.894035 -0.188167 0.0421477 RAD 0.00617284 + txt002 + SPHERE CENTER -0.885777 -0.195141 0.0643473 RAD 0.00617284 + txt002 + SPHERE CENTER -0.89378 -0.172046 0.0608487 RAD 0.00617284 + txt002 + SPHERE CENTER -0.880811 -0.172463 0.0284303 RAD 0.00617284 + txt002 + SPHERE CENTER -0.880556 -0.156342 0.0471312 RAD 0.00617284 + txt002 + SPHERE CENTER -0.859328 -0.163733 0.0369125 RAD 0.00617284 + txt002 + SPHERE CENTER -0.872807 -0.195558 0.0319289 RAD 0.00617284 + txt002 + SPHERE CENTER -0.851325 -0.186828 0.0404111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.864549 -0.202532 0.0541285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.884071 -0.194213 0.153697 RAD 0.0185185 + txt002 + SPHERE CENTER -0.891905 -0.197746 0.176845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.867957 -0.193701 0.172398 RAD 0.00617284 + txt002 + SPHERE CENTER -0.884286 -0.175383 0.169668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.908019 -0.198259 0.158144 RAD 0.00617284 + txt002 + SPHERE CENTER -0.900401 -0.175896 0.150967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.900186 -0.194726 0.134996 RAD 0.00617284 + txt002 + SPHERE CENTER -0.89169 -0.216576 0.160875 RAD 0.00617284 + txt002 + SPHERE CENTER -0.883856 -0.213043 0.137727 RAD 0.00617284 + txt002 + SPHERE CENTER -0.867741 -0.212531 0.156428 RAD 0.00617284 + txt002 + SPHERE CENTER -0.84824 -0.229621 0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.843832 -0.25245 0.107698 RAD 0.00617284 + txt002 + SPHERE CENTER -0.826426 -0.235043 0.109608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.846687 -0.233837 0.123668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.865646 -0.247028 0.0974792 RAD 0.00617284 + txt002 + SPHERE CENTER -0.868501 -0.228415 0.113449 RAD 0.00617284 + txt002 + SPHERE CENTER -0.870053 -0.224198 0.0891702 RAD 0.00617284 + txt002 + SPHERE CENTER -0.845385 -0.248234 0.0834188 RAD 0.00617284 + txt002 + SPHERE CENTER -0.849792 -0.225404 0.0751099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.827978 -0.230827 0.0853287 RAD 0.00617284 + txt002 + SPHERE CENTER -0.811502 -0.207727 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.794108 -0.212743 0.176661 RAD 0.00617284 + txt002 + SPHERE CENTER -0.788345 -0.199907 0.156372 RAD 0.00617284 + txt002 + SPHERE CENTER -0.802328 -0.189621 0.173931 RAD 0.00617284 + txt002 + SPHERE CENTER -0.817265 -0.220563 0.18016 RAD 0.00617284 + txt002 + SPHERE CENTER -0.825486 -0.197441 0.177429 RAD 0.00617284 + txt002 + SPHERE CENTER -0.83466 -0.215547 0.163369 RAD 0.00617284 + txt002 + SPHERE CENTER -0.803282 -0.230849 0.162601 RAD 0.00617284 + txt002 + SPHERE CENTER -0.820676 -0.225832 0.14581 RAD 0.00617284 + txt002 + SPHERE CENTER -0.797518 -0.218012 0.142311 RAD 0.00617284 + txt002 + SPHERE CENTER -0.643951 -0.172546 0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER -0.61371 -0.142305 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.597249 -0.125845 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER -0.592635 -0.138689 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.610094 -0.12123 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.618324 -0.12946 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.631169 -0.124846 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.634785 -0.145921 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.600865 -0.14692 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.617326 -0.163381 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.596251 -0.159765 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.5724 -0.153374 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.554772 -0.141271 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.5724 -0.153374 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.577935 -0.13272 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.554772 -0.141271 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.577935 -0.13272 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.5724 -0.153374 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.549237 -0.161926 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.566866 -0.174029 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.566866 -0.174029 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624779 -0.100996 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.612676 -0.0833673 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.604124 -0.10653 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624779 -0.100996 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.633331 -0.0778329 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.645433 -0.0954616 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.645433 -0.0954616 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.612676 -0.0833673 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624779 -0.100996 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.604124 -0.10653 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.68526 -0.161477 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.687686 -0.148046 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.6652 -0.154071 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.678869 -0.137627 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.707746 -0.155452 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER -0.698929 -0.145033 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.70532 -0.168883 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.694077 -0.171896 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.691651 -0.185327 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671591 -0.177921 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.696329 -0.120168 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.700504 -0.095832 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.681209 -0.105047 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.681209 -0.105047 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.715624 -0.110952 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.696329 -0.120168 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.711449 -0.135288 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.715624 -0.110952 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.711449 -0.135288 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.696329 -0.120168 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.715501 -0.191718 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.736819 -0.190051 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.715501 -0.191718 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.721035 -0.171063 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.736819 -0.190051 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.721035 -0.171063 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.715501 -0.191718 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.731284 -0.210706 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.709966 -0.212373 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.709966 -0.212373 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.632882 -0.213855 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.61945 -0.216282 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.609032 -0.207465 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.625476 -0.193796 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.6433 -0.222672 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.649326 -0.200186 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.656732 -0.220246 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.626857 -0.236341 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER -0.640288 -0.233915 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616438 -0.227525 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.663122 -0.244096 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.661455 -0.265414 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.642468 -0.249631 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.663122 -0.244096 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.68211 -0.25988 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.683777 -0.238562 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.683777 -0.238562 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.661455 -0.265414 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.663122 -0.244096 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.642468 -0.249631 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.591572 -0.224924 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.567237 -0.2291 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.576452 -0.209804 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.576452 -0.209804 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.582357 -0.24422 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.591572 -0.224924 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.606693 -0.240045 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.582357 -0.24422 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.606693 -0.240045 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.591572 -0.224924 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.69376 0.0133465 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.674309 0.0838533 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.66171 0.103063 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.653258 0.0800983 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.673446 0.0876683 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.682761 0.106818 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.694497 0.0914233 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.69536 0.0876083 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.662574 0.0992478 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.675172 0.0800382 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.654121 0.0762832 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62221 0.0325183 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.604582 0.0446211 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62221 0.0325183 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.627745 0.053173 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.604582 0.0446211 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.627745 0.053173 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62221 0.0325183 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.599047 0.0239663 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616676 0.0118635 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616676 0.0118635 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.666287 0.0539145 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.662466 0.0547519 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.660752 0.0332597 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.682791 0.0439578 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.668 0.0754066 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.688325 0.0646126 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671821 0.0745692 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.645962 0.0647085 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.649783 0.0638711 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.644249 0.0432164 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.745859 0.0646815 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.750021 0.0887955 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.729506 0.078459 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.732161 0.0813312 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.766375 0.075018 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.748514 0.0675537 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.762212 0.050904 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.763719 0.0721458 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.759557 0.0480318 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.743204 0.0618093 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.737837 0.0347427 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.747099 0.0542122 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.743371 0.0553974 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.7241 0.0550267 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.741565 0.0335575 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.718566 0.0343719 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.732303 0.014088 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.760836 0.0339282 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.751574 0.0144587 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.757108 0.0351134 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.76531 -0.0058253 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.786629 -0.00415829 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.76531 -0.0058253 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.770845 0.0148294 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.786629 -0.00415829 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.770845 0.0148294 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.76531 -0.0058253 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.781094 -0.024813 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.759776 -0.02648 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.759776 -0.02648 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.701782 0.0432853 0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.693716 0.0608821 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.677932 0.0496759 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.694884 0.0652402 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.717566 0.0544915 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.718734 0.0588496 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.725632 0.0368947 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.700615 0.0389272 0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.708681 0.0213304 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.684831 0.027721 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.721234 -0.0272215 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.720593 -0.0310802 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.7 -0.0246945 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.718114 -0.00820099 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.741827 -0.0336072 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.739347 -0.010728 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.742467 -0.0297485 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.723713 -0.0501007 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.724354 -0.046242 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.70312 -0.043715 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.649684 -0.00804971 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.628657 -0.00328338 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.630031 0.000378614 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.642244 0.0152909 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.648309 -0.0117117 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.661896 0.00686255 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.669336 -0.016478 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.636097 -0.026624 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.657124 -0.0313903 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.637471 -0.022962 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.835815 -0.157543 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.899353 -0.119969 -0.117284 RAD 0.0185185 + txt002 + SPHERE CENTER -0.909872 -0.0977075 -0.115431 RAD 0.00617284 + txt002 + SPHERE CENTER -0.891613 -0.104052 -0.100068 RAD 0.00617284 + txt002 + SPHERE CENTER -0.886771 -0.0997803 -0.1239 RAD 0.00617284 + txt002 + SPHERE CENTER -0.917612 -0.113625 -0.132647 RAD 0.00617284 + txt002 + SPHERE CENTER -0.894512 -0.115698 -0.141116 RAD 0.00617284 + txt002 + SPHERE CENTER -0.907093 -0.135886 -0.1345 RAD 0.00617284 + txt002 + SPHERE CENTER -0.922453 -0.117896 -0.108814 RAD 0.00617284 + txt002 + SPHERE CENTER -0.911935 -0.140158 -0.110668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.904194 -0.124241 -0.0934517 RAD 0.00617284 + txt002 + SPHERE CENTER -0.868703 -0.130205 -0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER -0.867758 -0.11253 -0.0334138 RAD 0.00617284 + txt002 + SPHERE CENTER -0.846864 -0.122142 -0.0423994 RAD 0.00617284 + txt002 + SPHERE CENTER -0.860854 -0.107566 -0.0565949 RAD 0.00617284 + txt002 + SPHERE CENTER -0.889596 -0.120593 -0.0416443 RAD 0.00617284 + txt002 + SPHERE CENTER -0.882692 -0.115629 -0.0648253 RAD 0.00617284 + txt002 + SPHERE CENTER -0.890541 -0.138267 -0.0588603 RAD 0.00617284 + txt002 + SPHERE CENTER -0.875606 -0.135168 -0.0274488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.876551 -0.152843 -0.0446649 RAD 0.00617284 + txt002 + SPHERE CENTER -0.854713 -0.14478 -0.0364345 RAD 0.00617284 + txt002 + SPHERE CENTER -0.836885 -0.0844101 -0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.826973 -0.0627848 -0.106005 RAD 0.00617284 + txt002 + SPHERE CENTER -0.81296 -0.083104 -0.105354 RAD 0.00617284 + txt002 + SPHERE CENTER -0.830202 -0.0805529 -0.122844 RAD 0.00617284 + txt002 + SPHERE CENTER -0.850898 -0.0640908 -0.10004 RAD 0.00617284 + txt002 + SPHERE CENTER -0.854126 -0.0818589 -0.116879 RAD 0.00617284 + txt002 + SPHERE CENTER -0.860809 -0.0857161 -0.093424 RAD 0.00617284 + txt002 + SPHERE CENTER -0.833656 -0.0666419 -0.0825505 RAD 0.00617284 + txt002 + SPHERE CENTER -0.843568 -0.0882673 -0.0759343 RAD 0.00617284 + txt002 + SPHERE CENTER -0.819643 -0.0869612 -0.0818993 RAD 0.00617284 + txt002 + SPHERE CENTER -0.866465 -0.147308 -0.177765 RAD 0.0185185 + txt002 + SPHERE CENTER -0.876203 -0.130609 -0.193128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.879733 -0.128522 -0.16878 RAD 0.00617284 + txt002 + SPHERE CENTER -0.857385 -0.124356 -0.178416 RAD 0.00617284 + txt002 + SPHERE CENTER -0.862935 -0.149395 -0.202114 RAD 0.00617284 + txt002 + SPHERE CENTER -0.844117 -0.143141 -0.187402 RAD 0.00617284 + txt002 + SPHERE CENTER -0.853198 -0.166093 -0.186751 RAD 0.00617284 + txt002 + SPHERE CENTER -0.885283 -0.153561 -0.192477 RAD 0.00617284 + txt002 + SPHERE CENTER -0.875546 -0.170259 -0.177114 RAD 0.00617284 + txt002 + SPHERE CENTER -0.888813 -0.151474 -0.168128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.803997 -0.111748 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.798532 -0.108311 -0.183703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.797989 -0.131037 -0.174066 RAD 0.00617284 + txt002 + SPHERE CENTER -0.819589 -0.119537 -0.17736 RAD 0.00617284 + txt002 + SPHERE CENTER -0.80454 -0.0890219 -0.169507 RAD 0.00617284 + txt002 + SPHERE CENTER -0.825597 -0.100248 -0.163165 RAD 0.00617284 + txt002 + SPHERE CENTER -0.810005 -0.0924597 -0.145675 RAD 0.00617284 + txt002 + SPHERE CENTER -0.78294 -0.100522 -0.166213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.788405 -0.10396 -0.142381 RAD 0.00617284 + txt002 + SPHERE CENTER -0.782397 -0.123249 -0.156576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.802927 -0.184881 -0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER -0.785723 -0.180723 -0.188808 RAD 0.00617284 + txt002 + SPHERE CENTER -0.798991 -0.161937 -0.179823 RAD 0.00617284 + txt002 + SPHERE CENTER -0.782104 -0.173028 -0.165627 RAD 0.00617284 + txt002 + SPHERE CENTER -0.78966 -0.203667 -0.180578 RAD 0.00617284 + txt002 + SPHERE CENTER -0.786041 -0.195972 -0.157397 RAD 0.00617284 + txt002 + SPHERE CENTER -0.806864 -0.207825 -0.163362 RAD 0.00617284 + txt002 + SPHERE CENTER -0.806546 -0.192576 -0.194773 RAD 0.00617284 + txt002 + SPHERE CENTER -0.82375 -0.196734 -0.177557 RAD 0.00617284 + txt002 + SPHERE CENTER -0.819813 -0.17379 -0.185788 RAD 0.00617284 + txt002 + SPHERE CENTER -0.898283 -0.193102 -0.129006 RAD 0.0185185 + txt002 + SPHERE CENTER -0.920038 -0.201143 -0.120537 RAD 0.00617284 + txt002 + SPHERE CENTER -0.900209 -0.201384 -0.105825 RAD 0.00617284 + txt002 + SPHERE CENTER -0.910616 -0.17991 -0.112168 RAD 0.00617284 + txt002 + SPHERE CENTER -0.918112 -0.192861 -0.143718 RAD 0.00617284 + txt002 + SPHERE CENTER -0.90869 -0.171628 -0.135349 RAD 0.00617284 + txt002 + SPHERE CENTER -0.896357 -0.18482 -0.152187 RAD 0.00617284 + txt002 + SPHERE CENTER -0.907705 -0.214335 -0.137375 RAD 0.00617284 + txt002 + SPHERE CENTER -0.88595 -0.206294 -0.145845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.887876 -0.214576 -0.122663 RAD 0.00617284 + txt002 + SPHERE CENTER -0.834745 -0.230676 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.824206 -0.252002 -0.116217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.810793 -0.231282 -0.116868 RAD 0.00617284 + txt002 + SPHERE CENTER -0.827952 -0.234336 -0.0993785 RAD 0.00617284 + txt002 + SPHERE CENTER -0.848158 -0.251396 -0.122182 RAD 0.00617284 + txt002 + SPHERE CENTER -0.851905 -0.23373 -0.105343 RAD 0.00617284 + txt002 + SPHERE CENTER -0.858698 -0.23007 -0.128798 RAD 0.00617284 + txt002 + SPHERE CENTER -0.830999 -0.248342 -0.139672 RAD 0.00617284 + txt002 + SPHERE CENTER -0.841538 -0.227016 -0.146288 RAD 0.00617284 + txt002 + SPHERE CENTER -0.817586 -0.227621 -0.140323 RAD 0.00617284 + txt002 + SPHERE CENTER -0.867633 -0.203337 -0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER -0.868948 -0.209658 -0.0385197 RAD 0.00617284 + txt002 + SPHERE CENTER -0.84746 -0.202239 -0.0481565 RAD 0.00617284 + txt002 + SPHERE CENTER -0.865773 -0.186008 -0.0448623 RAD 0.00617284 + txt002 + SPHERE CENTER -0.889121 -0.210757 -0.0527151 RAD 0.00617284 + txt002 + SPHERE CENTER -0.885946 -0.187106 -0.0590577 RAD 0.00617284 + txt002 + SPHERE CENTER -0.887806 -0.204436 -0.0765474 RAD 0.00617284 + txt002 + SPHERE CENTER -0.870808 -0.226988 -0.0560094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.869493 -0.220667 -0.0798417 RAD 0.00617284 + txt002 + SPHERE CENTER -0.84932 -0.219569 -0.0656463 RAD 0.00617284 + txt002 + SPHERE CENTER -0.69376 0.0133465 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.668775 0.0631985 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.661946 0.0667914 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.65711 0.0452771 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.680354 0.0511945 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.673611 0.0847128 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.692019 0.069116 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.680439 0.08112 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.650366 0.0787954 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.657195 0.0752026 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.64553 0.0572811 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62221 0.0325183 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.604582 0.0446211 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62221 0.0325183 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.627745 0.053173 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.604582 0.0446211 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.627745 0.053173 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.62221 0.0325183 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.599047 0.0239663 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616676 0.0118635 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616676 0.0118635 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.649684 -0.00804971 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.634953 -0.000226782 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.655218 0.012605 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.635947 0.0122343 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.629419 -0.0208815 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.630413 -0.00842045 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.644149 -0.0287044 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.64869 -0.0205108 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.66342 -0.0283337 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.668955 -0.00767898 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.740325 0.0440268 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.746894 0.0650768 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.739183 0.0653796 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.723153 0.0607735 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.748035 0.0437239 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.724295 0.0394207 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.741466 0.0226739 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.764065 0.04833 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.757496 0.02728 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.756355 0.0486329 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.721234 -0.0272215 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.732368 -0.0484665 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.715699 -0.0478762 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.737738 -0.0371781 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.737902 -0.0278118 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.743272 -0.0165234 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.726768 -0.00656677 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.715864 -0.0385099 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.70473 -0.0172649 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.699195 -0.0379196 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.76531 -0.0058253 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.786629 -0.00415829 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.76531 -0.0058253 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.770845 0.0148294 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.786629 -0.00415829 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.770845 0.0148294 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.76531 -0.0058253 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.781094 -0.024813 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.759776 -0.02648 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.759776 -0.02648 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.712851 0.0845947 -0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER -0.706291 0.107813 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.689001 0.0909853 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.701434 0.0896851 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.730141 0.101422 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.725284 0.0832945 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.736701 0.0782041 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.717709 0.102723 -0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER -0.724268 0.0795043 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.700418 0.0858949 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.737837 0.0347427 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.740802 0.0511556 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.718185 0.043171 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.730397 0.0580833 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.760455 0.0427273 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.750049 0.0496549 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.757489 0.0263144 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.748242 0.027815 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.745277 0.0114021 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.725625 0.0198304 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.666287 0.0539145 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.650692 0.0721382 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.645053 0.0564414 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.663167 0.072935 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671925 0.0696112 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.6844 0.070408 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.68752 0.0513875 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.653812 0.0531177 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.669407 0.034894 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.648173 0.0374209 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.643951 -0.172546 -0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER -0.674191 -0.142305 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.672341 -0.123995 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.666199 -0.120057 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.651943 -0.134313 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.680334 -0.146243 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.659936 -0.156561 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER -0.682184 -0.164554 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.69459 -0.131987 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER -0.696439 -0.150298 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.688447 -0.12805 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER -0.715501 -0.153374 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.731779 -0.136231 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.712305 -0.141449 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.70911 -0.129524 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.734974 -0.148156 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER -0.712305 -0.141449 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.718696 -0.165299 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.738169 -0.160081 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.721891 -0.177224 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.718696 -0.165299 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.663122 -0.100996 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.656415 -0.0783272 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.639272 -0.0946054 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.651197 -0.0978007 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.680265 -0.0847178 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.675047 -0.104191 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.686972 -0.107387 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.66834 -0.0815225 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.675047 -0.104191 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.651197 -0.0978007 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.602641 -0.161477 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.60298 -0.154189 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.622115 -0.166695 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER -0.617912 -0.143431 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.583506 -0.148971 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER -0.598439 -0.138214 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.583168 -0.156259 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER -0.587708 -0.172234 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.58737 -0.179523 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.606843 -0.184741 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.591572 -0.120168 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.577317 -0.105912 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER -0.582843 -0.128897 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.600302 -0.111438 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.586046 -0.0971825 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.609032 -0.102708 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.600302 -0.111438 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.568587 -0.114642 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.582843 -0.128897 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.574113 -0.137627 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.5724 -0.191718 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.549732 -0.185011 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.569205 -0.179793 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.56601 -0.167868 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.552927 -0.196936 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.569205 -0.179793 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.575596 -0.203643 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.556122 -0.208861 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.578791 -0.215568 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.575596 -0.203643 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.655019 -0.213855 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.653756 -0.23668 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER -0.636974 -0.229127 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.660237 -0.233329 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671802 -0.221409 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.678283 -0.218058 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.673065 -0.198584 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.648538 -0.217207 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.649801 -0.194382 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER -0.631756 -0.209653 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624779 -0.244096 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.607636 -0.260374 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.600929 -0.237705 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.612854 -0.240901 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.631486 -0.266765 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.636704 -0.247291 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.648629 -0.250487 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.619561 -0.26357 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER -0.636704 -0.247291 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.612854 -0.240901 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.696329 -0.224924 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.710584 -0.23918 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.687599 -0.233654 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.705059 -0.216195 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.719314 -0.23045 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.713788 -0.207465 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.705059 -0.216195 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.701855 -0.24791 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.687599 -0.233654 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.678869 -0.242384 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.786005 -0.343435 8.51251e-17 RAD 0.0555556 + txt002 + SPHERE CENTER -0.82165 -0.392454 0.0425863 RAD 0.0185185 + txt002 + SPHERE CENTER -0.824791 -0.400556 0.065698 RAD 0.00617284 + txt002 + SPHERE CENTER -0.802599 -0.392663 0.058292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.821021 -0.376528 0.0614442 RAD 0.00617284 + txt002 + SPHERE CENTER -0.843843 -0.400347 0.0499923 RAD 0.00617284 + txt002 + SPHERE CENTER -0.840073 -0.376319 0.0457385 RAD 0.00617284 + txt002 + SPHERE CENTER -0.840701 -0.392245 0.0268805 RAD 0.00617284 + txt002 + SPHERE CENTER -0.82542 -0.416482 0.0468401 RAD 0.00617284 + txt002 + SPHERE CENTER -0.822279 -0.40838 0.0237283 RAD 0.00617284 + txt002 + SPHERE CENTER -0.803228 -0.408589 0.0394341 RAD 0.00617284 + txt002 + SPHERE CENTER -0.753118 -0.370774 0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER -0.734271 -0.367981 0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER -0.731279 -0.362711 0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER -0.745269 -0.348136 0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER -0.756109 -0.376044 0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER -0.767107 -0.356199 0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER -0.774956 -0.378837 0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER -0.74212 -0.390619 0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.760966 -0.393412 0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER -0.739128 -0.385349 0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER -0.80984 -0.323622 0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER -0.80634 -0.308073 0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER -0.786996 -0.316395 0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER -0.802721 -0.300378 0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER -0.829184 -0.315299 0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER -0.825565 -0.307605 0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER -0.832685 -0.330849 0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.813459 -0.331317 0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER -0.81696 -0.346866 0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER -0.794116 -0.339639 0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER -0.854538 -0.365116 -0.0178949 RAD 0.0185185 + txt002 + SPHERE CENTER -0.878086 -0.365674 -0.0104889 RAD 0.00617284 + txt002 + SPHERE CENTER -0.859887 -0.367962 0.00604126 RAD 0.00617284 + txt002 + SPHERE CENTER -0.863875 -0.346241 -0.00500196 RAD 0.00617284 + txt002 + SPHERE CENTER -0.872736 -0.362827 -0.0344251 RAD 0.00617284 + txt002 + SPHERE CENTER -0.858526 -0.343394 -0.0289382 RAD 0.00617284 + txt002 + SPHERE CENTER -0.849188 -0.362269 -0.0418311 RAD 0.00617284 + txt002 + SPHERE CENTER -0.868748 -0.384548 -0.0233819 RAD 0.00617284 + txt002 + SPHERE CENTER -0.8452 -0.38399 -0.0307879 RAD 0.00617284 + txt002 + SPHERE CENTER -0.85055 -0.386837 -0.00685171 RAD 0.00617284 + txt002 + SPHERE CENTER -0.842728 -0.296284 0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER -0.848999 -0.272611 0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER -0.828835 -0.281616 0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER -0.829121 -0.278432 -0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.862893 -0.287278 -0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER -0.843015 -0.293099 -0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER -0.856621 -0.310951 -0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER -0.862606 -0.290462 0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER -0.856335 -0.314135 0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.842441 -0.299468 0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.818893 -0.316097 -0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER -0.819591 -0.297057 -0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER -0.814956 -0.293153 -0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER -0.79807 -0.304244 -0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER -0.823527 -0.320001 -0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER -0.802007 -0.327188 -0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER -0.822829 -0.339041 -0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER -0.840413 -0.30891 -0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.839716 -0.32795 -0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER -0.835779 -0.305006 -0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER -0.797815 -0.412267 -0.0246914 RAD 0.0185185 + txt002 + SPHERE CENTER -0.793573 -0.436217 -0.0204376 RAD 0.00617284 + txt002 + SPHERE CENTER -0.776294 -0.419454 -0.0149506 RAD 0.00617284 + txt002 + SPHERE CENTER -0.796968 -0.420728 -0.00151032 RAD 0.00617284 + txt002 + SPHERE CENTER -0.815094 -0.42903 -0.0301783 RAD 0.00617284 + txt002 + SPHERE CENTER -0.818489 -0.413542 -0.0112511 RAD 0.00617284 + txt002 + SPHERE CENTER -0.819335 -0.405081 -0.0344321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.79442 -0.427756 -0.0436186 RAD 0.00617284 + txt002 + SPHERE CENTER -0.798662 -0.403807 -0.0478724 RAD 0.00617284 + txt002 + SPHERE CENTER -0.777141 -0.410993 -0.0381316 RAD 0.00617284 + txt002 + SPHERE CENTER -0.76217 -0.363249 -0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER -0.747522 -0.356966 -0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER -0.759239 -0.339469 -0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER -0.740618 -0.352002 -0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER -0.750453 -0.380746 -0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER -0.743549 -0.375782 -0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER -0.765101 -0.387029 -0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.769074 -0.368213 -0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER -0.783722 -0.374496 -0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER -0.780791 -0.350716 -0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER -0.729282 -0.390587 -0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER -0.704862 -0.392427 -0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER -0.717401 -0.374248 -0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER -0.714218 -0.373948 0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.716744 -0.408767 0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER -0.726099 -0.390287 0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER -0.741164 -0.406927 0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER -0.719927 -0.409067 -0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER -0.744347 -0.407227 -0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.732465 -0.390887 -0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.594141 -0.358439 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.542042 -0.409774 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.517869 -0.413579 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.528508 -0.393219 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.525596 -0.395831 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.531404 -0.430134 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.539131 -0.412386 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555577 -0.426328 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.534315 -0.427522 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.558488 -0.423716 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.544953 -0.407161 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.522591 -0.339267 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.504962 -0.327164 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.522591 -0.339267 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.528125 -0.318612 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.504962 -0.327164 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.528125 -0.318612 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.522591 -0.339267 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.499428 -0.347819 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.517056 -0.359921 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.517056 -0.359921 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.550064 -0.379835 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.529037 -0.375068 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.530412 -0.371406 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.542624 -0.356494 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.548689 -0.383497 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.562276 -0.364922 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.569716 -0.388263 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.536477 -0.398409 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.557504 -0.403175 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.537852 -0.394747 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.613592 -0.428945 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.612625 -0.451897 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.593593 -0.436515 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.614807 -0.432663 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.632624 -0.444328 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.634806 -0.425094 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.633591 -0.421376 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.61141 -0.448179 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.612377 -0.425227 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.592379 -0.432797 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.621614 -0.399007 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.620974 -0.402865 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.600381 -0.39648 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.618494 -0.379986 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.642207 -0.405392 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.639728 -0.382513 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.642848 -0.401533 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624094 -0.421886 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624734 -0.418027 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.603501 -0.4155 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.665691 -0.37761 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.687009 -0.375943 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.665691 -0.37761 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671225 -0.356956 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.687009 -0.375943 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671225 -0.356956 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.665691 -0.37761 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.681475 -0.396598 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.660156 -0.398265 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.660156 -0.398265 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.586119 -0.388377 -0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.570335 -0.399584 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.562269 -0.381987 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.569167 -0.403942 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.594185 -0.405974 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.593017 -0.410332 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.609969 -0.394768 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.587286 -0.384019 -0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.60307 -0.372813 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.57922 -0.366422 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.638217 -0.337042 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.64748 -0.317573 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.643752 -0.316388 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.624481 -0.316758 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.641945 -0.338228 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.618946 -0.337413 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.632683 -0.357697 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.661216 -0.337857 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.651954 -0.357326 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.657489 -0.336672 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.566667 -0.317871 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.562847 -0.317033 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.561133 -0.338525 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.583171 -0.327827 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.568381 -0.296378 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.588706 -0.307172 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.572202 -0.297216 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.546343 -0.307077 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.550163 -0.307914 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.544629 -0.328569 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.594141 -0.358439 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.547576 -0.389119 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.525642 -0.386849 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.528407 -0.379645 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.538964 -0.366733 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.544812 -0.396323 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.558134 -0.376207 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.566746 -0.398593 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.534255 -0.409235 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.556189 -0.411505 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.537019 -0.402031 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.522591 -0.339267 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.504962 -0.327164 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.522591 -0.339267 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.528125 -0.318612 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.504962 -0.327164 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.528125 -0.318612 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.522591 -0.339267 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.499428 -0.347819 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.517056 -0.359921 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.517056 -0.359921 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.566667 -0.317871 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.551072 -0.299647 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.545434 -0.315344 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.563547 -0.29885 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.572306 -0.302174 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.584781 -0.301377 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.587901 -0.320398 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.554192 -0.318667 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.569787 -0.336891 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.548554 -0.334364 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.619127 -0.408291 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.617918 -0.415912 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.597788 -0.406911 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616439 -0.39183 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.639257 -0.417292 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.637778 -0.39321 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.640465 -0.409671 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.620605 -0.432372 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.621814 -0.424751 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.600475 -0.423371 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.638217 -0.337042 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.641183 -0.320629 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.618565 -0.328614 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.630777 -0.313702 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.660835 -0.329058 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.65043 -0.32213 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.65787 -0.345471 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.648623 -0.34397 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.645657 -0.360383 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.626005 -0.351955 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.665691 -0.37761 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.687009 -0.375943 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.665691 -0.37761 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671225 -0.356956 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.687009 -0.375943 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.671225 -0.356956 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.665691 -0.37761 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.681475 -0.396598 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.660156 -0.398265 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.660156 -0.398265 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.57505 -0.429687 0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER -0.55776 -0.446515 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.5512 -0.423296 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.562617 -0.428387 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.58161 -0.452905 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.586467 -0.434777 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.5989 -0.436077 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.570193 -0.447815 0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER -0.587483 -0.430987 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.563633 -0.424596 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.621614 -0.399007 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.632748 -0.420252 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.61608 -0.419661 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.638118 -0.408963 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.638282 -0.399597 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.643653 -0.388308 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.627149 -0.378352 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.616244 -0.410295 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.60511 -0.38905 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.599576 -0.409705 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.550064 -0.379835 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.535334 -0.372012 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.555599 -0.35918 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.536327 -0.359551 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.529799 -0.392667 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.530793 -0.380205 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.54453 -0.400489 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.549071 -0.392296 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.563801 -0.400119 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.569335 -0.379464 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0996195 -0.371785 0.544331 RAD 0.166667 + txt002 + SPHERE CENTER 0.220501 -0.393621 0.729516 RAD 0.0555556 + txt002 + SPHERE CENTER 0.279642 -0.368601 0.766439 RAD 0.0185185 + txt002 + SPHERE CENTER 0.299716 -0.354293 0.765035 RAD 0.00617284 + txt002 + SPHERE CENTER 0.292196 -0.366989 0.745238 RAD 0.00617284 + txt002 + SPHERE CENTER 0.279022 -0.347717 0.753281 RAD 0.00617284 + txt002 + SPHERE CENTER 0.287162 -0.355904 0.786236 RAD 0.00617284 + txt002 + SPHERE CENTER 0.266468 -0.349329 0.774481 RAD 0.00617284 + txt002 + SPHERE CENTER 0.267088 -0.370213 0.787639 RAD 0.00617284 + txt002 + SPHERE CENTER 0.300337 -0.375177 0.778193 RAD 0.00617284 + txt002 + SPHERE CENTER 0.280263 -0.389485 0.779597 RAD 0.00617284 + txt002 + SPHERE CENTER 0.292817 -0.387873 0.758396 RAD 0.00617284 + txt002 + SPHERE CENTER 0.281062 -0.372464 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER 0.289441 -0.362978 0.671279 RAD 0.00617284 + txt002 + SPHERE CENTER 0.270044 -0.378255 0.671155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.267771 -0.35549 0.680442 RAD 0.00617284 + txt002 + SPHERE CENTER 0.30046 -0.357187 0.692603 RAD 0.00617284 + txt002 + SPHERE CENTER 0.278789 -0.349699 0.701767 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29208 -0.366673 0.713804 RAD 0.00617284 + txt002 + SPHERE CENTER 0.302733 -0.379952 0.683315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.294353 -0.389438 0.704516 RAD 0.00617284 + txt002 + SPHERE CENTER 0.283335 -0.395229 0.683192 RAD 0.00617284 + txt002 + SPHERE CENTER 0.238665 -0.321889 0.726118 RAD 0.0185185 + txt002 + SPHERE CENTER 0.250544 -0.304702 0.71296 RAD 0.00617284 + txt002 + SPHERE CENTER 0.259421 -0.327715 0.714081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.238717 -0.32307 0.701455 RAD 0.00617284 + txt002 + SPHERE CENTER 0.229788 -0.298875 0.724997 RAD 0.00617284 + txt002 + SPHERE CENTER 0.21796 -0.317244 0.713492 RAD 0.00617284 + txt002 + SPHERE CENTER 0.217908 -0.316063 0.738155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.250492 -0.30352 0.737623 RAD 0.00617284 + txt002 + SPHERE CENTER 0.238612 -0.320707 0.750781 RAD 0.00617284 + txt002 + SPHERE CENTER 0.259369 -0.326533 0.738744 RAD 0.00617284 + txt002 + SPHERE CENTER 0.219082 -0.389758 0.803476 RAD 0.0185185 + txt002 + SPHERE CENTER 0.228779 -0.378635 0.823273 RAD 0.00617284 + txt002 + SPHERE CENTER 0.24293 -0.383364 0.8036 RAD 0.00617284 + txt002 + SPHERE CENTER 0.225483 -0.365937 0.802355 RAD 0.00617284 + txt002 + SPHERE CENTER 0.20493 -0.385029 0.823149 RAD 0.00617284 + txt002 + SPHERE CENTER 0.201634 -0.372331 0.802231 RAD 0.00617284 + txt002 + SPHERE CENTER 0.195233 -0.396152 0.803352 RAD 0.00617284 + txt002 + SPHERE CENTER 0.222377 -0.402455 0.824394 RAD 0.00617284 + txt002 + SPHERE CENTER 0.21268 -0.413578 0.804597 RAD 0.00617284 + txt002 + SPHERE CENTER 0.236529 -0.407185 0.804721 RAD 0.00617284 + txt002 + SPHERE CENTER 0.178104 -0.343046 0.763155 RAD 0.0185185 + txt002 + SPHERE CENTER 0.177083 -0.319723 0.771198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.198298 -0.332294 0.772443 RAD 0.00617284 + txt002 + SPHERE CENTER 0.189464 -0.325124 0.750529 RAD 0.00617284 + txt002 + SPHERE CENTER 0.156889 -0.330475 0.76191 RAD 0.00617284 + txt002 + SPHERE CENTER 0.16927 -0.335876 0.741241 RAD 0.00617284 + txt002 + SPHERE CENTER 0.157909 -0.353797 0.753867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.165722 -0.337645 0.783824 RAD 0.00617284 + txt002 + SPHERE CENTER 0.166743 -0.360967 0.775781 RAD 0.00617284 + txt002 + SPHERE CENTER 0.186938 -0.350216 0.785069 RAD 0.00617284 + txt002 + SPHERE CENTER 0.15994 -0.414778 0.766553 RAD 0.0185185 + txt002 + SPHERE CENTER 0.147477 -0.412573 0.787754 RAD 0.00617284 + txt002 + SPHERE CENTER 0.172167 -0.412448 0.787878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.15977 -0.39322 0.77859 RAD 0.00617284 + txt002 + SPHERE CENTER 0.13525 -0.414903 0.766429 RAD 0.00617284 + txt002 + SPHERE CENTER 0.147543 -0.39555 0.757266 RAD 0.00617284 + txt002 + SPHERE CENTER 0.147713 -0.417108 0.745229 RAD 0.00617284 + txt002 + SPHERE CENTER 0.147647 -0.434131 0.775717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.16011 -0.436336 0.754517 RAD 0.00617284 + txt002 + SPHERE CENTER 0.172338 -0.434006 0.775841 RAD 0.00617284 + txt002 + SPHERE CENTER 0.261479 -0.440333 0.769837 RAD 0.0185185 + txt002 + SPHERE CENTER 0.282991 -0.443285 0.781591 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282046 -0.4302 0.760673 RAD 0.00617284 + txt002 + SPHERE CENTER 0.271991 -0.421181 0.781342 RAD 0.00617284 + txt002 + SPHERE CENTER 0.262424 -0.453417 0.790755 RAD 0.00617284 + txt002 + SPHERE CENTER 0.251423 -0.431313 0.790506 RAD 0.00617284 + txt002 + SPHERE CENTER 0.240911 -0.450466 0.779001 RAD 0.00617284 + txt002 + SPHERE CENTER 0.27248 -0.462437 0.770086 RAD 0.00617284 + txt002 + SPHERE CENTER 0.250967 -0.459485 0.758332 RAD 0.00617284 + txt002 + SPHERE CENTER 0.271534 -0.449353 0.749168 RAD 0.00617284 + txt002 + SPHERE CENTER 0.202338 -0.465353 0.732914 RAD 0.0185185 + txt002 + SPHERE CENTER 0.204606 -0.486123 0.746073 RAD 0.00617284 + txt002 + SPHERE CENTER 0.223366 -0.470107 0.744951 RAD 0.00617284 + txt002 + SPHERE CENTER 0.202946 -0.464339 0.757577 RAD 0.00617284 + txt002 + SPHERE CENTER 0.183578 -0.481368 0.734036 RAD 0.00617284 + txt002 + SPHERE CENTER 0.181918 -0.459584 0.745541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.18131 -0.460599 0.720878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.203998 -0.487137 0.72141 RAD 0.00617284 + txt002 + SPHERE CENTER 0.201729 -0.466367 0.708251 RAD 0.00617284 + txt002 + SPHERE CENTER 0.222757 -0.471122 0.720288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.262898 -0.444196 0.695877 RAD 0.0185185 + txt002 + SPHERE CENTER 0.285685 -0.449273 0.687835 RAD 0.00617284 + txt002 + SPHERE CENTER 0.27701 -0.426189 0.68659 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282528 -0.436139 0.708504 RAD 0.00617284 + txt002 + SPHERE CENTER 0.271573 -0.46728 0.697123 RAD 0.00617284 + txt002 + SPHERE CENTER 0.268416 -0.454146 0.717791 RAD 0.00617284 + txt002 + SPHERE CENTER 0.248787 -0.462204 0.705165 RAD 0.00617284 + txt002 + SPHERE CENTER 0.266055 -0.45733 0.675209 RAD 0.00617284 + txt002 + SPHERE CENTER 0.243269 -0.452254 0.683251 RAD 0.00617284 + txt002 + SPHERE CENTER 0.257381 -0.434246 0.673964 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31427 -0.31427 0.544331 RAD 0.0555556 + txt002 + SPHERE CENTER 0.367156 -0.277961 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.374298 -0.269898 0.485076 RAD 0.00617284 + txt002 + SPHERE CENTER 0.362218 -0.291334 0.487134 RAD 0.00617284 + txt002 + SPHERE CENTER 0.350338 -0.270045 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER 0.379235 -0.256525 0.505236 RAD 0.00617284 + txt002 + SPHERE CENTER 0.355276 -0.256671 0.511201 RAD 0.00617284 + txt002 + SPHERE CENTER 0.372093 -0.264588 0.527454 RAD 0.00617284 + txt002 + SPHERE CENTER 0.391115 -0.277815 0.501329 RAD 0.00617284 + txt002 + SPHERE CENTER 0.383973 -0.285878 0.523547 RAD 0.00617284 + txt002 + SPHERE CENTER 0.379036 -0.299251 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31427 -0.31427 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER 0.304189 -0.304189 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29042 -0.307879 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.307879 -0.29042 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.328039 -0.31058 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER 0.331729 -0.29681 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.33812 -0.32066 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31058 -0.328039 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER 0.32066 -0.33812 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29681 -0.331729 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.297666 -0.252306 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.305995 -0.235688 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER 0.321516 -0.245915 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.312359 -0.259438 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282145 -0.242079 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER 0.288509 -0.265828 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.273816 -0.258696 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.291303 -0.228556 0.509559 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282974 -0.245173 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.306824 -0.238783 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.367156 -0.277961 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.385852 -0.261966 0.57931 RAD 0.00617284 + txt002 + SPHERE CENTER 0.38141 -0.278159 0.561208 RAD 0.00617284 + txt002 + SPHERE CENTER 0.36581 -0.259422 0.565115 RAD 0.00617284 + txt002 + SPHERE CENTER 0.371598 -0.261768 0.599471 RAD 0.00617284 + txt002 + SPHERE CENTER 0.351556 -0.259225 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER 0.352901 -0.277764 0.601529 RAD 0.00617284 + txt002 + SPHERE CENTER 0.387198 -0.280504 0.595564 RAD 0.00617284 + txt002 + SPHERE CENTER 0.368501 -0.2965 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER 0.382755 -0.296698 0.577461 RAD 0.00617284 + txt002 + SPHERE CENTER 0.297666 -0.252306 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.30415 -0.228803 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER 0.321516 -0.245915 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.306824 -0.238783 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.2803 -0.235194 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282974 -0.245173 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.273816 -0.258696 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.294992 -0.242326 0.603794 RAD 0.00617284 + txt002 + SPHERE CENTER 0.288509 -0.265828 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.312359 -0.259438 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31427 -0.31427 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.32435 -0.304189 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.33812 -0.307879 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.32066 -0.29042 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.3005 -0.31058 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29681 -0.29681 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29042 -0.32066 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.317959 -0.328039 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.307879 -0.33812 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.331729 -0.331729 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.383759 -0.339925 0.544331 RAD 0.0185185 + txt002 + SPHERE CENTER 0.407156 -0.334762 0.538366 RAD 0.00617284 + txt002 + SPHERE CENTER 0.388696 -0.326552 0.524171 RAD 0.00617284 + txt002 + SPHERE CENTER 0.392275 -0.31686 0.546597 RAD 0.00617284 + txt002 + SPHERE CENTER 0.402218 -0.348135 0.558526 RAD 0.00617284 + txt002 + SPHERE CENTER 0.387337 -0.330233 0.566757 RAD 0.00617284 + txt002 + SPHERE CENTER 0.378821 -0.353299 0.564491 RAD 0.00617284 + txt002 + SPHERE CENTER 0.39864 -0.357827 0.536101 RAD 0.00617284 + txt002 + SPHERE CENTER 0.375243 -0.362991 0.542066 RAD 0.00617284 + txt002 + SPHERE CENTER 0.380181 -0.349618 0.521905 RAD 0.00617284 + txt002 + SPHERE CENTER 0.330873 -0.376234 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER 0.346394 -0.386461 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER 0.354723 -0.369843 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.340031 -0.362711 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.322544 -0.392851 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER 0.316181 -0.369102 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER 0.307023 -0.382624 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337237 -0.399983 0.579103 RAD 0.00617284 + txt002 + SPHERE CENTER 0.321715 -0.389757 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.345565 -0.383366 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.330873 -0.376234 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER 0.348239 -0.393346 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.354723 -0.369843 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.345565 -0.383366 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.324389 -0.399736 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.321715 -0.389757 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER 0.307023 -0.382624 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER 0.333547 -0.386213 0.484868 RAD 0.00617284 + txt002 + SPHERE CENTER 0.316181 -0.369102 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.340031 -0.362711 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER 0.166275 -0.191247 0.655442 RAD 0.0555556 + txt002 + SPHERE CENTER 0.20793 -0.130089 0.652044 RAD 0.0185185 + txt002 + SPHERE CENTER 0.221102 -0.115471 0.637128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.220766 -0.13987 0.633356 RAD 0.00617284 + txt002 + SPHERE CENTER 0.200597 -0.126388 0.628759 RAD 0.00617284 + txt002 + SPHERE CENTER 0.208266 -0.10569 0.655816 RAD 0.00617284 + txt002 + SPHERE CENTER 0.187762 -0.116607 0.647447 RAD 0.00617284 + txt002 + SPHERE CENTER 0.195095 -0.120308 0.670732 RAD 0.00617284 + txt002 + SPHERE CENTER 0.228435 -0.119172 0.660413 RAD 0.00617284 + txt002 + SPHERE CENTER 0.215264 -0.13379 0.675329 RAD 0.00617284 + txt002 + SPHERE CENTER 0.228099 -0.143571 0.656641 RAD 0.00617284 + txt002 + SPHERE CENTER 0.230419 -0.192135 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.243049 -0.18209 0.599717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.218634 -0.185251 0.597829 RAD 0.00617284 + txt002 + SPHERE CENTER 0.227721 -0.168159 0.613157 RAD 0.00617284 + txt002 + SPHERE CENTER 0.254834 -0.188974 0.620293 RAD 0.00617284 + txt002 + SPHERE CENTER 0.239506 -0.175043 0.633733 RAD 0.00617284 + txt002 + SPHERE CENTER 0.242204 -0.199019 0.638981 RAD 0.00617284 + txt002 + SPHERE CENTER 0.245747 -0.206066 0.604965 RAD 0.00617284 + txt002 + SPHERE CENTER 0.233117 -0.216111 0.623653 RAD 0.00617284 + txt002 + SPHERE CENTER 0.221332 -0.209227 0.603077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.172673 -0.154295 0.591563 RAD 0.0185185 + txt002 + SPHERE CENTER 0.180792 -0.15554 0.568278 RAD 0.00617284 + txt002 + SPHERE CENTER 0.19323 -0.166926 0.586315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.171251 -0.17557 0.579113 RAD 0.00617284 + txt002 + SPHERE CENTER 0.160236 -0.142909 0.573526 RAD 0.00617284 + txt002 + SPHERE CENTER 0.150694 -0.162939 0.584361 RAD 0.00617284 + txt002 + SPHERE CENTER 0.152117 -0.141663 0.596811 RAD 0.00617284 + txt002 + SPHERE CENTER 0.182215 -0.134265 0.580727 RAD 0.00617284 + txt002 + SPHERE CENTER 0.174096 -0.133019 0.604012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.194652 -0.145651 0.598764 RAD 0.00617284 + txt002 + SPHERE CENTER 0.143787 -0.129201 0.689081 RAD 0.0185185 + txt002 + SPHERE CENTER 0.14887 -0.105335 0.692853 RAD 0.00617284 + txt002 + SPHERE CENTER 0.167242 -0.121723 0.690969 RAD 0.00617284 + txt002 + SPHERE CENTER 0.153943 -0.115741 0.671044 RAD 0.00617284 + txt002 + SPHERE CENTER 0.125414 -0.112813 0.690965 RAD 0.00617284 + txt002 + SPHERE CENTER 0.130487 -0.123219 0.669156 RAD 0.00617284 + txt002 + SPHERE CENTER 0.120331 -0.136679 0.687193 RAD 0.00617284 + txt002 + SPHERE CENTER 0.138714 -0.118795 0.71089 RAD 0.00617284 + txt002 + SPHERE CENTER 0.13363 -0.142661 0.707118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.157086 -0.135183 0.709006 RAD 0.00617284 + txt002 + SPHERE CENTER 0.108529 -0.153407 0.6286 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0995811 -0.130858 0.624003 RAD 0.00617284 + txt002 + SPHERE CENTER 0.113639 -0.134736 0.643928 RAD 0.00617284 + txt002 + SPHERE CENTER 0.123725 -0.135326 0.621398 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0944715 -0.149528 0.608675 RAD 0.00617284 + txt002 + SPHERE CENTER 0.118615 -0.153997 0.60607 RAD 0.00617284 + txt002 + SPHERE CENTER 0.10342 -0.172078 0.613272 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0843858 -0.148938 0.631205 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0933338 -0.171487 0.635801 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0984435 -0.152816 0.65113 RAD 0.00617284 + txt002 + SPHERE CENTER 0.102131 -0.190359 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0897843 -0.179968 0.711167 RAD 0.00617284 + txt002 + SPHERE CENTER 0.114103 -0.183804 0.713055 RAD 0.00617284 + txt002 + SPHERE CENTER 0.105492 -0.166467 0.697727 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0778128 -0.186523 0.690591 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0935207 -0.173022 0.677151 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0901597 -0.196914 0.671903 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0864233 -0.20386 0.705919 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0987702 -0.214251 0.687231 RAD 0.00617284 + txt002 + SPHERE CENTER 0.110742 -0.207696 0.707807 RAD 0.00617284 + txt002 + SPHERE CENTER 0.201532 -0.167041 0.715923 RAD 0.0185185 + txt002 + SPHERE CENTER 0.219088 -0.151829 0.724292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.221861 -0.163068 0.702483 RAD 0.00617284 + txt002 + SPHERE CENTER 0.205084 -0.14514 0.705088 RAD 0.00617284 + txt002 + SPHERE CENTER 0.19876 -0.155801 0.737733 RAD 0.00617284 + txt002 + SPHERE CENTER 0.184756 -0.149113 0.718528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.181204 -0.171014 0.729364 RAD 0.00617284 + txt002 + SPHERE CENTER 0.215537 -0.173729 0.735128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.197981 -0.188942 0.726759 RAD 0.00617284 + txt002 + SPHERE CENTER 0.218309 -0.184969 0.713318 RAD 0.00617284 + txt002 + SPHERE CENTER 0.159877 -0.228199 0.719322 RAD 0.0185185 + txt002 + SPHERE CENTER 0.167942 -0.229756 0.742607 RAD 0.00617284 + txt002 + SPHERE CENTER 0.183484 -0.223214 0.72457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.16569 -0.207683 0.731771 RAD 0.00617284 + txt002 + SPHERE CENTER 0.144336 -0.234741 0.737359 RAD 0.00617284 + txt002 + SPHERE CENTER 0.142084 -0.212668 0.726523 RAD 0.00617284 + txt002 + SPHERE CENTER 0.13627 -0.233184 0.714074 RAD 0.00617284 + txt002 + SPHERE CENTER 0.162129 -0.250271 0.730157 RAD 0.00617284 + txt002 + SPHERE CENTER 0.154064 -0.248714 0.706872 RAD 0.00617284 + txt002 + SPHERE CENTER 0.177671 -0.243729 0.71212 RAD 0.00617284 + txt002 + SPHERE CENTER 0.224021 -0.229087 0.682285 RAD 0.0185185 + txt002 + SPHERE CENTER 0.248268 -0.22829 0.686881 RAD 0.00617284 + txt002 + SPHERE CENTER 0.2391 -0.216949 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER 0.234532 -0.207937 0.689486 RAD 0.00617284 + txt002 + SPHERE CENTER 0.233189 -0.240428 0.702209 RAD 0.00617284 + txt002 + SPHERE CENTER 0.219453 -0.220075 0.704814 RAD 0.00617284 + txt002 + SPHERE CENTER 0.208942 -0.241225 0.697613 RAD 0.00617284 + txt002 + SPHERE CENTER 0.237756 -0.249439 0.67968 RAD 0.00617284 + txt002 + SPHERE CENTER 0.213509 -0.250236 0.675083 RAD 0.00617284 + txt002 + SPHERE CENTER 0.228589 -0.238098 0.659755 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0058509 -0.451136 0.729516 RAD 0.0555556 + txt002 + SPHERE CENTER 0.0051487 -0.447081 0.803476 RAD 0.0185185 + txt002 + SPHERE CENTER 0.01504 -0.435909 0.823149 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0289993 -0.440694 0.803352 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0115452 -0.423265 0.802231 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00881065 -0.442297 0.823273 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0123054 -0.429652 0.802355 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0187019 -0.453468 0.8036 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00864346 -0.459725 0.824394 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0012478 -0.470897 0.804721 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0226028 -0.46451 0.804597 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0688765 -0.439178 0.766553 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0903221 -0.426942 0.766429 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0806307 -0.435083 0.745229 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0699989 -0.416328 0.757266 RAD 0.00617284 + txt002 + SPHERE CENTER 0.078568 -0.431037 0.787754 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0582447 -0.420423 0.77859 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0571224 -0.443274 0.787878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0891998 -0.449792 0.775717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0677542 -0.462029 0.775841 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0795084 -0.457933 0.754517 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0172804 -0.386138 0.763155 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0293677 -0.364644 0.76191 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0401449 -0.385352 0.753867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0213457 -0.375512 0.741241 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0065032 -0.36543 0.771198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00151881 -0.376298 0.750529 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00558411 -0.386924 0.772443 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0253024 -0.37527 0.783824 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0132151 -0.396764 0.785069 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0360796 -0.395978 0.775781 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0578769 -0.459039 0.766439 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0707378 -0.451803 0.786236 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0461991 -0.454158 0.787639 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0561039 -0.435761 0.774481 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0824157 -0.456685 0.765035 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0677817 -0.440643 0.753281 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0695548 -0.46392 0.745238 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0725109 -0.475081 0.778193 RAD 0.00617284 + txt002 + SPHERE CENTER -0.05965 -0.482316 0.758396 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0479721 -0.477435 0.779597 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0457452 -0.398096 0.726118 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0495643 -0.373728 0.724997 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0306825 -0.382672 0.738155 RAD 0.00617284 + txt002 + SPHERE CENTER -0.030137 -0.383722 0.713492 RAD 0.00617284 + txt002 + SPHERE CENTER -0.064627 -0.389151 0.71296 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0451997 -0.399146 0.701455 RAD 0.00617284 + txt002 + SPHERE CENTER -0.060808 -0.41352 0.714081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0651725 -0.388102 0.737623 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0613535 -0.41247 0.738744 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0462908 -0.397047 0.750781 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0571747 -0.463094 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER -0.081612 -0.459563 0.692603 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0696122 -0.463589 0.713804 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0665888 -0.442243 0.701767 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0691745 -0.459069 0.671279 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0541513 -0.441749 0.680442 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0447373 -0.4626 0.671155 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0721979 -0.480415 0.683315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0477607 -0.483946 0.683192 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0601982 -0.48444 0.704516 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00628079 -0.512079 0.769837 RAD 0.0185185 + txt002 + SPHERE CENTER -0.000557006 -0.523883 0.790755 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0165974 -0.51057 0.779001 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00208214 -0.49924 0.790506 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0234352 -0.525392 0.781591 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0249603 -0.500749 0.781342 RAD 0.00617284 + txt002 + SPHERE CENTER -0.029159 -0.513588 0.760673 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00475566 -0.536722 0.770086 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0104794 -0.524918 0.749168 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0123987 -0.523409 0.758332 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00557859 -0.516134 0.695877 RAD 0.0185185 + txt002 + SPHERE CENTER -0.00154892 -0.540463 0.697123 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0156462 -0.524673 0.705165 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00538221 -0.52751 0.717791 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0227737 -0.531924 0.687835 RAD 0.00617284 + txt002 + SPHERE CENTER -0.026607 -0.518971 0.708504 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0268034 -0.507596 0.68659 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00174531 -0.529087 0.675209 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00577498 -0.504759 0.673964 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0154498 -0.513298 0.683251 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0574471 -0.504176 0.732914 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0817008 -0.508666 0.734036 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0732807 -0.489545 0.720878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0722467 -0.488971 0.745541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0658672 -0.523298 0.746073 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0564131 -0.503602 0.757577 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0416134 -0.518808 0.744951 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0669012 -0.523872 0.72141 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0426474 -0.519382 0.720288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.058481 -0.504751 0.708251 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0483751 -0.248762 0.655442 RAD 0.0555556 + txt002 + SPHERE CENTER -0.0599222 -0.183785 0.689081 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0522053 -0.160406 0.690965 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0358698 -0.178533 0.687193 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0513956 -0.171954 0.669156 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0762577 -0.165658 0.692853 RAD 0.00617284 + txt002 + SPHERE CENTER -0.075448 -0.177206 0.671044 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0839747 -0.189036 0.690969 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0607319 -0.172236 0.71089 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0684488 -0.195615 0.709006 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0443964 -0.190363 0.707118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00673113 -0.215921 0.692479 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0258737 -0.20044 0.690591 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0203763 -0.215612 0.671903 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00551963 -0.196602 0.677151 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0122285 -0.200749 0.711167 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00812553 -0.196911 0.697727 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00691403 -0.21623 0.713055 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0270852 -0.21976 0.705919 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00794264 -0.235241 0.707807 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0215878 -0.234932 0.687231 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0172857 -0.187119 0.6286 RAD 0.0185185 + txt002 + SPHERE CENTER -0.00705049 -0.176731 0.608675 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00352517 -0.200733 0.613272 RAD 0.00617284 + txt002 + SPHERE CENTER -0.025725 -0.192673 0.60607 RAD 0.00617284 + txt002 + SPHERE CENTER -0.020811 -0.163117 0.624003 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0394855 -0.179058 0.621398 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0310463 -0.173504 0.643928 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00138875 -0.171177 0.631205 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00884647 -0.181564 0.65113 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00491406 -0.195179 0.635801 RAD 0.00617284 + txt002 + SPHERE CENTER -0.115028 -0.216626 0.652044 RAD 0.0185185 + txt002 + SPHERE CENTER -0.127519 -0.195663 0.655816 RAD 0.00617284 + txt002 + SPHERE CENTER -0.108803 -0.201738 0.670732 RAD 0.00617284 + txt002 + SPHERE CENTER -0.104303 -0.194866 0.647447 RAD 0.00617284 + txt002 + SPHERE CENTER -0.133744 -0.210551 0.637128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.110528 -0.209754 0.628759 RAD 0.00617284 + txt002 + SPHERE CENTER -0.121254 -0.231514 0.633356 RAD 0.00617284 + txt002 + SPHERE CENTER -0.138245 -0.217423 0.660413 RAD 0.00617284 + txt002 + SPHERE CENTER -0.125754 -0.238386 0.656641 RAD 0.00617284 + txt002 + SPHERE CENTER -0.119529 -0.223497 0.675329 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0723919 -0.21996 0.591563 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0673141 -0.20388 0.573526 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0609052 -0.198742 0.596811 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0490355 -0.216456 0.584361 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0788008 -0.225098 0.568278 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0605222 -0.237674 0.579113 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0838786 -0.241177 0.586315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0906706 -0.207384 0.580727 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0957484 -0.223463 0.598764 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0842617 -0.202246 0.604012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.103481 -0.281603 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.126206 -0.291073 0.620293 RAD 0.00617284 + txt002 + SPHERE CENTER -0.110246 -0.293457 0.638981 RAD 0.00617284 + txt002 + SPHERE CENTER -0.119897 -0.271345 0.633733 RAD 0.00617284 + txt002 + SPHERE CENTER -0.119442 -0.279219 0.599717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.113132 -0.25949 0.613157 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0967168 -0.269749 0.597829 RAD 0.00617284 + txt002 + SPHERE CENTER -0.10979 -0.301332 0.604965 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0870656 -0.291862 0.603077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0938302 -0.303716 0.623653 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0910116 -0.245428 0.715923 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0942304 -0.234308 0.737733 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0714204 -0.238704 0.729364 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0854464 -0.221514 0.718528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.113822 -0.241032 0.724292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.105038 -0.228237 0.705088 RAD 0.00617284 + txt002 + SPHERE CENTER -0.110603 -0.252152 0.702483 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0997955 -0.258223 0.735128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0965768 -0.269343 0.713318 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0769856 -0.262619 0.726759 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0794645 -0.310405 0.682285 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0817333 -0.324811 0.702209 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0603366 -0.313378 0.697613 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0800146 -0.300317 0.704814 RAD 0.00617284 + txt002 + SPHERE CENTER -0.100861 -0.321838 0.686881 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0991425 -0.297345 0.689486 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0985923 -0.307433 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0811832 -0.334899 0.67968 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0789143 -0.320493 0.659755 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0597864 -0.323466 0.675083 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0243582 -0.277564 0.719322 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0076281 -0.275459 0.737359 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00142185 -0.270078 0.714074 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0167139 -0.255218 0.726523 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0305645 -0.282946 0.742607 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0396503 -0.262704 0.731771 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0472946 -0.285051 0.72457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0152725 -0.297806 0.730157 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0320026 -0.299911 0.71212 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00906621 -0.292425 0.706872 RAD 0.00617284 + txt002 + SPHERE CENTER -0.115031 -0.4293 0.544331 RAD 0.0555556 + txt002 + SPHERE CENTER -0.178985 -0.424299 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.190929 -0.412497 0.599471 RAD 0.00617284 + txt002 + SPHERE CENTER -0.16674 -0.417001 0.601529 RAD 0.00617284 + txt002 + SPHERE CENTER -0.174844 -0.400273 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER -0.203175 -0.419795 0.57931 RAD 0.00617284 + txt002 + SPHERE CENTER -0.18709 -0.407571 0.565115 RAD 0.00617284 + txt002 + SPHERE CENTER -0.191231 -0.431597 0.561208 RAD 0.00617284 + txt002 + SPHERE CENTER -0.195071 -0.436523 0.595564 RAD 0.00617284 + txt002 + SPHERE CENTER -0.183127 -0.448325 0.577461 RAD 0.00617284 + txt002 + SPHERE CENTER -0.170881 -0.441027 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER -0.115031 -0.4293 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER -0.10495 -0.41922 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0911807 -0.42291 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.10864 -0.40545 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.128801 -0.425611 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.13249 -0.411841 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.138881 -0.435691 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.111341 -0.44307 0.638566 RAD 0.00617284 + txt002 + SPHERE CENTER -0.121421 -0.45315 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0975713 -0.44676 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER -0.131634 -0.367336 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.12515 -0.343834 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER -0.107784 -0.360946 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.122476 -0.353814 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.149 -0.350225 0.585275 RAD 0.00617284 + txt002 + SPHERE CENTER -0.146326 -0.360204 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.155484 -0.373727 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.134308 -0.357357 0.603794 RAD 0.00617284 + txt002 + SPHERE CENTER -0.140792 -0.380859 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.116942 -0.374468 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.178985 -0.424299 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.200165 -0.411775 0.505236 RAD 0.00617284 + txt002 + SPHERE CENTER -0.189948 -0.415187 0.527454 RAD 0.00617284 + txt002 + SPHERE CENTER -0.179342 -0.399922 0.511201 RAD 0.00617284 + txt002 + SPHERE CENTER -0.189202 -0.420888 0.485076 RAD 0.00617284 + txt002 + SPHERE CENTER -0.168379 -0.409035 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER -0.168023 -0.433412 0.487134 RAD 0.00617284 + txt002 + SPHERE CENTER -0.199808 -0.436152 0.501329 RAD 0.00617284 + txt002 + SPHERE CENTER -0.178629 -0.448677 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.189591 -0.439564 0.523547 RAD 0.00617284 + txt002 + SPHERE CENTER -0.131634 -0.367336 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.123305 -0.350719 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER -0.107784 -0.360946 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.116942 -0.374468 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.147155 -0.357109 0.491041 RAD 0.00617284 + txt002 + SPHERE CENTER -0.140792 -0.380859 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.155484 -0.373727 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.137998 -0.343587 0.509559 RAD 0.00617284 + txt002 + SPHERE CENTER -0.146326 -0.360204 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.122476 -0.353814 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.115031 -0.4293 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER -0.125111 -0.41922 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER -0.138881 -0.42291 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.121421 -0.40545 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.101261 -0.425611 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0975713 -0.411841 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0911807 -0.435691 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.11872 -0.44307 0.450097 RAD 0.00617284 + txt002 + SPHERE CENTER -0.10864 -0.45315 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.13249 -0.44676 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER -0.162382 -0.486264 0.544331 RAD 0.0185185 + txt002 + SPHERE CENTER -0.174264 -0.502603 0.558526 RAD 0.00617284 + txt002 + SPHERE CENTER -0.15142 -0.495376 0.564491 RAD 0.00617284 + txt002 + SPHERE CENTER -0.170327 -0.479659 0.566757 RAD 0.00617284 + txt002 + SPHERE CENTER -0.185226 -0.49349 0.538366 RAD 0.00617284 + txt002 + SPHERE CENTER -0.18129 -0.470546 0.546597 RAD 0.00617284 + txt002 + SPHERE CENTER -0.173345 -0.477151 0.524171 RAD 0.00617284 + txt002 + SPHERE CENTER -0.166319 -0.509207 0.536101 RAD 0.00617284 + txt002 + SPHERE CENTER -0.154437 -0.492868 0.521905 RAD 0.00617284 + txt002 + SPHERE CENTER -0.143475 -0.501981 0.542066 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0984274 -0.491265 0.507294 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0810612 -0.508376 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0745774 -0.484874 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0837352 -0.498397 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.104911 -0.514767 0.503387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.107585 -0.504787 0.525813 RAD 0.00617284 + txt002 + SPHERE CENTER -0.122277 -0.497655 0.507294 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0957534 -0.501244 0.484868 RAD 0.00617284 + txt002 + SPHERE CENTER -0.11312 -0.484132 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0892696 -0.477742 0.488775 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0984274 -0.491265 0.581368 RAD 0.0185185 + txt002 + SPHERE CENTER -0.082906 -0.501491 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0745774 -0.484874 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0892696 -0.477742 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.106756 -0.507882 0.597621 RAD 0.00617284 + txt002 + SPHERE CENTER -0.11312 -0.484132 0.599887 RAD 0.00617284 + txt002 + SPHERE CENTER -0.122277 -0.497655 0.581368 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0920638 -0.515014 0.579103 RAD 0.00617284 + txt002 + SPHERE CENTER -0.107585 -0.504787 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0837352 -0.498397 0.56285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.153845 -0.574159 0.618405 RAD 0.0555556 + txt002 + SPHERE CENTER 0.202534 -0.612768 0.658726 RAD 0.0185185 + txt002 + SPHERE CENTER 0.225282 -0.612732 0.668328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.22113 -0.60221 0.64638 RAD 0.00617284 + txt002 + SPHERE CENTER 0.212428 -0.591695 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER 0.206686 -0.62329 0.680674 RAD 0.00617284 + txt002 + SPHERE CENTER 0.193832 -0.602253 0.679302 RAD 0.00617284 + txt002 + SPHERE CENTER 0.183939 -0.623325 0.671072 RAD 0.00617284 + txt002 + SPHERE CENTER 0.215388 -0.633805 0.660098 RAD 0.00617284 + txt002 + SPHERE CENTER 0.192641 -0.63384 0.650495 RAD 0.00617284 + txt002 + SPHERE CENTER 0.211236 -0.623283 0.63815 RAD 0.00617284 + txt002 + SPHERE CENTER 0.225396 -0.554987 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.243024 -0.542885 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.225396 -0.554987 0.593714 RAD 0.00617284 + txt002 + SPHERE CENTER 0.219861 -0.534333 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.243024 -0.542885 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.219861 -0.534333 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.225396 -0.554987 0.643096 RAD 0.00617284 + txt002 + SPHERE CENTER 0.248559 -0.563539 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.23093 -0.575642 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.23093 -0.575642 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.184086 -0.543919 0.678886 RAD 0.0185185 + txt002 + SPHERE CENTER 0.200547 -0.527458 0.687117 RAD 0.00617284 + txt002 + SPHERE CENTER 0.205161 -0.540303 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.187702 -0.522843 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.179472 -0.531074 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.166627 -0.526459 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER 0.163011 -0.547535 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER 0.196931 -0.548533 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.18047 -0.564994 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER 0.201546 -0.561378 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER 0.130984 -0.631939 0.658726 RAD 0.0185185 + txt002 + SPHERE CENTER 0.132649 -0.643128 0.680674 RAD 0.00617284 + txt002 + SPHERE CENTER 0.152367 -0.631785 0.671072 RAD 0.00617284 + txt002 + SPHERE CENTER 0.133263 -0.618482 0.679302 RAD 0.00617284 + txt002 + SPHERE CENTER 0.111266 -0.643283 0.668328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.11188 -0.618637 0.666956 RAD 0.00617284 + txt002 + SPHERE CENTER 0.109601 -0.632094 0.64638 RAD 0.00617284 + txt002 + SPHERE CENTER 0.130371 -0.656585 0.660098 RAD 0.00617284 + txt002 + SPHERE CENTER 0.128706 -0.645397 0.63815 RAD 0.00617284 + txt002 + SPHERE CENTER 0.150088 -0.645242 0.650495 RAD 0.00617284 + txt002 + SPHERE CENTER 0.112536 -0.56309 0.678886 RAD 0.0185185 + txt002 + SPHERE CENTER 0.11011 -0.549659 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.132596 -0.555684 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER 0.118927 -0.53924 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER 0.09005 -0.557065 0.687117 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0988668 -0.546646 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0924762 -0.570497 0.666541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.103719 -0.573509 0.699462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.106145 -0.58694 0.678886 RAD 0.00617284 + txt002 + SPHERE CENTER 0.126205 -0.579534 0.691232 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0822954 -0.593331 0.618405 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0609772 -0.591664 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0822954 -0.593331 0.643096 RAD 0.00617284 + txt002 + SPHERE CENTER 0.076761 -0.572676 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0609772 -0.591664 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.076761 -0.572676 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0822954 -0.593331 0.593714 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0665116 -0.612319 0.618405 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0878298 -0.613986 0.606059 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0878298 -0.613986 0.630751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.172294 -0.643008 0.598245 RAD 0.0185185 + txt002 + SPHERE CENTER 0.189742 -0.660425 0.599616 RAD 0.00617284 + txt002 + SPHERE CENTER 0.196144 -0.636618 0.598245 RAD 0.00617284 + txt002 + SPHERE CENTER 0.185725 -0.645434 0.618821 RAD 0.00617284 + txt002 + SPHERE CENTER 0.165892 -0.666816 0.599616 RAD 0.00617284 + txt002 + SPHERE CENTER 0.161875 -0.651825 0.618821 RAD 0.00617284 + txt002 + SPHERE CENTER 0.148444 -0.649399 0.598245 RAD 0.00617284 + txt002 + SPHERE CENTER 0.17631 -0.657999 0.57904 RAD 0.00617284 + txt002 + SPHERE CENTER 0.158862 -0.640582 0.577669 RAD 0.00617284 + txt002 + SPHERE CENTER 0.182712 -0.634191 0.577669 RAD 0.00617284 + txt002 + SPHERE CENTER 0.123605 -0.6044 0.557924 RAD 0.0185185 + txt002 + SPHERE CENTER 0.107144 -0.620861 0.549693 RAD 0.00617284 + txt002 + SPHERE CENTER 0.119989 -0.625475 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER 0.102529 -0.608016 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER 0.11076 -0.599785 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER 0.106145 -0.58694 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER 0.127221 -0.583324 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.128219 -0.617245 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER 0.14468 -0.600784 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.141064 -0.621859 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER 0.195155 -0.585228 0.557924 RAD 0.0185185 + txt002 + SPHERE CENTER 0.203972 -0.574809 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER 0.181486 -0.568784 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.201546 -0.561378 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER 0.217641 -0.591253 0.549693 RAD 0.00617284 + txt002 + SPHERE CENTER 0.215215 -0.577822 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER 0.208824 -0.601672 0.57027 RAD 0.00617284 + txt002 + SPHERE CENTER 0.197581 -0.598659 0.537348 RAD 0.00617284 + txt002 + SPHERE CENTER 0.188764 -0.609078 0.557924 RAD 0.00617284 + txt002 + SPHERE CENTER 0.175095 -0.592634 0.545578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0329639 -0.552323 0.43322 RAD 0.0555556 + txt002 + SPHERE CENTER 0.0248832 -0.625877 0.436618 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0316054 -0.646362 0.448652 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0478 -0.627981 0.445566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0287309 -0.625173 0.460998 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00868865 -0.644258 0.439705 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00581415 -0.623069 0.45205 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00196644 -0.623773 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0277577 -0.647066 0.424272 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0210355 -0.62658 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0439523 -0.628685 0.421186 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0822954 -0.593331 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER 0.105299 -0.593994 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER 0.100664 -0.582384 0.457911 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0926585 -0.572783 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0869303 -0.604941 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0742898 -0.58373 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0639267 -0.604278 0.482603 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0949359 -0.614541 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0719323 -0.613879 0.46131 RAD 0.00617284 + txt002 + SPHERE CENTER 0.090301 -0.602932 0.448964 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0138144 -0.584567 0.497099 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0177119 -0.584898 0.521479 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0364224 -0.580268 0.506047 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0185345 -0.56353 0.509133 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00489609 -0.589197 0.512531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00407348 -0.567829 0.500186 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00879364 -0.588867 0.488152 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0129918 -0.605935 0.509445 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00909422 -0.605605 0.485065 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0317022 -0.601305 0.494013 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0244483 -0.584869 0.399581 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0473753 -0.5935 0.402668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0308315 -0.595617 0.420874 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0399691 -0.57344 0.415013 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0409921 -0.582752 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0335859 -0.562692 0.39372 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0180651 -0.574121 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0318545 -0.604929 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00892756 -0.596298 0.384149 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0153107 -0.607046 0.405442 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0355172 -0.54356 0.460062 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0495897 -0.530389 0.475494 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0261165 -0.53532 0.481355 RAD 0.00617284 + txt002 + SPHERE CENTER -0.031221 -0.519442 0.463149 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0589904 -0.538628 0.454201 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0406217 -0.527681 0.441856 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0449178 -0.551799 0.438769 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0538859 -0.554507 0.472408 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0398133 -0.567678 0.456976 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0304127 -0.559438 0.478269 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0163676 -0.511316 0.396183 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0212225 -0.48882 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00896145 -0.491256 0.408529 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00194055 -0.497372 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0286287 -0.50888 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00546563 -0.517432 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0237738 -0.531375 0.383837 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0395307 -0.502764 0.396183 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0346758 -0.525259 0.40513 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0272696 -0.505199 0.417476 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0440327 -0.593633 0.372739 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0604766 -0.607302 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0678827 -0.587242 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0604766 -0.607302 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0366265 -0.613693 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0366265 -0.613693 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0201827 -0.600023 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0440327 -0.593633 0.348047 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0275889 -0.579964 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0514389 -0.573573 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0521134 -0.520079 0.369341 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0542684 -0.523344 0.344961 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0591566 -0.541988 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0358996 -0.534291 0.357307 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0472252 -0.501435 0.353908 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0288565 -0.512382 0.366254 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0450702 -0.49817 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0704822 -0.509132 0.356995 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0683272 -0.505868 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0753703 -0.527777 0.372427 RAD 0.00617284 + txt002 + SPHERE CENTER 0.101445 -0.561087 0.406378 RAD 0.0185185 + txt002 + SPHERE CENTER 0.118381 -0.551884 0.390945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0944221 -0.550745 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.103361 -0.536664 0.403291 RAD 0.00617284 + txt002 + SPHERE CENTER 0.125404 -0.562225 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.110383 -0.547006 0.424584 RAD 0.00617284 + txt002 + SPHERE CENTER 0.108468 -0.571428 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER 0.116465 -0.576307 0.394032 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0995293 -0.58551 0.409464 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0925065 -0.575168 0.388171 RAD 0.00617284 + txt002 + SPHERE CENTER 0.247614 -0.494808 0.43322 RAD 0.0555556 + txt002 + SPHERE CENTER 0.313607 -0.494287 0.399581 RAD 0.0185185 + txt002 + SPHERE CENTER 0.326876 -0.484182 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER 0.302705 -0.488171 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.310432 -0.470513 0.39372 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337778 -0.490299 0.402668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.321334 -0.476629 0.415013 RAD 0.00617284 + txt002 + SPHERE CENTER 0.324509 -0.500404 0.420874 RAD 0.00617284 + txt002 + SPHERE CENTER 0.330051 -0.507957 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.316783 -0.518062 0.405442 RAD 0.00617284 + txt002 + SPHERE CENTER 0.305881 -0.511946 0.384149 RAD 0.00617284 + txt002 + SPHERE CENTER 0.269833 -0.434629 0.396183 RAD 0.0185185 + txt002 + SPHERE CENTER 0.279233 -0.426389 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER 0.286276 -0.448298 0.383837 RAD 0.00617284 + txt002 + SPHERE CENTER 0.263449 -0.445377 0.37489 RAD 0.00617284 + txt002 + SPHERE CENTER 0.262789 -0.41272 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.247006 -0.431707 0.387235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.253389 -0.420959 0.408529 RAD 0.00617284 + txt002 + SPHERE CENTER 0.285616 -0.415641 0.396183 RAD 0.00617284 + txt002 + SPHERE CENTER 0.276216 -0.42388 0.417476 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29266 -0.43755 0.40513 RAD 0.00617284 + txt002 + SPHERE CENTER 0.302539 -0.452978 0.460062 RAD 0.0185185 + txt002 + SPHERE CENTER 0.320401 -0.436971 0.454201 RAD 0.00617284 + txt002 + SPHERE CENTER 0.3148 -0.455413 0.438769 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29902 -0.436675 0.441856 RAD 0.00617284 + txt002 + SPHERE CENTER 0.30814 -0.434535 0.475494 RAD 0.00617284 + txt002 + SPHERE CENTER 0.286759 -0.434239 0.463149 RAD 0.00617284 + txt002 + SPHERE CENTER 0.290278 -0.450543 0.481355 RAD 0.00617284 + txt002 + SPHERE CENTER 0.32392 -0.453274 0.472408 RAD 0.00617284 + txt002 + SPHERE CENTER 0.306057 -0.469281 0.478269 RAD 0.00617284 + txt002 + SPHERE CENTER 0.318318 -0.471717 0.456976 RAD 0.00617284 + txt002 + SPHERE CENTER 0.291389 -0.554467 0.436618 RAD 0.0185185 + txt002 + SPHERE CENTER 0.314604 -0.562288 0.439705 RAD 0.00617284 + txt002 + SPHERE CENTER 0.310183 -0.541186 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER 0.306499 -0.542501 0.45205 RAD 0.00617284 + txt002 + SPHERE CENTER 0.29581 -0.575569 0.448652 RAD 0.00617284 + txt002 + SPHERE CENTER 0.287705 -0.555781 0.460998 RAD 0.00617284 + txt002 + SPHERE CENTER 0.272595 -0.567748 0.445566 RAD 0.00617284 + txt002 + SPHERE CENTER 0.299494 -0.574255 0.424272 RAD 0.00617284 + txt002 + SPHERE CENTER 0.276279 -0.566433 0.421186 RAD 0.00617284 + txt002 + SPHERE CENTER 0.295073 -0.553152 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.28032 -0.513157 0.497099 RAD 0.0185185 + txt002 + SPHERE CENTER 0.298839 -0.507811 0.512531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.302049 -0.505577 0.488152 RAD 0.00617284 + txt002 + SPHERE CENTER 0.287442 -0.489718 0.500186 RAD 0.00617284 + txt002 + SPHERE CENTER 0.27711 -0.515392 0.521479 RAD 0.00617284 + txt002 + SPHERE CENTER 0.265714 -0.497299 0.509133 RAD 0.00617284 + txt002 + SPHERE CENTER 0.258591 -0.520738 0.506047 RAD 0.00617284 + txt002 + SPHERE CENTER 0.291716 -0.531251 0.509445 RAD 0.00617284 + txt002 + SPHERE CENTER 0.273198 -0.536597 0.494013 RAD 0.00617284 + txt002 + SPHERE CENTER 0.294927 -0.529016 0.485065 RAD 0.00617284 + txt002 + SPHERE CENTER 0.225396 -0.554987 0.470257 RAD 0.0185185 + txt002 + SPHERE CENTER 0.227186 -0.567359 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.246777 -0.555283 0.482603 RAD 0.00617284 + txt002 + SPHERE CENTER 0.227528 -0.54267 0.49155 RAD 0.00617284 + txt002 + SPHERE CENTER 0.205805 -0.567063 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER 0.206147 -0.542374 0.479204 RAD 0.00617284 + txt002 + SPHERE CENTER 0.204014 -0.554691 0.457911 RAD 0.00617284 + txt002 + SPHERE CENTER 0.225054 -0.579676 0.470257 RAD 0.00617284 + txt002 + SPHERE CENTER 0.223263 -0.567305 0.448964 RAD 0.00617284 + txt002 + SPHERE CENTER 0.244644 -0.567601 0.46131 RAD 0.00617284 + txt002 + SPHERE CENTER 0.258683 -0.536117 0.372739 RAD 0.0185185 + txt002 + SPHERE CENTER 0.275127 -0.549787 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282533 -0.529727 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER 0.275127 -0.549787 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.251277 -0.556177 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.251277 -0.556177 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.234833 -0.542508 0.372739 RAD 0.00617284 + txt002 + SPHERE CENTER 0.258683 -0.536117 0.348047 RAD 0.00617284 + txt002 + SPHERE CENTER 0.242239 -0.522448 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.266089 -0.516058 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.19269 -0.536638 0.406378 RAD 0.0185185 + txt002 + SPHERE CENTER 0.17251 -0.549603 0.412239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.191778 -0.549105 0.427671 RAD 0.00617284 + txt002 + SPHERE CENTER 0.177908 -0.528912 0.424584 RAD 0.00617284 + txt002 + SPHERE CENTER 0.173421 -0.537136 0.390945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.178819 -0.516445 0.403291 RAD 0.00617284 + txt002 + SPHERE CENTER 0.193601 -0.524171 0.385084 RAD 0.00617284 + txt002 + SPHERE CENTER 0.187292 -0.557329 0.394032 RAD 0.00617284 + txt002 + SPHERE CENTER 0.207471 -0.544363 0.388171 RAD 0.00617284 + txt002 + SPHERE CENTER 0.20656 -0.556831 0.409464 RAD 0.00617284 + txt002 + SPHERE CENTER 0.214908 -0.476459 0.369341 RAD 0.0185185 + txt002 + SPHERE CENTER 0.209819 -0.457868 0.353908 RAD 0.00617284 + txt002 + SPHERE CENTER 0.210053 -0.453963 0.378288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.2312 -0.458164 0.366254 RAD 0.00617284 + txt002 + SPHERE CENTER 0.214674 -0.480363 0.344961 RAD 0.00617284 + txt002 + SPHERE CENTER 0.236055 -0.480659 0.357307 RAD 0.00617284 + txt002 + SPHERE CENTER 0.219763 -0.498954 0.360393 RAD 0.00617284 + txt002 + SPHERE CENTER 0.193527 -0.476163 0.356995 RAD 0.00617284 + txt002 + SPHERE CENTER 0.198616 -0.494753 0.372427 RAD 0.00617284 + txt002 + SPHERE CENTER 0.193761 -0.472258 0.381374 RAD 0.00617284 + txt002 + SPHERE CENTER -0.172546 -0.643951 1.11022e-16 RAD 0.166667 + txt002 + SPHERE CENTER -0.157543 -0.835815 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.122136 -0.871646 0.165419 RAD 0.0185185 + txt002 + SPHERE CENTER -0.102403 -0.871334 0.180258 RAD 0.00617284 + txt002 + SPHERE CENTER -0.100577 -0.862937 0.157111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.113406 -0.850164 0.173902 RAD 0.00617284 + txt002 + SPHERE CENTER -0.123961 -0.880044 0.188567 RAD 0.00617284 + txt002 + SPHERE CENTER -0.134964 -0.858873 0.182211 RAD 0.00617284 + txt002 + SPHERE CENTER -0.143694 -0.880356 0.173728 RAD 0.00617284 + txt002 + SPHERE CENTER -0.111133 -0.892817 0.171776 RAD 0.00617284 + txt002 + SPHERE CENTER -0.130866 -0.893129 0.156937 RAD 0.00617284 + txt002 + SPHERE CENTER -0.109307 -0.884419 0.148628 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0854653 -0.82339 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0654286 -0.811594 0.114524 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0820122 -0.820516 0.0985541 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0876595 -0.80102 0.112614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0688817 -0.814468 0.138803 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0911125 -0.803895 0.136894 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0889183 -0.826265 0.147112 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0632344 -0.833964 0.124743 RAD 0.00617284 + txt002 + SPHERE CENTER -0.083271 -0.845761 0.133052 RAD 0.00617284 + txt002 + SPHERE CENTER -0.079818 -0.842886 0.108773 RAD 0.00617284 + txt002 + SPHERE CENTER -0.135649 -0.799077 0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER -0.120908 -0.781177 0.180075 RAD 0.00617284 + txt002 + SPHERE CENTER -0.113462 -0.795477 0.161374 RAD 0.00617284 + txt002 + SPHERE CENTER -0.13149 -0.778973 0.157875 RAD 0.00617284 + txt002 + SPHERE CENTER -0.143095 -0.784778 0.190293 RAD 0.00617284 + txt002 + SPHERE CENTER -0.153678 -0.782573 0.168094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.157836 -0.802678 0.181811 RAD 0.00617284 + txt002 + SPHERE CENTER -0.125067 -0.801282 0.193792 RAD 0.00617284 + txt002 + SPHERE CENTER -0.139808 -0.819182 0.18531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.11762 -0.815582 0.175091 RAD 0.00617284 + txt002 + SPHERE CENTER -0.194213 -0.884071 0.153697 RAD 0.0185185 + txt002 + SPHERE CENTER -0.197746 -0.891905 0.176845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.175383 -0.884286 0.169668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.193701 -0.867957 0.172398 RAD 0.00617284 + txt002 + SPHERE CENTER -0.216576 -0.89169 0.160875 RAD 0.00617284 + txt002 + SPHERE CENTER -0.212531 -0.867741 0.156428 RAD 0.00617284 + txt002 + SPHERE CENTER -0.213043 -0.883856 0.137727 RAD 0.00617284 + txt002 + SPHERE CENTER -0.198259 -0.908019 0.158144 RAD 0.00617284 + txt002 + SPHERE CENTER -0.194726 -0.900186 0.134996 RAD 0.00617284 + txt002 + SPHERE CENTER -0.175896 -0.900401 0.150967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.207727 -0.811502 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.212743 -0.794108 0.176661 RAD 0.00617284 + txt002 + SPHERE CENTER -0.189621 -0.802328 0.173931 RAD 0.00617284 + txt002 + SPHERE CENTER -0.199907 -0.788345 0.156372 RAD 0.00617284 + txt002 + SPHERE CENTER -0.230849 -0.803282 0.162601 RAD 0.00617284 + txt002 + SPHERE CENTER -0.218012 -0.797518 0.142311 RAD 0.00617284 + txt002 + SPHERE CENTER -0.225832 -0.820676 0.14581 RAD 0.00617284 + txt002 + SPHERE CENTER -0.220563 -0.817265 0.18016 RAD 0.00617284 + txt002 + SPHERE CENTER -0.215547 -0.83466 0.163369 RAD 0.00617284 + txt002 + SPHERE CENTER -0.197441 -0.825486 0.177429 RAD 0.00617284 + txt002 + SPHERE CENTER -0.229621 -0.84824 0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.25245 -0.843832 0.107698 RAD 0.00617284 + txt002 + SPHERE CENTER -0.233837 -0.846687 0.123668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.235043 -0.826426 0.109608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.248234 -0.845385 0.0834188 RAD 0.00617284 + txt002 + SPHERE CENTER -0.230827 -0.827978 0.0853287 RAD 0.00617284 + txt002 + SPHERE CENTER -0.225404 -0.849792 0.0751099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.247028 -0.865646 0.0974792 RAD 0.00617284 + txt002 + SPHERE CENTER -0.224198 -0.870053 0.0891702 RAD 0.00617284 + txt002 + SPHERE CENTER -0.228415 -0.868501 0.113449 RAD 0.00617284 + txt002 + SPHERE CENTER -0.14403 -0.908384 0.104938 RAD 0.0185185 + txt002 + SPHERE CENTER -0.128672 -0.926643 0.111295 RAD 0.00617284 + txt002 + SPHERE CENTER -0.1198 -0.904034 0.106848 RAD 0.00617284 + txt002 + SPHERE CENTER -0.133221 -0.90826 0.127138 RAD 0.00617284 + txt002 + SPHERE CENTER -0.152902 -0.930993 0.109385 RAD 0.00617284 + txt002 + SPHERE CENTER -0.157451 -0.912609 0.125228 RAD 0.00617284 + txt002 + SPHERE CENTER -0.16826 -0.912733 0.103028 RAD 0.00617284 + txt002 + SPHERE CENTER -0.139481 -0.926768 0.0890951 RAD 0.00617284 + txt002 + SPHERE CENTER -0.154838 -0.908508 0.0827387 RAD 0.00617284 + txt002 + SPHERE CENTER -0.130608 -0.904159 0.0846485 RAD 0.00617284 + txt002 + SPHERE CENTER -0.179437 -0.872552 0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER -0.188167 -0.894035 0.0421477 RAD 0.00617284 + txt002 + SPHERE CENTER -0.172046 -0.89378 0.0608487 RAD 0.00617284 + txt002 + SPHERE CENTER -0.195141 -0.885777 0.0643473 RAD 0.00617284 + txt002 + SPHERE CENTER -0.195558 -0.872807 0.0319289 RAD 0.00617284 + txt002 + SPHERE CENTER -0.202532 -0.864549 0.0541285 RAD 0.00617284 + txt002 + SPHERE CENTER -0.186828 -0.851325 0.0404111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.172463 -0.880811 0.0284303 RAD 0.00617284 + txt002 + SPHERE CENTER -0.163733 -0.859328 0.0369125 RAD 0.00617284 + txt002 + SPHERE CENTER -0.156342 -0.880556 0.0471312 RAD 0.00617284 + txt002 + SPHERE CENTER -0.107359 -0.860128 0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0905999 -0.853284 0.0455609 RAD 0.00617284 + txt002 + SPHERE CENTER -0.111382 -0.840233 0.0482916 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0940331 -0.839638 0.0658506 RAD 0.00617284 + txt002 + SPHERE CENTER -0.086577 -0.873178 0.0596212 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0900102 -0.859532 0.079911 RAD 0.00617284 + txt002 + SPHERE CENTER -0.103336 -0.880022 0.0764123 RAD 0.00617284 + txt002 + SPHERE CENTER -0.103926 -0.873773 0.0420622 RAD 0.00617284 + txt002 + SPHERE CENTER -0.120685 -0.880618 0.0588533 RAD 0.00617284 + txt002 + SPHERE CENTER -0.124708 -0.860723 0.044793 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0133465 -0.69376 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.0838533 -0.674309 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.103063 -0.66171 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0876683 -0.673446 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0800983 -0.653258 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0992478 -0.662574 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0762832 -0.654121 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0800382 -0.675172 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.106818 -0.682761 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0876083 -0.69536 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0914233 -0.694497 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0539145 -0.666287 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0547519 -0.662466 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0439578 -0.682791 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0332597 -0.660752 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0647085 -0.645962 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0432164 -0.644249 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0638711 -0.649783 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0754066 -0.668 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0745692 -0.671821 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0646126 -0.688325 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0325183 -0.62221 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0446211 -0.604582 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.053173 -0.627745 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0325183 -0.62221 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0239663 -0.599047 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0118635 -0.616676 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0118635 -0.616676 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0446211 -0.604582 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0325183 -0.62221 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.053173 -0.627745 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0432853 -0.701782 0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0608821 -0.693716 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0652402 -0.694884 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0496759 -0.677932 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0389272 -0.700615 0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.027721 -0.684831 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0213304 -0.708681 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0544915 -0.717566 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0368947 -0.725632 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0588496 -0.718734 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00804971 -0.649684 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.00328338 -0.628657 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0152909 -0.642244 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.000378614 -0.630031 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.026624 -0.636097 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.022962 -0.637471 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0313903 -0.657124 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0117117 -0.648309 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.016478 -0.669336 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.00686255 -0.661896 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0272215 -0.721234 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0310802 -0.720593 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00820099 -0.718114 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0246945 -0.7 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0501007 -0.723713 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.043715 -0.70312 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.046242 -0.724354 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0336072 -0.741827 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0297485 -0.742467 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.010728 -0.739347 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0646815 -0.745859 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0887955 -0.750021 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0813312 -0.732161 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.078459 -0.729506 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0721458 -0.763719 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0618093 -0.743204 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0480318 -0.759557 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.075018 -0.766375 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.050904 -0.762212 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0675537 -0.748514 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0058253 -0.76531 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.00415829 -0.786629 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0148294 -0.770845 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0058253 -0.76531 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.024813 -0.781094 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.02648 -0.759776 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.02648 -0.759776 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00415829 -0.786629 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0058253 -0.76531 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0148294 -0.770845 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0347427 -0.737837 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0542122 -0.747099 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0550267 -0.7241 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0553974 -0.743371 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0339282 -0.760836 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0351134 -0.757108 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0144587 -0.751574 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0335575 -0.741565 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.014088 -0.732303 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0343719 -0.718566 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.172546 -0.643951 0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER -0.142305 -0.61371 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.125845 -0.597249 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER -0.12123 -0.610094 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.138689 -0.592635 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.14692 -0.600865 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.159765 -0.596251 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.163381 -0.617326 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.12946 -0.618324 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.145921 -0.634785 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.124846 -0.631169 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.100996 -0.624779 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0833673 -0.612676 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.100996 -0.624779 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.10653 -0.604124 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0833673 -0.612676 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.10653 -0.604124 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.100996 -0.624779 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0778329 -0.633331 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0954616 -0.645433 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0954616 -0.645433 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.153374 -0.5724 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.141271 -0.554772 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.13272 -0.577935 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.153374 -0.5724 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.161926 -0.549237 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.174029 -0.566866 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.174029 -0.566866 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.141271 -0.554772 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.153374 -0.5724 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.13272 -0.577935 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.213855 -0.632882 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.216282 -0.61945 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.193796 -0.625476 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.207465 -0.609032 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.236341 -0.626857 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER -0.227525 -0.616438 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.233915 -0.640288 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.222672 -0.6433 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.220246 -0.656732 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.200186 -0.649326 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.224924 -0.591572 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.2291 -0.567237 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.209804 -0.576452 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.209804 -0.576452 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.24422 -0.582357 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.224924 -0.591572 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.240045 -0.606693 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.24422 -0.582357 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.240045 -0.606693 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.224924 -0.591572 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.244096 -0.663122 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.265414 -0.661455 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.244096 -0.663122 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.249631 -0.642468 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.265414 -0.661455 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.249631 -0.642468 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.244096 -0.663122 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.25988 -0.68211 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.238562 -0.683777 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.238562 -0.683777 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.161477 -0.68526 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.148046 -0.687686 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.137627 -0.678869 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.154071 -0.6652 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.171896 -0.694077 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER -0.177921 -0.671591 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER -0.185327 -0.691651 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.155452 -0.707746 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER -0.168883 -0.70532 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.145033 -0.698929 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.191718 -0.715501 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.190051 -0.736819 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.171063 -0.721035 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.191718 -0.715501 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.210706 -0.731284 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.212373 -0.709966 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.212373 -0.709966 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.190051 -0.736819 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.191718 -0.715501 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.171063 -0.721035 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.120168 -0.696329 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.095832 -0.700504 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.105047 -0.681209 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.105047 -0.681209 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.110952 -0.715624 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.120168 -0.696329 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER -0.135288 -0.711449 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER -0.110952 -0.715624 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.135288 -0.711449 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.120168 -0.696329 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER -0.343435 -0.786005 8.51251e-17 RAD 0.0555556 + txt002 + SPHERE CENTER -0.392454 -0.82165 0.0425863 RAD 0.0185185 + txt002 + SPHERE CENTER -0.400556 -0.824791 0.065698 RAD 0.00617284 + txt002 + SPHERE CENTER -0.376528 -0.821021 0.0614442 RAD 0.00617284 + txt002 + SPHERE CENTER -0.392663 -0.802599 0.058292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.416482 -0.82542 0.0468401 RAD 0.00617284 + txt002 + SPHERE CENTER -0.408589 -0.803228 0.0394341 RAD 0.00617284 + txt002 + SPHERE CENTER -0.40838 -0.822279 0.0237283 RAD 0.00617284 + txt002 + SPHERE CENTER -0.400347 -0.843843 0.0499923 RAD 0.00617284 + txt002 + SPHERE CENTER -0.392245 -0.840701 0.0268805 RAD 0.00617284 + txt002 + SPHERE CENTER -0.376319 -0.840073 0.0457385 RAD 0.00617284 + txt002 + SPHERE CENTER -0.323622 -0.80984 0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER -0.308073 -0.80634 0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER -0.300378 -0.802721 0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER -0.316395 -0.786996 0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER -0.331317 -0.813459 0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER -0.339639 -0.794116 0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER -0.346866 -0.81696 0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER -0.315299 -0.829184 0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER -0.330849 -0.832685 0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.307605 -0.825565 0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER -0.370774 -0.753118 0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER -0.367981 -0.734271 0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER -0.348136 -0.745269 0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER -0.362711 -0.731279 0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER -0.390619 -0.74212 0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.385349 -0.739128 0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER -0.393412 -0.760966 0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER -0.376044 -0.756109 0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER -0.378837 -0.774956 0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER -0.356199 -0.767107 0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER -0.412267 -0.797815 -0.0246914 RAD 0.0185185 + txt002 + SPHERE CENTER -0.436217 -0.793573 -0.0204376 RAD 0.00617284 + txt002 + SPHERE CENTER -0.420728 -0.796968 -0.00151032 RAD 0.00617284 + txt002 + SPHERE CENTER -0.419454 -0.776294 -0.0149506 RAD 0.00617284 + txt002 + SPHERE CENTER -0.427756 -0.79442 -0.0436186 RAD 0.00617284 + txt002 + SPHERE CENTER -0.410993 -0.777141 -0.0381316 RAD 0.00617284 + txt002 + SPHERE CENTER -0.403807 -0.798662 -0.0478724 RAD 0.00617284 + txt002 + SPHERE CENTER -0.42903 -0.815094 -0.0301783 RAD 0.00617284 + txt002 + SPHERE CENTER -0.405081 -0.819335 -0.0344321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.413542 -0.818489 -0.0112511 RAD 0.00617284 + txt002 + SPHERE CENTER -0.390587 -0.729282 -0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER -0.392427 -0.704862 -0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER -0.373948 -0.714218 0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.374248 -0.717401 -0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER -0.409067 -0.719927 -0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER -0.390887 -0.732465 -0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.407227 -0.744347 -0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.408767 -0.716744 0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER -0.406927 -0.741164 0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER -0.390287 -0.726099 0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER -0.363249 -0.76217 -0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER -0.356966 -0.747522 -0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER -0.352002 -0.740618 -0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER -0.339469 -0.759239 -0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER -0.368213 -0.769074 -0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER -0.350716 -0.780791 -0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER -0.374496 -0.783722 -0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER -0.380746 -0.750453 -0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER -0.387029 -0.765101 -0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.375782 -0.743549 -0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER -0.365116 -0.854538 -0.0178949 RAD 0.0185185 + txt002 + SPHERE CENTER -0.365674 -0.878086 -0.0104889 RAD 0.00617284 + txt002 + SPHERE CENTER -0.346241 -0.863875 -0.00500196 RAD 0.00617284 + txt002 + SPHERE CENTER -0.367962 -0.859887 0.00604126 RAD 0.00617284 + txt002 + SPHERE CENTER -0.384548 -0.868748 -0.0233819 RAD 0.00617284 + txt002 + SPHERE CENTER -0.386837 -0.85055 -0.00685171 RAD 0.00617284 + txt002 + SPHERE CENTER -0.38399 -0.8452 -0.0307879 RAD 0.00617284 + txt002 + SPHERE CENTER -0.362827 -0.872736 -0.0344251 RAD 0.00617284 + txt002 + SPHERE CENTER -0.362269 -0.849188 -0.0418311 RAD 0.00617284 + txt002 + SPHERE CENTER -0.343394 -0.858526 -0.0289382 RAD 0.00617284 + txt002 + SPHERE CENTER -0.316097 -0.818893 -0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER -0.297057 -0.819591 -0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER -0.304244 -0.79807 -0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER -0.293153 -0.814956 -0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER -0.30891 -0.840413 -0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.305006 -0.835779 -0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER -0.32795 -0.839716 -0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER -0.320001 -0.823527 -0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER -0.339041 -0.822829 -0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER -0.327188 -0.802007 -0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER -0.296284 -0.842728 0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER -0.272611 -0.848999 0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER -0.278432 -0.829121 -0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.281616 -0.828835 0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER -0.290462 -0.862606 0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER -0.299468 -0.842441 0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.314135 -0.856335 0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.287278 -0.862893 -0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER -0.310951 -0.856621 -0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER -0.293099 -0.843015 -0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER -0.358439 -0.594141 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.389119 -0.547576 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.386849 -0.525642 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.366733 -0.538964 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.379645 -0.528407 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.409235 -0.534255 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.402031 -0.537019 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.411505 -0.556189 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.396323 -0.544812 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.398593 -0.566746 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.376207 -0.558134 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.317871 -0.566667 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.299647 -0.551072 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.29885 -0.563547 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.315344 -0.545434 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.318667 -0.554192 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.334364 -0.548554 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.336891 -0.569787 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.302174 -0.572306 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.320398 -0.587901 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.301377 -0.584781 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.339267 -0.522591 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.327164 -0.504962 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.318612 -0.528125 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.339267 -0.522591 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.347819 -0.499428 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.359921 -0.517056 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.359921 -0.517056 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.327164 -0.504962 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.339267 -0.522591 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.318612 -0.528125 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.429687 -0.57505 0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER -0.446515 -0.55776 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.428387 -0.562617 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.423296 -0.5512 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.447815 -0.570193 0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER -0.424596 -0.563633 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.430987 -0.587483 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER -0.452905 -0.58161 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER -0.436077 -0.5989 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER -0.434777 -0.586467 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER -0.379835 -0.550064 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.372012 -0.535334 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.359551 -0.536327 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.35918 -0.555599 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.392296 -0.549071 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.379464 -0.569335 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.400119 -0.563801 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.392667 -0.529799 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.400489 -0.54453 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.380205 -0.530793 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399007 -0.621614 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.420252 -0.632748 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER -0.408963 -0.638118 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.419661 -0.61608 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.410295 -0.616244 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER -0.409705 -0.599576 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.38905 -0.60511 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399597 -0.638282 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.378352 -0.627149 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.388308 -0.643653 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.408291 -0.619127 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.415912 -0.617918 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER -0.39183 -0.616439 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.406911 -0.597788 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER -0.432372 -0.620605 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER -0.423371 -0.600475 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER -0.424751 -0.621814 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.417292 -0.639257 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER -0.409671 -0.640465 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER -0.39321 -0.637778 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37761 -0.665691 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.375943 -0.687009 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.356956 -0.671225 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37761 -0.665691 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.396598 -0.681475 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.398265 -0.660156 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.398265 -0.660156 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.375943 -0.687009 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37761 -0.665691 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.356956 -0.671225 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.337042 -0.638217 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.320629 -0.641183 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.313702 -0.630777 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.328614 -0.618565 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.34397 -0.648623 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.351955 -0.626005 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.360383 -0.645657 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.329058 -0.660835 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.345471 -0.65787 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.32213 -0.65043 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.358439 -0.594141 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.409774 -0.542042 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.413579 -0.517869 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.395831 -0.525596 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.393219 -0.528508 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.427522 -0.534315 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.407161 -0.544953 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.423716 -0.558488 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.430134 -0.531404 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.426328 -0.555577 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.412386 -0.539131 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.379835 -0.550064 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.375068 -0.529037 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.356494 -0.542624 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.371406 -0.530412 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.398409 -0.536477 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.394747 -0.537852 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.403175 -0.557504 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.383497 -0.548689 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.388263 -0.569716 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.364922 -0.562276 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.339267 -0.522591 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.327164 -0.504962 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.318612 -0.528125 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.339267 -0.522591 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.347819 -0.499428 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.359921 -0.517056 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.359921 -0.517056 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.327164 -0.504962 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.339267 -0.522591 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.318612 -0.528125 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.388377 -0.586119 -0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.399584 -0.570335 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.403942 -0.569167 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.381987 -0.562269 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.384019 -0.587286 -0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER -0.366422 -0.57922 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.372813 -0.60307 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER -0.405974 -0.594185 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER -0.394768 -0.609969 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER -0.410332 -0.593017 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER -0.317871 -0.566667 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.317033 -0.562847 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.327827 -0.583171 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.338525 -0.561133 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.307077 -0.546343 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.328569 -0.544629 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.307914 -0.550163 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.296378 -0.568381 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.297216 -0.572202 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.307172 -0.588706 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.337042 -0.638217 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.317573 -0.64748 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER -0.316758 -0.624481 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.316388 -0.643752 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.337857 -0.661216 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER -0.336672 -0.657489 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.357326 -0.651954 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER -0.338228 -0.641945 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER -0.357697 -0.632683 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.337413 -0.618946 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.428945 -0.613592 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.451897 -0.612625 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER -0.432663 -0.614807 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER -0.436515 -0.593593 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.448179 -0.61141 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER -0.432797 -0.592379 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER -0.425227 -0.612377 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.444328 -0.632624 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER -0.421376 -0.633591 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER -0.425094 -0.634806 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37761 -0.665691 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.375943 -0.687009 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.356956 -0.671225 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37761 -0.665691 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.396598 -0.681475 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.398265 -0.660156 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.398265 -0.660156 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.375943 -0.687009 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.37761 -0.665691 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER -0.356956 -0.671225 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.399007 -0.621614 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER -0.402865 -0.620974 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER -0.379986 -0.618494 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.39648 -0.600381 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.421886 -0.624094 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER -0.4155 -0.603501 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER -0.418027 -0.624734 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER -0.405392 -0.642207 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.401533 -0.642848 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.382513 -0.639728 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER -0.157543 -0.835815 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER -0.119969 -0.899353 -0.117284 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0977075 -0.909872 -0.115431 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0997803 -0.886771 -0.1239 RAD 0.00617284 + txt002 + SPHERE CENTER -0.104052 -0.891613 -0.100068 RAD 0.00617284 + txt002 + SPHERE CENTER -0.117896 -0.922453 -0.108814 RAD 0.00617284 + txt002 + SPHERE CENTER -0.124241 -0.904194 -0.0934517 RAD 0.00617284 + txt002 + SPHERE CENTER -0.140158 -0.911935 -0.110668 RAD 0.00617284 + txt002 + SPHERE CENTER -0.113625 -0.917612 -0.132647 RAD 0.00617284 + txt002 + SPHERE CENTER -0.135886 -0.907093 -0.1345 RAD 0.00617284 + txt002 + SPHERE CENTER -0.115698 -0.894512 -0.141116 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0844101 -0.836885 -0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0627848 -0.826973 -0.106005 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0805529 -0.830202 -0.122844 RAD 0.00617284 + txt002 + SPHERE CENTER -0.083104 -0.81296 -0.105354 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0666419 -0.833656 -0.0825505 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0869612 -0.819643 -0.0818993 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0882673 -0.843568 -0.0759343 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0640908 -0.850898 -0.10004 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0857161 -0.860809 -0.093424 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0818589 -0.854126 -0.116879 RAD 0.00617284 + txt002 + SPHERE CENTER -0.130205 -0.868703 -0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER -0.11253 -0.867758 -0.0334138 RAD 0.00617284 + txt002 + SPHERE CENTER -0.107566 -0.860854 -0.0565949 RAD 0.00617284 + txt002 + SPHERE CENTER -0.122142 -0.846864 -0.0423994 RAD 0.00617284 + txt002 + SPHERE CENTER -0.135168 -0.875606 -0.0274488 RAD 0.00617284 + txt002 + SPHERE CENTER -0.14478 -0.854713 -0.0364345 RAD 0.00617284 + txt002 + SPHERE CENTER -0.152843 -0.876551 -0.0446649 RAD 0.00617284 + txt002 + SPHERE CENTER -0.120593 -0.889596 -0.0416443 RAD 0.00617284 + txt002 + SPHERE CENTER -0.138267 -0.890541 -0.0588603 RAD 0.00617284 + txt002 + SPHERE CENTER -0.115629 -0.882692 -0.0648253 RAD 0.00617284 + txt002 + SPHERE CENTER -0.193102 -0.898283 -0.129006 RAD 0.0185185 + txt002 + SPHERE CENTER -0.201143 -0.920038 -0.120537 RAD 0.00617284 + txt002 + SPHERE CENTER -0.17991 -0.910616 -0.112168 RAD 0.00617284 + txt002 + SPHERE CENTER -0.201384 -0.900209 -0.105825 RAD 0.00617284 + txt002 + SPHERE CENTER -0.214335 -0.907705 -0.137375 RAD 0.00617284 + txt002 + SPHERE CENTER -0.214576 -0.887876 -0.122663 RAD 0.00617284 + txt002 + SPHERE CENTER -0.206294 -0.88595 -0.145845 RAD 0.00617284 + txt002 + SPHERE CENTER -0.192861 -0.918112 -0.143718 RAD 0.00617284 + txt002 + SPHERE CENTER -0.18482 -0.896357 -0.152187 RAD 0.00617284 + txt002 + SPHERE CENTER -0.171628 -0.90869 -0.135349 RAD 0.00617284 + txt002 + SPHERE CENTER -0.203337 -0.867633 -0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER -0.209658 -0.868948 -0.0385197 RAD 0.00617284 + txt002 + SPHERE CENTER -0.186008 -0.865773 -0.0448623 RAD 0.00617284 + txt002 + SPHERE CENTER -0.202239 -0.84746 -0.0481565 RAD 0.00617284 + txt002 + SPHERE CENTER -0.226988 -0.870808 -0.0560094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.219569 -0.84932 -0.0656463 RAD 0.00617284 + txt002 + SPHERE CENTER -0.220667 -0.869493 -0.0798417 RAD 0.00617284 + txt002 + SPHERE CENTER -0.210757 -0.889121 -0.0527151 RAD 0.00617284 + txt002 + SPHERE CENTER -0.204436 -0.887806 -0.0765474 RAD 0.00617284 + txt002 + SPHERE CENTER -0.187106 -0.885946 -0.0590577 RAD 0.00617284 + txt002 + SPHERE CENTER -0.230676 -0.834745 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER -0.252002 -0.824206 -0.116217 RAD 0.00617284 + txt002 + SPHERE CENTER -0.234336 -0.827952 -0.0993785 RAD 0.00617284 + txt002 + SPHERE CENTER -0.231282 -0.810793 -0.116868 RAD 0.00617284 + txt002 + SPHERE CENTER -0.248342 -0.830999 -0.139672 RAD 0.00617284 + txt002 + SPHERE CENTER -0.227621 -0.817586 -0.140323 RAD 0.00617284 + txt002 + SPHERE CENTER -0.227016 -0.841538 -0.146288 RAD 0.00617284 + txt002 + SPHERE CENTER -0.251396 -0.848158 -0.122182 RAD 0.00617284 + txt002 + SPHERE CENTER -0.23007 -0.858698 -0.128798 RAD 0.00617284 + txt002 + SPHERE CENTER -0.23373 -0.851905 -0.105343 RAD 0.00617284 + txt002 + SPHERE CENTER -0.147308 -0.866465 -0.177765 RAD 0.0185185 + txt002 + SPHERE CENTER -0.130609 -0.876203 -0.193128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.124356 -0.857385 -0.178416 RAD 0.00617284 + txt002 + SPHERE CENTER -0.128522 -0.879733 -0.16878 RAD 0.00617284 + txt002 + SPHERE CENTER -0.153561 -0.885283 -0.192477 RAD 0.00617284 + txt002 + SPHERE CENTER -0.151474 -0.888813 -0.168128 RAD 0.00617284 + txt002 + SPHERE CENTER -0.170259 -0.875546 -0.177114 RAD 0.00617284 + txt002 + SPHERE CENTER -0.149395 -0.862935 -0.202114 RAD 0.00617284 + txt002 + SPHERE CENTER -0.166093 -0.853198 -0.186751 RAD 0.00617284 + txt002 + SPHERE CENTER -0.143141 -0.844117 -0.187402 RAD 0.00617284 + txt002 + SPHERE CENTER -0.184881 -0.802927 -0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER -0.180723 -0.785723 -0.188808 RAD 0.00617284 + txt002 + SPHERE CENTER -0.173028 -0.782104 -0.165627 RAD 0.00617284 + txt002 + SPHERE CENTER -0.161937 -0.798991 -0.179823 RAD 0.00617284 + txt002 + SPHERE CENTER -0.192576 -0.806546 -0.194773 RAD 0.00617284 + txt002 + SPHERE CENTER -0.17379 -0.819813 -0.185788 RAD 0.00617284 + txt002 + SPHERE CENTER -0.196734 -0.82375 -0.177557 RAD 0.00617284 + txt002 + SPHERE CENTER -0.203667 -0.78966 -0.180578 RAD 0.00617284 + txt002 + SPHERE CENTER -0.207825 -0.806864 -0.163362 RAD 0.00617284 + txt002 + SPHERE CENTER -0.195972 -0.786041 -0.157397 RAD 0.00617284 + txt002 + SPHERE CENTER -0.111748 -0.803997 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER -0.108311 -0.798532 -0.183703 RAD 0.00617284 + txt002 + SPHERE CENTER -0.119537 -0.819589 -0.17736 RAD 0.00617284 + txt002 + SPHERE CENTER -0.131037 -0.797989 -0.174066 RAD 0.00617284 + txt002 + SPHERE CENTER -0.100522 -0.78294 -0.166213 RAD 0.00617284 + txt002 + SPHERE CENTER -0.123249 -0.782397 -0.156576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.10396 -0.788405 -0.142381 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0890219 -0.80454 -0.169507 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0924597 -0.810005 -0.145675 RAD 0.00617284 + txt002 + SPHERE CENTER -0.100248 -0.825597 -0.163165 RAD 0.00617284 + txt002 + SPHERE CENTER -0.172546 -0.643951 -0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER -0.202787 -0.61371 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.200937 -0.595399 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.194794 -0.591462 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.180539 -0.605717 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.208929 -0.617647 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.188531 -0.627965 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER -0.210779 -0.635958 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.223185 -0.603392 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER -0.225035 -0.621702 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.217042 -0.599454 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER -0.244096 -0.624779 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.260374 -0.607636 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.240901 -0.612854 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.237705 -0.600929 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.26357 -0.619561 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER -0.240901 -0.612854 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.247291 -0.636704 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.266765 -0.631486 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.250487 -0.648629 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.247291 -0.636704 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.191718 -0.5724 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.185011 -0.549732 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.167868 -0.56601 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.179793 -0.569205 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.208861 -0.556122 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.203643 -0.575596 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.215568 -0.578791 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.196936 -0.552927 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.203643 -0.575596 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.179793 -0.569205 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.131237 -0.632882 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.131575 -0.625593 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.15071 -0.6381 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER -0.146508 -0.614836 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.112102 -0.620375 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER -0.127034 -0.609618 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.111763 -0.627664 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER -0.116304 -0.643639 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.115965 -0.650927 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.135439 -0.656145 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.120168 -0.591572 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.105912 -0.577317 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER -0.111438 -0.600302 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.128897 -0.582843 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.114642 -0.568587 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.137627 -0.574113 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.128897 -0.582843 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0971825 -0.586046 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.111438 -0.600302 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.102708 -0.609032 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.100996 -0.663122 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0783272 -0.656415 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0978007 -0.651197 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0946054 -0.639272 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0815225 -0.66834 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0978007 -0.651197 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.104191 -0.675047 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0847178 -0.680265 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.107387 -0.686972 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.104191 -0.675047 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.183615 -0.68526 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER -0.182351 -0.708085 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER -0.165569 -0.700531 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.188833 -0.704733 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER -0.200397 -0.692813 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER -0.206879 -0.689462 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER -0.201661 -0.669989 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.177134 -0.688611 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER -0.178397 -0.665787 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER -0.160351 -0.681058 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER -0.153374 -0.715501 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.136231 -0.731779 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.129524 -0.70911 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.141449 -0.712305 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.160081 -0.738169 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER -0.165299 -0.718696 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.177224 -0.721891 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.148156 -0.734974 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER -0.165299 -0.718696 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.141449 -0.712305 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.224924 -0.696329 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER -0.23918 -0.710584 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER -0.216195 -0.705059 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.233654 -0.687599 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER -0.24791 -0.701855 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.242384 -0.678869 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER -0.233654 -0.687599 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.23045 -0.719314 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER -0.216195 -0.705059 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER -0.207465 -0.713788 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0133465 -0.69376 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.0631985 -0.668775 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0667914 -0.661946 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0511945 -0.680354 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0452771 -0.65711 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0787954 -0.650366 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0572811 -0.64553 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0752026 -0.657195 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0847128 -0.673611 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.08112 -0.680439 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.069116 -0.692019 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00804971 -0.649684 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.000226782 -0.634953 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0122343 -0.635947 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.012605 -0.655218 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0205108 -0.64869 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00767898 -0.668955 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0283337 -0.66342 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0208815 -0.629419 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0287044 -0.644149 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00842045 -0.630413 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0325183 -0.62221 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0446211 -0.604582 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.053173 -0.627745 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0325183 -0.62221 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0239663 -0.599047 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0118635 -0.616676 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0118635 -0.616676 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0446211 -0.604582 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0325183 -0.62221 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.053173 -0.627745 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0845947 -0.712851 -0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER 0.107813 -0.706291 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0896851 -0.701434 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0909853 -0.689001 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.102723 -0.717709 -0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0858949 -0.700418 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0795043 -0.724268 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.101422 -0.730141 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0782041 -0.736701 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0832945 -0.725284 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0539145 -0.666287 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0721382 -0.650692 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.072935 -0.663167 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0564414 -0.645053 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0531177 -0.653812 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0374209 -0.648173 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.034894 -0.669407 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0696112 -0.671925 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0513875 -0.68752 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.070408 -0.6844 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0347427 -0.737837 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0511556 -0.740802 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0580833 -0.730397 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.043171 -0.718185 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.027815 -0.748242 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0198304 -0.725625 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0114021 -0.745277 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0427273 -0.760455 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0263144 -0.757489 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0496549 -0.750049 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0440268 -0.740325 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.0650768 -0.746894 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0607735 -0.723153 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0653796 -0.739183 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.04833 -0.764065 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0486329 -0.756355 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.02728 -0.757496 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0437239 -0.748035 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0226739 -0.741466 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0394207 -0.724295 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0058253 -0.76531 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER -0.00415829 -0.786629 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0148294 -0.770845 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0058253 -0.76531 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER -0.024813 -0.781094 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER -0.02648 -0.759776 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER -0.02648 -0.759776 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00415829 -0.786629 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0058253 -0.76531 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.0148294 -0.770845 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0272215 -0.721234 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER -0.0484665 -0.732368 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0371781 -0.737738 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0478762 -0.715699 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0385099 -0.715864 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0379196 -0.699195 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0172649 -0.70473 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0278118 -0.737902 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER -0.00656677 -0.726768 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER -0.0165234 -0.743272 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.471405 -0.471405 1.11022e-16 RAD 0.166667 + txt002 + SPHERE CENTER 0.690426 -0.508983 1.83812e-16 RAD 0.0555556 + txt002 + SPHERE CENTER 0.755941 -0.484794 -0.0246914 RAD 0.0185185 + txt002 + SPHERE CENTER 0.767658 -0.47411 -0.0436186 RAD 0.00617284 + txt002 + SPHERE CENTER 0.749038 -0.489758 -0.0478724 RAD 0.00617284 + txt002 + SPHERE CENTER 0.744501 -0.467528 -0.0381316 RAD 0.00617284 + txt002 + SPHERE CENTER 0.774562 -0.469146 -0.0204376 RAD 0.00617284 + txt002 + SPHERE CENTER 0.751405 -0.462564 -0.0149506 RAD 0.00617284 + txt002 + SPHERE CENTER 0.762845 -0.47983 -0.00151032 RAD 0.00617284 + txt002 + SPHERE CENTER 0.779098 -0.491377 -0.0301783 RAD 0.00617284 + txt002 + SPHERE CENTER 0.767382 -0.502061 -0.0112511 RAD 0.00617284 + txt002 + SPHERE CENTER 0.760478 -0.507025 -0.0344321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.695668 -0.478434 -0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER 0.703418 -0.481931 -0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER 0.716184 -0.491475 -0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER 0.694124 -0.500827 -0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER 0.682902 -0.46889 -0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER 0.673608 -0.487786 -0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER 0.675152 -0.465393 -0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER 0.704962 -0.459538 -0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER 0.697211 -0.456041 -0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER 0.717727 -0.469082 -0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.7029 -0.436283 -0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER 0.714226 -0.418941 -0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER 0.724842 -0.44101 -0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.704751 -0.43889 -0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.692283 -0.414215 -0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER 0.682808 -0.434163 -0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER 0.680957 -0.431557 0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.712374 -0.416335 0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER 0.701048 -0.433677 0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER 0.722991 -0.438403 0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER 0.7507 -0.515343 0.0425863 RAD 0.0185185 + txt002 + SPHERE CENTER 0.773394 -0.506594 0.0468401 RAD 0.00617284 + txt002 + SPHERE CENTER 0.764807 -0.507924 0.0237283 RAD 0.00617284 + txt002 + SPHERE CENTER 0.755462 -0.491321 0.0394341 RAD 0.00617284 + txt002 + SPHERE CENTER 0.759287 -0.514012 0.065698 RAD 0.00617284 + txt002 + SPHERE CENTER 0.741355 -0.49874 0.058292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.736593 -0.522762 0.0614442 RAD 0.00617284 + txt002 + SPHERE CENTER 0.768632 -0.530616 0.0499923 RAD 0.00617284 + txt002 + SPHERE CENTER 0.745938 -0.539365 0.0457385 RAD 0.00617284 + txt002 + SPHERE CENTER 0.760045 -0.531946 0.0268805 RAD 0.00617284 + txt002 + SPHERE CENTER 0.697658 -0.466832 0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER 0.709346 -0.447385 0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.721188 -0.46231 0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER 0.703286 -0.447429 0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER 0.685816 -0.451907 0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER 0.679757 -0.451951 0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER 0.674129 -0.471354 0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.703718 -0.466788 0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER 0.692031 -0.486235 0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER 0.71556 -0.481713 0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER 0.685185 -0.539531 0.0672777 RAD 0.0185185 + txt002 + SPHERE CENTER 0.693658 -0.538818 0.0904587 RAD 0.00617284 + txt002 + SPHERE CENTER 0.708875 -0.534075 0.0716007 RAD 0.00617284 + txt002 + SPHERE CENTER 0.691194 -0.517905 0.0775657 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669969 -0.544274 0.0861356 RAD 0.00617284 + txt002 + SPHERE CENTER 0.667505 -0.523361 0.0732426 RAD 0.00617284 + txt002 + SPHERE CENTER 0.661495 -0.544988 0.0629546 RAD 0.00617284 + txt002 + SPHERE CENTER 0.687649 -0.560445 0.0801706 RAD 0.00617284 + txt002 + SPHERE CENTER 0.679176 -0.561158 0.0569896 RAD 0.00617284 + txt002 + SPHERE CENTER 0.702866 -0.555702 0.0613127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.743468 -0.557494 -0.0178949 RAD 0.0185185 + txt002 + SPHERE CENTER 0.767402 -0.560084 -0.0233819 RAD 0.00617284 + txt002 + SPHERE CENTER 0.755145 -0.53997 -0.0307879 RAD 0.00617284 + txt002 + SPHERE CENTER 0.760285 -0.543179 -0.00685171 RAD 0.00617284 + txt002 + SPHERE CENTER 0.755725 -0.577608 -0.0104889 RAD 0.00617284 + txt002 + SPHERE CENTER 0.748608 -0.560703 0.00604126 RAD 0.00617284 + txt002 + SPHERE CENTER 0.731791 -0.575017 -0.00500196 RAD 0.00617284 + txt002 + SPHERE CENTER 0.750585 -0.574398 -0.0344251 RAD 0.00617284 + txt002 + SPHERE CENTER 0.726651 -0.571808 -0.0289382 RAD 0.00617284 + txt002 + SPHERE CENTER 0.738328 -0.554284 -0.0418311 RAD 0.00617284 + txt002 + SPHERE CENTER 0.677953 -0.581682 0.00679642 RAD 0.0185185 + txt002 + SPHERE CENTER 0.682851 -0.601808 0.0202367 RAD 0.00617284 + txt002 + SPHERE CENTER 0.700216 -0.58454 0.0170845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.680568 -0.579842 0.0312799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.660588 -0.59895 0.00994863 RAD 0.00617284 + txt002 + SPHERE CENTER 0.658304 -0.576984 0.0209919 RAD 0.00617284 + txt002 + SPHERE CENTER 0.65569 -0.578824 -0.00349164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.680237 -0.603648 -0.0042468 RAD 0.00617284 + txt002 + SPHERE CENTER 0.675339 -0.583522 -0.0176871 RAD 0.00617284 + txt002 + SPHERE CENTER 0.697602 -0.58638 -0.00739901 RAD 0.00617284 + txt002 + SPHERE CENTER 0.683194 -0.551134 -0.0604812 RAD 0.0185185 + txt002 + SPHERE CENTER 0.687731 -0.573364 -0.070222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.703871 -0.56324 -0.0545162 RAD 0.00617284 + txt002 + SPHERE CENTER 0.682033 -0.571303 -0.0462858 RAD 0.00617284 + txt002 + SPHERE CENTER 0.667055 -0.561258 -0.076187 RAD 0.00617284 + txt002 + SPHERE CENTER 0.661356 -0.559196 -0.0522508 RAD 0.00617284 + txt002 + SPHERE CENTER 0.662518 -0.539027 -0.0664462 RAD 0.00617284 + txt002 + SPHERE CENTER 0.688893 -0.553195 -0.0844174 RAD 0.00617284 + txt002 + SPHERE CENTER 0.684356 -0.530964 -0.0746767 RAD 0.00617284 + txt002 + SPHERE CENTER 0.705033 -0.543071 -0.0687117 RAD 0.00617284 + txt002 + SPHERE CENTER 0.607487 -0.335322 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.629404 -0.313405 -0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.626214 -0.316595 -0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.624401 -0.335868 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.606941 -0.318408 -0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.631217 -0.294133 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.611945 -0.295946 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.634407 -0.290942 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.648676 -0.311592 -0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.651867 -0.308402 -0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.646863 -0.330864 -0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.610996 -0.384191 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.623201 -0.403702 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.635431 -0.385946 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.62031 -0.401066 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.598766 -0.401947 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.595876 -0.399312 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.586561 -0.382437 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.613886 -0.386827 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.601681 -0.367317 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.626116 -0.369071 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.558618 -0.331813 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.539107 -0.319608 -0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.541743 -0.322499 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.556863 -0.307378 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.555982 -0.328923 -0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.573738 -0.316693 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.575492 -0.341128 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.540862 -0.344043 -0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.560372 -0.356248 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.543497 -0.346933 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.625895 -0.264535 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.637402 -0.248969 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.646193 -0.271807 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.625088 -0.268363 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.617105 -0.241698 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.604791 -0.261092 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.605598 -0.257264 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.638209 -0.245142 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.626702 -0.260708 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.647 -0.267979 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.555109 -0.282943 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.550934 -0.258608 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.570229 -0.267823 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.570229 -0.267823 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.535813 -0.273728 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.555109 -0.282943 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539989 -0.298064 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.535813 -0.273728 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539989 -0.298064 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.555109 -0.282943 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.603979 -0.286452 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.613271 -0.265398 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.627912 -0.281225 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.610787 -0.26842 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.589337 -0.270625 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.586853 -0.273647 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.580045 -0.291679 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.606463 -0.283431 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.59717 -0.304484 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.621104 -0.299257 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.678274 -0.316914 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.69384 -0.305407 -0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.674446 -0.317721 -0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.671002 -0.296616 -0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.697667 -0.3046 -0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.67483 -0.295809 -0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.682101 -0.316107 -0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.701111 -0.325704 -0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.685545 -0.337211 -0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.681717 -0.338018 -0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.656357 -0.33883 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.677411 -0.329538 -0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.674389 -0.332022 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.661584 -0.314897 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.659378 -0.336346 -0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.643552 -0.321705 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.638325 -0.345639 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.672184 -0.353472 -0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.65113 -0.362764 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669162 -0.355956 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.659866 -0.3877 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.684201 -0.391875 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.674986 -0.37258 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.674986 -0.37258 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669081 -0.406996 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.659866 -0.3877 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.644745 -0.40282 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669081 -0.406996 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.644745 -0.40282 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.659866 -0.3877 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.607487 -0.335322 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.659645 -0.283164 0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER 0.672915 -0.269894 0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER 0.666987 -0.293281 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.649528 -0.275822 0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.665573 -0.259777 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.642185 -0.265705 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.652302 -0.273047 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.683032 -0.277236 0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669762 -0.290507 0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.677104 -0.300624 0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.656357 -0.33883 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.663448 -0.328536 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.639482 -0.329516 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.654603 -0.314396 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.680322 -0.33785 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.671477 -0.32371 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.673232 -0.348145 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.665202 -0.35297 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.658111 -0.363265 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.641237 -0.353951 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.603979 -0.286452 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.614273 -0.279361 0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.628413 -0.288206 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.613293 -0.303327 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.589839 -0.277607 0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.588858 -0.301572 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.579544 -0.284698 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.604959 -0.262487 0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.594664 -0.269578 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.619099 -0.271332 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.610775 -0.279656 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.621535 -0.258061 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.634468 -0.275921 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.616678 -0.264057 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.597842 -0.261795 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.592985 -0.267791 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.587082 -0.28339 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.615632 -0.27366 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.604872 -0.295255 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.628565 -0.29152 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.555109 -0.282943 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.550934 -0.258608 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.570229 -0.267823 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.570229 -0.267823 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.535813 -0.273728 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.555109 -0.282943 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539989 -0.298064 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.535813 -0.273728 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539989 -0.298064 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.555109 -0.282943 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.558618 -0.331813 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.55307 -0.320611 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.57665 -0.325005 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.563845 -0.30788 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.535038 -0.327419 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.545813 -0.314688 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.540585 -0.338621 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.547843 -0.344544 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.553391 -0.355747 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.571423 -0.348938 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.663153 -0.332034 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.684748 -0.321274 0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.678752 -0.326131 0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.666888 -0.308341 0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669149 -0.327177 0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.651289 -0.314244 0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.647554 -0.337937 0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.681014 -0.344967 0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.659419 -0.355727 0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.675018 -0.349824 0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.610996 -0.384191 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.622198 -0.389739 0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.63493 -0.378964 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.617804 -0.366159 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.598265 -0.394966 0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.593871 -0.371386 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.587062 -0.389418 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.61539 -0.407771 0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.604188 -0.402224 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.628121 -0.396997 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.659866 -0.3877 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.684201 -0.391875 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.674986 -0.37258 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.674986 -0.37258 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669081 -0.406996 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.659866 -0.3877 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.644745 -0.40282 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.669081 -0.406996 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.644745 -0.40282 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.659866 -0.3877 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.554344 -0.645066 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.610229 -0.668521 0.153697 RAD 0.0185185 + txt002 + SPHERE CENTER 0.633406 -0.663938 0.160875 RAD 0.00617284 + txt002 + SPHERE CENTER 0.626429 -0.65892 0.137727 RAD 0.00617284 + txt002 + SPHERE CENTER 0.617928 -0.64522 0.156428 RAD 0.00617284 + txt002 + SPHERE CENTER 0.617206 -0.673539 0.176845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.601728 -0.654822 0.172398 RAD 0.00617284 + txt002 + SPHERE CENTER 0.59403 -0.678123 0.169668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.625707 -0.687239 0.158144 RAD 0.00617284 + txt002 + SPHERE CENTER 0.602531 -0.691822 0.150967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.61873 -0.682221 0.134996 RAD 0.00617284 + txt002 + SPHERE CENTER 0.622977 -0.619787 0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.63767 -0.608008 0.0834188 RAD 0.00617284 + txt002 + SPHERE CENTER 0.620102 -0.623239 0.0751099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.613891 -0.601637 0.0853287 RAD 0.00617284 + txt002 + SPHERE CENTER 0.640545 -0.604555 0.107698 RAD 0.00617284 + txt002 + SPHERE CENTER 0.616766 -0.598184 0.109608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.625852 -0.616334 0.123668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.646756 -0.626157 0.0974792 RAD 0.00617284 + txt002 + SPHERE CENTER 0.632063 -0.637936 0.113449 RAD 0.00617284 + txt002 + SPHERE CENTER 0.629188 -0.641389 0.0891702 RAD 0.00617284 + txt002 + SPHERE CENTER 0.585648 -0.598918 0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.601562 -0.580238 0.162601 RAD 0.00617284 + txt002 + SPHERE CENTER 0.605914 -0.59781 0.14581 RAD 0.00617284 + txt002 + SPHERE CENTER 0.587563 -0.581665 0.142311 RAD 0.00617284 + txt002 + SPHERE CENTER 0.581295 -0.581346 0.176661 RAD 0.00617284 + txt002 + SPHERE CENTER 0.567297 -0.582773 0.156372 RAD 0.00617284 + txt002 + SPHERE CENTER 0.565381 -0.600026 0.173931 RAD 0.00617284 + txt002 + SPHERE CENTER 0.599646 -0.597491 0.18016 RAD 0.00617284 + txt002 + SPHERE CENTER 0.583732 -0.616171 0.177429 RAD 0.00617284 + txt002 + SPHERE CENTER 0.603999 -0.615063 0.163369 RAD 0.00617284 + txt002 + SPHERE CENTER 0.541596 -0.6938 0.165419 RAD 0.0185185 + txt002 + SPHERE CENTER 0.547376 -0.70016 0.188567 RAD 0.00617284 + txt002 + SPHERE CENTER 0.564621 -0.690564 0.173728 RAD 0.00617284 + txt002 + SPHERE CENTER 0.546319 -0.676324 0.182211 RAD 0.00617284 + txt002 + SPHERE CENTER 0.524351 -0.703396 0.180258 RAD 0.00617284 + txt002 + SPHERE CENTER 0.523294 -0.679561 0.173902 RAD 0.00617284 + txt002 + SPHERE CENTER 0.518571 -0.697037 0.157111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.542652 -0.717636 0.171776 RAD 0.00617284 + txt002 + SPHERE CENTER 0.536873 -0.711276 0.148628 RAD 0.00617284 + txt002 + SPHERE CENTER 0.559898 -0.70804 0.156937 RAD 0.00617284 + txt002 + SPHERE CENTER 0.517014 -0.624197 0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER 0.516313 -0.60809 0.190293 RAD 0.00617284 + txt002 + SPHERE CENTER 0.538029 -0.616221 0.181811 RAD 0.00617284 + txt002 + SPHERE CENTER 0.524375 -0.60089 0.168094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.495298 -0.616065 0.180075 RAD 0.00617284 + txt002 + SPHERE CENTER 0.50336 -0.608865 0.157875 RAD 0.00617284 + txt002 + SPHERE CENTER 0.495999 -0.632172 0.161374 RAD 0.00617284 + txt002 + SPHERE CENTER 0.508952 -0.631397 0.193792 RAD 0.00617284 + txt002 + SPHERE CENTER 0.509653 -0.647504 0.175091 RAD 0.00617284 + txt002 + SPHERE CENTER 0.530668 -0.639529 0.18531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.48571 -0.670344 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.466887 -0.67091 0.138803 RAD 0.00617284 + txt002 + SPHERE CENTER 0.490138 -0.671107 0.147112 RAD 0.00617284 + txt002 + SPHERE CENTER 0.480853 -0.650637 0.136894 RAD 0.00617284 + txt002 + SPHERE CENTER 0.46246 -0.670147 0.114524 RAD 0.00617284 + txt002 + SPHERE CENTER 0.476425 -0.649874 0.112614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.481283 -0.669581 0.0985541 RAD 0.00617284 + txt002 + SPHERE CENTER 0.471745 -0.690617 0.124743 RAD 0.00617284 + txt002 + SPHERE CENTER 0.490567 -0.690052 0.108773 RAD 0.00617284 + txt002 + SPHERE CENTER 0.494995 -0.690815 0.133052 RAD 0.00617284 + txt002 + SPHERE CENTER 0.578925 -0.714669 0.104938 RAD 0.0185185 + txt002 + SPHERE CENTER 0.597914 -0.729812 0.109385 RAD 0.00617284 + txt002 + SPHERE CENTER 0.602084 -0.70632 0.103028 RAD 0.00617284 + txt002 + SPHERE CENTER 0.592661 -0.711617 0.125228 RAD 0.00617284 + txt002 + SPHERE CENTER 0.574755 -0.738161 0.111295 RAD 0.00617284 + txt002 + SPHERE CENTER 0.569503 -0.719965 0.127138 RAD 0.00617284 + txt002 + SPHERE CENTER 0.555767 -0.723017 0.106848 RAD 0.00617284 + txt002 + SPHERE CENTER 0.584178 -0.732864 0.0890951 RAD 0.00617284 + txt002 + SPHERE CENTER 0.565189 -0.71772 0.0846485 RAD 0.00617284 + txt002 + SPHERE CENTER 0.588348 -0.709372 0.0827387 RAD 0.00617284 + txt002 + SPHERE CENTER 0.52304 -0.691213 0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER 0.511567 -0.712906 0.0596212 RAD 0.00617284 + txt002 + SPHERE CENTER 0.529503 -0.710453 0.0764123 RAD 0.00617284 + txt002 + SPHERE CENTER 0.507717 -0.699372 0.079911 RAD 0.00617284 + txt002 + SPHERE CENTER 0.505104 -0.693665 0.0455609 RAD 0.00617284 + txt002 + SPHERE CENTER 0.501254 -0.680131 0.0658506 RAD 0.00617284 + txt002 + SPHERE CENTER 0.516576 -0.671972 0.0482916 RAD 0.00617284 + txt002 + SPHERE CENTER 0.526889 -0.704747 0.0420622 RAD 0.00617284 + txt002 + SPHERE CENTER 0.538362 -0.683054 0.044793 RAD 0.00617284 + txt002 + SPHERE CENTER 0.544826 -0.702295 0.0588533 RAD 0.00617284 + txt002 + SPHERE CENTER 0.591673 -0.665934 0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER 0.605761 -0.658095 0.0319289 RAD 0.00617284 + txt002 + SPHERE CENTER 0.58746 -0.643855 0.0404111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.607672 -0.647455 0.0541285 RAD 0.00617284 + txt002 + SPHERE CENTER 0.609975 -0.680174 0.0421477 RAD 0.00617284 + txt002 + SPHERE CENTER 0.611885 -0.669535 0.0643473 RAD 0.00617284 + txt002 + SPHERE CENTER 0.595887 -0.688013 0.0608487 RAD 0.00617284 + txt002 + SPHERE CENTER 0.589763 -0.676573 0.0284303 RAD 0.00617284 + txt002 + SPHERE CENTER 0.575674 -0.684413 0.0471312 RAD 0.00617284 + txt002 + SPHERE CENTER 0.571461 -0.662334 0.0369125 RAD 0.00617284 + txt002 + SPHERE CENTER 0.471405 -0.471405 0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER 0.501645 -0.441164 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.518106 -0.424703 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER 0.522721 -0.437548 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.505261 -0.420089 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.497031 -0.428319 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.484186 -0.423704 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.48057 -0.44478 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.51449 -0.445778 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.498029 -0.462239 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.519105 -0.458623 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.542955 -0.452233 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.560583 -0.44013 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.542955 -0.452233 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.53742 -0.431578 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.560583 -0.44013 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.53742 -0.431578 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.542955 -0.452233 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.566118 -0.460785 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.548489 -0.472887 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.548489 -0.472887 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.490576 -0.399854 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.502679 -0.382226 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.511231 -0.405389 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.490576 -0.399854 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.482024 -0.376691 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.469922 -0.39432 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.469922 -0.39432 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.502679 -0.382226 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.490576 -0.399854 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.511231 -0.405389 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.430095 -0.460336 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.427669 -0.446904 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.450155 -0.45293 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.436486 -0.436486 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.407609 -0.454311 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER 0.416426 -0.443892 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.410035 -0.467742 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.421278 -0.470754 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.423704 -0.484186 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.443764 -0.47678 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.419026 -0.419026 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.414851 -0.39469 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.434147 -0.403906 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.434147 -0.403906 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399731 -0.409811 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.419026 -0.419026 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.403906 -0.434147 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399731 -0.409811 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.403906 -0.434147 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.419026 -0.419026 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399854 -0.490576 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.378536 -0.488909 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399854 -0.490576 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.39432 -0.469922 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.378536 -0.488909 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.39432 -0.469922 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399854 -0.490576 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.384071 -0.509564 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.405389 -0.511231 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.405389 -0.511231 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.482473 -0.512714 0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.495905 -0.51514 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.506323 -0.506323 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.48988 -0.492654 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.472055 -0.521531 0.30328 RAD 0.00617284 + txt002 + SPHERE CENTER 0.46603 -0.499045 0.295049 RAD 0.00617284 + txt002 + SPHERE CENTER 0.458623 -0.519105 0.282703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.488498 -0.5352 0.290934 RAD 0.00617284 + txt002 + SPHERE CENTER 0.475067 -0.532774 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.498917 -0.526383 0.270358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.452233 -0.542955 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.4539 -0.564273 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.472887 -0.548489 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.452233 -0.542955 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.433245 -0.558738 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.431578 -0.53742 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.431578 -0.53742 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.4539 -0.564273 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.452233 -0.542955 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.472887 -0.548489 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.523783 -0.523783 0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.548119 -0.527958 0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.538903 -0.508662 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.538903 -0.508662 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.532998 -0.543078 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.523783 -0.523783 0.246914 RAD 0.00617284 + txt002 + SPHERE CENTER 0.508662 -0.538903 0.234568 RAD 0.00617284 + txt002 + SPHERE CENTER 0.532998 -0.543078 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.508662 -0.538903 0.209877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.523783 -0.523783 0.197531 RAD 0.00617284 + txt002 + SPHERE CENTER 0.335322 -0.607487 0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.313405 -0.629404 0.178389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.316595 -0.626214 0.202664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.335868 -0.624401 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.318408 -0.606941 0.187336 RAD 0.00617284 + txt002 + SPHERE CENTER 0.294133 -0.631217 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.295946 -0.611945 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.290942 -0.634407 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.311592 -0.648676 0.193717 RAD 0.00617284 + txt002 + SPHERE CENTER 0.308402 -0.651867 0.169441 RAD 0.00617284 + txt002 + SPHERE CENTER 0.330864 -0.646863 0.178389 RAD 0.00617284 + txt002 + SPHERE CENTER 0.384191 -0.610996 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.405245 -0.601704 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.402224 -0.604188 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.389418 -0.587062 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.387213 -0.608512 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.371386 -0.593871 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.366159 -0.617804 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.400018 -0.625637 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.378964 -0.63493 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.396997 -0.628121 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.331813 -0.558618 0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.341105 -0.537564 0.175614 RAD 0.00617284 + txt002 + SPHERE CENTER 0.355747 -0.553391 0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.338621 -0.540585 0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.317172 -0.542791 0.178701 RAD 0.00617284 + txt002 + SPHERE CENTER 0.314688 -0.545813 0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.30788 -0.563845 0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.334297 -0.555596 0.191046 RAD 0.00617284 + txt002 + SPHERE CENTER 0.325005 -0.57665 0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.348938 -0.571423 0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.264535 -0.625895 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.245336 -0.623429 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.268271 -0.624736 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.260997 -0.604627 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.2416 -0.624589 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.257262 -0.605787 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.2608 -0.627055 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.248874 -0.644697 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.268073 -0.647163 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.271809 -0.646004 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282943 -0.555109 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.278768 -0.530773 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.298064 -0.539989 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.298064 -0.539989 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.263648 -0.545894 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282943 -0.555109 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.267823 -0.570229 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.263648 -0.545894 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.267823 -0.570229 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282943 -0.555109 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.286452 -0.603979 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.266942 -0.591774 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.269578 -0.594664 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.284698 -0.579544 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.283817 -0.601088 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.301572 -0.588858 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.303327 -0.613293 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.268696 -0.616209 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.288206 -0.628413 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.271332 -0.619099 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.316914 -0.678274 0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.31938 -0.697473 0.138161 RAD 0.00617284 + txt002 + SPHERE CENTER 0.338182 -0.681812 0.134867 RAD 0.00617284 + txt002 + SPHERE CENTER 0.318074 -0.674538 0.147213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.298112 -0.693935 0.126127 RAD 0.00617284 + txt002 + SPHERE CENTER 0.296805 -0.671 0.135179 RAD 0.00617284 + txt002 + SPHERE CENTER 0.295646 -0.674736 0.110799 RAD 0.00617284 + txt002 + SPHERE CENTER 0.31822 -0.701209 0.113782 RAD 0.00617284 + txt002 + SPHERE CENTER 0.315754 -0.682009 0.0984536 RAD 0.00617284 + txt002 + SPHERE CENTER 0.337022 -0.685547 0.110488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.33883 -0.656357 0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.351035 -0.675867 0.0466081 RAD 0.00617284 + txt002 + SPHERE CENTER 0.363265 -0.658111 0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.348145 -0.673232 0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.3266 -0.674113 0.0435217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.32371 -0.671477 0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.314396 -0.654603 0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.341721 -0.658993 0.031176 RAD 0.00617284 + txt002 + SPHERE CENTER 0.329516 -0.639482 0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.353951 -0.641237 0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.3877 -0.659866 0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.412036 -0.664041 0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.40282 -0.644745 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.40282 -0.644745 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.396915 -0.679161 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.3877 -0.659866 0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37258 -0.674986 0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.396915 -0.679161 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37258 -0.674986 0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.3877 -0.659866 0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.554344 -0.645066 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.616373 -0.681385 -0.129006 RAD 0.0185185 + txt002 + SPHERE CENTER 0.639472 -0.678928 -0.137375 RAD 0.00617284 + txt002 + SPHERE CENTER 0.621631 -0.664108 -0.145845 RAD 0.00617284 + txt002 + SPHERE CENTER 0.629767 -0.661636 -0.122663 RAD 0.00617284 + txt002 + SPHERE CENTER 0.634214 -0.696205 -0.120537 RAD 0.00617284 + txt002 + SPHERE CENTER 0.624508 -0.678912 -0.105825 RAD 0.00617284 + txt002 + SPHERE CENTER 0.611115 -0.698662 -0.112168 RAD 0.00617284 + txt002 + SPHERE CENTER 0.626079 -0.698678 -0.143718 RAD 0.00617284 + txt002 + SPHERE CENTER 0.602979 -0.701135 -0.135349 RAD 0.00617284 + txt002 + SPHERE CENTER 0.608237 -0.683858 -0.152187 RAD 0.00617284 + txt002 + SPHERE CENTER 0.617144 -0.607573 -0.122833 RAD 0.0185185 + txt002 + SPHERE CENTER 0.63057 -0.595495 -0.139672 RAD 0.00617284 + txt002 + SPHERE CENTER 0.617371 -0.615286 -0.146288 RAD 0.00617284 + txt002 + SPHERE CENTER 0.605919 -0.594239 -0.140323 RAD 0.00617284 + txt002 + SPHERE CENTER 0.630343 -0.587782 -0.116217 RAD 0.00617284 + txt002 + SPHERE CENTER 0.605692 -0.586526 -0.116868 RAD 0.00617284 + txt002 + SPHERE CENTER 0.616917 -0.59986 -0.0993785 RAD 0.00617284 + txt002 + SPHERE CENTER 0.641795 -0.608828 -0.122182 RAD 0.00617284 + txt002 + SPHERE CENTER 0.628369 -0.620906 -0.105343 RAD 0.00617284 + txt002 + SPHERE CENTER 0.628595 -0.628619 -0.128798 RAD 0.00617284 + txt002 + SPHERE CENTER 0.609912 -0.649723 -0.062352 RAD 0.0185185 + txt002 + SPHERE CENTER 0.631982 -0.640648 -0.0560094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.62585 -0.64267 -0.0798417 RAD 0.00617284 + txt002 + SPHERE CENTER 0.614812 -0.625749 -0.0656463 RAD 0.00617284 + txt002 + SPHERE CENTER 0.616044 -0.647702 -0.0385197 RAD 0.00617284 + txt002 + SPHERE CENTER 0.598874 -0.632802 -0.0481565 RAD 0.00617284 + txt002 + SPHERE CENTER 0.593974 -0.656777 -0.0448623 RAD 0.00617284 + txt002 + SPHERE CENTER 0.627081 -0.664623 -0.0527151 RAD 0.00617284 + txt002 + SPHERE CENTER 0.605012 -0.673698 -0.0590577 RAD 0.00617284 + txt002 + SPHERE CENTER 0.620949 -0.666645 -0.0765474 RAD 0.00617284 + txt002 + SPHERE CENTER 0.553573 -0.718878 -0.117284 RAD 0.0185185 + txt002 + SPHERE CENTER 0.563328 -0.73992 -0.108814 RAD 0.00617284 + txt002 + SPHERE CENTER 0.577348 -0.719679 -0.110668 RAD 0.00617284 + txt002 + SPHERE CENTER 0.559693 -0.720935 -0.0934517 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539553 -0.739118 -0.115431 RAD 0.00617284 + txt002 + SPHERE CENTER 0.535918 -0.720133 -0.100068 RAD 0.00617284 + txt002 + SPHERE CENTER 0.529798 -0.718076 -0.1239 RAD 0.00617284 + txt002 + SPHERE CENTER 0.557208 -0.737863 -0.132647 RAD 0.00617284 + txt002 + SPHERE CENTER 0.547453 -0.716821 -0.141116 RAD 0.00617284 + txt002 + SPHERE CENTER 0.571228 -0.717623 -0.1345 RAD 0.00617284 + txt002 + SPHERE CENTER 0.547112 -0.687216 -0.0506299 RAD 0.0185185 + txt002 + SPHERE CENTER 0.554862 -0.690713 -0.0274488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.570641 -0.682694 -0.0446649 RAD 0.00617284 + txt002 + SPHERE CENTER 0.552739 -0.667813 -0.0364345 RAD 0.00617284 + txt002 + SPHERE CENTER 0.531333 -0.695235 -0.0334138 RAD 0.00617284 + txt002 + SPHERE CENTER 0.52921 -0.672335 -0.0423994 RAD 0.00617284 + txt002 + SPHERE CENTER 0.523582 -0.691738 -0.0565949 RAD 0.00617284 + txt002 + SPHERE CENTER 0.549235 -0.710116 -0.0416443 RAD 0.00617284 + txt002 + SPHERE CENTER 0.541484 -0.706619 -0.0648253 RAD 0.00617284 + txt002 + SPHERE CENTER 0.565014 -0.702097 -0.0588603 RAD 0.00617284 + txt002 + SPHERE CENTER 0.491544 -0.682558 -0.099389 RAD 0.0185185 + txt002 + SPHERE CENTER 0.474542 -0.688647 -0.0825505 RAD 0.00617284 + txt002 + SPHERE CENTER 0.498226 -0.686417 -0.0759343 RAD 0.00617284 + txt002 + SPHERE CENTER 0.485132 -0.666351 -0.0818993 RAD 0.00617284 + txt002 + SPHERE CENTER 0.46786 -0.684788 -0.106005 RAD 0.00617284 + txt002 + SPHERE CENTER 0.47845 -0.662492 -0.105354 RAD 0.00617284 + txt002 + SPHERE CENTER 0.484862 -0.678699 -0.122844 RAD 0.00617284 + txt002 + SPHERE CENTER 0.480953 -0.704854 -0.10004 RAD 0.00617284 + txt002 + SPHERE CENTER 0.497955 -0.698765 -0.116879 RAD 0.00617284 + txt002 + SPHERE CENTER 0.504637 -0.702624 -0.093424 RAD 0.00617284 + txt002 + SPHERE CENTER 0.560805 -0.676727 -0.177765 RAD 0.0185185 + txt002 + SPHERE CENTER 0.57563 -0.689897 -0.192477 RAD 0.00617284 + txt002 + SPHERE CENTER 0.585222 -0.673115 -0.177114 RAD 0.00617284 + txt002 + SPHERE CENTER 0.575587 -0.693998 -0.168128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.551213 -0.693509 -0.193128 RAD 0.00617284 + txt002 + SPHERE CENTER 0.55117 -0.69761 -0.16878 RAD 0.00617284 + txt002 + SPHERE CENTER 0.536388 -0.680339 -0.178416 RAD 0.00617284 + txt002 + SPHERE CENTER 0.560848 -0.672626 -0.202114 RAD 0.00617284 + txt002 + SPHERE CENTER 0.546023 -0.659456 -0.187402 RAD 0.00617284 + txt002 + SPHERE CENTER 0.57044 -0.655844 -0.186751 RAD 0.00617284 + txt002 + SPHERE CENTER 0.498776 -0.640408 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.478525 -0.627785 -0.166213 RAD 0.00617284 + txt002 + SPHERE CENTER 0.484234 -0.630799 -0.142381 RAD 0.00617284 + txt002 + SPHERE CENTER 0.497935 -0.615951 -0.156576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.493066 -0.637394 -0.183703 RAD 0.00617284 + txt002 + SPHERE CENTER 0.512476 -0.62556 -0.174066 RAD 0.00617284 + txt002 + SPHERE CENTER 0.513317 -0.650016 -0.17736 RAD 0.00617284 + txt002 + SPHERE CENTER 0.479365 -0.652241 -0.169507 RAD 0.00617284 + txt002 + SPHERE CENTER 0.499616 -0.664864 -0.163165 RAD 0.00617284 + txt002 + SPHERE CENTER 0.485075 -0.655255 -0.145675 RAD 0.00617284 + txt002 + SPHERE CENTER 0.561576 -0.602915 -0.171592 RAD 0.0185185 + txt002 + SPHERE CENTER 0.570049 -0.602201 -0.194773 RAD 0.00617284 + txt002 + SPHERE CENTER 0.582252 -0.615021 -0.177557 RAD 0.00617284 + txt002 + SPHERE CENTER 0.560414 -0.623084 -0.185788 RAD 0.00617284 + txt002 + SPHERE CENTER 0.549372 -0.590095 -0.188808 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539737 -0.610978 -0.179823 RAD 0.00617284 + txt002 + SPHERE CENTER 0.540899 -0.590808 -0.165627 RAD 0.00617284 + txt002 + SPHERE CENTER 0.571211 -0.582032 -0.180578 RAD 0.00617284 + txt002 + SPHERE CENTER 0.562738 -0.582745 -0.157397 RAD 0.00617284 + txt002 + SPHERE CENTER 0.583414 -0.594852 -0.163362 RAD 0.00617284 + txt002 + SPHERE CENTER 0.335322 -0.607487 -0.111111 RAD 0.0555556 + txt002 + SPHERE CENTER 0.283164 -0.659645 -0.104315 RAD 0.0185185 + txt002 + SPHERE CENTER 0.269894 -0.672915 -0.0882695 RAD 0.00617284 + txt002 + SPHERE CENTER 0.293281 -0.666987 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.275822 -0.649528 -0.0830215 RAD 0.00617284 + txt002 + SPHERE CENTER 0.259777 -0.665573 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.265705 -0.642185 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.273047 -0.652302 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.277236 -0.683032 -0.109563 RAD 0.00617284 + txt002 + SPHERE CENTER 0.290507 -0.669762 -0.125608 RAD 0.00617284 + txt002 + SPHERE CENTER 0.300624 -0.677104 -0.104315 RAD 0.00617284 + txt002 + SPHERE CENTER 0.33883 -0.656357 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.350033 -0.661904 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.362764 -0.65113 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.345639 -0.638325 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.326099 -0.667131 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.321705 -0.643552 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.314897 -0.661584 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.343224 -0.679937 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.332022 -0.674389 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.355956 -0.669162 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.286452 -0.603979 -0.0555556 RAD 0.0185185 + txt002 + SPHERE CENTER 0.280905 -0.592776 -0.0342624 RAD 0.00617284 + txt002 + SPHERE CENTER 0.304484 -0.59717 -0.0401235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.291679 -0.580045 -0.0524691 RAD 0.00617284 + txt002 + SPHERE CENTER 0.262872 -0.599585 -0.0496945 RAD 0.00617284 + txt002 + SPHERE CENTER 0.273647 -0.586853 -0.0679012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.26842 -0.610787 -0.0709877 RAD 0.00617284 + txt002 + SPHERE CENTER 0.275678 -0.61671 -0.0373488 RAD 0.00617284 + txt002 + SPHERE CENTER 0.281225 -0.627912 -0.058642 RAD 0.00617284 + txt002 + SPHERE CENTER 0.299257 -0.621104 -0.0432099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.279656 -0.610775 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.256944 -0.602632 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.26347 -0.606749 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.273158 -0.587686 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.27313 -0.606658 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.289344 -0.591712 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.295841 -0.614801 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.263442 -0.62572 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.286153 -0.633864 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.269968 -0.629838 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282943 -0.555109 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.278768 -0.530773 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.298064 -0.539989 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.298064 -0.539989 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.263648 -0.545894 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282943 -0.555109 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.267823 -0.570229 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.263648 -0.545894 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.267823 -0.570229 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.282943 -0.555109 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.331813 -0.558618 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.342108 -0.551527 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.356248 -0.560372 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.341128 -0.575492 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.317673 -0.549772 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.316693 -0.573738 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.307378 -0.556863 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.332793 -0.534652 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.322499 -0.541743 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.346933 -0.543497 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.332034 -0.663153 -0.15987 RAD 0.0185185 + txt002 + SPHERE CENTER 0.340177 -0.685865 -0.165118 RAD 0.00617284 + txt002 + SPHERE CENTER 0.355123 -0.669651 -0.154009 RAD 0.00617284 + txt002 + SPHERE CENTER 0.33606 -0.679339 -0.141664 RAD 0.00617284 + txt002 + SPHERE CENTER 0.317089 -0.679367 -0.170979 RAD 0.00617284 + txt002 + SPHERE CENTER 0.312971 -0.672841 -0.147525 RAD 0.00617284 + txt002 + SPHERE CENTER 0.308945 -0.656656 -0.165731 RAD 0.00617284 + txt002 + SPHERE CENTER 0.336151 -0.669679 -0.183325 RAD 0.00617284 + txt002 + SPHERE CENTER 0.328008 -0.646968 -0.178077 RAD 0.00617284 + txt002 + SPHERE CENTER 0.351097 -0.653465 -0.172216 RAD 0.00617284 + txt002 + SPHERE CENTER 0.384191 -0.610996 -0.166667 RAD 0.0185185 + txt002 + SPHERE CENTER 0.391282 -0.600701 -0.18796 RAD 0.00617284 + txt002 + SPHERE CENTER 0.367317 -0.601681 -0.182099 RAD 0.00617284 + txt002 + SPHERE CENTER 0.382437 -0.586561 -0.169753 RAD 0.00617284 + txt002 + SPHERE CENTER 0.408157 -0.610016 -0.172528 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399312 -0.595876 -0.154321 RAD 0.00617284 + txt002 + SPHERE CENTER 0.401066 -0.62031 -0.151235 RAD 0.00617284 + txt002 + SPHERE CENTER 0.393037 -0.625136 -0.184873 RAD 0.00617284 + txt002 + SPHERE CENTER 0.385946 -0.635431 -0.16358 RAD 0.00617284 + txt002 + SPHERE CENTER 0.369071 -0.626116 -0.179012 RAD 0.00617284 + txt002 + SPHERE CENTER 0.3877 -0.659866 -0.111111 RAD 0.0185185 + txt002 + SPHERE CENTER 0.412036 -0.664041 -0.111111 RAD 0.00617284 + txt002 + SPHERE CENTER 0.40282 -0.644745 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.40282 -0.644745 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.396915 -0.679161 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.3877 -0.659866 -0.0864198 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37258 -0.674986 -0.0987654 RAD 0.00617284 + txt002 + SPHERE CENTER 0.396915 -0.679161 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.37258 -0.674986 -0.123457 RAD 0.00617284 + txt002 + SPHERE CENTER 0.3877 -0.659866 -0.135802 RAD 0.00617284 + txt002 + SPHERE CENTER 0.471405 -0.471405 -0.222222 RAD 0.0555556 + txt002 + SPHERE CENTER 0.441164 -0.441164 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.443014 -0.422853 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.449156 -0.418916 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.463412 -0.433171 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.435021 -0.445101 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.455419 -0.455419 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER 0.433171 -0.463412 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.420766 -0.430846 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER 0.418916 -0.449156 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.426908 -0.426908 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER 0.399854 -0.452233 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.383576 -0.43509 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.40305 -0.440308 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.406245 -0.428383 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.380381 -0.447015 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER 0.40305 -0.440308 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.396659 -0.464158 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.377186 -0.45894 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.393464 -0.476083 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.396659 -0.464158 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.452233 -0.399854 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.45894 -0.377186 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.476083 -0.393464 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.464158 -0.396659 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.43509 -0.383576 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.440308 -0.40305 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.428383 -0.406245 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.447015 -0.380381 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.440308 -0.40305 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.464158 -0.396659 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.512714 -0.460336 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.512375 -0.453047 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.493241 -0.465554 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER 0.497443 -0.44229 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.531849 -0.447829 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER 0.516916 -0.437072 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.532187 -0.455118 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER 0.527647 -0.471093 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.527985 -0.478381 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.508512 -0.483599 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.523783 -0.419026 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.538038 -0.404771 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER 0.532513 -0.427756 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.515053 -0.410297 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.529309 -0.396041 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.506323 -0.401567 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.515053 -0.410297 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.546768 -0.4135 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.532513 -0.427756 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.541242 -0.436486 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.542955 -0.490576 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.565623 -0.483869 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.54615 -0.478651 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.549345 -0.466726 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.562428 -0.495794 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.54615 -0.478651 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539759 -0.502501 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.559233 -0.507719 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.536564 -0.514426 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.539759 -0.502501 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.460336 -0.512714 -0.282703 RAD 0.0185185 + txt002 + SPHERE CENTER 0.461599 -0.535539 -0.292037 RAD 0.00617284 + txt002 + SPHERE CENTER 0.478381 -0.527985 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.455118 -0.532187 -0.268448 RAD 0.00617284 + txt002 + SPHERE CENTER 0.443553 -0.520267 -0.299164 RAD 0.00617284 + txt002 + SPHERE CENTER 0.437072 -0.516916 -0.275576 RAD 0.00617284 + txt002 + SPHERE CENTER 0.44229 -0.497443 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.466817 -0.516065 -0.306292 RAD 0.00617284 + txt002 + SPHERE CENTER 0.465554 -0.493241 -0.296959 RAD 0.00617284 + txt002 + SPHERE CENTER 0.483599 -0.508512 -0.289831 RAD 0.00617284 + txt002 + SPHERE CENTER 0.490576 -0.542955 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.507719 -0.559233 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.514426 -0.536564 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.502501 -0.539759 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.483869 -0.565623 -0.215094 RAD 0.00617284 + txt002 + SPHERE CENTER 0.478651 -0.54615 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.466726 -0.549345 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.495794 -0.562428 -0.236478 RAD 0.00617284 + txt002 + SPHERE CENTER 0.478651 -0.54615 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.502501 -0.539759 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.419026 -0.523783 -0.222222 RAD 0.0185185 + txt002 + SPHERE CENTER 0.404771 -0.538038 -0.207967 RAD 0.00617284 + txt002 + SPHERE CENTER 0.427756 -0.532513 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.410297 -0.515053 -0.200839 RAD 0.00617284 + txt002 + SPHERE CENTER 0.396041 -0.529309 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.401567 -0.506323 -0.222222 RAD 0.00617284 + txt002 + SPHERE CENTER 0.410297 -0.515053 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.4135 -0.546768 -0.22935 RAD 0.00617284 + txt002 + SPHERE CENTER 0.427756 -0.532513 -0.243606 RAD 0.00617284 + txt002 + SPHERE CENTER 0.436486 -0.541242 -0.222222 RAD 0.00617284 + txt002 + +END_SCENE diff --git a/src/tbb/examples/parallel_for/tachyon/dat/lattice.dat b/src/tbb/examples/parallel_for/tachyon/dat/lattice.dat new file mode 100644 index 0000000..fc40ed8 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/dat/lattice.dat @@ -0,0 +1,18012 @@ +BEGIN_SCENE + OUTFILE /dev/null + RESOLUTION 512 512 + VERBOSE 0 + +CAMERA + ZOOM 1.0 + ASPECTRATIO 1.0 + ANTIALIASING 0 + RAYDEPTH 8 + CENTER 0.5625 1 0.9375 + VIEWDIR 0 -0.707107 -0.707107 + UPDIR 0.272166 0.680414 -0.680414 + +END_CAMERA + +LIGHT CENTER 2 0.5 0.5 RAD 0.002 COLOR 0.5 0.5 0.5 + +LIGHT CENTER -1 0.5 0.5 RAD 0.002 COLOR 0.5 0.5 0.5 + +LIGHT CENTER 0.5 2 0.5 RAD 0.002 COLOR 0.5 0.5 0.5 + +LIGHT CENTER 0.5 -1 0.5 RAD 0.002 COLOR 0.5 0.5 0.5 + +LIGHT CENTER 0.5 0.5 2 RAD 0.002 COLOR 0.5 0.5 0.5 + +LIGHT CENTER 0.5 0.5 -1 RAD 0.002 COLOR 0.5 0.5 0.5 + +TEXDEF txt001 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0 0 RAD 0.03125 + txt001 +TEXDEF txt002 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0 0 APEX 0.109531 0 0 RAD 0.0078125 + txt002 +TEXDEF txt003 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.0154687 0 APEX 0 0.109531 0 RAD 0.0078125 + txt003 +TEXDEF txt004 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0 0.0154687 APEX 0 0 0.109531 RAD 0.0078125 + txt004 +TEXDEF txt005 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0 0.125 RAD 0.03125 + txt005 +TEXDEF txt006 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0 0.125 APEX 0.109531 0 0.125 RAD 0.0078125 + txt006 +TEXDEF txt007 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.0154687 0.125 APEX 0 0.109531 0.125 RAD 0.0078125 + txt007 +TEXDEF txt008 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0 0.140469 APEX 0 0 0.234531 RAD 0.0078125 + txt008 +TEXDEF txt009 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0 0.25 RAD 0.03125 + txt009 +TEXDEF txt010 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0 0.25 APEX 0.109531 0 0.25 RAD 0.0078125 + txt010 +TEXDEF txt011 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.0154687 0.25 APEX 0 0.109531 0.25 RAD 0.0078125 + txt011 +TEXDEF txt012 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0 0.265469 APEX 0 0 0.359531 RAD 0.0078125 + txt012 +TEXDEF txt013 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0 0.375 RAD 0.03125 + txt013 +TEXDEF txt014 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0 0.375 APEX 0.109531 0 0.375 RAD 0.0078125 + txt014 +TEXDEF txt015 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.0154687 0.375 APEX 0 0.109531 0.375 RAD 0.0078125 + txt015 +TEXDEF txt016 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0 0.390469 APEX 0 0 0.484531 RAD 0.0078125 + txt016 +TEXDEF txt017 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0 0.5 RAD 0.03125 + txt017 +TEXDEF txt018 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0 0.5 APEX 0.109531 0 0.5 RAD 0.0078125 + txt018 +TEXDEF txt019 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.0154687 0.5 APEX 0 0.109531 0.5 RAD 0.0078125 + txt019 +TEXDEF txt020 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0 0.515469 APEX 0 0 0.609531 RAD 0.0078125 + txt020 +TEXDEF txt021 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0 0.625 RAD 0.03125 + txt021 +TEXDEF txt022 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0 0.625 APEX 0.109531 0 0.625 RAD 0.0078125 + txt022 +TEXDEF txt023 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.0154687 0.625 APEX 0 0.109531 0.625 RAD 0.0078125 + txt023 +TEXDEF txt024 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0 0.640469 APEX 0 0 0.734531 RAD 0.0078125 + txt024 +TEXDEF txt025 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0 0.75 RAD 0.03125 + txt025 +TEXDEF txt026 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0 0.75 APEX 0.109531 0 0.75 RAD 0.0078125 + txt026 +TEXDEF txt027 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.0154687 0.75 APEX 0 0.109531 0.75 RAD 0.0078125 + txt027 +TEXDEF txt028 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0 0.765469 APEX 0 0 0.859531 RAD 0.0078125 + txt028 +TEXDEF txt029 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0 0.875 RAD 0.03125 + txt029 +TEXDEF txt030 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0 0.875 APEX 0.109531 0 0.875 RAD 0.0078125 + txt030 +TEXDEF txt031 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.0154687 0.875 APEX 0 0.109531 0.875 RAD 0.0078125 + txt031 +TEXDEF txt032 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0 0.890469 APEX 0 0 0.984531 RAD 0.0078125 + txt032 +TEXDEF txt033 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0 1 RAD 0.03125 + txt033 +TEXDEF txt034 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0 1 APEX 0.109531 0 1 RAD 0.0078125 + txt034 +TEXDEF txt035 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.0154687 1 APEX 0 0.109531 1 RAD 0.0078125 + txt035 +TEXDEF txt036 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.125 0 RAD 0.03125 + txt036 +TEXDEF txt037 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.125 0 APEX 0.109531 0.125 0 RAD 0.0078125 + txt037 +TEXDEF txt038 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.140469 0 APEX 0 0.234531 0 RAD 0.0078125 + txt038 +TEXDEF txt039 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.125 0.0154687 APEX 0 0.125 0.109531 RAD 0.0078125 + txt039 +TEXDEF txt040 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.125 0.125 RAD 0.03125 + txt040 +TEXDEF txt041 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.125 0.125 APEX 0.109531 0.125 0.125 RAD 0.0078125 + txt041 +TEXDEF txt042 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.140469 0.125 APEX 0 0.234531 0.125 RAD 0.0078125 + txt042 +TEXDEF txt043 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.125 0.140469 APEX 0 0.125 0.234531 RAD 0.0078125 + txt043 +TEXDEF txt044 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.125 0.25 RAD 0.03125 + txt044 +TEXDEF txt045 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.125 0.25 APEX 0.109531 0.125 0.25 RAD 0.0078125 + txt045 +TEXDEF txt046 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.140469 0.25 APEX 0 0.234531 0.25 RAD 0.0078125 + txt046 +TEXDEF txt047 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.125 0.265469 APEX 0 0.125 0.359531 RAD 0.0078125 + txt047 +TEXDEF txt048 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.125 0.375 RAD 0.03125 + txt048 +TEXDEF txt049 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.125 0.375 APEX 0.109531 0.125 0.375 RAD 0.0078125 + txt049 +TEXDEF txt050 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.140469 0.375 APEX 0 0.234531 0.375 RAD 0.0078125 + txt050 +TEXDEF txt051 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.125 0.390469 APEX 0 0.125 0.484531 RAD 0.0078125 + txt051 +TEXDEF txt052 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.125 0.5 RAD 0.03125 + txt052 +TEXDEF txt053 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.125 0.5 APEX 0.109531 0.125 0.5 RAD 0.0078125 + txt053 +TEXDEF txt054 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.140469 0.5 APEX 0 0.234531 0.5 RAD 0.0078125 + txt054 +TEXDEF txt055 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.125 0.515469 APEX 0 0.125 0.609531 RAD 0.0078125 + txt055 +TEXDEF txt056 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.125 0.625 RAD 0.03125 + txt056 +TEXDEF txt057 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.125 0.625 APEX 0.109531 0.125 0.625 RAD 0.0078125 + txt057 +TEXDEF txt058 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.140469 0.625 APEX 0 0.234531 0.625 RAD 0.0078125 + txt058 +TEXDEF txt059 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.125 0.640469 APEX 0 0.125 0.734531 RAD 0.0078125 + txt059 +TEXDEF txt060 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.125 0.75 RAD 0.03125 + txt060 +TEXDEF txt061 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.125 0.75 APEX 0.109531 0.125 0.75 RAD 0.0078125 + txt061 +TEXDEF txt062 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.140469 0.75 APEX 0 0.234531 0.75 RAD 0.0078125 + txt062 +TEXDEF txt063 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.125 0.765469 APEX 0 0.125 0.859531 RAD 0.0078125 + txt063 +TEXDEF txt064 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.125 0.875 RAD 0.03125 + txt064 +TEXDEF txt065 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.125 0.875 APEX 0.109531 0.125 0.875 RAD 0.0078125 + txt065 +TEXDEF txt066 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.140469 0.875 APEX 0 0.234531 0.875 RAD 0.0078125 + txt066 +TEXDEF txt067 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.125 0.890469 APEX 0 0.125 0.984531 RAD 0.0078125 + txt067 +TEXDEF txt068 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.125 1 RAD 0.03125 + txt068 +TEXDEF txt069 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.125 1 APEX 0.109531 0.125 1 RAD 0.0078125 + txt069 +TEXDEF txt070 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.140469 1 APEX 0 0.234531 1 RAD 0.0078125 + txt070 +TEXDEF txt071 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.25 0 RAD 0.03125 + txt071 +TEXDEF txt072 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.25 0 APEX 0.109531 0.25 0 RAD 0.0078125 + txt072 +TEXDEF txt073 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.265469 0 APEX 0 0.359531 0 RAD 0.0078125 + txt073 +TEXDEF txt074 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.25 0.0154687 APEX 0 0.25 0.109531 RAD 0.0078125 + txt074 +TEXDEF txt075 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.25 0.125 RAD 0.03125 + txt075 +TEXDEF txt076 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.25 0.125 APEX 0.109531 0.25 0.125 RAD 0.0078125 + txt076 +TEXDEF txt077 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.265469 0.125 APEX 0 0.359531 0.125 RAD 0.0078125 + txt077 +TEXDEF txt078 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.25 0.140469 APEX 0 0.25 0.234531 RAD 0.0078125 + txt078 +TEXDEF txt079 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.25 0.25 RAD 0.03125 + txt079 +TEXDEF txt080 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.25 0.25 APEX 0.109531 0.25 0.25 RAD 0.0078125 + txt080 +TEXDEF txt081 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.265469 0.25 APEX 0 0.359531 0.25 RAD 0.0078125 + txt081 +TEXDEF txt082 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.25 0.265469 APEX 0 0.25 0.359531 RAD 0.0078125 + txt082 +TEXDEF txt083 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.25 0.375 RAD 0.03125 + txt083 +TEXDEF txt084 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.25 0.375 APEX 0.109531 0.25 0.375 RAD 0.0078125 + txt084 +TEXDEF txt085 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.265469 0.375 APEX 0 0.359531 0.375 RAD 0.0078125 + txt085 +TEXDEF txt086 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.25 0.390469 APEX 0 0.25 0.484531 RAD 0.0078125 + txt086 +TEXDEF txt087 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.25 0.5 RAD 0.03125 + txt087 +TEXDEF txt088 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.25 0.5 APEX 0.109531 0.25 0.5 RAD 0.0078125 + txt088 +TEXDEF txt089 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.265469 0.5 APEX 0 0.359531 0.5 RAD 0.0078125 + txt089 +TEXDEF txt090 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.25 0.515469 APEX 0 0.25 0.609531 RAD 0.0078125 + txt090 +TEXDEF txt091 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.25 0.625 RAD 0.03125 + txt091 +TEXDEF txt092 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.25 0.625 APEX 0.109531 0.25 0.625 RAD 0.0078125 + txt092 +TEXDEF txt093 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.265469 0.625 APEX 0 0.359531 0.625 RAD 0.0078125 + txt093 +TEXDEF txt094 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.25 0.640469 APEX 0 0.25 0.734531 RAD 0.0078125 + txt094 +TEXDEF txt095 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.25 0.75 RAD 0.03125 + txt095 +TEXDEF txt096 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.25 0.75 APEX 0.109531 0.25 0.75 RAD 0.0078125 + txt096 +TEXDEF txt097 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.265469 0.75 APEX 0 0.359531 0.75 RAD 0.0078125 + txt097 +TEXDEF txt098 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.25 0.765469 APEX 0 0.25 0.859531 RAD 0.0078125 + txt098 +TEXDEF txt099 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.25 0.875 RAD 0.03125 + txt099 +TEXDEF txt100 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.25 0.875 APEX 0.109531 0.25 0.875 RAD 0.0078125 + txt100 +TEXDEF txt101 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.265469 0.875 APEX 0 0.359531 0.875 RAD 0.0078125 + txt101 +TEXDEF txt102 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.25 0.890469 APEX 0 0.25 0.984531 RAD 0.0078125 + txt102 +TEXDEF txt103 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.25 1 RAD 0.03125 + txt103 +TEXDEF txt104 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.25 1 APEX 0.109531 0.25 1 RAD 0.0078125 + txt104 +TEXDEF txt105 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.265469 1 APEX 0 0.359531 1 RAD 0.0078125 + txt105 +TEXDEF txt106 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.375 0 RAD 0.03125 + txt106 +TEXDEF txt107 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.375 0 APEX 0.109531 0.375 0 RAD 0.0078125 + txt107 +TEXDEF txt108 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.390469 0 APEX 0 0.484531 0 RAD 0.0078125 + txt108 +TEXDEF txt109 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.375 0.0154687 APEX 0 0.375 0.109531 RAD 0.0078125 + txt109 +TEXDEF txt110 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.375 0.125 RAD 0.03125 + txt110 +TEXDEF txt111 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.375 0.125 APEX 0.109531 0.375 0.125 RAD 0.0078125 + txt111 +TEXDEF txt112 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.390469 0.125 APEX 0 0.484531 0.125 RAD 0.0078125 + txt112 +TEXDEF txt113 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.375 0.140469 APEX 0 0.375 0.234531 RAD 0.0078125 + txt113 +TEXDEF txt114 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.375 0.25 RAD 0.03125 + txt114 +TEXDEF txt115 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.375 0.25 APEX 0.109531 0.375 0.25 RAD 0.0078125 + txt115 +TEXDEF txt116 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.390469 0.25 APEX 0 0.484531 0.25 RAD 0.0078125 + txt116 +TEXDEF txt117 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.375 0.265469 APEX 0 0.375 0.359531 RAD 0.0078125 + txt117 +TEXDEF txt118 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.375 0.375 RAD 0.03125 + txt118 +TEXDEF txt119 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.375 0.375 APEX 0.109531 0.375 0.375 RAD 0.0078125 + txt119 +TEXDEF txt120 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.390469 0.375 APEX 0 0.484531 0.375 RAD 0.0078125 + txt120 +TEXDEF txt121 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.375 0.390469 APEX 0 0.375 0.484531 RAD 0.0078125 + txt121 +TEXDEF txt122 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.375 0.5 RAD 0.03125 + txt122 +TEXDEF txt123 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.375 0.5 APEX 0.109531 0.375 0.5 RAD 0.0078125 + txt123 +TEXDEF txt124 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.390469 0.5 APEX 0 0.484531 0.5 RAD 0.0078125 + txt124 +TEXDEF txt125 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.375 0.515469 APEX 0 0.375 0.609531 RAD 0.0078125 + txt125 +TEXDEF txt126 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.375 0.625 RAD 0.03125 + txt126 +TEXDEF txt127 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.375 0.625 APEX 0.109531 0.375 0.625 RAD 0.0078125 + txt127 +TEXDEF txt128 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.390469 0.625 APEX 0 0.484531 0.625 RAD 0.0078125 + txt128 +TEXDEF txt129 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.375 0.640469 APEX 0 0.375 0.734531 RAD 0.0078125 + txt129 +TEXDEF txt130 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.375 0.75 RAD 0.03125 + txt130 +TEXDEF txt131 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.375 0.75 APEX 0.109531 0.375 0.75 RAD 0.0078125 + txt131 +TEXDEF txt132 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.390469 0.75 APEX 0 0.484531 0.75 RAD 0.0078125 + txt132 +TEXDEF txt133 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.375 0.765469 APEX 0 0.375 0.859531 RAD 0.0078125 + txt133 +TEXDEF txt134 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.375 0.875 RAD 0.03125 + txt134 +TEXDEF txt135 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.375 0.875 APEX 0.109531 0.375 0.875 RAD 0.0078125 + txt135 +TEXDEF txt136 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.390469 0.875 APEX 0 0.484531 0.875 RAD 0.0078125 + txt136 +TEXDEF txt137 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.375 0.890469 APEX 0 0.375 0.984531 RAD 0.0078125 + txt137 +TEXDEF txt138 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.375 1 RAD 0.03125 + txt138 +TEXDEF txt139 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.375 1 APEX 0.109531 0.375 1 RAD 0.0078125 + txt139 +TEXDEF txt140 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.390469 1 APEX 0 0.484531 1 RAD 0.0078125 + txt140 +TEXDEF txt141 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.5 0 RAD 0.03125 + txt141 +TEXDEF txt142 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.5 0 APEX 0.109531 0.5 0 RAD 0.0078125 + txt142 +TEXDEF txt143 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.515469 0 APEX 0 0.609531 0 RAD 0.0078125 + txt143 +TEXDEF txt144 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.5 0.0154687 APEX 0 0.5 0.109531 RAD 0.0078125 + txt144 +TEXDEF txt145 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.5 0.125 RAD 0.03125 + txt145 +TEXDEF txt146 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.5 0.125 APEX 0.109531 0.5 0.125 RAD 0.0078125 + txt146 +TEXDEF txt147 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.515469 0.125 APEX 0 0.609531 0.125 RAD 0.0078125 + txt147 +TEXDEF txt148 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.5 0.140469 APEX 0 0.5 0.234531 RAD 0.0078125 + txt148 +TEXDEF txt149 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.5 0.25 RAD 0.03125 + txt149 +TEXDEF txt150 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.5 0.25 APEX 0.109531 0.5 0.25 RAD 0.0078125 + txt150 +TEXDEF txt151 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.515469 0.25 APEX 0 0.609531 0.25 RAD 0.0078125 + txt151 +TEXDEF txt152 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.5 0.265469 APEX 0 0.5 0.359531 RAD 0.0078125 + txt152 +TEXDEF txt153 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.5 0.375 RAD 0.03125 + txt153 +TEXDEF txt154 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.5 0.375 APEX 0.109531 0.5 0.375 RAD 0.0078125 + txt154 +TEXDEF txt155 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.515469 0.375 APEX 0 0.609531 0.375 RAD 0.0078125 + txt155 +TEXDEF txt156 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.5 0.390469 APEX 0 0.5 0.484531 RAD 0.0078125 + txt156 +TEXDEF txt157 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.5 0.5 RAD 0.03125 + txt157 +TEXDEF txt158 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.5 0.5 APEX 0.109531 0.5 0.5 RAD 0.0078125 + txt158 +TEXDEF txt159 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.515469 0.5 APEX 0 0.609531 0.5 RAD 0.0078125 + txt159 +TEXDEF txt160 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.5 0.515469 APEX 0 0.5 0.609531 RAD 0.0078125 + txt160 +TEXDEF txt161 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.5 0.625 RAD 0.03125 + txt161 +TEXDEF txt162 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.5 0.625 APEX 0.109531 0.5 0.625 RAD 0.0078125 + txt162 +TEXDEF txt163 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.515469 0.625 APEX 0 0.609531 0.625 RAD 0.0078125 + txt163 +TEXDEF txt164 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.5 0.640469 APEX 0 0.5 0.734531 RAD 0.0078125 + txt164 +TEXDEF txt165 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.5 0.75 RAD 0.03125 + txt165 +TEXDEF txt166 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.5 0.75 APEX 0.109531 0.5 0.75 RAD 0.0078125 + txt166 +TEXDEF txt167 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.515469 0.75 APEX 0 0.609531 0.75 RAD 0.0078125 + txt167 +TEXDEF txt168 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.5 0.765469 APEX 0 0.5 0.859531 RAD 0.0078125 + txt168 +TEXDEF txt169 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.5 0.875 RAD 0.03125 + txt169 +TEXDEF txt170 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.5 0.875 APEX 0.109531 0.5 0.875 RAD 0.0078125 + txt170 +TEXDEF txt171 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.515469 0.875 APEX 0 0.609531 0.875 RAD 0.0078125 + txt171 +TEXDEF txt172 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.5 0.890469 APEX 0 0.5 0.984531 RAD 0.0078125 + txt172 +TEXDEF txt173 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.5 1 RAD 0.03125 + txt173 +TEXDEF txt174 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.5 1 APEX 0.109531 0.5 1 RAD 0.0078125 + txt174 +TEXDEF txt175 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.515469 1 APEX 0 0.609531 1 RAD 0.0078125 + txt175 +TEXDEF txt176 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.625 0 RAD 0.03125 + txt176 +TEXDEF txt177 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.625 0 APEX 0.109531 0.625 0 RAD 0.0078125 + txt177 +TEXDEF txt178 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.640469 0 APEX 0 0.734531 0 RAD 0.0078125 + txt178 +TEXDEF txt179 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.625 0.0154687 APEX 0 0.625 0.109531 RAD 0.0078125 + txt179 +TEXDEF txt180 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.625 0.125 RAD 0.03125 + txt180 +TEXDEF txt181 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.625 0.125 APEX 0.109531 0.625 0.125 RAD 0.0078125 + txt181 +TEXDEF txt182 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.640469 0.125 APEX 0 0.734531 0.125 RAD 0.0078125 + txt182 +TEXDEF txt183 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.625 0.140469 APEX 0 0.625 0.234531 RAD 0.0078125 + txt183 +TEXDEF txt184 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.625 0.25 RAD 0.03125 + txt184 +TEXDEF txt185 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.625 0.25 APEX 0.109531 0.625 0.25 RAD 0.0078125 + txt185 +TEXDEF txt186 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.640469 0.25 APEX 0 0.734531 0.25 RAD 0.0078125 + txt186 +TEXDEF txt187 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.625 0.265469 APEX 0 0.625 0.359531 RAD 0.0078125 + txt187 +TEXDEF txt188 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.625 0.375 RAD 0.03125 + txt188 +TEXDEF txt189 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.625 0.375 APEX 0.109531 0.625 0.375 RAD 0.0078125 + txt189 +TEXDEF txt190 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.640469 0.375 APEX 0 0.734531 0.375 RAD 0.0078125 + txt190 +TEXDEF txt191 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.625 0.390469 APEX 0 0.625 0.484531 RAD 0.0078125 + txt191 +TEXDEF txt192 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.625 0.5 RAD 0.03125 + txt192 +TEXDEF txt193 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.625 0.5 APEX 0.109531 0.625 0.5 RAD 0.0078125 + txt193 +TEXDEF txt194 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.640469 0.5 APEX 0 0.734531 0.5 RAD 0.0078125 + txt194 +TEXDEF txt195 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.625 0.515469 APEX 0 0.625 0.609531 RAD 0.0078125 + txt195 +TEXDEF txt196 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.625 0.625 RAD 0.03125 + txt196 +TEXDEF txt197 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.625 0.625 APEX 0.109531 0.625 0.625 RAD 0.0078125 + txt197 +TEXDEF txt198 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.640469 0.625 APEX 0 0.734531 0.625 RAD 0.0078125 + txt198 +TEXDEF txt199 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.625 0.640469 APEX 0 0.625 0.734531 RAD 0.0078125 + txt199 +TEXDEF txt200 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.625 0.75 RAD 0.03125 + txt200 +TEXDEF txt201 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.625 0.75 APEX 0.109531 0.625 0.75 RAD 0.0078125 + txt201 +TEXDEF txt202 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.640469 0.75 APEX 0 0.734531 0.75 RAD 0.0078125 + txt202 +TEXDEF txt203 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.625 0.765469 APEX 0 0.625 0.859531 RAD 0.0078125 + txt203 +TEXDEF txt204 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.625 0.875 RAD 0.03125 + txt204 +TEXDEF txt205 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.625 0.875 APEX 0.109531 0.625 0.875 RAD 0.0078125 + txt205 +TEXDEF txt206 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.640469 0.875 APEX 0 0.734531 0.875 RAD 0.0078125 + txt206 +TEXDEF txt207 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.625 0.890469 APEX 0 0.625 0.984531 RAD 0.0078125 + txt207 +TEXDEF txt208 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.625 1 RAD 0.03125 + txt208 +TEXDEF txt209 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.625 1 APEX 0.109531 0.625 1 RAD 0.0078125 + txt209 +TEXDEF txt210 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.640469 1 APEX 0 0.734531 1 RAD 0.0078125 + txt210 +TEXDEF txt211 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.75 0 RAD 0.03125 + txt211 +TEXDEF txt212 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.75 0 APEX 0.109531 0.75 0 RAD 0.0078125 + txt212 +TEXDEF txt213 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.765469 0 APEX 0 0.859531 0 RAD 0.0078125 + txt213 +TEXDEF txt214 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.75 0.0154687 APEX 0 0.75 0.109531 RAD 0.0078125 + txt214 +TEXDEF txt215 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.75 0.125 RAD 0.03125 + txt215 +TEXDEF txt216 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.75 0.125 APEX 0.109531 0.75 0.125 RAD 0.0078125 + txt216 +TEXDEF txt217 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.765469 0.125 APEX 0 0.859531 0.125 RAD 0.0078125 + txt217 +TEXDEF txt218 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.75 0.140469 APEX 0 0.75 0.234531 RAD 0.0078125 + txt218 +TEXDEF txt219 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.75 0.25 RAD 0.03125 + txt219 +TEXDEF txt220 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.75 0.25 APEX 0.109531 0.75 0.25 RAD 0.0078125 + txt220 +TEXDEF txt221 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.765469 0.25 APEX 0 0.859531 0.25 RAD 0.0078125 + txt221 +TEXDEF txt222 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.75 0.265469 APEX 0 0.75 0.359531 RAD 0.0078125 + txt222 +TEXDEF txt223 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.75 0.375 RAD 0.03125 + txt223 +TEXDEF txt224 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.75 0.375 APEX 0.109531 0.75 0.375 RAD 0.0078125 + txt224 +TEXDEF txt225 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.765469 0.375 APEX 0 0.859531 0.375 RAD 0.0078125 + txt225 +TEXDEF txt226 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.75 0.390469 APEX 0 0.75 0.484531 RAD 0.0078125 + txt226 +TEXDEF txt227 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.75 0.5 RAD 0.03125 + txt227 +TEXDEF txt228 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.75 0.5 APEX 0.109531 0.75 0.5 RAD 0.0078125 + txt228 +TEXDEF txt229 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.765469 0.5 APEX 0 0.859531 0.5 RAD 0.0078125 + txt229 +TEXDEF txt230 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.75 0.515469 APEX 0 0.75 0.609531 RAD 0.0078125 + txt230 +TEXDEF txt231 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.75 0.625 RAD 0.03125 + txt231 +TEXDEF txt232 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.75 0.625 APEX 0.109531 0.75 0.625 RAD 0.0078125 + txt232 +TEXDEF txt233 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.765469 0.625 APEX 0 0.859531 0.625 RAD 0.0078125 + txt233 +TEXDEF txt234 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.75 0.640469 APEX 0 0.75 0.734531 RAD 0.0078125 + txt234 +TEXDEF txt235 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.75 0.75 RAD 0.03125 + txt235 +TEXDEF txt236 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.75 0.75 APEX 0.109531 0.75 0.75 RAD 0.0078125 + txt236 +TEXDEF txt237 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.765469 0.75 APEX 0 0.859531 0.75 RAD 0.0078125 + txt237 +TEXDEF txt238 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.75 0.765469 APEX 0 0.75 0.859531 RAD 0.0078125 + txt238 +TEXDEF txt239 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.75 0.875 RAD 0.03125 + txt239 +TEXDEF txt240 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.75 0.875 APEX 0.109531 0.75 0.875 RAD 0.0078125 + txt240 +TEXDEF txt241 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.765469 0.875 APEX 0 0.859531 0.875 RAD 0.0078125 + txt241 +TEXDEF txt242 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.75 0.890469 APEX 0 0.75 0.984531 RAD 0.0078125 + txt242 +TEXDEF txt243 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.75 1 RAD 0.03125 + txt243 +TEXDEF txt244 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.75 1 APEX 0.109531 0.75 1 RAD 0.0078125 + txt244 +TEXDEF txt245 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.765469 1 APEX 0 0.859531 1 RAD 0.0078125 + txt245 +TEXDEF txt246 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.875 0 RAD 0.03125 + txt246 +TEXDEF txt247 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.875 0 APEX 0.109531 0.875 0 RAD 0.0078125 + txt247 +TEXDEF txt248 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.890469 0 APEX 0 0.984531 0 RAD 0.0078125 + txt248 +TEXDEF txt249 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.875 0.0154687 APEX 0 0.875 0.109531 RAD 0.0078125 + txt249 +TEXDEF txt250 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.875 0.125 RAD 0.03125 + txt250 +TEXDEF txt251 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.875 0.125 APEX 0.109531 0.875 0.125 RAD 0.0078125 + txt251 +TEXDEF txt252 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.890469 0.125 APEX 0 0.984531 0.125 RAD 0.0078125 + txt252 +TEXDEF txt253 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.875 0.140469 APEX 0 0.875 0.234531 RAD 0.0078125 + txt253 +TEXDEF txt254 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.875 0.25 RAD 0.03125 + txt254 +TEXDEF txt255 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.875 0.25 APEX 0.109531 0.875 0.25 RAD 0.0078125 + txt255 +TEXDEF txt256 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.890469 0.25 APEX 0 0.984531 0.25 RAD 0.0078125 + txt256 +TEXDEF txt257 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.875 0.265469 APEX 0 0.875 0.359531 RAD 0.0078125 + txt257 +TEXDEF txt258 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.875 0.375 RAD 0.03125 + txt258 +TEXDEF txt259 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.875 0.375 APEX 0.109531 0.875 0.375 RAD 0.0078125 + txt259 +TEXDEF txt260 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.890469 0.375 APEX 0 0.984531 0.375 RAD 0.0078125 + txt260 +TEXDEF txt261 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.875 0.390469 APEX 0 0.875 0.484531 RAD 0.0078125 + txt261 +TEXDEF txt262 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.875 0.5 RAD 0.03125 + txt262 +TEXDEF txt263 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.875 0.5 APEX 0.109531 0.875 0.5 RAD 0.0078125 + txt263 +TEXDEF txt264 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.890469 0.5 APEX 0 0.984531 0.5 RAD 0.0078125 + txt264 +TEXDEF txt265 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.875 0.515469 APEX 0 0.875 0.609531 RAD 0.0078125 + txt265 +TEXDEF txt266 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.875 0.625 RAD 0.03125 + txt266 +TEXDEF txt267 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.875 0.625 APEX 0.109531 0.875 0.625 RAD 0.0078125 + txt267 +TEXDEF txt268 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.890469 0.625 APEX 0 0.984531 0.625 RAD 0.0078125 + txt268 +TEXDEF txt269 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.875 0.640469 APEX 0 0.875 0.734531 RAD 0.0078125 + txt269 +TEXDEF txt270 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.875 0.75 RAD 0.03125 + txt270 +TEXDEF txt271 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.875 0.75 APEX 0.109531 0.875 0.75 RAD 0.0078125 + txt271 +TEXDEF txt272 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.890469 0.75 APEX 0 0.984531 0.75 RAD 0.0078125 + txt272 +TEXDEF txt273 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.875 0.765469 APEX 0 0.875 0.859531 RAD 0.0078125 + txt273 +TEXDEF txt274 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.875 0.875 RAD 0.03125 + txt274 +TEXDEF txt275 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.875 0.875 APEX 0.109531 0.875 0.875 RAD 0.0078125 + txt275 +TEXDEF txt276 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.890469 0.875 APEX 0 0.984531 0.875 RAD 0.0078125 + txt276 +TEXDEF txt277 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.875 0.890469 APEX 0 0.875 0.984531 RAD 0.0078125 + txt277 +TEXDEF txt278 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 0.875 1 RAD 0.03125 + txt278 +TEXDEF txt279 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 0.875 1 APEX 0.109531 0.875 1 RAD 0.0078125 + txt279 +TEXDEF txt280 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0 0.890469 1 APEX 0 0.984531 1 RAD 0.0078125 + txt280 +TEXDEF txt281 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 1 0 RAD 0.03125 + txt281 +TEXDEF txt282 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 1 0 APEX 0.109531 1 0 RAD 0.0078125 + txt282 +TEXDEF txt283 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 1 0.0154687 APEX 0 1 0.109531 RAD 0.0078125 + txt283 +TEXDEF txt284 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 1 0.125 RAD 0.03125 + txt284 +TEXDEF txt285 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 1 0.125 APEX 0.109531 1 0.125 RAD 0.0078125 + txt285 +TEXDEF txt286 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 1 0.140469 APEX 0 1 0.234531 RAD 0.0078125 + txt286 +TEXDEF txt287 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 1 0.25 RAD 0.03125 + txt287 +TEXDEF txt288 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 1 0.25 APEX 0.109531 1 0.25 RAD 0.0078125 + txt288 +TEXDEF txt289 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 1 0.265469 APEX 0 1 0.359531 RAD 0.0078125 + txt289 +TEXDEF txt290 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 1 0.375 RAD 0.03125 + txt290 +TEXDEF txt291 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 1 0.375 APEX 0.109531 1 0.375 RAD 0.0078125 + txt291 +TEXDEF txt292 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 1 0.390469 APEX 0 1 0.484531 RAD 0.0078125 + txt292 +TEXDEF txt293 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 1 0.5 RAD 0.03125 + txt293 +TEXDEF txt294 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 1 0.5 APEX 0.109531 1 0.5 RAD 0.0078125 + txt294 +TEXDEF txt295 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 1 0.515469 APEX 0 1 0.609531 RAD 0.0078125 + txt295 +TEXDEF txt296 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 1 0.625 RAD 0.03125 + txt296 +TEXDEF txt297 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 1 0.625 APEX 0.109531 1 0.625 RAD 0.0078125 + txt297 +TEXDEF txt298 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 1 0.640469 APEX 0 1 0.734531 RAD 0.0078125 + txt298 +TEXDEF txt299 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 1 0.75 RAD 0.03125 + txt299 +TEXDEF txt300 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 1 0.75 APEX 0.109531 1 0.75 RAD 0.0078125 + txt300 +TEXDEF txt301 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 1 0.765469 APEX 0 1 0.859531 RAD 0.0078125 + txt301 +TEXDEF txt302 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 1 0.875 RAD 0.03125 + txt302 +TEXDEF txt303 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 1 0.875 APEX 0.109531 1 0.875 RAD 0.0078125 + txt303 +TEXDEF txt304 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0 1 0.890469 APEX 0 1 0.984531 RAD 0.0078125 + txt304 +TEXDEF txt305 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0 1 1 RAD 0.03125 + txt305 +TEXDEF txt306 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.0154687 1 1 APEX 0.109531 1 1 RAD 0.0078125 + txt306 +TEXDEF txt307 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0 0 RAD 0.03125 + txt307 +TEXDEF txt308 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0 0 APEX 0.234531 0 0 RAD 0.0078125 + txt308 +TEXDEF txt309 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.0154687 0 APEX 0.125 0.109531 0 RAD 0.0078125 + txt309 +TEXDEF txt310 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0 0.0154687 APEX 0.125 0 0.109531 RAD 0.0078125 + txt310 +TEXDEF txt311 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0 0.125 RAD 0.03125 + txt311 +TEXDEF txt312 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0 0.125 APEX 0.234531 0 0.125 RAD 0.0078125 + txt312 +TEXDEF txt313 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.0154687 0.125 APEX 0.125 0.109531 0.125 RAD 0.0078125 + txt313 +TEXDEF txt314 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0 0.140469 APEX 0.125 0 0.234531 RAD 0.0078125 + txt314 +TEXDEF txt315 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0 0.25 RAD 0.03125 + txt315 +TEXDEF txt316 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0 0.25 APEX 0.234531 0 0.25 RAD 0.0078125 + txt316 +TEXDEF txt317 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.0154687 0.25 APEX 0.125 0.109531 0.25 RAD 0.0078125 + txt317 +TEXDEF txt318 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0 0.265469 APEX 0.125 0 0.359531 RAD 0.0078125 + txt318 +TEXDEF txt319 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0 0.375 RAD 0.03125 + txt319 +TEXDEF txt320 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0 0.375 APEX 0.234531 0 0.375 RAD 0.0078125 + txt320 +TEXDEF txt321 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.0154687 0.375 APEX 0.125 0.109531 0.375 RAD 0.0078125 + txt321 +TEXDEF txt322 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0 0.390469 APEX 0.125 0 0.484531 RAD 0.0078125 + txt322 +TEXDEF txt323 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0 0.5 RAD 0.03125 + txt323 +TEXDEF txt324 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0 0.5 APEX 0.234531 0 0.5 RAD 0.0078125 + txt324 +TEXDEF txt325 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.0154687 0.5 APEX 0.125 0.109531 0.5 RAD 0.0078125 + txt325 +TEXDEF txt326 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0 0.515469 APEX 0.125 0 0.609531 RAD 0.0078125 + txt326 +TEXDEF txt327 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0 0.625 RAD 0.03125 + txt327 +TEXDEF txt328 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0 0.625 APEX 0.234531 0 0.625 RAD 0.0078125 + txt328 +TEXDEF txt329 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.0154687 0.625 APEX 0.125 0.109531 0.625 RAD 0.0078125 + txt329 +TEXDEF txt330 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0 0.640469 APEX 0.125 0 0.734531 RAD 0.0078125 + txt330 +TEXDEF txt331 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0 0.75 RAD 0.03125 + txt331 +TEXDEF txt332 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0 0.75 APEX 0.234531 0 0.75 RAD 0.0078125 + txt332 +TEXDEF txt333 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.0154687 0.75 APEX 0.125 0.109531 0.75 RAD 0.0078125 + txt333 +TEXDEF txt334 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0 0.765469 APEX 0.125 0 0.859531 RAD 0.0078125 + txt334 +TEXDEF txt335 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0 0.875 RAD 0.03125 + txt335 +TEXDEF txt336 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0 0.875 APEX 0.234531 0 0.875 RAD 0.0078125 + txt336 +TEXDEF txt337 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.0154687 0.875 APEX 0.125 0.109531 0.875 RAD 0.0078125 + txt337 +TEXDEF txt338 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0 0.890469 APEX 0.125 0 0.984531 RAD 0.0078125 + txt338 +TEXDEF txt339 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0 1 RAD 0.03125 + txt339 +TEXDEF txt340 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0 1 APEX 0.234531 0 1 RAD 0.0078125 + txt340 +TEXDEF txt341 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.0154687 1 APEX 0.125 0.109531 1 RAD 0.0078125 + txt341 +TEXDEF txt342 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.125 0 RAD 0.03125 + txt342 +TEXDEF txt343 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.125 0 APEX 0.234531 0.125 0 RAD 0.0078125 + txt343 +TEXDEF txt344 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.140469 0 APEX 0.125 0.234531 0 RAD 0.0078125 + txt344 +TEXDEF txt345 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.125 0.0154687 APEX 0.125 0.125 0.109531 RAD 0.0078125 + txt345 +TEXDEF txt346 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.125 0.125 RAD 0.03125 + txt346 +TEXDEF txt347 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.125 0.125 APEX 0.234531 0.125 0.125 RAD 0.0078125 + txt347 +TEXDEF txt348 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.140469 0.125 APEX 0.125 0.234531 0.125 RAD 0.0078125 + txt348 +TEXDEF txt349 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.125 0.140469 APEX 0.125 0.125 0.234531 RAD 0.0078125 + txt349 +TEXDEF txt350 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.125 0.25 RAD 0.03125 + txt350 +TEXDEF txt351 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.125 0.25 APEX 0.234531 0.125 0.25 RAD 0.0078125 + txt351 +TEXDEF txt352 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.140469 0.25 APEX 0.125 0.234531 0.25 RAD 0.0078125 + txt352 +TEXDEF txt353 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.125 0.265469 APEX 0.125 0.125 0.359531 RAD 0.0078125 + txt353 +TEXDEF txt354 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.125 0.375 RAD 0.03125 + txt354 +TEXDEF txt355 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.125 0.375 APEX 0.234531 0.125 0.375 RAD 0.0078125 + txt355 +TEXDEF txt356 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.140469 0.375 APEX 0.125 0.234531 0.375 RAD 0.0078125 + txt356 +TEXDEF txt357 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.125 0.390469 APEX 0.125 0.125 0.484531 RAD 0.0078125 + txt357 +TEXDEF txt358 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.125 0.5 RAD 0.03125 + txt358 +TEXDEF txt359 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.125 0.5 APEX 0.234531 0.125 0.5 RAD 0.0078125 + txt359 +TEXDEF txt360 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.140469 0.5 APEX 0.125 0.234531 0.5 RAD 0.0078125 + txt360 +TEXDEF txt361 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.125 0.515469 APEX 0.125 0.125 0.609531 RAD 0.0078125 + txt361 +TEXDEF txt362 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.125 0.625 RAD 0.03125 + txt362 +TEXDEF txt363 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.125 0.625 APEX 0.234531 0.125 0.625 RAD 0.0078125 + txt363 +TEXDEF txt364 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.140469 0.625 APEX 0.125 0.234531 0.625 RAD 0.0078125 + txt364 +TEXDEF txt365 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.125 0.640469 APEX 0.125 0.125 0.734531 RAD 0.0078125 + txt365 +TEXDEF txt366 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.125 0.75 RAD 0.03125 + txt366 +TEXDEF txt367 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.125 0.75 APEX 0.234531 0.125 0.75 RAD 0.0078125 + txt367 +TEXDEF txt368 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.140469 0.75 APEX 0.125 0.234531 0.75 RAD 0.0078125 + txt368 +TEXDEF txt369 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.125 0.765469 APEX 0.125 0.125 0.859531 RAD 0.0078125 + txt369 +TEXDEF txt370 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.125 0.875 RAD 0.03125 + txt370 +TEXDEF txt371 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.125 0.875 APEX 0.234531 0.125 0.875 RAD 0.0078125 + txt371 +TEXDEF txt372 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.140469 0.875 APEX 0.125 0.234531 0.875 RAD 0.0078125 + txt372 +TEXDEF txt373 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.125 0.890469 APEX 0.125 0.125 0.984531 RAD 0.0078125 + txt373 +TEXDEF txt374 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.125 1 RAD 0.03125 + txt374 +TEXDEF txt375 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.125 1 APEX 0.234531 0.125 1 RAD 0.0078125 + txt375 +TEXDEF txt376 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.140469 1 APEX 0.125 0.234531 1 RAD 0.0078125 + txt376 +TEXDEF txt377 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.25 0 RAD 0.03125 + txt377 +TEXDEF txt378 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.25 0 APEX 0.234531 0.25 0 RAD 0.0078125 + txt378 +TEXDEF txt379 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.265469 0 APEX 0.125 0.359531 0 RAD 0.0078125 + txt379 +TEXDEF txt380 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.25 0.0154687 APEX 0.125 0.25 0.109531 RAD 0.0078125 + txt380 +TEXDEF txt381 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.25 0.125 RAD 0.03125 + txt381 +TEXDEF txt382 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.25 0.125 APEX 0.234531 0.25 0.125 RAD 0.0078125 + txt382 +TEXDEF txt383 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.265469 0.125 APEX 0.125 0.359531 0.125 RAD 0.0078125 + txt383 +TEXDEF txt384 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.25 0.140469 APEX 0.125 0.25 0.234531 RAD 0.0078125 + txt384 +TEXDEF txt385 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.25 0.25 RAD 0.03125 + txt385 +TEXDEF txt386 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.25 0.25 APEX 0.234531 0.25 0.25 RAD 0.0078125 + txt386 +TEXDEF txt387 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.265469 0.25 APEX 0.125 0.359531 0.25 RAD 0.0078125 + txt387 +TEXDEF txt388 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.25 0.265469 APEX 0.125 0.25 0.359531 RAD 0.0078125 + txt388 +TEXDEF txt389 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.25 0.375 RAD 0.03125 + txt389 +TEXDEF txt390 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.25 0.375 APEX 0.234531 0.25 0.375 RAD 0.0078125 + txt390 +TEXDEF txt391 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.265469 0.375 APEX 0.125 0.359531 0.375 RAD 0.0078125 + txt391 +TEXDEF txt392 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.25 0.390469 APEX 0.125 0.25 0.484531 RAD 0.0078125 + txt392 +TEXDEF txt393 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.25 0.5 RAD 0.03125 + txt393 +TEXDEF txt394 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.25 0.5 APEX 0.234531 0.25 0.5 RAD 0.0078125 + txt394 +TEXDEF txt395 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.265469 0.5 APEX 0.125 0.359531 0.5 RAD 0.0078125 + txt395 +TEXDEF txt396 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.25 0.515469 APEX 0.125 0.25 0.609531 RAD 0.0078125 + txt396 +TEXDEF txt397 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.25 0.625 RAD 0.03125 + txt397 +TEXDEF txt398 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.25 0.625 APEX 0.234531 0.25 0.625 RAD 0.0078125 + txt398 +TEXDEF txt399 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.265469 0.625 APEX 0.125 0.359531 0.625 RAD 0.0078125 + txt399 +TEXDEF txt400 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.25 0.640469 APEX 0.125 0.25 0.734531 RAD 0.0078125 + txt400 +TEXDEF txt401 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.25 0.75 RAD 0.03125 + txt401 +TEXDEF txt402 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.25 0.75 APEX 0.234531 0.25 0.75 RAD 0.0078125 + txt402 +TEXDEF txt403 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.265469 0.75 APEX 0.125 0.359531 0.75 RAD 0.0078125 + txt403 +TEXDEF txt404 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.25 0.765469 APEX 0.125 0.25 0.859531 RAD 0.0078125 + txt404 +TEXDEF txt405 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.25 0.875 RAD 0.03125 + txt405 +TEXDEF txt406 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.25 0.875 APEX 0.234531 0.25 0.875 RAD 0.0078125 + txt406 +TEXDEF txt407 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.265469 0.875 APEX 0.125 0.359531 0.875 RAD 0.0078125 + txt407 +TEXDEF txt408 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.25 0.890469 APEX 0.125 0.25 0.984531 RAD 0.0078125 + txt408 +TEXDEF txt409 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.25 1 RAD 0.03125 + txt409 +TEXDEF txt410 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.25 1 APEX 0.234531 0.25 1 RAD 0.0078125 + txt410 +TEXDEF txt411 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.265469 1 APEX 0.125 0.359531 1 RAD 0.0078125 + txt411 +TEXDEF txt412 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.375 0 RAD 0.03125 + txt412 +TEXDEF txt413 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.375 0 APEX 0.234531 0.375 0 RAD 0.0078125 + txt413 +TEXDEF txt414 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.390469 0 APEX 0.125 0.484531 0 RAD 0.0078125 + txt414 +TEXDEF txt415 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.375 0.0154687 APEX 0.125 0.375 0.109531 RAD 0.0078125 + txt415 +TEXDEF txt416 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.375 0.125 RAD 0.03125 + txt416 +TEXDEF txt417 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.375 0.125 APEX 0.234531 0.375 0.125 RAD 0.0078125 + txt417 +TEXDEF txt418 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.390469 0.125 APEX 0.125 0.484531 0.125 RAD 0.0078125 + txt418 +TEXDEF txt419 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.375 0.140469 APEX 0.125 0.375 0.234531 RAD 0.0078125 + txt419 +TEXDEF txt420 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.375 0.25 RAD 0.03125 + txt420 +TEXDEF txt421 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.375 0.25 APEX 0.234531 0.375 0.25 RAD 0.0078125 + txt421 +TEXDEF txt422 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.390469 0.25 APEX 0.125 0.484531 0.25 RAD 0.0078125 + txt422 +TEXDEF txt423 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.375 0.265469 APEX 0.125 0.375 0.359531 RAD 0.0078125 + txt423 +TEXDEF txt424 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.375 0.375 RAD 0.03125 + txt424 +TEXDEF txt425 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.375 0.375 APEX 0.234531 0.375 0.375 RAD 0.0078125 + txt425 +TEXDEF txt426 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.390469 0.375 APEX 0.125 0.484531 0.375 RAD 0.0078125 + txt426 +TEXDEF txt427 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.375 0.390469 APEX 0.125 0.375 0.484531 RAD 0.0078125 + txt427 +TEXDEF txt428 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.375 0.5 RAD 0.03125 + txt428 +TEXDEF txt429 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.375 0.5 APEX 0.234531 0.375 0.5 RAD 0.0078125 + txt429 +TEXDEF txt430 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.390469 0.5 APEX 0.125 0.484531 0.5 RAD 0.0078125 + txt430 +TEXDEF txt431 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.375 0.515469 APEX 0.125 0.375 0.609531 RAD 0.0078125 + txt431 +TEXDEF txt432 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.375 0.625 RAD 0.03125 + txt432 +TEXDEF txt433 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.375 0.625 APEX 0.234531 0.375 0.625 RAD 0.0078125 + txt433 +TEXDEF txt434 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.390469 0.625 APEX 0.125 0.484531 0.625 RAD 0.0078125 + txt434 +TEXDEF txt435 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.375 0.640469 APEX 0.125 0.375 0.734531 RAD 0.0078125 + txt435 +TEXDEF txt436 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.375 0.75 RAD 0.03125 + txt436 +TEXDEF txt437 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.375 0.75 APEX 0.234531 0.375 0.75 RAD 0.0078125 + txt437 +TEXDEF txt438 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.390469 0.75 APEX 0.125 0.484531 0.75 RAD 0.0078125 + txt438 +TEXDEF txt439 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.375 0.765469 APEX 0.125 0.375 0.859531 RAD 0.0078125 + txt439 +TEXDEF txt440 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.375 0.875 RAD 0.03125 + txt440 +TEXDEF txt441 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.375 0.875 APEX 0.234531 0.375 0.875 RAD 0.0078125 + txt441 +TEXDEF txt442 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.390469 0.875 APEX 0.125 0.484531 0.875 RAD 0.0078125 + txt442 +TEXDEF txt443 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.375 0.890469 APEX 0.125 0.375 0.984531 RAD 0.0078125 + txt443 +TEXDEF txt444 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.375 1 RAD 0.03125 + txt444 +TEXDEF txt445 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.375 1 APEX 0.234531 0.375 1 RAD 0.0078125 + txt445 +TEXDEF txt446 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.390469 1 APEX 0.125 0.484531 1 RAD 0.0078125 + txt446 +TEXDEF txt447 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.5 0 RAD 0.03125 + txt447 +TEXDEF txt448 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.5 0 APEX 0.234531 0.5 0 RAD 0.0078125 + txt448 +TEXDEF txt449 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.515469 0 APEX 0.125 0.609531 0 RAD 0.0078125 + txt449 +TEXDEF txt450 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.5 0.0154687 APEX 0.125 0.5 0.109531 RAD 0.0078125 + txt450 +TEXDEF txt451 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.5 0.125 RAD 0.03125 + txt451 +TEXDEF txt452 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.5 0.125 APEX 0.234531 0.5 0.125 RAD 0.0078125 + txt452 +TEXDEF txt453 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.515469 0.125 APEX 0.125 0.609531 0.125 RAD 0.0078125 + txt453 +TEXDEF txt454 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.5 0.140469 APEX 0.125 0.5 0.234531 RAD 0.0078125 + txt454 +TEXDEF txt455 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.5 0.25 RAD 0.03125 + txt455 +TEXDEF txt456 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.5 0.25 APEX 0.234531 0.5 0.25 RAD 0.0078125 + txt456 +TEXDEF txt457 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.515469 0.25 APEX 0.125 0.609531 0.25 RAD 0.0078125 + txt457 +TEXDEF txt458 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.5 0.265469 APEX 0.125 0.5 0.359531 RAD 0.0078125 + txt458 +TEXDEF txt459 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.5 0.375 RAD 0.03125 + txt459 +TEXDEF txt460 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.5 0.375 APEX 0.234531 0.5 0.375 RAD 0.0078125 + txt460 +TEXDEF txt461 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.515469 0.375 APEX 0.125 0.609531 0.375 RAD 0.0078125 + txt461 +TEXDEF txt462 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.5 0.390469 APEX 0.125 0.5 0.484531 RAD 0.0078125 + txt462 +TEXDEF txt463 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.5 0.5 RAD 0.03125 + txt463 +TEXDEF txt464 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.5 0.5 APEX 0.234531 0.5 0.5 RAD 0.0078125 + txt464 +TEXDEF txt465 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.515469 0.5 APEX 0.125 0.609531 0.5 RAD 0.0078125 + txt465 +TEXDEF txt466 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.5 0.515469 APEX 0.125 0.5 0.609531 RAD 0.0078125 + txt466 +TEXDEF txt467 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.5 0.625 RAD 0.03125 + txt467 +TEXDEF txt468 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.5 0.625 APEX 0.234531 0.5 0.625 RAD 0.0078125 + txt468 +TEXDEF txt469 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.515469 0.625 APEX 0.125 0.609531 0.625 RAD 0.0078125 + txt469 +TEXDEF txt470 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.5 0.640469 APEX 0.125 0.5 0.734531 RAD 0.0078125 + txt470 +TEXDEF txt471 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.5 0.75 RAD 0.03125 + txt471 +TEXDEF txt472 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.5 0.75 APEX 0.234531 0.5 0.75 RAD 0.0078125 + txt472 +TEXDEF txt473 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.515469 0.75 APEX 0.125 0.609531 0.75 RAD 0.0078125 + txt473 +TEXDEF txt474 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.5 0.765469 APEX 0.125 0.5 0.859531 RAD 0.0078125 + txt474 +TEXDEF txt475 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.5 0.875 RAD 0.03125 + txt475 +TEXDEF txt476 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.5 0.875 APEX 0.234531 0.5 0.875 RAD 0.0078125 + txt476 +TEXDEF txt477 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.515469 0.875 APEX 0.125 0.609531 0.875 RAD 0.0078125 + txt477 +TEXDEF txt478 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.5 0.890469 APEX 0.125 0.5 0.984531 RAD 0.0078125 + txt478 +TEXDEF txt479 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.5 1 RAD 0.03125 + txt479 +TEXDEF txt480 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.5 1 APEX 0.234531 0.5 1 RAD 0.0078125 + txt480 +TEXDEF txt481 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.515469 1 APEX 0.125 0.609531 1 RAD 0.0078125 + txt481 +TEXDEF txt482 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.625 0 RAD 0.03125 + txt482 +TEXDEF txt483 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.625 0 APEX 0.234531 0.625 0 RAD 0.0078125 + txt483 +TEXDEF txt484 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.640469 0 APEX 0.125 0.734531 0 RAD 0.0078125 + txt484 +TEXDEF txt485 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.625 0.0154687 APEX 0.125 0.625 0.109531 RAD 0.0078125 + txt485 +TEXDEF txt486 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.625 0.125 RAD 0.03125 + txt486 +TEXDEF txt487 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.625 0.125 APEX 0.234531 0.625 0.125 RAD 0.0078125 + txt487 +TEXDEF txt488 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.640469 0.125 APEX 0.125 0.734531 0.125 RAD 0.0078125 + txt488 +TEXDEF txt489 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.625 0.140469 APEX 0.125 0.625 0.234531 RAD 0.0078125 + txt489 +TEXDEF txt490 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.625 0.25 RAD 0.03125 + txt490 +TEXDEF txt491 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.625 0.25 APEX 0.234531 0.625 0.25 RAD 0.0078125 + txt491 +TEXDEF txt492 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.640469 0.25 APEX 0.125 0.734531 0.25 RAD 0.0078125 + txt492 +TEXDEF txt493 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.625 0.265469 APEX 0.125 0.625 0.359531 RAD 0.0078125 + txt493 +TEXDEF txt494 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.625 0.375 RAD 0.03125 + txt494 +TEXDEF txt495 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.625 0.375 APEX 0.234531 0.625 0.375 RAD 0.0078125 + txt495 +TEXDEF txt496 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.640469 0.375 APEX 0.125 0.734531 0.375 RAD 0.0078125 + txt496 +TEXDEF txt497 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.625 0.390469 APEX 0.125 0.625 0.484531 RAD 0.0078125 + txt497 +TEXDEF txt498 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.625 0.5 RAD 0.03125 + txt498 +TEXDEF txt499 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.625 0.5 APEX 0.234531 0.625 0.5 RAD 0.0078125 + txt499 +TEXDEF txt500 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.640469 0.5 APEX 0.125 0.734531 0.5 RAD 0.0078125 + txt500 +TEXDEF txt501 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.625 0.515469 APEX 0.125 0.625 0.609531 RAD 0.0078125 + txt501 +TEXDEF txt502 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.625 0.625 RAD 0.03125 + txt502 +TEXDEF txt503 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.625 0.625 APEX 0.234531 0.625 0.625 RAD 0.0078125 + txt503 +TEXDEF txt504 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.640469 0.625 APEX 0.125 0.734531 0.625 RAD 0.0078125 + txt504 +TEXDEF txt505 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.625 0.640469 APEX 0.125 0.625 0.734531 RAD 0.0078125 + txt505 +TEXDEF txt506 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.625 0.75 RAD 0.03125 + txt506 +TEXDEF txt507 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.625 0.75 APEX 0.234531 0.625 0.75 RAD 0.0078125 + txt507 +TEXDEF txt508 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.640469 0.75 APEX 0.125 0.734531 0.75 RAD 0.0078125 + txt508 +TEXDEF txt509 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.625 0.765469 APEX 0.125 0.625 0.859531 RAD 0.0078125 + txt509 +TEXDEF txt510 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.625 0.875 RAD 0.03125 + txt510 +TEXDEF txt511 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.625 0.875 APEX 0.234531 0.625 0.875 RAD 0.0078125 + txt511 +TEXDEF txt512 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.640469 0.875 APEX 0.125 0.734531 0.875 RAD 0.0078125 + txt512 +TEXDEF txt513 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.625 0.890469 APEX 0.125 0.625 0.984531 RAD 0.0078125 + txt513 +TEXDEF txt514 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.625 1 RAD 0.03125 + txt514 +TEXDEF txt515 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.625 1 APEX 0.234531 0.625 1 RAD 0.0078125 + txt515 +TEXDEF txt516 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.640469 1 APEX 0.125 0.734531 1 RAD 0.0078125 + txt516 +TEXDEF txt517 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.75 0 RAD 0.03125 + txt517 +TEXDEF txt518 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.75 0 APEX 0.234531 0.75 0 RAD 0.0078125 + txt518 +TEXDEF txt519 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.765469 0 APEX 0.125 0.859531 0 RAD 0.0078125 + txt519 +TEXDEF txt520 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.75 0.0154687 APEX 0.125 0.75 0.109531 RAD 0.0078125 + txt520 +TEXDEF txt521 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.75 0.125 RAD 0.03125 + txt521 +TEXDEF txt522 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.75 0.125 APEX 0.234531 0.75 0.125 RAD 0.0078125 + txt522 +TEXDEF txt523 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.765469 0.125 APEX 0.125 0.859531 0.125 RAD 0.0078125 + txt523 +TEXDEF txt524 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.75 0.140469 APEX 0.125 0.75 0.234531 RAD 0.0078125 + txt524 +TEXDEF txt525 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.75 0.25 RAD 0.03125 + txt525 +TEXDEF txt526 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.75 0.25 APEX 0.234531 0.75 0.25 RAD 0.0078125 + txt526 +TEXDEF txt527 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.765469 0.25 APEX 0.125 0.859531 0.25 RAD 0.0078125 + txt527 +TEXDEF txt528 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.75 0.265469 APEX 0.125 0.75 0.359531 RAD 0.0078125 + txt528 +TEXDEF txt529 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.75 0.375 RAD 0.03125 + txt529 +TEXDEF txt530 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.75 0.375 APEX 0.234531 0.75 0.375 RAD 0.0078125 + txt530 +TEXDEF txt531 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.765469 0.375 APEX 0.125 0.859531 0.375 RAD 0.0078125 + txt531 +TEXDEF txt532 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.75 0.390469 APEX 0.125 0.75 0.484531 RAD 0.0078125 + txt532 +TEXDEF txt533 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.75 0.5 RAD 0.03125 + txt533 +TEXDEF txt534 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.75 0.5 APEX 0.234531 0.75 0.5 RAD 0.0078125 + txt534 +TEXDEF txt535 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.765469 0.5 APEX 0.125 0.859531 0.5 RAD 0.0078125 + txt535 +TEXDEF txt536 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.75 0.515469 APEX 0.125 0.75 0.609531 RAD 0.0078125 + txt536 +TEXDEF txt537 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.75 0.625 RAD 0.03125 + txt537 +TEXDEF txt538 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.75 0.625 APEX 0.234531 0.75 0.625 RAD 0.0078125 + txt538 +TEXDEF txt539 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.765469 0.625 APEX 0.125 0.859531 0.625 RAD 0.0078125 + txt539 +TEXDEF txt540 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.75 0.640469 APEX 0.125 0.75 0.734531 RAD 0.0078125 + txt540 +TEXDEF txt541 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.75 0.75 RAD 0.03125 + txt541 +TEXDEF txt542 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.75 0.75 APEX 0.234531 0.75 0.75 RAD 0.0078125 + txt542 +TEXDEF txt543 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.765469 0.75 APEX 0.125 0.859531 0.75 RAD 0.0078125 + txt543 +TEXDEF txt544 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.75 0.765469 APEX 0.125 0.75 0.859531 RAD 0.0078125 + txt544 +TEXDEF txt545 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.75 0.875 RAD 0.03125 + txt545 +TEXDEF txt546 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.75 0.875 APEX 0.234531 0.75 0.875 RAD 0.0078125 + txt546 +TEXDEF txt547 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.765469 0.875 APEX 0.125 0.859531 0.875 RAD 0.0078125 + txt547 +TEXDEF txt548 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.75 0.890469 APEX 0.125 0.75 0.984531 RAD 0.0078125 + txt548 +TEXDEF txt549 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.75 1 RAD 0.03125 + txt549 +TEXDEF txt550 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.75 1 APEX 0.234531 0.75 1 RAD 0.0078125 + txt550 +TEXDEF txt551 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.765469 1 APEX 0.125 0.859531 1 RAD 0.0078125 + txt551 +TEXDEF txt552 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.875 0 RAD 0.03125 + txt552 +TEXDEF txt553 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.875 0 APEX 0.234531 0.875 0 RAD 0.0078125 + txt553 +TEXDEF txt554 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.890469 0 APEX 0.125 0.984531 0 RAD 0.0078125 + txt554 +TEXDEF txt555 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.875 0.0154687 APEX 0.125 0.875 0.109531 RAD 0.0078125 + txt555 +TEXDEF txt556 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.875 0.125 RAD 0.03125 + txt556 +TEXDEF txt557 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.875 0.125 APEX 0.234531 0.875 0.125 RAD 0.0078125 + txt557 +TEXDEF txt558 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.890469 0.125 APEX 0.125 0.984531 0.125 RAD 0.0078125 + txt558 +TEXDEF txt559 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.875 0.140469 APEX 0.125 0.875 0.234531 RAD 0.0078125 + txt559 +TEXDEF txt560 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.875 0.25 RAD 0.03125 + txt560 +TEXDEF txt561 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.875 0.25 APEX 0.234531 0.875 0.25 RAD 0.0078125 + txt561 +TEXDEF txt562 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.890469 0.25 APEX 0.125 0.984531 0.25 RAD 0.0078125 + txt562 +TEXDEF txt563 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.875 0.265469 APEX 0.125 0.875 0.359531 RAD 0.0078125 + txt563 +TEXDEF txt564 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.875 0.375 RAD 0.03125 + txt564 +TEXDEF txt565 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.875 0.375 APEX 0.234531 0.875 0.375 RAD 0.0078125 + txt565 +TEXDEF txt566 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.890469 0.375 APEX 0.125 0.984531 0.375 RAD 0.0078125 + txt566 +TEXDEF txt567 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.875 0.390469 APEX 0.125 0.875 0.484531 RAD 0.0078125 + txt567 +TEXDEF txt568 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.875 0.5 RAD 0.03125 + txt568 +TEXDEF txt569 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.875 0.5 APEX 0.234531 0.875 0.5 RAD 0.0078125 + txt569 +TEXDEF txt570 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.890469 0.5 APEX 0.125 0.984531 0.5 RAD 0.0078125 + txt570 +TEXDEF txt571 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.875 0.515469 APEX 0.125 0.875 0.609531 RAD 0.0078125 + txt571 +TEXDEF txt572 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.875 0.625 RAD 0.03125 + txt572 +TEXDEF txt573 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.875 0.625 APEX 0.234531 0.875 0.625 RAD 0.0078125 + txt573 +TEXDEF txt574 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.890469 0.625 APEX 0.125 0.984531 0.625 RAD 0.0078125 + txt574 +TEXDEF txt575 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.875 0.640469 APEX 0.125 0.875 0.734531 RAD 0.0078125 + txt575 +TEXDEF txt576 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.875 0.75 RAD 0.03125 + txt576 +TEXDEF txt577 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.875 0.75 APEX 0.234531 0.875 0.75 RAD 0.0078125 + txt577 +TEXDEF txt578 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.890469 0.75 APEX 0.125 0.984531 0.75 RAD 0.0078125 + txt578 +TEXDEF txt579 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.875 0.765469 APEX 0.125 0.875 0.859531 RAD 0.0078125 + txt579 +TEXDEF txt580 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.875 0.875 RAD 0.03125 + txt580 +TEXDEF txt581 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.875 0.875 APEX 0.234531 0.875 0.875 RAD 0.0078125 + txt581 +TEXDEF txt582 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.890469 0.875 APEX 0.125 0.984531 0.875 RAD 0.0078125 + txt582 +TEXDEF txt583 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.875 0.890469 APEX 0.125 0.875 0.984531 RAD 0.0078125 + txt583 +TEXDEF txt584 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 0.875 1 RAD 0.03125 + txt584 +TEXDEF txt585 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 0.875 1 APEX 0.234531 0.875 1 RAD 0.0078125 + txt585 +TEXDEF txt586 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 0.890469 1 APEX 0.125 0.984531 1 RAD 0.0078125 + txt586 +TEXDEF txt587 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 1 0 RAD 0.03125 + txt587 +TEXDEF txt588 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 1 0 APEX 0.234531 1 0 RAD 0.0078125 + txt588 +TEXDEF txt589 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 1 0.0154687 APEX 0.125 1 0.109531 RAD 0.0078125 + txt589 +TEXDEF txt590 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 1 0.125 RAD 0.03125 + txt590 +TEXDEF txt591 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 1 0.125 APEX 0.234531 1 0.125 RAD 0.0078125 + txt591 +TEXDEF txt592 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 1 0.140469 APEX 0.125 1 0.234531 RAD 0.0078125 + txt592 +TEXDEF txt593 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 1 0.25 RAD 0.03125 + txt593 +TEXDEF txt594 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 1 0.25 APEX 0.234531 1 0.25 RAD 0.0078125 + txt594 +TEXDEF txt595 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 1 0.265469 APEX 0.125 1 0.359531 RAD 0.0078125 + txt595 +TEXDEF txt596 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 1 0.375 RAD 0.03125 + txt596 +TEXDEF txt597 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 1 0.375 APEX 0.234531 1 0.375 RAD 0.0078125 + txt597 +TEXDEF txt598 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 1 0.390469 APEX 0.125 1 0.484531 RAD 0.0078125 + txt598 +TEXDEF txt599 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 1 0.5 RAD 0.03125 + txt599 +TEXDEF txt600 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 1 0.5 APEX 0.234531 1 0.5 RAD 0.0078125 + txt600 +TEXDEF txt601 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 1 0.515469 APEX 0.125 1 0.609531 RAD 0.0078125 + txt601 +TEXDEF txt602 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 1 0.625 RAD 0.03125 + txt602 +TEXDEF txt603 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 1 0.625 APEX 0.234531 1 0.625 RAD 0.0078125 + txt603 +TEXDEF txt604 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 1 0.640469 APEX 0.125 1 0.734531 RAD 0.0078125 + txt604 +TEXDEF txt605 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 1 0.75 RAD 0.03125 + txt605 +TEXDEF txt606 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 1 0.75 APEX 0.234531 1 0.75 RAD 0.0078125 + txt606 +TEXDEF txt607 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 1 0.765469 APEX 0.125 1 0.859531 RAD 0.0078125 + txt607 +TEXDEF txt608 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 1 0.875 RAD 0.03125 + txt608 +TEXDEF txt609 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 1 0.875 APEX 0.234531 1 0.875 RAD 0.0078125 + txt609 +TEXDEF txt610 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.125 1 0.890469 APEX 0.125 1 0.984531 RAD 0.0078125 + txt610 +TEXDEF txt611 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.125 1 1 RAD 0.03125 + txt611 +TEXDEF txt612 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.140469 1 1 APEX 0.234531 1 1 RAD 0.0078125 + txt612 +TEXDEF txt613 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0 0 RAD 0.03125 + txt613 +TEXDEF txt614 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0 0 APEX 0.359531 0 0 RAD 0.0078125 + txt614 +TEXDEF txt615 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.0154687 0 APEX 0.25 0.109531 0 RAD 0.0078125 + txt615 +TEXDEF txt616 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0 0.0154687 APEX 0.25 0 0.109531 RAD 0.0078125 + txt616 +TEXDEF txt617 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0 0.125 RAD 0.03125 + txt617 +TEXDEF txt618 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0 0.125 APEX 0.359531 0 0.125 RAD 0.0078125 + txt618 +TEXDEF txt619 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.0154687 0.125 APEX 0.25 0.109531 0.125 RAD 0.0078125 + txt619 +TEXDEF txt620 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0 0.140469 APEX 0.25 0 0.234531 RAD 0.0078125 + txt620 +TEXDEF txt621 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0 0.25 RAD 0.03125 + txt621 +TEXDEF txt622 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0 0.25 APEX 0.359531 0 0.25 RAD 0.0078125 + txt622 +TEXDEF txt623 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.0154687 0.25 APEX 0.25 0.109531 0.25 RAD 0.0078125 + txt623 +TEXDEF txt624 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0 0.265469 APEX 0.25 0 0.359531 RAD 0.0078125 + txt624 +TEXDEF txt625 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0 0.375 RAD 0.03125 + txt625 +TEXDEF txt626 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0 0.375 APEX 0.359531 0 0.375 RAD 0.0078125 + txt626 +TEXDEF txt627 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.0154687 0.375 APEX 0.25 0.109531 0.375 RAD 0.0078125 + txt627 +TEXDEF txt628 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0 0.390469 APEX 0.25 0 0.484531 RAD 0.0078125 + txt628 +TEXDEF txt629 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0 0.5 RAD 0.03125 + txt629 +TEXDEF txt630 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0 0.5 APEX 0.359531 0 0.5 RAD 0.0078125 + txt630 +TEXDEF txt631 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.0154687 0.5 APEX 0.25 0.109531 0.5 RAD 0.0078125 + txt631 +TEXDEF txt632 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0 0.515469 APEX 0.25 0 0.609531 RAD 0.0078125 + txt632 +TEXDEF txt633 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0 0.625 RAD 0.03125 + txt633 +TEXDEF txt634 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0 0.625 APEX 0.359531 0 0.625 RAD 0.0078125 + txt634 +TEXDEF txt635 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.0154687 0.625 APEX 0.25 0.109531 0.625 RAD 0.0078125 + txt635 +TEXDEF txt636 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0 0.640469 APEX 0.25 0 0.734531 RAD 0.0078125 + txt636 +TEXDEF txt637 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0 0.75 RAD 0.03125 + txt637 +TEXDEF txt638 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0 0.75 APEX 0.359531 0 0.75 RAD 0.0078125 + txt638 +TEXDEF txt639 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.0154687 0.75 APEX 0.25 0.109531 0.75 RAD 0.0078125 + txt639 +TEXDEF txt640 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0 0.765469 APEX 0.25 0 0.859531 RAD 0.0078125 + txt640 +TEXDEF txt641 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0 0.875 RAD 0.03125 + txt641 +TEXDEF txt642 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0 0.875 APEX 0.359531 0 0.875 RAD 0.0078125 + txt642 +TEXDEF txt643 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.0154687 0.875 APEX 0.25 0.109531 0.875 RAD 0.0078125 + txt643 +TEXDEF txt644 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0 0.890469 APEX 0.25 0 0.984531 RAD 0.0078125 + txt644 +TEXDEF txt645 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0 1 RAD 0.03125 + txt645 +TEXDEF txt646 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0 1 APEX 0.359531 0 1 RAD 0.0078125 + txt646 +TEXDEF txt647 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.0154687 1 APEX 0.25 0.109531 1 RAD 0.0078125 + txt647 +TEXDEF txt648 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.125 0 RAD 0.03125 + txt648 +TEXDEF txt649 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.125 0 APEX 0.359531 0.125 0 RAD 0.0078125 + txt649 +TEXDEF txt650 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.140469 0 APEX 0.25 0.234531 0 RAD 0.0078125 + txt650 +TEXDEF txt651 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.125 0.0154687 APEX 0.25 0.125 0.109531 RAD 0.0078125 + txt651 +TEXDEF txt652 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.125 0.125 RAD 0.03125 + txt652 +TEXDEF txt653 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.125 0.125 APEX 0.359531 0.125 0.125 RAD 0.0078125 + txt653 +TEXDEF txt654 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.140469 0.125 APEX 0.25 0.234531 0.125 RAD 0.0078125 + txt654 +TEXDEF txt655 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.125 0.140469 APEX 0.25 0.125 0.234531 RAD 0.0078125 + txt655 +TEXDEF txt656 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.125 0.25 RAD 0.03125 + txt656 +TEXDEF txt657 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.125 0.25 APEX 0.359531 0.125 0.25 RAD 0.0078125 + txt657 +TEXDEF txt658 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.140469 0.25 APEX 0.25 0.234531 0.25 RAD 0.0078125 + txt658 +TEXDEF txt659 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.125 0.265469 APEX 0.25 0.125 0.359531 RAD 0.0078125 + txt659 +TEXDEF txt660 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.125 0.375 RAD 0.03125 + txt660 +TEXDEF txt661 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.125 0.375 APEX 0.359531 0.125 0.375 RAD 0.0078125 + txt661 +TEXDEF txt662 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.140469 0.375 APEX 0.25 0.234531 0.375 RAD 0.0078125 + txt662 +TEXDEF txt663 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.125 0.390469 APEX 0.25 0.125 0.484531 RAD 0.0078125 + txt663 +TEXDEF txt664 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.125 0.5 RAD 0.03125 + txt664 +TEXDEF txt665 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.125 0.5 APEX 0.359531 0.125 0.5 RAD 0.0078125 + txt665 +TEXDEF txt666 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.140469 0.5 APEX 0.25 0.234531 0.5 RAD 0.0078125 + txt666 +TEXDEF txt667 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.125 0.515469 APEX 0.25 0.125 0.609531 RAD 0.0078125 + txt667 +TEXDEF txt668 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.125 0.625 RAD 0.03125 + txt668 +TEXDEF txt669 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.125 0.625 APEX 0.359531 0.125 0.625 RAD 0.0078125 + txt669 +TEXDEF txt670 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.140469 0.625 APEX 0.25 0.234531 0.625 RAD 0.0078125 + txt670 +TEXDEF txt671 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.125 0.640469 APEX 0.25 0.125 0.734531 RAD 0.0078125 + txt671 +TEXDEF txt672 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.125 0.75 RAD 0.03125 + txt672 +TEXDEF txt673 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.125 0.75 APEX 0.359531 0.125 0.75 RAD 0.0078125 + txt673 +TEXDEF txt674 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.140469 0.75 APEX 0.25 0.234531 0.75 RAD 0.0078125 + txt674 +TEXDEF txt675 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.125 0.765469 APEX 0.25 0.125 0.859531 RAD 0.0078125 + txt675 +TEXDEF txt676 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.125 0.875 RAD 0.03125 + txt676 +TEXDEF txt677 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.125 0.875 APEX 0.359531 0.125 0.875 RAD 0.0078125 + txt677 +TEXDEF txt678 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.140469 0.875 APEX 0.25 0.234531 0.875 RAD 0.0078125 + txt678 +TEXDEF txt679 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.125 0.890469 APEX 0.25 0.125 0.984531 RAD 0.0078125 + txt679 +TEXDEF txt680 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.125 1 RAD 0.03125 + txt680 +TEXDEF txt681 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.125 1 APEX 0.359531 0.125 1 RAD 0.0078125 + txt681 +TEXDEF txt682 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.140469 1 APEX 0.25 0.234531 1 RAD 0.0078125 + txt682 +TEXDEF txt683 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.25 0 RAD 0.03125 + txt683 +TEXDEF txt684 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.25 0 APEX 0.359531 0.25 0 RAD 0.0078125 + txt684 +TEXDEF txt685 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.265469 0 APEX 0.25 0.359531 0 RAD 0.0078125 + txt685 +TEXDEF txt686 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.25 0.0154687 APEX 0.25 0.25 0.109531 RAD 0.0078125 + txt686 +TEXDEF txt687 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.25 0.125 RAD 0.03125 + txt687 +TEXDEF txt688 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.25 0.125 APEX 0.359531 0.25 0.125 RAD 0.0078125 + txt688 +TEXDEF txt689 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.265469 0.125 APEX 0.25 0.359531 0.125 RAD 0.0078125 + txt689 +TEXDEF txt690 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.25 0.140469 APEX 0.25 0.25 0.234531 RAD 0.0078125 + txt690 +TEXDEF txt691 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.25 0.25 RAD 0.03125 + txt691 +TEXDEF txt692 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.25 0.25 APEX 0.359531 0.25 0.25 RAD 0.0078125 + txt692 +TEXDEF txt693 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.265469 0.25 APEX 0.25 0.359531 0.25 RAD 0.0078125 + txt693 +TEXDEF txt694 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.25 0.265469 APEX 0.25 0.25 0.359531 RAD 0.0078125 + txt694 +TEXDEF txt695 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.25 0.375 RAD 0.03125 + txt695 +TEXDEF txt696 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.25 0.375 APEX 0.359531 0.25 0.375 RAD 0.0078125 + txt696 +TEXDEF txt697 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.265469 0.375 APEX 0.25 0.359531 0.375 RAD 0.0078125 + txt697 +TEXDEF txt698 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.25 0.390469 APEX 0.25 0.25 0.484531 RAD 0.0078125 + txt698 +TEXDEF txt699 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.25 0.5 RAD 0.03125 + txt699 +TEXDEF txt700 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.25 0.5 APEX 0.359531 0.25 0.5 RAD 0.0078125 + txt700 +TEXDEF txt701 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.265469 0.5 APEX 0.25 0.359531 0.5 RAD 0.0078125 + txt701 +TEXDEF txt702 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.25 0.515469 APEX 0.25 0.25 0.609531 RAD 0.0078125 + txt702 +TEXDEF txt703 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.25 0.625 RAD 0.03125 + txt703 +TEXDEF txt704 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.25 0.625 APEX 0.359531 0.25 0.625 RAD 0.0078125 + txt704 +TEXDEF txt705 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.265469 0.625 APEX 0.25 0.359531 0.625 RAD 0.0078125 + txt705 +TEXDEF txt706 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.25 0.640469 APEX 0.25 0.25 0.734531 RAD 0.0078125 + txt706 +TEXDEF txt707 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.25 0.75 RAD 0.03125 + txt707 +TEXDEF txt708 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.25 0.75 APEX 0.359531 0.25 0.75 RAD 0.0078125 + txt708 +TEXDEF txt709 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.265469 0.75 APEX 0.25 0.359531 0.75 RAD 0.0078125 + txt709 +TEXDEF txt710 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.25 0.765469 APEX 0.25 0.25 0.859531 RAD 0.0078125 + txt710 +TEXDEF txt711 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.25 0.875 RAD 0.03125 + txt711 +TEXDEF txt712 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.25 0.875 APEX 0.359531 0.25 0.875 RAD 0.0078125 + txt712 +TEXDEF txt713 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.265469 0.875 APEX 0.25 0.359531 0.875 RAD 0.0078125 + txt713 +TEXDEF txt714 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.25 0.890469 APEX 0.25 0.25 0.984531 RAD 0.0078125 + txt714 +TEXDEF txt715 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.25 1 RAD 0.03125 + txt715 +TEXDEF txt716 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.25 1 APEX 0.359531 0.25 1 RAD 0.0078125 + txt716 +TEXDEF txt717 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.265469 1 APEX 0.25 0.359531 1 RAD 0.0078125 + txt717 +TEXDEF txt718 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.375 0 RAD 0.03125 + txt718 +TEXDEF txt719 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.375 0 APEX 0.359531 0.375 0 RAD 0.0078125 + txt719 +TEXDEF txt720 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.390469 0 APEX 0.25 0.484531 0 RAD 0.0078125 + txt720 +TEXDEF txt721 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.375 0.0154687 APEX 0.25 0.375 0.109531 RAD 0.0078125 + txt721 +TEXDEF txt722 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.375 0.125 RAD 0.03125 + txt722 +TEXDEF txt723 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.375 0.125 APEX 0.359531 0.375 0.125 RAD 0.0078125 + txt723 +TEXDEF txt724 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.390469 0.125 APEX 0.25 0.484531 0.125 RAD 0.0078125 + txt724 +TEXDEF txt725 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.375 0.140469 APEX 0.25 0.375 0.234531 RAD 0.0078125 + txt725 +TEXDEF txt726 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.375 0.25 RAD 0.03125 + txt726 +TEXDEF txt727 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.375 0.25 APEX 0.359531 0.375 0.25 RAD 0.0078125 + txt727 +TEXDEF txt728 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.390469 0.25 APEX 0.25 0.484531 0.25 RAD 0.0078125 + txt728 +TEXDEF txt729 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.375 0.265469 APEX 0.25 0.375 0.359531 RAD 0.0078125 + txt729 +TEXDEF txt730 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.375 0.375 RAD 0.03125 + txt730 +TEXDEF txt731 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.375 0.375 APEX 0.359531 0.375 0.375 RAD 0.0078125 + txt731 +TEXDEF txt732 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.390469 0.375 APEX 0.25 0.484531 0.375 RAD 0.0078125 + txt732 +TEXDEF txt733 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.375 0.390469 APEX 0.25 0.375 0.484531 RAD 0.0078125 + txt733 +TEXDEF txt734 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.375 0.5 RAD 0.03125 + txt734 +TEXDEF txt735 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.375 0.5 APEX 0.359531 0.375 0.5 RAD 0.0078125 + txt735 +TEXDEF txt736 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.390469 0.5 APEX 0.25 0.484531 0.5 RAD 0.0078125 + txt736 +TEXDEF txt737 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.375 0.515469 APEX 0.25 0.375 0.609531 RAD 0.0078125 + txt737 +TEXDEF txt738 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.375 0.625 RAD 0.03125 + txt738 +TEXDEF txt739 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.375 0.625 APEX 0.359531 0.375 0.625 RAD 0.0078125 + txt739 +TEXDEF txt740 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.390469 0.625 APEX 0.25 0.484531 0.625 RAD 0.0078125 + txt740 +TEXDEF txt741 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.375 0.640469 APEX 0.25 0.375 0.734531 RAD 0.0078125 + txt741 +TEXDEF txt742 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.375 0.75 RAD 0.03125 + txt742 +TEXDEF txt743 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.375 0.75 APEX 0.359531 0.375 0.75 RAD 0.0078125 + txt743 +TEXDEF txt744 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.390469 0.75 APEX 0.25 0.484531 0.75 RAD 0.0078125 + txt744 +TEXDEF txt745 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.375 0.765469 APEX 0.25 0.375 0.859531 RAD 0.0078125 + txt745 +TEXDEF txt746 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.375 0.875 RAD 0.03125 + txt746 +TEXDEF txt747 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.375 0.875 APEX 0.359531 0.375 0.875 RAD 0.0078125 + txt747 +TEXDEF txt748 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.390469 0.875 APEX 0.25 0.484531 0.875 RAD 0.0078125 + txt748 +TEXDEF txt749 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.375 0.890469 APEX 0.25 0.375 0.984531 RAD 0.0078125 + txt749 +TEXDEF txt750 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.375 1 RAD 0.03125 + txt750 +TEXDEF txt751 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.375 1 APEX 0.359531 0.375 1 RAD 0.0078125 + txt751 +TEXDEF txt752 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.390469 1 APEX 0.25 0.484531 1 RAD 0.0078125 + txt752 +TEXDEF txt753 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.5 0 RAD 0.03125 + txt753 +TEXDEF txt754 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.5 0 APEX 0.359531 0.5 0 RAD 0.0078125 + txt754 +TEXDEF txt755 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.515469 0 APEX 0.25 0.609531 0 RAD 0.0078125 + txt755 +TEXDEF txt756 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.5 0.0154687 APEX 0.25 0.5 0.109531 RAD 0.0078125 + txt756 +TEXDEF txt757 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.5 0.125 RAD 0.03125 + txt757 +TEXDEF txt758 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.5 0.125 APEX 0.359531 0.5 0.125 RAD 0.0078125 + txt758 +TEXDEF txt759 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.515469 0.125 APEX 0.25 0.609531 0.125 RAD 0.0078125 + txt759 +TEXDEF txt760 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.5 0.140469 APEX 0.25 0.5 0.234531 RAD 0.0078125 + txt760 +TEXDEF txt761 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.5 0.25 RAD 0.03125 + txt761 +TEXDEF txt762 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.5 0.25 APEX 0.359531 0.5 0.25 RAD 0.0078125 + txt762 +TEXDEF txt763 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.515469 0.25 APEX 0.25 0.609531 0.25 RAD 0.0078125 + txt763 +TEXDEF txt764 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.5 0.265469 APEX 0.25 0.5 0.359531 RAD 0.0078125 + txt764 +TEXDEF txt765 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.5 0.375 RAD 0.03125 + txt765 +TEXDEF txt766 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.5 0.375 APEX 0.359531 0.5 0.375 RAD 0.0078125 + txt766 +TEXDEF txt767 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.515469 0.375 APEX 0.25 0.609531 0.375 RAD 0.0078125 + txt767 +TEXDEF txt768 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.5 0.390469 APEX 0.25 0.5 0.484531 RAD 0.0078125 + txt768 +TEXDEF txt769 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.5 0.5 RAD 0.03125 + txt769 +TEXDEF txt770 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.5 0.5 APEX 0.359531 0.5 0.5 RAD 0.0078125 + txt770 +TEXDEF txt771 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.515469 0.5 APEX 0.25 0.609531 0.5 RAD 0.0078125 + txt771 +TEXDEF txt772 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.5 0.515469 APEX 0.25 0.5 0.609531 RAD 0.0078125 + txt772 +TEXDEF txt773 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.5 0.625 RAD 0.03125 + txt773 +TEXDEF txt774 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.5 0.625 APEX 0.359531 0.5 0.625 RAD 0.0078125 + txt774 +TEXDEF txt775 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.515469 0.625 APEX 0.25 0.609531 0.625 RAD 0.0078125 + txt775 +TEXDEF txt776 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.5 0.640469 APEX 0.25 0.5 0.734531 RAD 0.0078125 + txt776 +TEXDEF txt777 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.5 0.75 RAD 0.03125 + txt777 +TEXDEF txt778 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.5 0.75 APEX 0.359531 0.5 0.75 RAD 0.0078125 + txt778 +TEXDEF txt779 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.515469 0.75 APEX 0.25 0.609531 0.75 RAD 0.0078125 + txt779 +TEXDEF txt780 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.5 0.765469 APEX 0.25 0.5 0.859531 RAD 0.0078125 + txt780 +TEXDEF txt781 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.5 0.875 RAD 0.03125 + txt781 +TEXDEF txt782 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.5 0.875 APEX 0.359531 0.5 0.875 RAD 0.0078125 + txt782 +TEXDEF txt783 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.515469 0.875 APEX 0.25 0.609531 0.875 RAD 0.0078125 + txt783 +TEXDEF txt784 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.5 0.890469 APEX 0.25 0.5 0.984531 RAD 0.0078125 + txt784 +TEXDEF txt785 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.5 1 RAD 0.03125 + txt785 +TEXDEF txt786 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.5 1 APEX 0.359531 0.5 1 RAD 0.0078125 + txt786 +TEXDEF txt787 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.515469 1 APEX 0.25 0.609531 1 RAD 0.0078125 + txt787 +TEXDEF txt788 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.625 0 RAD 0.03125 + txt788 +TEXDEF txt789 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.625 0 APEX 0.359531 0.625 0 RAD 0.0078125 + txt789 +TEXDEF txt790 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.640469 0 APEX 0.25 0.734531 0 RAD 0.0078125 + txt790 +TEXDEF txt791 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.625 0.0154687 APEX 0.25 0.625 0.109531 RAD 0.0078125 + txt791 +TEXDEF txt792 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.625 0.125 RAD 0.03125 + txt792 +TEXDEF txt793 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.625 0.125 APEX 0.359531 0.625 0.125 RAD 0.0078125 + txt793 +TEXDEF txt794 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.640469 0.125 APEX 0.25 0.734531 0.125 RAD 0.0078125 + txt794 +TEXDEF txt795 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.625 0.140469 APEX 0.25 0.625 0.234531 RAD 0.0078125 + txt795 +TEXDEF txt796 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.625 0.25 RAD 0.03125 + txt796 +TEXDEF txt797 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.625 0.25 APEX 0.359531 0.625 0.25 RAD 0.0078125 + txt797 +TEXDEF txt798 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.640469 0.25 APEX 0.25 0.734531 0.25 RAD 0.0078125 + txt798 +TEXDEF txt799 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.625 0.265469 APEX 0.25 0.625 0.359531 RAD 0.0078125 + txt799 +TEXDEF txt800 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.625 0.375 RAD 0.03125 + txt800 +TEXDEF txt801 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.625 0.375 APEX 0.359531 0.625 0.375 RAD 0.0078125 + txt801 +TEXDEF txt802 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.640469 0.375 APEX 0.25 0.734531 0.375 RAD 0.0078125 + txt802 +TEXDEF txt803 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.625 0.390469 APEX 0.25 0.625 0.484531 RAD 0.0078125 + txt803 +TEXDEF txt804 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.625 0.5 RAD 0.03125 + txt804 +TEXDEF txt805 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.625 0.5 APEX 0.359531 0.625 0.5 RAD 0.0078125 + txt805 +TEXDEF txt806 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.640469 0.5 APEX 0.25 0.734531 0.5 RAD 0.0078125 + txt806 +TEXDEF txt807 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.625 0.515469 APEX 0.25 0.625 0.609531 RAD 0.0078125 + txt807 +TEXDEF txt808 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.625 0.625 RAD 0.03125 + txt808 +TEXDEF txt809 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.625 0.625 APEX 0.359531 0.625 0.625 RAD 0.0078125 + txt809 +TEXDEF txt810 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.640469 0.625 APEX 0.25 0.734531 0.625 RAD 0.0078125 + txt810 +TEXDEF txt811 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.625 0.640469 APEX 0.25 0.625 0.734531 RAD 0.0078125 + txt811 +TEXDEF txt812 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.625 0.75 RAD 0.03125 + txt812 +TEXDEF txt813 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.625 0.75 APEX 0.359531 0.625 0.75 RAD 0.0078125 + txt813 +TEXDEF txt814 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.640469 0.75 APEX 0.25 0.734531 0.75 RAD 0.0078125 + txt814 +TEXDEF txt815 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.625 0.765469 APEX 0.25 0.625 0.859531 RAD 0.0078125 + txt815 +TEXDEF txt816 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.625 0.875 RAD 0.03125 + txt816 +TEXDEF txt817 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.625 0.875 APEX 0.359531 0.625 0.875 RAD 0.0078125 + txt817 +TEXDEF txt818 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.640469 0.875 APEX 0.25 0.734531 0.875 RAD 0.0078125 + txt818 +TEXDEF txt819 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.625 0.890469 APEX 0.25 0.625 0.984531 RAD 0.0078125 + txt819 +TEXDEF txt820 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.625 1 RAD 0.03125 + txt820 +TEXDEF txt821 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.625 1 APEX 0.359531 0.625 1 RAD 0.0078125 + txt821 +TEXDEF txt822 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.640469 1 APEX 0.25 0.734531 1 RAD 0.0078125 + txt822 +TEXDEF txt823 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.75 0 RAD 0.03125 + txt823 +TEXDEF txt824 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.75 0 APEX 0.359531 0.75 0 RAD 0.0078125 + txt824 +TEXDEF txt825 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.765469 0 APEX 0.25 0.859531 0 RAD 0.0078125 + txt825 +TEXDEF txt826 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.75 0.0154687 APEX 0.25 0.75 0.109531 RAD 0.0078125 + txt826 +TEXDEF txt827 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.75 0.125 RAD 0.03125 + txt827 +TEXDEF txt828 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.75 0.125 APEX 0.359531 0.75 0.125 RAD 0.0078125 + txt828 +TEXDEF txt829 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.765469 0.125 APEX 0.25 0.859531 0.125 RAD 0.0078125 + txt829 +TEXDEF txt830 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.75 0.140469 APEX 0.25 0.75 0.234531 RAD 0.0078125 + txt830 +TEXDEF txt831 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.75 0.25 RAD 0.03125 + txt831 +TEXDEF txt832 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.75 0.25 APEX 0.359531 0.75 0.25 RAD 0.0078125 + txt832 +TEXDEF txt833 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.765469 0.25 APEX 0.25 0.859531 0.25 RAD 0.0078125 + txt833 +TEXDEF txt834 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.75 0.265469 APEX 0.25 0.75 0.359531 RAD 0.0078125 + txt834 +TEXDEF txt835 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.75 0.375 RAD 0.03125 + txt835 +TEXDEF txt836 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.75 0.375 APEX 0.359531 0.75 0.375 RAD 0.0078125 + txt836 +TEXDEF txt837 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.765469 0.375 APEX 0.25 0.859531 0.375 RAD 0.0078125 + txt837 +TEXDEF txt838 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.75 0.390469 APEX 0.25 0.75 0.484531 RAD 0.0078125 + txt838 +TEXDEF txt839 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.75 0.5 RAD 0.03125 + txt839 +TEXDEF txt840 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.75 0.5 APEX 0.359531 0.75 0.5 RAD 0.0078125 + txt840 +TEXDEF txt841 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.765469 0.5 APEX 0.25 0.859531 0.5 RAD 0.0078125 + txt841 +TEXDEF txt842 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.75 0.515469 APEX 0.25 0.75 0.609531 RAD 0.0078125 + txt842 +TEXDEF txt843 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.75 0.625 RAD 0.03125 + txt843 +TEXDEF txt844 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.75 0.625 APEX 0.359531 0.75 0.625 RAD 0.0078125 + txt844 +TEXDEF txt845 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.765469 0.625 APEX 0.25 0.859531 0.625 RAD 0.0078125 + txt845 +TEXDEF txt846 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.75 0.640469 APEX 0.25 0.75 0.734531 RAD 0.0078125 + txt846 +TEXDEF txt847 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.75 0.75 RAD 0.03125 + txt847 +TEXDEF txt848 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.75 0.75 APEX 0.359531 0.75 0.75 RAD 0.0078125 + txt848 +TEXDEF txt849 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.765469 0.75 APEX 0.25 0.859531 0.75 RAD 0.0078125 + txt849 +TEXDEF txt850 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.75 0.765469 APEX 0.25 0.75 0.859531 RAD 0.0078125 + txt850 +TEXDEF txt851 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.75 0.875 RAD 0.03125 + txt851 +TEXDEF txt852 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.75 0.875 APEX 0.359531 0.75 0.875 RAD 0.0078125 + txt852 +TEXDEF txt853 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.765469 0.875 APEX 0.25 0.859531 0.875 RAD 0.0078125 + txt853 +TEXDEF txt854 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.75 0.890469 APEX 0.25 0.75 0.984531 RAD 0.0078125 + txt854 +TEXDEF txt855 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.75 1 RAD 0.03125 + txt855 +TEXDEF txt856 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.75 1 APEX 0.359531 0.75 1 RAD 0.0078125 + txt856 +TEXDEF txt857 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.765469 1 APEX 0.25 0.859531 1 RAD 0.0078125 + txt857 +TEXDEF txt858 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.875 0 RAD 0.03125 + txt858 +TEXDEF txt859 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.875 0 APEX 0.359531 0.875 0 RAD 0.0078125 + txt859 +TEXDEF txt860 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.890469 0 APEX 0.25 0.984531 0 RAD 0.0078125 + txt860 +TEXDEF txt861 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.875 0.0154687 APEX 0.25 0.875 0.109531 RAD 0.0078125 + txt861 +TEXDEF txt862 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.875 0.125 RAD 0.03125 + txt862 +TEXDEF txt863 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.875 0.125 APEX 0.359531 0.875 0.125 RAD 0.0078125 + txt863 +TEXDEF txt864 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.890469 0.125 APEX 0.25 0.984531 0.125 RAD 0.0078125 + txt864 +TEXDEF txt865 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.875 0.140469 APEX 0.25 0.875 0.234531 RAD 0.0078125 + txt865 +TEXDEF txt866 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.875 0.25 RAD 0.03125 + txt866 +TEXDEF txt867 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.875 0.25 APEX 0.359531 0.875 0.25 RAD 0.0078125 + txt867 +TEXDEF txt868 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.890469 0.25 APEX 0.25 0.984531 0.25 RAD 0.0078125 + txt868 +TEXDEF txt869 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.875 0.265469 APEX 0.25 0.875 0.359531 RAD 0.0078125 + txt869 +TEXDEF txt870 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.875 0.375 RAD 0.03125 + txt870 +TEXDEF txt871 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.875 0.375 APEX 0.359531 0.875 0.375 RAD 0.0078125 + txt871 +TEXDEF txt872 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.890469 0.375 APEX 0.25 0.984531 0.375 RAD 0.0078125 + txt872 +TEXDEF txt873 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.875 0.390469 APEX 0.25 0.875 0.484531 RAD 0.0078125 + txt873 +TEXDEF txt874 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.875 0.5 RAD 0.03125 + txt874 +TEXDEF txt875 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.875 0.5 APEX 0.359531 0.875 0.5 RAD 0.0078125 + txt875 +TEXDEF txt876 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.890469 0.5 APEX 0.25 0.984531 0.5 RAD 0.0078125 + txt876 +TEXDEF txt877 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.875 0.515469 APEX 0.25 0.875 0.609531 RAD 0.0078125 + txt877 +TEXDEF txt878 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.875 0.625 RAD 0.03125 + txt878 +TEXDEF txt879 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.875 0.625 APEX 0.359531 0.875 0.625 RAD 0.0078125 + txt879 +TEXDEF txt880 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.890469 0.625 APEX 0.25 0.984531 0.625 RAD 0.0078125 + txt880 +TEXDEF txt881 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.875 0.640469 APEX 0.25 0.875 0.734531 RAD 0.0078125 + txt881 +TEXDEF txt882 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.875 0.75 RAD 0.03125 + txt882 +TEXDEF txt883 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.875 0.75 APEX 0.359531 0.875 0.75 RAD 0.0078125 + txt883 +TEXDEF txt884 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.890469 0.75 APEX 0.25 0.984531 0.75 RAD 0.0078125 + txt884 +TEXDEF txt885 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.875 0.765469 APEX 0.25 0.875 0.859531 RAD 0.0078125 + txt885 +TEXDEF txt886 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.875 0.875 RAD 0.03125 + txt886 +TEXDEF txt887 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.875 0.875 APEX 0.359531 0.875 0.875 RAD 0.0078125 + txt887 +TEXDEF txt888 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.890469 0.875 APEX 0.25 0.984531 0.875 RAD 0.0078125 + txt888 +TEXDEF txt889 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.875 0.890469 APEX 0.25 0.875 0.984531 RAD 0.0078125 + txt889 +TEXDEF txt890 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 0.875 1 RAD 0.03125 + txt890 +TEXDEF txt891 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 0.875 1 APEX 0.359531 0.875 1 RAD 0.0078125 + txt891 +TEXDEF txt892 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 0.890469 1 APEX 0.25 0.984531 1 RAD 0.0078125 + txt892 +TEXDEF txt893 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 1 0 RAD 0.03125 + txt893 +TEXDEF txt894 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 1 0 APEX 0.359531 1 0 RAD 0.0078125 + txt894 +TEXDEF txt895 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 1 0.0154687 APEX 0.25 1 0.109531 RAD 0.0078125 + txt895 +TEXDEF txt896 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 1 0.125 RAD 0.03125 + txt896 +TEXDEF txt897 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 1 0.125 APEX 0.359531 1 0.125 RAD 0.0078125 + txt897 +TEXDEF txt898 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 1 0.140469 APEX 0.25 1 0.234531 RAD 0.0078125 + txt898 +TEXDEF txt899 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 1 0.25 RAD 0.03125 + txt899 +TEXDEF txt900 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 1 0.25 APEX 0.359531 1 0.25 RAD 0.0078125 + txt900 +TEXDEF txt901 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 1 0.265469 APEX 0.25 1 0.359531 RAD 0.0078125 + txt901 +TEXDEF txt902 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 1 0.375 RAD 0.03125 + txt902 +TEXDEF txt903 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 1 0.375 APEX 0.359531 1 0.375 RAD 0.0078125 + txt903 +TEXDEF txt904 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 1 0.390469 APEX 0.25 1 0.484531 RAD 0.0078125 + txt904 +TEXDEF txt905 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 1 0.5 RAD 0.03125 + txt905 +TEXDEF txt906 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 1 0.5 APEX 0.359531 1 0.5 RAD 0.0078125 + txt906 +TEXDEF txt907 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 1 0.515469 APEX 0.25 1 0.609531 RAD 0.0078125 + txt907 +TEXDEF txt908 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 1 0.625 RAD 0.03125 + txt908 +TEXDEF txt909 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 1 0.625 APEX 0.359531 1 0.625 RAD 0.0078125 + txt909 +TEXDEF txt910 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 1 0.640469 APEX 0.25 1 0.734531 RAD 0.0078125 + txt910 +TEXDEF txt911 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 1 0.75 RAD 0.03125 + txt911 +TEXDEF txt912 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 1 0.75 APEX 0.359531 1 0.75 RAD 0.0078125 + txt912 +TEXDEF txt913 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 1 0.765469 APEX 0.25 1 0.859531 RAD 0.0078125 + txt913 +TEXDEF txt914 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 1 0.875 RAD 0.03125 + txt914 +TEXDEF txt915 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 1 0.875 APEX 0.359531 1 0.875 RAD 0.0078125 + txt915 +TEXDEF txt916 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.25 1 0.890469 APEX 0.25 1 0.984531 RAD 0.0078125 + txt916 +TEXDEF txt917 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.25 1 1 RAD 0.03125 + txt917 +TEXDEF txt918 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.265469 1 1 APEX 0.359531 1 1 RAD 0.0078125 + txt918 +TEXDEF txt919 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0 0 RAD 0.03125 + txt919 +TEXDEF txt920 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0 0 APEX 0.484531 0 0 RAD 0.0078125 + txt920 +TEXDEF txt921 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.0154687 0 APEX 0.375 0.109531 0 RAD 0.0078125 + txt921 +TEXDEF txt922 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0 0.0154687 APEX 0.375 0 0.109531 RAD 0.0078125 + txt922 +TEXDEF txt923 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0 0.125 RAD 0.03125 + txt923 +TEXDEF txt924 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0 0.125 APEX 0.484531 0 0.125 RAD 0.0078125 + txt924 +TEXDEF txt925 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.0154687 0.125 APEX 0.375 0.109531 0.125 RAD 0.0078125 + txt925 +TEXDEF txt926 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0 0.140469 APEX 0.375 0 0.234531 RAD 0.0078125 + txt926 +TEXDEF txt927 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0 0.25 RAD 0.03125 + txt927 +TEXDEF txt928 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0 0.25 APEX 0.484531 0 0.25 RAD 0.0078125 + txt928 +TEXDEF txt929 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.0154687 0.25 APEX 0.375 0.109531 0.25 RAD 0.0078125 + txt929 +TEXDEF txt930 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0 0.265469 APEX 0.375 0 0.359531 RAD 0.0078125 + txt930 +TEXDEF txt931 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0 0.375 RAD 0.03125 + txt931 +TEXDEF txt932 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0 0.375 APEX 0.484531 0 0.375 RAD 0.0078125 + txt932 +TEXDEF txt933 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.0154687 0.375 APEX 0.375 0.109531 0.375 RAD 0.0078125 + txt933 +TEXDEF txt934 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0 0.390469 APEX 0.375 0 0.484531 RAD 0.0078125 + txt934 +TEXDEF txt935 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0 0.5 RAD 0.03125 + txt935 +TEXDEF txt936 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0 0.5 APEX 0.484531 0 0.5 RAD 0.0078125 + txt936 +TEXDEF txt937 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.0154687 0.5 APEX 0.375 0.109531 0.5 RAD 0.0078125 + txt937 +TEXDEF txt938 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0 0.515469 APEX 0.375 0 0.609531 RAD 0.0078125 + txt938 +TEXDEF txt939 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0 0.625 RAD 0.03125 + txt939 +TEXDEF txt940 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0 0.625 APEX 0.484531 0 0.625 RAD 0.0078125 + txt940 +TEXDEF txt941 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.0154687 0.625 APEX 0.375 0.109531 0.625 RAD 0.0078125 + txt941 +TEXDEF txt942 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0 0.640469 APEX 0.375 0 0.734531 RAD 0.0078125 + txt942 +TEXDEF txt943 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0 0.75 RAD 0.03125 + txt943 +TEXDEF txt944 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0 0.75 APEX 0.484531 0 0.75 RAD 0.0078125 + txt944 +TEXDEF txt945 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.0154687 0.75 APEX 0.375 0.109531 0.75 RAD 0.0078125 + txt945 +TEXDEF txt946 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0 0.765469 APEX 0.375 0 0.859531 RAD 0.0078125 + txt946 +TEXDEF txt947 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0 0.875 RAD 0.03125 + txt947 +TEXDEF txt948 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0 0.875 APEX 0.484531 0 0.875 RAD 0.0078125 + txt948 +TEXDEF txt949 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.0154687 0.875 APEX 0.375 0.109531 0.875 RAD 0.0078125 + txt949 +TEXDEF txt950 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0 0.890469 APEX 0.375 0 0.984531 RAD 0.0078125 + txt950 +TEXDEF txt951 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0 1 RAD 0.03125 + txt951 +TEXDEF txt952 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0 1 APEX 0.484531 0 1 RAD 0.0078125 + txt952 +TEXDEF txt953 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.0154687 1 APEX 0.375 0.109531 1 RAD 0.0078125 + txt953 +TEXDEF txt954 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.125 0 RAD 0.03125 + txt954 +TEXDEF txt955 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.125 0 APEX 0.484531 0.125 0 RAD 0.0078125 + txt955 +TEXDEF txt956 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.140469 0 APEX 0.375 0.234531 0 RAD 0.0078125 + txt956 +TEXDEF txt957 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.125 0.0154687 APEX 0.375 0.125 0.109531 RAD 0.0078125 + txt957 +TEXDEF txt958 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.125 0.125 RAD 0.03125 + txt958 +TEXDEF txt959 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.125 0.125 APEX 0.484531 0.125 0.125 RAD 0.0078125 + txt959 +TEXDEF txt960 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.140469 0.125 APEX 0.375 0.234531 0.125 RAD 0.0078125 + txt960 +TEXDEF txt961 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.125 0.140469 APEX 0.375 0.125 0.234531 RAD 0.0078125 + txt961 +TEXDEF txt962 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.125 0.25 RAD 0.03125 + txt962 +TEXDEF txt963 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.125 0.25 APEX 0.484531 0.125 0.25 RAD 0.0078125 + txt963 +TEXDEF txt964 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.140469 0.25 APEX 0.375 0.234531 0.25 RAD 0.0078125 + txt964 +TEXDEF txt965 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.125 0.265469 APEX 0.375 0.125 0.359531 RAD 0.0078125 + txt965 +TEXDEF txt966 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.125 0.375 RAD 0.03125 + txt966 +TEXDEF txt967 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.125 0.375 APEX 0.484531 0.125 0.375 RAD 0.0078125 + txt967 +TEXDEF txt968 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.140469 0.375 APEX 0.375 0.234531 0.375 RAD 0.0078125 + txt968 +TEXDEF txt969 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.125 0.390469 APEX 0.375 0.125 0.484531 RAD 0.0078125 + txt969 +TEXDEF txt970 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.125 0.5 RAD 0.03125 + txt970 +TEXDEF txt971 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.125 0.5 APEX 0.484531 0.125 0.5 RAD 0.0078125 + txt971 +TEXDEF txt972 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.140469 0.5 APEX 0.375 0.234531 0.5 RAD 0.0078125 + txt972 +TEXDEF txt973 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.125 0.515469 APEX 0.375 0.125 0.609531 RAD 0.0078125 + txt973 +TEXDEF txt974 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.125 0.625 RAD 0.03125 + txt974 +TEXDEF txt975 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.125 0.625 APEX 0.484531 0.125 0.625 RAD 0.0078125 + txt975 +TEXDEF txt976 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.140469 0.625 APEX 0.375 0.234531 0.625 RAD 0.0078125 + txt976 +TEXDEF txt977 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.125 0.640469 APEX 0.375 0.125 0.734531 RAD 0.0078125 + txt977 +TEXDEF txt978 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.125 0.75 RAD 0.03125 + txt978 +TEXDEF txt979 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.125 0.75 APEX 0.484531 0.125 0.75 RAD 0.0078125 + txt979 +TEXDEF txt980 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.140469 0.75 APEX 0.375 0.234531 0.75 RAD 0.0078125 + txt980 +TEXDEF txt981 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.125 0.765469 APEX 0.375 0.125 0.859531 RAD 0.0078125 + txt981 +TEXDEF txt982 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.125 0.875 RAD 0.03125 + txt982 +TEXDEF txt983 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.125 0.875 APEX 0.484531 0.125 0.875 RAD 0.0078125 + txt983 +TEXDEF txt984 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.140469 0.875 APEX 0.375 0.234531 0.875 RAD 0.0078125 + txt984 +TEXDEF txt985 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.125 0.890469 APEX 0.375 0.125 0.984531 RAD 0.0078125 + txt985 +TEXDEF txt986 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.125 1 RAD 0.03125 + txt986 +TEXDEF txt987 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.125 1 APEX 0.484531 0.125 1 RAD 0.0078125 + txt987 +TEXDEF txt988 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.140469 1 APEX 0.375 0.234531 1 RAD 0.0078125 + txt988 +TEXDEF txt989 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.25 0 RAD 0.03125 + txt989 +TEXDEF txt990 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.25 0 APEX 0.484531 0.25 0 RAD 0.0078125 + txt990 +TEXDEF txt991 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.265469 0 APEX 0.375 0.359531 0 RAD 0.0078125 + txt991 +TEXDEF txt992 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.25 0.0154687 APEX 0.375 0.25 0.109531 RAD 0.0078125 + txt992 +TEXDEF txt993 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.25 0.125 RAD 0.03125 + txt993 +TEXDEF txt994 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.25 0.125 APEX 0.484531 0.25 0.125 RAD 0.0078125 + txt994 +TEXDEF txt995 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.265469 0.125 APEX 0.375 0.359531 0.125 RAD 0.0078125 + txt995 +TEXDEF txt996 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.25 0.140469 APEX 0.375 0.25 0.234531 RAD 0.0078125 + txt996 +TEXDEF txt997 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.25 0.25 RAD 0.03125 + txt997 +TEXDEF txt998 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.25 0.25 APEX 0.484531 0.25 0.25 RAD 0.0078125 + txt998 +TEXDEF txt999 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.265469 0.25 APEX 0.375 0.359531 0.25 RAD 0.0078125 + txt999 +TEXDEF txt100 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.25 0.265469 APEX 0.375 0.25 0.359531 RAD 0.0078125 + txt100 +TEXDEF txt100 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.25 0.375 RAD 0.03125 + txt100 +TEXDEF txt100 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.25 0.375 APEX 0.484531 0.25 0.375 RAD 0.0078125 + txt100 +TEXDEF txt100 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.265469 0.375 APEX 0.375 0.359531 0.375 RAD 0.0078125 + txt100 +TEXDEF txt100 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.25 0.390469 APEX 0.375 0.25 0.484531 RAD 0.0078125 + txt100 +TEXDEF txt100 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.25 0.5 RAD 0.03125 + txt100 +TEXDEF txt100 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.25 0.5 APEX 0.484531 0.25 0.5 RAD 0.0078125 + txt100 +TEXDEF txt100 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.265469 0.5 APEX 0.375 0.359531 0.5 RAD 0.0078125 + txt100 +TEXDEF txt100 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.25 0.515469 APEX 0.375 0.25 0.609531 RAD 0.0078125 + txt100 +TEXDEF txt100 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.25 0.625 RAD 0.03125 + txt100 +TEXDEF txt101 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.25 0.625 APEX 0.484531 0.25 0.625 RAD 0.0078125 + txt101 +TEXDEF txt101 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.265469 0.625 APEX 0.375 0.359531 0.625 RAD 0.0078125 + txt101 +TEXDEF txt101 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.25 0.640469 APEX 0.375 0.25 0.734531 RAD 0.0078125 + txt101 +TEXDEF txt101 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.25 0.75 RAD 0.03125 + txt101 +TEXDEF txt101 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.25 0.75 APEX 0.484531 0.25 0.75 RAD 0.0078125 + txt101 +TEXDEF txt101 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.265469 0.75 APEX 0.375 0.359531 0.75 RAD 0.0078125 + txt101 +TEXDEF txt101 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.25 0.765469 APEX 0.375 0.25 0.859531 RAD 0.0078125 + txt101 +TEXDEF txt101 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.25 0.875 RAD 0.03125 + txt101 +TEXDEF txt101 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.25 0.875 APEX 0.484531 0.25 0.875 RAD 0.0078125 + txt101 +TEXDEF txt101 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.265469 0.875 APEX 0.375 0.359531 0.875 RAD 0.0078125 + txt101 +TEXDEF txt102 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.25 0.890469 APEX 0.375 0.25 0.984531 RAD 0.0078125 + txt102 +TEXDEF txt102 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.25 1 RAD 0.03125 + txt102 +TEXDEF txt102 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.25 1 APEX 0.484531 0.25 1 RAD 0.0078125 + txt102 +TEXDEF txt102 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.265469 1 APEX 0.375 0.359531 1 RAD 0.0078125 + txt102 +TEXDEF txt102 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.375 0 RAD 0.03125 + txt102 +TEXDEF txt102 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.375 0 APEX 0.484531 0.375 0 RAD 0.0078125 + txt102 +TEXDEF txt102 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.390469 0 APEX 0.375 0.484531 0 RAD 0.0078125 + txt102 +TEXDEF txt102 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.375 0.0154687 APEX 0.375 0.375 0.109531 RAD 0.0078125 + txt102 +TEXDEF txt102 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.375 0.125 RAD 0.03125 + txt102 +TEXDEF txt102 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.375 0.125 APEX 0.484531 0.375 0.125 RAD 0.0078125 + txt102 +TEXDEF txt103 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.390469 0.125 APEX 0.375 0.484531 0.125 RAD 0.0078125 + txt103 +TEXDEF txt103 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.375 0.140469 APEX 0.375 0.375 0.234531 RAD 0.0078125 + txt103 +TEXDEF txt103 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.375 0.25 RAD 0.03125 + txt103 +TEXDEF txt103 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.375 0.25 APEX 0.484531 0.375 0.25 RAD 0.0078125 + txt103 +TEXDEF txt103 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.390469 0.25 APEX 0.375 0.484531 0.25 RAD 0.0078125 + txt103 +TEXDEF txt103 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.375 0.265469 APEX 0.375 0.375 0.359531 RAD 0.0078125 + txt103 +TEXDEF txt103 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.375 0.375 RAD 0.03125 + txt103 +TEXDEF txt103 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.375 0.375 APEX 0.484531 0.375 0.375 RAD 0.0078125 + txt103 +TEXDEF txt103 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.390469 0.375 APEX 0.375 0.484531 0.375 RAD 0.0078125 + txt103 +TEXDEF txt103 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.375 0.390469 APEX 0.375 0.375 0.484531 RAD 0.0078125 + txt103 +TEXDEF txt104 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.375 0.5 RAD 0.03125 + txt104 +TEXDEF txt104 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.375 0.5 APEX 0.484531 0.375 0.5 RAD 0.0078125 + txt104 +TEXDEF txt104 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.390469 0.5 APEX 0.375 0.484531 0.5 RAD 0.0078125 + txt104 +TEXDEF txt104 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.375 0.515469 APEX 0.375 0.375 0.609531 RAD 0.0078125 + txt104 +TEXDEF txt104 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.375 0.625 RAD 0.03125 + txt104 +TEXDEF txt104 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.375 0.625 APEX 0.484531 0.375 0.625 RAD 0.0078125 + txt104 +TEXDEF txt104 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.390469 0.625 APEX 0.375 0.484531 0.625 RAD 0.0078125 + txt104 +TEXDEF txt104 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.375 0.640469 APEX 0.375 0.375 0.734531 RAD 0.0078125 + txt104 +TEXDEF txt104 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.375 0.75 RAD 0.03125 + txt104 +TEXDEF txt104 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.375 0.75 APEX 0.484531 0.375 0.75 RAD 0.0078125 + txt104 +TEXDEF txt105 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.390469 0.75 APEX 0.375 0.484531 0.75 RAD 0.0078125 + txt105 +TEXDEF txt105 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.375 0.765469 APEX 0.375 0.375 0.859531 RAD 0.0078125 + txt105 +TEXDEF txt105 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.375 0.875 RAD 0.03125 + txt105 +TEXDEF txt105 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.375 0.875 APEX 0.484531 0.375 0.875 RAD 0.0078125 + txt105 +TEXDEF txt105 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.390469 0.875 APEX 0.375 0.484531 0.875 RAD 0.0078125 + txt105 +TEXDEF txt105 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.375 0.890469 APEX 0.375 0.375 0.984531 RAD 0.0078125 + txt105 +TEXDEF txt105 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.375 1 RAD 0.03125 + txt105 +TEXDEF txt105 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.375 1 APEX 0.484531 0.375 1 RAD 0.0078125 + txt105 +TEXDEF txt105 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.390469 1 APEX 0.375 0.484531 1 RAD 0.0078125 + txt105 +TEXDEF txt105 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.5 0 RAD 0.03125 + txt105 +TEXDEF txt106 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.5 0 APEX 0.484531 0.5 0 RAD 0.0078125 + txt106 +TEXDEF txt106 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.515469 0 APEX 0.375 0.609531 0 RAD 0.0078125 + txt106 +TEXDEF txt106 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.5 0.0154687 APEX 0.375 0.5 0.109531 RAD 0.0078125 + txt106 +TEXDEF txt106 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.5 0.125 RAD 0.03125 + txt106 +TEXDEF txt106 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.5 0.125 APEX 0.484531 0.5 0.125 RAD 0.0078125 + txt106 +TEXDEF txt106 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.515469 0.125 APEX 0.375 0.609531 0.125 RAD 0.0078125 + txt106 +TEXDEF txt106 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.5 0.140469 APEX 0.375 0.5 0.234531 RAD 0.0078125 + txt106 +TEXDEF txt106 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.5 0.25 RAD 0.03125 + txt106 +TEXDEF txt106 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.5 0.25 APEX 0.484531 0.5 0.25 RAD 0.0078125 + txt106 +TEXDEF txt106 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.515469 0.25 APEX 0.375 0.609531 0.25 RAD 0.0078125 + txt106 +TEXDEF txt107 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.5 0.265469 APEX 0.375 0.5 0.359531 RAD 0.0078125 + txt107 +TEXDEF txt107 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.5 0.375 RAD 0.03125 + txt107 +TEXDEF txt107 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.5 0.375 APEX 0.484531 0.5 0.375 RAD 0.0078125 + txt107 +TEXDEF txt107 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.515469 0.375 APEX 0.375 0.609531 0.375 RAD 0.0078125 + txt107 +TEXDEF txt107 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.5 0.390469 APEX 0.375 0.5 0.484531 RAD 0.0078125 + txt107 +TEXDEF txt107 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.5 0.5 RAD 0.03125 + txt107 +TEXDEF txt107 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.5 0.5 APEX 0.484531 0.5 0.5 RAD 0.0078125 + txt107 +TEXDEF txt107 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.515469 0.5 APEX 0.375 0.609531 0.5 RAD 0.0078125 + txt107 +TEXDEF txt107 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.5 0.515469 APEX 0.375 0.5 0.609531 RAD 0.0078125 + txt107 +TEXDEF txt107 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.5 0.625 RAD 0.03125 + txt107 +TEXDEF txt108 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.5 0.625 APEX 0.484531 0.5 0.625 RAD 0.0078125 + txt108 +TEXDEF txt108 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.515469 0.625 APEX 0.375 0.609531 0.625 RAD 0.0078125 + txt108 +TEXDEF txt108 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.5 0.640469 APEX 0.375 0.5 0.734531 RAD 0.0078125 + txt108 +TEXDEF txt108 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.5 0.75 RAD 0.03125 + txt108 +TEXDEF txt108 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.5 0.75 APEX 0.484531 0.5 0.75 RAD 0.0078125 + txt108 +TEXDEF txt108 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.515469 0.75 APEX 0.375 0.609531 0.75 RAD 0.0078125 + txt108 +TEXDEF txt108 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.5 0.765469 APEX 0.375 0.5 0.859531 RAD 0.0078125 + txt108 +TEXDEF txt108 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.5 0.875 RAD 0.03125 + txt108 +TEXDEF txt108 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.5 0.875 APEX 0.484531 0.5 0.875 RAD 0.0078125 + txt108 +TEXDEF txt108 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.515469 0.875 APEX 0.375 0.609531 0.875 RAD 0.0078125 + txt108 +TEXDEF txt109 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.5 0.890469 APEX 0.375 0.5 0.984531 RAD 0.0078125 + txt109 +TEXDEF txt109 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.5 1 RAD 0.03125 + txt109 +TEXDEF txt109 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.5 1 APEX 0.484531 0.5 1 RAD 0.0078125 + txt109 +TEXDEF txt109 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.515469 1 APEX 0.375 0.609531 1 RAD 0.0078125 + txt109 +TEXDEF txt109 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.625 0 RAD 0.03125 + txt109 +TEXDEF txt109 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.625 0 APEX 0.484531 0.625 0 RAD 0.0078125 + txt109 +TEXDEF txt109 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.640469 0 APEX 0.375 0.734531 0 RAD 0.0078125 + txt109 +TEXDEF txt109 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.625 0.0154687 APEX 0.375 0.625 0.109531 RAD 0.0078125 + txt109 +TEXDEF txt109 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.625 0.125 RAD 0.03125 + txt109 +TEXDEF txt109 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.625 0.125 APEX 0.484531 0.625 0.125 RAD 0.0078125 + txt109 +TEXDEF txt110 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.640469 0.125 APEX 0.375 0.734531 0.125 RAD 0.0078125 + txt110 +TEXDEF txt110 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.625 0.140469 APEX 0.375 0.625 0.234531 RAD 0.0078125 + txt110 +TEXDEF txt110 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.625 0.25 RAD 0.03125 + txt110 +TEXDEF txt110 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.625 0.25 APEX 0.484531 0.625 0.25 RAD 0.0078125 + txt110 +TEXDEF txt110 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.640469 0.25 APEX 0.375 0.734531 0.25 RAD 0.0078125 + txt110 +TEXDEF txt110 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.625 0.265469 APEX 0.375 0.625 0.359531 RAD 0.0078125 + txt110 +TEXDEF txt110 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.625 0.375 RAD 0.03125 + txt110 +TEXDEF txt110 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.625 0.375 APEX 0.484531 0.625 0.375 RAD 0.0078125 + txt110 +TEXDEF txt110 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.640469 0.375 APEX 0.375 0.734531 0.375 RAD 0.0078125 + txt110 +TEXDEF txt110 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.625 0.390469 APEX 0.375 0.625 0.484531 RAD 0.0078125 + txt110 +TEXDEF txt111 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.625 0.5 RAD 0.03125 + txt111 +TEXDEF txt111 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.625 0.5 APEX 0.484531 0.625 0.5 RAD 0.0078125 + txt111 +TEXDEF txt111 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.640469 0.5 APEX 0.375 0.734531 0.5 RAD 0.0078125 + txt111 +TEXDEF txt111 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.625 0.515469 APEX 0.375 0.625 0.609531 RAD 0.0078125 + txt111 +TEXDEF txt111 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.625 0.625 RAD 0.03125 + txt111 +TEXDEF txt111 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.625 0.625 APEX 0.484531 0.625 0.625 RAD 0.0078125 + txt111 +TEXDEF txt111 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.640469 0.625 APEX 0.375 0.734531 0.625 RAD 0.0078125 + txt111 +TEXDEF txt111 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.625 0.640469 APEX 0.375 0.625 0.734531 RAD 0.0078125 + txt111 +TEXDEF txt111 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.625 0.75 RAD 0.03125 + txt111 +TEXDEF txt111 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.625 0.75 APEX 0.484531 0.625 0.75 RAD 0.0078125 + txt111 +TEXDEF txt112 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.640469 0.75 APEX 0.375 0.734531 0.75 RAD 0.0078125 + txt112 +TEXDEF txt112 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.625 0.765469 APEX 0.375 0.625 0.859531 RAD 0.0078125 + txt112 +TEXDEF txt112 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.625 0.875 RAD 0.03125 + txt112 +TEXDEF txt112 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.625 0.875 APEX 0.484531 0.625 0.875 RAD 0.0078125 + txt112 +TEXDEF txt112 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.640469 0.875 APEX 0.375 0.734531 0.875 RAD 0.0078125 + txt112 +TEXDEF txt112 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.625 0.890469 APEX 0.375 0.625 0.984531 RAD 0.0078125 + txt112 +TEXDEF txt112 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.625 1 RAD 0.03125 + txt112 +TEXDEF txt112 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.625 1 APEX 0.484531 0.625 1 RAD 0.0078125 + txt112 +TEXDEF txt112 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.640469 1 APEX 0.375 0.734531 1 RAD 0.0078125 + txt112 +TEXDEF txt112 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.75 0 RAD 0.03125 + txt112 +TEXDEF txt113 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.75 0 APEX 0.484531 0.75 0 RAD 0.0078125 + txt113 +TEXDEF txt113 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.765469 0 APEX 0.375 0.859531 0 RAD 0.0078125 + txt113 +TEXDEF txt113 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.75 0.0154687 APEX 0.375 0.75 0.109531 RAD 0.0078125 + txt113 +TEXDEF txt113 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.75 0.125 RAD 0.03125 + txt113 +TEXDEF txt113 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.75 0.125 APEX 0.484531 0.75 0.125 RAD 0.0078125 + txt113 +TEXDEF txt113 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.765469 0.125 APEX 0.375 0.859531 0.125 RAD 0.0078125 + txt113 +TEXDEF txt113 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.75 0.140469 APEX 0.375 0.75 0.234531 RAD 0.0078125 + txt113 +TEXDEF txt113 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.75 0.25 RAD 0.03125 + txt113 +TEXDEF txt113 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.75 0.25 APEX 0.484531 0.75 0.25 RAD 0.0078125 + txt113 +TEXDEF txt113 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.765469 0.25 APEX 0.375 0.859531 0.25 RAD 0.0078125 + txt113 +TEXDEF txt114 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.75 0.265469 APEX 0.375 0.75 0.359531 RAD 0.0078125 + txt114 +TEXDEF txt114 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.75 0.375 RAD 0.03125 + txt114 +TEXDEF txt114 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.75 0.375 APEX 0.484531 0.75 0.375 RAD 0.0078125 + txt114 +TEXDEF txt114 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.765469 0.375 APEX 0.375 0.859531 0.375 RAD 0.0078125 + txt114 +TEXDEF txt114 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.75 0.390469 APEX 0.375 0.75 0.484531 RAD 0.0078125 + txt114 +TEXDEF txt114 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.75 0.5 RAD 0.03125 + txt114 +TEXDEF txt114 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.75 0.5 APEX 0.484531 0.75 0.5 RAD 0.0078125 + txt114 +TEXDEF txt114 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.765469 0.5 APEX 0.375 0.859531 0.5 RAD 0.0078125 + txt114 +TEXDEF txt114 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.75 0.515469 APEX 0.375 0.75 0.609531 RAD 0.0078125 + txt114 +TEXDEF txt114 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.75 0.625 RAD 0.03125 + txt114 +TEXDEF txt115 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.75 0.625 APEX 0.484531 0.75 0.625 RAD 0.0078125 + txt115 +TEXDEF txt115 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.765469 0.625 APEX 0.375 0.859531 0.625 RAD 0.0078125 + txt115 +TEXDEF txt115 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.75 0.640469 APEX 0.375 0.75 0.734531 RAD 0.0078125 + txt115 +TEXDEF txt115 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.75 0.75 RAD 0.03125 + txt115 +TEXDEF txt115 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.75 0.75 APEX 0.484531 0.75 0.75 RAD 0.0078125 + txt115 +TEXDEF txt115 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.765469 0.75 APEX 0.375 0.859531 0.75 RAD 0.0078125 + txt115 +TEXDEF txt115 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.75 0.765469 APEX 0.375 0.75 0.859531 RAD 0.0078125 + txt115 +TEXDEF txt115 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.75 0.875 RAD 0.03125 + txt115 +TEXDEF txt115 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.75 0.875 APEX 0.484531 0.75 0.875 RAD 0.0078125 + txt115 +TEXDEF txt115 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.765469 0.875 APEX 0.375 0.859531 0.875 RAD 0.0078125 + txt115 +TEXDEF txt116 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.75 0.890469 APEX 0.375 0.75 0.984531 RAD 0.0078125 + txt116 +TEXDEF txt116 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.75 1 RAD 0.03125 + txt116 +TEXDEF txt116 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.75 1 APEX 0.484531 0.75 1 RAD 0.0078125 + txt116 +TEXDEF txt116 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.765469 1 APEX 0.375 0.859531 1 RAD 0.0078125 + txt116 +TEXDEF txt116 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.875 0 RAD 0.03125 + txt116 +TEXDEF txt116 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.875 0 APEX 0.484531 0.875 0 RAD 0.0078125 + txt116 +TEXDEF txt116 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.890469 0 APEX 0.375 0.984531 0 RAD 0.0078125 + txt116 +TEXDEF txt116 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.875 0.0154687 APEX 0.375 0.875 0.109531 RAD 0.0078125 + txt116 +TEXDEF txt116 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.875 0.125 RAD 0.03125 + txt116 +TEXDEF txt116 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.875 0.125 APEX 0.484531 0.875 0.125 RAD 0.0078125 + txt116 +TEXDEF txt117 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.890469 0.125 APEX 0.375 0.984531 0.125 RAD 0.0078125 + txt117 +TEXDEF txt117 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.875 0.140469 APEX 0.375 0.875 0.234531 RAD 0.0078125 + txt117 +TEXDEF txt117 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.875 0.25 RAD 0.03125 + txt117 +TEXDEF txt117 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.875 0.25 APEX 0.484531 0.875 0.25 RAD 0.0078125 + txt117 +TEXDEF txt117 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.890469 0.25 APEX 0.375 0.984531 0.25 RAD 0.0078125 + txt117 +TEXDEF txt117 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.875 0.265469 APEX 0.375 0.875 0.359531 RAD 0.0078125 + txt117 +TEXDEF txt117 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.875 0.375 RAD 0.03125 + txt117 +TEXDEF txt117 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.875 0.375 APEX 0.484531 0.875 0.375 RAD 0.0078125 + txt117 +TEXDEF txt117 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.890469 0.375 APEX 0.375 0.984531 0.375 RAD 0.0078125 + txt117 +TEXDEF txt117 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.875 0.390469 APEX 0.375 0.875 0.484531 RAD 0.0078125 + txt117 +TEXDEF txt118 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.875 0.5 RAD 0.03125 + txt118 +TEXDEF txt118 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.875 0.5 APEX 0.484531 0.875 0.5 RAD 0.0078125 + txt118 +TEXDEF txt118 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.890469 0.5 APEX 0.375 0.984531 0.5 RAD 0.0078125 + txt118 +TEXDEF txt118 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.875 0.515469 APEX 0.375 0.875 0.609531 RAD 0.0078125 + txt118 +TEXDEF txt118 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.875 0.625 RAD 0.03125 + txt118 +TEXDEF txt118 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.875 0.625 APEX 0.484531 0.875 0.625 RAD 0.0078125 + txt118 +TEXDEF txt118 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.890469 0.625 APEX 0.375 0.984531 0.625 RAD 0.0078125 + txt118 +TEXDEF txt118 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.875 0.640469 APEX 0.375 0.875 0.734531 RAD 0.0078125 + txt118 +TEXDEF txt118 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.875 0.75 RAD 0.03125 + txt118 +TEXDEF txt118 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.875 0.75 APEX 0.484531 0.875 0.75 RAD 0.0078125 + txt118 +TEXDEF txt119 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.890469 0.75 APEX 0.375 0.984531 0.75 RAD 0.0078125 + txt119 +TEXDEF txt119 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.875 0.765469 APEX 0.375 0.875 0.859531 RAD 0.0078125 + txt119 +TEXDEF txt119 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.875 0.875 RAD 0.03125 + txt119 +TEXDEF txt119 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.875 0.875 APEX 0.484531 0.875 0.875 RAD 0.0078125 + txt119 +TEXDEF txt119 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.890469 0.875 APEX 0.375 0.984531 0.875 RAD 0.0078125 + txt119 +TEXDEF txt119 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.875 0.890469 APEX 0.375 0.875 0.984531 RAD 0.0078125 + txt119 +TEXDEF txt119 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 0.875 1 RAD 0.03125 + txt119 +TEXDEF txt119 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 0.875 1 APEX 0.484531 0.875 1 RAD 0.0078125 + txt119 +TEXDEF txt119 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 0.890469 1 APEX 0.375 0.984531 1 RAD 0.0078125 + txt119 +TEXDEF txt119 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 1 0 RAD 0.03125 + txt119 +TEXDEF txt120 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 1 0 APEX 0.484531 1 0 RAD 0.0078125 + txt120 +TEXDEF txt120 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 1 0.0154687 APEX 0.375 1 0.109531 RAD 0.0078125 + txt120 +TEXDEF txt120 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 1 0.125 RAD 0.03125 + txt120 +TEXDEF txt120 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 1 0.125 APEX 0.484531 1 0.125 RAD 0.0078125 + txt120 +TEXDEF txt120 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 1 0.140469 APEX 0.375 1 0.234531 RAD 0.0078125 + txt120 +TEXDEF txt120 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 1 0.25 RAD 0.03125 + txt120 +TEXDEF txt120 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 1 0.25 APEX 0.484531 1 0.25 RAD 0.0078125 + txt120 +TEXDEF txt120 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 1 0.265469 APEX 0.375 1 0.359531 RAD 0.0078125 + txt120 +TEXDEF txt120 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 1 0.375 RAD 0.03125 + txt120 +TEXDEF txt120 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 1 0.375 APEX 0.484531 1 0.375 RAD 0.0078125 + txt120 +TEXDEF txt121 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 1 0.390469 APEX 0.375 1 0.484531 RAD 0.0078125 + txt121 +TEXDEF txt121 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 1 0.5 RAD 0.03125 + txt121 +TEXDEF txt121 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 1 0.5 APEX 0.484531 1 0.5 RAD 0.0078125 + txt121 +TEXDEF txt121 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 1 0.515469 APEX 0.375 1 0.609531 RAD 0.0078125 + txt121 +TEXDEF txt121 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 1 0.625 RAD 0.03125 + txt121 +TEXDEF txt121 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 1 0.625 APEX 0.484531 1 0.625 RAD 0.0078125 + txt121 +TEXDEF txt121 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 1 0.640469 APEX 0.375 1 0.734531 RAD 0.0078125 + txt121 +TEXDEF txt121 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 1 0.75 RAD 0.03125 + txt121 +TEXDEF txt121 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 1 0.75 APEX 0.484531 1 0.75 RAD 0.0078125 + txt121 +TEXDEF txt121 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 1 0.765469 APEX 0.375 1 0.859531 RAD 0.0078125 + txt121 +TEXDEF txt122 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 1 0.875 RAD 0.03125 + txt122 +TEXDEF txt122 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 1 0.875 APEX 0.484531 1 0.875 RAD 0.0078125 + txt122 +TEXDEF txt122 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.375 1 0.890469 APEX 0.375 1 0.984531 RAD 0.0078125 + txt122 +TEXDEF txt122 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.375 1 1 RAD 0.03125 + txt122 +TEXDEF txt122 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.390469 1 1 APEX 0.484531 1 1 RAD 0.0078125 + txt122 +TEXDEF txt122 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0 0 RAD 0.03125 + txt122 +TEXDEF txt122 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0 0 APEX 0.609531 0 0 RAD 0.0078125 + txt122 +TEXDEF txt122 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.0154687 0 APEX 0.5 0.109531 0 RAD 0.0078125 + txt122 +TEXDEF txt122 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0 0.0154687 APEX 0.5 0 0.109531 RAD 0.0078125 + txt122 +TEXDEF txt122 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0 0.125 RAD 0.03125 + txt122 +TEXDEF txt123 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0 0.125 APEX 0.609531 0 0.125 RAD 0.0078125 + txt123 +TEXDEF txt123 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.0154687 0.125 APEX 0.5 0.109531 0.125 RAD 0.0078125 + txt123 +TEXDEF txt123 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0 0.140469 APEX 0.5 0 0.234531 RAD 0.0078125 + txt123 +TEXDEF txt123 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0 0.25 RAD 0.03125 + txt123 +TEXDEF txt123 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0 0.25 APEX 0.609531 0 0.25 RAD 0.0078125 + txt123 +TEXDEF txt123 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.0154687 0.25 APEX 0.5 0.109531 0.25 RAD 0.0078125 + txt123 +TEXDEF txt123 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0 0.265469 APEX 0.5 0 0.359531 RAD 0.0078125 + txt123 +TEXDEF txt123 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0 0.375 RAD 0.03125 + txt123 +TEXDEF txt123 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0 0.375 APEX 0.609531 0 0.375 RAD 0.0078125 + txt123 +TEXDEF txt123 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.0154687 0.375 APEX 0.5 0.109531 0.375 RAD 0.0078125 + txt123 +TEXDEF txt124 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0 0.390469 APEX 0.5 0 0.484531 RAD 0.0078125 + txt124 +TEXDEF txt124 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0 0.5 RAD 0.03125 + txt124 +TEXDEF txt124 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0 0.5 APEX 0.609531 0 0.5 RAD 0.0078125 + txt124 +TEXDEF txt124 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.0154687 0.5 APEX 0.5 0.109531 0.5 RAD 0.0078125 + txt124 +TEXDEF txt124 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0 0.515469 APEX 0.5 0 0.609531 RAD 0.0078125 + txt124 +TEXDEF txt124 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0 0.625 RAD 0.03125 + txt124 +TEXDEF txt124 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0 0.625 APEX 0.609531 0 0.625 RAD 0.0078125 + txt124 +TEXDEF txt124 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.0154687 0.625 APEX 0.5 0.109531 0.625 RAD 0.0078125 + txt124 +TEXDEF txt124 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0 0.640469 APEX 0.5 0 0.734531 RAD 0.0078125 + txt124 +TEXDEF txt124 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0 0.75 RAD 0.03125 + txt124 +TEXDEF txt125 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0 0.75 APEX 0.609531 0 0.75 RAD 0.0078125 + txt125 +TEXDEF txt125 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.0154687 0.75 APEX 0.5 0.109531 0.75 RAD 0.0078125 + txt125 +TEXDEF txt125 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0 0.765469 APEX 0.5 0 0.859531 RAD 0.0078125 + txt125 +TEXDEF txt125 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0 0.875 RAD 0.03125 + txt125 +TEXDEF txt125 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0 0.875 APEX 0.609531 0 0.875 RAD 0.0078125 + txt125 +TEXDEF txt125 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.0154687 0.875 APEX 0.5 0.109531 0.875 RAD 0.0078125 + txt125 +TEXDEF txt125 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0 0.890469 APEX 0.5 0 0.984531 RAD 0.0078125 + txt125 +TEXDEF txt125 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0 1 RAD 0.03125 + txt125 +TEXDEF txt125 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0 1 APEX 0.609531 0 1 RAD 0.0078125 + txt125 +TEXDEF txt125 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.0154687 1 APEX 0.5 0.109531 1 RAD 0.0078125 + txt125 +TEXDEF txt126 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.125 0 RAD 0.03125 + txt126 +TEXDEF txt126 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.125 0 APEX 0.609531 0.125 0 RAD 0.0078125 + txt126 +TEXDEF txt126 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.140469 0 APEX 0.5 0.234531 0 RAD 0.0078125 + txt126 +TEXDEF txt126 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.125 0.0154687 APEX 0.5 0.125 0.109531 RAD 0.0078125 + txt126 +TEXDEF txt126 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.125 0.125 RAD 0.03125 + txt126 +TEXDEF txt126 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.125 0.125 APEX 0.609531 0.125 0.125 RAD 0.0078125 + txt126 +TEXDEF txt126 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.140469 0.125 APEX 0.5 0.234531 0.125 RAD 0.0078125 + txt126 +TEXDEF txt126 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.125 0.140469 APEX 0.5 0.125 0.234531 RAD 0.0078125 + txt126 +TEXDEF txt126 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.125 0.25 RAD 0.03125 + txt126 +TEXDEF txt126 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.125 0.25 APEX 0.609531 0.125 0.25 RAD 0.0078125 + txt126 +TEXDEF txt127 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.140469 0.25 APEX 0.5 0.234531 0.25 RAD 0.0078125 + txt127 +TEXDEF txt127 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.125 0.265469 APEX 0.5 0.125 0.359531 RAD 0.0078125 + txt127 +TEXDEF txt127 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.125 0.375 RAD 0.03125 + txt127 +TEXDEF txt127 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.125 0.375 APEX 0.609531 0.125 0.375 RAD 0.0078125 + txt127 +TEXDEF txt127 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.140469 0.375 APEX 0.5 0.234531 0.375 RAD 0.0078125 + txt127 +TEXDEF txt127 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.125 0.390469 APEX 0.5 0.125 0.484531 RAD 0.0078125 + txt127 +TEXDEF txt127 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.125 0.5 RAD 0.03125 + txt127 +TEXDEF txt127 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.125 0.5 APEX 0.609531 0.125 0.5 RAD 0.0078125 + txt127 +TEXDEF txt127 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.140469 0.5 APEX 0.5 0.234531 0.5 RAD 0.0078125 + txt127 +TEXDEF txt127 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.125 0.515469 APEX 0.5 0.125 0.609531 RAD 0.0078125 + txt127 +TEXDEF txt128 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.125 0.625 RAD 0.03125 + txt128 +TEXDEF txt128 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.125 0.625 APEX 0.609531 0.125 0.625 RAD 0.0078125 + txt128 +TEXDEF txt128 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.140469 0.625 APEX 0.5 0.234531 0.625 RAD 0.0078125 + txt128 +TEXDEF txt128 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.125 0.640469 APEX 0.5 0.125 0.734531 RAD 0.0078125 + txt128 +TEXDEF txt128 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.125 0.75 RAD 0.03125 + txt128 +TEXDEF txt128 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.125 0.75 APEX 0.609531 0.125 0.75 RAD 0.0078125 + txt128 +TEXDEF txt128 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.140469 0.75 APEX 0.5 0.234531 0.75 RAD 0.0078125 + txt128 +TEXDEF txt128 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.125 0.765469 APEX 0.5 0.125 0.859531 RAD 0.0078125 + txt128 +TEXDEF txt128 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.125 0.875 RAD 0.03125 + txt128 +TEXDEF txt128 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.125 0.875 APEX 0.609531 0.125 0.875 RAD 0.0078125 + txt128 +TEXDEF txt129 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.140469 0.875 APEX 0.5 0.234531 0.875 RAD 0.0078125 + txt129 +TEXDEF txt129 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.125 0.890469 APEX 0.5 0.125 0.984531 RAD 0.0078125 + txt129 +TEXDEF txt129 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.125 1 RAD 0.03125 + txt129 +TEXDEF txt129 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.125 1 APEX 0.609531 0.125 1 RAD 0.0078125 + txt129 +TEXDEF txt129 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.140469 1 APEX 0.5 0.234531 1 RAD 0.0078125 + txt129 +TEXDEF txt129 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.25 0 RAD 0.03125 + txt129 +TEXDEF txt129 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.25 0 APEX 0.609531 0.25 0 RAD 0.0078125 + txt129 +TEXDEF txt129 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.265469 0 APEX 0.5 0.359531 0 RAD 0.0078125 + txt129 +TEXDEF txt129 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.25 0.0154687 APEX 0.5 0.25 0.109531 RAD 0.0078125 + txt129 +TEXDEF txt129 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.25 0.125 RAD 0.03125 + txt129 +TEXDEF txt130 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.25 0.125 APEX 0.609531 0.25 0.125 RAD 0.0078125 + txt130 +TEXDEF txt130 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.265469 0.125 APEX 0.5 0.359531 0.125 RAD 0.0078125 + txt130 +TEXDEF txt130 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.25 0.140469 APEX 0.5 0.25 0.234531 RAD 0.0078125 + txt130 +TEXDEF txt130 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.25 0.25 RAD 0.03125 + txt130 +TEXDEF txt130 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.25 0.25 APEX 0.609531 0.25 0.25 RAD 0.0078125 + txt130 +TEXDEF txt130 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.265469 0.25 APEX 0.5 0.359531 0.25 RAD 0.0078125 + txt130 +TEXDEF txt130 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.25 0.265469 APEX 0.5 0.25 0.359531 RAD 0.0078125 + txt130 +TEXDEF txt130 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.25 0.375 RAD 0.03125 + txt130 +TEXDEF txt130 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.25 0.375 APEX 0.609531 0.25 0.375 RAD 0.0078125 + txt130 +TEXDEF txt130 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.265469 0.375 APEX 0.5 0.359531 0.375 RAD 0.0078125 + txt130 +TEXDEF txt131 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.25 0.390469 APEX 0.5 0.25 0.484531 RAD 0.0078125 + txt131 +TEXDEF txt131 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.25 0.5 RAD 0.03125 + txt131 +TEXDEF txt131 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.25 0.5 APEX 0.609531 0.25 0.5 RAD 0.0078125 + txt131 +TEXDEF txt131 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.265469 0.5 APEX 0.5 0.359531 0.5 RAD 0.0078125 + txt131 +TEXDEF txt131 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.25 0.515469 APEX 0.5 0.25 0.609531 RAD 0.0078125 + txt131 +TEXDEF txt131 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.25 0.625 RAD 0.03125 + txt131 +TEXDEF txt131 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.25 0.625 APEX 0.609531 0.25 0.625 RAD 0.0078125 + txt131 +TEXDEF txt131 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.265469 0.625 APEX 0.5 0.359531 0.625 RAD 0.0078125 + txt131 +TEXDEF txt131 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.25 0.640469 APEX 0.5 0.25 0.734531 RAD 0.0078125 + txt131 +TEXDEF txt131 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.25 0.75 RAD 0.03125 + txt131 +TEXDEF txt132 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.25 0.75 APEX 0.609531 0.25 0.75 RAD 0.0078125 + txt132 +TEXDEF txt132 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.265469 0.75 APEX 0.5 0.359531 0.75 RAD 0.0078125 + txt132 +TEXDEF txt132 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.25 0.765469 APEX 0.5 0.25 0.859531 RAD 0.0078125 + txt132 +TEXDEF txt132 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.25 0.875 RAD 0.03125 + txt132 +TEXDEF txt132 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.25 0.875 APEX 0.609531 0.25 0.875 RAD 0.0078125 + txt132 +TEXDEF txt132 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.265469 0.875 APEX 0.5 0.359531 0.875 RAD 0.0078125 + txt132 +TEXDEF txt132 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.25 0.890469 APEX 0.5 0.25 0.984531 RAD 0.0078125 + txt132 +TEXDEF txt132 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.25 1 RAD 0.03125 + txt132 +TEXDEF txt132 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.25 1 APEX 0.609531 0.25 1 RAD 0.0078125 + txt132 +TEXDEF txt132 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.265469 1 APEX 0.5 0.359531 1 RAD 0.0078125 + txt132 +TEXDEF txt133 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.375 0 RAD 0.03125 + txt133 +TEXDEF txt133 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.375 0 APEX 0.609531 0.375 0 RAD 0.0078125 + txt133 +TEXDEF txt133 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.390469 0 APEX 0.5 0.484531 0 RAD 0.0078125 + txt133 +TEXDEF txt133 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.375 0.0154687 APEX 0.5 0.375 0.109531 RAD 0.0078125 + txt133 +TEXDEF txt133 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.375 0.125 RAD 0.03125 + txt133 +TEXDEF txt133 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.375 0.125 APEX 0.609531 0.375 0.125 RAD 0.0078125 + txt133 +TEXDEF txt133 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.390469 0.125 APEX 0.5 0.484531 0.125 RAD 0.0078125 + txt133 +TEXDEF txt133 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.375 0.140469 APEX 0.5 0.375 0.234531 RAD 0.0078125 + txt133 +TEXDEF txt133 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.375 0.25 RAD 0.03125 + txt133 +TEXDEF txt133 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.375 0.25 APEX 0.609531 0.375 0.25 RAD 0.0078125 + txt133 +TEXDEF txt134 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.390469 0.25 APEX 0.5 0.484531 0.25 RAD 0.0078125 + txt134 +TEXDEF txt134 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.375 0.265469 APEX 0.5 0.375 0.359531 RAD 0.0078125 + txt134 +TEXDEF txt134 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.375 0.375 RAD 0.03125 + txt134 +TEXDEF txt134 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.375 0.375 APEX 0.609531 0.375 0.375 RAD 0.0078125 + txt134 +TEXDEF txt134 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.390469 0.375 APEX 0.5 0.484531 0.375 RAD 0.0078125 + txt134 +TEXDEF txt134 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.375 0.390469 APEX 0.5 0.375 0.484531 RAD 0.0078125 + txt134 +TEXDEF txt134 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.375 0.5 RAD 0.03125 + txt134 +TEXDEF txt134 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.375 0.5 APEX 0.609531 0.375 0.5 RAD 0.0078125 + txt134 +TEXDEF txt134 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.390469 0.5 APEX 0.5 0.484531 0.5 RAD 0.0078125 + txt134 +TEXDEF txt134 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.375 0.515469 APEX 0.5 0.375 0.609531 RAD 0.0078125 + txt134 +TEXDEF txt135 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.375 0.625 RAD 0.03125 + txt135 +TEXDEF txt135 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.375 0.625 APEX 0.609531 0.375 0.625 RAD 0.0078125 + txt135 +TEXDEF txt135 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.390469 0.625 APEX 0.5 0.484531 0.625 RAD 0.0078125 + txt135 +TEXDEF txt135 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.375 0.640469 APEX 0.5 0.375 0.734531 RAD 0.0078125 + txt135 +TEXDEF txt135 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.375 0.75 RAD 0.03125 + txt135 +TEXDEF txt135 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.375 0.75 APEX 0.609531 0.375 0.75 RAD 0.0078125 + txt135 +TEXDEF txt135 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.390469 0.75 APEX 0.5 0.484531 0.75 RAD 0.0078125 + txt135 +TEXDEF txt135 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.375 0.765469 APEX 0.5 0.375 0.859531 RAD 0.0078125 + txt135 +TEXDEF txt135 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.375 0.875 RAD 0.03125 + txt135 +TEXDEF txt135 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.375 0.875 APEX 0.609531 0.375 0.875 RAD 0.0078125 + txt135 +TEXDEF txt136 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.390469 0.875 APEX 0.5 0.484531 0.875 RAD 0.0078125 + txt136 +TEXDEF txt136 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.375 0.890469 APEX 0.5 0.375 0.984531 RAD 0.0078125 + txt136 +TEXDEF txt136 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.375 1 RAD 0.03125 + txt136 +TEXDEF txt136 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.375 1 APEX 0.609531 0.375 1 RAD 0.0078125 + txt136 +TEXDEF txt136 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.390469 1 APEX 0.5 0.484531 1 RAD 0.0078125 + txt136 +TEXDEF txt136 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.5 0 RAD 0.03125 + txt136 +TEXDEF txt136 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.5 0 APEX 0.609531 0.5 0 RAD 0.0078125 + txt136 +TEXDEF txt136 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.515469 0 APEX 0.5 0.609531 0 RAD 0.0078125 + txt136 +TEXDEF txt136 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.5 0.0154687 APEX 0.5 0.5 0.109531 RAD 0.0078125 + txt136 +TEXDEF txt136 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.5 0.125 RAD 0.03125 + txt136 +TEXDEF txt137 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.5 0.125 APEX 0.609531 0.5 0.125 RAD 0.0078125 + txt137 +TEXDEF txt137 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.515469 0.125 APEX 0.5 0.609531 0.125 RAD 0.0078125 + txt137 +TEXDEF txt137 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.5 0.140469 APEX 0.5 0.5 0.234531 RAD 0.0078125 + txt137 +TEXDEF txt137 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.5 0.25 RAD 0.03125 + txt137 +TEXDEF txt137 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.5 0.25 APEX 0.609531 0.5 0.25 RAD 0.0078125 + txt137 +TEXDEF txt137 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.515469 0.25 APEX 0.5 0.609531 0.25 RAD 0.0078125 + txt137 +TEXDEF txt137 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.5 0.265469 APEX 0.5 0.5 0.359531 RAD 0.0078125 + txt137 +TEXDEF txt137 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.5 0.375 RAD 0.03125 + txt137 +TEXDEF txt137 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.5 0.375 APEX 0.609531 0.5 0.375 RAD 0.0078125 + txt137 +TEXDEF txt137 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.515469 0.375 APEX 0.5 0.609531 0.375 RAD 0.0078125 + txt137 +TEXDEF txt138 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.5 0.390469 APEX 0.5 0.5 0.484531 RAD 0.0078125 + txt138 +TEXDEF txt138 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.5 0.5 RAD 0.03125 + txt138 +TEXDEF txt138 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.5 0.5 APEX 0.609531 0.5 0.5 RAD 0.0078125 + txt138 +TEXDEF txt138 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.515469 0.5 APEX 0.5 0.609531 0.5 RAD 0.0078125 + txt138 +TEXDEF txt138 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.5 0.515469 APEX 0.5 0.5 0.609531 RAD 0.0078125 + txt138 +TEXDEF txt138 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.5 0.625 RAD 0.03125 + txt138 +TEXDEF txt138 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.5 0.625 APEX 0.609531 0.5 0.625 RAD 0.0078125 + txt138 +TEXDEF txt138 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.515469 0.625 APEX 0.5 0.609531 0.625 RAD 0.0078125 + txt138 +TEXDEF txt138 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.5 0.640469 APEX 0.5 0.5 0.734531 RAD 0.0078125 + txt138 +TEXDEF txt138 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.5 0.75 RAD 0.03125 + txt138 +TEXDEF txt139 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.5 0.75 APEX 0.609531 0.5 0.75 RAD 0.0078125 + txt139 +TEXDEF txt139 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.515469 0.75 APEX 0.5 0.609531 0.75 RAD 0.0078125 + txt139 +TEXDEF txt139 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.5 0.765469 APEX 0.5 0.5 0.859531 RAD 0.0078125 + txt139 +TEXDEF txt139 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.5 0.875 RAD 0.03125 + txt139 +TEXDEF txt139 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.5 0.875 APEX 0.609531 0.5 0.875 RAD 0.0078125 + txt139 +TEXDEF txt139 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.515469 0.875 APEX 0.5 0.609531 0.875 RAD 0.0078125 + txt139 +TEXDEF txt139 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.5 0.890469 APEX 0.5 0.5 0.984531 RAD 0.0078125 + txt139 +TEXDEF txt139 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.5 1 RAD 0.03125 + txt139 +TEXDEF txt139 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.5 1 APEX 0.609531 0.5 1 RAD 0.0078125 + txt139 +TEXDEF txt139 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.515469 1 APEX 0.5 0.609531 1 RAD 0.0078125 + txt139 +TEXDEF txt140 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.625 0 RAD 0.03125 + txt140 +TEXDEF txt140 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.625 0 APEX 0.609531 0.625 0 RAD 0.0078125 + txt140 +TEXDEF txt140 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.640469 0 APEX 0.5 0.734531 0 RAD 0.0078125 + txt140 +TEXDEF txt140 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.625 0.0154687 APEX 0.5 0.625 0.109531 RAD 0.0078125 + txt140 +TEXDEF txt140 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.625 0.125 RAD 0.03125 + txt140 +TEXDEF txt140 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.625 0.125 APEX 0.609531 0.625 0.125 RAD 0.0078125 + txt140 +TEXDEF txt140 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.640469 0.125 APEX 0.5 0.734531 0.125 RAD 0.0078125 + txt140 +TEXDEF txt140 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.625 0.140469 APEX 0.5 0.625 0.234531 RAD 0.0078125 + txt140 +TEXDEF txt140 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.625 0.25 RAD 0.03125 + txt140 +TEXDEF txt140 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.625 0.25 APEX 0.609531 0.625 0.25 RAD 0.0078125 + txt140 +TEXDEF txt141 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.640469 0.25 APEX 0.5 0.734531 0.25 RAD 0.0078125 + txt141 +TEXDEF txt141 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.625 0.265469 APEX 0.5 0.625 0.359531 RAD 0.0078125 + txt141 +TEXDEF txt141 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.625 0.375 RAD 0.03125 + txt141 +TEXDEF txt141 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.625 0.375 APEX 0.609531 0.625 0.375 RAD 0.0078125 + txt141 +TEXDEF txt141 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.640469 0.375 APEX 0.5 0.734531 0.375 RAD 0.0078125 + txt141 +TEXDEF txt141 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.625 0.390469 APEX 0.5 0.625 0.484531 RAD 0.0078125 + txt141 +TEXDEF txt141 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.625 0.5 RAD 0.03125 + txt141 +TEXDEF txt141 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.625 0.5 APEX 0.609531 0.625 0.5 RAD 0.0078125 + txt141 +TEXDEF txt141 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.640469 0.5 APEX 0.5 0.734531 0.5 RAD 0.0078125 + txt141 +TEXDEF txt141 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.625 0.515469 APEX 0.5 0.625 0.609531 RAD 0.0078125 + txt141 +TEXDEF txt142 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.625 0.625 RAD 0.03125 + txt142 +TEXDEF txt142 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.625 0.625 APEX 0.609531 0.625 0.625 RAD 0.0078125 + txt142 +TEXDEF txt142 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.640469 0.625 APEX 0.5 0.734531 0.625 RAD 0.0078125 + txt142 +TEXDEF txt142 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.625 0.640469 APEX 0.5 0.625 0.734531 RAD 0.0078125 + txt142 +TEXDEF txt142 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.625 0.75 RAD 0.03125 + txt142 +TEXDEF txt142 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.625 0.75 APEX 0.609531 0.625 0.75 RAD 0.0078125 + txt142 +TEXDEF txt142 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.640469 0.75 APEX 0.5 0.734531 0.75 RAD 0.0078125 + txt142 +TEXDEF txt142 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.625 0.765469 APEX 0.5 0.625 0.859531 RAD 0.0078125 + txt142 +TEXDEF txt142 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.625 0.875 RAD 0.03125 + txt142 +TEXDEF txt142 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.625 0.875 APEX 0.609531 0.625 0.875 RAD 0.0078125 + txt142 +TEXDEF txt143 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.640469 0.875 APEX 0.5 0.734531 0.875 RAD 0.0078125 + txt143 +TEXDEF txt143 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.625 0.890469 APEX 0.5 0.625 0.984531 RAD 0.0078125 + txt143 +TEXDEF txt143 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.625 1 RAD 0.03125 + txt143 +TEXDEF txt143 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.625 1 APEX 0.609531 0.625 1 RAD 0.0078125 + txt143 +TEXDEF txt143 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.640469 1 APEX 0.5 0.734531 1 RAD 0.0078125 + txt143 +TEXDEF txt143 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.75 0 RAD 0.03125 + txt143 +TEXDEF txt143 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.75 0 APEX 0.609531 0.75 0 RAD 0.0078125 + txt143 +TEXDEF txt143 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.765469 0 APEX 0.5 0.859531 0 RAD 0.0078125 + txt143 +TEXDEF txt143 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.75 0.0154687 APEX 0.5 0.75 0.109531 RAD 0.0078125 + txt143 +TEXDEF txt143 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.75 0.125 RAD 0.03125 + txt143 +TEXDEF txt144 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.75 0.125 APEX 0.609531 0.75 0.125 RAD 0.0078125 + txt144 +TEXDEF txt144 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.765469 0.125 APEX 0.5 0.859531 0.125 RAD 0.0078125 + txt144 +TEXDEF txt144 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.75 0.140469 APEX 0.5 0.75 0.234531 RAD 0.0078125 + txt144 +TEXDEF txt144 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.75 0.25 RAD 0.03125 + txt144 +TEXDEF txt144 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.75 0.25 APEX 0.609531 0.75 0.25 RAD 0.0078125 + txt144 +TEXDEF txt144 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.765469 0.25 APEX 0.5 0.859531 0.25 RAD 0.0078125 + txt144 +TEXDEF txt144 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.75 0.265469 APEX 0.5 0.75 0.359531 RAD 0.0078125 + txt144 +TEXDEF txt144 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.75 0.375 RAD 0.03125 + txt144 +TEXDEF txt144 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.75 0.375 APEX 0.609531 0.75 0.375 RAD 0.0078125 + txt144 +TEXDEF txt144 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.765469 0.375 APEX 0.5 0.859531 0.375 RAD 0.0078125 + txt144 +TEXDEF txt145 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.75 0.390469 APEX 0.5 0.75 0.484531 RAD 0.0078125 + txt145 +TEXDEF txt145 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.75 0.5 RAD 0.03125 + txt145 +TEXDEF txt145 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.75 0.5 APEX 0.609531 0.75 0.5 RAD 0.0078125 + txt145 +TEXDEF txt145 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.765469 0.5 APEX 0.5 0.859531 0.5 RAD 0.0078125 + txt145 +TEXDEF txt145 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.75 0.515469 APEX 0.5 0.75 0.609531 RAD 0.0078125 + txt145 +TEXDEF txt145 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.75 0.625 RAD 0.03125 + txt145 +TEXDEF txt145 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.75 0.625 APEX 0.609531 0.75 0.625 RAD 0.0078125 + txt145 +TEXDEF txt145 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.765469 0.625 APEX 0.5 0.859531 0.625 RAD 0.0078125 + txt145 +TEXDEF txt145 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.75 0.640469 APEX 0.5 0.75 0.734531 RAD 0.0078125 + txt145 +TEXDEF txt145 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.75 0.75 RAD 0.03125 + txt145 +TEXDEF txt146 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.75 0.75 APEX 0.609531 0.75 0.75 RAD 0.0078125 + txt146 +TEXDEF txt146 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.765469 0.75 APEX 0.5 0.859531 0.75 RAD 0.0078125 + txt146 +TEXDEF txt146 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.75 0.765469 APEX 0.5 0.75 0.859531 RAD 0.0078125 + txt146 +TEXDEF txt146 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.75 0.875 RAD 0.03125 + txt146 +TEXDEF txt146 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.75 0.875 APEX 0.609531 0.75 0.875 RAD 0.0078125 + txt146 +TEXDEF txt146 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.765469 0.875 APEX 0.5 0.859531 0.875 RAD 0.0078125 + txt146 +TEXDEF txt146 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.75 0.890469 APEX 0.5 0.75 0.984531 RAD 0.0078125 + txt146 +TEXDEF txt146 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.75 1 RAD 0.03125 + txt146 +TEXDEF txt146 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.75 1 APEX 0.609531 0.75 1 RAD 0.0078125 + txt146 +TEXDEF txt146 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.765469 1 APEX 0.5 0.859531 1 RAD 0.0078125 + txt146 +TEXDEF txt147 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.875 0 RAD 0.03125 + txt147 +TEXDEF txt147 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.875 0 APEX 0.609531 0.875 0 RAD 0.0078125 + txt147 +TEXDEF txt147 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.890469 0 APEX 0.5 0.984531 0 RAD 0.0078125 + txt147 +TEXDEF txt147 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.875 0.0154687 APEX 0.5 0.875 0.109531 RAD 0.0078125 + txt147 +TEXDEF txt147 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.875 0.125 RAD 0.03125 + txt147 +TEXDEF txt147 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.875 0.125 APEX 0.609531 0.875 0.125 RAD 0.0078125 + txt147 +TEXDEF txt147 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.890469 0.125 APEX 0.5 0.984531 0.125 RAD 0.0078125 + txt147 +TEXDEF txt147 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.875 0.140469 APEX 0.5 0.875 0.234531 RAD 0.0078125 + txt147 +TEXDEF txt147 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.875 0.25 RAD 0.03125 + txt147 +TEXDEF txt147 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.875 0.25 APEX 0.609531 0.875 0.25 RAD 0.0078125 + txt147 +TEXDEF txt148 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.890469 0.25 APEX 0.5 0.984531 0.25 RAD 0.0078125 + txt148 +TEXDEF txt148 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.875 0.265469 APEX 0.5 0.875 0.359531 RAD 0.0078125 + txt148 +TEXDEF txt148 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.875 0.375 RAD 0.03125 + txt148 +TEXDEF txt148 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.875 0.375 APEX 0.609531 0.875 0.375 RAD 0.0078125 + txt148 +TEXDEF txt148 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.890469 0.375 APEX 0.5 0.984531 0.375 RAD 0.0078125 + txt148 +TEXDEF txt148 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.875 0.390469 APEX 0.5 0.875 0.484531 RAD 0.0078125 + txt148 +TEXDEF txt148 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.875 0.5 RAD 0.03125 + txt148 +TEXDEF txt148 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.875 0.5 APEX 0.609531 0.875 0.5 RAD 0.0078125 + txt148 +TEXDEF txt148 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.890469 0.5 APEX 0.5 0.984531 0.5 RAD 0.0078125 + txt148 +TEXDEF txt148 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.875 0.515469 APEX 0.5 0.875 0.609531 RAD 0.0078125 + txt148 +TEXDEF txt149 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.875 0.625 RAD 0.03125 + txt149 +TEXDEF txt149 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.875 0.625 APEX 0.609531 0.875 0.625 RAD 0.0078125 + txt149 +TEXDEF txt149 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.890469 0.625 APEX 0.5 0.984531 0.625 RAD 0.0078125 + txt149 +TEXDEF txt149 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.875 0.640469 APEX 0.5 0.875 0.734531 RAD 0.0078125 + txt149 +TEXDEF txt149 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.875 0.75 RAD 0.03125 + txt149 +TEXDEF txt149 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.875 0.75 APEX 0.609531 0.875 0.75 RAD 0.0078125 + txt149 +TEXDEF txt149 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.890469 0.75 APEX 0.5 0.984531 0.75 RAD 0.0078125 + txt149 +TEXDEF txt149 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.875 0.765469 APEX 0.5 0.875 0.859531 RAD 0.0078125 + txt149 +TEXDEF txt149 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.875 0.875 RAD 0.03125 + txt149 +TEXDEF txt149 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.875 0.875 APEX 0.609531 0.875 0.875 RAD 0.0078125 + txt149 +TEXDEF txt150 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.890469 0.875 APEX 0.5 0.984531 0.875 RAD 0.0078125 + txt150 +TEXDEF txt150 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.875 0.890469 APEX 0.5 0.875 0.984531 RAD 0.0078125 + txt150 +TEXDEF txt150 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 0.875 1 RAD 0.03125 + txt150 +TEXDEF txt150 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 0.875 1 APEX 0.609531 0.875 1 RAD 0.0078125 + txt150 +TEXDEF txt150 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 0.890469 1 APEX 0.5 0.984531 1 RAD 0.0078125 + txt150 +TEXDEF txt150 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 1 0 RAD 0.03125 + txt150 +TEXDEF txt150 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 1 0 APEX 0.609531 1 0 RAD 0.0078125 + txt150 +TEXDEF txt150 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 1 0.0154687 APEX 0.5 1 0.109531 RAD 0.0078125 + txt150 +TEXDEF txt150 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 1 0.125 RAD 0.03125 + txt150 +TEXDEF txt150 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 1 0.125 APEX 0.609531 1 0.125 RAD 0.0078125 + txt150 +TEXDEF txt151 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 1 0.140469 APEX 0.5 1 0.234531 RAD 0.0078125 + txt151 +TEXDEF txt151 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 1 0.25 RAD 0.03125 + txt151 +TEXDEF txt151 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 1 0.25 APEX 0.609531 1 0.25 RAD 0.0078125 + txt151 +TEXDEF txt151 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 1 0.265469 APEX 0.5 1 0.359531 RAD 0.0078125 + txt151 +TEXDEF txt151 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 1 0.375 RAD 0.03125 + txt151 +TEXDEF txt151 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 1 0.375 APEX 0.609531 1 0.375 RAD 0.0078125 + txt151 +TEXDEF txt151 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 1 0.390469 APEX 0.5 1 0.484531 RAD 0.0078125 + txt151 +TEXDEF txt151 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 1 0.5 RAD 0.03125 + txt151 +TEXDEF txt151 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 1 0.5 APEX 0.609531 1 0.5 RAD 0.0078125 + txt151 +TEXDEF txt151 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 1 0.515469 APEX 0.5 1 0.609531 RAD 0.0078125 + txt151 +TEXDEF txt152 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 1 0.625 RAD 0.03125 + txt152 +TEXDEF txt152 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 1 0.625 APEX 0.609531 1 0.625 RAD 0.0078125 + txt152 +TEXDEF txt152 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 1 0.640469 APEX 0.5 1 0.734531 RAD 0.0078125 + txt152 +TEXDEF txt152 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 1 0.75 RAD 0.03125 + txt152 +TEXDEF txt152 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 1 0.75 APEX 0.609531 1 0.75 RAD 0.0078125 + txt152 +TEXDEF txt152 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 1 0.765469 APEX 0.5 1 0.859531 RAD 0.0078125 + txt152 +TEXDEF txt152 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 1 0.875 RAD 0.03125 + txt152 +TEXDEF txt152 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 1 0.875 APEX 0.609531 1 0.875 RAD 0.0078125 + txt152 +TEXDEF txt152 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.5 1 0.890469 APEX 0.5 1 0.984531 RAD 0.0078125 + txt152 +TEXDEF txt152 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.5 1 1 RAD 0.03125 + txt152 +TEXDEF txt153 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.515469 1 1 APEX 0.609531 1 1 RAD 0.0078125 + txt153 +TEXDEF txt153 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0 0 RAD 0.03125 + txt153 +TEXDEF txt153 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0 0 APEX 0.734531 0 0 RAD 0.0078125 + txt153 +TEXDEF txt153 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.0154687 0 APEX 0.625 0.109531 0 RAD 0.0078125 + txt153 +TEXDEF txt153 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0 0.0154687 APEX 0.625 0 0.109531 RAD 0.0078125 + txt153 +TEXDEF txt153 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0 0.125 RAD 0.03125 + txt153 +TEXDEF txt153 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0 0.125 APEX 0.734531 0 0.125 RAD 0.0078125 + txt153 +TEXDEF txt153 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.0154687 0.125 APEX 0.625 0.109531 0.125 RAD 0.0078125 + txt153 +TEXDEF txt153 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0 0.140469 APEX 0.625 0 0.234531 RAD 0.0078125 + txt153 +TEXDEF txt153 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0 0.25 RAD 0.03125 + txt153 +TEXDEF txt154 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0 0.25 APEX 0.734531 0 0.25 RAD 0.0078125 + txt154 +TEXDEF txt154 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.0154687 0.25 APEX 0.625 0.109531 0.25 RAD 0.0078125 + txt154 +TEXDEF txt154 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0 0.265469 APEX 0.625 0 0.359531 RAD 0.0078125 + txt154 +TEXDEF txt154 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0 0.375 RAD 0.03125 + txt154 +TEXDEF txt154 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0 0.375 APEX 0.734531 0 0.375 RAD 0.0078125 + txt154 +TEXDEF txt154 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.0154687 0.375 APEX 0.625 0.109531 0.375 RAD 0.0078125 + txt154 +TEXDEF txt154 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0 0.390469 APEX 0.625 0 0.484531 RAD 0.0078125 + txt154 +TEXDEF txt154 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0 0.5 RAD 0.03125 + txt154 +TEXDEF txt154 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0 0.5 APEX 0.734531 0 0.5 RAD 0.0078125 + txt154 +TEXDEF txt154 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.0154687 0.5 APEX 0.625 0.109531 0.5 RAD 0.0078125 + txt154 +TEXDEF txt155 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0 0.515469 APEX 0.625 0 0.609531 RAD 0.0078125 + txt155 +TEXDEF txt155 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0 0.625 RAD 0.03125 + txt155 +TEXDEF txt155 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0 0.625 APEX 0.734531 0 0.625 RAD 0.0078125 + txt155 +TEXDEF txt155 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.0154687 0.625 APEX 0.625 0.109531 0.625 RAD 0.0078125 + txt155 +TEXDEF txt155 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0 0.640469 APEX 0.625 0 0.734531 RAD 0.0078125 + txt155 +TEXDEF txt155 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0 0.75 RAD 0.03125 + txt155 +TEXDEF txt155 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0 0.75 APEX 0.734531 0 0.75 RAD 0.0078125 + txt155 +TEXDEF txt155 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.0154687 0.75 APEX 0.625 0.109531 0.75 RAD 0.0078125 + txt155 +TEXDEF txt155 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0 0.765469 APEX 0.625 0 0.859531 RAD 0.0078125 + txt155 +TEXDEF txt155 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0 0.875 RAD 0.03125 + txt155 +TEXDEF txt156 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0 0.875 APEX 0.734531 0 0.875 RAD 0.0078125 + txt156 +TEXDEF txt156 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.0154687 0.875 APEX 0.625 0.109531 0.875 RAD 0.0078125 + txt156 +TEXDEF txt156 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0 0.890469 APEX 0.625 0 0.984531 RAD 0.0078125 + txt156 +TEXDEF txt156 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0 1 RAD 0.03125 + txt156 +TEXDEF txt156 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0 1 APEX 0.734531 0 1 RAD 0.0078125 + txt156 +TEXDEF txt156 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.0154687 1 APEX 0.625 0.109531 1 RAD 0.0078125 + txt156 +TEXDEF txt156 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.125 0 RAD 0.03125 + txt156 +TEXDEF txt156 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.125 0 APEX 0.734531 0.125 0 RAD 0.0078125 + txt156 +TEXDEF txt156 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.140469 0 APEX 0.625 0.234531 0 RAD 0.0078125 + txt156 +TEXDEF txt156 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.125 0.0154687 APEX 0.625 0.125 0.109531 RAD 0.0078125 + txt156 +TEXDEF txt157 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.125 0.125 RAD 0.03125 + txt157 +TEXDEF txt157 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.125 0.125 APEX 0.734531 0.125 0.125 RAD 0.0078125 + txt157 +TEXDEF txt157 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.140469 0.125 APEX 0.625 0.234531 0.125 RAD 0.0078125 + txt157 +TEXDEF txt157 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.125 0.140469 APEX 0.625 0.125 0.234531 RAD 0.0078125 + txt157 +TEXDEF txt157 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.125 0.25 RAD 0.03125 + txt157 +TEXDEF txt157 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.125 0.25 APEX 0.734531 0.125 0.25 RAD 0.0078125 + txt157 +TEXDEF txt157 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.140469 0.25 APEX 0.625 0.234531 0.25 RAD 0.0078125 + txt157 +TEXDEF txt157 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.125 0.265469 APEX 0.625 0.125 0.359531 RAD 0.0078125 + txt157 +TEXDEF txt157 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.125 0.375 RAD 0.03125 + txt157 +TEXDEF txt157 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.125 0.375 APEX 0.734531 0.125 0.375 RAD 0.0078125 + txt157 +TEXDEF txt158 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.140469 0.375 APEX 0.625 0.234531 0.375 RAD 0.0078125 + txt158 +TEXDEF txt158 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.125 0.390469 APEX 0.625 0.125 0.484531 RAD 0.0078125 + txt158 +TEXDEF txt158 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.125 0.5 RAD 0.03125 + txt158 +TEXDEF txt158 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.125 0.5 APEX 0.734531 0.125 0.5 RAD 0.0078125 + txt158 +TEXDEF txt158 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.140469 0.5 APEX 0.625 0.234531 0.5 RAD 0.0078125 + txt158 +TEXDEF txt158 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.125 0.515469 APEX 0.625 0.125 0.609531 RAD 0.0078125 + txt158 +TEXDEF txt158 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.125 0.625 RAD 0.03125 + txt158 +TEXDEF txt158 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.125 0.625 APEX 0.734531 0.125 0.625 RAD 0.0078125 + txt158 +TEXDEF txt158 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.140469 0.625 APEX 0.625 0.234531 0.625 RAD 0.0078125 + txt158 +TEXDEF txt158 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.125 0.640469 APEX 0.625 0.125 0.734531 RAD 0.0078125 + txt158 +TEXDEF txt159 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.125 0.75 RAD 0.03125 + txt159 +TEXDEF txt159 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.125 0.75 APEX 0.734531 0.125 0.75 RAD 0.0078125 + txt159 +TEXDEF txt159 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.140469 0.75 APEX 0.625 0.234531 0.75 RAD 0.0078125 + txt159 +TEXDEF txt159 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.125 0.765469 APEX 0.625 0.125 0.859531 RAD 0.0078125 + txt159 +TEXDEF txt159 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.125 0.875 RAD 0.03125 + txt159 +TEXDEF txt159 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.125 0.875 APEX 0.734531 0.125 0.875 RAD 0.0078125 + txt159 +TEXDEF txt159 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.140469 0.875 APEX 0.625 0.234531 0.875 RAD 0.0078125 + txt159 +TEXDEF txt159 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.125 0.890469 APEX 0.625 0.125 0.984531 RAD 0.0078125 + txt159 +TEXDEF txt159 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.125 1 RAD 0.03125 + txt159 +TEXDEF txt159 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.125 1 APEX 0.734531 0.125 1 RAD 0.0078125 + txt159 +TEXDEF txt160 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.140469 1 APEX 0.625 0.234531 1 RAD 0.0078125 + txt160 +TEXDEF txt160 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.25 0 RAD 0.03125 + txt160 +TEXDEF txt160 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.25 0 APEX 0.734531 0.25 0 RAD 0.0078125 + txt160 +TEXDEF txt160 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.265469 0 APEX 0.625 0.359531 0 RAD 0.0078125 + txt160 +TEXDEF txt160 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.25 0.0154687 APEX 0.625 0.25 0.109531 RAD 0.0078125 + txt160 +TEXDEF txt160 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.25 0.125 RAD 0.03125 + txt160 +TEXDEF txt160 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.25 0.125 APEX 0.734531 0.25 0.125 RAD 0.0078125 + txt160 +TEXDEF txt160 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.265469 0.125 APEX 0.625 0.359531 0.125 RAD 0.0078125 + txt160 +TEXDEF txt160 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.25 0.140469 APEX 0.625 0.25 0.234531 RAD 0.0078125 + txt160 +TEXDEF txt160 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.25 0.25 RAD 0.03125 + txt160 +TEXDEF txt161 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.25 0.25 APEX 0.734531 0.25 0.25 RAD 0.0078125 + txt161 +TEXDEF txt161 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.265469 0.25 APEX 0.625 0.359531 0.25 RAD 0.0078125 + txt161 +TEXDEF txt161 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.25 0.265469 APEX 0.625 0.25 0.359531 RAD 0.0078125 + txt161 +TEXDEF txt161 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.25 0.375 RAD 0.03125 + txt161 +TEXDEF txt161 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.25 0.375 APEX 0.734531 0.25 0.375 RAD 0.0078125 + txt161 +TEXDEF txt161 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.265469 0.375 APEX 0.625 0.359531 0.375 RAD 0.0078125 + txt161 +TEXDEF txt161 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.25 0.390469 APEX 0.625 0.25 0.484531 RAD 0.0078125 + txt161 +TEXDEF txt161 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.25 0.5 RAD 0.03125 + txt161 +TEXDEF txt161 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.25 0.5 APEX 0.734531 0.25 0.5 RAD 0.0078125 + txt161 +TEXDEF txt161 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.265469 0.5 APEX 0.625 0.359531 0.5 RAD 0.0078125 + txt161 +TEXDEF txt162 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.25 0.515469 APEX 0.625 0.25 0.609531 RAD 0.0078125 + txt162 +TEXDEF txt162 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.25 0.625 RAD 0.03125 + txt162 +TEXDEF txt162 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.25 0.625 APEX 0.734531 0.25 0.625 RAD 0.0078125 + txt162 +TEXDEF txt162 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.265469 0.625 APEX 0.625 0.359531 0.625 RAD 0.0078125 + txt162 +TEXDEF txt162 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.25 0.640469 APEX 0.625 0.25 0.734531 RAD 0.0078125 + txt162 +TEXDEF txt162 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.25 0.75 RAD 0.03125 + txt162 +TEXDEF txt162 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.25 0.75 APEX 0.734531 0.25 0.75 RAD 0.0078125 + txt162 +TEXDEF txt162 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.265469 0.75 APEX 0.625 0.359531 0.75 RAD 0.0078125 + txt162 +TEXDEF txt162 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.25 0.765469 APEX 0.625 0.25 0.859531 RAD 0.0078125 + txt162 +TEXDEF txt162 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.25 0.875 RAD 0.03125 + txt162 +TEXDEF txt163 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.25 0.875 APEX 0.734531 0.25 0.875 RAD 0.0078125 + txt163 +TEXDEF txt163 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.265469 0.875 APEX 0.625 0.359531 0.875 RAD 0.0078125 + txt163 +TEXDEF txt163 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.25 0.890469 APEX 0.625 0.25 0.984531 RAD 0.0078125 + txt163 +TEXDEF txt163 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.25 1 RAD 0.03125 + txt163 +TEXDEF txt163 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.25 1 APEX 0.734531 0.25 1 RAD 0.0078125 + txt163 +TEXDEF txt163 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.265469 1 APEX 0.625 0.359531 1 RAD 0.0078125 + txt163 +TEXDEF txt163 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.375 0 RAD 0.03125 + txt163 +TEXDEF txt163 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.375 0 APEX 0.734531 0.375 0 RAD 0.0078125 + txt163 +TEXDEF txt163 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.390469 0 APEX 0.625 0.484531 0 RAD 0.0078125 + txt163 +TEXDEF txt163 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.375 0.0154687 APEX 0.625 0.375 0.109531 RAD 0.0078125 + txt163 +TEXDEF txt164 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.375 0.125 RAD 0.03125 + txt164 +TEXDEF txt164 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.375 0.125 APEX 0.734531 0.375 0.125 RAD 0.0078125 + txt164 +TEXDEF txt164 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.390469 0.125 APEX 0.625 0.484531 0.125 RAD 0.0078125 + txt164 +TEXDEF txt164 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.375 0.140469 APEX 0.625 0.375 0.234531 RAD 0.0078125 + txt164 +TEXDEF txt164 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.375 0.25 RAD 0.03125 + txt164 +TEXDEF txt164 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.375 0.25 APEX 0.734531 0.375 0.25 RAD 0.0078125 + txt164 +TEXDEF txt164 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.390469 0.25 APEX 0.625 0.484531 0.25 RAD 0.0078125 + txt164 +TEXDEF txt164 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.375 0.265469 APEX 0.625 0.375 0.359531 RAD 0.0078125 + txt164 +TEXDEF txt164 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.375 0.375 RAD 0.03125 + txt164 +TEXDEF txt164 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.375 0.375 APEX 0.734531 0.375 0.375 RAD 0.0078125 + txt164 +TEXDEF txt165 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.390469 0.375 APEX 0.625 0.484531 0.375 RAD 0.0078125 + txt165 +TEXDEF txt165 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.375 0.390469 APEX 0.625 0.375 0.484531 RAD 0.0078125 + txt165 +TEXDEF txt165 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.375 0.5 RAD 0.03125 + txt165 +TEXDEF txt165 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.375 0.5 APEX 0.734531 0.375 0.5 RAD 0.0078125 + txt165 +TEXDEF txt165 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.390469 0.5 APEX 0.625 0.484531 0.5 RAD 0.0078125 + txt165 +TEXDEF txt165 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.375 0.515469 APEX 0.625 0.375 0.609531 RAD 0.0078125 + txt165 +TEXDEF txt165 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.375 0.625 RAD 0.03125 + txt165 +TEXDEF txt165 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.375 0.625 APEX 0.734531 0.375 0.625 RAD 0.0078125 + txt165 +TEXDEF txt165 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.390469 0.625 APEX 0.625 0.484531 0.625 RAD 0.0078125 + txt165 +TEXDEF txt165 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.375 0.640469 APEX 0.625 0.375 0.734531 RAD 0.0078125 + txt165 +TEXDEF txt166 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.375 0.75 RAD 0.03125 + txt166 +TEXDEF txt166 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.375 0.75 APEX 0.734531 0.375 0.75 RAD 0.0078125 + txt166 +TEXDEF txt166 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.390469 0.75 APEX 0.625 0.484531 0.75 RAD 0.0078125 + txt166 +TEXDEF txt166 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.375 0.765469 APEX 0.625 0.375 0.859531 RAD 0.0078125 + txt166 +TEXDEF txt166 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.375 0.875 RAD 0.03125 + txt166 +TEXDEF txt166 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.375 0.875 APEX 0.734531 0.375 0.875 RAD 0.0078125 + txt166 +TEXDEF txt166 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.390469 0.875 APEX 0.625 0.484531 0.875 RAD 0.0078125 + txt166 +TEXDEF txt166 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.375 0.890469 APEX 0.625 0.375 0.984531 RAD 0.0078125 + txt166 +TEXDEF txt166 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.375 1 RAD 0.03125 + txt166 +TEXDEF txt166 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.375 1 APEX 0.734531 0.375 1 RAD 0.0078125 + txt166 +TEXDEF txt167 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.390469 1 APEX 0.625 0.484531 1 RAD 0.0078125 + txt167 +TEXDEF txt167 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.5 0 RAD 0.03125 + txt167 +TEXDEF txt167 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.5 0 APEX 0.734531 0.5 0 RAD 0.0078125 + txt167 +TEXDEF txt167 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.515469 0 APEX 0.625 0.609531 0 RAD 0.0078125 + txt167 +TEXDEF txt167 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.5 0.0154687 APEX 0.625 0.5 0.109531 RAD 0.0078125 + txt167 +TEXDEF txt167 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.5 0.125 RAD 0.03125 + txt167 +TEXDEF txt167 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.5 0.125 APEX 0.734531 0.5 0.125 RAD 0.0078125 + txt167 +TEXDEF txt167 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.515469 0.125 APEX 0.625 0.609531 0.125 RAD 0.0078125 + txt167 +TEXDEF txt167 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.5 0.140469 APEX 0.625 0.5 0.234531 RAD 0.0078125 + txt167 +TEXDEF txt167 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.5 0.25 RAD 0.03125 + txt167 +TEXDEF txt168 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.5 0.25 APEX 0.734531 0.5 0.25 RAD 0.0078125 + txt168 +TEXDEF txt168 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.515469 0.25 APEX 0.625 0.609531 0.25 RAD 0.0078125 + txt168 +TEXDEF txt168 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.5 0.265469 APEX 0.625 0.5 0.359531 RAD 0.0078125 + txt168 +TEXDEF txt168 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.5 0.375 RAD 0.03125 + txt168 +TEXDEF txt168 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.5 0.375 APEX 0.734531 0.5 0.375 RAD 0.0078125 + txt168 +TEXDEF txt168 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.515469 0.375 APEX 0.625 0.609531 0.375 RAD 0.0078125 + txt168 +TEXDEF txt168 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.5 0.390469 APEX 0.625 0.5 0.484531 RAD 0.0078125 + txt168 +TEXDEF txt168 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.5 0.5 RAD 0.03125 + txt168 +TEXDEF txt168 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.5 0.5 APEX 0.734531 0.5 0.5 RAD 0.0078125 + txt168 +TEXDEF txt168 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.515469 0.5 APEX 0.625 0.609531 0.5 RAD 0.0078125 + txt168 +TEXDEF txt169 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.5 0.515469 APEX 0.625 0.5 0.609531 RAD 0.0078125 + txt169 +TEXDEF txt169 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.5 0.625 RAD 0.03125 + txt169 +TEXDEF txt169 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.5 0.625 APEX 0.734531 0.5 0.625 RAD 0.0078125 + txt169 +TEXDEF txt169 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.515469 0.625 APEX 0.625 0.609531 0.625 RAD 0.0078125 + txt169 +TEXDEF txt169 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.5 0.640469 APEX 0.625 0.5 0.734531 RAD 0.0078125 + txt169 +TEXDEF txt169 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.5 0.75 RAD 0.03125 + txt169 +TEXDEF txt169 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.5 0.75 APEX 0.734531 0.5 0.75 RAD 0.0078125 + txt169 +TEXDEF txt169 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.515469 0.75 APEX 0.625 0.609531 0.75 RAD 0.0078125 + txt169 +TEXDEF txt169 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.5 0.765469 APEX 0.625 0.5 0.859531 RAD 0.0078125 + txt169 +TEXDEF txt169 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.5 0.875 RAD 0.03125 + txt169 +TEXDEF txt170 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.5 0.875 APEX 0.734531 0.5 0.875 RAD 0.0078125 + txt170 +TEXDEF txt170 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.515469 0.875 APEX 0.625 0.609531 0.875 RAD 0.0078125 + txt170 +TEXDEF txt170 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.5 0.890469 APEX 0.625 0.5 0.984531 RAD 0.0078125 + txt170 +TEXDEF txt170 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.5 1 RAD 0.03125 + txt170 +TEXDEF txt170 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.5 1 APEX 0.734531 0.5 1 RAD 0.0078125 + txt170 +TEXDEF txt170 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.515469 1 APEX 0.625 0.609531 1 RAD 0.0078125 + txt170 +TEXDEF txt170 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.625 0 RAD 0.03125 + txt170 +TEXDEF txt170 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.625 0 APEX 0.734531 0.625 0 RAD 0.0078125 + txt170 +TEXDEF txt170 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.640469 0 APEX 0.625 0.734531 0 RAD 0.0078125 + txt170 +TEXDEF txt170 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.625 0.0154687 APEX 0.625 0.625 0.109531 RAD 0.0078125 + txt170 +TEXDEF txt171 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.625 0.125 RAD 0.03125 + txt171 +TEXDEF txt171 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.625 0.125 APEX 0.734531 0.625 0.125 RAD 0.0078125 + txt171 +TEXDEF txt171 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.640469 0.125 APEX 0.625 0.734531 0.125 RAD 0.0078125 + txt171 +TEXDEF txt171 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.625 0.140469 APEX 0.625 0.625 0.234531 RAD 0.0078125 + txt171 +TEXDEF txt171 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.625 0.25 RAD 0.03125 + txt171 +TEXDEF txt171 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.625 0.25 APEX 0.734531 0.625 0.25 RAD 0.0078125 + txt171 +TEXDEF txt171 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.640469 0.25 APEX 0.625 0.734531 0.25 RAD 0.0078125 + txt171 +TEXDEF txt171 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.625 0.265469 APEX 0.625 0.625 0.359531 RAD 0.0078125 + txt171 +TEXDEF txt171 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.625 0.375 RAD 0.03125 + txt171 +TEXDEF txt171 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.625 0.375 APEX 0.734531 0.625 0.375 RAD 0.0078125 + txt171 +TEXDEF txt172 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.640469 0.375 APEX 0.625 0.734531 0.375 RAD 0.0078125 + txt172 +TEXDEF txt172 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.625 0.390469 APEX 0.625 0.625 0.484531 RAD 0.0078125 + txt172 +TEXDEF txt172 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.625 0.5 RAD 0.03125 + txt172 +TEXDEF txt172 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.625 0.5 APEX 0.734531 0.625 0.5 RAD 0.0078125 + txt172 +TEXDEF txt172 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.640469 0.5 APEX 0.625 0.734531 0.5 RAD 0.0078125 + txt172 +TEXDEF txt172 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.625 0.515469 APEX 0.625 0.625 0.609531 RAD 0.0078125 + txt172 +TEXDEF txt172 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.625 0.625 RAD 0.03125 + txt172 +TEXDEF txt172 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.625 0.625 APEX 0.734531 0.625 0.625 RAD 0.0078125 + txt172 +TEXDEF txt172 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.640469 0.625 APEX 0.625 0.734531 0.625 RAD 0.0078125 + txt172 +TEXDEF txt172 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.625 0.640469 APEX 0.625 0.625 0.734531 RAD 0.0078125 + txt172 +TEXDEF txt173 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.625 0.75 RAD 0.03125 + txt173 +TEXDEF txt173 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.625 0.75 APEX 0.734531 0.625 0.75 RAD 0.0078125 + txt173 +TEXDEF txt173 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.640469 0.75 APEX 0.625 0.734531 0.75 RAD 0.0078125 + txt173 +TEXDEF txt173 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.625 0.765469 APEX 0.625 0.625 0.859531 RAD 0.0078125 + txt173 +TEXDEF txt173 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.625 0.875 RAD 0.03125 + txt173 +TEXDEF txt173 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.625 0.875 APEX 0.734531 0.625 0.875 RAD 0.0078125 + txt173 +TEXDEF txt173 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.640469 0.875 APEX 0.625 0.734531 0.875 RAD 0.0078125 + txt173 +TEXDEF txt173 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.625 0.890469 APEX 0.625 0.625 0.984531 RAD 0.0078125 + txt173 +TEXDEF txt173 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.625 1 RAD 0.03125 + txt173 +TEXDEF txt173 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.625 1 APEX 0.734531 0.625 1 RAD 0.0078125 + txt173 +TEXDEF txt174 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.640469 1 APEX 0.625 0.734531 1 RAD 0.0078125 + txt174 +TEXDEF txt174 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.75 0 RAD 0.03125 + txt174 +TEXDEF txt174 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.75 0 APEX 0.734531 0.75 0 RAD 0.0078125 + txt174 +TEXDEF txt174 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.765469 0 APEX 0.625 0.859531 0 RAD 0.0078125 + txt174 +TEXDEF txt174 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.75 0.0154687 APEX 0.625 0.75 0.109531 RAD 0.0078125 + txt174 +TEXDEF txt174 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.75 0.125 RAD 0.03125 + txt174 +TEXDEF txt174 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.75 0.125 APEX 0.734531 0.75 0.125 RAD 0.0078125 + txt174 +TEXDEF txt174 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.765469 0.125 APEX 0.625 0.859531 0.125 RAD 0.0078125 + txt174 +TEXDEF txt174 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.75 0.140469 APEX 0.625 0.75 0.234531 RAD 0.0078125 + txt174 +TEXDEF txt174 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.75 0.25 RAD 0.03125 + txt174 +TEXDEF txt175 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.75 0.25 APEX 0.734531 0.75 0.25 RAD 0.0078125 + txt175 +TEXDEF txt175 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.765469 0.25 APEX 0.625 0.859531 0.25 RAD 0.0078125 + txt175 +TEXDEF txt175 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.75 0.265469 APEX 0.625 0.75 0.359531 RAD 0.0078125 + txt175 +TEXDEF txt175 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.75 0.375 RAD 0.03125 + txt175 +TEXDEF txt175 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.75 0.375 APEX 0.734531 0.75 0.375 RAD 0.0078125 + txt175 +TEXDEF txt175 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.765469 0.375 APEX 0.625 0.859531 0.375 RAD 0.0078125 + txt175 +TEXDEF txt175 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.75 0.390469 APEX 0.625 0.75 0.484531 RAD 0.0078125 + txt175 +TEXDEF txt175 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.75 0.5 RAD 0.03125 + txt175 +TEXDEF txt175 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.75 0.5 APEX 0.734531 0.75 0.5 RAD 0.0078125 + txt175 +TEXDEF txt175 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.765469 0.5 APEX 0.625 0.859531 0.5 RAD 0.0078125 + txt175 +TEXDEF txt176 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.75 0.515469 APEX 0.625 0.75 0.609531 RAD 0.0078125 + txt176 +TEXDEF txt176 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.75 0.625 RAD 0.03125 + txt176 +TEXDEF txt176 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.75 0.625 APEX 0.734531 0.75 0.625 RAD 0.0078125 + txt176 +TEXDEF txt176 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.765469 0.625 APEX 0.625 0.859531 0.625 RAD 0.0078125 + txt176 +TEXDEF txt176 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.75 0.640469 APEX 0.625 0.75 0.734531 RAD 0.0078125 + txt176 +TEXDEF txt176 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.75 0.75 RAD 0.03125 + txt176 +TEXDEF txt176 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.75 0.75 APEX 0.734531 0.75 0.75 RAD 0.0078125 + txt176 +TEXDEF txt176 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.765469 0.75 APEX 0.625 0.859531 0.75 RAD 0.0078125 + txt176 +TEXDEF txt176 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.75 0.765469 APEX 0.625 0.75 0.859531 RAD 0.0078125 + txt176 +TEXDEF txt176 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.75 0.875 RAD 0.03125 + txt176 +TEXDEF txt177 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.75 0.875 APEX 0.734531 0.75 0.875 RAD 0.0078125 + txt177 +TEXDEF txt177 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.765469 0.875 APEX 0.625 0.859531 0.875 RAD 0.0078125 + txt177 +TEXDEF txt177 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.75 0.890469 APEX 0.625 0.75 0.984531 RAD 0.0078125 + txt177 +TEXDEF txt177 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.75 1 RAD 0.03125 + txt177 +TEXDEF txt177 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.75 1 APEX 0.734531 0.75 1 RAD 0.0078125 + txt177 +TEXDEF txt177 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.765469 1 APEX 0.625 0.859531 1 RAD 0.0078125 + txt177 +TEXDEF txt177 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.875 0 RAD 0.03125 + txt177 +TEXDEF txt177 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.875 0 APEX 0.734531 0.875 0 RAD 0.0078125 + txt177 +TEXDEF txt177 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.890469 0 APEX 0.625 0.984531 0 RAD 0.0078125 + txt177 +TEXDEF txt177 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.875 0.0154687 APEX 0.625 0.875 0.109531 RAD 0.0078125 + txt177 +TEXDEF txt178 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.875 0.125 RAD 0.03125 + txt178 +TEXDEF txt178 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.875 0.125 APEX 0.734531 0.875 0.125 RAD 0.0078125 + txt178 +TEXDEF txt178 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.890469 0.125 APEX 0.625 0.984531 0.125 RAD 0.0078125 + txt178 +TEXDEF txt178 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.875 0.140469 APEX 0.625 0.875 0.234531 RAD 0.0078125 + txt178 +TEXDEF txt178 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.875 0.25 RAD 0.03125 + txt178 +TEXDEF txt178 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.875 0.25 APEX 0.734531 0.875 0.25 RAD 0.0078125 + txt178 +TEXDEF txt178 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.890469 0.25 APEX 0.625 0.984531 0.25 RAD 0.0078125 + txt178 +TEXDEF txt178 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.875 0.265469 APEX 0.625 0.875 0.359531 RAD 0.0078125 + txt178 +TEXDEF txt178 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.875 0.375 RAD 0.03125 + txt178 +TEXDEF txt178 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.875 0.375 APEX 0.734531 0.875 0.375 RAD 0.0078125 + txt178 +TEXDEF txt179 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.890469 0.375 APEX 0.625 0.984531 0.375 RAD 0.0078125 + txt179 +TEXDEF txt179 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.875 0.390469 APEX 0.625 0.875 0.484531 RAD 0.0078125 + txt179 +TEXDEF txt179 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.875 0.5 RAD 0.03125 + txt179 +TEXDEF txt179 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.875 0.5 APEX 0.734531 0.875 0.5 RAD 0.0078125 + txt179 +TEXDEF txt179 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.890469 0.5 APEX 0.625 0.984531 0.5 RAD 0.0078125 + txt179 +TEXDEF txt179 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.875 0.515469 APEX 0.625 0.875 0.609531 RAD 0.0078125 + txt179 +TEXDEF txt179 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.875 0.625 RAD 0.03125 + txt179 +TEXDEF txt179 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.875 0.625 APEX 0.734531 0.875 0.625 RAD 0.0078125 + txt179 +TEXDEF txt179 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.890469 0.625 APEX 0.625 0.984531 0.625 RAD 0.0078125 + txt179 +TEXDEF txt179 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.875 0.640469 APEX 0.625 0.875 0.734531 RAD 0.0078125 + txt179 +TEXDEF txt180 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.875 0.75 RAD 0.03125 + txt180 +TEXDEF txt180 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.875 0.75 APEX 0.734531 0.875 0.75 RAD 0.0078125 + txt180 +TEXDEF txt180 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.890469 0.75 APEX 0.625 0.984531 0.75 RAD 0.0078125 + txt180 +TEXDEF txt180 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.875 0.765469 APEX 0.625 0.875 0.859531 RAD 0.0078125 + txt180 +TEXDEF txt180 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.875 0.875 RAD 0.03125 + txt180 +TEXDEF txt180 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.875 0.875 APEX 0.734531 0.875 0.875 RAD 0.0078125 + txt180 +TEXDEF txt180 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.890469 0.875 APEX 0.625 0.984531 0.875 RAD 0.0078125 + txt180 +TEXDEF txt180 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.875 0.890469 APEX 0.625 0.875 0.984531 RAD 0.0078125 + txt180 +TEXDEF txt180 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 0.875 1 RAD 0.03125 + txt180 +TEXDEF txt180 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 0.875 1 APEX 0.734531 0.875 1 RAD 0.0078125 + txt180 +TEXDEF txt181 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 0.890469 1 APEX 0.625 0.984531 1 RAD 0.0078125 + txt181 +TEXDEF txt181 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 1 0 RAD 0.03125 + txt181 +TEXDEF txt181 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 1 0 APEX 0.734531 1 0 RAD 0.0078125 + txt181 +TEXDEF txt181 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 1 0.0154687 APEX 0.625 1 0.109531 RAD 0.0078125 + txt181 +TEXDEF txt181 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 1 0.125 RAD 0.03125 + txt181 +TEXDEF txt181 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 1 0.125 APEX 0.734531 1 0.125 RAD 0.0078125 + txt181 +TEXDEF txt181 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 1 0.140469 APEX 0.625 1 0.234531 RAD 0.0078125 + txt181 +TEXDEF txt181 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 1 0.25 RAD 0.03125 + txt181 +TEXDEF txt181 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 1 0.25 APEX 0.734531 1 0.25 RAD 0.0078125 + txt181 +TEXDEF txt181 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 1 0.265469 APEX 0.625 1 0.359531 RAD 0.0078125 + txt181 +TEXDEF txt182 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 1 0.375 RAD 0.03125 + txt182 +TEXDEF txt182 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 1 0.375 APEX 0.734531 1 0.375 RAD 0.0078125 + txt182 +TEXDEF txt182 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 1 0.390469 APEX 0.625 1 0.484531 RAD 0.0078125 + txt182 +TEXDEF txt182 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 1 0.5 RAD 0.03125 + txt182 +TEXDEF txt182 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 1 0.5 APEX 0.734531 1 0.5 RAD 0.0078125 + txt182 +TEXDEF txt182 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 1 0.515469 APEX 0.625 1 0.609531 RAD 0.0078125 + txt182 +TEXDEF txt182 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 1 0.625 RAD 0.03125 + txt182 +TEXDEF txt182 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 1 0.625 APEX 0.734531 1 0.625 RAD 0.0078125 + txt182 +TEXDEF txt182 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 1 0.640469 APEX 0.625 1 0.734531 RAD 0.0078125 + txt182 +TEXDEF txt182 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 1 0.75 RAD 0.03125 + txt182 +TEXDEF txt183 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 1 0.75 APEX 0.734531 1 0.75 RAD 0.0078125 + txt183 +TEXDEF txt183 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 1 0.765469 APEX 0.625 1 0.859531 RAD 0.0078125 + txt183 +TEXDEF txt183 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 1 0.875 RAD 0.03125 + txt183 +TEXDEF txt183 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 1 0.875 APEX 0.734531 1 0.875 RAD 0.0078125 + txt183 +TEXDEF txt183 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.625 1 0.890469 APEX 0.625 1 0.984531 RAD 0.0078125 + txt183 +TEXDEF txt183 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.625 1 1 RAD 0.03125 + txt183 +TEXDEF txt183 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.640469 1 1 APEX 0.734531 1 1 RAD 0.0078125 + txt183 +TEXDEF txt183 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0 0 RAD 0.03125 + txt183 +TEXDEF txt183 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0 0 APEX 0.859531 0 0 RAD 0.0078125 + txt183 +TEXDEF txt183 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.0154687 0 APEX 0.75 0.109531 0 RAD 0.0078125 + txt183 +TEXDEF txt184 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0 0.0154687 APEX 0.75 0 0.109531 RAD 0.0078125 + txt184 +TEXDEF txt184 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0 0.125 RAD 0.03125 + txt184 +TEXDEF txt184 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0 0.125 APEX 0.859531 0 0.125 RAD 0.0078125 + txt184 +TEXDEF txt184 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.0154687 0.125 APEX 0.75 0.109531 0.125 RAD 0.0078125 + txt184 +TEXDEF txt184 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0 0.140469 APEX 0.75 0 0.234531 RAD 0.0078125 + txt184 +TEXDEF txt184 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0 0.25 RAD 0.03125 + txt184 +TEXDEF txt184 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0 0.25 APEX 0.859531 0 0.25 RAD 0.0078125 + txt184 +TEXDEF txt184 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.0154687 0.25 APEX 0.75 0.109531 0.25 RAD 0.0078125 + txt184 +TEXDEF txt184 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0 0.265469 APEX 0.75 0 0.359531 RAD 0.0078125 + txt184 +TEXDEF txt184 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0 0.375 RAD 0.03125 + txt184 +TEXDEF txt185 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0 0.375 APEX 0.859531 0 0.375 RAD 0.0078125 + txt185 +TEXDEF txt185 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.0154687 0.375 APEX 0.75 0.109531 0.375 RAD 0.0078125 + txt185 +TEXDEF txt185 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0 0.390469 APEX 0.75 0 0.484531 RAD 0.0078125 + txt185 +TEXDEF txt185 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0 0.5 RAD 0.03125 + txt185 +TEXDEF txt185 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0 0.5 APEX 0.859531 0 0.5 RAD 0.0078125 + txt185 +TEXDEF txt185 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.0154687 0.5 APEX 0.75 0.109531 0.5 RAD 0.0078125 + txt185 +TEXDEF txt185 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0 0.515469 APEX 0.75 0 0.609531 RAD 0.0078125 + txt185 +TEXDEF txt185 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0 0.625 RAD 0.03125 + txt185 +TEXDEF txt185 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0 0.625 APEX 0.859531 0 0.625 RAD 0.0078125 + txt185 +TEXDEF txt185 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.0154687 0.625 APEX 0.75 0.109531 0.625 RAD 0.0078125 + txt185 +TEXDEF txt186 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0 0.640469 APEX 0.75 0 0.734531 RAD 0.0078125 + txt186 +TEXDEF txt186 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0 0.75 RAD 0.03125 + txt186 +TEXDEF txt186 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0 0.75 APEX 0.859531 0 0.75 RAD 0.0078125 + txt186 +TEXDEF txt186 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.0154687 0.75 APEX 0.75 0.109531 0.75 RAD 0.0078125 + txt186 +TEXDEF txt186 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0 0.765469 APEX 0.75 0 0.859531 RAD 0.0078125 + txt186 +TEXDEF txt186 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0 0.875 RAD 0.03125 + txt186 +TEXDEF txt186 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0 0.875 APEX 0.859531 0 0.875 RAD 0.0078125 + txt186 +TEXDEF txt186 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.0154687 0.875 APEX 0.75 0.109531 0.875 RAD 0.0078125 + txt186 +TEXDEF txt186 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0 0.890469 APEX 0.75 0 0.984531 RAD 0.0078125 + txt186 +TEXDEF txt186 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0 1 RAD 0.03125 + txt186 +TEXDEF txt187 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0 1 APEX 0.859531 0 1 RAD 0.0078125 + txt187 +TEXDEF txt187 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.0154687 1 APEX 0.75 0.109531 1 RAD 0.0078125 + txt187 +TEXDEF txt187 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.125 0 RAD 0.03125 + txt187 +TEXDEF txt187 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.125 0 APEX 0.859531 0.125 0 RAD 0.0078125 + txt187 +TEXDEF txt187 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.140469 0 APEX 0.75 0.234531 0 RAD 0.0078125 + txt187 +TEXDEF txt187 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.125 0.0154687 APEX 0.75 0.125 0.109531 RAD 0.0078125 + txt187 +TEXDEF txt187 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.125 0.125 RAD 0.03125 + txt187 +TEXDEF txt187 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.125 0.125 APEX 0.859531 0.125 0.125 RAD 0.0078125 + txt187 +TEXDEF txt187 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.140469 0.125 APEX 0.75 0.234531 0.125 RAD 0.0078125 + txt187 +TEXDEF txt187 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.125 0.140469 APEX 0.75 0.125 0.234531 RAD 0.0078125 + txt187 +TEXDEF txt188 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.125 0.25 RAD 0.03125 + txt188 +TEXDEF txt188 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.125 0.25 APEX 0.859531 0.125 0.25 RAD 0.0078125 + txt188 +TEXDEF txt188 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.140469 0.25 APEX 0.75 0.234531 0.25 RAD 0.0078125 + txt188 +TEXDEF txt188 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.125 0.265469 APEX 0.75 0.125 0.359531 RAD 0.0078125 + txt188 +TEXDEF txt188 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.125 0.375 RAD 0.03125 + txt188 +TEXDEF txt188 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.125 0.375 APEX 0.859531 0.125 0.375 RAD 0.0078125 + txt188 +TEXDEF txt188 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.140469 0.375 APEX 0.75 0.234531 0.375 RAD 0.0078125 + txt188 +TEXDEF txt188 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.125 0.390469 APEX 0.75 0.125 0.484531 RAD 0.0078125 + txt188 +TEXDEF txt188 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.125 0.5 RAD 0.03125 + txt188 +TEXDEF txt188 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.125 0.5 APEX 0.859531 0.125 0.5 RAD 0.0078125 + txt188 +TEXDEF txt189 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.140469 0.5 APEX 0.75 0.234531 0.5 RAD 0.0078125 + txt189 +TEXDEF txt189 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.125 0.515469 APEX 0.75 0.125 0.609531 RAD 0.0078125 + txt189 +TEXDEF txt189 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.125 0.625 RAD 0.03125 + txt189 +TEXDEF txt189 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.125 0.625 APEX 0.859531 0.125 0.625 RAD 0.0078125 + txt189 +TEXDEF txt189 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.140469 0.625 APEX 0.75 0.234531 0.625 RAD 0.0078125 + txt189 +TEXDEF txt189 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.125 0.640469 APEX 0.75 0.125 0.734531 RAD 0.0078125 + txt189 +TEXDEF txt189 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.125 0.75 RAD 0.03125 + txt189 +TEXDEF txt189 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.125 0.75 APEX 0.859531 0.125 0.75 RAD 0.0078125 + txt189 +TEXDEF txt189 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.140469 0.75 APEX 0.75 0.234531 0.75 RAD 0.0078125 + txt189 +TEXDEF txt189 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.125 0.765469 APEX 0.75 0.125 0.859531 RAD 0.0078125 + txt189 +TEXDEF txt190 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.125 0.875 RAD 0.03125 + txt190 +TEXDEF txt190 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.125 0.875 APEX 0.859531 0.125 0.875 RAD 0.0078125 + txt190 +TEXDEF txt190 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.140469 0.875 APEX 0.75 0.234531 0.875 RAD 0.0078125 + txt190 +TEXDEF txt190 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.125 0.890469 APEX 0.75 0.125 0.984531 RAD 0.0078125 + txt190 +TEXDEF txt190 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.125 1 RAD 0.03125 + txt190 +TEXDEF txt190 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.125 1 APEX 0.859531 0.125 1 RAD 0.0078125 + txt190 +TEXDEF txt190 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.140469 1 APEX 0.75 0.234531 1 RAD 0.0078125 + txt190 +TEXDEF txt190 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.25 0 RAD 0.03125 + txt190 +TEXDEF txt190 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.25 0 APEX 0.859531 0.25 0 RAD 0.0078125 + txt190 +TEXDEF txt190 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.265469 0 APEX 0.75 0.359531 0 RAD 0.0078125 + txt190 +TEXDEF txt191 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.25 0.0154687 APEX 0.75 0.25 0.109531 RAD 0.0078125 + txt191 +TEXDEF txt191 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.25 0.125 RAD 0.03125 + txt191 +TEXDEF txt191 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.25 0.125 APEX 0.859531 0.25 0.125 RAD 0.0078125 + txt191 +TEXDEF txt191 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.265469 0.125 APEX 0.75 0.359531 0.125 RAD 0.0078125 + txt191 +TEXDEF txt191 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.25 0.140469 APEX 0.75 0.25 0.234531 RAD 0.0078125 + txt191 +TEXDEF txt191 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.25 0.25 RAD 0.03125 + txt191 +TEXDEF txt191 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.25 0.25 APEX 0.859531 0.25 0.25 RAD 0.0078125 + txt191 +TEXDEF txt191 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.265469 0.25 APEX 0.75 0.359531 0.25 RAD 0.0078125 + txt191 +TEXDEF txt191 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.25 0.265469 APEX 0.75 0.25 0.359531 RAD 0.0078125 + txt191 +TEXDEF txt191 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.25 0.375 RAD 0.03125 + txt191 +TEXDEF txt192 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.25 0.375 APEX 0.859531 0.25 0.375 RAD 0.0078125 + txt192 +TEXDEF txt192 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.265469 0.375 APEX 0.75 0.359531 0.375 RAD 0.0078125 + txt192 +TEXDEF txt192 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.25 0.390469 APEX 0.75 0.25 0.484531 RAD 0.0078125 + txt192 +TEXDEF txt192 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.25 0.5 RAD 0.03125 + txt192 +TEXDEF txt192 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.25 0.5 APEX 0.859531 0.25 0.5 RAD 0.0078125 + txt192 +TEXDEF txt192 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.265469 0.5 APEX 0.75 0.359531 0.5 RAD 0.0078125 + txt192 +TEXDEF txt192 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.25 0.515469 APEX 0.75 0.25 0.609531 RAD 0.0078125 + txt192 +TEXDEF txt192 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.25 0.625 RAD 0.03125 + txt192 +TEXDEF txt192 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.25 0.625 APEX 0.859531 0.25 0.625 RAD 0.0078125 + txt192 +TEXDEF txt192 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.265469 0.625 APEX 0.75 0.359531 0.625 RAD 0.0078125 + txt192 +TEXDEF txt193 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.25 0.640469 APEX 0.75 0.25 0.734531 RAD 0.0078125 + txt193 +TEXDEF txt193 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.25 0.75 RAD 0.03125 + txt193 +TEXDEF txt193 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.25 0.75 APEX 0.859531 0.25 0.75 RAD 0.0078125 + txt193 +TEXDEF txt193 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.265469 0.75 APEX 0.75 0.359531 0.75 RAD 0.0078125 + txt193 +TEXDEF txt193 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.25 0.765469 APEX 0.75 0.25 0.859531 RAD 0.0078125 + txt193 +TEXDEF txt193 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.25 0.875 RAD 0.03125 + txt193 +TEXDEF txt193 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.25 0.875 APEX 0.859531 0.25 0.875 RAD 0.0078125 + txt193 +TEXDEF txt193 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.265469 0.875 APEX 0.75 0.359531 0.875 RAD 0.0078125 + txt193 +TEXDEF txt193 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.25 0.890469 APEX 0.75 0.25 0.984531 RAD 0.0078125 + txt193 +TEXDEF txt193 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.25 1 RAD 0.03125 + txt193 +TEXDEF txt194 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.25 1 APEX 0.859531 0.25 1 RAD 0.0078125 + txt194 +TEXDEF txt194 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.265469 1 APEX 0.75 0.359531 1 RAD 0.0078125 + txt194 +TEXDEF txt194 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.375 0 RAD 0.03125 + txt194 +TEXDEF txt194 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.375 0 APEX 0.859531 0.375 0 RAD 0.0078125 + txt194 +TEXDEF txt194 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.390469 0 APEX 0.75 0.484531 0 RAD 0.0078125 + txt194 +TEXDEF txt194 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.375 0.0154687 APEX 0.75 0.375 0.109531 RAD 0.0078125 + txt194 +TEXDEF txt194 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.375 0.125 RAD 0.03125 + txt194 +TEXDEF txt194 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.375 0.125 APEX 0.859531 0.375 0.125 RAD 0.0078125 + txt194 +TEXDEF txt194 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.390469 0.125 APEX 0.75 0.484531 0.125 RAD 0.0078125 + txt194 +TEXDEF txt194 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.375 0.140469 APEX 0.75 0.375 0.234531 RAD 0.0078125 + txt194 +TEXDEF txt195 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.375 0.25 RAD 0.03125 + txt195 +TEXDEF txt195 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.375 0.25 APEX 0.859531 0.375 0.25 RAD 0.0078125 + txt195 +TEXDEF txt195 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.390469 0.25 APEX 0.75 0.484531 0.25 RAD 0.0078125 + txt195 +TEXDEF txt195 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.375 0.265469 APEX 0.75 0.375 0.359531 RAD 0.0078125 + txt195 +TEXDEF txt195 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.375 0.375 RAD 0.03125 + txt195 +TEXDEF txt195 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.375 0.375 APEX 0.859531 0.375 0.375 RAD 0.0078125 + txt195 +TEXDEF txt195 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.390469 0.375 APEX 0.75 0.484531 0.375 RAD 0.0078125 + txt195 +TEXDEF txt195 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.375 0.390469 APEX 0.75 0.375 0.484531 RAD 0.0078125 + txt195 +TEXDEF txt195 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.375 0.5 RAD 0.03125 + txt195 +TEXDEF txt195 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.375 0.5 APEX 0.859531 0.375 0.5 RAD 0.0078125 + txt195 +TEXDEF txt196 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.390469 0.5 APEX 0.75 0.484531 0.5 RAD 0.0078125 + txt196 +TEXDEF txt196 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.375 0.515469 APEX 0.75 0.375 0.609531 RAD 0.0078125 + txt196 +TEXDEF txt196 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.375 0.625 RAD 0.03125 + txt196 +TEXDEF txt196 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.375 0.625 APEX 0.859531 0.375 0.625 RAD 0.0078125 + txt196 +TEXDEF txt196 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.390469 0.625 APEX 0.75 0.484531 0.625 RAD 0.0078125 + txt196 +TEXDEF txt196 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.375 0.640469 APEX 0.75 0.375 0.734531 RAD 0.0078125 + txt196 +TEXDEF txt196 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.375 0.75 RAD 0.03125 + txt196 +TEXDEF txt196 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.375 0.75 APEX 0.859531 0.375 0.75 RAD 0.0078125 + txt196 +TEXDEF txt196 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.390469 0.75 APEX 0.75 0.484531 0.75 RAD 0.0078125 + txt196 +TEXDEF txt196 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.375 0.765469 APEX 0.75 0.375 0.859531 RAD 0.0078125 + txt196 +TEXDEF txt197 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.375 0.875 RAD 0.03125 + txt197 +TEXDEF txt197 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.375 0.875 APEX 0.859531 0.375 0.875 RAD 0.0078125 + txt197 +TEXDEF txt197 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.390469 0.875 APEX 0.75 0.484531 0.875 RAD 0.0078125 + txt197 +TEXDEF txt197 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.375 0.890469 APEX 0.75 0.375 0.984531 RAD 0.0078125 + txt197 +TEXDEF txt197 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.375 1 RAD 0.03125 + txt197 +TEXDEF txt197 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.375 1 APEX 0.859531 0.375 1 RAD 0.0078125 + txt197 +TEXDEF txt197 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.390469 1 APEX 0.75 0.484531 1 RAD 0.0078125 + txt197 +TEXDEF txt197 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.5 0 RAD 0.03125 + txt197 +TEXDEF txt197 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.5 0 APEX 0.859531 0.5 0 RAD 0.0078125 + txt197 +TEXDEF txt197 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.515469 0 APEX 0.75 0.609531 0 RAD 0.0078125 + txt197 +TEXDEF txt198 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.5 0.0154687 APEX 0.75 0.5 0.109531 RAD 0.0078125 + txt198 +TEXDEF txt198 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.5 0.125 RAD 0.03125 + txt198 +TEXDEF txt198 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.5 0.125 APEX 0.859531 0.5 0.125 RAD 0.0078125 + txt198 +TEXDEF txt198 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.515469 0.125 APEX 0.75 0.609531 0.125 RAD 0.0078125 + txt198 +TEXDEF txt198 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.5 0.140469 APEX 0.75 0.5 0.234531 RAD 0.0078125 + txt198 +TEXDEF txt198 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.5 0.25 RAD 0.03125 + txt198 +TEXDEF txt198 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.5 0.25 APEX 0.859531 0.5 0.25 RAD 0.0078125 + txt198 +TEXDEF txt198 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.515469 0.25 APEX 0.75 0.609531 0.25 RAD 0.0078125 + txt198 +TEXDEF txt198 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.5 0.265469 APEX 0.75 0.5 0.359531 RAD 0.0078125 + txt198 +TEXDEF txt198 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.5 0.375 RAD 0.03125 + txt198 +TEXDEF txt199 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.5 0.375 APEX 0.859531 0.5 0.375 RAD 0.0078125 + txt199 +TEXDEF txt199 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.515469 0.375 APEX 0.75 0.609531 0.375 RAD 0.0078125 + txt199 +TEXDEF txt199 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.5 0.390469 APEX 0.75 0.5 0.484531 RAD 0.0078125 + txt199 +TEXDEF txt199 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.5 0.5 RAD 0.03125 + txt199 +TEXDEF txt199 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.5 0.5 APEX 0.859531 0.5 0.5 RAD 0.0078125 + txt199 +TEXDEF txt199 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.515469 0.5 APEX 0.75 0.609531 0.5 RAD 0.0078125 + txt199 +TEXDEF txt199 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.5 0.515469 APEX 0.75 0.5 0.609531 RAD 0.0078125 + txt199 +TEXDEF txt199 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.5 0.625 RAD 0.03125 + txt199 +TEXDEF txt199 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.5 0.625 APEX 0.859531 0.5 0.625 RAD 0.0078125 + txt199 +TEXDEF txt199 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.515469 0.625 APEX 0.75 0.609531 0.625 RAD 0.0078125 + txt199 +TEXDEF txt200 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.5 0.640469 APEX 0.75 0.5 0.734531 RAD 0.0078125 + txt200 +TEXDEF txt200 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.5 0.75 RAD 0.03125 + txt200 +TEXDEF txt200 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.5 0.75 APEX 0.859531 0.5 0.75 RAD 0.0078125 + txt200 +TEXDEF txt200 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.515469 0.75 APEX 0.75 0.609531 0.75 RAD 0.0078125 + txt200 +TEXDEF txt200 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.5 0.765469 APEX 0.75 0.5 0.859531 RAD 0.0078125 + txt200 +TEXDEF txt200 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.5 0.875 RAD 0.03125 + txt200 +TEXDEF txt200 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.5 0.875 APEX 0.859531 0.5 0.875 RAD 0.0078125 + txt200 +TEXDEF txt200 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.515469 0.875 APEX 0.75 0.609531 0.875 RAD 0.0078125 + txt200 +TEXDEF txt200 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.5 0.890469 APEX 0.75 0.5 0.984531 RAD 0.0078125 + txt200 +TEXDEF txt200 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.5 1 RAD 0.03125 + txt200 +TEXDEF txt201 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.5 1 APEX 0.859531 0.5 1 RAD 0.0078125 + txt201 +TEXDEF txt201 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.515469 1 APEX 0.75 0.609531 1 RAD 0.0078125 + txt201 +TEXDEF txt201 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.625 0 RAD 0.03125 + txt201 +TEXDEF txt201 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.625 0 APEX 0.859531 0.625 0 RAD 0.0078125 + txt201 +TEXDEF txt201 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.640469 0 APEX 0.75 0.734531 0 RAD 0.0078125 + txt201 +TEXDEF txt201 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.625 0.0154687 APEX 0.75 0.625 0.109531 RAD 0.0078125 + txt201 +TEXDEF txt201 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.625 0.125 RAD 0.03125 + txt201 +TEXDEF txt201 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.625 0.125 APEX 0.859531 0.625 0.125 RAD 0.0078125 + txt201 +TEXDEF txt201 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.640469 0.125 APEX 0.75 0.734531 0.125 RAD 0.0078125 + txt201 +TEXDEF txt201 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.625 0.140469 APEX 0.75 0.625 0.234531 RAD 0.0078125 + txt201 +TEXDEF txt202 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.625 0.25 RAD 0.03125 + txt202 +TEXDEF txt202 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.625 0.25 APEX 0.859531 0.625 0.25 RAD 0.0078125 + txt202 +TEXDEF txt202 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.640469 0.25 APEX 0.75 0.734531 0.25 RAD 0.0078125 + txt202 +TEXDEF txt202 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.625 0.265469 APEX 0.75 0.625 0.359531 RAD 0.0078125 + txt202 +TEXDEF txt202 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.625 0.375 RAD 0.03125 + txt202 +TEXDEF txt202 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.625 0.375 APEX 0.859531 0.625 0.375 RAD 0.0078125 + txt202 +TEXDEF txt202 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.640469 0.375 APEX 0.75 0.734531 0.375 RAD 0.0078125 + txt202 +TEXDEF txt202 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.625 0.390469 APEX 0.75 0.625 0.484531 RAD 0.0078125 + txt202 +TEXDEF txt202 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.625 0.5 RAD 0.03125 + txt202 +TEXDEF txt202 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.625 0.5 APEX 0.859531 0.625 0.5 RAD 0.0078125 + txt202 +TEXDEF txt203 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.640469 0.5 APEX 0.75 0.734531 0.5 RAD 0.0078125 + txt203 +TEXDEF txt203 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.625 0.515469 APEX 0.75 0.625 0.609531 RAD 0.0078125 + txt203 +TEXDEF txt203 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.625 0.625 RAD 0.03125 + txt203 +TEXDEF txt203 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.625 0.625 APEX 0.859531 0.625 0.625 RAD 0.0078125 + txt203 +TEXDEF txt203 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.640469 0.625 APEX 0.75 0.734531 0.625 RAD 0.0078125 + txt203 +TEXDEF txt203 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.625 0.640469 APEX 0.75 0.625 0.734531 RAD 0.0078125 + txt203 +TEXDEF txt203 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.625 0.75 RAD 0.03125 + txt203 +TEXDEF txt203 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.625 0.75 APEX 0.859531 0.625 0.75 RAD 0.0078125 + txt203 +TEXDEF txt203 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.640469 0.75 APEX 0.75 0.734531 0.75 RAD 0.0078125 + txt203 +TEXDEF txt203 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.625 0.765469 APEX 0.75 0.625 0.859531 RAD 0.0078125 + txt203 +TEXDEF txt204 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.625 0.875 RAD 0.03125 + txt204 +TEXDEF txt204 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.625 0.875 APEX 0.859531 0.625 0.875 RAD 0.0078125 + txt204 +TEXDEF txt204 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.640469 0.875 APEX 0.75 0.734531 0.875 RAD 0.0078125 + txt204 +TEXDEF txt204 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.625 0.890469 APEX 0.75 0.625 0.984531 RAD 0.0078125 + txt204 +TEXDEF txt204 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.625 1 RAD 0.03125 + txt204 +TEXDEF txt204 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.625 1 APEX 0.859531 0.625 1 RAD 0.0078125 + txt204 +TEXDEF txt204 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.640469 1 APEX 0.75 0.734531 1 RAD 0.0078125 + txt204 +TEXDEF txt204 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.75 0 RAD 0.03125 + txt204 +TEXDEF txt204 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.75 0 APEX 0.859531 0.75 0 RAD 0.0078125 + txt204 +TEXDEF txt204 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.765469 0 APEX 0.75 0.859531 0 RAD 0.0078125 + txt204 +TEXDEF txt205 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.75 0.0154687 APEX 0.75 0.75 0.109531 RAD 0.0078125 + txt205 +TEXDEF txt205 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.75 0.125 RAD 0.03125 + txt205 +TEXDEF txt205 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.75 0.125 APEX 0.859531 0.75 0.125 RAD 0.0078125 + txt205 +TEXDEF txt205 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.765469 0.125 APEX 0.75 0.859531 0.125 RAD 0.0078125 + txt205 +TEXDEF txt205 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.75 0.140469 APEX 0.75 0.75 0.234531 RAD 0.0078125 + txt205 +TEXDEF txt205 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.75 0.25 RAD 0.03125 + txt205 +TEXDEF txt205 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.75 0.25 APEX 0.859531 0.75 0.25 RAD 0.0078125 + txt205 +TEXDEF txt205 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.765469 0.25 APEX 0.75 0.859531 0.25 RAD 0.0078125 + txt205 +TEXDEF txt205 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.75 0.265469 APEX 0.75 0.75 0.359531 RAD 0.0078125 + txt205 +TEXDEF txt205 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.75 0.375 RAD 0.03125 + txt205 +TEXDEF txt206 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.75 0.375 APEX 0.859531 0.75 0.375 RAD 0.0078125 + txt206 +TEXDEF txt206 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.765469 0.375 APEX 0.75 0.859531 0.375 RAD 0.0078125 + txt206 +TEXDEF txt206 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.75 0.390469 APEX 0.75 0.75 0.484531 RAD 0.0078125 + txt206 +TEXDEF txt206 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.75 0.5 RAD 0.03125 + txt206 +TEXDEF txt206 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.75 0.5 APEX 0.859531 0.75 0.5 RAD 0.0078125 + txt206 +TEXDEF txt206 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.765469 0.5 APEX 0.75 0.859531 0.5 RAD 0.0078125 + txt206 +TEXDEF txt206 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.75 0.515469 APEX 0.75 0.75 0.609531 RAD 0.0078125 + txt206 +TEXDEF txt206 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.75 0.625 RAD 0.03125 + txt206 +TEXDEF txt206 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.75 0.625 APEX 0.859531 0.75 0.625 RAD 0.0078125 + txt206 +TEXDEF txt206 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.765469 0.625 APEX 0.75 0.859531 0.625 RAD 0.0078125 + txt206 +TEXDEF txt207 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.75 0.640469 APEX 0.75 0.75 0.734531 RAD 0.0078125 + txt207 +TEXDEF txt207 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.75 0.75 RAD 0.03125 + txt207 +TEXDEF txt207 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.75 0.75 APEX 0.859531 0.75 0.75 RAD 0.0078125 + txt207 +TEXDEF txt207 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.765469 0.75 APEX 0.75 0.859531 0.75 RAD 0.0078125 + txt207 +TEXDEF txt207 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.75 0.765469 APEX 0.75 0.75 0.859531 RAD 0.0078125 + txt207 +TEXDEF txt207 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.75 0.875 RAD 0.03125 + txt207 +TEXDEF txt207 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.75 0.875 APEX 0.859531 0.75 0.875 RAD 0.0078125 + txt207 +TEXDEF txt207 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.765469 0.875 APEX 0.75 0.859531 0.875 RAD 0.0078125 + txt207 +TEXDEF txt207 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.75 0.890469 APEX 0.75 0.75 0.984531 RAD 0.0078125 + txt207 +TEXDEF txt207 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.75 1 RAD 0.03125 + txt207 +TEXDEF txt208 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.75 1 APEX 0.859531 0.75 1 RAD 0.0078125 + txt208 +TEXDEF txt208 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.765469 1 APEX 0.75 0.859531 1 RAD 0.0078125 + txt208 +TEXDEF txt208 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.875 0 RAD 0.03125 + txt208 +TEXDEF txt208 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.875 0 APEX 0.859531 0.875 0 RAD 0.0078125 + txt208 +TEXDEF txt208 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.890469 0 APEX 0.75 0.984531 0 RAD 0.0078125 + txt208 +TEXDEF txt208 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.875 0.0154687 APEX 0.75 0.875 0.109531 RAD 0.0078125 + txt208 +TEXDEF txt208 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.875 0.125 RAD 0.03125 + txt208 +TEXDEF txt208 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.875 0.125 APEX 0.859531 0.875 0.125 RAD 0.0078125 + txt208 +TEXDEF txt208 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.890469 0.125 APEX 0.75 0.984531 0.125 RAD 0.0078125 + txt208 +TEXDEF txt208 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.875 0.140469 APEX 0.75 0.875 0.234531 RAD 0.0078125 + txt208 +TEXDEF txt209 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.875 0.25 RAD 0.03125 + txt209 +TEXDEF txt209 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.875 0.25 APEX 0.859531 0.875 0.25 RAD 0.0078125 + txt209 +TEXDEF txt209 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.890469 0.25 APEX 0.75 0.984531 0.25 RAD 0.0078125 + txt209 +TEXDEF txt209 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.875 0.265469 APEX 0.75 0.875 0.359531 RAD 0.0078125 + txt209 +TEXDEF txt209 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.875 0.375 RAD 0.03125 + txt209 +TEXDEF txt209 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.875 0.375 APEX 0.859531 0.875 0.375 RAD 0.0078125 + txt209 +TEXDEF txt209 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.890469 0.375 APEX 0.75 0.984531 0.375 RAD 0.0078125 + txt209 +TEXDEF txt209 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.875 0.390469 APEX 0.75 0.875 0.484531 RAD 0.0078125 + txt209 +TEXDEF txt209 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.875 0.5 RAD 0.03125 + txt209 +TEXDEF txt209 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.875 0.5 APEX 0.859531 0.875 0.5 RAD 0.0078125 + txt209 +TEXDEF txt210 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.890469 0.5 APEX 0.75 0.984531 0.5 RAD 0.0078125 + txt210 +TEXDEF txt210 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.875 0.515469 APEX 0.75 0.875 0.609531 RAD 0.0078125 + txt210 +TEXDEF txt210 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.875 0.625 RAD 0.03125 + txt210 +TEXDEF txt210 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.875 0.625 APEX 0.859531 0.875 0.625 RAD 0.0078125 + txt210 +TEXDEF txt210 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.890469 0.625 APEX 0.75 0.984531 0.625 RAD 0.0078125 + txt210 +TEXDEF txt210 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.875 0.640469 APEX 0.75 0.875 0.734531 RAD 0.0078125 + txt210 +TEXDEF txt210 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.875 0.75 RAD 0.03125 + txt210 +TEXDEF txt210 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.875 0.75 APEX 0.859531 0.875 0.75 RAD 0.0078125 + txt210 +TEXDEF txt210 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.890469 0.75 APEX 0.75 0.984531 0.75 RAD 0.0078125 + txt210 +TEXDEF txt210 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.875 0.765469 APEX 0.75 0.875 0.859531 RAD 0.0078125 + txt210 +TEXDEF txt211 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.875 0.875 RAD 0.03125 + txt211 +TEXDEF txt211 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.875 0.875 APEX 0.859531 0.875 0.875 RAD 0.0078125 + txt211 +TEXDEF txt211 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.890469 0.875 APEX 0.75 0.984531 0.875 RAD 0.0078125 + txt211 +TEXDEF txt211 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.875 0.890469 APEX 0.75 0.875 0.984531 RAD 0.0078125 + txt211 +TEXDEF txt211 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 0.875 1 RAD 0.03125 + txt211 +TEXDEF txt211 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 0.875 1 APEX 0.859531 0.875 1 RAD 0.0078125 + txt211 +TEXDEF txt211 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 0.890469 1 APEX 0.75 0.984531 1 RAD 0.0078125 + txt211 +TEXDEF txt211 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 1 0 RAD 0.03125 + txt211 +TEXDEF txt211 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 1 0 APEX 0.859531 1 0 RAD 0.0078125 + txt211 +TEXDEF txt211 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 1 0.0154687 APEX 0.75 1 0.109531 RAD 0.0078125 + txt211 +TEXDEF txt212 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 1 0.125 RAD 0.03125 + txt212 +TEXDEF txt212 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 1 0.125 APEX 0.859531 1 0.125 RAD 0.0078125 + txt212 +TEXDEF txt212 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 1 0.140469 APEX 0.75 1 0.234531 RAD 0.0078125 + txt212 +TEXDEF txt212 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 1 0.25 RAD 0.03125 + txt212 +TEXDEF txt212 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 1 0.25 APEX 0.859531 1 0.25 RAD 0.0078125 + txt212 +TEXDEF txt212 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 1 0.265469 APEX 0.75 1 0.359531 RAD 0.0078125 + txt212 +TEXDEF txt212 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 1 0.375 RAD 0.03125 + txt212 +TEXDEF txt212 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 1 0.375 APEX 0.859531 1 0.375 RAD 0.0078125 + txt212 +TEXDEF txt212 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 1 0.390469 APEX 0.75 1 0.484531 RAD 0.0078125 + txt212 +TEXDEF txt212 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 1 0.5 RAD 0.03125 + txt212 +TEXDEF txt213 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 1 0.5 APEX 0.859531 1 0.5 RAD 0.0078125 + txt213 +TEXDEF txt213 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 1 0.515469 APEX 0.75 1 0.609531 RAD 0.0078125 + txt213 +TEXDEF txt213 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 1 0.625 RAD 0.03125 + txt213 +TEXDEF txt213 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 1 0.625 APEX 0.859531 1 0.625 RAD 0.0078125 + txt213 +TEXDEF txt213 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 1 0.640469 APEX 0.75 1 0.734531 RAD 0.0078125 + txt213 +TEXDEF txt213 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 1 0.75 RAD 0.03125 + txt213 +TEXDEF txt213 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 1 0.75 APEX 0.859531 1 0.75 RAD 0.0078125 + txt213 +TEXDEF txt213 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 1 0.765469 APEX 0.75 1 0.859531 RAD 0.0078125 + txt213 +TEXDEF txt213 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 1 0.875 RAD 0.03125 + txt213 +TEXDEF txt213 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 1 0.875 APEX 0.859531 1 0.875 RAD 0.0078125 + txt213 +TEXDEF txt214 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.75 1 0.890469 APEX 0.75 1 0.984531 RAD 0.0078125 + txt214 +TEXDEF txt214 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.75 1 1 RAD 0.03125 + txt214 +TEXDEF txt214 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.765469 1 1 APEX 0.859531 1 1 RAD 0.0078125 + txt214 +TEXDEF txt214 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0 0 RAD 0.03125 + txt214 +TEXDEF txt214 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0 0 APEX 0.984531 0 0 RAD 0.0078125 + txt214 +TEXDEF txt214 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.0154687 0 APEX 0.875 0.109531 0 RAD 0.0078125 + txt214 +TEXDEF txt214 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0 0.0154687 APEX 0.875 0 0.109531 RAD 0.0078125 + txt214 +TEXDEF txt214 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0 0.125 RAD 0.03125 + txt214 +TEXDEF txt214 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0 0.125 APEX 0.984531 0 0.125 RAD 0.0078125 + txt214 +TEXDEF txt214 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.0154687 0.125 APEX 0.875 0.109531 0.125 RAD 0.0078125 + txt214 +TEXDEF txt215 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0 0.140469 APEX 0.875 0 0.234531 RAD 0.0078125 + txt215 +TEXDEF txt215 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0 0.25 RAD 0.03125 + txt215 +TEXDEF txt215 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0 0.25 APEX 0.984531 0 0.25 RAD 0.0078125 + txt215 +TEXDEF txt215 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.0154687 0.25 APEX 0.875 0.109531 0.25 RAD 0.0078125 + txt215 +TEXDEF txt215 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0 0.265469 APEX 0.875 0 0.359531 RAD 0.0078125 + txt215 +TEXDEF txt215 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0 0.375 RAD 0.03125 + txt215 +TEXDEF txt215 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0 0.375 APEX 0.984531 0 0.375 RAD 0.0078125 + txt215 +TEXDEF txt215 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.0154687 0.375 APEX 0.875 0.109531 0.375 RAD 0.0078125 + txt215 +TEXDEF txt215 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0 0.390469 APEX 0.875 0 0.484531 RAD 0.0078125 + txt215 +TEXDEF txt215 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0 0.5 RAD 0.03125 + txt215 +TEXDEF txt216 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0 0.5 APEX 0.984531 0 0.5 RAD 0.0078125 + txt216 +TEXDEF txt216 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.0154687 0.5 APEX 0.875 0.109531 0.5 RAD 0.0078125 + txt216 +TEXDEF txt216 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0 0.515469 APEX 0.875 0 0.609531 RAD 0.0078125 + txt216 +TEXDEF txt216 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0 0.625 RAD 0.03125 + txt216 +TEXDEF txt216 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0 0.625 APEX 0.984531 0 0.625 RAD 0.0078125 + txt216 +TEXDEF txt216 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.0154687 0.625 APEX 0.875 0.109531 0.625 RAD 0.0078125 + txt216 +TEXDEF txt216 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0 0.640469 APEX 0.875 0 0.734531 RAD 0.0078125 + txt216 +TEXDEF txt216 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0 0.75 RAD 0.03125 + txt216 +TEXDEF txt216 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0 0.75 APEX 0.984531 0 0.75 RAD 0.0078125 + txt216 +TEXDEF txt216 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.0154687 0.75 APEX 0.875 0.109531 0.75 RAD 0.0078125 + txt216 +TEXDEF txt217 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0 0.765469 APEX 0.875 0 0.859531 RAD 0.0078125 + txt217 +TEXDEF txt217 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0 0.875 RAD 0.03125 + txt217 +TEXDEF txt217 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0 0.875 APEX 0.984531 0 0.875 RAD 0.0078125 + txt217 +TEXDEF txt217 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.0154687 0.875 APEX 0.875 0.109531 0.875 RAD 0.0078125 + txt217 +TEXDEF txt217 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0 0.890469 APEX 0.875 0 0.984531 RAD 0.0078125 + txt217 +TEXDEF txt217 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0 1 RAD 0.03125 + txt217 +TEXDEF txt217 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0 1 APEX 0.984531 0 1 RAD 0.0078125 + txt217 +TEXDEF txt217 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.0154687 1 APEX 0.875 0.109531 1 RAD 0.0078125 + txt217 +TEXDEF txt217 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.125 0 RAD 0.03125 + txt217 +TEXDEF txt217 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.125 0 APEX 0.984531 0.125 0 RAD 0.0078125 + txt217 +TEXDEF txt218 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.140469 0 APEX 0.875 0.234531 0 RAD 0.0078125 + txt218 +TEXDEF txt218 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.125 0.0154687 APEX 0.875 0.125 0.109531 RAD 0.0078125 + txt218 +TEXDEF txt218 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.125 0.125 RAD 0.03125 + txt218 +TEXDEF txt218 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.125 0.125 APEX 0.984531 0.125 0.125 RAD 0.0078125 + txt218 +TEXDEF txt218 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.140469 0.125 APEX 0.875 0.234531 0.125 RAD 0.0078125 + txt218 +TEXDEF txt218 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.125 0.140469 APEX 0.875 0.125 0.234531 RAD 0.0078125 + txt218 +TEXDEF txt218 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.125 0.25 RAD 0.03125 + txt218 +TEXDEF txt218 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.125 0.25 APEX 0.984531 0.125 0.25 RAD 0.0078125 + txt218 +TEXDEF txt218 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.140469 0.25 APEX 0.875 0.234531 0.25 RAD 0.0078125 + txt218 +TEXDEF txt218 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.125 0.265469 APEX 0.875 0.125 0.359531 RAD 0.0078125 + txt218 +TEXDEF txt219 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.125 0.375 RAD 0.03125 + txt219 +TEXDEF txt219 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.125 0.375 APEX 0.984531 0.125 0.375 RAD 0.0078125 + txt219 +TEXDEF txt219 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.140469 0.375 APEX 0.875 0.234531 0.375 RAD 0.0078125 + txt219 +TEXDEF txt219 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.125 0.390469 APEX 0.875 0.125 0.484531 RAD 0.0078125 + txt219 +TEXDEF txt219 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.125 0.5 RAD 0.03125 + txt219 +TEXDEF txt219 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.125 0.5 APEX 0.984531 0.125 0.5 RAD 0.0078125 + txt219 +TEXDEF txt219 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.140469 0.5 APEX 0.875 0.234531 0.5 RAD 0.0078125 + txt219 +TEXDEF txt219 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.125 0.515469 APEX 0.875 0.125 0.609531 RAD 0.0078125 + txt219 +TEXDEF txt219 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.125 0.625 RAD 0.03125 + txt219 +TEXDEF txt219 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.125 0.625 APEX 0.984531 0.125 0.625 RAD 0.0078125 + txt219 +TEXDEF txt220 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.140469 0.625 APEX 0.875 0.234531 0.625 RAD 0.0078125 + txt220 +TEXDEF txt220 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.125 0.640469 APEX 0.875 0.125 0.734531 RAD 0.0078125 + txt220 +TEXDEF txt220 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.125 0.75 RAD 0.03125 + txt220 +TEXDEF txt220 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.125 0.75 APEX 0.984531 0.125 0.75 RAD 0.0078125 + txt220 +TEXDEF txt220 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.140469 0.75 APEX 0.875 0.234531 0.75 RAD 0.0078125 + txt220 +TEXDEF txt220 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.125 0.765469 APEX 0.875 0.125 0.859531 RAD 0.0078125 + txt220 +TEXDEF txt220 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.125 0.875 RAD 0.03125 + txt220 +TEXDEF txt220 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.125 0.875 APEX 0.984531 0.125 0.875 RAD 0.0078125 + txt220 +TEXDEF txt220 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.140469 0.875 APEX 0.875 0.234531 0.875 RAD 0.0078125 + txt220 +TEXDEF txt220 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.125 0.890469 APEX 0.875 0.125 0.984531 RAD 0.0078125 + txt220 +TEXDEF txt221 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.125 1 RAD 0.03125 + txt221 +TEXDEF txt221 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.125 1 APEX 0.984531 0.125 1 RAD 0.0078125 + txt221 +TEXDEF txt221 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.140469 1 APEX 0.875 0.234531 1 RAD 0.0078125 + txt221 +TEXDEF txt221 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.25 0 RAD 0.03125 + txt221 +TEXDEF txt221 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.25 0 APEX 0.984531 0.25 0 RAD 0.0078125 + txt221 +TEXDEF txt221 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.265469 0 APEX 0.875 0.359531 0 RAD 0.0078125 + txt221 +TEXDEF txt221 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.25 0.0154687 APEX 0.875 0.25 0.109531 RAD 0.0078125 + txt221 +TEXDEF txt221 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.25 0.125 RAD 0.03125 + txt221 +TEXDEF txt221 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.25 0.125 APEX 0.984531 0.25 0.125 RAD 0.0078125 + txt221 +TEXDEF txt221 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.265469 0.125 APEX 0.875 0.359531 0.125 RAD 0.0078125 + txt221 +TEXDEF txt222 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.25 0.140469 APEX 0.875 0.25 0.234531 RAD 0.0078125 + txt222 +TEXDEF txt222 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.25 0.25 RAD 0.03125 + txt222 +TEXDEF txt222 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.25 0.25 APEX 0.984531 0.25 0.25 RAD 0.0078125 + txt222 +TEXDEF txt222 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.265469 0.25 APEX 0.875 0.359531 0.25 RAD 0.0078125 + txt222 +TEXDEF txt222 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.25 0.265469 APEX 0.875 0.25 0.359531 RAD 0.0078125 + txt222 +TEXDEF txt222 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.25 0.375 RAD 0.03125 + txt222 +TEXDEF txt222 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.25 0.375 APEX 0.984531 0.25 0.375 RAD 0.0078125 + txt222 +TEXDEF txt222 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.265469 0.375 APEX 0.875 0.359531 0.375 RAD 0.0078125 + txt222 +TEXDEF txt222 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.25 0.390469 APEX 0.875 0.25 0.484531 RAD 0.0078125 + txt222 +TEXDEF txt222 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.25 0.5 RAD 0.03125 + txt222 +TEXDEF txt223 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.25 0.5 APEX 0.984531 0.25 0.5 RAD 0.0078125 + txt223 +TEXDEF txt223 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.265469 0.5 APEX 0.875 0.359531 0.5 RAD 0.0078125 + txt223 +TEXDEF txt223 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.25 0.515469 APEX 0.875 0.25 0.609531 RAD 0.0078125 + txt223 +TEXDEF txt223 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.25 0.625 RAD 0.03125 + txt223 +TEXDEF txt223 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.25 0.625 APEX 0.984531 0.25 0.625 RAD 0.0078125 + txt223 +TEXDEF txt223 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.265469 0.625 APEX 0.875 0.359531 0.625 RAD 0.0078125 + txt223 +TEXDEF txt223 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.25 0.640469 APEX 0.875 0.25 0.734531 RAD 0.0078125 + txt223 +TEXDEF txt223 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.25 0.75 RAD 0.03125 + txt223 +TEXDEF txt223 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.25 0.75 APEX 0.984531 0.25 0.75 RAD 0.0078125 + txt223 +TEXDEF txt223 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.265469 0.75 APEX 0.875 0.359531 0.75 RAD 0.0078125 + txt223 +TEXDEF txt224 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.25 0.765469 APEX 0.875 0.25 0.859531 RAD 0.0078125 + txt224 +TEXDEF txt224 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.25 0.875 RAD 0.03125 + txt224 +TEXDEF txt224 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.25 0.875 APEX 0.984531 0.25 0.875 RAD 0.0078125 + txt224 +TEXDEF txt224 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.265469 0.875 APEX 0.875 0.359531 0.875 RAD 0.0078125 + txt224 +TEXDEF txt224 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.25 0.890469 APEX 0.875 0.25 0.984531 RAD 0.0078125 + txt224 +TEXDEF txt224 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.25 1 RAD 0.03125 + txt224 +TEXDEF txt224 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.25 1 APEX 0.984531 0.25 1 RAD 0.0078125 + txt224 +TEXDEF txt224 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.265469 1 APEX 0.875 0.359531 1 RAD 0.0078125 + txt224 +TEXDEF txt224 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.375 0 RAD 0.03125 + txt224 +TEXDEF txt224 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.375 0 APEX 0.984531 0.375 0 RAD 0.0078125 + txt224 +TEXDEF txt225 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.390469 0 APEX 0.875 0.484531 0 RAD 0.0078125 + txt225 +TEXDEF txt225 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.375 0.0154687 APEX 0.875 0.375 0.109531 RAD 0.0078125 + txt225 +TEXDEF txt225 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.375 0.125 RAD 0.03125 + txt225 +TEXDEF txt225 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.375 0.125 APEX 0.984531 0.375 0.125 RAD 0.0078125 + txt225 +TEXDEF txt225 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.390469 0.125 APEX 0.875 0.484531 0.125 RAD 0.0078125 + txt225 +TEXDEF txt225 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.375 0.140469 APEX 0.875 0.375 0.234531 RAD 0.0078125 + txt225 +TEXDEF txt225 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.375 0.25 RAD 0.03125 + txt225 +TEXDEF txt225 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.375 0.25 APEX 0.984531 0.375 0.25 RAD 0.0078125 + txt225 +TEXDEF txt225 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.390469 0.25 APEX 0.875 0.484531 0.25 RAD 0.0078125 + txt225 +TEXDEF txt225 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.375 0.265469 APEX 0.875 0.375 0.359531 RAD 0.0078125 + txt225 +TEXDEF txt226 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.375 0.375 RAD 0.03125 + txt226 +TEXDEF txt226 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.375 0.375 APEX 0.984531 0.375 0.375 RAD 0.0078125 + txt226 +TEXDEF txt226 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.390469 0.375 APEX 0.875 0.484531 0.375 RAD 0.0078125 + txt226 +TEXDEF txt226 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.375 0.390469 APEX 0.875 0.375 0.484531 RAD 0.0078125 + txt226 +TEXDEF txt226 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.375 0.5 RAD 0.03125 + txt226 +TEXDEF txt226 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.375 0.5 APEX 0.984531 0.375 0.5 RAD 0.0078125 + txt226 +TEXDEF txt226 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.390469 0.5 APEX 0.875 0.484531 0.5 RAD 0.0078125 + txt226 +TEXDEF txt226 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.375 0.515469 APEX 0.875 0.375 0.609531 RAD 0.0078125 + txt226 +TEXDEF txt226 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.375 0.625 RAD 0.03125 + txt226 +TEXDEF txt226 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.375 0.625 APEX 0.984531 0.375 0.625 RAD 0.0078125 + txt226 +TEXDEF txt227 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.390469 0.625 APEX 0.875 0.484531 0.625 RAD 0.0078125 + txt227 +TEXDEF txt227 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.375 0.640469 APEX 0.875 0.375 0.734531 RAD 0.0078125 + txt227 +TEXDEF txt227 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.375 0.75 RAD 0.03125 + txt227 +TEXDEF txt227 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.375 0.75 APEX 0.984531 0.375 0.75 RAD 0.0078125 + txt227 +TEXDEF txt227 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.390469 0.75 APEX 0.875 0.484531 0.75 RAD 0.0078125 + txt227 +TEXDEF txt227 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.375 0.765469 APEX 0.875 0.375 0.859531 RAD 0.0078125 + txt227 +TEXDEF txt227 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.375 0.875 RAD 0.03125 + txt227 +TEXDEF txt227 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.375 0.875 APEX 0.984531 0.375 0.875 RAD 0.0078125 + txt227 +TEXDEF txt227 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.390469 0.875 APEX 0.875 0.484531 0.875 RAD 0.0078125 + txt227 +TEXDEF txt227 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.375 0.890469 APEX 0.875 0.375 0.984531 RAD 0.0078125 + txt227 +TEXDEF txt228 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.375 1 RAD 0.03125 + txt228 +TEXDEF txt228 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.375 1 APEX 0.984531 0.375 1 RAD 0.0078125 + txt228 +TEXDEF txt228 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.390469 1 APEX 0.875 0.484531 1 RAD 0.0078125 + txt228 +TEXDEF txt228 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.5 0 RAD 0.03125 + txt228 +TEXDEF txt228 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.5 0 APEX 0.984531 0.5 0 RAD 0.0078125 + txt228 +TEXDEF txt228 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.515469 0 APEX 0.875 0.609531 0 RAD 0.0078125 + txt228 +TEXDEF txt228 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.5 0.0154687 APEX 0.875 0.5 0.109531 RAD 0.0078125 + txt228 +TEXDEF txt228 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.5 0.125 RAD 0.03125 + txt228 +TEXDEF txt228 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.5 0.125 APEX 0.984531 0.5 0.125 RAD 0.0078125 + txt228 +TEXDEF txt228 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.515469 0.125 APEX 0.875 0.609531 0.125 RAD 0.0078125 + txt228 +TEXDEF txt229 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.5 0.140469 APEX 0.875 0.5 0.234531 RAD 0.0078125 + txt229 +TEXDEF txt229 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.5 0.25 RAD 0.03125 + txt229 +TEXDEF txt229 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.5 0.25 APEX 0.984531 0.5 0.25 RAD 0.0078125 + txt229 +TEXDEF txt229 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.515469 0.25 APEX 0.875 0.609531 0.25 RAD 0.0078125 + txt229 +TEXDEF txt229 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.5 0.265469 APEX 0.875 0.5 0.359531 RAD 0.0078125 + txt229 +TEXDEF txt229 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.5 0.375 RAD 0.03125 + txt229 +TEXDEF txt229 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.5 0.375 APEX 0.984531 0.5 0.375 RAD 0.0078125 + txt229 +TEXDEF txt229 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.515469 0.375 APEX 0.875 0.609531 0.375 RAD 0.0078125 + txt229 +TEXDEF txt229 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.5 0.390469 APEX 0.875 0.5 0.484531 RAD 0.0078125 + txt229 +TEXDEF txt229 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.5 0.5 RAD 0.03125 + txt229 +TEXDEF txt230 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.5 0.5 APEX 0.984531 0.5 0.5 RAD 0.0078125 + txt230 +TEXDEF txt230 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.515469 0.5 APEX 0.875 0.609531 0.5 RAD 0.0078125 + txt230 +TEXDEF txt230 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.5 0.515469 APEX 0.875 0.5 0.609531 RAD 0.0078125 + txt230 +TEXDEF txt230 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.5 0.625 RAD 0.03125 + txt230 +TEXDEF txt230 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.5 0.625 APEX 0.984531 0.5 0.625 RAD 0.0078125 + txt230 +TEXDEF txt230 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.515469 0.625 APEX 0.875 0.609531 0.625 RAD 0.0078125 + txt230 +TEXDEF txt230 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.5 0.640469 APEX 0.875 0.5 0.734531 RAD 0.0078125 + txt230 +TEXDEF txt230 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.5 0.75 RAD 0.03125 + txt230 +TEXDEF txt230 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.5 0.75 APEX 0.984531 0.5 0.75 RAD 0.0078125 + txt230 +TEXDEF txt230 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.515469 0.75 APEX 0.875 0.609531 0.75 RAD 0.0078125 + txt230 +TEXDEF txt231 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.5 0.765469 APEX 0.875 0.5 0.859531 RAD 0.0078125 + txt231 +TEXDEF txt231 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.5 0.875 RAD 0.03125 + txt231 +TEXDEF txt231 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.5 0.875 APEX 0.984531 0.5 0.875 RAD 0.0078125 + txt231 +TEXDEF txt231 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.515469 0.875 APEX 0.875 0.609531 0.875 RAD 0.0078125 + txt231 +TEXDEF txt231 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.5 0.890469 APEX 0.875 0.5 0.984531 RAD 0.0078125 + txt231 +TEXDEF txt231 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.5 1 RAD 0.03125 + txt231 +TEXDEF txt231 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.5 1 APEX 0.984531 0.5 1 RAD 0.0078125 + txt231 +TEXDEF txt231 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.515469 1 APEX 0.875 0.609531 1 RAD 0.0078125 + txt231 +TEXDEF txt231 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.625 0 RAD 0.03125 + txt231 +TEXDEF txt231 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.625 0 APEX 0.984531 0.625 0 RAD 0.0078125 + txt231 +TEXDEF txt232 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.640469 0 APEX 0.875 0.734531 0 RAD 0.0078125 + txt232 +TEXDEF txt232 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.625 0.0154687 APEX 0.875 0.625 0.109531 RAD 0.0078125 + txt232 +TEXDEF txt232 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.625 0.125 RAD 0.03125 + txt232 +TEXDEF txt232 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.625 0.125 APEX 0.984531 0.625 0.125 RAD 0.0078125 + txt232 +TEXDEF txt232 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.640469 0.125 APEX 0.875 0.734531 0.125 RAD 0.0078125 + txt232 +TEXDEF txt232 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.625 0.140469 APEX 0.875 0.625 0.234531 RAD 0.0078125 + txt232 +TEXDEF txt232 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.625 0.25 RAD 0.03125 + txt232 +TEXDEF txt232 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.625 0.25 APEX 0.984531 0.625 0.25 RAD 0.0078125 + txt232 +TEXDEF txt232 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.640469 0.25 APEX 0.875 0.734531 0.25 RAD 0.0078125 + txt232 +TEXDEF txt232 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.625 0.265469 APEX 0.875 0.625 0.359531 RAD 0.0078125 + txt232 +TEXDEF txt233 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.625 0.375 RAD 0.03125 + txt233 +TEXDEF txt233 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.625 0.375 APEX 0.984531 0.625 0.375 RAD 0.0078125 + txt233 +TEXDEF txt233 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.640469 0.375 APEX 0.875 0.734531 0.375 RAD 0.0078125 + txt233 +TEXDEF txt233 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.625 0.390469 APEX 0.875 0.625 0.484531 RAD 0.0078125 + txt233 +TEXDEF txt233 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.625 0.5 RAD 0.03125 + txt233 +TEXDEF txt233 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.625 0.5 APEX 0.984531 0.625 0.5 RAD 0.0078125 + txt233 +TEXDEF txt233 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.640469 0.5 APEX 0.875 0.734531 0.5 RAD 0.0078125 + txt233 +TEXDEF txt233 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.625 0.515469 APEX 0.875 0.625 0.609531 RAD 0.0078125 + txt233 +TEXDEF txt233 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.625 0.625 RAD 0.03125 + txt233 +TEXDEF txt233 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.625 0.625 APEX 0.984531 0.625 0.625 RAD 0.0078125 + txt233 +TEXDEF txt234 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.640469 0.625 APEX 0.875 0.734531 0.625 RAD 0.0078125 + txt234 +TEXDEF txt234 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.625 0.640469 APEX 0.875 0.625 0.734531 RAD 0.0078125 + txt234 +TEXDEF txt234 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.625 0.75 RAD 0.03125 + txt234 +TEXDEF txt234 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.625 0.75 APEX 0.984531 0.625 0.75 RAD 0.0078125 + txt234 +TEXDEF txt234 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.640469 0.75 APEX 0.875 0.734531 0.75 RAD 0.0078125 + txt234 +TEXDEF txt234 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.625 0.765469 APEX 0.875 0.625 0.859531 RAD 0.0078125 + txt234 +TEXDEF txt234 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.625 0.875 RAD 0.03125 + txt234 +TEXDEF txt234 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.625 0.875 APEX 0.984531 0.625 0.875 RAD 0.0078125 + txt234 +TEXDEF txt234 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.640469 0.875 APEX 0.875 0.734531 0.875 RAD 0.0078125 + txt234 +TEXDEF txt234 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.625 0.890469 APEX 0.875 0.625 0.984531 RAD 0.0078125 + txt234 +TEXDEF txt235 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.625 1 RAD 0.03125 + txt235 +TEXDEF txt235 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.625 1 APEX 0.984531 0.625 1 RAD 0.0078125 + txt235 +TEXDEF txt235 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.640469 1 APEX 0.875 0.734531 1 RAD 0.0078125 + txt235 +TEXDEF txt235 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.75 0 RAD 0.03125 + txt235 +TEXDEF txt235 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.75 0 APEX 0.984531 0.75 0 RAD 0.0078125 + txt235 +TEXDEF txt235 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.765469 0 APEX 0.875 0.859531 0 RAD 0.0078125 + txt235 +TEXDEF txt235 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.75 0.0154687 APEX 0.875 0.75 0.109531 RAD 0.0078125 + txt235 +TEXDEF txt235 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.75 0.125 RAD 0.03125 + txt235 +TEXDEF txt235 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.75 0.125 APEX 0.984531 0.75 0.125 RAD 0.0078125 + txt235 +TEXDEF txt235 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.765469 0.125 APEX 0.875 0.859531 0.125 RAD 0.0078125 + txt235 +TEXDEF txt236 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.75 0.140469 APEX 0.875 0.75 0.234531 RAD 0.0078125 + txt236 +TEXDEF txt236 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.75 0.25 RAD 0.03125 + txt236 +TEXDEF txt236 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.75 0.25 APEX 0.984531 0.75 0.25 RAD 0.0078125 + txt236 +TEXDEF txt236 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.765469 0.25 APEX 0.875 0.859531 0.25 RAD 0.0078125 + txt236 +TEXDEF txt236 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.75 0.265469 APEX 0.875 0.75 0.359531 RAD 0.0078125 + txt236 +TEXDEF txt236 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.75 0.375 RAD 0.03125 + txt236 +TEXDEF txt236 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.75 0.375 APEX 0.984531 0.75 0.375 RAD 0.0078125 + txt236 +TEXDEF txt236 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.765469 0.375 APEX 0.875 0.859531 0.375 RAD 0.0078125 + txt236 +TEXDEF txt236 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.75 0.390469 APEX 0.875 0.75 0.484531 RAD 0.0078125 + txt236 +TEXDEF txt236 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.75 0.5 RAD 0.03125 + txt236 +TEXDEF txt237 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.75 0.5 APEX 0.984531 0.75 0.5 RAD 0.0078125 + txt237 +TEXDEF txt237 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.765469 0.5 APEX 0.875 0.859531 0.5 RAD 0.0078125 + txt237 +TEXDEF txt237 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.75 0.515469 APEX 0.875 0.75 0.609531 RAD 0.0078125 + txt237 +TEXDEF txt237 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.75 0.625 RAD 0.03125 + txt237 +TEXDEF txt237 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.75 0.625 APEX 0.984531 0.75 0.625 RAD 0.0078125 + txt237 +TEXDEF txt237 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.765469 0.625 APEX 0.875 0.859531 0.625 RAD 0.0078125 + txt237 +TEXDEF txt237 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.75 0.640469 APEX 0.875 0.75 0.734531 RAD 0.0078125 + txt237 +TEXDEF txt237 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.75 0.75 RAD 0.03125 + txt237 +TEXDEF txt237 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.75 0.75 APEX 0.984531 0.75 0.75 RAD 0.0078125 + txt237 +TEXDEF txt237 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.765469 0.75 APEX 0.875 0.859531 0.75 RAD 0.0078125 + txt237 +TEXDEF txt238 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.75 0.765469 APEX 0.875 0.75 0.859531 RAD 0.0078125 + txt238 +TEXDEF txt238 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.75 0.875 RAD 0.03125 + txt238 +TEXDEF txt238 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.75 0.875 APEX 0.984531 0.75 0.875 RAD 0.0078125 + txt238 +TEXDEF txt238 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.765469 0.875 APEX 0.875 0.859531 0.875 RAD 0.0078125 + txt238 +TEXDEF txt238 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.75 0.890469 APEX 0.875 0.75 0.984531 RAD 0.0078125 + txt238 +TEXDEF txt238 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.75 1 RAD 0.03125 + txt238 +TEXDEF txt238 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.75 1 APEX 0.984531 0.75 1 RAD 0.0078125 + txt238 +TEXDEF txt238 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.765469 1 APEX 0.875 0.859531 1 RAD 0.0078125 + txt238 +TEXDEF txt238 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.875 0 RAD 0.03125 + txt238 +TEXDEF txt238 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.875 0 APEX 0.984531 0.875 0 RAD 0.0078125 + txt238 +TEXDEF txt239 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.890469 0 APEX 0.875 0.984531 0 RAD 0.0078125 + txt239 +TEXDEF txt239 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.875 0.0154687 APEX 0.875 0.875 0.109531 RAD 0.0078125 + txt239 +TEXDEF txt239 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.875 0.125 RAD 0.03125 + txt239 +TEXDEF txt239 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.875 0.125 APEX 0.984531 0.875 0.125 RAD 0.0078125 + txt239 +TEXDEF txt239 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.890469 0.125 APEX 0.875 0.984531 0.125 RAD 0.0078125 + txt239 +TEXDEF txt239 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.875 0.140469 APEX 0.875 0.875 0.234531 RAD 0.0078125 + txt239 +TEXDEF txt239 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.875 0.25 RAD 0.03125 + txt239 +TEXDEF txt239 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.875 0.25 APEX 0.984531 0.875 0.25 RAD 0.0078125 + txt239 +TEXDEF txt239 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.890469 0.25 APEX 0.875 0.984531 0.25 RAD 0.0078125 + txt239 +TEXDEF txt239 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.875 0.265469 APEX 0.875 0.875 0.359531 RAD 0.0078125 + txt239 +TEXDEF txt240 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.875 0.375 RAD 0.03125 + txt240 +TEXDEF txt240 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.875 0.375 APEX 0.984531 0.875 0.375 RAD 0.0078125 + txt240 +TEXDEF txt240 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.890469 0.375 APEX 0.875 0.984531 0.375 RAD 0.0078125 + txt240 +TEXDEF txt240 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.875 0.390469 APEX 0.875 0.875 0.484531 RAD 0.0078125 + txt240 +TEXDEF txt240 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.875 0.5 RAD 0.03125 + txt240 +TEXDEF txt240 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.875 0.5 APEX 0.984531 0.875 0.5 RAD 0.0078125 + txt240 +TEXDEF txt240 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.890469 0.5 APEX 0.875 0.984531 0.5 RAD 0.0078125 + txt240 +TEXDEF txt240 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.875 0.515469 APEX 0.875 0.875 0.609531 RAD 0.0078125 + txt240 +TEXDEF txt240 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.875 0.625 RAD 0.03125 + txt240 +TEXDEF txt240 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.875 0.625 APEX 0.984531 0.875 0.625 RAD 0.0078125 + txt240 +TEXDEF txt241 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.890469 0.625 APEX 0.875 0.984531 0.625 RAD 0.0078125 + txt241 +TEXDEF txt241 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.875 0.640469 APEX 0.875 0.875 0.734531 RAD 0.0078125 + txt241 +TEXDEF txt241 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.875 0.75 RAD 0.03125 + txt241 +TEXDEF txt241 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.875 0.75 APEX 0.984531 0.875 0.75 RAD 0.0078125 + txt241 +TEXDEF txt241 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.890469 0.75 APEX 0.875 0.984531 0.75 RAD 0.0078125 + txt241 +TEXDEF txt241 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.875 0.765469 APEX 0.875 0.875 0.859531 RAD 0.0078125 + txt241 +TEXDEF txt241 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.875 0.875 RAD 0.03125 + txt241 +TEXDEF txt241 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.875 0.875 APEX 0.984531 0.875 0.875 RAD 0.0078125 + txt241 +TEXDEF txt241 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.890469 0.875 APEX 0.875 0.984531 0.875 RAD 0.0078125 + txt241 +TEXDEF txt241 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.875 0.890469 APEX 0.875 0.875 0.984531 RAD 0.0078125 + txt241 +TEXDEF txt242 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 0.875 1 RAD 0.03125 + txt242 +TEXDEF txt242 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 0.875 1 APEX 0.984531 0.875 1 RAD 0.0078125 + txt242 +TEXDEF txt242 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 0.890469 1 APEX 0.875 0.984531 1 RAD 0.0078125 + txt242 +TEXDEF txt242 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 1 0 RAD 0.03125 + txt242 +TEXDEF txt242 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 1 0 APEX 0.984531 1 0 RAD 0.0078125 + txt242 +TEXDEF txt242 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 1 0.0154687 APEX 0.875 1 0.109531 RAD 0.0078125 + txt242 +TEXDEF txt242 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 1 0.125 RAD 0.03125 + txt242 +TEXDEF txt242 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 1 0.125 APEX 0.984531 1 0.125 RAD 0.0078125 + txt242 +TEXDEF txt242 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 1 0.140469 APEX 0.875 1 0.234531 RAD 0.0078125 + txt242 +TEXDEF txt242 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 1 0.25 RAD 0.03125 + txt242 +TEXDEF txt243 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 1 0.25 APEX 0.984531 1 0.25 RAD 0.0078125 + txt243 +TEXDEF txt243 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 1 0.265469 APEX 0.875 1 0.359531 RAD 0.0078125 + txt243 +TEXDEF txt243 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 1 0.375 RAD 0.03125 + txt243 +TEXDEF txt243 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 1 0.375 APEX 0.984531 1 0.375 RAD 0.0078125 + txt243 +TEXDEF txt243 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 1 0.390469 APEX 0.875 1 0.484531 RAD 0.0078125 + txt243 +TEXDEF txt243 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 1 0.5 RAD 0.03125 + txt243 +TEXDEF txt243 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 1 0.5 APEX 0.984531 1 0.5 RAD 0.0078125 + txt243 +TEXDEF txt243 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 1 0.515469 APEX 0.875 1 0.609531 RAD 0.0078125 + txt243 +TEXDEF txt243 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 1 0.625 RAD 0.03125 + txt243 +TEXDEF txt243 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 1 0.625 APEX 0.984531 1 0.625 RAD 0.0078125 + txt243 +TEXDEF txt244 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 1 0.640469 APEX 0.875 1 0.734531 RAD 0.0078125 + txt244 +TEXDEF txt244 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 1 0.75 RAD 0.03125 + txt244 +TEXDEF txt244 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 1 0.75 APEX 0.984531 1 0.75 RAD 0.0078125 + txt244 +TEXDEF txt244 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 1 0.765469 APEX 0.875 1 0.859531 RAD 0.0078125 + txt244 +TEXDEF txt244 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 1 0.875 RAD 0.03125 + txt244 +TEXDEF txt244 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 1 0.875 APEX 0.984531 1 0.875 RAD 0.0078125 + txt244 +TEXDEF txt244 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 0.875 1 0.890469 APEX 0.875 1 0.984531 RAD 0.0078125 + txt244 +TEXDEF txt244 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 0.875 1 1 RAD 0.03125 + txt244 +TEXDEF txt244 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.9 0.1 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 0.890469 1 1 APEX 0.984531 1 1 RAD 0.0078125 + txt244 +TEXDEF txt244 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0 0 RAD 0.03125 + txt244 +TEXDEF txt245 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.0154687 0 APEX 1 0.109531 0 RAD 0.0078125 + txt245 +TEXDEF txt245 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0 0.0154687 APEX 1 0 0.109531 RAD 0.0078125 + txt245 +TEXDEF txt245 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0 0.125 RAD 0.03125 + txt245 +TEXDEF txt245 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.0154687 0.125 APEX 1 0.109531 0.125 RAD 0.0078125 + txt245 +TEXDEF txt245 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0 0.140469 APEX 1 0 0.234531 RAD 0.0078125 + txt245 +TEXDEF txt245 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0 0.25 RAD 0.03125 + txt245 +TEXDEF txt245 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.0154687 0.25 APEX 1 0.109531 0.25 RAD 0.0078125 + txt245 +TEXDEF txt245 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0 0.265469 APEX 1 0 0.359531 RAD 0.0078125 + txt245 +TEXDEF txt245 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0 0.375 RAD 0.03125 + txt245 +TEXDEF txt245 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.0154687 0.375 APEX 1 0.109531 0.375 RAD 0.0078125 + txt245 +TEXDEF txt246 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0 0.390469 APEX 1 0 0.484531 RAD 0.0078125 + txt246 +TEXDEF txt246 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0 0.5 RAD 0.03125 + txt246 +TEXDEF txt246 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.0154687 0.5 APEX 1 0.109531 0.5 RAD 0.0078125 + txt246 +TEXDEF txt246 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0 0.515469 APEX 1 0 0.609531 RAD 0.0078125 + txt246 +TEXDEF txt246 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0 0.625 RAD 0.03125 + txt246 +TEXDEF txt246 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.0154687 0.625 APEX 1 0.109531 0.625 RAD 0.0078125 + txt246 +TEXDEF txt246 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0 0.640469 APEX 1 0 0.734531 RAD 0.0078125 + txt246 +TEXDEF txt246 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0 0.75 RAD 0.03125 + txt246 +TEXDEF txt246 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.0154687 0.75 APEX 1 0.109531 0.75 RAD 0.0078125 + txt246 +TEXDEF txt246 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0 0.765469 APEX 1 0 0.859531 RAD 0.0078125 + txt246 +TEXDEF txt247 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0 0.875 RAD 0.03125 + txt247 +TEXDEF txt247 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.0154687 0.875 APEX 1 0.109531 0.875 RAD 0.0078125 + txt247 +TEXDEF txt247 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0 0.890469 APEX 1 0 0.984531 RAD 0.0078125 + txt247 +TEXDEF txt247 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0 1 RAD 0.03125 + txt247 +TEXDEF txt247 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.0154687 1 APEX 1 0.109531 1 RAD 0.0078125 + txt247 +TEXDEF txt247 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.125 0 RAD 0.03125 + txt247 +TEXDEF txt247 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.140469 0 APEX 1 0.234531 0 RAD 0.0078125 + txt247 +TEXDEF txt247 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.125 0.0154687 APEX 1 0.125 0.109531 RAD 0.0078125 + txt247 +TEXDEF txt247 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.125 0.125 RAD 0.03125 + txt247 +TEXDEF txt247 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.140469 0.125 APEX 1 0.234531 0.125 RAD 0.0078125 + txt247 +TEXDEF txt248 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.125 0.140469 APEX 1 0.125 0.234531 RAD 0.0078125 + txt248 +TEXDEF txt248 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.125 0.25 RAD 0.03125 + txt248 +TEXDEF txt248 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.140469 0.25 APEX 1 0.234531 0.25 RAD 0.0078125 + txt248 +TEXDEF txt248 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.125 0.265469 APEX 1 0.125 0.359531 RAD 0.0078125 + txt248 +TEXDEF txt248 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.125 0.375 RAD 0.03125 + txt248 +TEXDEF txt248 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.140469 0.375 APEX 1 0.234531 0.375 RAD 0.0078125 + txt248 +TEXDEF txt248 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.125 0.390469 APEX 1 0.125 0.484531 RAD 0.0078125 + txt248 +TEXDEF txt248 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.125 0.5 RAD 0.03125 + txt248 +TEXDEF txt248 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.140469 0.5 APEX 1 0.234531 0.5 RAD 0.0078125 + txt248 +TEXDEF txt248 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.125 0.515469 APEX 1 0.125 0.609531 RAD 0.0078125 + txt248 +TEXDEF txt249 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.125 0.625 RAD 0.03125 + txt249 +TEXDEF txt249 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.140469 0.625 APEX 1 0.234531 0.625 RAD 0.0078125 + txt249 +TEXDEF txt249 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.125 0.640469 APEX 1 0.125 0.734531 RAD 0.0078125 + txt249 +TEXDEF txt249 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.125 0.75 RAD 0.03125 + txt249 +TEXDEF txt249 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.140469 0.75 APEX 1 0.234531 0.75 RAD 0.0078125 + txt249 +TEXDEF txt249 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.125 0.765469 APEX 1 0.125 0.859531 RAD 0.0078125 + txt249 +TEXDEF txt249 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.125 0.875 RAD 0.03125 + txt249 +TEXDEF txt249 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.140469 0.875 APEX 1 0.234531 0.875 RAD 0.0078125 + txt249 +TEXDEF txt249 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.125 0.890469 APEX 1 0.125 0.984531 RAD 0.0078125 + txt249 +TEXDEF txt249 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.125 1 RAD 0.03125 + txt249 +TEXDEF txt250 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.140469 1 APEX 1 0.234531 1 RAD 0.0078125 + txt250 +TEXDEF txt250 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.25 0 RAD 0.03125 + txt250 +TEXDEF txt250 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.265469 0 APEX 1 0.359531 0 RAD 0.0078125 + txt250 +TEXDEF txt250 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.25 0.0154687 APEX 1 0.25 0.109531 RAD 0.0078125 + txt250 +TEXDEF txt250 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.25 0.125 RAD 0.03125 + txt250 +TEXDEF txt250 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.265469 0.125 APEX 1 0.359531 0.125 RAD 0.0078125 + txt250 +TEXDEF txt250 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.25 0.140469 APEX 1 0.25 0.234531 RAD 0.0078125 + txt250 +TEXDEF txt250 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.25 0.25 RAD 0.03125 + txt250 +TEXDEF txt250 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.265469 0.25 APEX 1 0.359531 0.25 RAD 0.0078125 + txt250 +TEXDEF txt250 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.25 0.265469 APEX 1 0.25 0.359531 RAD 0.0078125 + txt250 +TEXDEF txt251 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.25 0.375 RAD 0.03125 + txt251 +TEXDEF txt251 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.265469 0.375 APEX 1 0.359531 0.375 RAD 0.0078125 + txt251 +TEXDEF txt251 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.25 0.390469 APEX 1 0.25 0.484531 RAD 0.0078125 + txt251 +TEXDEF txt251 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.25 0.5 RAD 0.03125 + txt251 +TEXDEF txt251 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.265469 0.5 APEX 1 0.359531 0.5 RAD 0.0078125 + txt251 +TEXDEF txt251 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.25 0.515469 APEX 1 0.25 0.609531 RAD 0.0078125 + txt251 +TEXDEF txt251 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.25 0.625 RAD 0.03125 + txt251 +TEXDEF txt251 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.265469 0.625 APEX 1 0.359531 0.625 RAD 0.0078125 + txt251 +TEXDEF txt251 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.25 0.640469 APEX 1 0.25 0.734531 RAD 0.0078125 + txt251 +TEXDEF txt251 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.25 0.75 RAD 0.03125 + txt251 +TEXDEF txt252 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.265469 0.75 APEX 1 0.359531 0.75 RAD 0.0078125 + txt252 +TEXDEF txt252 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.25 0.765469 APEX 1 0.25 0.859531 RAD 0.0078125 + txt252 +TEXDEF txt252 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.25 0.875 RAD 0.03125 + txt252 +TEXDEF txt252 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.265469 0.875 APEX 1 0.359531 0.875 RAD 0.0078125 + txt252 +TEXDEF txt252 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.25 0.890469 APEX 1 0.25 0.984531 RAD 0.0078125 + txt252 +TEXDEF txt252 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.25 1 RAD 0.03125 + txt252 +TEXDEF txt252 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.265469 1 APEX 1 0.359531 1 RAD 0.0078125 + txt252 +TEXDEF txt252 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.375 0 RAD 0.03125 + txt252 +TEXDEF txt252 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.390469 0 APEX 1 0.484531 0 RAD 0.0078125 + txt252 +TEXDEF txt252 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.375 0.0154687 APEX 1 0.375 0.109531 RAD 0.0078125 + txt252 +TEXDEF txt253 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.375 0.125 RAD 0.03125 + txt253 +TEXDEF txt253 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.390469 0.125 APEX 1 0.484531 0.125 RAD 0.0078125 + txt253 +TEXDEF txt253 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.375 0.140469 APEX 1 0.375 0.234531 RAD 0.0078125 + txt253 +TEXDEF txt253 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.375 0.25 RAD 0.03125 + txt253 +TEXDEF txt253 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.390469 0.25 APEX 1 0.484531 0.25 RAD 0.0078125 + txt253 +TEXDEF txt253 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.375 0.265469 APEX 1 0.375 0.359531 RAD 0.0078125 + txt253 +TEXDEF txt253 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.375 0.375 RAD 0.03125 + txt253 +TEXDEF txt253 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.390469 0.375 APEX 1 0.484531 0.375 RAD 0.0078125 + txt253 +TEXDEF txt253 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.375 0.390469 APEX 1 0.375 0.484531 RAD 0.0078125 + txt253 +TEXDEF txt253 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.375 0.5 RAD 0.03125 + txt253 +TEXDEF txt254 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.390469 0.5 APEX 1 0.484531 0.5 RAD 0.0078125 + txt254 +TEXDEF txt254 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.375 0.515469 APEX 1 0.375 0.609531 RAD 0.0078125 + txt254 +TEXDEF txt254 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.375 0.625 RAD 0.03125 + txt254 +TEXDEF txt254 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.390469 0.625 APEX 1 0.484531 0.625 RAD 0.0078125 + txt254 +TEXDEF txt254 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.375 0.640469 APEX 1 0.375 0.734531 RAD 0.0078125 + txt254 +TEXDEF txt254 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.375 0.75 RAD 0.03125 + txt254 +TEXDEF txt254 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.390469 0.75 APEX 1 0.484531 0.75 RAD 0.0078125 + txt254 +TEXDEF txt254 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.375 0.765469 APEX 1 0.375 0.859531 RAD 0.0078125 + txt254 +TEXDEF txt254 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.375 0.875 RAD 0.03125 + txt254 +TEXDEF txt254 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.390469 0.875 APEX 1 0.484531 0.875 RAD 0.0078125 + txt254 +TEXDEF txt255 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.375 0.890469 APEX 1 0.375 0.984531 RAD 0.0078125 + txt255 +TEXDEF txt255 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.375 1 RAD 0.03125 + txt255 +TEXDEF txt255 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.390469 1 APEX 1 0.484531 1 RAD 0.0078125 + txt255 +TEXDEF txt255 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.5 0 RAD 0.03125 + txt255 +TEXDEF txt255 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.515469 0 APEX 1 0.609531 0 RAD 0.0078125 + txt255 +TEXDEF txt255 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.5 0.0154687 APEX 1 0.5 0.109531 RAD 0.0078125 + txt255 +TEXDEF txt255 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.5 0.125 RAD 0.03125 + txt255 +TEXDEF txt255 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.515469 0.125 APEX 1 0.609531 0.125 RAD 0.0078125 + txt255 +TEXDEF txt255 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.5 0.140469 APEX 1 0.5 0.234531 RAD 0.0078125 + txt255 +TEXDEF txt255 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.5 0.25 RAD 0.03125 + txt255 +TEXDEF txt256 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.515469 0.25 APEX 1 0.609531 0.25 RAD 0.0078125 + txt256 +TEXDEF txt256 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.5 0.265469 APEX 1 0.5 0.359531 RAD 0.0078125 + txt256 +TEXDEF txt256 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.5 0.375 RAD 0.03125 + txt256 +TEXDEF txt256 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.515469 0.375 APEX 1 0.609531 0.375 RAD 0.0078125 + txt256 +TEXDEF txt256 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.5 0.390469 APEX 1 0.5 0.484531 RAD 0.0078125 + txt256 +TEXDEF txt256 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.5 0.5 RAD 0.03125 + txt256 +TEXDEF txt256 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.515469 0.5 APEX 1 0.609531 0.5 RAD 0.0078125 + txt256 +TEXDEF txt256 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.5 0.515469 APEX 1 0.5 0.609531 RAD 0.0078125 + txt256 +TEXDEF txt256 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.5 0.625 RAD 0.03125 + txt256 +TEXDEF txt256 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.515469 0.625 APEX 1 0.609531 0.625 RAD 0.0078125 + txt256 +TEXDEF txt257 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.5 0.640469 APEX 1 0.5 0.734531 RAD 0.0078125 + txt257 +TEXDEF txt257 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.5 0.75 RAD 0.03125 + txt257 +TEXDEF txt257 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.515469 0.75 APEX 1 0.609531 0.75 RAD 0.0078125 + txt257 +TEXDEF txt257 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.5 0.765469 APEX 1 0.5 0.859531 RAD 0.0078125 + txt257 +TEXDEF txt257 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.5 0.875 RAD 0.03125 + txt257 +TEXDEF txt257 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.515469 0.875 APEX 1 0.609531 0.875 RAD 0.0078125 + txt257 +TEXDEF txt257 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.5 0.890469 APEX 1 0.5 0.984531 RAD 0.0078125 + txt257 +TEXDEF txt257 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.5 1 RAD 0.03125 + txt257 +TEXDEF txt257 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.515469 1 APEX 1 0.609531 1 RAD 0.0078125 + txt257 +TEXDEF txt257 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.625 0 RAD 0.03125 + txt257 +TEXDEF txt258 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.640469 0 APEX 1 0.734531 0 RAD 0.0078125 + txt258 +TEXDEF txt258 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.625 0.0154687 APEX 1 0.625 0.109531 RAD 0.0078125 + txt258 +TEXDEF txt258 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.625 0.125 RAD 0.03125 + txt258 +TEXDEF txt258 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.640469 0.125 APEX 1 0.734531 0.125 RAD 0.0078125 + txt258 +TEXDEF txt258 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.625 0.140469 APEX 1 0.625 0.234531 RAD 0.0078125 + txt258 +TEXDEF txt258 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.625 0.25 RAD 0.03125 + txt258 +TEXDEF txt258 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.640469 0.25 APEX 1 0.734531 0.25 RAD 0.0078125 + txt258 +TEXDEF txt258 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.625 0.265469 APEX 1 0.625 0.359531 RAD 0.0078125 + txt258 +TEXDEF txt258 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.625 0.375 RAD 0.03125 + txt258 +TEXDEF txt258 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.640469 0.375 APEX 1 0.734531 0.375 RAD 0.0078125 + txt258 +TEXDEF txt259 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.625 0.390469 APEX 1 0.625 0.484531 RAD 0.0078125 + txt259 +TEXDEF txt259 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.625 0.5 RAD 0.03125 + txt259 +TEXDEF txt259 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.640469 0.5 APEX 1 0.734531 0.5 RAD 0.0078125 + txt259 +TEXDEF txt259 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.625 0.515469 APEX 1 0.625 0.609531 RAD 0.0078125 + txt259 +TEXDEF txt259 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.625 0.625 RAD 0.03125 + txt259 +TEXDEF txt259 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.640469 0.625 APEX 1 0.734531 0.625 RAD 0.0078125 + txt259 +TEXDEF txt259 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.625 0.640469 APEX 1 0.625 0.734531 RAD 0.0078125 + txt259 +TEXDEF txt259 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.625 0.75 RAD 0.03125 + txt259 +TEXDEF txt259 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.640469 0.75 APEX 1 0.734531 0.75 RAD 0.0078125 + txt259 +TEXDEF txt259 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.625 0.765469 APEX 1 0.625 0.859531 RAD 0.0078125 + txt259 +TEXDEF txt260 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.625 0.875 RAD 0.03125 + txt260 +TEXDEF txt260 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.640469 0.875 APEX 1 0.734531 0.875 RAD 0.0078125 + txt260 +TEXDEF txt260 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.625 0.890469 APEX 1 0.625 0.984531 RAD 0.0078125 + txt260 +TEXDEF txt260 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.625 1 RAD 0.03125 + txt260 +TEXDEF txt260 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.640469 1 APEX 1 0.734531 1 RAD 0.0078125 + txt260 +TEXDEF txt260 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.75 0 RAD 0.03125 + txt260 +TEXDEF txt260 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.765469 0 APEX 1 0.859531 0 RAD 0.0078125 + txt260 +TEXDEF txt260 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.75 0.0154687 APEX 1 0.75 0.109531 RAD 0.0078125 + txt260 +TEXDEF txt260 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.75 0.125 RAD 0.03125 + txt260 +TEXDEF txt260 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.765469 0.125 APEX 1 0.859531 0.125 RAD 0.0078125 + txt260 +TEXDEF txt261 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.75 0.140469 APEX 1 0.75 0.234531 RAD 0.0078125 + txt261 +TEXDEF txt261 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.75 0.25 RAD 0.03125 + txt261 +TEXDEF txt261 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.765469 0.25 APEX 1 0.859531 0.25 RAD 0.0078125 + txt261 +TEXDEF txt261 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.75 0.265469 APEX 1 0.75 0.359531 RAD 0.0078125 + txt261 +TEXDEF txt261 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.75 0.375 RAD 0.03125 + txt261 +TEXDEF txt261 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.765469 0.375 APEX 1 0.859531 0.375 RAD 0.0078125 + txt261 +TEXDEF txt261 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.75 0.390469 APEX 1 0.75 0.484531 RAD 0.0078125 + txt261 +TEXDEF txt261 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.75 0.5 RAD 0.03125 + txt261 +TEXDEF txt261 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.765469 0.5 APEX 1 0.859531 0.5 RAD 0.0078125 + txt261 +TEXDEF txt261 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.75 0.515469 APEX 1 0.75 0.609531 RAD 0.0078125 + txt261 +TEXDEF txt262 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.75 0.625 RAD 0.03125 + txt262 +TEXDEF txt262 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.765469 0.625 APEX 1 0.859531 0.625 RAD 0.0078125 + txt262 +TEXDEF txt262 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.75 0.640469 APEX 1 0.75 0.734531 RAD 0.0078125 + txt262 +TEXDEF txt262 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.75 0.75 RAD 0.03125 + txt262 +TEXDEF txt262 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.765469 0.75 APEX 1 0.859531 0.75 RAD 0.0078125 + txt262 +TEXDEF txt262 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.75 0.765469 APEX 1 0.75 0.859531 RAD 0.0078125 + txt262 +TEXDEF txt262 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.75 0.875 RAD 0.03125 + txt262 +TEXDEF txt262 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.765469 0.875 APEX 1 0.859531 0.875 RAD 0.0078125 + txt262 +TEXDEF txt262 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.75 0.890469 APEX 1 0.75 0.984531 RAD 0.0078125 + txt262 +TEXDEF txt262 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.75 1 RAD 0.03125 + txt262 +TEXDEF txt263 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.765469 1 APEX 1 0.859531 1 RAD 0.0078125 + txt263 +TEXDEF txt263 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.875 0 RAD 0.03125 + txt263 +TEXDEF txt263 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.890469 0 APEX 1 0.984531 0 RAD 0.0078125 + txt263 +TEXDEF txt263 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.875 0.0154687 APEX 1 0.875 0.109531 RAD 0.0078125 + txt263 +TEXDEF txt263 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.875 0.125 RAD 0.03125 + txt263 +TEXDEF txt263 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.890469 0.125 APEX 1 0.984531 0.125 RAD 0.0078125 + txt263 +TEXDEF txt263 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.875 0.140469 APEX 1 0.875 0.234531 RAD 0.0078125 + txt263 +TEXDEF txt263 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.875 0.25 RAD 0.03125 + txt263 +TEXDEF txt263 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.890469 0.25 APEX 1 0.984531 0.25 RAD 0.0078125 + txt263 +TEXDEF txt263 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.875 0.265469 APEX 1 0.875 0.359531 RAD 0.0078125 + txt263 +TEXDEF txt264 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.875 0.375 RAD 0.03125 + txt264 +TEXDEF txt264 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.890469 0.375 APEX 1 0.984531 0.375 RAD 0.0078125 + txt264 +TEXDEF txt264 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.875 0.390469 APEX 1 0.875 0.484531 RAD 0.0078125 + txt264 +TEXDEF txt264 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.875 0.5 RAD 0.03125 + txt264 +TEXDEF txt264 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.890469 0.5 APEX 1 0.984531 0.5 RAD 0.0078125 + txt264 +TEXDEF txt264 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.875 0.515469 APEX 1 0.875 0.609531 RAD 0.0078125 + txt264 +TEXDEF txt264 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.875 0.625 RAD 0.03125 + txt264 +TEXDEF txt264 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.890469 0.625 APEX 1 0.984531 0.625 RAD 0.0078125 + txt264 +TEXDEF txt264 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.875 0.640469 APEX 1 0.875 0.734531 RAD 0.0078125 + txt264 +TEXDEF txt264 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.875 0.75 RAD 0.03125 + txt264 +TEXDEF txt265 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.890469 0.75 APEX 1 0.984531 0.75 RAD 0.0078125 + txt265 +TEXDEF txt265 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.875 0.765469 APEX 1 0.875 0.859531 RAD 0.0078125 + txt265 +TEXDEF txt265 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.875 0.875 RAD 0.03125 + txt265 +TEXDEF txt265 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.890469 0.875 APEX 1 0.984531 0.875 RAD 0.0078125 + txt265 +TEXDEF txt265 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.875 0.890469 APEX 1 0.875 0.984531 RAD 0.0078125 + txt265 +TEXDEF txt265 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 0.875 1 RAD 0.03125 + txt265 +TEXDEF txt265 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.9 0.1 + TEXFUNC 0 + +FCYLINDER + BASE 1 0.890469 1 APEX 1 0.984531 1 RAD 0.0078125 + txt265 +TEXDEF txt265 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 1 0 RAD 0.03125 + txt265 +TEXDEF txt265 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 1 0.0154687 APEX 1 1 0.109531 RAD 0.0078125 + txt265 +TEXDEF txt265 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 1 0.125 RAD 0.03125 + txt265 +TEXDEF txt266 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 1 0.140469 APEX 1 1 0.234531 RAD 0.0078125 + txt266 +TEXDEF txt266 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 1 0.25 RAD 0.03125 + txt266 +TEXDEF txt266 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 1 0.265469 APEX 1 1 0.359531 RAD 0.0078125 + txt266 +TEXDEF txt266 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 1 0.375 RAD 0.03125 + txt266 +TEXDEF txt266 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 1 0.390469 APEX 1 1 0.484531 RAD 0.0078125 + txt266 +TEXDEF txt266 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 1 0.5 RAD 0.03125 + txt266 +TEXDEF txt266 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 1 0.515469 APEX 1 1 0.609531 RAD 0.0078125 + txt266 +TEXDEF txt266 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 1 0.625 RAD 0.03125 + txt266 +TEXDEF txt266 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 1 0.640469 APEX 1 1 0.734531 RAD 0.0078125 + txt266 +TEXDEF txt266 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 1 0.75 RAD 0.03125 + txt266 +TEXDEF txt267 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 1 0.765469 APEX 1 1 0.859531 RAD 0.0078125 + txt267 +TEXDEF txt267 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 1 0.875 RAD 0.03125 + txt267 +TEXDEF txt267 AMBIENT 0.1 DIFFUSE 0.99 SPECULAR 0 OPACITY 1 + COLOR 0.1 0.1 0.9 + TEXFUNC 0 + +FCYLINDER + BASE 1 1 0.890469 APEX 1 1 0.984531 RAD 0.0078125 + txt267 +TEXDEF txt267 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 + COLOR 0.9 0.9 0.9 + TEXFUNC 0 + + SPHERE CENTER 1 1 1 RAD 0.03125 + txt267 + +END_SCENE diff --git a/src/tbb/examples/parallel_for/tachyon/dat/model2.dat b/src/tbb/examples/parallel_for/tachyon/dat/model2.dat new file mode 100644 index 0000000..c57ce49 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/dat/model2.dat @@ -0,0 +1,104 @@ +BEGIN_SCENE + OUTFILE /dev/null + RESOLUTION 512 512 + VERBOSE 0 + +CAMERA + ZOOM 1.0 + ASPECTRATIO 1.0 + ANTIALIASING 1 + RAYDEPTH 12 + CENTER 0.0 0.0 -5.0 + VIEWDIR 0.0 0.0 1.0 + UPDIR 0.0 1.0 0.0 +END_CAMERA + +LIGHT + CENTER -5.0 0.0 -4.0 + RAD 0.2 + COLOR 1.0 0.1 0.0 + +LIGHT + CENTER 4.0 5.0 -4.0 + RAD 0.2 + COLOR 0.0 0.1 1.0 + +LIGHT + CENTER 4.0 1.5 3.0 + RAD 0.2 + COLOR 0.5 0.5 0.5 + +TRI + V0 0.0 -4.0 12.0 + V1 4.0 -4.0 8.0 + V2 -4.0 -4.0 8.0 + TEXTURE + AMBIENT 0.1 DIFFUSE 0.2 SPECULAR 0.7 OPACITY 1.0 + COLOR 1.0 1.0 1.0 + TEXFUNC 0 + +SPHERE + CENTER 0.0 0.0 5.0 + RAD 1.3 + TEXTURE + AMBIENT 0.1 DIFFUSE 0.0 SPECULAR 0.9 OPACITY 1.0 + COLOR 1.0 1.0 1.0 + TEXFUNC 0 + +SPHERE + CENTER 1.0 0.0 4.3 + RAD 0.8 + TEXTURE + AMBIENT 0.1 DIFFUSE 0.9 SPECULAR 0.0 OPACITY 1.0 + COLOR 0.3 0.3 1.0 + TEXFUNC 3 + CENTER 1.0 0.0 4.3 + ROTATE 0. 0.0 0.0 + SCALE 1.0 1.0 1.0 + +SPHERE + CENTER 0.0 2.0 8.0 + RAD 1.0 + TEXTURE + AMBIENT 0.1 DIFFUSE 0.9 SPECULAR 0.0 OPACITY 1.0 + COLOR 1.0 0.0 1.0 + TEXFUNC 4 + CENTER 0.0 1.0 8.0 + ROTATE 0. 0.0 0.0 + SCALE 1.0 1.0 1.0 + +SPHERE + CENTER -1.0 -0.5 5.0 + RAD 1.0 + TEXTURE + AMBIENT 0.1 DIFFUSE 0.9 SPECULAR 0.0 OPACITY 1.0 + COLOR 1.0 1.0 0.5 + TEXFUNC 6 + CENTER -1.0 -0.5 5.0 + ROTATE 0. 0.0 0.0 + SCALE 1.0 1.0 1.0 + +PLANE + CENTER 0.0 -5.0 0.0 + NORMAL 0.0 1.0 0.0 + TEXTURE + AMBIENT 0.1 DIFFUSE 0.9 SPECULAR 0.0 OPACITY 1.0 + COLOR 1.0 1.0 1.0 + TEXFUNC 1 + CENTER 0.0 -5.0 0.0 + ROTATE 0. 0.0 0.0 + SCALE 1.0 1.0 1.0 + +PLANE + CENTER 0.0 0.0 15.0 + NORMAL 0.0 0.0 -1.0 + TEXTURE + AMBIENT 0.1 DIFFUSE 0.9 SPECULAR 0.0 OPACITY 1.0 + COLOR 1.0 1.0 1.0 + TEXFUNC 3 + CENTER 0.0 0.0 15.0 + ROTATE 0. 0.0 0.0 + SCALE 1.0 1.0 1.0 + +END_SCENE + diff --git a/src/tbb/examples/parallel_for/tachyon/dat/teapot.dat b/src/tbb/examples/parallel_for/tachyon/dat/teapot.dat new file mode 100644 index 0000000..105afcd --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/dat/teapot.dat @@ -0,0 +1,9279 @@ +BEGIN_SCENE + OUTFILE /dev/null + RESOLUTION 512 512 + VERBOSE 0 + +CAMERA + ZOOM 1.20711 +ASPECTRATIO 1.0 + ANTIALIASING 0 + RAYDEPTH 5 + CENTER 4.86 7.2 5.4 + VIEWDIR -0.475149 -0.703924 -0.527943 + UPDIR -0.29537 -0.437585 0.84928 + +END_CAMERA + +BACKGROUND 0.078 0.361 0.753 + +LIGHT CENTER -3.1 9.8 12.1 RAD 0.002 COLOR 0.5 0.5 0.5 + +LIGHT CENTER 11.3 5.1 8.8 RAD 0.002 COLOR 0.5 0.5 0.5 + +TEXDEF txt001 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 +PHONG METAL 0.5 PHONG_SIZE 4.81884 + COLOR 1 1 1 + TEXFUNC 0 + +TRI + V0 -4 -2.66667 0 V1 -2.66667 -2.66667 0 V2 -4 -1.33333 0 + txt001 +TRI + V0 -2.66667 -2.66667 0 V1 -2.66667 -1.33333 0 V2 -4 -1.33333 0 + txt001 +TRI + V0 -4 0 0 V1 -2.66667 0 0 V2 -4 1.33333 0 + txt001 +TRI + V0 -2.66667 0 0 V1 -2.66667 1.33333 0 V2 -4 1.33333 0 + txt001 +TRI + V0 -4 2.66667 0 V1 -2.66667 2.66667 0 V2 -4 4 0 + txt001 +TRI + V0 -2.66667 2.66667 0 V1 -2.66667 4 0 V2 -4 4 0 + txt001 +TRI + V0 -2.66667 -4 0 V1 -1.33333 -4 0 V2 -2.66667 -2.66667 0 + txt001 +TRI + V0 -1.33333 -4 0 V1 -1.33333 -2.66667 0 V2 -2.66667 -2.66667 0 + txt001 +TRI + V0 -2.66667 -1.33333 0 V1 -1.33333 -1.33333 0 V2 -2.66667 0 0 + txt001 +TRI + V0 -1.33333 -1.33333 0 V1 -1.33333 0 0 V2 -2.66667 0 0 + txt001 +TRI + V0 -2.66667 1.33333 0 V1 -1.33333 1.33333 0 V2 -2.66667 2.66667 0 + txt001 +TRI + V0 -1.33333 1.33333 0 V1 -1.33333 2.66667 0 V2 -2.66667 2.66667 0 + txt001 +TRI + V0 -1.33333 -2.66667 0 V1 0 -2.66667 0 V2 -1.33333 -1.33333 0 + txt001 +TRI + V0 0 -2.66667 0 V1 0 -1.33333 0 V2 -1.33333 -1.33333 0 + txt001 +TRI + V0 -1.33333 0 0 V1 0 0 0 V2 -1.33333 1.33333 0 + txt001 +TRI + V0 0 0 0 V1 0 1.33333 0 V2 -1.33333 1.33333 0 + txt001 +TRI + V0 -1.33333 2.66667 0 V1 0 2.66667 0 V2 -1.33333 4 0 + txt001 +TRI + V0 0 2.66667 0 V1 0 4 0 V2 -1.33333 4 0 + txt001 +TRI + V0 0 -4 0 V1 1.33333 -4 0 V2 0 -2.66667 0 + txt001 +TRI + V0 1.33333 -4 0 V1 1.33333 -2.66667 0 V2 0 -2.66667 0 + txt001 +TRI + V0 0 -1.33333 0 V1 1.33333 -1.33333 0 V2 0 0 0 + txt001 +TRI + V0 1.33333 -1.33333 0 V1 1.33333 0 0 V2 0 0 0 + txt001 +TRI + V0 0 1.33333 0 V1 1.33333 1.33333 0 V2 0 2.66667 0 + txt001 +TRI + V0 1.33333 1.33333 0 V1 1.33333 2.66667 0 V2 0 2.66667 0 + txt001 +TRI + V0 1.33333 -2.66667 0 V1 2.66667 -2.66667 0 V2 1.33333 -1.33333 0 + txt001 +TRI + V0 2.66667 -2.66667 0 V1 2.66667 -1.33333 0 V2 1.33333 -1.33333 0 + txt001 +TRI + V0 1.33333 0 0 V1 2.66667 0 0 V2 1.33333 1.33333 0 + txt001 +TRI + V0 2.66667 0 0 V1 2.66667 1.33333 0 V2 1.33333 1.33333 0 + txt001 +TRI + V0 1.33333 2.66667 0 V1 2.66667 2.66667 0 V2 1.33333 4 0 + txt001 +TRI + V0 2.66667 2.66667 0 V1 2.66667 4 0 V2 1.33333 4 0 + txt001 +TRI + V0 2.66667 -4 0 V1 4 -4 0 V2 2.66667 -2.66667 0 + txt001 +TRI + V0 4 -4 0 V1 4 -2.66667 0 V2 2.66667 -2.66667 0 + txt001 +TRI + V0 2.66667 -1.33333 0 V1 4 -1.33333 0 V2 2.66667 0 0 + txt001 +TRI + V0 4 -1.33333 0 V1 4 0 0 V2 2.66667 0 0 + txt001 +TRI + V0 2.66667 1.33333 0 V1 4 1.33333 0 V2 2.66667 2.66667 0 + txt001 +TRI + V0 4 1.33333 0 V1 4 2.66667 0 V2 2.66667 2.66667 0 + txt001 +TEXDEF txt002 AMBIENT 0 DIFFUSE 0.5 SPECULAR 0.5 OPACITY 1 +PHONG METAL 0.5 PHONG_SIZE 4.81884 + COLOR 0.5 0.5 0.5 + TEXFUNC 0 + +TRI + V0 -4 -4 0 V1 -2.66667 -4 0 V2 -4 -2.66667 0 + txt002 +TRI + V0 -2.66667 -4 0 V1 -2.66667 -2.66667 0 V2 -4 -2.66667 0 + txt002 +TRI + V0 -4 -1.33333 0 V1 -2.66667 -1.33333 0 V2 -4 0 0 + txt002 +TRI + V0 -2.66667 -1.33333 0 V1 -2.66667 0 0 V2 -4 0 0 + txt002 +TRI + V0 -4 1.33333 0 V1 -2.66667 1.33333 0 V2 -4 2.66667 0 + txt002 +TRI + V0 -2.66667 1.33333 0 V1 -2.66667 2.66667 0 V2 -4 2.66667 0 + txt002 +TRI + V0 -2.66667 -2.66667 0 V1 -1.33333 -2.66667 0 V2 -2.66667 -1.33333 0 + txt002 +TRI + V0 -1.33333 -2.66667 0 V1 -1.33333 -1.33333 0 V2 -2.66667 -1.33333 0 + txt002 +TRI + V0 -2.66667 0 0 V1 -1.33333 0 0 V2 -2.66667 1.33333 0 + txt002 +TRI + V0 -1.33333 0 0 V1 -1.33333 1.33333 0 V2 -2.66667 1.33333 0 + txt002 +TRI + V0 -2.66667 2.66667 0 V1 -1.33333 2.66667 0 V2 -2.66667 4 0 + txt002 +TRI + V0 -1.33333 2.66667 0 V1 -1.33333 4 0 V2 -2.66667 4 0 + txt002 +TRI + V0 -1.33333 -4 0 V1 0 -4 0 V2 -1.33333 -2.66667 0 + txt002 +TRI + V0 0 -4 0 V1 0 -2.66667 0 V2 -1.33333 -2.66667 0 + txt002 +TRI + V0 -1.33333 -1.33333 0 V1 0 -1.33333 0 V2 -1.33333 0 0 + txt002 +TRI + V0 0 -1.33333 0 V1 0 0 0 V2 -1.33333 0 0 + txt002 +TRI + V0 -1.33333 1.33333 0 V1 0 1.33333 0 V2 -1.33333 2.66667 0 + txt002 +TRI + V0 0 1.33333 0 V1 0 2.66667 0 V2 -1.33333 2.66667 0 + txt002 +TRI + V0 0 -2.66667 0 V1 1.33333 -2.66667 0 V2 0 -1.33333 0 + txt002 +TRI + V0 1.33333 -2.66667 0 V1 1.33333 -1.33333 0 V2 0 -1.33333 0 + txt002 +TRI + V0 0 0 0 V1 1.33333 0 0 V2 0 1.33333 0 + txt002 +TRI + V0 1.33333 0 0 V1 1.33333 1.33333 0 V2 0 1.33333 0 + txt002 +TRI + V0 0 2.66667 0 V1 1.33333 2.66667 0 V2 0 4 0 + txt002 +TRI + V0 1.33333 2.66667 0 V1 1.33333 4 0 V2 0 4 0 + txt002 +TRI + V0 1.33333 -4 0 V1 2.66667 -4 0 V2 1.33333 -2.66667 0 + txt002 +TRI + V0 2.66667 -4 0 V1 2.66667 -2.66667 0 V2 1.33333 -2.66667 0 + txt002 +TRI + V0 1.33333 -1.33333 0 V1 2.66667 -1.33333 0 V2 1.33333 0 0 + txt002 +TRI + V0 2.66667 -1.33333 0 V1 2.66667 0 0 V2 1.33333 0 0 + txt002 +TRI + V0 1.33333 1.33333 0 V1 2.66667 1.33333 0 V2 1.33333 2.66667 0 + txt002 +TRI + V0 2.66667 1.33333 0 V1 2.66667 2.66667 0 V2 1.33333 2.66667 0 + txt002 +TRI + V0 2.66667 -2.66667 0 V1 4 -2.66667 0 V2 2.66667 -1.33333 0 + txt002 +TRI + V0 4 -2.66667 0 V1 4 -1.33333 0 V2 2.66667 -1.33333 0 + txt002 +TRI + V0 2.66667 0 0 V1 4 0 0 V2 2.66667 1.33333 0 + txt002 +TRI + V0 4 0 0 V1 4 1.33333 0 V2 2.66667 1.33333 0 + txt002 +TRI + V0 2.66667 2.66667 0 V1 4 2.66667 0 V2 2.66667 4 0 + txt002 +TRI + V0 4 2.66667 0 V1 4 4 0 V2 2.66667 4 0 + txt002 +TEXDEF txt003 AMBIENT 0 DIFFUSE 0.75 SPECULAR 0.25 OPACITY 1 +PHONG PLASTIC 0.25 PHONG_SIZE 45.2776 + COLOR 1 0.5 0.1 + TEXFUNC 0 + +STRI + V0 1.4 0 2.4 V1 1.35074 -0.375926 2.4 V2 1.33276 -0.370922 2.45469 + N0 -0.902861 -0 -0.429934 N1 -0.871509 0.234929 -0.430442 N2 -0.953562 0.257047 -0.156989 + txt003 +STRI + V0 1.33276 -0.370922 2.45469 V1 1.38137 0 2.45469 V2 1.4 0 2.4 + N0 -0.953562 0.257047 -0.156989 N1 -0.987636 -0 -0.156768 N2 -0.902861 -0 -0.429934 + txt003 +STRI + V0 1.35074 -0.375926 2.4 V1 1.21126 -0.711407 2.4 V2 1.19514 -0.701938 2.45469 + N0 -0.871509 0.234929 -0.430442 N1 -0.780517 0.4527 -0.43111 N2 -0.854265 0.495474 -0.157281 + txt003 +STRI + V0 1.19514 -0.701938 2.45469 V1 1.33276 -0.370922 2.45469 V2 1.35074 -0.375926 2.4 + N0 -0.854265 0.495474 -0.157281 N1 -0.953562 0.257047 -0.156989 N2 -0.871509 0.234929 -0.430442 + txt003 +STRI + V0 1.21126 -0.711407 2.4 V1 0.994 -0.994 2.4 V2 0.98077 -0.98077 2.45469 + N0 -0.780517 0.4527 -0.43111 N1 -0.637936 0.637936 -0.431366 N2 -0.698293 0.698293 -0.157393 + txt003 +STRI + V0 0.98077 -0.98077 2.45469 V1 1.19514 -0.701938 2.45469 V2 1.21126 -0.711407 2.4 + N0 -0.698293 0.698293 -0.157393 N1 -0.854265 0.495474 -0.157281 N2 -0.780517 0.4527 -0.43111 + txt003 +STRI + V0 0.994 -0.994 2.4 V1 0.711407 -1.21126 2.4 V2 0.701938 -1.19514 2.45469 + N0 -0.637936 0.637936 -0.431366 N1 -0.4527 0.780517 -0.43111 N2 -0.495474 0.854265 -0.157281 + txt003 +STRI + V0 0.701938 -1.19514 2.45469 V1 0.98077 -0.98077 2.45469 V2 0.994 -0.994 2.4 + N0 -0.495474 0.854265 -0.157281 N1 -0.698293 0.698293 -0.157393 N2 -0.637936 0.637936 -0.431366 + txt003 +STRI + V0 0.711407 -1.21126 2.4 V1 0.375926 -1.35074 2.4 V2 0.370922 -1.33276 2.45469 + N0 -0.4527 0.780517 -0.43111 N1 -0.234929 0.871509 -0.430442 N2 -0.257047 0.953562 -0.156989 + txt003 +STRI + V0 0.370922 -1.33276 2.45469 V1 0.701938 -1.19514 2.45469 V2 0.711407 -1.21126 2.4 + N0 -0.257047 0.953562 -0.156989 N1 -0.495474 0.854265 -0.157281 N2 -0.4527 0.780517 -0.43111 + txt003 +STRI + V0 0.375926 -1.35074 2.4 V1 0 -1.4 2.4 V2 0 -1.38137 2.45469 + N0 -0.234929 0.871509 -0.430442 N1 7.30595e-17 0.902861 -0.429934 N2 -9.89971e-17 0.987636 -0.156768 + txt003 +STRI + V0 0 -1.38137 2.45469 V1 0.370922 -1.33276 2.45469 V2 0.375926 -1.35074 2.4 + N0 -9.89971e-17 0.987636 -0.156768 N1 -0.257047 0.953562 -0.156989 N2 -0.234929 0.871509 -0.430442 + txt003 +STRI + V0 1.38137 0 2.45469 V1 1.33276 -0.370922 2.45469 V2 1.33555 -0.371699 2.4875 + N0 -0.987636 -0 -0.156768 N1 -0.953562 0.257047 -0.156989 N2 -0.849414 0.228972 0.475466 + txt003 +STRI + V0 1.33555 -0.371699 2.4875 V1 1.38426 0 2.4875 V2 1.38137 0 2.45469 + N0 -0.849414 0.228972 0.475466 N1 -0.880022 0 0.474933 N2 -0.987636 -0 -0.156768 + txt003 +STRI + V0 1.33276 -0.370922 2.45469 V1 1.19514 -0.701938 2.45469 V2 1.19764 -0.703409 2.4875 + N0 -0.953562 0.257047 -0.156989 N1 -0.854265 0.495474 -0.157281 N2 -0.760669 0.441188 0.476167 + txt003 +STRI + V0 1.19764 -0.703409 2.4875 V1 1.33555 -0.371699 2.4875 V2 1.33276 -0.370922 2.45469 + N0 -0.760669 0.441188 0.476167 N1 -0.849414 0.228972 0.475466 N2 -0.953562 0.257047 -0.156989 + txt003 +STRI + V0 1.19514 -0.701938 2.45469 V1 0.98077 -0.98077 2.45469 V2 0.982824 -0.982824 2.4875 + N0 -0.854265 0.495474 -0.157281 N1 -0.698293 0.698293 -0.157393 N2 -0.621695 0.621695 0.476435 + txt003 +STRI + V0 0.982824 -0.982824 2.4875 V1 1.19764 -0.703409 2.4875 V2 1.19514 -0.701938 2.45469 + N0 -0.621695 0.621695 0.476435 N1 -0.760669 0.441188 0.476167 N2 -0.854265 0.495474 -0.157281 + txt003 +STRI + V0 0.98077 -0.98077 2.45469 V1 0.701938 -1.19514 2.45469 V2 0.703409 -1.19764 2.4875 + N0 -0.698293 0.698293 -0.157393 N1 -0.495474 0.854265 -0.157281 N2 -0.441188 0.760669 0.476167 + txt003 +STRI + V0 0.703409 -1.19764 2.4875 V1 0.982824 -0.982824 2.4875 V2 0.98077 -0.98077 2.45469 + N0 -0.441188 0.760669 0.476167 N1 -0.621695 0.621695 0.476435 N2 -0.698293 0.698293 -0.157393 + txt003 +STRI + V0 0.701938 -1.19514 2.45469 V1 0.370922 -1.33276 2.45469 V2 0.371699 -1.33555 2.4875 + N0 -0.495474 0.854265 -0.157281 N1 -0.257047 0.953562 -0.156989 N2 -0.228972 0.849414 0.475466 + txt003 +STRI + V0 0.371699 -1.33555 2.4875 V1 0.703409 -1.19764 2.4875 V2 0.701938 -1.19514 2.45469 + N0 -0.228972 0.849414 0.475466 N1 -0.441188 0.760669 0.476167 N2 -0.495474 0.854265 -0.157281 + txt003 +STRI + V0 0.370922 -1.33276 2.45469 V1 0 -1.38137 2.45469 V2 0 -1.38426 2.4875 + N0 -0.257047 0.953562 -0.156989 N1 -9.89971e-17 0.987636 -0.156768 N2 -6.08179e-16 0.880022 0.474933 + txt003 +STRI + V0 0 -1.38426 2.4875 V1 0.371699 -1.33555 2.4875 V2 0.370922 -1.33276 2.45469 + N0 -6.08179e-16 0.880022 0.474933 N1 -0.228972 0.849414 0.475466 N2 -0.257047 0.953562 -0.156989 + txt003 +STRI + V0 1.38426 0 2.4875 V1 1.33555 -0.371699 2.4875 V2 1.35376 -0.376765 2.49844 + N0 -0.880022 0 0.474933 N1 -0.849414 0.228972 0.475466 N2 2.13636e-15 -5.93089e-16 1 + txt003 +STRI + V0 1.35376 -0.376765 2.49844 V1 1.40312 0 2.49844 V2 1.38426 0 2.4875 + N0 2.13636e-15 -5.93089e-16 1 N1 2.22045e-15 0 1 N2 -0.880022 0 0.474933 + txt003 +STRI + V0 1.33555 -0.371699 2.4875 V1 1.19764 -0.703409 2.4875 V2 1.21396 -0.712995 2.49844 + N0 -0.849414 0.228972 0.475466 N1 -0.760669 0.441188 0.476167 N2 1.87966e-15 -1.16933e-15 1 + txt003 +STRI + V0 1.21396 -0.712995 2.49844 V1 1.35376 -0.376765 2.49844 V2 1.33555 -0.371699 2.4875 + N0 1.87966e-15 -1.16933e-15 1 N1 2.13636e-15 -5.93089e-16 1 N2 -0.849414 0.228972 0.475466 + txt003 +STRI + V0 1.19764 -0.703409 2.4875 V1 0.982824 -0.982824 2.4875 V2 0.996219 -0.996219 2.49844 + N0 -0.760669 0.441188 0.476167 N1 -0.621695 0.621695 0.476435 N2 1.4538e-15 -1.67359e-15 1 + txt003 +STRI + V0 0.996219 -0.996219 2.49844 V1 1.21396 -0.712995 2.49844 V2 1.19764 -0.703409 2.4875 + N0 1.4538e-15 -1.67359e-15 1 N1 1.87966e-15 -1.16933e-15 1 N2 -0.760669 0.441188 0.476167 + txt003 +STRI + V0 0.982824 -0.982824 2.4875 V1 0.703409 -1.19764 2.4875 V2 0.712995 -1.21396 2.49844 + N0 -0.621695 0.621695 0.476435 N1 -0.441188 0.760669 0.476167 N2 8.74229e-16 -2.05298e-15 1 + txt003 +STRI + V0 0.712995 -1.21396 2.49844 V1 0.996219 -0.996219 2.49844 V2 0.982824 -0.982824 2.4875 + N0 8.74229e-16 -2.05298e-15 1 N1 1.4538e-15 -1.67359e-15 1 N2 -0.621695 0.621695 0.476435 + txt003 +STRI + V0 0.703409 -1.19764 2.4875 V1 0.371699 -1.33555 2.4875 V2 0.376765 -1.35376 2.49844 + N0 -0.441188 0.760669 0.476167 N1 -0.228972 0.849414 0.475466 N2 1.77072e-16 -2.25214e-15 1 + txt003 +STRI + V0 0.376765 -1.35376 2.49844 V1 0.712995 -1.21396 2.49844 V2 0.703409 -1.19764 2.4875 + N0 1.77072e-16 -2.25214e-15 1 N1 8.74229e-16 -2.05298e-15 1 N2 -0.441188 0.760669 0.476167 + txt003 +STRI + V0 0.371699 -1.33555 2.4875 V1 0 -1.38426 2.4875 V2 0 -1.40312 2.49844 + N0 -0.228972 0.849414 0.475466 N1 -6.08179e-16 0.880022 0.474933 N2 -5.65179e-16 -2.22045e-15 1 + txt003 +STRI + V0 0 -1.40312 2.49844 V1 0.376765 -1.35376 2.49844 V2 0.371699 -1.33555 2.4875 + N0 -5.65179e-16 -2.22045e-15 1 N1 1.77072e-16 -2.25214e-15 1 N2 -0.228972 0.849414 0.475466 + txt003 +STRI + V0 1.40312 0 2.49844 V1 1.35376 -0.376765 2.49844 V2 1.38201 -0.384628 2.4875 + N0 2.22045e-15 0 1 N1 2.13636e-15 -5.93089e-16 1 N2 0.537012 -0.14476 0.831061 + txt003 +STRI + V0 1.38201 -0.384628 2.4875 V1 1.43241 0 2.4875 V2 1.40312 0 2.49844 + N0 0.537012 -0.14476 0.831061 N1 0.556738 0 0.830688 N2 2.22045e-15 0 1 + txt003 +STRI + V0 1.35376 -0.376765 2.49844 V1 1.21396 -0.712995 2.49844 V2 1.2393 -0.727875 2.4875 + N0 2.13636e-15 -5.93089e-16 1 N1 1.87966e-15 -1.16933e-15 1 N2 0.480481 -0.278679 0.83155 + txt003 +STRI + V0 1.2393 -0.727875 2.4875 V1 1.38201 -0.384628 2.4875 V2 1.35376 -0.376765 2.49844 + N0 0.480481 -0.278679 0.83155 N1 0.537012 -0.14476 0.831061 N2 2.13636e-15 -5.93089e-16 1 + txt003 +STRI + V0 1.21396 -0.712995 2.49844 V1 0.996219 -0.996219 2.49844 V2 1.01701 -1.01701 2.4875 + N0 1.87966e-15 -1.16933e-15 1 N1 1.4538e-15 -1.67359e-15 1 N2 0.392564 -0.392564 0.831737 + txt003 +STRI + V0 1.01701 -1.01701 2.4875 V1 1.2393 -0.727875 2.4875 V2 1.21396 -0.712995 2.49844 + N0 0.392564 -0.392564 0.831737 N1 0.480481 -0.278679 0.83155 N2 1.87966e-15 -1.16933e-15 1 + txt003 +STRI + V0 0.996219 -0.996219 2.49844 V1 0.712995 -1.21396 2.49844 V2 0.727875 -1.2393 2.4875 + N0 1.4538e-15 -1.67359e-15 1 N1 8.74229e-16 -2.05298e-15 1 N2 0.278679 -0.480481 0.83155 + txt003 +STRI + V0 0.727875 -1.2393 2.4875 V1 1.01701 -1.01701 2.4875 V2 0.996219 -0.996219 2.49844 + N0 0.278679 -0.480481 0.83155 N1 0.392564 -0.392564 0.831737 N2 1.4538e-15 -1.67359e-15 1 + txt003 +STRI + V0 0.712995 -1.21396 2.49844 V1 0.376765 -1.35376 2.49844 V2 0.384628 -1.38201 2.4875 + N0 8.74229e-16 -2.05298e-15 1 N1 1.77072e-16 -2.25214e-15 1 N2 0.14476 -0.537012 0.831061 + txt003 +STRI + V0 0.384628 -1.38201 2.4875 V1 0.727875 -1.2393 2.4875 V2 0.712995 -1.21396 2.49844 + N0 0.14476 -0.537012 0.831061 N1 0.278679 -0.480481 0.83155 N2 8.74229e-16 -2.05298e-15 1 + txt003 +STRI + V0 0.376765 -1.35376 2.49844 V1 0 -1.40312 2.49844 V2 0 -1.43241 2.4875 + N0 1.77072e-16 -2.25214e-15 1 N1 -5.65179e-16 -2.22045e-15 1 N2 -4.5989e-16 -0.556738 0.830688 + txt003 +STRI + V0 0 -1.43241 2.4875 V1 0.384628 -1.38201 2.4875 V2 0.376765 -1.35376 2.49844 + N0 -4.5989e-16 -0.556738 0.830688 N1 0.14476 -0.537012 0.831061 N2 1.77072e-16 -2.25214e-15 1 + txt003 +STRI + V0 1.43241 0 2.4875 V1 1.38201 -0.384628 2.4875 V2 1.41495 -0.393796 2.45469 + N0 0.556738 0 0.830688 N1 0.537012 -0.14476 0.831061 N2 0.755869 -0.203756 0.622211 + txt003 +STRI + V0 1.41495 -0.393796 2.45469 V1 1.46655 0 2.45469 V2 1.43241 0 2.4875 + N0 0.755869 -0.203756 0.622211 N1 0.783289 0 0.621658 N2 0.556738 0 0.830688 + txt003 +STRI + V0 1.38201 -0.384628 2.4875 V1 1.2393 -0.727875 2.4875 V2 1.26884 -0.745225 2.45469 + N0 0.537012 -0.14476 0.831061 N1 0.480481 -0.278679 0.83155 N2 0.67669 -0.39248 0.622937 + txt003 +STRI + V0 1.26884 -0.745225 2.45469 V1 1.41495 -0.393796 2.45469 V2 1.38201 -0.384628 2.4875 + N0 0.67669 -0.39248 0.622937 N1 0.755869 -0.203756 0.622211 N2 0.537012 -0.14476 0.831061 + txt003 +STRI + V0 1.2393 -0.727875 2.4875 V1 1.01701 -1.01701 2.4875 V2 1.04125 -1.04125 2.45469 + N0 0.480481 -0.278679 0.83155 N1 0.392564 -0.392564 0.831737 N2 0.552993 -0.552993 0.623215 + txt003 +STRI + V0 1.04125 -1.04125 2.45469 V1 1.26884 -0.745225 2.45469 V2 1.2393 -0.727875 2.4875 + N0 0.552993 -0.552993 0.623215 N1 0.67669 -0.39248 0.622937 N2 0.480481 -0.278679 0.83155 + txt003 +STRI + V0 1.01701 -1.01701 2.4875 V1 0.727875 -1.2393 2.4875 V2 0.745225 -1.26884 2.45469 + N0 0.392564 -0.392564 0.831737 N1 0.278679 -0.480481 0.83155 N2 0.39248 -0.67669 0.622937 + txt003 +STRI + V0 0.745225 -1.26884 2.45469 V1 1.04125 -1.04125 2.45469 V2 1.01701 -1.01701 2.4875 + N0 0.39248 -0.67669 0.622937 N1 0.552993 -0.552993 0.623215 N2 0.392564 -0.392564 0.831737 + txt003 +STRI + V0 0.727875 -1.2393 2.4875 V1 0.384628 -1.38201 2.4875 V2 0.393796 -1.41495 2.45469 + N0 0.278679 -0.480481 0.83155 N1 0.14476 -0.537012 0.831061 N2 0.203756 -0.755869 0.622211 + txt003 +STRI + V0 0.393796 -1.41495 2.45469 V1 0.745225 -1.26884 2.45469 V2 0.727875 -1.2393 2.4875 + N0 0.203756 -0.755869 0.622211 N1 0.39248 -0.67669 0.622937 N2 0.278679 -0.480481 0.83155 + txt003 +STRI + V0 0.384628 -1.38201 2.4875 V1 0 -1.43241 2.4875 V2 0 -1.46655 2.45469 + N0 0.14476 -0.537012 0.831061 N1 -4.5989e-16 -0.556738 0.830688 N2 -1.94969e-16 -0.783289 0.621658 + txt003 +STRI + V0 0 -1.46655 2.45469 V1 0.393796 -1.41495 2.45469 V2 0.384628 -1.38201 2.4875 + N0 -1.94969e-16 -0.783289 0.621658 N1 0.203756 -0.755869 0.622211 N2 0.14476 -0.537012 0.831061 + txt003 +STRI + V0 1.46655 0 2.45469 V1 1.41495 -0.393796 2.45469 V2 1.44722 -0.402778 2.4 + N0 0.783289 0 0.621658 N1 0.755869 -0.203756 0.622211 N2 0.871509 -0.234929 0.430442 + txt003 +STRI + V0 1.44722 -0.402778 2.4 V1 1.5 0 2.4 V2 1.46655 0 2.45469 + N0 0.871509 -0.234929 0.430442 N1 0.902861 0 0.429934 N2 0.783289 0 0.621658 + txt003 +STRI + V0 1.41495 -0.393796 2.45469 V1 1.26884 -0.745225 2.45469 V2 1.29778 -0.762222 2.4 + N0 0.755869 -0.203756 0.622211 N1 0.67669 -0.39248 0.622937 N2 0.780517 -0.4527 0.43111 + txt003 +STRI + V0 1.29778 -0.762222 2.4 V1 1.44722 -0.402778 2.4 V2 1.41495 -0.393796 2.45469 + N0 0.780517 -0.4527 0.43111 N1 0.871509 -0.234929 0.430442 N2 0.755869 -0.203756 0.622211 + txt003 +STRI + V0 1.26884 -0.745225 2.45469 V1 1.04125 -1.04125 2.45469 V2 1.065 -1.065 2.4 + N0 0.67669 -0.39248 0.622937 N1 0.552993 -0.552993 0.623215 N2 0.637936 -0.637936 0.431366 + txt003 +STRI + V0 1.065 -1.065 2.4 V1 1.29778 -0.762222 2.4 V2 1.26884 -0.745225 2.45469 + N0 0.637936 -0.637936 0.431366 N1 0.780517 -0.4527 0.43111 N2 0.67669 -0.39248 0.622937 + txt003 +STRI + V0 1.04125 -1.04125 2.45469 V1 0.745225 -1.26884 2.45469 V2 0.762222 -1.29778 2.4 + N0 0.552993 -0.552993 0.623215 N1 0.39248 -0.67669 0.622937 N2 0.4527 -0.780517 0.43111 + txt003 +STRI + V0 0.762222 -1.29778 2.4 V1 1.065 -1.065 2.4 V2 1.04125 -1.04125 2.45469 + N0 0.4527 -0.780517 0.43111 N1 0.637936 -0.637936 0.431366 N2 0.552993 -0.552993 0.623215 + txt003 +STRI + V0 0.745225 -1.26884 2.45469 V1 0.393796 -1.41495 2.45469 V2 0.402778 -1.44722 2.4 + N0 0.39248 -0.67669 0.622937 N1 0.203756 -0.755869 0.622211 N2 0.234929 -0.871509 0.430442 + txt003 +STRI + V0 0.402778 -1.44722 2.4 V1 0.762222 -1.29778 2.4 V2 0.745225 -1.26884 2.45469 + N0 0.234929 -0.871509 0.430442 N1 0.4527 -0.780517 0.43111 N2 0.39248 -0.67669 0.622937 + txt003 +STRI + V0 0.393796 -1.41495 2.45469 V1 0 -1.46655 2.45469 V2 0 -1.5 2.4 + N0 0.203756 -0.755869 0.622211 N1 -1.94969e-16 -0.783289 0.621658 N2 -6.81889e-17 -0.902861 0.429934 + txt003 +STRI + V0 0 -1.5 2.4 V1 0.402778 -1.44722 2.4 V2 0.393796 -1.41495 2.45469 + N0 -6.81889e-17 -0.902861 0.429934 N1 0.234929 -0.871509 0.430442 N2 0.203756 -0.755869 0.622211 + txt003 +STRI + V0 0 -1.4 2.4 V1 -0.375926 -1.35074 2.4 V2 -0.370922 -1.33276 2.45469 + N0 0 0.902861 -0.429934 N1 0.234929 0.871509 -0.430442 N2 0.257047 0.953562 -0.156989 + txt003 +STRI + V0 -0.370922 -1.33276 2.45469 V1 0 -1.38137 2.45469 V2 0 -1.4 2.4 + N0 0.257047 0.953562 -0.156989 N1 0 0.987636 -0.156768 N2 0 0.902861 -0.429934 + txt003 +STRI + V0 -0.375926 -1.35074 2.4 V1 -0.711407 -1.21126 2.4 V2 -0.701938 -1.19514 2.45469 + N0 0.234929 0.871509 -0.430442 N1 0.4527 0.780517 -0.43111 N2 0.495474 0.854265 -0.157281 + txt003 +STRI + V0 -0.701938 -1.19514 2.45469 V1 -0.370922 -1.33276 2.45469 V2 -0.375926 -1.35074 2.4 + N0 0.495474 0.854265 -0.157281 N1 0.257047 0.953562 -0.156989 N2 0.234929 0.871509 -0.430442 + txt003 +STRI + V0 -0.711407 -1.21126 2.4 V1 -0.994 -0.994 2.4 V2 -0.98077 -0.98077 2.45469 + N0 0.4527 0.780517 -0.43111 N1 0.637936 0.637936 -0.431366 N2 0.698293 0.698293 -0.157393 + txt003 +STRI + V0 -0.98077 -0.98077 2.45469 V1 -0.701938 -1.19514 2.45469 V2 -0.711407 -1.21126 2.4 + N0 0.698293 0.698293 -0.157393 N1 0.495474 0.854265 -0.157281 N2 0.4527 0.780517 -0.43111 + txt003 +STRI + V0 -0.994 -0.994 2.4 V1 -1.21126 -0.711407 2.4 V2 -1.19514 -0.701938 2.45469 + N0 0.637936 0.637936 -0.431366 N1 0.780517 0.4527 -0.43111 N2 0.854265 0.495474 -0.157281 + txt003 +STRI + V0 -1.19514 -0.701938 2.45469 V1 -0.98077 -0.98077 2.45469 V2 -0.994 -0.994 2.4 + N0 0.854265 0.495474 -0.157281 N1 0.698293 0.698293 -0.157393 N2 0.637936 0.637936 -0.431366 + txt003 +STRI + V0 -1.21126 -0.711407 2.4 V1 -1.35074 -0.375926 2.4 V2 -1.33276 -0.370922 2.45469 + N0 0.780517 0.4527 -0.43111 N1 0.871509 0.234929 -0.430442 N2 0.953562 0.257047 -0.156989 + txt003 +STRI + V0 -1.33276 -0.370922 2.45469 V1 -1.19514 -0.701938 2.45469 V2 -1.21126 -0.711407 2.4 + N0 0.953562 0.257047 -0.156989 N1 0.854265 0.495474 -0.157281 N2 0.780517 0.4527 -0.43111 + txt003 +STRI + V0 -1.35074 -0.375926 2.4 V1 -1.4 0 2.4 V2 -1.38137 0 2.45469 + N0 0.871509 0.234929 -0.430442 N1 0.902861 -7.30595e-17 -0.429934 N2 0.987636 9.89971e-17 -0.156768 + txt003 +STRI + V0 -1.38137 0 2.45469 V1 -1.33276 -0.370922 2.45469 V2 -1.35074 -0.375926 2.4 + N0 0.987636 9.89971e-17 -0.156768 N1 0.953562 0.257047 -0.156989 N2 0.871509 0.234929 -0.430442 + txt003 +STRI + V0 0 -1.38137 2.45469 V1 -0.370922 -1.33276 2.45469 V2 -0.371699 -1.33555 2.4875 + N0 0 0.987636 -0.156768 N1 0.257047 0.953562 -0.156989 N2 0.228972 0.849414 0.475466 + txt003 +STRI + V0 -0.371699 -1.33555 2.4875 V1 0 -1.38426 2.4875 V2 0 -1.38137 2.45469 + N0 0.228972 0.849414 0.475466 N1 0 0.880022 0.474933 N2 0 0.987636 -0.156768 + txt003 +STRI + V0 -0.370922 -1.33276 2.45469 V1 -0.701938 -1.19514 2.45469 V2 -0.703409 -1.19764 2.4875 + N0 0.257047 0.953562 -0.156989 N1 0.495474 0.854265 -0.157281 N2 0.441188 0.760669 0.476167 + txt003 +STRI + V0 -0.703409 -1.19764 2.4875 V1 -0.371699 -1.33555 2.4875 V2 -0.370922 -1.33276 2.45469 + N0 0.441188 0.760669 0.476167 N1 0.228972 0.849414 0.475466 N2 0.257047 0.953562 -0.156989 + txt003 +STRI + V0 -0.701938 -1.19514 2.45469 V1 -0.98077 -0.98077 2.45469 V2 -0.982824 -0.982824 2.4875 + N0 0.495474 0.854265 -0.157281 N1 0.698293 0.698293 -0.157393 N2 0.621695 0.621695 0.476435 + txt003 +STRI + V0 -0.982824 -0.982824 2.4875 V1 -0.703409 -1.19764 2.4875 V2 -0.701938 -1.19514 2.45469 + N0 0.621695 0.621695 0.476435 N1 0.441188 0.760669 0.476167 N2 0.495474 0.854265 -0.157281 + txt003 +STRI + V0 -0.98077 -0.98077 2.45469 V1 -1.19514 -0.701938 2.45469 V2 -1.19764 -0.703409 2.4875 + N0 0.698293 0.698293 -0.157393 N1 0.854265 0.495474 -0.157281 N2 0.760669 0.441188 0.476167 + txt003 +STRI + V0 -1.19764 -0.703409 2.4875 V1 -0.982824 -0.982824 2.4875 V2 -0.98077 -0.98077 2.45469 + N0 0.760669 0.441188 0.476167 N1 0.621695 0.621695 0.476435 N2 0.698293 0.698293 -0.157393 + txt003 +STRI + V0 -1.19514 -0.701938 2.45469 V1 -1.33276 -0.370922 2.45469 V2 -1.33555 -0.371699 2.4875 + N0 0.854265 0.495474 -0.157281 N1 0.953562 0.257047 -0.156989 N2 0.849414 0.228972 0.475466 + txt003 +STRI + V0 -1.33555 -0.371699 2.4875 V1 -1.19764 -0.703409 2.4875 V2 -1.19514 -0.701938 2.45469 + N0 0.849414 0.228972 0.475466 N1 0.760669 0.441188 0.476167 N2 0.854265 0.495474 -0.157281 + txt003 +STRI + V0 -1.33276 -0.370922 2.45469 V1 -1.38137 0 2.45469 V2 -1.38426 0 2.4875 + N0 0.953562 0.257047 -0.156989 N1 0.987636 9.89971e-17 -0.156768 N2 0.880022 6.08179e-16 0.474933 + txt003 +STRI + V0 -1.38426 0 2.4875 V1 -1.33555 -0.371699 2.4875 V2 -1.33276 -0.370922 2.45469 + N0 0.880022 6.08179e-16 0.474933 N1 0.849414 0.228972 0.475466 N2 0.953562 0.257047 -0.156989 + txt003 +STRI + V0 0 -1.38426 2.4875 V1 -0.371699 -1.33555 2.4875 V2 -0.376765 -1.35376 2.49844 + N0 0 0.880022 0.474933 N1 0.228972 0.849414 0.475466 N2 -5.93089e-16 -2.13636e-15 1 + txt003 +STRI + V0 -0.376765 -1.35376 2.49844 V1 0 -1.40312 2.49844 V2 0 -1.38426 2.4875 + N0 -5.93089e-16 -2.13636e-15 1 N1 0 -2.22045e-15 1 N2 0 0.880022 0.474933 + txt003 +STRI + V0 -0.371699 -1.33555 2.4875 V1 -0.703409 -1.19764 2.4875 V2 -0.712995 -1.21396 2.49844 + N0 0.228972 0.849414 0.475466 N1 0.441188 0.760669 0.476167 N2 -1.16933e-15 -1.87966e-15 1 + txt003 +STRI + V0 -0.712995 -1.21396 2.49844 V1 -0.376765 -1.35376 2.49844 V2 -0.371699 -1.33555 2.4875 + N0 -1.16933e-15 -1.87966e-15 1 N1 -5.93089e-16 -2.13636e-15 1 N2 0.228972 0.849414 0.475466 + txt003 +STRI + V0 -0.703409 -1.19764 2.4875 V1 -0.982824 -0.982824 2.4875 V2 -0.996219 -0.996219 2.49844 + N0 0.441188 0.760669 0.476167 N1 0.621695 0.621695 0.476435 N2 -1.67359e-15 -1.4538e-15 1 + txt003 +STRI + V0 -0.996219 -0.996219 2.49844 V1 -0.712995 -1.21396 2.49844 V2 -0.703409 -1.19764 2.4875 + N0 -1.67359e-15 -1.4538e-15 1 N1 -1.16933e-15 -1.87966e-15 1 N2 0.441188 0.760669 0.476167 + txt003 +STRI + V0 -0.982824 -0.982824 2.4875 V1 -1.19764 -0.703409 2.4875 V2 -1.21396 -0.712995 2.49844 + N0 0.621695 0.621695 0.476435 N1 0.760669 0.441188 0.476167 N2 -2.05298e-15 -8.74229e-16 1 + txt003 +STRI + V0 -1.21396 -0.712995 2.49844 V1 -0.996219 -0.996219 2.49844 V2 -0.982824 -0.982824 2.4875 + N0 -2.05298e-15 -8.74229e-16 1 N1 -1.67359e-15 -1.4538e-15 1 N2 0.621695 0.621695 0.476435 + txt003 +STRI + V0 -1.19764 -0.703409 2.4875 V1 -1.33555 -0.371699 2.4875 V2 -1.35376 -0.376765 2.49844 + N0 0.760669 0.441188 0.476167 N1 0.849414 0.228972 0.475466 N2 -2.25214e-15 -1.77072e-16 1 + txt003 +STRI + V0 -1.35376 -0.376765 2.49844 V1 -1.21396 -0.712995 2.49844 V2 -1.19764 -0.703409 2.4875 + N0 -2.25214e-15 -1.77072e-16 1 N1 -2.05298e-15 -8.74229e-16 1 N2 0.760669 0.441188 0.476167 + txt003 +STRI + V0 -1.33555 -0.371699 2.4875 V1 -1.38426 0 2.4875 V2 -1.40312 0 2.49844 + N0 0.849414 0.228972 0.475466 N1 0.880022 6.08179e-16 0.474933 N2 -2.22045e-15 5.65179e-16 1 + txt003 +STRI + V0 -1.40312 0 2.49844 V1 -1.35376 -0.376765 2.49844 V2 -1.33555 -0.371699 2.4875 + N0 -2.22045e-15 5.65179e-16 1 N1 -2.25214e-15 -1.77072e-16 1 N2 0.849414 0.228972 0.475466 + txt003 +STRI + V0 0 -1.40312 2.49844 V1 -0.376765 -1.35376 2.49844 V2 -0.384628 -1.38201 2.4875 + N0 0 -2.22045e-15 1 N1 -5.93089e-16 -2.13636e-15 1 N2 -0.14476 -0.537012 0.831061 + txt003 +STRI + V0 -0.384628 -1.38201 2.4875 V1 0 -1.43241 2.4875 V2 0 -1.40312 2.49844 + N0 -0.14476 -0.537012 0.831061 N1 0 -0.556738 0.830688 N2 0 -2.22045e-15 1 + txt003 +STRI + V0 -0.376765 -1.35376 2.49844 V1 -0.712995 -1.21396 2.49844 V2 -0.727875 -1.2393 2.4875 + N0 -5.93089e-16 -2.13636e-15 1 N1 -1.16933e-15 -1.87966e-15 1 N2 -0.278679 -0.480481 0.83155 + txt003 +STRI + V0 -0.727875 -1.2393 2.4875 V1 -0.384628 -1.38201 2.4875 V2 -0.376765 -1.35376 2.49844 + N0 -0.278679 -0.480481 0.83155 N1 -0.14476 -0.537012 0.831061 N2 -5.93089e-16 -2.13636e-15 1 + txt003 +STRI + V0 -0.712995 -1.21396 2.49844 V1 -0.996219 -0.996219 2.49844 V2 -1.01701 -1.01701 2.4875 + N0 -1.16933e-15 -1.87966e-15 1 N1 -1.67359e-15 -1.4538e-15 1 N2 -0.392564 -0.392564 0.831737 + txt003 +STRI + V0 -1.01701 -1.01701 2.4875 V1 -0.727875 -1.2393 2.4875 V2 -0.712995 -1.21396 2.49844 + N0 -0.392564 -0.392564 0.831737 N1 -0.278679 -0.480481 0.83155 N2 -1.16933e-15 -1.87966e-15 1 + txt003 +STRI + V0 -0.996219 -0.996219 2.49844 V1 -1.21396 -0.712995 2.49844 V2 -1.2393 -0.727875 2.4875 + N0 -1.67359e-15 -1.4538e-15 1 N1 -2.05298e-15 -8.74229e-16 1 N2 -0.480481 -0.278679 0.83155 + txt003 +STRI + V0 -1.2393 -0.727875 2.4875 V1 -1.01701 -1.01701 2.4875 V2 -0.996219 -0.996219 2.49844 + N0 -0.480481 -0.278679 0.83155 N1 -0.392564 -0.392564 0.831737 N2 -1.67359e-15 -1.4538e-15 1 + txt003 +STRI + V0 -1.21396 -0.712995 2.49844 V1 -1.35376 -0.376765 2.49844 V2 -1.38201 -0.384628 2.4875 + N0 -2.05298e-15 -8.74229e-16 1 N1 -2.25214e-15 -1.77072e-16 1 N2 -0.537012 -0.14476 0.831061 + txt003 +STRI + V0 -1.38201 -0.384628 2.4875 V1 -1.2393 -0.727875 2.4875 V2 -1.21396 -0.712995 2.49844 + N0 -0.537012 -0.14476 0.831061 N1 -0.480481 -0.278679 0.83155 N2 -2.05298e-15 -8.74229e-16 1 + txt003 +STRI + V0 -1.35376 -0.376765 2.49844 V1 -1.40312 0 2.49844 V2 -1.43241 0 2.4875 + N0 -2.25214e-15 -1.77072e-16 1 N1 -2.22045e-15 5.65179e-16 1 N2 -0.556738 4.5989e-16 0.830688 + txt003 +STRI + V0 -1.43241 0 2.4875 V1 -1.38201 -0.384628 2.4875 V2 -1.35376 -0.376765 2.49844 + N0 -0.556738 4.5989e-16 0.830688 N1 -0.537012 -0.14476 0.831061 N2 -2.25214e-15 -1.77072e-16 1 + txt003 +STRI + V0 0 -1.43241 2.4875 V1 -0.384628 -1.38201 2.4875 V2 -0.393796 -1.41495 2.45469 + N0 0 -0.556738 0.830688 N1 -0.14476 -0.537012 0.831061 N2 -0.203756 -0.755869 0.622211 + txt003 +STRI + V0 -0.393796 -1.41495 2.45469 V1 0 -1.46655 2.45469 V2 0 -1.43241 2.4875 + N0 -0.203756 -0.755869 0.622211 N1 0 -0.783289 0.621658 N2 0 -0.556738 0.830688 + txt003 +STRI + V0 -0.384628 -1.38201 2.4875 V1 -0.727875 -1.2393 2.4875 V2 -0.745225 -1.26884 2.45469 + N0 -0.14476 -0.537012 0.831061 N1 -0.278679 -0.480481 0.83155 N2 -0.39248 -0.67669 0.622937 + txt003 +STRI + V0 -0.745225 -1.26884 2.45469 V1 -0.393796 -1.41495 2.45469 V2 -0.384628 -1.38201 2.4875 + N0 -0.39248 -0.67669 0.622937 N1 -0.203756 -0.755869 0.622211 N2 -0.14476 -0.537012 0.831061 + txt003 +STRI + V0 -0.727875 -1.2393 2.4875 V1 -1.01701 -1.01701 2.4875 V2 -1.04125 -1.04125 2.45469 + N0 -0.278679 -0.480481 0.83155 N1 -0.392564 -0.392564 0.831737 N2 -0.552993 -0.552993 0.623215 + txt003 +STRI + V0 -1.04125 -1.04125 2.45469 V1 -0.745225 -1.26884 2.45469 V2 -0.727875 -1.2393 2.4875 + N0 -0.552993 -0.552993 0.623215 N1 -0.39248 -0.67669 0.622937 N2 -0.278679 -0.480481 0.83155 + txt003 +STRI + V0 -1.01701 -1.01701 2.4875 V1 -1.2393 -0.727875 2.4875 V2 -1.26884 -0.745225 2.45469 + N0 -0.392564 -0.392564 0.831737 N1 -0.480481 -0.278679 0.83155 N2 -0.67669 -0.39248 0.622937 + txt003 +STRI + V0 -1.26884 -0.745225 2.45469 V1 -1.04125 -1.04125 2.45469 V2 -1.01701 -1.01701 2.4875 + N0 -0.67669 -0.39248 0.622937 N1 -0.552993 -0.552993 0.623215 N2 -0.392564 -0.392564 0.831737 + txt003 +STRI + V0 -1.2393 -0.727875 2.4875 V1 -1.38201 -0.384628 2.4875 V2 -1.41495 -0.393796 2.45469 + N0 -0.480481 -0.278679 0.83155 N1 -0.537012 -0.14476 0.831061 N2 -0.755869 -0.203756 0.622211 + txt003 +STRI + V0 -1.41495 -0.393796 2.45469 V1 -1.26884 -0.745225 2.45469 V2 -1.2393 -0.727875 2.4875 + N0 -0.755869 -0.203756 0.622211 N1 -0.67669 -0.39248 0.622937 N2 -0.480481 -0.278679 0.83155 + txt003 +STRI + V0 -1.38201 -0.384628 2.4875 V1 -1.43241 0 2.4875 V2 -1.46655 0 2.45469 + N0 -0.537012 -0.14476 0.831061 N1 -0.556738 4.5989e-16 0.830688 N2 -0.783289 1.94969e-16 0.621658 + txt003 +STRI + V0 -1.46655 0 2.45469 V1 -1.41495 -0.393796 2.45469 V2 -1.38201 -0.384628 2.4875 + N0 -0.783289 1.94969e-16 0.621658 N1 -0.755869 -0.203756 0.622211 N2 -0.537012 -0.14476 0.831061 + txt003 +STRI + V0 0 -1.46655 2.45469 V1 -0.393796 -1.41495 2.45469 V2 -0.402778 -1.44722 2.4 + N0 0 -0.783289 0.621658 N1 -0.203756 -0.755869 0.622211 N2 -0.234929 -0.871509 0.430442 + txt003 +STRI + V0 -0.402778 -1.44722 2.4 V1 0 -1.5 2.4 V2 0 -1.46655 2.45469 + N0 -0.234929 -0.871509 0.430442 N1 0 -0.902861 0.429934 N2 0 -0.783289 0.621658 + txt003 +STRI + V0 -0.393796 -1.41495 2.45469 V1 -0.745225 -1.26884 2.45469 V2 -0.762222 -1.29778 2.4 + N0 -0.203756 -0.755869 0.622211 N1 -0.39248 -0.67669 0.622937 N2 -0.4527 -0.780517 0.43111 + txt003 +STRI + V0 -0.762222 -1.29778 2.4 V1 -0.402778 -1.44722 2.4 V2 -0.393796 -1.41495 2.45469 + N0 -0.4527 -0.780517 0.43111 N1 -0.234929 -0.871509 0.430442 N2 -0.203756 -0.755869 0.622211 + txt003 +STRI + V0 -0.745225 -1.26884 2.45469 V1 -1.04125 -1.04125 2.45469 V2 -1.065 -1.065 2.4 + N0 -0.39248 -0.67669 0.622937 N1 -0.552993 -0.552993 0.623215 N2 -0.637936 -0.637936 0.431366 + txt003 +STRI + V0 -1.065 -1.065 2.4 V1 -0.762222 -1.29778 2.4 V2 -0.745225 -1.26884 2.45469 + N0 -0.637936 -0.637936 0.431366 N1 -0.4527 -0.780517 0.43111 N2 -0.39248 -0.67669 0.622937 + txt003 +STRI + V0 -1.04125 -1.04125 2.45469 V1 -1.26884 -0.745225 2.45469 V2 -1.29778 -0.762222 2.4 + N0 -0.552993 -0.552993 0.623215 N1 -0.67669 -0.39248 0.622937 N2 -0.780517 -0.4527 0.43111 + txt003 +STRI + V0 -1.29778 -0.762222 2.4 V1 -1.065 -1.065 2.4 V2 -1.04125 -1.04125 2.45469 + N0 -0.780517 -0.4527 0.43111 N1 -0.637936 -0.637936 0.431366 N2 -0.552993 -0.552993 0.623215 + txt003 +STRI + V0 -1.26884 -0.745225 2.45469 V1 -1.41495 -0.393796 2.45469 V2 -1.44722 -0.402778 2.4 + N0 -0.67669 -0.39248 0.622937 N1 -0.755869 -0.203756 0.622211 N2 -0.871509 -0.234929 0.430442 + txt003 +STRI + V0 -1.44722 -0.402778 2.4 V1 -1.29778 -0.762222 2.4 V2 -1.26884 -0.745225 2.45469 + N0 -0.871509 -0.234929 0.430442 N1 -0.780517 -0.4527 0.43111 N2 -0.67669 -0.39248 0.622937 + txt003 +STRI + V0 -1.41495 -0.393796 2.45469 V1 -1.46655 0 2.45469 V2 -1.5 0 2.4 + N0 -0.755869 -0.203756 0.622211 N1 -0.783289 1.94969e-16 0.621658 N2 -0.902861 6.81889e-17 0.429934 + txt003 +STRI + V0 -1.5 0 2.4 V1 -1.44722 -0.402778 2.4 V2 -1.41495 -0.393796 2.45469 + N0 -0.902861 6.81889e-17 0.429934 N1 -0.871509 -0.234929 0.430442 N2 -0.755869 -0.203756 0.622211 + txt003 +STRI + V0 -1.4 0 2.4 V1 -1.35074 0.375926 2.4 V2 -1.33276 0.370922 2.45469 + N0 0.902861 0 -0.429934 N1 0.871509 -0.234929 -0.430442 N2 0.953562 -0.257047 -0.156989 + txt003 +STRI + V0 -1.33276 0.370922 2.45469 V1 -1.38137 0 2.45469 V2 -1.4 0 2.4 + N0 0.953562 -0.257047 -0.156989 N1 0.987636 0 -0.156768 N2 0.902861 0 -0.429934 + txt003 +STRI + V0 -1.35074 0.375926 2.4 V1 -1.21126 0.711407 2.4 V2 -1.19514 0.701938 2.45469 + N0 0.871509 -0.234929 -0.430442 N1 0.780517 -0.4527 -0.43111 N2 0.854265 -0.495474 -0.157281 + txt003 +STRI + V0 -1.19514 0.701938 2.45469 V1 -1.33276 0.370922 2.45469 V2 -1.35074 0.375926 2.4 + N0 0.854265 -0.495474 -0.157281 N1 0.953562 -0.257047 -0.156989 N2 0.871509 -0.234929 -0.430442 + txt003 +STRI + V0 -1.21126 0.711407 2.4 V1 -0.994 0.994 2.4 V2 -0.98077 0.98077 2.45469 + N0 0.780517 -0.4527 -0.43111 N1 0.637936 -0.637936 -0.431366 N2 0.698293 -0.698293 -0.157393 + txt003 +STRI + V0 -0.98077 0.98077 2.45469 V1 -1.19514 0.701938 2.45469 V2 -1.21126 0.711407 2.4 + N0 0.698293 -0.698293 -0.157393 N1 0.854265 -0.495474 -0.157281 N2 0.780517 -0.4527 -0.43111 + txt003 +STRI + V0 -0.994 0.994 2.4 V1 -0.711407 1.21126 2.4 V2 -0.701938 1.19514 2.45469 + N0 0.637936 -0.637936 -0.431366 N1 0.4527 -0.780517 -0.43111 N2 0.495474 -0.854265 -0.157281 + txt003 +STRI + V0 -0.701938 1.19514 2.45469 V1 -0.98077 0.98077 2.45469 V2 -0.994 0.994 2.4 + N0 0.495474 -0.854265 -0.157281 N1 0.698293 -0.698293 -0.157393 N2 0.637936 -0.637936 -0.431366 + txt003 +STRI + V0 -0.711407 1.21126 2.4 V1 -0.375926 1.35074 2.4 V2 -0.370922 1.33276 2.45469 + N0 0.4527 -0.780517 -0.43111 N1 0.234929 -0.871509 -0.430442 N2 0.257047 -0.953562 -0.156989 + txt003 +STRI + V0 -0.370922 1.33276 2.45469 V1 -0.701938 1.19514 2.45469 V2 -0.711407 1.21126 2.4 + N0 0.257047 -0.953562 -0.156989 N1 0.495474 -0.854265 -0.157281 N2 0.4527 -0.780517 -0.43111 + txt003 +STRI + V0 -0.375926 1.35074 2.4 V1 0 1.4 2.4 V2 0 1.38137 2.45469 + N0 0.234929 -0.871509 -0.430442 N1 -7.30595e-17 -0.902861 -0.429934 N2 9.89971e-17 -0.987636 -0.156768 + txt003 +STRI + V0 0 1.38137 2.45469 V1 -0.370922 1.33276 2.45469 V2 -0.375926 1.35074 2.4 + N0 9.89971e-17 -0.987636 -0.156768 N1 0.257047 -0.953562 -0.156989 N2 0.234929 -0.871509 -0.430442 + txt003 +STRI + V0 -1.38137 0 2.45469 V1 -1.33276 0.370922 2.45469 V2 -1.33555 0.371699 2.4875 + N0 0.987636 0 -0.156768 N1 0.953562 -0.257047 -0.156989 N2 0.849414 -0.228972 0.475466 + txt003 +STRI + V0 -1.33555 0.371699 2.4875 V1 -1.38426 0 2.4875 V2 -1.38137 0 2.45469 + N0 0.849414 -0.228972 0.475466 N1 0.880022 -0 0.474933 N2 0.987636 0 -0.156768 + txt003 +STRI + V0 -1.33276 0.370922 2.45469 V1 -1.19514 0.701938 2.45469 V2 -1.19764 0.703409 2.4875 + N0 0.953562 -0.257047 -0.156989 N1 0.854265 -0.495474 -0.157281 N2 0.760669 -0.441188 0.476167 + txt003 +STRI + V0 -1.19764 0.703409 2.4875 V1 -1.33555 0.371699 2.4875 V2 -1.33276 0.370922 2.45469 + N0 0.760669 -0.441188 0.476167 N1 0.849414 -0.228972 0.475466 N2 0.953562 -0.257047 -0.156989 + txt003 +STRI + V0 -1.19514 0.701938 2.45469 V1 -0.98077 0.98077 2.45469 V2 -0.982824 0.982824 2.4875 + N0 0.854265 -0.495474 -0.157281 N1 0.698293 -0.698293 -0.157393 N2 0.621695 -0.621695 0.476435 + txt003 +STRI + V0 -0.982824 0.982824 2.4875 V1 -1.19764 0.703409 2.4875 V2 -1.19514 0.701938 2.45469 + N0 0.621695 -0.621695 0.476435 N1 0.760669 -0.441188 0.476167 N2 0.854265 -0.495474 -0.157281 + txt003 +STRI + V0 -0.98077 0.98077 2.45469 V1 -0.701938 1.19514 2.45469 V2 -0.703409 1.19764 2.4875 + N0 0.698293 -0.698293 -0.157393 N1 0.495474 -0.854265 -0.157281 N2 0.441188 -0.760669 0.476167 + txt003 +STRI + V0 -0.703409 1.19764 2.4875 V1 -0.982824 0.982824 2.4875 V2 -0.98077 0.98077 2.45469 + N0 0.441188 -0.760669 0.476167 N1 0.621695 -0.621695 0.476435 N2 0.698293 -0.698293 -0.157393 + txt003 +STRI + V0 -0.701938 1.19514 2.45469 V1 -0.370922 1.33276 2.45469 V2 -0.371699 1.33555 2.4875 + N0 0.495474 -0.854265 -0.157281 N1 0.257047 -0.953562 -0.156989 N2 0.228972 -0.849414 0.475466 + txt003 +STRI + V0 -0.371699 1.33555 2.4875 V1 -0.703409 1.19764 2.4875 V2 -0.701938 1.19514 2.45469 + N0 0.228972 -0.849414 0.475466 N1 0.441188 -0.760669 0.476167 N2 0.495474 -0.854265 -0.157281 + txt003 +STRI + V0 -0.370922 1.33276 2.45469 V1 0 1.38137 2.45469 V2 0 1.38426 2.4875 + N0 0.257047 -0.953562 -0.156989 N1 9.89971e-17 -0.987636 -0.156768 N2 6.08179e-16 -0.880022 0.474933 + txt003 +STRI + V0 0 1.38426 2.4875 V1 -0.371699 1.33555 2.4875 V2 -0.370922 1.33276 2.45469 + N0 6.08179e-16 -0.880022 0.474933 N1 0.228972 -0.849414 0.475466 N2 0.257047 -0.953562 -0.156989 + txt003 +STRI + V0 -1.38426 0 2.4875 V1 -1.33555 0.371699 2.4875 V2 -1.35376 0.376765 2.49844 + N0 0.880022 -0 0.474933 N1 0.849414 -0.228972 0.475466 N2 -2.13636e-15 5.93089e-16 1 + txt003 +STRI + V0 -1.35376 0.376765 2.49844 V1 -1.40312 0 2.49844 V2 -1.38426 0 2.4875 + N0 -2.13636e-15 5.93089e-16 1 N1 -2.22045e-15 0 1 N2 0.880022 -0 0.474933 + txt003 +STRI + V0 -1.33555 0.371699 2.4875 V1 -1.19764 0.703409 2.4875 V2 -1.21396 0.712995 2.49844 + N0 0.849414 -0.228972 0.475466 N1 0.760669 -0.441188 0.476167 N2 -1.87966e-15 1.16933e-15 1 + txt003 +STRI + V0 -1.21396 0.712995 2.49844 V1 -1.35376 0.376765 2.49844 V2 -1.33555 0.371699 2.4875 + N0 -1.87966e-15 1.16933e-15 1 N1 -2.13636e-15 5.93089e-16 1 N2 0.849414 -0.228972 0.475466 + txt003 +STRI + V0 -1.19764 0.703409 2.4875 V1 -0.982824 0.982824 2.4875 V2 -0.996219 0.996219 2.49844 + N0 0.760669 -0.441188 0.476167 N1 0.621695 -0.621695 0.476435 N2 -1.4538e-15 1.67359e-15 1 + txt003 +STRI + V0 -0.996219 0.996219 2.49844 V1 -1.21396 0.712995 2.49844 V2 -1.19764 0.703409 2.4875 + N0 -1.4538e-15 1.67359e-15 1 N1 -1.87966e-15 1.16933e-15 1 N2 0.760669 -0.441188 0.476167 + txt003 +STRI + V0 -0.982824 0.982824 2.4875 V1 -0.703409 1.19764 2.4875 V2 -0.712995 1.21396 2.49844 + N0 0.621695 -0.621695 0.476435 N1 0.441188 -0.760669 0.476167 N2 -8.74229e-16 2.05298e-15 1 + txt003 +STRI + V0 -0.712995 1.21396 2.49844 V1 -0.996219 0.996219 2.49844 V2 -0.982824 0.982824 2.4875 + N0 -8.74229e-16 2.05298e-15 1 N1 -1.4538e-15 1.67359e-15 1 N2 0.621695 -0.621695 0.476435 + txt003 +STRI + V0 -0.703409 1.19764 2.4875 V1 -0.371699 1.33555 2.4875 V2 -0.376765 1.35376 2.49844 + N0 0.441188 -0.760669 0.476167 N1 0.228972 -0.849414 0.475466 N2 -1.77072e-16 2.25214e-15 1 + txt003 +STRI + V0 -0.376765 1.35376 2.49844 V1 -0.712995 1.21396 2.49844 V2 -0.703409 1.19764 2.4875 + N0 -1.77072e-16 2.25214e-15 1 N1 -8.74229e-16 2.05298e-15 1 N2 0.441188 -0.760669 0.476167 + txt003 +STRI + V0 -0.371699 1.33555 2.4875 V1 0 1.38426 2.4875 V2 0 1.40312 2.49844 + N0 0.228972 -0.849414 0.475466 N1 6.08179e-16 -0.880022 0.474933 N2 5.65179e-16 2.22045e-15 1 + txt003 +STRI + V0 0 1.40312 2.49844 V1 -0.376765 1.35376 2.49844 V2 -0.371699 1.33555 2.4875 + N0 5.65179e-16 2.22045e-15 1 N1 -1.77072e-16 2.25214e-15 1 N2 0.228972 -0.849414 0.475466 + txt003 +STRI + V0 -1.40312 0 2.49844 V1 -1.35376 0.376765 2.49844 V2 -1.38201 0.384628 2.4875 + N0 -2.22045e-15 0 1 N1 -2.13636e-15 5.93089e-16 1 N2 -0.537012 0.14476 0.831061 + txt003 +STRI + V0 -1.38201 0.384628 2.4875 V1 -1.43241 0 2.4875 V2 -1.40312 0 2.49844 + N0 -0.537012 0.14476 0.831061 N1 -0.556738 0 0.830688 N2 -2.22045e-15 0 1 + txt003 +STRI + V0 -1.35376 0.376765 2.49844 V1 -1.21396 0.712995 2.49844 V2 -1.2393 0.727875 2.4875 + N0 -2.13636e-15 5.93089e-16 1 N1 -1.87966e-15 1.16933e-15 1 N2 -0.480481 0.278679 0.83155 + txt003 +STRI + V0 -1.2393 0.727875 2.4875 V1 -1.38201 0.384628 2.4875 V2 -1.35376 0.376765 2.49844 + N0 -0.480481 0.278679 0.83155 N1 -0.537012 0.14476 0.831061 N2 -2.13636e-15 5.93089e-16 1 + txt003 +STRI + V0 -1.21396 0.712995 2.49844 V1 -0.996219 0.996219 2.49844 V2 -1.01701 1.01701 2.4875 + N0 -1.87966e-15 1.16933e-15 1 N1 -1.4538e-15 1.67359e-15 1 N2 -0.392564 0.392564 0.831737 + txt003 +STRI + V0 -1.01701 1.01701 2.4875 V1 -1.2393 0.727875 2.4875 V2 -1.21396 0.712995 2.49844 + N0 -0.392564 0.392564 0.831737 N1 -0.480481 0.278679 0.83155 N2 -1.87966e-15 1.16933e-15 1 + txt003 +STRI + V0 -0.996219 0.996219 2.49844 V1 -0.712995 1.21396 2.49844 V2 -0.727875 1.2393 2.4875 + N0 -1.4538e-15 1.67359e-15 1 N1 -8.74229e-16 2.05298e-15 1 N2 -0.278679 0.480481 0.83155 + txt003 +STRI + V0 -0.727875 1.2393 2.4875 V1 -1.01701 1.01701 2.4875 V2 -0.996219 0.996219 2.49844 + N0 -0.278679 0.480481 0.83155 N1 -0.392564 0.392564 0.831737 N2 -1.4538e-15 1.67359e-15 1 + txt003 +STRI + V0 -0.712995 1.21396 2.49844 V1 -0.376765 1.35376 2.49844 V2 -0.384628 1.38201 2.4875 + N0 -8.74229e-16 2.05298e-15 1 N1 -1.77072e-16 2.25214e-15 1 N2 -0.14476 0.537012 0.831061 + txt003 +STRI + V0 -0.384628 1.38201 2.4875 V1 -0.727875 1.2393 2.4875 V2 -0.712995 1.21396 2.49844 + N0 -0.14476 0.537012 0.831061 N1 -0.278679 0.480481 0.83155 N2 -8.74229e-16 2.05298e-15 1 + txt003 +STRI + V0 -0.376765 1.35376 2.49844 V1 0 1.40312 2.49844 V2 0 1.43241 2.4875 + N0 -1.77072e-16 2.25214e-15 1 N1 5.65179e-16 2.22045e-15 1 N2 4.5989e-16 0.556738 0.830688 + txt003 +STRI + V0 0 1.43241 2.4875 V1 -0.384628 1.38201 2.4875 V2 -0.376765 1.35376 2.49844 + N0 4.5989e-16 0.556738 0.830688 N1 -0.14476 0.537012 0.831061 N2 -1.77072e-16 2.25214e-15 1 + txt003 +STRI + V0 -1.43241 0 2.4875 V1 -1.38201 0.384628 2.4875 V2 -1.41495 0.393796 2.45469 + N0 -0.556738 0 0.830688 N1 -0.537012 0.14476 0.831061 N2 -0.755869 0.203756 0.622211 + txt003 +STRI + V0 -1.41495 0.393796 2.45469 V1 -1.46655 0 2.45469 V2 -1.43241 0 2.4875 + N0 -0.755869 0.203756 0.622211 N1 -0.783289 0 0.621658 N2 -0.556738 0 0.830688 + txt003 +STRI + V0 -1.38201 0.384628 2.4875 V1 -1.2393 0.727875 2.4875 V2 -1.26884 0.745225 2.45469 + N0 -0.537012 0.14476 0.831061 N1 -0.480481 0.278679 0.83155 N2 -0.67669 0.39248 0.622937 + txt003 +STRI + V0 -1.26884 0.745225 2.45469 V1 -1.41495 0.393796 2.45469 V2 -1.38201 0.384628 2.4875 + N0 -0.67669 0.39248 0.622937 N1 -0.755869 0.203756 0.622211 N2 -0.537012 0.14476 0.831061 + txt003 +STRI + V0 -1.2393 0.727875 2.4875 V1 -1.01701 1.01701 2.4875 V2 -1.04125 1.04125 2.45469 + N0 -0.480481 0.278679 0.83155 N1 -0.392564 0.392564 0.831737 N2 -0.552993 0.552993 0.623215 + txt003 +STRI + V0 -1.04125 1.04125 2.45469 V1 -1.26884 0.745225 2.45469 V2 -1.2393 0.727875 2.4875 + N0 -0.552993 0.552993 0.623215 N1 -0.67669 0.39248 0.622937 N2 -0.480481 0.278679 0.83155 + txt003 +STRI + V0 -1.01701 1.01701 2.4875 V1 -0.727875 1.2393 2.4875 V2 -0.745225 1.26884 2.45469 + N0 -0.392564 0.392564 0.831737 N1 -0.278679 0.480481 0.83155 N2 -0.39248 0.67669 0.622937 + txt003 +STRI + V0 -0.745225 1.26884 2.45469 V1 -1.04125 1.04125 2.45469 V2 -1.01701 1.01701 2.4875 + N0 -0.39248 0.67669 0.622937 N1 -0.552993 0.552993 0.623215 N2 -0.392564 0.392564 0.831737 + txt003 +STRI + V0 -0.727875 1.2393 2.4875 V1 -0.384628 1.38201 2.4875 V2 -0.393796 1.41495 2.45469 + N0 -0.278679 0.480481 0.83155 N1 -0.14476 0.537012 0.831061 N2 -0.203756 0.755869 0.622211 + txt003 +STRI + V0 -0.393796 1.41495 2.45469 V1 -0.745225 1.26884 2.45469 V2 -0.727875 1.2393 2.4875 + N0 -0.203756 0.755869 0.622211 N1 -0.39248 0.67669 0.622937 N2 -0.278679 0.480481 0.83155 + txt003 +STRI + V0 -0.384628 1.38201 2.4875 V1 0 1.43241 2.4875 V2 0 1.46655 2.45469 + N0 -0.14476 0.537012 0.831061 N1 4.5989e-16 0.556738 0.830688 N2 1.94969e-16 0.783289 0.621658 + txt003 +STRI + V0 0 1.46655 2.45469 V1 -0.393796 1.41495 2.45469 V2 -0.384628 1.38201 2.4875 + N0 1.94969e-16 0.783289 0.621658 N1 -0.203756 0.755869 0.622211 N2 -0.14476 0.537012 0.831061 + txt003 +STRI + V0 -1.46655 0 2.45469 V1 -1.41495 0.393796 2.45469 V2 -1.44722 0.402778 2.4 + N0 -0.783289 0 0.621658 N1 -0.755869 0.203756 0.622211 N2 -0.871509 0.234929 0.430442 + txt003 +STRI + V0 -1.44722 0.402778 2.4 V1 -1.5 0 2.4 V2 -1.46655 0 2.45469 + N0 -0.871509 0.234929 0.430442 N1 -0.902861 0 0.429934 N2 -0.783289 0 0.621658 + txt003 +STRI + V0 -1.41495 0.393796 2.45469 V1 -1.26884 0.745225 2.45469 V2 -1.29778 0.762222 2.4 + N0 -0.755869 0.203756 0.622211 N1 -0.67669 0.39248 0.622937 N2 -0.780517 0.4527 0.43111 + txt003 +STRI + V0 -1.29778 0.762222 2.4 V1 -1.44722 0.402778 2.4 V2 -1.41495 0.393796 2.45469 + N0 -0.780517 0.4527 0.43111 N1 -0.871509 0.234929 0.430442 N2 -0.755869 0.203756 0.622211 + txt003 +STRI + V0 -1.26884 0.745225 2.45469 V1 -1.04125 1.04125 2.45469 V2 -1.065 1.065 2.4 + N0 -0.67669 0.39248 0.622937 N1 -0.552993 0.552993 0.623215 N2 -0.637936 0.637936 0.431366 + txt003 +STRI + V0 -1.065 1.065 2.4 V1 -1.29778 0.762222 2.4 V2 -1.26884 0.745225 2.45469 + N0 -0.637936 0.637936 0.431366 N1 -0.780517 0.4527 0.43111 N2 -0.67669 0.39248 0.622937 + txt003 +STRI + V0 -1.04125 1.04125 2.45469 V1 -0.745225 1.26884 2.45469 V2 -0.762222 1.29778 2.4 + N0 -0.552993 0.552993 0.623215 N1 -0.39248 0.67669 0.622937 N2 -0.4527 0.780517 0.43111 + txt003 +STRI + V0 -0.762222 1.29778 2.4 V1 -1.065 1.065 2.4 V2 -1.04125 1.04125 2.45469 + N0 -0.4527 0.780517 0.43111 N1 -0.637936 0.637936 0.431366 N2 -0.552993 0.552993 0.623215 + txt003 +STRI + V0 -0.745225 1.26884 2.45469 V1 -0.393796 1.41495 2.45469 V2 -0.402778 1.44722 2.4 + N0 -0.39248 0.67669 0.622937 N1 -0.203756 0.755869 0.622211 N2 -0.234929 0.871509 0.430442 + txt003 +STRI + V0 -0.402778 1.44722 2.4 V1 -0.762222 1.29778 2.4 V2 -0.745225 1.26884 2.45469 + N0 -0.234929 0.871509 0.430442 N1 -0.4527 0.780517 0.43111 N2 -0.39248 0.67669 0.622937 + txt003 +STRI + V0 -0.393796 1.41495 2.45469 V1 0 1.46655 2.45469 V2 0 1.5 2.4 + N0 -0.203756 0.755869 0.622211 N1 1.94969e-16 0.783289 0.621658 N2 6.81889e-17 0.902861 0.429934 + txt003 +STRI + V0 0 1.5 2.4 V1 -0.402778 1.44722 2.4 V2 -0.393796 1.41495 2.45469 + N0 6.81889e-17 0.902861 0.429934 N1 -0.234929 0.871509 0.430442 N2 -0.203756 0.755869 0.622211 + txt003 +STRI + V0 0 1.4 2.4 V1 0.375926 1.35074 2.4 V2 0.370922 1.33276 2.45469 + N0 0 -0.902861 -0.429934 N1 -0.234929 -0.871509 -0.430442 N2 -0.257047 -0.953562 -0.156989 + txt003 +STRI + V0 0.370922 1.33276 2.45469 V1 0 1.38137 2.45469 V2 0 1.4 2.4 + N0 -0.257047 -0.953562 -0.156989 N1 0 -0.987636 -0.156768 N2 0 -0.902861 -0.429934 + txt003 +STRI + V0 0.375926 1.35074 2.4 V1 0.711407 1.21126 2.4 V2 0.701938 1.19514 2.45469 + N0 -0.234929 -0.871509 -0.430442 N1 -0.4527 -0.780517 -0.43111 N2 -0.495474 -0.854265 -0.157281 + txt003 +STRI + V0 0.701938 1.19514 2.45469 V1 0.370922 1.33276 2.45469 V2 0.375926 1.35074 2.4 + N0 -0.495474 -0.854265 -0.157281 N1 -0.257047 -0.953562 -0.156989 N2 -0.234929 -0.871509 -0.430442 + txt003 +STRI + V0 0.711407 1.21126 2.4 V1 0.994 0.994 2.4 V2 0.98077 0.98077 2.45469 + N0 -0.4527 -0.780517 -0.43111 N1 -0.637936 -0.637936 -0.431366 N2 -0.698293 -0.698293 -0.157393 + txt003 +STRI + V0 0.98077 0.98077 2.45469 V1 0.701938 1.19514 2.45469 V2 0.711407 1.21126 2.4 + N0 -0.698293 -0.698293 -0.157393 N1 -0.495474 -0.854265 -0.157281 N2 -0.4527 -0.780517 -0.43111 + txt003 +STRI + V0 0.994 0.994 2.4 V1 1.21126 0.711407 2.4 V2 1.19514 0.701938 2.45469 + N0 -0.637936 -0.637936 -0.431366 N1 -0.780517 -0.4527 -0.43111 N2 -0.854265 -0.495474 -0.157281 + txt003 +STRI + V0 1.19514 0.701938 2.45469 V1 0.98077 0.98077 2.45469 V2 0.994 0.994 2.4 + N0 -0.854265 -0.495474 -0.157281 N1 -0.698293 -0.698293 -0.157393 N2 -0.637936 -0.637936 -0.431366 + txt003 +STRI + V0 1.21126 0.711407 2.4 V1 1.35074 0.375926 2.4 V2 1.33276 0.370922 2.45469 + N0 -0.780517 -0.4527 -0.43111 N1 -0.871509 -0.234929 -0.430442 N2 -0.953562 -0.257047 -0.156989 + txt003 +STRI + V0 1.33276 0.370922 2.45469 V1 1.19514 0.701938 2.45469 V2 1.21126 0.711407 2.4 + N0 -0.953562 -0.257047 -0.156989 N1 -0.854265 -0.495474 -0.157281 N2 -0.780517 -0.4527 -0.43111 + txt003 +STRI + V0 1.35074 0.375926 2.4 V1 1.4 0 2.4 V2 1.38137 0 2.45469 + N0 -0.871509 -0.234929 -0.430442 N1 -0.902861 7.30595e-17 -0.429934 N2 -0.987636 -9.89971e-17 -0.156768 + txt003 +STRI + V0 1.38137 0 2.45469 V1 1.33276 0.370922 2.45469 V2 1.35074 0.375926 2.4 + N0 -0.987636 -9.89971e-17 -0.156768 N1 -0.953562 -0.257047 -0.156989 N2 -0.871509 -0.234929 -0.430442 + txt003 +STRI + V0 0 1.38137 2.45469 V1 0.370922 1.33276 2.45469 V2 0.371699 1.33555 2.4875 + N0 0 -0.987636 -0.156768 N1 -0.257047 -0.953562 -0.156989 N2 -0.228972 -0.849414 0.475466 + txt003 +STRI + V0 0.371699 1.33555 2.4875 V1 0 1.38426 2.4875 V2 0 1.38137 2.45469 + N0 -0.228972 -0.849414 0.475466 N1 0 -0.880022 0.474933 N2 0 -0.987636 -0.156768 + txt003 +STRI + V0 0.370922 1.33276 2.45469 V1 0.701938 1.19514 2.45469 V2 0.703409 1.19764 2.4875 + N0 -0.257047 -0.953562 -0.156989 N1 -0.495474 -0.854265 -0.157281 N2 -0.441188 -0.760669 0.476167 + txt003 +STRI + V0 0.703409 1.19764 2.4875 V1 0.371699 1.33555 2.4875 V2 0.370922 1.33276 2.45469 + N0 -0.441188 -0.760669 0.476167 N1 -0.228972 -0.849414 0.475466 N2 -0.257047 -0.953562 -0.156989 + txt003 +STRI + V0 0.701938 1.19514 2.45469 V1 0.98077 0.98077 2.45469 V2 0.982824 0.982824 2.4875 + N0 -0.495474 -0.854265 -0.157281 N1 -0.698293 -0.698293 -0.157393 N2 -0.621695 -0.621695 0.476435 + txt003 +STRI + V0 0.982824 0.982824 2.4875 V1 0.703409 1.19764 2.4875 V2 0.701938 1.19514 2.45469 + N0 -0.621695 -0.621695 0.476435 N1 -0.441188 -0.760669 0.476167 N2 -0.495474 -0.854265 -0.157281 + txt003 +STRI + V0 0.98077 0.98077 2.45469 V1 1.19514 0.701938 2.45469 V2 1.19764 0.703409 2.4875 + N0 -0.698293 -0.698293 -0.157393 N1 -0.854265 -0.495474 -0.157281 N2 -0.760669 -0.441188 0.476167 + txt003 +STRI + V0 1.19764 0.703409 2.4875 V1 0.982824 0.982824 2.4875 V2 0.98077 0.98077 2.45469 + N0 -0.760669 -0.441188 0.476167 N1 -0.621695 -0.621695 0.476435 N2 -0.698293 -0.698293 -0.157393 + txt003 +STRI + V0 1.19514 0.701938 2.45469 V1 1.33276 0.370922 2.45469 V2 1.33555 0.371699 2.4875 + N0 -0.854265 -0.495474 -0.157281 N1 -0.953562 -0.257047 -0.156989 N2 -0.849414 -0.228972 0.475466 + txt003 +STRI + V0 1.33555 0.371699 2.4875 V1 1.19764 0.703409 2.4875 V2 1.19514 0.701938 2.45469 + N0 -0.849414 -0.228972 0.475466 N1 -0.760669 -0.441188 0.476167 N2 -0.854265 -0.495474 -0.157281 + txt003 +STRI + V0 1.33276 0.370922 2.45469 V1 1.38137 0 2.45469 V2 1.38426 0 2.4875 + N0 -0.953562 -0.257047 -0.156989 N1 -0.987636 -9.89971e-17 -0.156768 N2 -0.880022 -6.08179e-16 0.474933 + txt003 +STRI + V0 1.38426 0 2.4875 V1 1.33555 0.371699 2.4875 V2 1.33276 0.370922 2.45469 + N0 -0.880022 -6.08179e-16 0.474933 N1 -0.849414 -0.228972 0.475466 N2 -0.953562 -0.257047 -0.156989 + txt003 +STRI + V0 0 1.38426 2.4875 V1 0.371699 1.33555 2.4875 V2 0.376765 1.35376 2.49844 + N0 0 -0.880022 0.474933 N1 -0.228972 -0.849414 0.475466 N2 5.93089e-16 2.13636e-15 1 + txt003 +STRI + V0 0.376765 1.35376 2.49844 V1 0 1.40312 2.49844 V2 0 1.38426 2.4875 + N0 5.93089e-16 2.13636e-15 1 N1 -0 2.22045e-15 1 N2 0 -0.880022 0.474933 + txt003 +STRI + V0 0.371699 1.33555 2.4875 V1 0.703409 1.19764 2.4875 V2 0.712995 1.21396 2.49844 + N0 -0.228972 -0.849414 0.475466 N1 -0.441188 -0.760669 0.476167 N2 1.16933e-15 1.87966e-15 1 + txt003 +STRI + V0 0.712995 1.21396 2.49844 V1 0.376765 1.35376 2.49844 V2 0.371699 1.33555 2.4875 + N0 1.16933e-15 1.87966e-15 1 N1 5.93089e-16 2.13636e-15 1 N2 -0.228972 -0.849414 0.475466 + txt003 +STRI + V0 0.703409 1.19764 2.4875 V1 0.982824 0.982824 2.4875 V2 0.996219 0.996219 2.49844 + N0 -0.441188 -0.760669 0.476167 N1 -0.621695 -0.621695 0.476435 N2 1.67359e-15 1.4538e-15 1 + txt003 +STRI + V0 0.996219 0.996219 2.49844 V1 0.712995 1.21396 2.49844 V2 0.703409 1.19764 2.4875 + N0 1.67359e-15 1.4538e-15 1 N1 1.16933e-15 1.87966e-15 1 N2 -0.441188 -0.760669 0.476167 + txt003 +STRI + V0 0.982824 0.982824 2.4875 V1 1.19764 0.703409 2.4875 V2 1.21396 0.712995 2.49844 + N0 -0.621695 -0.621695 0.476435 N1 -0.760669 -0.441188 0.476167 N2 2.05298e-15 8.74229e-16 1 + txt003 +STRI + V0 1.21396 0.712995 2.49844 V1 0.996219 0.996219 2.49844 V2 0.982824 0.982824 2.4875 + N0 2.05298e-15 8.74229e-16 1 N1 1.67359e-15 1.4538e-15 1 N2 -0.621695 -0.621695 0.476435 + txt003 +STRI + V0 1.19764 0.703409 2.4875 V1 1.33555 0.371699 2.4875 V2 1.35376 0.376765 2.49844 + N0 -0.760669 -0.441188 0.476167 N1 -0.849414 -0.228972 0.475466 N2 2.25214e-15 1.77072e-16 1 + txt003 +STRI + V0 1.35376 0.376765 2.49844 V1 1.21396 0.712995 2.49844 V2 1.19764 0.703409 2.4875 + N0 2.25214e-15 1.77072e-16 1 N1 2.05298e-15 8.74229e-16 1 N2 -0.760669 -0.441188 0.476167 + txt003 +STRI + V0 1.33555 0.371699 2.4875 V1 1.38426 0 2.4875 V2 1.40312 0 2.49844 + N0 -0.849414 -0.228972 0.475466 N1 -0.880022 -6.08179e-16 0.474933 N2 2.22045e-15 -5.65179e-16 1 + txt003 +STRI + V0 1.40312 0 2.49844 V1 1.35376 0.376765 2.49844 V2 1.33555 0.371699 2.4875 + N0 2.22045e-15 -5.65179e-16 1 N1 2.25214e-15 1.77072e-16 1 N2 -0.849414 -0.228972 0.475466 + txt003 +STRI + V0 0 1.40312 2.49844 V1 0.376765 1.35376 2.49844 V2 0.384628 1.38201 2.4875 + N0 -0 2.22045e-15 1 N1 5.93089e-16 2.13636e-15 1 N2 0.14476 0.537012 0.831061 + txt003 +STRI + V0 0.384628 1.38201 2.4875 V1 0 1.43241 2.4875 V2 0 1.40312 2.49844 + N0 0.14476 0.537012 0.831061 N1 -0 0.556738 0.830688 N2 -0 2.22045e-15 1 + txt003 +STRI + V0 0.376765 1.35376 2.49844 V1 0.712995 1.21396 2.49844 V2 0.727875 1.2393 2.4875 + N0 5.93089e-16 2.13636e-15 1 N1 1.16933e-15 1.87966e-15 1 N2 0.278679 0.480481 0.83155 + txt003 +STRI + V0 0.727875 1.2393 2.4875 V1 0.384628 1.38201 2.4875 V2 0.376765 1.35376 2.49844 + N0 0.278679 0.480481 0.83155 N1 0.14476 0.537012 0.831061 N2 5.93089e-16 2.13636e-15 1 + txt003 +STRI + V0 0.712995 1.21396 2.49844 V1 0.996219 0.996219 2.49844 V2 1.01701 1.01701 2.4875 + N0 1.16933e-15 1.87966e-15 1 N1 1.67359e-15 1.4538e-15 1 N2 0.392564 0.392564 0.831737 + txt003 +STRI + V0 1.01701 1.01701 2.4875 V1 0.727875 1.2393 2.4875 V2 0.712995 1.21396 2.49844 + N0 0.392564 0.392564 0.831737 N1 0.278679 0.480481 0.83155 N2 1.16933e-15 1.87966e-15 1 + txt003 +STRI + V0 0.996219 0.996219 2.49844 V1 1.21396 0.712995 2.49844 V2 1.2393 0.727875 2.4875 + N0 1.67359e-15 1.4538e-15 1 N1 2.05298e-15 8.74229e-16 1 N2 0.480481 0.278679 0.83155 + txt003 +STRI + V0 1.2393 0.727875 2.4875 V1 1.01701 1.01701 2.4875 V2 0.996219 0.996219 2.49844 + N0 0.480481 0.278679 0.83155 N1 0.392564 0.392564 0.831737 N2 1.67359e-15 1.4538e-15 1 + txt003 +STRI + V0 1.21396 0.712995 2.49844 V1 1.35376 0.376765 2.49844 V2 1.38201 0.384628 2.4875 + N0 2.05298e-15 8.74229e-16 1 N1 2.25214e-15 1.77072e-16 1 N2 0.537012 0.14476 0.831061 + txt003 +STRI + V0 1.38201 0.384628 2.4875 V1 1.2393 0.727875 2.4875 V2 1.21396 0.712995 2.49844 + N0 0.537012 0.14476 0.831061 N1 0.480481 0.278679 0.83155 N2 2.05298e-15 8.74229e-16 1 + txt003 +STRI + V0 1.35376 0.376765 2.49844 V1 1.40312 0 2.49844 V2 1.43241 0 2.4875 + N0 2.25214e-15 1.77072e-16 1 N1 2.22045e-15 -5.65179e-16 1 N2 0.556738 -4.5989e-16 0.830688 + txt003 +STRI + V0 1.43241 0 2.4875 V1 1.38201 0.384628 2.4875 V2 1.35376 0.376765 2.49844 + N0 0.556738 -4.5989e-16 0.830688 N1 0.537012 0.14476 0.831061 N2 2.25214e-15 1.77072e-16 1 + txt003 +STRI + V0 0 1.43241 2.4875 V1 0.384628 1.38201 2.4875 V2 0.393796 1.41495 2.45469 + N0 -0 0.556738 0.830688 N1 0.14476 0.537012 0.831061 N2 0.203756 0.755869 0.622211 + txt003 +STRI + V0 0.393796 1.41495 2.45469 V1 0 1.46655 2.45469 V2 0 1.43241 2.4875 + N0 0.203756 0.755869 0.622211 N1 -0 0.783289 0.621658 N2 -0 0.556738 0.830688 + txt003 +STRI + V0 0.384628 1.38201 2.4875 V1 0.727875 1.2393 2.4875 V2 0.745225 1.26884 2.45469 + N0 0.14476 0.537012 0.831061 N1 0.278679 0.480481 0.83155 N2 0.39248 0.67669 0.622937 + txt003 +STRI + V0 0.745225 1.26884 2.45469 V1 0.393796 1.41495 2.45469 V2 0.384628 1.38201 2.4875 + N0 0.39248 0.67669 0.622937 N1 0.203756 0.755869 0.622211 N2 0.14476 0.537012 0.831061 + txt003 +STRI + V0 0.727875 1.2393 2.4875 V1 1.01701 1.01701 2.4875 V2 1.04125 1.04125 2.45469 + N0 0.278679 0.480481 0.83155 N1 0.392564 0.392564 0.831737 N2 0.552993 0.552993 0.623215 + txt003 +STRI + V0 1.04125 1.04125 2.45469 V1 0.745225 1.26884 2.45469 V2 0.727875 1.2393 2.4875 + N0 0.552993 0.552993 0.623215 N1 0.39248 0.67669 0.622937 N2 0.278679 0.480481 0.83155 + txt003 +STRI + V0 1.01701 1.01701 2.4875 V1 1.2393 0.727875 2.4875 V2 1.26884 0.745225 2.45469 + N0 0.392564 0.392564 0.831737 N1 0.480481 0.278679 0.83155 N2 0.67669 0.39248 0.622937 + txt003 +STRI + V0 1.26884 0.745225 2.45469 V1 1.04125 1.04125 2.45469 V2 1.01701 1.01701 2.4875 + N0 0.67669 0.39248 0.622937 N1 0.552993 0.552993 0.623215 N2 0.392564 0.392564 0.831737 + txt003 +STRI + V0 1.2393 0.727875 2.4875 V1 1.38201 0.384628 2.4875 V2 1.41495 0.393796 2.45469 + N0 0.480481 0.278679 0.83155 N1 0.537012 0.14476 0.831061 N2 0.755869 0.203756 0.622211 + txt003 +STRI + V0 1.41495 0.393796 2.45469 V1 1.26884 0.745225 2.45469 V2 1.2393 0.727875 2.4875 + N0 0.755869 0.203756 0.622211 N1 0.67669 0.39248 0.622937 N2 0.480481 0.278679 0.83155 + txt003 +STRI + V0 1.38201 0.384628 2.4875 V1 1.43241 0 2.4875 V2 1.46655 0 2.45469 + N0 0.537012 0.14476 0.831061 N1 0.556738 -4.5989e-16 0.830688 N2 0.783289 -1.94969e-16 0.621658 + txt003 +STRI + V0 1.46655 0 2.45469 V1 1.41495 0.393796 2.45469 V2 1.38201 0.384628 2.4875 + N0 0.783289 -1.94969e-16 0.621658 N1 0.755869 0.203756 0.622211 N2 0.537012 0.14476 0.831061 + txt003 +STRI + V0 0 1.46655 2.45469 V1 0.393796 1.41495 2.45469 V2 0.402778 1.44722 2.4 + N0 -0 0.783289 0.621658 N1 0.203756 0.755869 0.622211 N2 0.234929 0.871509 0.430442 + txt003 +STRI + V0 0.402778 1.44722 2.4 V1 0 1.5 2.4 V2 0 1.46655 2.45469 + N0 0.234929 0.871509 0.430442 N1 -0 0.902861 0.429934 N2 -0 0.783289 0.621658 + txt003 +STRI + V0 0.393796 1.41495 2.45469 V1 0.745225 1.26884 2.45469 V2 0.762222 1.29778 2.4 + N0 0.203756 0.755869 0.622211 N1 0.39248 0.67669 0.622937 N2 0.4527 0.780517 0.43111 + txt003 +STRI + V0 0.762222 1.29778 2.4 V1 0.402778 1.44722 2.4 V2 0.393796 1.41495 2.45469 + N0 0.4527 0.780517 0.43111 N1 0.234929 0.871509 0.430442 N2 0.203756 0.755869 0.622211 + txt003 +STRI + V0 0.745225 1.26884 2.45469 V1 1.04125 1.04125 2.45469 V2 1.065 1.065 2.4 + N0 0.39248 0.67669 0.622937 N1 0.552993 0.552993 0.623215 N2 0.637936 0.637936 0.431366 + txt003 +STRI + V0 1.065 1.065 2.4 V1 0.762222 1.29778 2.4 V2 0.745225 1.26884 2.45469 + N0 0.637936 0.637936 0.431366 N1 0.4527 0.780517 0.43111 N2 0.39248 0.67669 0.622937 + txt003 +STRI + V0 1.04125 1.04125 2.45469 V1 1.26884 0.745225 2.45469 V2 1.29778 0.762222 2.4 + N0 0.552993 0.552993 0.623215 N1 0.67669 0.39248 0.622937 N2 0.780517 0.4527 0.43111 + txt003 +STRI + V0 1.29778 0.762222 2.4 V1 1.065 1.065 2.4 V2 1.04125 1.04125 2.45469 + N0 0.780517 0.4527 0.43111 N1 0.637936 0.637936 0.431366 N2 0.552993 0.552993 0.623215 + txt003 +STRI + V0 1.26884 0.745225 2.45469 V1 1.41495 0.393796 2.45469 V2 1.44722 0.402778 2.4 + N0 0.67669 0.39248 0.622937 N1 0.755869 0.203756 0.622211 N2 0.871509 0.234929 0.430442 + txt003 +STRI + V0 1.44722 0.402778 2.4 V1 1.29778 0.762222 2.4 V2 1.26884 0.745225 2.45469 + N0 0.871509 0.234929 0.430442 N1 0.780517 0.4527 0.43111 N2 0.67669 0.39248 0.622937 + txt003 +STRI + V0 1.41495 0.393796 2.45469 V1 1.46655 0 2.45469 V2 1.5 0 2.4 + N0 0.755869 0.203756 0.622211 N1 0.783289 -1.94969e-16 0.621658 N2 0.902861 -6.81889e-17 0.429934 + txt003 +STRI + V0 1.5 0 2.4 V1 1.44722 0.402778 2.4 V2 1.41495 0.393796 2.45469 + N0 0.902861 -6.81889e-17 0.429934 N1 0.871509 0.234929 0.430442 N2 0.755869 0.203756 0.622211 + txt003 +STRI + V0 1.5 0 2.4 V1 1.44722 -0.402778 2.4 V2 1.56671 -0.436032 2.13785 + N0 0.902861 0 0.429934 N1 0.871509 -0.234929 0.430442 N2 0.875348 -0.235963 0.422003 + txt003 +STRI + V0 1.56671 -0.436032 2.13785 V1 1.62384 0 2.13785 V2 1.5 0 2.4 + N0 0.875348 -0.235963 0.422003 N1 0.906828 0 0.4215 N2 0.902861 0 0.429934 + txt003 +STRI + V0 1.44722 -0.402778 2.4 V1 1.29778 -0.762222 2.4 V2 1.40492 -0.825153 2.13785 + N0 0.871509 -0.234929 0.430442 N1 0.780517 -0.4527 0.43111 N2 0.783966 -0.4547 0.422664 + txt003 +STRI + V0 1.40492 -0.825153 2.13785 V1 1.56671 -0.436032 2.13785 V2 1.44722 -0.402778 2.4 + N0 0.783966 -0.4547 0.422664 N1 0.875348 -0.235963 0.422003 N2 0.871509 -0.234929 0.430442 + txt003 +STRI + V0 1.29778 -0.762222 2.4 V1 1.065 -1.065 2.4 V2 1.15293 -1.15293 2.13785 + N0 0.780517 -0.4527 0.43111 N1 0.637936 -0.637936 0.431366 N2 0.640758 -0.640758 0.422917 + txt003 +STRI + V0 1.15293 -1.15293 2.13785 V1 1.40492 -0.825153 2.13785 V2 1.29778 -0.762222 2.4 + N0 0.640758 -0.640758 0.422917 N1 0.783966 -0.4547 0.422664 N2 0.780517 -0.4527 0.43111 + txt003 +STRI + V0 1.065 -1.065 2.4 V1 0.762222 -1.29778 2.4 V2 0.825153 -1.40492 2.13785 + N0 0.637936 -0.637936 0.431366 N1 0.4527 -0.780517 0.43111 N2 0.4547 -0.783966 0.422664 + txt003 +STRI + V0 0.825153 -1.40492 2.13785 V1 1.15293 -1.15293 2.13785 V2 1.065 -1.065 2.4 + N0 0.4547 -0.783966 0.422664 N1 0.640758 -0.640758 0.422917 N2 0.637936 -0.637936 0.431366 + txt003 +STRI + V0 0.762222 -1.29778 2.4 V1 0.402778 -1.44722 2.4 V2 0.436032 -1.56671 2.13785 + N0 0.4527 -0.780517 0.43111 N1 0.234929 -0.871509 0.430442 N2 0.235963 -0.875348 0.422003 + txt003 +STRI + V0 0.436032 -1.56671 2.13785 V1 0.825153 -1.40492 2.13785 V2 0.762222 -1.29778 2.4 + N0 0.235963 -0.875348 0.422003 N1 0.4547 -0.783966 0.422664 N2 0.4527 -0.780517 0.43111 + txt003 +STRI + V0 0.402778 -1.44722 2.4 V1 0 -1.5 2.4 V2 2.22045e-16 -1.62384 2.13785 + N0 0.234929 -0.871509 0.430442 N1 -2.27296e-16 -0.902861 0.429934 N2 -2.05843e-16 -0.906828 0.4215 + txt003 +STRI + V0 2.22045e-16 -1.62384 2.13785 V1 0.436032 -1.56671 2.13785 V2 0.402778 -1.44722 2.4 + N0 -2.05843e-16 -0.906828 0.4215 N1 0.235963 -0.875348 0.422003 N2 0.234929 -0.871509 0.430442 + txt003 +STRI + V0 1.62384 0 2.13785 V1 1.56671 -0.436032 2.13785 V2 1.67949 -0.467421 1.87778 + N0 0.906828 0 0.4215 N1 0.875348 -0.235963 0.422003 N2 0.886771 -0.239043 0.395595 + txt003 +STRI + V0 1.67949 -0.467421 1.87778 V1 1.74074 0 1.87778 V2 1.62384 0 2.13785 + N0 0.886771 -0.239043 0.395595 N1 0.918633 0 0.395111 N2 0.906828 0 0.4215 + txt003 +STRI + V0 1.56671 -0.436032 2.13785 V1 1.40492 -0.825153 2.13785 V2 1.50606 -0.884554 1.87778 + N0 0.875348 -0.235963 0.422003 N1 0.783966 -0.4547 0.422664 N2 0.794229 -0.460653 0.39623 + txt003 +STRI + V0 1.50606 -0.884554 1.87778 V1 1.67949 -0.467421 1.87778 V2 1.56671 -0.436032 2.13785 + N0 0.794229 -0.460653 0.39623 N1 0.886771 -0.239043 0.395595 N2 0.875348 -0.235963 0.422003 + txt003 +STRI + V0 1.40492 -0.825153 2.13785 V1 1.15293 -1.15293 2.13785 V2 1.23593 -1.23593 1.87778 + N0 0.783966 -0.4547 0.422664 N1 0.640758 -0.640758 0.422917 N2 0.649156 -0.649156 0.396474 + txt003 +STRI + V0 1.23593 -1.23593 1.87778 V1 1.50606 -0.884554 1.87778 V2 1.40492 -0.825153 2.13785 + N0 0.649156 -0.649156 0.396474 N1 0.794229 -0.460653 0.39623 N2 0.783966 -0.4547 0.422664 + txt003 +STRI + V0 1.15293 -1.15293 2.13785 V1 0.825153 -1.40492 2.13785 V2 0.884554 -1.50606 1.87778 + N0 0.640758 -0.640758 0.422917 N1 0.4547 -0.783966 0.422664 N2 0.460653 -0.794229 0.39623 + txt003 +STRI + V0 0.884554 -1.50606 1.87778 V1 1.23593 -1.23593 1.87778 V2 1.15293 -1.15293 2.13785 + N0 0.460653 -0.794229 0.39623 N1 0.649156 -0.649156 0.396474 N2 0.640758 -0.640758 0.422917 + txt003 +STRI + V0 0.825153 -1.40492 2.13785 V1 0.436032 -1.56671 2.13785 V2 0.467421 -1.67949 1.87778 + N0 0.4547 -0.783966 0.422664 N1 0.235963 -0.875348 0.422003 N2 0.239043 -0.886771 0.395595 + txt003 +STRI + V0 0.467421 -1.67949 1.87778 V1 0.884554 -1.50606 1.87778 V2 0.825153 -1.40492 2.13785 + N0 0.239043 -0.886771 0.395595 N1 0.460653 -0.794229 0.39623 N2 0.4547 -0.783966 0.422664 + txt003 +STRI + V0 0.436032 -1.56671 2.13785 V1 2.22045e-16 -1.62384 2.13785 V2 0 -1.74074 1.87778 + N0 0.235963 -0.875348 0.422003 N1 -2.05843e-16 -0.906828 0.4215 N2 -1.79998e-16 -0.918633 0.395111 + txt003 +STRI + V0 0 -1.74074 1.87778 V1 0.467421 -1.67949 1.87778 V2 0.436032 -1.56671 2.13785 + N0 -1.79998e-16 -0.918633 0.395111 N1 0.239043 -0.886771 0.395595 N2 0.235963 -0.875348 0.422003 + txt003 +STRI + V0 1.74074 0 1.87778 V1 1.67949 -0.467421 1.87778 V2 1.77888 -0.495081 1.62188 + N0 0.918633 0 0.395111 N1 0.886771 -0.239043 0.395595 N2 0.90527 -0.244029 0.347757 + txt003 +STRI + V0 1.77888 -0.495081 1.62188 V1 1.84375 0 1.62188 V2 1.74074 0 1.87778 + N0 0.90527 -0.244029 0.347757 N1 0.937749 0 0.347314 N2 0.918633 0 0.395111 + txt003 +STRI + V0 1.67949 -0.467421 1.87778 V1 1.50606 -0.884554 1.87778 V2 1.59519 -0.936898 1.62188 + N0 0.886771 -0.239043 0.395595 N1 0.794229 -0.460653 0.39623 N2 0.810853 -0.470295 0.34834 + txt003 +STRI + V0 1.59519 -0.936898 1.62188 V1 1.77888 -0.495081 1.62188 V2 1.67949 -0.467421 1.87778 + N0 0.810853 -0.470295 0.34834 N1 0.90527 -0.244029 0.347757 N2 0.886771 -0.239043 0.395595 + txt003 +STRI + V0 1.50606 -0.884554 1.87778 V1 1.23593 -1.23593 1.87778 V2 1.30906 -1.30906 1.62188 + N0 0.794229 -0.460653 0.39623 N1 0.649156 -0.649156 0.396474 N2 0.662761 -0.662761 0.348563 + txt003 +STRI + V0 1.30906 -1.30906 1.62188 V1 1.59519 -0.936898 1.62188 V2 1.50606 -0.884554 1.87778 + N0 0.662761 -0.662761 0.348563 N1 0.810853 -0.470295 0.34834 N2 0.794229 -0.460653 0.39623 + txt003 +STRI + V0 1.23593 -1.23593 1.87778 V1 0.884554 -1.50606 1.87778 V2 0.936898 -1.59519 1.62187 + N0 0.649156 -0.649156 0.396474 N1 0.460653 -0.794229 0.39623 N2 0.470295 -0.810853 0.34834 + txt003 +STRI + V0 0.936898 -1.59519 1.62187 V1 1.30906 -1.30906 1.62188 V2 1.23593 -1.23593 1.87778 + N0 0.470295 -0.810853 0.34834 N1 0.662761 -0.662761 0.348563 N2 0.649156 -0.649156 0.396474 + txt003 +STRI + V0 0.884554 -1.50606 1.87778 V1 0.467421 -1.67949 1.87778 V2 0.495081 -1.77888 1.62187 + N0 0.460653 -0.794229 0.39623 N1 0.239043 -0.886771 0.395595 N2 0.244029 -0.90527 0.347757 + txt003 +STRI + V0 0.495081 -1.77888 1.62187 V1 0.936898 -1.59519 1.62187 V2 0.884554 -1.50606 1.87778 + N0 0.244029 -0.90527 0.347757 N1 0.470295 -0.810853 0.34834 N2 0.460653 -0.794229 0.39623 + txt003 +STRI + V0 0.467421 -1.67949 1.87778 V1 0 -1.74074 1.87778 V2 0 -1.84375 1.62187 + N0 0.239043 -0.886771 0.395595 N1 -1.79998e-16 -0.918633 0.395111 N2 -1.49384e-16 -0.937749 0.347314 + txt003 +STRI + V0 0 -1.84375 1.62187 V1 0.495081 -1.77888 1.62187 V2 0.467421 -1.67949 1.87778 + N0 -1.49384e-16 -0.937749 0.347314 N1 0.244029 -0.90527 0.347757 N2 0.239043 -0.886771 0.395595 + txt003 +STRI + V0 1.84375 0 1.62188 V1 1.77888 -0.495081 1.62188 V2 1.85816 -0.517147 1.37222 + N0 0.937749 0 0.347314 N1 0.90527 -0.244029 0.347757 N2 0.929073 -0.250446 0.272213 + txt003 +STRI + V0 1.85816 -0.517147 1.37222 V1 1.92593 0 1.37222 V2 1.84375 0 1.62188 + N0 0.929073 -0.250446 0.272213 N1 0.96234 0 0.271848 N2 0.937749 0 0.347314 + txt003 +STRI + V0 1.77888 -0.495081 1.62188 V1 1.59519 -0.936898 1.62188 V2 1.66628 -0.978656 1.37222 + N0 0.90527 -0.244029 0.347757 N1 0.810853 -0.470295 0.34834 N2 0.832247 -0.482704 0.272693 + txt003 +STRI + V0 1.66628 -0.978656 1.37222 V1 1.85816 -0.517147 1.37222 V2 1.77888 -0.495081 1.62188 + N0 0.832247 -0.482704 0.272693 N1 0.929073 -0.250446 0.272213 N2 0.90527 -0.244029 0.347757 + txt003 +STRI + V0 1.59519 -0.936898 1.62188 V1 1.30906 -1.30906 1.62188 V2 1.36741 -1.36741 1.37222 + N0 0.810853 -0.470295 0.34834 N1 0.662761 -0.662761 0.348563 N2 0.680271 -0.680271 0.272877 + txt003 +STRI + V0 1.36741 -1.36741 1.37222 V1 1.66628 -0.978656 1.37222 V2 1.59519 -0.936898 1.62188 + N0 0.680271 -0.680271 0.272877 N1 0.832247 -0.482704 0.272693 N2 0.810853 -0.470295 0.34834 + txt003 +STRI + V0 1.30906 -1.30906 1.62188 V1 0.936898 -1.59519 1.62187 V2 0.978656 -1.66628 1.37222 + N0 0.662761 -0.662761 0.348563 N1 0.470295 -0.810853 0.34834 N2 0.482704 -0.832247 0.272693 + txt003 +STRI + V0 0.978656 -1.66628 1.37222 V1 1.36741 -1.36741 1.37222 V2 1.30906 -1.30906 1.62188 + N0 0.482704 -0.832247 0.272693 N1 0.680271 -0.680271 0.272877 N2 0.662761 -0.662761 0.348563 + txt003 +STRI + V0 0.936898 -1.59519 1.62187 V1 0.495081 -1.77888 1.62187 V2 0.517147 -1.85816 1.37222 + N0 0.470295 -0.810853 0.34834 N1 0.244029 -0.90527 0.347757 N2 0.250446 -0.929073 0.272213 + txt003 +STRI + V0 0.517147 -1.85816 1.37222 V1 0.978656 -1.66628 1.37222 V2 0.936898 -1.59519 1.62187 + N0 0.250446 -0.929073 0.272213 N1 0.482704 -0.832247 0.272693 N2 0.470295 -0.810853 0.34834 + txt003 +STRI + V0 0.495081 -1.77888 1.62187 V1 0 -1.84375 1.62187 V2 2.22045e-16 -1.92593 1.37222 + N0 0.244029 -0.90527 0.347757 N1 -1.49384e-16 -0.937749 0.347314 N2 -1.11936e-16 -0.96234 0.271848 + txt003 +STRI + V0 2.22045e-16 -1.92593 1.37222 V1 0.517147 -1.85816 1.37222 V2 0.495081 -1.77888 1.62187 + N0 -1.11936e-16 -0.96234 0.271848 N1 0.250446 -0.929073 0.272213 N2 0.244029 -0.90527 0.347757 + txt003 +STRI + V0 1.92593 0 1.37222 V1 1.85816 -0.517147 1.37222 V2 1.91065 -0.531754 1.1309 + N0 0.96234 0 0.271848 N1 0.929073 -0.250446 0.272213 N2 0.953145 -0.256935 0.159686 + txt003 +STRI + V0 1.91065 -0.531754 1.1309 V1 1.98032 0 1.1309 V2 1.92593 0 1.37222 + N0 0.953145 -0.256935 0.159686 N1 0.987204 0 0.15946 N2 0.96234 0 0.271848 + txt003 +STRI + V0 1.85816 -0.517147 1.37222 V1 1.66628 -0.978656 1.37222 V2 1.71335 -1.0063 1.1309 + N0 0.929073 -0.250446 0.272213 N1 0.832247 -0.482704 0.272693 N2 0.853889 -0.495256 0.159982 + txt003 +STRI + V0 1.71335 -1.0063 1.1309 V1 1.91065 -0.531754 1.1309 V2 1.85816 -0.517147 1.37222 + N0 0.853889 -0.495256 0.159982 N1 0.953145 -0.256935 0.159686 N2 0.929073 -0.250446 0.272213 + txt003 +STRI + V0 1.66628 -0.978656 1.37222 V1 1.36741 -1.36741 1.37222 V2 1.40603 -1.40603 1.1309 + N0 0.832247 -0.482704 0.272693 N1 0.680271 -0.680271 0.272877 N2 0.697986 -0.697986 0.160096 + txt003 +STRI + V0 1.40603 -1.40603 1.1309 V1 1.71335 -1.0063 1.1309 V2 1.66628 -0.978656 1.37222 + N0 0.697986 -0.697986 0.160096 N1 0.853889 -0.495256 0.159982 N2 0.832247 -0.482704 0.272693 + txt003 +STRI + V0 1.36741 -1.36741 1.37222 V1 0.978656 -1.66628 1.37222 V2 1.0063 -1.71335 1.1309 + N0 0.680271 -0.680271 0.272877 N1 0.482704 -0.832247 0.272693 N2 0.495256 -0.853889 0.159982 + txt003 +STRI + V0 1.0063 -1.71335 1.1309 V1 1.40603 -1.40603 1.1309 V2 1.36741 -1.36741 1.37222 + N0 0.495256 -0.853889 0.159982 N1 0.697986 -0.697986 0.160096 N2 0.680271 -0.680271 0.272877 + txt003 +STRI + V0 0.978656 -1.66628 1.37222 V1 0.517147 -1.85816 1.37222 V2 0.531754 -1.91065 1.1309 + N0 0.482704 -0.832247 0.272693 N1 0.250446 -0.929073 0.272213 N2 0.256935 -0.953145 0.159686 + txt003 +STRI + V0 0.531754 -1.91065 1.1309 V1 1.0063 -1.71335 1.1309 V2 0.978656 -1.66628 1.37222 + N0 0.256935 -0.953145 0.159686 N1 0.495256 -0.853889 0.159982 N2 0.482704 -0.832247 0.272693 + txt003 +STRI + V0 0.517147 -1.85816 1.37222 V1 2.22045e-16 -1.92593 1.37222 V2 -2.22045e-16 -1.98032 1.1309 + N0 0.250446 -0.929073 0.272213 N1 -1.11936e-16 -0.96234 0.271848 N2 -6.38555e-17 -0.987204 0.15946 + txt003 +STRI + V0 -2.22045e-16 -1.98032 1.1309 V1 0.531754 -1.91065 1.1309 V2 0.517147 -1.85816 1.37222 + N0 -6.38555e-17 -0.987204 0.15946 N1 0.256935 -0.953145 0.159686 N2 0.250446 -0.929073 0.272213 + txt003 +STRI + V0 1.98032 0 1.1309 V1 1.91065 -0.531754 1.1309 V2 1.92963 -0.537037 0.9 + N0 0.987204 0 0.15946 N1 0.953145 -0.256935 0.159686 N2 0.965535 -0.260275 5.17854e-17 + txt003 +STRI + V0 1.92963 -0.537037 0.9 V1 2 0 0.9 V2 1.98032 0 1.1309 + N0 0.965535 -0.260275 5.17854e-17 N1 1 0 0 N2 0.987204 0 0.15946 + txt003 +STRI + V0 1.91065 -0.531754 1.1309 V1 1.71335 -1.0063 1.1309 V2 1.73037 -1.0163 0.9 + N0 0.953145 -0.256935 0.159686 N1 0.853889 -0.495256 0.159982 N2 0.865031 -0.501718 1.36587e-16 + txt003 +STRI + V0 1.73037 -1.0163 0.9 V1 1.92963 -0.537037 0.9 V2 1.91065 -0.531754 1.1309 + N0 0.865031 -0.501718 1.36587e-16 N1 0.965535 -0.260275 5.17854e-17 N2 0.953145 -0.256935 0.159686 + txt003 +STRI + V0 1.71335 -1.0063 1.1309 V1 1.40603 -1.40603 1.1309 V2 1.42 -1.42 0.9 + N0 0.853889 -0.495256 0.159982 N1 0.697986 -0.697986 0.160096 N2 0.707107 -0.707107 1.74455e-16 + txt003 +STRI + V0 1.42 -1.42 0.9 V1 1.73037 -1.0163 0.9 V2 1.71335 -1.0063 1.1309 + N0 0.707107 -0.707107 1.74455e-16 N1 0.865031 -0.501718 1.36587e-16 N2 0.853889 -0.495256 0.159982 + txt003 +STRI + V0 1.40603 -1.40603 1.1309 V1 1.0063 -1.71335 1.1309 V2 1.0163 -1.73037 0.9 + N0 0.697986 -0.697986 0.160096 N1 0.495256 -0.853889 0.159982 N2 0.501718 -0.865031 1.36587e-16 + txt003 +STRI + V0 1.0163 -1.73037 0.9 V1 1.42 -1.42 0.9 V2 1.40603 -1.40603 1.1309 + N0 0.501718 -0.865031 1.36587e-16 N1 0.707107 -0.707107 1.74455e-16 N2 0.697986 -0.697986 0.160096 + txt003 +STRI + V0 1.0063 -1.71335 1.1309 V1 0.531754 -1.91065 1.1309 V2 0.537037 -1.92963 0.9 + N0 0.495256 -0.853889 0.159982 N1 0.256935 -0.953145 0.159686 N2 0.260275 -0.965535 5.17854e-17 + txt003 +STRI + V0 0.537037 -1.92963 0.9 V1 1.0163 -1.73037 0.9 V2 1.0063 -1.71335 1.1309 + N0 0.260275 -0.965535 5.17854e-17 N1 0.501718 -0.865031 1.36587e-16 N2 0.495256 -0.853889 0.159982 + txt003 +STRI + V0 0.531754 -1.91065 1.1309 V1 -2.22045e-16 -1.98032 1.1309 V2 0 -2 0.9 + N0 0.256935 -0.953145 0.159686 N1 -6.38555e-17 -0.987204 0.15946 N2 0 -1 -0 + txt003 +STRI + V0 0 -2 0.9 V1 0.537037 -1.92963 0.9 V2 0.531754 -1.91065 1.1309 + N0 0 -1 -0 N1 0.260275 -0.965535 5.17854e-17 N2 0.256935 -0.953145 0.159686 + txt003 +STRI + V0 0 -1.5 2.4 V1 -0.402778 -1.44722 2.4 V2 -0.436032 -1.56671 2.13785 + N0 0 -0.902861 0.429934 N1 -0.234929 -0.871509 0.430442 N2 -0.235963 -0.875348 0.422003 + txt003 +STRI + V0 -0.436032 -1.56671 2.13785 V1 0 -1.62384 2.13785 V2 0 -1.5 2.4 + N0 -0.235963 -0.875348 0.422003 N1 0 -0.906828 0.4215 N2 0 -0.902861 0.429934 + txt003 +STRI + V0 -0.402778 -1.44722 2.4 V1 -0.762222 -1.29778 2.4 V2 -0.825153 -1.40492 2.13785 + N0 -0.234929 -0.871509 0.430442 N1 -0.4527 -0.780517 0.43111 N2 -0.4547 -0.783966 0.422664 + txt003 +STRI + V0 -0.825153 -1.40492 2.13785 V1 -0.436032 -1.56671 2.13785 V2 -0.402778 -1.44722 2.4 + N0 -0.4547 -0.783966 0.422664 N1 -0.235963 -0.875348 0.422003 N2 -0.234929 -0.871509 0.430442 + txt003 +STRI + V0 -0.762222 -1.29778 2.4 V1 -1.065 -1.065 2.4 V2 -1.15293 -1.15293 2.13785 + N0 -0.4527 -0.780517 0.43111 N1 -0.637936 -0.637936 0.431366 N2 -0.640758 -0.640758 0.422917 + txt003 +STRI + V0 -1.15293 -1.15293 2.13785 V1 -0.825153 -1.40492 2.13785 V2 -0.762222 -1.29778 2.4 + N0 -0.640758 -0.640758 0.422917 N1 -0.4547 -0.783966 0.422664 N2 -0.4527 -0.780517 0.43111 + txt003 +STRI + V0 -1.065 -1.065 2.4 V1 -1.29778 -0.762222 2.4 V2 -1.40492 -0.825153 2.13785 + N0 -0.637936 -0.637936 0.431366 N1 -0.780517 -0.4527 0.43111 N2 -0.783966 -0.4547 0.422664 + txt003 +STRI + V0 -1.40492 -0.825153 2.13785 V1 -1.15293 -1.15293 2.13785 V2 -1.065 -1.065 2.4 + N0 -0.783966 -0.4547 0.422664 N1 -0.640758 -0.640758 0.422917 N2 -0.637936 -0.637936 0.431366 + txt003 +STRI + V0 -1.29778 -0.762222 2.4 V1 -1.44722 -0.402778 2.4 V2 -1.56671 -0.436032 2.13785 + N0 -0.780517 -0.4527 0.43111 N1 -0.871509 -0.234929 0.430442 N2 -0.875348 -0.235963 0.422003 + txt003 +STRI + V0 -1.56671 -0.436032 2.13785 V1 -1.40492 -0.825153 2.13785 V2 -1.29778 -0.762222 2.4 + N0 -0.875348 -0.235963 0.422003 N1 -0.783966 -0.4547 0.422664 N2 -0.780517 -0.4527 0.43111 + txt003 +STRI + V0 -1.44722 -0.402778 2.4 V1 -1.5 0 2.4 V2 -1.62384 -2.22045e-16 2.13785 + N0 -0.871509 -0.234929 0.430442 N1 -0.902861 2.27296e-16 0.429934 N2 -0.906828 2.05843e-16 0.4215 + txt003 +STRI + V0 -1.62384 -2.22045e-16 2.13785 V1 -1.56671 -0.436032 2.13785 V2 -1.44722 -0.402778 2.4 + N0 -0.906828 2.05843e-16 0.4215 N1 -0.875348 -0.235963 0.422003 N2 -0.871509 -0.234929 0.430442 + txt003 +STRI + V0 0 -1.62384 2.13785 V1 -0.436032 -1.56671 2.13785 V2 -0.467421 -1.67949 1.87778 + N0 0 -0.906828 0.4215 N1 -0.235963 -0.875348 0.422003 N2 -0.239043 -0.886771 0.395595 + txt003 +STRI + V0 -0.467421 -1.67949 1.87778 V1 0 -1.74074 1.87778 V2 0 -1.62384 2.13785 + N0 -0.239043 -0.886771 0.395595 N1 0 -0.918633 0.395111 N2 0 -0.906828 0.4215 + txt003 +STRI + V0 -0.436032 -1.56671 2.13785 V1 -0.825153 -1.40492 2.13785 V2 -0.884554 -1.50606 1.87778 + N0 -0.235963 -0.875348 0.422003 N1 -0.4547 -0.783966 0.422664 N2 -0.460653 -0.794229 0.39623 + txt003 +STRI + V0 -0.884554 -1.50606 1.87778 V1 -0.467421 -1.67949 1.87778 V2 -0.436032 -1.56671 2.13785 + N0 -0.460653 -0.794229 0.39623 N1 -0.239043 -0.886771 0.395595 N2 -0.235963 -0.875348 0.422003 + txt003 +STRI + V0 -0.825153 -1.40492 2.13785 V1 -1.15293 -1.15293 2.13785 V2 -1.23593 -1.23593 1.87778 + N0 -0.4547 -0.783966 0.422664 N1 -0.640758 -0.640758 0.422917 N2 -0.649156 -0.649156 0.396474 + txt003 +STRI + V0 -1.23593 -1.23593 1.87778 V1 -0.884554 -1.50606 1.87778 V2 -0.825153 -1.40492 2.13785 + N0 -0.649156 -0.649156 0.396474 N1 -0.460653 -0.794229 0.39623 N2 -0.4547 -0.783966 0.422664 + txt003 +STRI + V0 -1.15293 -1.15293 2.13785 V1 -1.40492 -0.825153 2.13785 V2 -1.50606 -0.884554 1.87778 + N0 -0.640758 -0.640758 0.422917 N1 -0.783966 -0.4547 0.422664 N2 -0.794229 -0.460653 0.39623 + txt003 +STRI + V0 -1.50606 -0.884554 1.87778 V1 -1.23593 -1.23593 1.87778 V2 -1.15293 -1.15293 2.13785 + N0 -0.794229 -0.460653 0.39623 N1 -0.649156 -0.649156 0.396474 N2 -0.640758 -0.640758 0.422917 + txt003 +STRI + V0 -1.40492 -0.825153 2.13785 V1 -1.56671 -0.436032 2.13785 V2 -1.67949 -0.467421 1.87778 + N0 -0.783966 -0.4547 0.422664 N1 -0.875348 -0.235963 0.422003 N2 -0.886771 -0.239043 0.395595 + txt003 +STRI + V0 -1.67949 -0.467421 1.87778 V1 -1.50606 -0.884554 1.87778 V2 -1.40492 -0.825153 2.13785 + N0 -0.886771 -0.239043 0.395595 N1 -0.794229 -0.460653 0.39623 N2 -0.783966 -0.4547 0.422664 + txt003 +STRI + V0 -1.56671 -0.436032 2.13785 V1 -1.62384 -2.22045e-16 2.13785 V2 -1.74074 0 1.87778 + N0 -0.875348 -0.235963 0.422003 N1 -0.906828 2.05843e-16 0.4215 N2 -0.918633 1.79998e-16 0.395111 + txt003 +STRI + V0 -1.74074 0 1.87778 V1 -1.67949 -0.467421 1.87778 V2 -1.56671 -0.436032 2.13785 + N0 -0.918633 1.79998e-16 0.395111 N1 -0.886771 -0.239043 0.395595 N2 -0.875348 -0.235963 0.422003 + txt003 +STRI + V0 0 -1.74074 1.87778 V1 -0.467421 -1.67949 1.87778 V2 -0.495081 -1.77888 1.62188 + N0 0 -0.918633 0.395111 N1 -0.239043 -0.886771 0.395595 N2 -0.244029 -0.90527 0.347757 + txt003 +STRI + V0 -0.495081 -1.77888 1.62188 V1 0 -1.84375 1.62188 V2 0 -1.74074 1.87778 + N0 -0.244029 -0.90527 0.347757 N1 0 -0.937749 0.347314 N2 0 -0.918633 0.395111 + txt003 +STRI + V0 -0.467421 -1.67949 1.87778 V1 -0.884554 -1.50606 1.87778 V2 -0.936898 -1.59519 1.62188 + N0 -0.239043 -0.886771 0.395595 N1 -0.460653 -0.794229 0.39623 N2 -0.470295 -0.810853 0.34834 + txt003 +STRI + V0 -0.936898 -1.59519 1.62188 V1 -0.495081 -1.77888 1.62188 V2 -0.467421 -1.67949 1.87778 + N0 -0.470295 -0.810853 0.34834 N1 -0.244029 -0.90527 0.347757 N2 -0.239043 -0.886771 0.395595 + txt003 +STRI + V0 -0.884554 -1.50606 1.87778 V1 -1.23593 -1.23593 1.87778 V2 -1.30906 -1.30906 1.62188 + N0 -0.460653 -0.794229 0.39623 N1 -0.649156 -0.649156 0.396474 N2 -0.662761 -0.662761 0.348563 + txt003 +STRI + V0 -1.30906 -1.30906 1.62188 V1 -0.936898 -1.59519 1.62188 V2 -0.884554 -1.50606 1.87778 + N0 -0.662761 -0.662761 0.348563 N1 -0.470295 -0.810853 0.34834 N2 -0.460653 -0.794229 0.39623 + txt003 +STRI + V0 -1.23593 -1.23593 1.87778 V1 -1.50606 -0.884554 1.87778 V2 -1.59519 -0.936898 1.62187 + N0 -0.649156 -0.649156 0.396474 N1 -0.794229 -0.460653 0.39623 N2 -0.810853 -0.470295 0.34834 + txt003 +STRI + V0 -1.59519 -0.936898 1.62187 V1 -1.30906 -1.30906 1.62188 V2 -1.23593 -1.23593 1.87778 + N0 -0.810853 -0.470295 0.34834 N1 -0.662761 -0.662761 0.348563 N2 -0.649156 -0.649156 0.396474 + txt003 +STRI + V0 -1.50606 -0.884554 1.87778 V1 -1.67949 -0.467421 1.87778 V2 -1.77888 -0.495081 1.62187 + N0 -0.794229 -0.460653 0.39623 N1 -0.886771 -0.239043 0.395595 N2 -0.90527 -0.244029 0.347757 + txt003 +STRI + V0 -1.77888 -0.495081 1.62187 V1 -1.59519 -0.936898 1.62187 V2 -1.50606 -0.884554 1.87778 + N0 -0.90527 -0.244029 0.347757 N1 -0.810853 -0.470295 0.34834 N2 -0.794229 -0.460653 0.39623 + txt003 +STRI + V0 -1.67949 -0.467421 1.87778 V1 -1.74074 0 1.87778 V2 -1.84375 0 1.62187 + N0 -0.886771 -0.239043 0.395595 N1 -0.918633 1.79998e-16 0.395111 N2 -0.937749 1.49384e-16 0.347314 + txt003 +STRI + V0 -1.84375 0 1.62187 V1 -1.77888 -0.495081 1.62187 V2 -1.67949 -0.467421 1.87778 + N0 -0.937749 1.49384e-16 0.347314 N1 -0.90527 -0.244029 0.347757 N2 -0.886771 -0.239043 0.395595 + txt003 +STRI + V0 0 -1.84375 1.62188 V1 -0.495081 -1.77888 1.62188 V2 -0.517147 -1.85816 1.37222 + N0 0 -0.937749 0.347314 N1 -0.244029 -0.90527 0.347757 N2 -0.250446 -0.929073 0.272213 + txt003 +STRI + V0 -0.517147 -1.85816 1.37222 V1 0 -1.92593 1.37222 V2 0 -1.84375 1.62188 + N0 -0.250446 -0.929073 0.272213 N1 0 -0.96234 0.271848 N2 0 -0.937749 0.347314 + txt003 +STRI + V0 -0.495081 -1.77888 1.62188 V1 -0.936898 -1.59519 1.62188 V2 -0.978656 -1.66628 1.37222 + N0 -0.244029 -0.90527 0.347757 N1 -0.470295 -0.810853 0.34834 N2 -0.482704 -0.832247 0.272693 + txt003 +STRI + V0 -0.978656 -1.66628 1.37222 V1 -0.517147 -1.85816 1.37222 V2 -0.495081 -1.77888 1.62188 + N0 -0.482704 -0.832247 0.272693 N1 -0.250446 -0.929073 0.272213 N2 -0.244029 -0.90527 0.347757 + txt003 +STRI + V0 -0.936898 -1.59519 1.62188 V1 -1.30906 -1.30906 1.62188 V2 -1.36741 -1.36741 1.37222 + N0 -0.470295 -0.810853 0.34834 N1 -0.662761 -0.662761 0.348563 N2 -0.680271 -0.680271 0.272877 + txt003 +STRI + V0 -1.36741 -1.36741 1.37222 V1 -0.978656 -1.66628 1.37222 V2 -0.936898 -1.59519 1.62188 + N0 -0.680271 -0.680271 0.272877 N1 -0.482704 -0.832247 0.272693 N2 -0.470295 -0.810853 0.34834 + txt003 +STRI + V0 -1.30906 -1.30906 1.62188 V1 -1.59519 -0.936898 1.62187 V2 -1.66628 -0.978656 1.37222 + N0 -0.662761 -0.662761 0.348563 N1 -0.810853 -0.470295 0.34834 N2 -0.832247 -0.482704 0.272693 + txt003 +STRI + V0 -1.66628 -0.978656 1.37222 V1 -1.36741 -1.36741 1.37222 V2 -1.30906 -1.30906 1.62188 + N0 -0.832247 -0.482704 0.272693 N1 -0.680271 -0.680271 0.272877 N2 -0.662761 -0.662761 0.348563 + txt003 +STRI + V0 -1.59519 -0.936898 1.62187 V1 -1.77888 -0.495081 1.62187 V2 -1.85816 -0.517147 1.37222 + N0 -0.810853 -0.470295 0.34834 N1 -0.90527 -0.244029 0.347757 N2 -0.929073 -0.250446 0.272213 + txt003 +STRI + V0 -1.85816 -0.517147 1.37222 V1 -1.66628 -0.978656 1.37222 V2 -1.59519 -0.936898 1.62187 + N0 -0.929073 -0.250446 0.272213 N1 -0.832247 -0.482704 0.272693 N2 -0.810853 -0.470295 0.34834 + txt003 +STRI + V0 -1.77888 -0.495081 1.62187 V1 -1.84375 0 1.62187 V2 -1.92593 -2.22045e-16 1.37222 + N0 -0.90527 -0.244029 0.347757 N1 -0.937749 1.49384e-16 0.347314 N2 -0.96234 1.11936e-16 0.271848 + txt003 +STRI + V0 -1.92593 -2.22045e-16 1.37222 V1 -1.85816 -0.517147 1.37222 V2 -1.77888 -0.495081 1.62187 + N0 -0.96234 1.11936e-16 0.271848 N1 -0.929073 -0.250446 0.272213 N2 -0.90527 -0.244029 0.347757 + txt003 +STRI + V0 0 -1.92593 1.37222 V1 -0.517147 -1.85816 1.37222 V2 -0.531754 -1.91065 1.1309 + N0 0 -0.96234 0.271848 N1 -0.250446 -0.929073 0.272213 N2 -0.256935 -0.953145 0.159686 + txt003 +STRI + V0 -0.531754 -1.91065 1.1309 V1 0 -1.98032 1.1309 V2 0 -1.92593 1.37222 + N0 -0.256935 -0.953145 0.159686 N1 0 -0.987204 0.15946 N2 0 -0.96234 0.271848 + txt003 +STRI + V0 -0.517147 -1.85816 1.37222 V1 -0.978656 -1.66628 1.37222 V2 -1.0063 -1.71335 1.1309 + N0 -0.250446 -0.929073 0.272213 N1 -0.482704 -0.832247 0.272693 N2 -0.495256 -0.853889 0.159982 + txt003 +STRI + V0 -1.0063 -1.71335 1.1309 V1 -0.531754 -1.91065 1.1309 V2 -0.517147 -1.85816 1.37222 + N0 -0.495256 -0.853889 0.159982 N1 -0.256935 -0.953145 0.159686 N2 -0.250446 -0.929073 0.272213 + txt003 +STRI + V0 -0.978656 -1.66628 1.37222 V1 -1.36741 -1.36741 1.37222 V2 -1.40603 -1.40603 1.1309 + N0 -0.482704 -0.832247 0.272693 N1 -0.680271 -0.680271 0.272877 N2 -0.697986 -0.697986 0.160096 + txt003 +STRI + V0 -1.40603 -1.40603 1.1309 V1 -1.0063 -1.71335 1.1309 V2 -0.978656 -1.66628 1.37222 + N0 -0.697986 -0.697986 0.160096 N1 -0.495256 -0.853889 0.159982 N2 -0.482704 -0.832247 0.272693 + txt003 +STRI + V0 -1.36741 -1.36741 1.37222 V1 -1.66628 -0.978656 1.37222 V2 -1.71335 -1.0063 1.1309 + N0 -0.680271 -0.680271 0.272877 N1 -0.832247 -0.482704 0.272693 N2 -0.853889 -0.495256 0.159982 + txt003 +STRI + V0 -1.71335 -1.0063 1.1309 V1 -1.40603 -1.40603 1.1309 V2 -1.36741 -1.36741 1.37222 + N0 -0.853889 -0.495256 0.159982 N1 -0.697986 -0.697986 0.160096 N2 -0.680271 -0.680271 0.272877 + txt003 +STRI + V0 -1.66628 -0.978656 1.37222 V1 -1.85816 -0.517147 1.37222 V2 -1.91065 -0.531754 1.1309 + N0 -0.832247 -0.482704 0.272693 N1 -0.929073 -0.250446 0.272213 N2 -0.953145 -0.256935 0.159686 + txt003 +STRI + V0 -1.91065 -0.531754 1.1309 V1 -1.71335 -1.0063 1.1309 V2 -1.66628 -0.978656 1.37222 + N0 -0.953145 -0.256935 0.159686 N1 -0.853889 -0.495256 0.159982 N2 -0.832247 -0.482704 0.272693 + txt003 +STRI + V0 -1.85816 -0.517147 1.37222 V1 -1.92593 -2.22045e-16 1.37222 V2 -1.98032 2.22045e-16 1.1309 + N0 -0.929073 -0.250446 0.272213 N1 -0.96234 1.11936e-16 0.271848 N2 -0.987204 6.38555e-17 0.15946 + txt003 +STRI + V0 -1.98032 2.22045e-16 1.1309 V1 -1.91065 -0.531754 1.1309 V2 -1.85816 -0.517147 1.37222 + N0 -0.987204 6.38555e-17 0.15946 N1 -0.953145 -0.256935 0.159686 N2 -0.929073 -0.250446 0.272213 + txt003 +STRI + V0 0 -1.98032 1.1309 V1 -0.531754 -1.91065 1.1309 V2 -0.537037 -1.92963 0.9 + N0 0 -0.987204 0.15946 N1 -0.256935 -0.953145 0.159686 N2 -0.260275 -0.965535 5.17854e-17 + txt003 +STRI + V0 -0.537037 -1.92963 0.9 V1 0 -2 0.9 V2 0 -1.98032 1.1309 + N0 -0.260275 -0.965535 5.17854e-17 N1 -0 -1 -0 N2 0 -0.987204 0.15946 + txt003 +STRI + V0 -0.531754 -1.91065 1.1309 V1 -1.0063 -1.71335 1.1309 V2 -1.0163 -1.73037 0.9 + N0 -0.256935 -0.953145 0.159686 N1 -0.495256 -0.853889 0.159982 N2 -0.501718 -0.865031 1.36587e-16 + txt003 +STRI + V0 -1.0163 -1.73037 0.9 V1 -0.537037 -1.92963 0.9 V2 -0.531754 -1.91065 1.1309 + N0 -0.501718 -0.865031 1.36587e-16 N1 -0.260275 -0.965535 5.17854e-17 N2 -0.256935 -0.953145 0.159686 + txt003 +STRI + V0 -1.0063 -1.71335 1.1309 V1 -1.40603 -1.40603 1.1309 V2 -1.42 -1.42 0.9 + N0 -0.495256 -0.853889 0.159982 N1 -0.697986 -0.697986 0.160096 N2 -0.707107 -0.707107 1.74455e-16 + txt003 +STRI + V0 -1.42 -1.42 0.9 V1 -1.0163 -1.73037 0.9 V2 -1.0063 -1.71335 1.1309 + N0 -0.707107 -0.707107 1.74455e-16 N1 -0.501718 -0.865031 1.36587e-16 N2 -0.495256 -0.853889 0.159982 + txt003 +STRI + V0 -1.40603 -1.40603 1.1309 V1 -1.71335 -1.0063 1.1309 V2 -1.73037 -1.0163 0.9 + N0 -0.697986 -0.697986 0.160096 N1 -0.853889 -0.495256 0.159982 N2 -0.865031 -0.501718 1.36587e-16 + txt003 +STRI + V0 -1.73037 -1.0163 0.9 V1 -1.42 -1.42 0.9 V2 -1.40603 -1.40603 1.1309 + N0 -0.865031 -0.501718 1.36587e-16 N1 -0.707107 -0.707107 1.74455e-16 N2 -0.697986 -0.697986 0.160096 + txt003 +STRI + V0 -1.71335 -1.0063 1.1309 V1 -1.91065 -0.531754 1.1309 V2 -1.92963 -0.537037 0.9 + N0 -0.853889 -0.495256 0.159982 N1 -0.953145 -0.256935 0.159686 N2 -0.965535 -0.260275 5.17854e-17 + txt003 +STRI + V0 -1.92963 -0.537037 0.9 V1 -1.73037 -1.0163 0.9 V2 -1.71335 -1.0063 1.1309 + N0 -0.965535 -0.260275 5.17854e-17 N1 -0.865031 -0.501718 1.36587e-16 N2 -0.853889 -0.495256 0.159982 + txt003 +STRI + V0 -1.91065 -0.531754 1.1309 V1 -1.98032 2.22045e-16 1.1309 V2 -2 0 0.9 + N0 -0.953145 -0.256935 0.159686 N1 -0.987204 6.38555e-17 0.15946 N2 -1 0 0 + txt003 +STRI + V0 -2 0 0.9 V1 -1.92963 -0.537037 0.9 V2 -1.91065 -0.531754 1.1309 + N0 -1 0 0 N1 -0.965535 -0.260275 5.17854e-17 N2 -0.953145 -0.256935 0.159686 + txt003 +STRI + V0 -1.5 0 2.4 V1 -1.44722 0.402778 2.4 V2 -1.56671 0.436032 2.13785 + N0 -0.902861 0 0.429934 N1 -0.871509 0.234929 0.430442 N2 -0.875348 0.235963 0.422003 + txt003 +STRI + V0 -1.56671 0.436032 2.13785 V1 -1.62384 0 2.13785 V2 -1.5 0 2.4 + N0 -0.875348 0.235963 0.422003 N1 -0.906828 0 0.4215 N2 -0.902861 0 0.429934 + txt003 +STRI + V0 -1.44722 0.402778 2.4 V1 -1.29778 0.762222 2.4 V2 -1.40492 0.825153 2.13785 + N0 -0.871509 0.234929 0.430442 N1 -0.780517 0.4527 0.43111 N2 -0.783966 0.4547 0.422664 + txt003 +STRI + V0 -1.40492 0.825153 2.13785 V1 -1.56671 0.436032 2.13785 V2 -1.44722 0.402778 2.4 + N0 -0.783966 0.4547 0.422664 N1 -0.875348 0.235963 0.422003 N2 -0.871509 0.234929 0.430442 + txt003 +STRI + V0 -1.29778 0.762222 2.4 V1 -1.065 1.065 2.4 V2 -1.15293 1.15293 2.13785 + N0 -0.780517 0.4527 0.43111 N1 -0.637936 0.637936 0.431366 N2 -0.640758 0.640758 0.422917 + txt003 +STRI + V0 -1.15293 1.15293 2.13785 V1 -1.40492 0.825153 2.13785 V2 -1.29778 0.762222 2.4 + N0 -0.640758 0.640758 0.422917 N1 -0.783966 0.4547 0.422664 N2 -0.780517 0.4527 0.43111 + txt003 +STRI + V0 -1.065 1.065 2.4 V1 -0.762222 1.29778 2.4 V2 -0.825153 1.40492 2.13785 + N0 -0.637936 0.637936 0.431366 N1 -0.4527 0.780517 0.43111 N2 -0.4547 0.783966 0.422664 + txt003 +STRI + V0 -0.825153 1.40492 2.13785 V1 -1.15293 1.15293 2.13785 V2 -1.065 1.065 2.4 + N0 -0.4547 0.783966 0.422664 N1 -0.640758 0.640758 0.422917 N2 -0.637936 0.637936 0.431366 + txt003 +STRI + V0 -0.762222 1.29778 2.4 V1 -0.402778 1.44722 2.4 V2 -0.436032 1.56671 2.13785 + N0 -0.4527 0.780517 0.43111 N1 -0.234929 0.871509 0.430442 N2 -0.235963 0.875348 0.422003 + txt003 +STRI + V0 -0.436032 1.56671 2.13785 V1 -0.825153 1.40492 2.13785 V2 -0.762222 1.29778 2.4 + N0 -0.235963 0.875348 0.422003 N1 -0.4547 0.783966 0.422664 N2 -0.4527 0.780517 0.43111 + txt003 +STRI + V0 -0.402778 1.44722 2.4 V1 0 1.5 2.4 V2 -2.22045e-16 1.62384 2.13785 + N0 -0.234929 0.871509 0.430442 N1 2.27296e-16 0.902861 0.429934 N2 2.05843e-16 0.906828 0.4215 + txt003 +STRI + V0 -2.22045e-16 1.62384 2.13785 V1 -0.436032 1.56671 2.13785 V2 -0.402778 1.44722 2.4 + N0 2.05843e-16 0.906828 0.4215 N1 -0.235963 0.875348 0.422003 N2 -0.234929 0.871509 0.430442 + txt003 +STRI + V0 -1.62384 0 2.13785 V1 -1.56671 0.436032 2.13785 V2 -1.67949 0.467421 1.87778 + N0 -0.906828 0 0.4215 N1 -0.875348 0.235963 0.422003 N2 -0.886771 0.239043 0.395595 + txt003 +STRI + V0 -1.67949 0.467421 1.87778 V1 -1.74074 0 1.87778 V2 -1.62384 0 2.13785 + N0 -0.886771 0.239043 0.395595 N1 -0.918633 0 0.395111 N2 -0.906828 0 0.4215 + txt003 +STRI + V0 -1.56671 0.436032 2.13785 V1 -1.40492 0.825153 2.13785 V2 -1.50606 0.884554 1.87778 + N0 -0.875348 0.235963 0.422003 N1 -0.783966 0.4547 0.422664 N2 -0.794229 0.460653 0.39623 + txt003 +STRI + V0 -1.50606 0.884554 1.87778 V1 -1.67949 0.467421 1.87778 V2 -1.56671 0.436032 2.13785 + N0 -0.794229 0.460653 0.39623 N1 -0.886771 0.239043 0.395595 N2 -0.875348 0.235963 0.422003 + txt003 +STRI + V0 -1.40492 0.825153 2.13785 V1 -1.15293 1.15293 2.13785 V2 -1.23593 1.23593 1.87778 + N0 -0.783966 0.4547 0.422664 N1 -0.640758 0.640758 0.422917 N2 -0.649156 0.649156 0.396474 + txt003 +STRI + V0 -1.23593 1.23593 1.87778 V1 -1.50606 0.884554 1.87778 V2 -1.40492 0.825153 2.13785 + N0 -0.649156 0.649156 0.396474 N1 -0.794229 0.460653 0.39623 N2 -0.783966 0.4547 0.422664 + txt003 +STRI + V0 -1.15293 1.15293 2.13785 V1 -0.825153 1.40492 2.13785 V2 -0.884554 1.50606 1.87778 + N0 -0.640758 0.640758 0.422917 N1 -0.4547 0.783966 0.422664 N2 -0.460653 0.794229 0.39623 + txt003 +STRI + V0 -0.884554 1.50606 1.87778 V1 -1.23593 1.23593 1.87778 V2 -1.15293 1.15293 2.13785 + N0 -0.460653 0.794229 0.39623 N1 -0.649156 0.649156 0.396474 N2 -0.640758 0.640758 0.422917 + txt003 +STRI + V0 -0.825153 1.40492 2.13785 V1 -0.436032 1.56671 2.13785 V2 -0.467421 1.67949 1.87778 + N0 -0.4547 0.783966 0.422664 N1 -0.235963 0.875348 0.422003 N2 -0.239043 0.886771 0.395595 + txt003 +STRI + V0 -0.467421 1.67949 1.87778 V1 -0.884554 1.50606 1.87778 V2 -0.825153 1.40492 2.13785 + N0 -0.239043 0.886771 0.395595 N1 -0.460653 0.794229 0.39623 N2 -0.4547 0.783966 0.422664 + txt003 +STRI + V0 -0.436032 1.56671 2.13785 V1 -2.22045e-16 1.62384 2.13785 V2 0 1.74074 1.87778 + N0 -0.235963 0.875348 0.422003 N1 2.05843e-16 0.906828 0.4215 N2 1.79998e-16 0.918633 0.395111 + txt003 +STRI + V0 0 1.74074 1.87778 V1 -0.467421 1.67949 1.87778 V2 -0.436032 1.56671 2.13785 + N0 1.79998e-16 0.918633 0.395111 N1 -0.239043 0.886771 0.395595 N2 -0.235963 0.875348 0.422003 + txt003 +STRI + V0 -1.74074 0 1.87778 V1 -1.67949 0.467421 1.87778 V2 -1.77888 0.495081 1.62188 + N0 -0.918633 0 0.395111 N1 -0.886771 0.239043 0.395595 N2 -0.90527 0.244029 0.347757 + txt003 +STRI + V0 -1.77888 0.495081 1.62188 V1 -1.84375 0 1.62188 V2 -1.74074 0 1.87778 + N0 -0.90527 0.244029 0.347757 N1 -0.937749 0 0.347314 N2 -0.918633 0 0.395111 + txt003 +STRI + V0 -1.67949 0.467421 1.87778 V1 -1.50606 0.884554 1.87778 V2 -1.59519 0.936898 1.62188 + N0 -0.886771 0.239043 0.395595 N1 -0.794229 0.460653 0.39623 N2 -0.810853 0.470295 0.34834 + txt003 +STRI + V0 -1.59519 0.936898 1.62188 V1 -1.77888 0.495081 1.62188 V2 -1.67949 0.467421 1.87778 + N0 -0.810853 0.470295 0.34834 N1 -0.90527 0.244029 0.347757 N2 -0.886771 0.239043 0.395595 + txt003 +STRI + V0 -1.50606 0.884554 1.87778 V1 -1.23593 1.23593 1.87778 V2 -1.30906 1.30906 1.62188 + N0 -0.794229 0.460653 0.39623 N1 -0.649156 0.649156 0.396474 N2 -0.662761 0.662761 0.348563 + txt003 +STRI + V0 -1.30906 1.30906 1.62188 V1 -1.59519 0.936898 1.62188 V2 -1.50606 0.884554 1.87778 + N0 -0.662761 0.662761 0.348563 N1 -0.810853 0.470295 0.34834 N2 -0.794229 0.460653 0.39623 + txt003 +STRI + V0 -1.23593 1.23593 1.87778 V1 -0.884554 1.50606 1.87778 V2 -0.936898 1.59519 1.62187 + N0 -0.649156 0.649156 0.396474 N1 -0.460653 0.794229 0.39623 N2 -0.470295 0.810853 0.34834 + txt003 +STRI + V0 -0.936898 1.59519 1.62187 V1 -1.30906 1.30906 1.62188 V2 -1.23593 1.23593 1.87778 + N0 -0.470295 0.810853 0.34834 N1 -0.662761 0.662761 0.348563 N2 -0.649156 0.649156 0.396474 + txt003 +STRI + V0 -0.884554 1.50606 1.87778 V1 -0.467421 1.67949 1.87778 V2 -0.495081 1.77888 1.62187 + N0 -0.460653 0.794229 0.39623 N1 -0.239043 0.886771 0.395595 N2 -0.244029 0.90527 0.347757 + txt003 +STRI + V0 -0.495081 1.77888 1.62187 V1 -0.936898 1.59519 1.62187 V2 -0.884554 1.50606 1.87778 + N0 -0.244029 0.90527 0.347757 N1 -0.470295 0.810853 0.34834 N2 -0.460653 0.794229 0.39623 + txt003 +STRI + V0 -0.467421 1.67949 1.87778 V1 0 1.74074 1.87778 V2 0 1.84375 1.62187 + N0 -0.239043 0.886771 0.395595 N1 1.79998e-16 0.918633 0.395111 N2 1.49384e-16 0.937749 0.347314 + txt003 +STRI + V0 0 1.84375 1.62187 V1 -0.495081 1.77888 1.62187 V2 -0.467421 1.67949 1.87778 + N0 1.49384e-16 0.937749 0.347314 N1 -0.244029 0.90527 0.347757 N2 -0.239043 0.886771 0.395595 + txt003 +STRI + V0 -1.84375 0 1.62188 V1 -1.77888 0.495081 1.62188 V2 -1.85816 0.517147 1.37222 + N0 -0.937749 0 0.347314 N1 -0.90527 0.244029 0.347757 N2 -0.929073 0.250446 0.272213 + txt003 +STRI + V0 -1.85816 0.517147 1.37222 V1 -1.92593 0 1.37222 V2 -1.84375 0 1.62188 + N0 -0.929073 0.250446 0.272213 N1 -0.96234 0 0.271848 N2 -0.937749 0 0.347314 + txt003 +STRI + V0 -1.77888 0.495081 1.62188 V1 -1.59519 0.936898 1.62188 V2 -1.66628 0.978656 1.37222 + N0 -0.90527 0.244029 0.347757 N1 -0.810853 0.470295 0.34834 N2 -0.832247 0.482704 0.272693 + txt003 +STRI + V0 -1.66628 0.978656 1.37222 V1 -1.85816 0.517147 1.37222 V2 -1.77888 0.495081 1.62188 + N0 -0.832247 0.482704 0.272693 N1 -0.929073 0.250446 0.272213 N2 -0.90527 0.244029 0.347757 + txt003 +STRI + V0 -1.59519 0.936898 1.62188 V1 -1.30906 1.30906 1.62188 V2 -1.36741 1.36741 1.37222 + N0 -0.810853 0.470295 0.34834 N1 -0.662761 0.662761 0.348563 N2 -0.680271 0.680271 0.272877 + txt003 +STRI + V0 -1.36741 1.36741 1.37222 V1 -1.66628 0.978656 1.37222 V2 -1.59519 0.936898 1.62188 + N0 -0.680271 0.680271 0.272877 N1 -0.832247 0.482704 0.272693 N2 -0.810853 0.470295 0.34834 + txt003 +STRI + V0 -1.30906 1.30906 1.62188 V1 -0.936898 1.59519 1.62187 V2 -0.978656 1.66628 1.37222 + N0 -0.662761 0.662761 0.348563 N1 -0.470295 0.810853 0.34834 N2 -0.482704 0.832247 0.272693 + txt003 +STRI + V0 -0.978656 1.66628 1.37222 V1 -1.36741 1.36741 1.37222 V2 -1.30906 1.30906 1.62188 + N0 -0.482704 0.832247 0.272693 N1 -0.680271 0.680271 0.272877 N2 -0.662761 0.662761 0.348563 + txt003 +STRI + V0 -0.936898 1.59519 1.62187 V1 -0.495081 1.77888 1.62187 V2 -0.517147 1.85816 1.37222 + N0 -0.470295 0.810853 0.34834 N1 -0.244029 0.90527 0.347757 N2 -0.250446 0.929073 0.272213 + txt003 +STRI + V0 -0.517147 1.85816 1.37222 V1 -0.978656 1.66628 1.37222 V2 -0.936898 1.59519 1.62187 + N0 -0.250446 0.929073 0.272213 N1 -0.482704 0.832247 0.272693 N2 -0.470295 0.810853 0.34834 + txt003 +STRI + V0 -0.495081 1.77888 1.62187 V1 0 1.84375 1.62187 V2 -2.22045e-16 1.92593 1.37222 + N0 -0.244029 0.90527 0.347757 N1 1.49384e-16 0.937749 0.347314 N2 1.11936e-16 0.96234 0.271848 + txt003 +STRI + V0 -2.22045e-16 1.92593 1.37222 V1 -0.517147 1.85816 1.37222 V2 -0.495081 1.77888 1.62187 + N0 1.11936e-16 0.96234 0.271848 N1 -0.250446 0.929073 0.272213 N2 -0.244029 0.90527 0.347757 + txt003 +STRI + V0 -1.92593 0 1.37222 V1 -1.85816 0.517147 1.37222 V2 -1.91065 0.531754 1.1309 + N0 -0.96234 0 0.271848 N1 -0.929073 0.250446 0.272213 N2 -0.953145 0.256935 0.159686 + txt003 +STRI + V0 -1.91065 0.531754 1.1309 V1 -1.98032 0 1.1309 V2 -1.92593 0 1.37222 + N0 -0.953145 0.256935 0.159686 N1 -0.987204 0 0.15946 N2 -0.96234 0 0.271848 + txt003 +STRI + V0 -1.85816 0.517147 1.37222 V1 -1.66628 0.978656 1.37222 V2 -1.71335 1.0063 1.1309 + N0 -0.929073 0.250446 0.272213 N1 -0.832247 0.482704 0.272693 N2 -0.853889 0.495256 0.159982 + txt003 +STRI + V0 -1.71335 1.0063 1.1309 V1 -1.91065 0.531754 1.1309 V2 -1.85816 0.517147 1.37222 + N0 -0.853889 0.495256 0.159982 N1 -0.953145 0.256935 0.159686 N2 -0.929073 0.250446 0.272213 + txt003 +STRI + V0 -1.66628 0.978656 1.37222 V1 -1.36741 1.36741 1.37222 V2 -1.40603 1.40603 1.1309 + N0 -0.832247 0.482704 0.272693 N1 -0.680271 0.680271 0.272877 N2 -0.697986 0.697986 0.160096 + txt003 +STRI + V0 -1.40603 1.40603 1.1309 V1 -1.71335 1.0063 1.1309 V2 -1.66628 0.978656 1.37222 + N0 -0.697986 0.697986 0.160096 N1 -0.853889 0.495256 0.159982 N2 -0.832247 0.482704 0.272693 + txt003 +STRI + V0 -1.36741 1.36741 1.37222 V1 -0.978656 1.66628 1.37222 V2 -1.0063 1.71335 1.1309 + N0 -0.680271 0.680271 0.272877 N1 -0.482704 0.832247 0.272693 N2 -0.495256 0.853889 0.159982 + txt003 +STRI + V0 -1.0063 1.71335 1.1309 V1 -1.40603 1.40603 1.1309 V2 -1.36741 1.36741 1.37222 + N0 -0.495256 0.853889 0.159982 N1 -0.697986 0.697986 0.160096 N2 -0.680271 0.680271 0.272877 + txt003 +STRI + V0 -0.978656 1.66628 1.37222 V1 -0.517147 1.85816 1.37222 V2 -0.531754 1.91065 1.1309 + N0 -0.482704 0.832247 0.272693 N1 -0.250446 0.929073 0.272213 N2 -0.256935 0.953145 0.159686 + txt003 +STRI + V0 -0.531754 1.91065 1.1309 V1 -1.0063 1.71335 1.1309 V2 -0.978656 1.66628 1.37222 + N0 -0.256935 0.953145 0.159686 N1 -0.495256 0.853889 0.159982 N2 -0.482704 0.832247 0.272693 + txt003 +STRI + V0 -0.517147 1.85816 1.37222 V1 -2.22045e-16 1.92593 1.37222 V2 2.22045e-16 1.98032 1.1309 + N0 -0.250446 0.929073 0.272213 N1 1.11936e-16 0.96234 0.271848 N2 6.38555e-17 0.987204 0.15946 + txt003 +STRI + V0 2.22045e-16 1.98032 1.1309 V1 -0.531754 1.91065 1.1309 V2 -0.517147 1.85816 1.37222 + N0 6.38555e-17 0.987204 0.15946 N1 -0.256935 0.953145 0.159686 N2 -0.250446 0.929073 0.272213 + txt003 +STRI + V0 -1.98032 0 1.1309 V1 -1.91065 0.531754 1.1309 V2 -1.92963 0.537037 0.9 + N0 -0.987204 0 0.15946 N1 -0.953145 0.256935 0.159686 N2 -0.965535 0.260275 5.17854e-17 + txt003 +STRI + V0 -1.92963 0.537037 0.9 V1 -2 0 0.9 V2 -1.98032 0 1.1309 + N0 -0.965535 0.260275 5.17854e-17 N1 -1 0 0 N2 -0.987204 0 0.15946 + txt003 +STRI + V0 -1.91065 0.531754 1.1309 V1 -1.71335 1.0063 1.1309 V2 -1.73037 1.0163 0.9 + N0 -0.953145 0.256935 0.159686 N1 -0.853889 0.495256 0.159982 N2 -0.865031 0.501718 1.36587e-16 + txt003 +STRI + V0 -1.73037 1.0163 0.9 V1 -1.92963 0.537037 0.9 V2 -1.91065 0.531754 1.1309 + N0 -0.865031 0.501718 1.36587e-16 N1 -0.965535 0.260275 5.17854e-17 N2 -0.953145 0.256935 0.159686 + txt003 +STRI + V0 -1.71335 1.0063 1.1309 V1 -1.40603 1.40603 1.1309 V2 -1.42 1.42 0.9 + N0 -0.853889 0.495256 0.159982 N1 -0.697986 0.697986 0.160096 N2 -0.707107 0.707107 1.74455e-16 + txt003 +STRI + V0 -1.42 1.42 0.9 V1 -1.73037 1.0163 0.9 V2 -1.71335 1.0063 1.1309 + N0 -0.707107 0.707107 1.74455e-16 N1 -0.865031 0.501718 1.36587e-16 N2 -0.853889 0.495256 0.159982 + txt003 +STRI + V0 -1.40603 1.40603 1.1309 V1 -1.0063 1.71335 1.1309 V2 -1.0163 1.73037 0.9 + N0 -0.697986 0.697986 0.160096 N1 -0.495256 0.853889 0.159982 N2 -0.501718 0.865031 1.36587e-16 + txt003 +STRI + V0 -1.0163 1.73037 0.9 V1 -1.42 1.42 0.9 V2 -1.40603 1.40603 1.1309 + N0 -0.501718 0.865031 1.36587e-16 N1 -0.707107 0.707107 1.74455e-16 N2 -0.697986 0.697986 0.160096 + txt003 +STRI + V0 -1.0063 1.71335 1.1309 V1 -0.531754 1.91065 1.1309 V2 -0.537037 1.92963 0.9 + N0 -0.495256 0.853889 0.159982 N1 -0.256935 0.953145 0.159686 N2 -0.260275 0.965535 5.17854e-17 + txt003 +STRI + V0 -0.537037 1.92963 0.9 V1 -1.0163 1.73037 0.9 V2 -1.0063 1.71335 1.1309 + N0 -0.260275 0.965535 5.17854e-17 N1 -0.501718 0.865031 1.36587e-16 N2 -0.495256 0.853889 0.159982 + txt003 +STRI + V0 -0.531754 1.91065 1.1309 V1 2.22045e-16 1.98032 1.1309 V2 0 2 0.9 + N0 -0.256935 0.953145 0.159686 N1 6.38555e-17 0.987204 0.15946 N2 0 1 0 + txt003 +STRI + V0 0 2 0.9 V1 -0.537037 1.92963 0.9 V2 -0.531754 1.91065 1.1309 + N0 0 1 0 N1 -0.260275 0.965535 5.17854e-17 N2 -0.256935 0.953145 0.159686 + txt003 +STRI + V0 0 1.5 2.4 V1 0.402778 1.44722 2.4 V2 0.436032 1.56671 2.13785 + N0 -0 0.902861 0.429934 N1 0.234929 0.871509 0.430442 N2 0.235963 0.875348 0.422003 + txt003 +STRI + V0 0.436032 1.56671 2.13785 V1 0 1.62384 2.13785 V2 0 1.5 2.4 + N0 0.235963 0.875348 0.422003 N1 -0 0.906828 0.4215 N2 -0 0.902861 0.429934 + txt003 +STRI + V0 0.402778 1.44722 2.4 V1 0.762222 1.29778 2.4 V2 0.825153 1.40492 2.13785 + N0 0.234929 0.871509 0.430442 N1 0.4527 0.780517 0.43111 N2 0.4547 0.783966 0.422664 + txt003 +STRI + V0 0.825153 1.40492 2.13785 V1 0.436032 1.56671 2.13785 V2 0.402778 1.44722 2.4 + N0 0.4547 0.783966 0.422664 N1 0.235963 0.875348 0.422003 N2 0.234929 0.871509 0.430442 + txt003 +STRI + V0 0.762222 1.29778 2.4 V1 1.065 1.065 2.4 V2 1.15293 1.15293 2.13785 + N0 0.4527 0.780517 0.43111 N1 0.637936 0.637936 0.431366 N2 0.640758 0.640758 0.422917 + txt003 +STRI + V0 1.15293 1.15293 2.13785 V1 0.825153 1.40492 2.13785 V2 0.762222 1.29778 2.4 + N0 0.640758 0.640758 0.422917 N1 0.4547 0.783966 0.422664 N2 0.4527 0.780517 0.43111 + txt003 +STRI + V0 1.065 1.065 2.4 V1 1.29778 0.762222 2.4 V2 1.40492 0.825153 2.13785 + N0 0.637936 0.637936 0.431366 N1 0.780517 0.4527 0.43111 N2 0.783966 0.4547 0.422664 + txt003 +STRI + V0 1.40492 0.825153 2.13785 V1 1.15293 1.15293 2.13785 V2 1.065 1.065 2.4 + N0 0.783966 0.4547 0.422664 N1 0.640758 0.640758 0.422917 N2 0.637936 0.637936 0.431366 + txt003 +STRI + V0 1.29778 0.762222 2.4 V1 1.44722 0.402778 2.4 V2 1.56671 0.436032 2.13785 + N0 0.780517 0.4527 0.43111 N1 0.871509 0.234929 0.430442 N2 0.875348 0.235963 0.422003 + txt003 +STRI + V0 1.56671 0.436032 2.13785 V1 1.40492 0.825153 2.13785 V2 1.29778 0.762222 2.4 + N0 0.875348 0.235963 0.422003 N1 0.783966 0.4547 0.422664 N2 0.780517 0.4527 0.43111 + txt003 +STRI + V0 1.44722 0.402778 2.4 V1 1.5 0 2.4 V2 1.62384 2.22045e-16 2.13785 + N0 0.871509 0.234929 0.430442 N1 0.902861 -2.27296e-16 0.429934 N2 0.906828 -2.05843e-16 0.4215 + txt003 +STRI + V0 1.62384 2.22045e-16 2.13785 V1 1.56671 0.436032 2.13785 V2 1.44722 0.402778 2.4 + N0 0.906828 -2.05843e-16 0.4215 N1 0.875348 0.235963 0.422003 N2 0.871509 0.234929 0.430442 + txt003 +STRI + V0 0 1.62384 2.13785 V1 0.436032 1.56671 2.13785 V2 0.467421 1.67949 1.87778 + N0 -0 0.906828 0.4215 N1 0.235963 0.875348 0.422003 N2 0.239043 0.886771 0.395595 + txt003 +STRI + V0 0.467421 1.67949 1.87778 V1 0 1.74074 1.87778 V2 0 1.62384 2.13785 + N0 0.239043 0.886771 0.395595 N1 -0 0.918633 0.395111 N2 -0 0.906828 0.4215 + txt003 +STRI + V0 0.436032 1.56671 2.13785 V1 0.825153 1.40492 2.13785 V2 0.884554 1.50606 1.87778 + N0 0.235963 0.875348 0.422003 N1 0.4547 0.783966 0.422664 N2 0.460653 0.794229 0.39623 + txt003 +STRI + V0 0.884554 1.50606 1.87778 V1 0.467421 1.67949 1.87778 V2 0.436032 1.56671 2.13785 + N0 0.460653 0.794229 0.39623 N1 0.239043 0.886771 0.395595 N2 0.235963 0.875348 0.422003 + txt003 +STRI + V0 0.825153 1.40492 2.13785 V1 1.15293 1.15293 2.13785 V2 1.23593 1.23593 1.87778 + N0 0.4547 0.783966 0.422664 N1 0.640758 0.640758 0.422917 N2 0.649156 0.649156 0.396474 + txt003 +STRI + V0 1.23593 1.23593 1.87778 V1 0.884554 1.50606 1.87778 V2 0.825153 1.40492 2.13785 + N0 0.649156 0.649156 0.396474 N1 0.460653 0.794229 0.39623 N2 0.4547 0.783966 0.422664 + txt003 +STRI + V0 1.15293 1.15293 2.13785 V1 1.40492 0.825153 2.13785 V2 1.50606 0.884554 1.87778 + N0 0.640758 0.640758 0.422917 N1 0.783966 0.4547 0.422664 N2 0.794229 0.460653 0.39623 + txt003 +STRI + V0 1.50606 0.884554 1.87778 V1 1.23593 1.23593 1.87778 V2 1.15293 1.15293 2.13785 + N0 0.794229 0.460653 0.39623 N1 0.649156 0.649156 0.396474 N2 0.640758 0.640758 0.422917 + txt003 +STRI + V0 1.40492 0.825153 2.13785 V1 1.56671 0.436032 2.13785 V2 1.67949 0.467421 1.87778 + N0 0.783966 0.4547 0.422664 N1 0.875348 0.235963 0.422003 N2 0.886771 0.239043 0.395595 + txt003 +STRI + V0 1.67949 0.467421 1.87778 V1 1.50606 0.884554 1.87778 V2 1.40492 0.825153 2.13785 + N0 0.886771 0.239043 0.395595 N1 0.794229 0.460653 0.39623 N2 0.783966 0.4547 0.422664 + txt003 +STRI + V0 1.56671 0.436032 2.13785 V1 1.62384 2.22045e-16 2.13785 V2 1.74074 0 1.87778 + N0 0.875348 0.235963 0.422003 N1 0.906828 -2.05843e-16 0.4215 N2 0.918633 -1.79998e-16 0.395111 + txt003 +STRI + V0 1.74074 0 1.87778 V1 1.67949 0.467421 1.87778 V2 1.56671 0.436032 2.13785 + N0 0.918633 -1.79998e-16 0.395111 N1 0.886771 0.239043 0.395595 N2 0.875348 0.235963 0.422003 + txt003 +STRI + V0 0 1.74074 1.87778 V1 0.467421 1.67949 1.87778 V2 0.495081 1.77888 1.62188 + N0 -0 0.918633 0.395111 N1 0.239043 0.886771 0.395595 N2 0.244029 0.90527 0.347757 + txt003 +STRI + V0 0.495081 1.77888 1.62188 V1 0 1.84375 1.62188 V2 0 1.74074 1.87778 + N0 0.244029 0.90527 0.347757 N1 -0 0.937749 0.347314 N2 -0 0.918633 0.395111 + txt003 +STRI + V0 0.467421 1.67949 1.87778 V1 0.884554 1.50606 1.87778 V2 0.936898 1.59519 1.62188 + N0 0.239043 0.886771 0.395595 N1 0.460653 0.794229 0.39623 N2 0.470295 0.810853 0.34834 + txt003 +STRI + V0 0.936898 1.59519 1.62188 V1 0.495081 1.77888 1.62188 V2 0.467421 1.67949 1.87778 + N0 0.470295 0.810853 0.34834 N1 0.244029 0.90527 0.347757 N2 0.239043 0.886771 0.395595 + txt003 +STRI + V0 0.884554 1.50606 1.87778 V1 1.23593 1.23593 1.87778 V2 1.30906 1.30906 1.62188 + N0 0.460653 0.794229 0.39623 N1 0.649156 0.649156 0.396474 N2 0.662761 0.662761 0.348563 + txt003 +STRI + V0 1.30906 1.30906 1.62188 V1 0.936898 1.59519 1.62188 V2 0.884554 1.50606 1.87778 + N0 0.662761 0.662761 0.348563 N1 0.470295 0.810853 0.34834 N2 0.460653 0.794229 0.39623 + txt003 +STRI + V0 1.23593 1.23593 1.87778 V1 1.50606 0.884554 1.87778 V2 1.59519 0.936898 1.62187 + N0 0.649156 0.649156 0.396474 N1 0.794229 0.460653 0.39623 N2 0.810853 0.470295 0.34834 + txt003 +STRI + V0 1.59519 0.936898 1.62187 V1 1.30906 1.30906 1.62188 V2 1.23593 1.23593 1.87778 + N0 0.810853 0.470295 0.34834 N1 0.662761 0.662761 0.348563 N2 0.649156 0.649156 0.396474 + txt003 +STRI + V0 1.50606 0.884554 1.87778 V1 1.67949 0.467421 1.87778 V2 1.77888 0.495081 1.62187 + N0 0.794229 0.460653 0.39623 N1 0.886771 0.239043 0.395595 N2 0.90527 0.244029 0.347757 + txt003 +STRI + V0 1.77888 0.495081 1.62187 V1 1.59519 0.936898 1.62187 V2 1.50606 0.884554 1.87778 + N0 0.90527 0.244029 0.347757 N1 0.810853 0.470295 0.34834 N2 0.794229 0.460653 0.39623 + txt003 +STRI + V0 1.67949 0.467421 1.87778 V1 1.74074 0 1.87778 V2 1.84375 0 1.62187 + N0 0.886771 0.239043 0.395595 N1 0.918633 -1.79998e-16 0.395111 N2 0.937749 -1.49384e-16 0.347314 + txt003 +STRI + V0 1.84375 0 1.62187 V1 1.77888 0.495081 1.62187 V2 1.67949 0.467421 1.87778 + N0 0.937749 -1.49384e-16 0.347314 N1 0.90527 0.244029 0.347757 N2 0.886771 0.239043 0.395595 + txt003 +STRI + V0 0 1.84375 1.62188 V1 0.495081 1.77888 1.62188 V2 0.517147 1.85816 1.37222 + N0 -0 0.937749 0.347314 N1 0.244029 0.90527 0.347757 N2 0.250446 0.929073 0.272213 + txt003 +STRI + V0 0.517147 1.85816 1.37222 V1 0 1.92593 1.37222 V2 0 1.84375 1.62188 + N0 0.250446 0.929073 0.272213 N1 -0 0.96234 0.271848 N2 -0 0.937749 0.347314 + txt003 +STRI + V0 0.495081 1.77888 1.62188 V1 0.936898 1.59519 1.62188 V2 0.978656 1.66628 1.37222 + N0 0.244029 0.90527 0.347757 N1 0.470295 0.810853 0.34834 N2 0.482704 0.832247 0.272693 + txt003 +STRI + V0 0.978656 1.66628 1.37222 V1 0.517147 1.85816 1.37222 V2 0.495081 1.77888 1.62188 + N0 0.482704 0.832247 0.272693 N1 0.250446 0.929073 0.272213 N2 0.244029 0.90527 0.347757 + txt003 +STRI + V0 0.936898 1.59519 1.62188 V1 1.30906 1.30906 1.62188 V2 1.36741 1.36741 1.37222 + N0 0.470295 0.810853 0.34834 N1 0.662761 0.662761 0.348563 N2 0.680271 0.680271 0.272877 + txt003 +STRI + V0 1.36741 1.36741 1.37222 V1 0.978656 1.66628 1.37222 V2 0.936898 1.59519 1.62188 + N0 0.680271 0.680271 0.272877 N1 0.482704 0.832247 0.272693 N2 0.470295 0.810853 0.34834 + txt003 +STRI + V0 1.30906 1.30906 1.62188 V1 1.59519 0.936898 1.62187 V2 1.66628 0.978656 1.37222 + N0 0.662761 0.662761 0.348563 N1 0.810853 0.470295 0.34834 N2 0.832247 0.482704 0.272693 + txt003 +STRI + V0 1.66628 0.978656 1.37222 V1 1.36741 1.36741 1.37222 V2 1.30906 1.30906 1.62188 + N0 0.832247 0.482704 0.272693 N1 0.680271 0.680271 0.272877 N2 0.662761 0.662761 0.348563 + txt003 +STRI + V0 1.59519 0.936898 1.62187 V1 1.77888 0.495081 1.62187 V2 1.85816 0.517147 1.37222 + N0 0.810853 0.470295 0.34834 N1 0.90527 0.244029 0.347757 N2 0.929073 0.250446 0.272213 + txt003 +STRI + V0 1.85816 0.517147 1.37222 V1 1.66628 0.978656 1.37222 V2 1.59519 0.936898 1.62187 + N0 0.929073 0.250446 0.272213 N1 0.832247 0.482704 0.272693 N2 0.810853 0.470295 0.34834 + txt003 +STRI + V0 1.77888 0.495081 1.62187 V1 1.84375 0 1.62187 V2 1.92593 2.22045e-16 1.37222 + N0 0.90527 0.244029 0.347757 N1 0.937749 -1.49384e-16 0.347314 N2 0.96234 -1.11936e-16 0.271848 + txt003 +STRI + V0 1.92593 2.22045e-16 1.37222 V1 1.85816 0.517147 1.37222 V2 1.77888 0.495081 1.62187 + N0 0.96234 -1.11936e-16 0.271848 N1 0.929073 0.250446 0.272213 N2 0.90527 0.244029 0.347757 + txt003 +STRI + V0 0 1.92593 1.37222 V1 0.517147 1.85816 1.37222 V2 0.531754 1.91065 1.1309 + N0 -0 0.96234 0.271848 N1 0.250446 0.929073 0.272213 N2 0.256935 0.953145 0.159686 + txt003 +STRI + V0 0.531754 1.91065 1.1309 V1 0 1.98032 1.1309 V2 0 1.92593 1.37222 + N0 0.256935 0.953145 0.159686 N1 -0 0.987204 0.15946 N2 -0 0.96234 0.271848 + txt003 +STRI + V0 0.517147 1.85816 1.37222 V1 0.978656 1.66628 1.37222 V2 1.0063 1.71335 1.1309 + N0 0.250446 0.929073 0.272213 N1 0.482704 0.832247 0.272693 N2 0.495256 0.853889 0.159982 + txt003 +STRI + V0 1.0063 1.71335 1.1309 V1 0.531754 1.91065 1.1309 V2 0.517147 1.85816 1.37222 + N0 0.495256 0.853889 0.159982 N1 0.256935 0.953145 0.159686 N2 0.250446 0.929073 0.272213 + txt003 +STRI + V0 0.978656 1.66628 1.37222 V1 1.36741 1.36741 1.37222 V2 1.40603 1.40603 1.1309 + N0 0.482704 0.832247 0.272693 N1 0.680271 0.680271 0.272877 N2 0.697986 0.697986 0.160096 + txt003 +STRI + V0 1.40603 1.40603 1.1309 V1 1.0063 1.71335 1.1309 V2 0.978656 1.66628 1.37222 + N0 0.697986 0.697986 0.160096 N1 0.495256 0.853889 0.159982 N2 0.482704 0.832247 0.272693 + txt003 +STRI + V0 1.36741 1.36741 1.37222 V1 1.66628 0.978656 1.37222 V2 1.71335 1.0063 1.1309 + N0 0.680271 0.680271 0.272877 N1 0.832247 0.482704 0.272693 N2 0.853889 0.495256 0.159982 + txt003 +STRI + V0 1.71335 1.0063 1.1309 V1 1.40603 1.40603 1.1309 V2 1.36741 1.36741 1.37222 + N0 0.853889 0.495256 0.159982 N1 0.697986 0.697986 0.160096 N2 0.680271 0.680271 0.272877 + txt003 +STRI + V0 1.66628 0.978656 1.37222 V1 1.85816 0.517147 1.37222 V2 1.91065 0.531754 1.1309 + N0 0.832247 0.482704 0.272693 N1 0.929073 0.250446 0.272213 N2 0.953145 0.256935 0.159686 + txt003 +STRI + V0 1.91065 0.531754 1.1309 V1 1.71335 1.0063 1.1309 V2 1.66628 0.978656 1.37222 + N0 0.953145 0.256935 0.159686 N1 0.853889 0.495256 0.159982 N2 0.832247 0.482704 0.272693 + txt003 +STRI + V0 1.85816 0.517147 1.37222 V1 1.92593 2.22045e-16 1.37222 V2 1.98032 -2.22045e-16 1.1309 + N0 0.929073 0.250446 0.272213 N1 0.96234 -1.11936e-16 0.271848 N2 0.987204 -6.38555e-17 0.15946 + txt003 +STRI + V0 1.98032 -2.22045e-16 1.1309 V1 1.91065 0.531754 1.1309 V2 1.85816 0.517147 1.37222 + N0 0.987204 -6.38555e-17 0.15946 N1 0.953145 0.256935 0.159686 N2 0.929073 0.250446 0.272213 + txt003 +STRI + V0 0 1.98032 1.1309 V1 0.531754 1.91065 1.1309 V2 0.537037 1.92963 0.9 + N0 -0 0.987204 0.15946 N1 0.256935 0.953145 0.159686 N2 0.260275 0.965535 5.17854e-17 + txt003 +STRI + V0 0.537037 1.92963 0.9 V1 0 2 0.9 V2 0 1.98032 1.1309 + N0 0.260275 0.965535 5.17854e-17 N1 -0 1 0 N2 -0 0.987204 0.15946 + txt003 +STRI + V0 0.531754 1.91065 1.1309 V1 1.0063 1.71335 1.1309 V2 1.0163 1.73037 0.9 + N0 0.256935 0.953145 0.159686 N1 0.495256 0.853889 0.159982 N2 0.501718 0.865031 1.36587e-16 + txt003 +STRI + V0 1.0163 1.73037 0.9 V1 0.537037 1.92963 0.9 V2 0.531754 1.91065 1.1309 + N0 0.501718 0.865031 1.36587e-16 N1 0.260275 0.965535 5.17854e-17 N2 0.256935 0.953145 0.159686 + txt003 +STRI + V0 1.0063 1.71335 1.1309 V1 1.40603 1.40603 1.1309 V2 1.42 1.42 0.9 + N0 0.495256 0.853889 0.159982 N1 0.697986 0.697986 0.160096 N2 0.707107 0.707107 1.74455e-16 + txt003 +STRI + V0 1.42 1.42 0.9 V1 1.0163 1.73037 0.9 V2 1.0063 1.71335 1.1309 + N0 0.707107 0.707107 1.74455e-16 N1 0.501718 0.865031 1.36587e-16 N2 0.495256 0.853889 0.159982 + txt003 +STRI + V0 1.40603 1.40603 1.1309 V1 1.71335 1.0063 1.1309 V2 1.73037 1.0163 0.9 + N0 0.697986 0.697986 0.160096 N1 0.853889 0.495256 0.159982 N2 0.865031 0.501718 1.36587e-16 + txt003 +STRI + V0 1.73037 1.0163 0.9 V1 1.42 1.42 0.9 V2 1.40603 1.40603 1.1309 + N0 0.865031 0.501718 1.36587e-16 N1 0.707107 0.707107 1.74455e-16 N2 0.697986 0.697986 0.160096 + txt003 +STRI + V0 1.71335 1.0063 1.1309 V1 1.91065 0.531754 1.1309 V2 1.92963 0.537037 0.9 + N0 0.853889 0.495256 0.159982 N1 0.953145 0.256935 0.159686 N2 0.965535 0.260275 5.17854e-17 + txt003 +STRI + V0 1.92963 0.537037 0.9 V1 1.73037 1.0163 0.9 V2 1.71335 1.0063 1.1309 + N0 0.965535 0.260275 5.17854e-17 N1 0.865031 0.501718 1.36587e-16 N2 0.853889 0.495256 0.159982 + txt003 +STRI + V0 1.91065 0.531754 1.1309 V1 1.98032 -2.22045e-16 1.1309 V2 2 0 0.9 + N0 0.953145 0.256935 0.159686 N1 0.987204 -6.38555e-17 0.15946 N2 1 0 0 + txt003 +STRI + V0 2 0 0.9 V1 1.92963 0.537037 0.9 V2 1.91065 0.531754 1.1309 + N0 1 0 0 N1 0.965535 0.260275 5.17854e-17 N2 0.953145 0.256935 0.159686 + txt003 +STRI + V0 2 0 0.9 V1 1.92963 -0.537037 0.9 V2 1.8939 -0.527092 0.693403 + N0 1 0 0 N1 0.965535 -0.260275 0 N2 0.905874 -0.244192 -0.346067 + txt003 +STRI + V0 1.8939 -0.527092 0.693403 V1 1.96296 0 0.693403 V2 2 0 0.9 + N0 0.905874 -0.244192 -0.346067 N1 0.938373 0 -0.345625 N2 1 0 0 + txt003 +STRI + V0 1.92963 -0.537037 0.9 V1 1.73037 -1.0163 0.9 V2 1.69833 -0.997476 0.693403 + N0 0.965535 -0.260275 0 N1 0.865031 -0.501718 0 N2 0.811395 -0.470609 -0.346647 + txt003 +STRI + V0 1.69833 -0.997476 0.693403 V1 1.8939 -0.527092 0.693403 V2 1.92963 -0.537037 0.9 + N0 0.811395 -0.470609 -0.346647 N1 0.905874 -0.244192 -0.346067 N2 0.965535 -0.260275 0 + txt003 +STRI + V0 1.73037 -1.0163 0.9 V1 1.42 -1.42 0.9 V2 1.3937 -1.3937 0.693403 + N0 0.865031 -0.501718 0 N1 0.707107 -0.707107 0 N2 0.663205 -0.663205 -0.34687 + txt003 +STRI + V0 1.3937 -1.3937 0.693403 V1 1.69833 -0.997476 0.693403 V2 1.73037 -1.0163 0.9 + N0 0.663205 -0.663205 -0.34687 N1 0.811395 -0.470609 -0.346647 N2 0.865031 -0.501718 0 + txt003 +STRI + V0 1.42 -1.42 0.9 V1 1.0163 -1.73037 0.9 V2 0.997476 -1.69833 0.693403 + N0 0.707107 -0.707107 0 N1 0.501718 -0.865031 0 N2 0.470609 -0.811395 -0.346647 + txt003 +STRI + V0 0.997476 -1.69833 0.693403 V1 1.3937 -1.3937 0.693403 V2 1.42 -1.42 0.9 + N0 0.470609 -0.811395 -0.346647 N1 0.663205 -0.663205 -0.34687 N2 0.707107 -0.707107 0 + txt003 +STRI + V0 1.0163 -1.73037 0.9 V1 0.537037 -1.92963 0.9 V2 0.527092 -1.8939 0.693403 + N0 0.501718 -0.865031 0 N1 0.260275 -0.965535 0 N2 0.244192 -0.905874 -0.346067 + txt003 +STRI + V0 0.527092 -1.8939 0.693403 V1 0.997476 -1.69833 0.693403 V2 1.0163 -1.73037 0.9 + N0 0.244192 -0.905874 -0.346067 N1 0.470609 -0.811395 -0.346647 N2 0.501718 -0.865031 0 + txt003 +STRI + V0 0.537037 -1.92963 0.9 V1 0 -2 0.9 V2 2.22045e-16 -1.96296 0.693403 + N0 0.260275 -0.965535 0 N1 -0 -1 -0 N2 -3.49072e-17 -0.938373 -0.345625 + txt003 +STRI + V0 2.22045e-16 -1.96296 0.693403 V1 0.527092 -1.8939 0.693403 V2 0.537037 -1.92963 0.9 + N0 -3.49072e-17 -0.938373 -0.345625 N1 0.244192 -0.905874 -0.346067 N2 0.260275 -0.965535 0 + txt003 +STRI + V0 1.96296 0 0.693403 V1 1.8939 -0.527092 0.693403 V2 1.80456 -0.502229 0.522222 + N0 0.938373 0 -0.345625 N1 0.905874 -0.244192 -0.346067 N2 0.782908 -0.211045 -0.585248 + txt003 +STRI + V0 1.80456 -0.502229 0.522222 V1 1.87037 0 0.522222 V2 1.96296 0 0.693403 + N0 0.782908 -0.211045 -0.585248 N1 0.811257 0 -0.58469 N2 0.938373 0 -0.345625 + txt003 +STRI + V0 1.8939 -0.527092 0.693403 V1 1.69833 -0.997476 0.693403 V2 1.61822 -0.950425 0.522222 + N0 0.905874 -0.244192 -0.346067 N1 0.811395 -0.470609 -0.346647 N2 0.700957 -0.406555 -0.58598 + txt003 +STRI + V0 1.61822 -0.950425 0.522222 V1 1.80456 -0.502229 0.522222 V2 1.8939 -0.527092 0.693403 + N0 0.700957 -0.406555 -0.58598 N1 0.782908 -0.211045 -0.585248 N2 0.905874 -0.244192 -0.346067 + txt003 +STRI + V0 1.69833 -0.997476 0.693403 V1 1.3937 -1.3937 0.693403 V2 1.32796 -1.32796 0.522222 + N0 0.811395 -0.470609 -0.346647 N1 0.663205 -0.663205 -0.34687 N2 0.572843 -0.572843 -0.586261 + txt003 +STRI + V0 1.32796 -1.32796 0.522222 V1 1.61822 -0.950425 0.522222 V2 1.69833 -0.997476 0.693403 + N0 0.572843 -0.572843 -0.586261 N1 0.700957 -0.406555 -0.58598 N2 0.811395 -0.470609 -0.346647 + txt003 +STRI + V0 1.3937 -1.3937 0.693403 V1 0.997476 -1.69833 0.693403 V2 0.950425 -1.61822 0.522222 + N0 0.663205 -0.663205 -0.34687 N1 0.470609 -0.811395 -0.346647 N2 0.406555 -0.700957 -0.58598 + txt003 +STRI + V0 0.950425 -1.61822 0.522222 V1 1.32796 -1.32796 0.522222 V2 1.3937 -1.3937 0.693403 + N0 0.406555 -0.700957 -0.58598 N1 0.572843 -0.572843 -0.586261 N2 0.663205 -0.663205 -0.34687 + txt003 +STRI + V0 0.997476 -1.69833 0.693403 V1 0.527092 -1.8939 0.693403 V2 0.502229 -1.80456 0.522222 + N0 0.470609 -0.811395 -0.346647 N1 0.244192 -0.905874 -0.346067 N2 0.211045 -0.782908 -0.585248 + txt003 +STRI + V0 0.502229 -1.80456 0.522222 V1 0.950425 -1.61822 0.522222 V2 0.997476 -1.69833 0.693403 + N0 0.211045 -0.782908 -0.585248 N1 0.406555 -0.700957 -0.58598 N2 0.470609 -0.811395 -0.346647 + txt003 +STRI + V0 0.527092 -1.8939 0.693403 V1 2.22045e-16 -1.96296 0.693403 V2 2.22045e-16 -1.87037 0.522222 + N0 0.244192 -0.905874 -0.346067 N1 -3.49072e-17 -0.938373 -0.345625 N2 -6.19755e-17 -0.811257 -0.58469 + txt003 +STRI + V0 2.22045e-16 -1.87037 0.522222 V1 0.502229 -1.80456 0.522222 V2 0.527092 -1.8939 0.693403 + N0 -6.19755e-17 -0.811257 -0.58469 N1 0.211045 -0.782908 -0.585248 N2 0.244192 -0.905874 -0.346067 + txt003 +STRI + V0 1.87037 0 0.522222 V1 1.80456 -0.502229 0.522222 V2 1.68843 -0.469907 0.384375 + N0 0.811257 0 -0.58469 N1 0.782908 -0.211045 -0.585248 N2 0.673539 -0.181563 -0.716506 + txt003 +STRI + V0 1.68843 -0.469907 0.384375 V1 1.75 0 0.384375 V2 1.87037 0 0.522222 + N0 0.673539 -0.181563 -0.716506 N1 0.6981 0 -0.716 N2 0.811257 0 -0.58469 + txt003 +STRI + V0 1.80456 -0.502229 0.522222 V1 1.61822 -0.950425 0.522222 V2 1.51407 -0.889259 0.384375 + N0 0.782908 -0.211045 -0.585248 N1 0.700957 -0.406555 -0.58598 N2 0.602839 -0.349647 -0.717169 + txt003 +STRI + V0 1.51407 -0.889259 0.384375 V1 1.68843 -0.469907 0.384375 V2 1.80456 -0.502229 0.522222 + N0 0.602839 -0.349647 -0.717169 N1 0.673539 -0.181563 -0.716506 N2 0.782908 -0.211045 -0.585248 + txt003 +STRI + V0 1.61822 -0.950425 0.522222 V1 1.32796 -1.32796 0.522222 V2 1.2425 -1.2425 0.384375 + N0 0.700957 -0.406555 -0.58598 N1 0.572843 -0.572843 -0.586261 N2 0.492597 -0.492597 -0.717423 + txt003 +STRI + V0 1.2425 -1.2425 0.384375 V1 1.51407 -0.889259 0.384375 V2 1.61822 -0.950425 0.522222 + N0 0.492597 -0.492597 -0.717423 N1 0.602839 -0.349647 -0.717169 N2 0.700957 -0.406555 -0.58598 + txt003 +STRI + V0 1.32796 -1.32796 0.522222 V1 0.950425 -1.61822 0.522222 V2 0.889259 -1.51407 0.384375 + N0 0.572843 -0.572843 -0.586261 N1 0.406555 -0.700957 -0.58598 N2 0.349647 -0.602839 -0.717169 + txt003 +STRI + V0 0.889259 -1.51407 0.384375 V1 1.2425 -1.2425 0.384375 V2 1.32796 -1.32796 0.522222 + N0 0.349647 -0.602839 -0.717169 N1 0.492597 -0.492597 -0.717423 N2 0.572843 -0.572843 -0.586261 + txt003 +STRI + V0 0.950425 -1.61822 0.522222 V1 0.502229 -1.80456 0.522222 V2 0.469907 -1.68843 0.384375 + N0 0.406555 -0.700957 -0.58598 N1 0.211045 -0.782908 -0.585248 N2 0.181563 -0.673539 -0.716506 + txt003 +STRI + V0 0.469907 -1.68843 0.384375 V1 0.889259 -1.51407 0.384375 V2 0.950425 -1.61822 0.522222 + N0 0.181563 -0.673539 -0.716506 N1 0.349647 -0.602839 -0.717169 N2 0.406555 -0.700957 -0.58598 + txt003 +STRI + V0 0.502229 -1.80456 0.522222 V1 2.22045e-16 -1.87037 0.522222 V2 2.22045e-16 -1.75 0.384375 + N0 0.211045 -0.782908 -0.585248 N1 -6.19755e-17 -0.811257 -0.58469 N2 -8.11143e-17 -0.6981 -0.716 + txt003 +STRI + V0 2.22045e-16 -1.75 0.384375 V1 0.469907 -1.68843 0.384375 V2 0.502229 -1.80456 0.522222 + N0 -8.11143e-17 -0.6981 -0.716 N1 0.181563 -0.673539 -0.716506 N2 0.211045 -0.782908 -0.585248 + txt003 +STRI + V0 1.75 0 0.384375 V1 1.68843 -0.469907 0.384375 V2 1.57229 -0.437586 0.277778 + N0 0.6981 0 -0.716 N1 0.673539 -0.181563 -0.716506 N2 0.61392 -0.165491 -0.771826 + txt003 +STRI + V0 1.57229 -0.437586 0.277778 V1 1.62963 0 0.277778 V2 1.75 0 0.384375 + N0 0.61392 -0.165491 -0.771826 N1 0.636383 0 -0.771373 N2 0.6981 0 -0.716 + txt003 +STRI + V0 1.68843 -0.469907 0.384375 V1 1.51407 -0.889259 0.384375 V2 1.40993 -0.828093 0.277778 + N0 0.673539 -0.181563 -0.716506 N1 0.602839 -0.349647 -0.717169 N2 0.549392 -0.318647 -0.77242 + txt003 +STRI + V0 1.40993 -0.828093 0.277778 V1 1.57229 -0.437586 0.277778 V2 1.68843 -0.469907 0.384375 + N0 0.549392 -0.318647 -0.77242 N1 0.61392 -0.165491 -0.771826 N2 0.673539 -0.181563 -0.716506 + txt003 +STRI + V0 1.51407 -0.889259 0.384375 V1 1.2425 -1.2425 0.384375 V2 1.15704 -1.15704 0.277778 + N0 0.602839 -0.349647 -0.717169 N1 0.492597 -0.492597 -0.717423 N2 0.448897 -0.448897 -0.772647 + txt003 +STRI + V0 1.15704 -1.15704 0.277778 V1 1.40993 -0.828093 0.277778 V2 1.51407 -0.889259 0.384375 + N0 0.448897 -0.448897 -0.772647 N1 0.549392 -0.318647 -0.77242 N2 0.602839 -0.349647 -0.717169 + txt003 +STRI + V0 1.2425 -1.2425 0.384375 V1 0.889259 -1.51407 0.384375 V2 0.828093 -1.40993 0.277778 + N0 0.492597 -0.492597 -0.717423 N1 0.349647 -0.602839 -0.717169 N2 0.318647 -0.549392 -0.77242 + txt003 +STRI + V0 0.828093 -1.40993 0.277778 V1 1.15704 -1.15704 0.277778 V2 1.2425 -1.2425 0.384375 + N0 0.318647 -0.549392 -0.77242 N1 0.448897 -0.448897 -0.772647 N2 0.492597 -0.492597 -0.717423 + txt003 +STRI + V0 0.889259 -1.51407 0.384375 V1 0.469907 -1.68843 0.384375 V2 0.437586 -1.57229 0.277778 + N0 0.349647 -0.602839 -0.717169 N1 0.181563 -0.673539 -0.716506 N2 0.165491 -0.61392 -0.771826 + txt003 +STRI + V0 0.437586 -1.57229 0.277778 V1 0.828093 -1.40993 0.277778 V2 0.889259 -1.51407 0.384375 + N0 0.165491 -0.61392 -0.771826 N1 0.318647 -0.549392 -0.77242 N2 0.349647 -0.602839 -0.717169 + txt003 +STRI + V0 0.469907 -1.68843 0.384375 V1 2.22045e-16 -1.75 0.384375 V2 0 -1.62963 0.277778 + N0 0.181563 -0.673539 -0.716506 N1 -8.11143e-17 -0.6981 -0.716 N2 -1.97068e-16 -0.636383 -0.771373 + txt003 +STRI + V0 0 -1.62963 0.277778 V1 0.437586 -1.57229 0.277778 V2 0.469907 -1.68843 0.384375 + N0 -1.97068e-16 -0.636383 -0.771373 N1 0.165491 -0.61392 -0.771826 N2 0.181563 -0.673539 -0.716506 + txt003 +STRI + V0 1.62963 0 0.277778 V1 1.57229 -0.437586 0.277778 V2 1.48296 -0.412723 0.200347 + N0 0.636383 0 -0.771373 N1 0.61392 -0.165491 -0.771826 N2 0.651276 -0.175561 -0.738253 + txt003 +STRI + V0 1.48296 -0.412723 0.200347 V1 1.53704 0 0.200347 V2 1.62963 0 0.277778 + N0 0.651276 -0.175561 -0.738253 N1 0.675056 0 -0.737766 N2 0.636383 0 -0.771373 + txt003 +STRI + V0 1.57229 -0.437586 0.277778 V1 1.40993 -0.828093 0.277778 V2 1.32982 -0.781043 0.200347 + N0 0.61392 -0.165491 -0.771826 N1 0.549392 -0.318647 -0.77242 N2 0.582878 -0.338069 -0.738893 + txt003 +STRI + V0 1.32982 -0.781043 0.200347 V1 1.48296 -0.412723 0.200347 V2 1.57229 -0.437586 0.277778 + N0 0.582878 -0.338069 -0.738893 N1 0.651276 -0.175561 -0.738253 N2 0.61392 -0.165491 -0.771826 + txt003 +STRI + V0 1.40993 -0.828093 0.277778 V1 1.15704 -1.15704 0.277778 V2 1.0913 -1.0913 0.200347 + N0 0.549392 -0.318647 -0.77242 N1 0.448897 -0.448897 -0.772647 N2 0.476275 -0.476275 -0.739137 + txt003 +STRI + V0 1.0913 -1.0913 0.200347 V1 1.32982 -0.781043 0.200347 V2 1.40993 -0.828093 0.277778 + N0 0.476275 -0.476275 -0.739137 N1 0.582878 -0.338069 -0.738893 N2 0.549392 -0.318647 -0.77242 + txt003 +STRI + V0 1.15704 -1.15704 0.277778 V1 0.828093 -1.40993 0.277778 V2 0.781043 -1.32982 0.200347 + N0 0.448897 -0.448897 -0.772647 N1 0.318647 -0.549392 -0.77242 N2 0.338069 -0.582878 -0.738893 + txt003 +STRI + V0 0.781043 -1.32982 0.200347 V1 1.0913 -1.0913 0.200347 V2 1.15704 -1.15704 0.277778 + N0 0.338069 -0.582878 -0.738893 N1 0.476275 -0.476275 -0.739137 N2 0.448897 -0.448897 -0.772647 + txt003 +STRI + V0 0.828093 -1.40993 0.277778 V1 0.437586 -1.57229 0.277778 V2 0.412723 -1.48296 0.200347 + N0 0.318647 -0.549392 -0.77242 N1 0.165491 -0.61392 -0.771826 N2 0.175561 -0.651276 -0.738253 + txt003 +STRI + V0 0.412723 -1.48296 0.200347 V1 0.781043 -1.32982 0.200347 V2 0.828093 -1.40993 0.277778 + N0 0.175561 -0.651276 -0.738253 N1 0.338069 -0.582878 -0.738893 N2 0.318647 -0.549392 -0.77242 + txt003 +STRI + V0 0.437586 -1.57229 0.277778 V1 0 -1.62963 0.277778 V2 0 -1.53704 0.200347 + N0 0.165491 -0.61392 -0.771826 N1 -1.97068e-16 -0.636383 -0.771373 N2 -9.51605e-17 -0.675056 -0.737766 + txt003 +STRI + V0 0 -1.53704 0.200347 V1 0.412723 -1.48296 0.200347 V2 0.437586 -1.57229 0.277778 + N0 -9.51605e-17 -0.675056 -0.737766 N1 0.175561 -0.651276 -0.738253 N2 0.165491 -0.61392 -0.771826 + txt003 +STRI + V0 1.53704 0 0.200347 V1 1.48296 -0.412723 0.200347 V2 1.44722 -0.402778 0.15 + N0 0.675056 0 -0.737766 N1 0.651276 -0.175561 -0.738253 N2 0.965535 -0.260275 0 + txt003 +STRI + V0 1.44722 -0.402778 0.15 V1 1.5 0 0.15 V2 1.53704 0 0.200347 + N0 0.965535 -0.260275 0 N1 1 0 0 N2 0.675056 0 -0.737766 + txt003 +STRI + V0 1.48296 -0.412723 0.200347 V1 1.32982 -0.781043 0.200347 V2 1.29778 -0.762222 0.15 + N0 0.651276 -0.175561 -0.738253 N1 0.582878 -0.338069 -0.738893 N2 0.865031 -0.501718 0 + txt003 +STRI + V0 1.29778 -0.762222 0.15 V1 1.44722 -0.402778 0.15 V2 1.48296 -0.412723 0.200347 + N0 0.865031 -0.501718 0 N1 0.965535 -0.260275 0 N2 0.651276 -0.175561 -0.738253 + txt003 +STRI + V0 1.32982 -0.781043 0.200347 V1 1.0913 -1.0913 0.200347 V2 1.065 -1.065 0.15 + N0 0.582878 -0.338069 -0.738893 N1 0.476275 -0.476275 -0.739137 N2 0.707107 -0.707107 0 + txt003 +STRI + V0 1.065 -1.065 0.15 V1 1.29778 -0.762222 0.15 V2 1.32982 -0.781043 0.200347 + N0 0.707107 -0.707107 0 N1 0.865031 -0.501718 0 N2 0.582878 -0.338069 -0.738893 + txt003 +STRI + V0 1.0913 -1.0913 0.200347 V1 0.781043 -1.32982 0.200347 V2 0.762222 -1.29778 0.15 + N0 0.476275 -0.476275 -0.739137 N1 0.338069 -0.582878 -0.738893 N2 0.501718 -0.865031 0 + txt003 +STRI + V0 0.762222 -1.29778 0.15 V1 1.065 -1.065 0.15 V2 1.0913 -1.0913 0.200347 + N0 0.501718 -0.865031 0 N1 0.707107 -0.707107 0 N2 0.476275 -0.476275 -0.739137 + txt003 +STRI + V0 0.781043 -1.32982 0.200347 V1 0.412723 -1.48296 0.200347 V2 0.402778 -1.44722 0.15 + N0 0.338069 -0.582878 -0.738893 N1 0.175561 -0.651276 -0.738253 N2 0.260275 -0.965535 0 + txt003 +STRI + V0 0.402778 -1.44722 0.15 V1 0.762222 -1.29778 0.15 V2 0.781043 -1.32982 0.200347 + N0 0.260275 -0.965535 0 N1 0.501718 -0.865031 0 N2 0.338069 -0.582878 -0.738893 + txt003 +STRI + V0 0.412723 -1.48296 0.200347 V1 0 -1.53704 0.200347 V2 0 -1.5 0.15 + N0 0.175561 -0.651276 -0.738253 N1 -9.51605e-17 -0.675056 -0.737766 N2 -0 -1 -0 + txt003 +STRI + V0 0 -1.5 0.15 V1 0.402778 -1.44722 0.15 V2 0.412723 -1.48296 0.200347 + N0 -0 -1 -0 N1 0.260275 -0.965535 0 N2 0.175561 -0.651276 -0.738253 + txt003 +STRI + V0 0 -2 0.9 V1 -0.537037 -1.92963 0.9 V2 -0.527092 -1.8939 0.693403 + N0 -0 -1 -0 N1 -0.260275 -0.965535 -0 N2 -0.244192 -0.905874 -0.346067 + txt003 +STRI + V0 -0.527092 -1.8939 0.693403 V1 0 -1.96296 0.693403 V2 0 -2 0.9 + N0 -0.244192 -0.905874 -0.346067 N1 -0 -0.938373 -0.345625 N2 -0 -1 -0 + txt003 +STRI + V0 -0.537037 -1.92963 0.9 V1 -1.0163 -1.73037 0.9 V2 -0.997476 -1.69833 0.693403 + N0 -0.260275 -0.965535 -0 N1 -0.501718 -0.865031 -0 N2 -0.470609 -0.811395 -0.346647 + txt003 +STRI + V0 -0.997476 -1.69833 0.693403 V1 -0.527092 -1.8939 0.693403 V2 -0.537037 -1.92963 0.9 + N0 -0.470609 -0.811395 -0.346647 N1 -0.244192 -0.905874 -0.346067 N2 -0.260275 -0.965535 -0 + txt003 +STRI + V0 -1.0163 -1.73037 0.9 V1 -1.42 -1.42 0.9 V2 -1.3937 -1.3937 0.693403 + N0 -0.501718 -0.865031 -0 N1 -0.707107 -0.707107 -0 N2 -0.663205 -0.663205 -0.34687 + txt003 +STRI + V0 -1.3937 -1.3937 0.693403 V1 -0.997476 -1.69833 0.693403 V2 -1.0163 -1.73037 0.9 + N0 -0.663205 -0.663205 -0.34687 N1 -0.470609 -0.811395 -0.346647 N2 -0.501718 -0.865031 -0 + txt003 +STRI + V0 -1.42 -1.42 0.9 V1 -1.73037 -1.0163 0.9 V2 -1.69833 -0.997476 0.693403 + N0 -0.707107 -0.707107 -0 N1 -0.865031 -0.501718 -0 N2 -0.811395 -0.470609 -0.346647 + txt003 +STRI + V0 -1.69833 -0.997476 0.693403 V1 -1.3937 -1.3937 0.693403 V2 -1.42 -1.42 0.9 + N0 -0.811395 -0.470609 -0.346647 N1 -0.663205 -0.663205 -0.34687 N2 -0.707107 -0.707107 -0 + txt003 +STRI + V0 -1.73037 -1.0163 0.9 V1 -1.92963 -0.537037 0.9 V2 -1.8939 -0.527092 0.693403 + N0 -0.865031 -0.501718 -0 N1 -0.965535 -0.260275 -0 N2 -0.905874 -0.244192 -0.346067 + txt003 +STRI + V0 -1.8939 -0.527092 0.693403 V1 -1.69833 -0.997476 0.693403 V2 -1.73037 -1.0163 0.9 + N0 -0.905874 -0.244192 -0.346067 N1 -0.811395 -0.470609 -0.346647 N2 -0.865031 -0.501718 -0 + txt003 +STRI + V0 -1.92963 -0.537037 0.9 V1 -2 0 0.9 V2 -1.96296 -2.22045e-16 0.693403 + N0 -0.965535 -0.260275 -0 N1 -1 0 0 N2 -0.938373 3.49072e-17 -0.345625 + txt003 +STRI + V0 -1.96296 -2.22045e-16 0.693403 V1 -1.8939 -0.527092 0.693403 V2 -1.92963 -0.537037 0.9 + N0 -0.938373 3.49072e-17 -0.345625 N1 -0.905874 -0.244192 -0.346067 N2 -0.965535 -0.260275 -0 + txt003 +STRI + V0 0 -1.96296 0.693403 V1 -0.527092 -1.8939 0.693403 V2 -0.502229 -1.80456 0.522222 + N0 -0 -0.938373 -0.345625 N1 -0.244192 -0.905874 -0.346067 N2 -0.211045 -0.782908 -0.585248 + txt003 +STRI + V0 -0.502229 -1.80456 0.522222 V1 0 -1.87037 0.522222 V2 0 -1.96296 0.693403 + N0 -0.211045 -0.782908 -0.585248 N1 -0 -0.811257 -0.58469 N2 -0 -0.938373 -0.345625 + txt003 +STRI + V0 -0.527092 -1.8939 0.693403 V1 -0.997476 -1.69833 0.693403 V2 -0.950425 -1.61822 0.522222 + N0 -0.244192 -0.905874 -0.346067 N1 -0.470609 -0.811395 -0.346647 N2 -0.406555 -0.700957 -0.58598 + txt003 +STRI + V0 -0.950425 -1.61822 0.522222 V1 -0.502229 -1.80456 0.522222 V2 -0.527092 -1.8939 0.693403 + N0 -0.406555 -0.700957 -0.58598 N1 -0.211045 -0.782908 -0.585248 N2 -0.244192 -0.905874 -0.346067 + txt003 +STRI + V0 -0.997476 -1.69833 0.693403 V1 -1.3937 -1.3937 0.693403 V2 -1.32796 -1.32796 0.522222 + N0 -0.470609 -0.811395 -0.346647 N1 -0.663205 -0.663205 -0.34687 N2 -0.572843 -0.572843 -0.586261 + txt003 +STRI + V0 -1.32796 -1.32796 0.522222 V1 -0.950425 -1.61822 0.522222 V2 -0.997476 -1.69833 0.693403 + N0 -0.572843 -0.572843 -0.586261 N1 -0.406555 -0.700957 -0.58598 N2 -0.470609 -0.811395 -0.346647 + txt003 +STRI + V0 -1.3937 -1.3937 0.693403 V1 -1.69833 -0.997476 0.693403 V2 -1.61822 -0.950425 0.522222 + N0 -0.663205 -0.663205 -0.34687 N1 -0.811395 -0.470609 -0.346647 N2 -0.700957 -0.406555 -0.58598 + txt003 +STRI + V0 -1.61822 -0.950425 0.522222 V1 -1.32796 -1.32796 0.522222 V2 -1.3937 -1.3937 0.693403 + N0 -0.700957 -0.406555 -0.58598 N1 -0.572843 -0.572843 -0.586261 N2 -0.663205 -0.663205 -0.34687 + txt003 +STRI + V0 -1.69833 -0.997476 0.693403 V1 -1.8939 -0.527092 0.693403 V2 -1.80456 -0.502229 0.522222 + N0 -0.811395 -0.470609 -0.346647 N1 -0.905874 -0.244192 -0.346067 N2 -0.782908 -0.211045 -0.585248 + txt003 +STRI + V0 -1.80456 -0.502229 0.522222 V1 -1.61822 -0.950425 0.522222 V2 -1.69833 -0.997476 0.693403 + N0 -0.782908 -0.211045 -0.585248 N1 -0.700957 -0.406555 -0.58598 N2 -0.811395 -0.470609 -0.346647 + txt003 +STRI + V0 -1.8939 -0.527092 0.693403 V1 -1.96296 -2.22045e-16 0.693403 V2 -1.87037 -2.22045e-16 0.522222 + N0 -0.905874 -0.244192 -0.346067 N1 -0.938373 3.49072e-17 -0.345625 N2 -0.811257 6.19755e-17 -0.58469 + txt003 +STRI + V0 -1.87037 -2.22045e-16 0.522222 V1 -1.80456 -0.502229 0.522222 V2 -1.8939 -0.527092 0.693403 + N0 -0.811257 6.19755e-17 -0.58469 N1 -0.782908 -0.211045 -0.585248 N2 -0.905874 -0.244192 -0.346067 + txt003 +STRI + V0 0 -1.87037 0.522222 V1 -0.502229 -1.80456 0.522222 V2 -0.469907 -1.68843 0.384375 + N0 -0 -0.811257 -0.58469 N1 -0.211045 -0.782908 -0.585248 N2 -0.181563 -0.673539 -0.716506 + txt003 +STRI + V0 -0.469907 -1.68843 0.384375 V1 0 -1.75 0.384375 V2 0 -1.87037 0.522222 + N0 -0.181563 -0.673539 -0.716506 N1 -0 -0.6981 -0.716 N2 -0 -0.811257 -0.58469 + txt003 +STRI + V0 -0.502229 -1.80456 0.522222 V1 -0.950425 -1.61822 0.522222 V2 -0.889259 -1.51407 0.384375 + N0 -0.211045 -0.782908 -0.585248 N1 -0.406555 -0.700957 -0.58598 N2 -0.349647 -0.602839 -0.717169 + txt003 +STRI + V0 -0.889259 -1.51407 0.384375 V1 -0.469907 -1.68843 0.384375 V2 -0.502229 -1.80456 0.522222 + N0 -0.349647 -0.602839 -0.717169 N1 -0.181563 -0.673539 -0.716506 N2 -0.211045 -0.782908 -0.585248 + txt003 +STRI + V0 -0.950425 -1.61822 0.522222 V1 -1.32796 -1.32796 0.522222 V2 -1.2425 -1.2425 0.384375 + N0 -0.406555 -0.700957 -0.58598 N1 -0.572843 -0.572843 -0.586261 N2 -0.492597 -0.492597 -0.717423 + txt003 +STRI + V0 -1.2425 -1.2425 0.384375 V1 -0.889259 -1.51407 0.384375 V2 -0.950425 -1.61822 0.522222 + N0 -0.492597 -0.492597 -0.717423 N1 -0.349647 -0.602839 -0.717169 N2 -0.406555 -0.700957 -0.58598 + txt003 +STRI + V0 -1.32796 -1.32796 0.522222 V1 -1.61822 -0.950425 0.522222 V2 -1.51407 -0.889259 0.384375 + N0 -0.572843 -0.572843 -0.586261 N1 -0.700957 -0.406555 -0.58598 N2 -0.602839 -0.349647 -0.717169 + txt003 +STRI + V0 -1.51407 -0.889259 0.384375 V1 -1.2425 -1.2425 0.384375 V2 -1.32796 -1.32796 0.522222 + N0 -0.602839 -0.349647 -0.717169 N1 -0.492597 -0.492597 -0.717423 N2 -0.572843 -0.572843 -0.586261 + txt003 +STRI + V0 -1.61822 -0.950425 0.522222 V1 -1.80456 -0.502229 0.522222 V2 -1.68843 -0.469907 0.384375 + N0 -0.700957 -0.406555 -0.58598 N1 -0.782908 -0.211045 -0.585248 N2 -0.673539 -0.181563 -0.716506 + txt003 +STRI + V0 -1.68843 -0.469907 0.384375 V1 -1.51407 -0.889259 0.384375 V2 -1.61822 -0.950425 0.522222 + N0 -0.673539 -0.181563 -0.716506 N1 -0.602839 -0.349647 -0.717169 N2 -0.700957 -0.406555 -0.58598 + txt003 +STRI + V0 -1.80456 -0.502229 0.522222 V1 -1.87037 -2.22045e-16 0.522222 V2 -1.75 -2.22045e-16 0.384375 + N0 -0.782908 -0.211045 -0.585248 N1 -0.811257 6.19755e-17 -0.58469 N2 -0.6981 8.11143e-17 -0.716 + txt003 +STRI + V0 -1.75 -2.22045e-16 0.384375 V1 -1.68843 -0.469907 0.384375 V2 -1.80456 -0.502229 0.522222 + N0 -0.6981 8.11143e-17 -0.716 N1 -0.673539 -0.181563 -0.716506 N2 -0.782908 -0.211045 -0.585248 + txt003 +STRI + V0 0 -1.75 0.384375 V1 -0.469907 -1.68843 0.384375 V2 -0.437586 -1.57229 0.277778 + N0 -0 -0.6981 -0.716 N1 -0.181563 -0.673539 -0.716506 N2 -0.165491 -0.61392 -0.771826 + txt003 +STRI + V0 -0.437586 -1.57229 0.277778 V1 0 -1.62963 0.277778 V2 0 -1.75 0.384375 + N0 -0.165491 -0.61392 -0.771826 N1 -0 -0.636383 -0.771373 N2 -0 -0.6981 -0.716 + txt003 +STRI + V0 -0.469907 -1.68843 0.384375 V1 -0.889259 -1.51407 0.384375 V2 -0.828093 -1.40993 0.277778 + N0 -0.181563 -0.673539 -0.716506 N1 -0.349647 -0.602839 -0.717169 N2 -0.318647 -0.549392 -0.77242 + txt003 +STRI + V0 -0.828093 -1.40993 0.277778 V1 -0.437586 -1.57229 0.277778 V2 -0.469907 -1.68843 0.384375 + N0 -0.318647 -0.549392 -0.77242 N1 -0.165491 -0.61392 -0.771826 N2 -0.181563 -0.673539 -0.716506 + txt003 +STRI + V0 -0.889259 -1.51407 0.384375 V1 -1.2425 -1.2425 0.384375 V2 -1.15704 -1.15704 0.277778 + N0 -0.349647 -0.602839 -0.717169 N1 -0.492597 -0.492597 -0.717423 N2 -0.448897 -0.448897 -0.772647 + txt003 +STRI + V0 -1.15704 -1.15704 0.277778 V1 -0.828093 -1.40993 0.277778 V2 -0.889259 -1.51407 0.384375 + N0 -0.448897 -0.448897 -0.772647 N1 -0.318647 -0.549392 -0.77242 N2 -0.349647 -0.602839 -0.717169 + txt003 +STRI + V0 -1.2425 -1.2425 0.384375 V1 -1.51407 -0.889259 0.384375 V2 -1.40993 -0.828093 0.277778 + N0 -0.492597 -0.492597 -0.717423 N1 -0.602839 -0.349647 -0.717169 N2 -0.549392 -0.318647 -0.77242 + txt003 +STRI + V0 -1.40993 -0.828093 0.277778 V1 -1.15704 -1.15704 0.277778 V2 -1.2425 -1.2425 0.384375 + N0 -0.549392 -0.318647 -0.77242 N1 -0.448897 -0.448897 -0.772647 N2 -0.492597 -0.492597 -0.717423 + txt003 +STRI + V0 -1.51407 -0.889259 0.384375 V1 -1.68843 -0.469907 0.384375 V2 -1.57229 -0.437586 0.277778 + N0 -0.602839 -0.349647 -0.717169 N1 -0.673539 -0.181563 -0.716506 N2 -0.61392 -0.165491 -0.771826 + txt003 +STRI + V0 -1.57229 -0.437586 0.277778 V1 -1.40993 -0.828093 0.277778 V2 -1.51407 -0.889259 0.384375 + N0 -0.61392 -0.165491 -0.771826 N1 -0.549392 -0.318647 -0.77242 N2 -0.602839 -0.349647 -0.717169 + txt003 +STRI + V0 -1.68843 -0.469907 0.384375 V1 -1.75 -2.22045e-16 0.384375 V2 -1.62963 0 0.277778 + N0 -0.673539 -0.181563 -0.716506 N1 -0.6981 8.11143e-17 -0.716 N2 -0.636383 1.97068e-16 -0.771373 + txt003 +STRI + V0 -1.62963 0 0.277778 V1 -1.57229 -0.437586 0.277778 V2 -1.68843 -0.469907 0.384375 + N0 -0.636383 1.97068e-16 -0.771373 N1 -0.61392 -0.165491 -0.771826 N2 -0.673539 -0.181563 -0.716506 + txt003 +STRI + V0 0 -1.62963 0.277778 V1 -0.437586 -1.57229 0.277778 V2 -0.412723 -1.48296 0.200347 + N0 -0 -0.636383 -0.771373 N1 -0.165491 -0.61392 -0.771826 N2 -0.175561 -0.651276 -0.738253 + txt003 +STRI + V0 -0.412723 -1.48296 0.200347 V1 0 -1.53704 0.200347 V2 0 -1.62963 0.277778 + N0 -0.175561 -0.651276 -0.738253 N1 -0 -0.675056 -0.737766 N2 -0 -0.636383 -0.771373 + txt003 +STRI + V0 -0.437586 -1.57229 0.277778 V1 -0.828093 -1.40993 0.277778 V2 -0.781043 -1.32982 0.200347 + N0 -0.165491 -0.61392 -0.771826 N1 -0.318647 -0.549392 -0.77242 N2 -0.338069 -0.582878 -0.738893 + txt003 +STRI + V0 -0.781043 -1.32982 0.200347 V1 -0.412723 -1.48296 0.200347 V2 -0.437586 -1.57229 0.277778 + N0 -0.338069 -0.582878 -0.738893 N1 -0.175561 -0.651276 -0.738253 N2 -0.165491 -0.61392 -0.771826 + txt003 +STRI + V0 -0.828093 -1.40993 0.277778 V1 -1.15704 -1.15704 0.277778 V2 -1.0913 -1.0913 0.200347 + N0 -0.318647 -0.549392 -0.77242 N1 -0.448897 -0.448897 -0.772647 N2 -0.476275 -0.476275 -0.739137 + txt003 +STRI + V0 -1.0913 -1.0913 0.200347 V1 -0.781043 -1.32982 0.200347 V2 -0.828093 -1.40993 0.277778 + N0 -0.476275 -0.476275 -0.739137 N1 -0.338069 -0.582878 -0.738893 N2 -0.318647 -0.549392 -0.77242 + txt003 +STRI + V0 -1.15704 -1.15704 0.277778 V1 -1.40993 -0.828093 0.277778 V2 -1.32982 -0.781043 0.200347 + N0 -0.448897 -0.448897 -0.772647 N1 -0.549392 -0.318647 -0.77242 N2 -0.582878 -0.338069 -0.738893 + txt003 +STRI + V0 -1.32982 -0.781043 0.200347 V1 -1.0913 -1.0913 0.200347 V2 -1.15704 -1.15704 0.277778 + N0 -0.582878 -0.338069 -0.738893 N1 -0.476275 -0.476275 -0.739137 N2 -0.448897 -0.448897 -0.772647 + txt003 +STRI + V0 -1.40993 -0.828093 0.277778 V1 -1.57229 -0.437586 0.277778 V2 -1.48296 -0.412723 0.200347 + N0 -0.549392 -0.318647 -0.77242 N1 -0.61392 -0.165491 -0.771826 N2 -0.651276 -0.175561 -0.738253 + txt003 +STRI + V0 -1.48296 -0.412723 0.200347 V1 -1.32982 -0.781043 0.200347 V2 -1.40993 -0.828093 0.277778 + N0 -0.651276 -0.175561 -0.738253 N1 -0.582878 -0.338069 -0.738893 N2 -0.549392 -0.318647 -0.77242 + txt003 +STRI + V0 -1.57229 -0.437586 0.277778 V1 -1.62963 0 0.277778 V2 -1.53704 0 0.200347 + N0 -0.61392 -0.165491 -0.771826 N1 -0.636383 1.97068e-16 -0.771373 N2 -0.675056 9.51605e-17 -0.737766 + txt003 +STRI + V0 -1.53704 0 0.200347 V1 -1.48296 -0.412723 0.200347 V2 -1.57229 -0.437586 0.277778 + N0 -0.675056 9.51605e-17 -0.737766 N1 -0.651276 -0.175561 -0.738253 N2 -0.61392 -0.165491 -0.771826 + txt003 +STRI + V0 0 -1.53704 0.200347 V1 -0.412723 -1.48296 0.200347 V2 -0.402778 -1.44722 0.15 + N0 -0 -0.675056 -0.737766 N1 -0.175561 -0.651276 -0.738253 N2 -0.260275 -0.965535 -0 + txt003 +STRI + V0 -0.402778 -1.44722 0.15 V1 0 -1.5 0.15 V2 0 -1.53704 0.200347 + N0 -0.260275 -0.965535 -0 N1 -0 -1 -0 N2 -0 -0.675056 -0.737766 + txt003 +STRI + V0 -0.412723 -1.48296 0.200347 V1 -0.781043 -1.32982 0.200347 V2 -0.762222 -1.29778 0.15 + N0 -0.175561 -0.651276 -0.738253 N1 -0.338069 -0.582878 -0.738893 N2 -0.501718 -0.865031 -0 + txt003 +STRI + V0 -0.762222 -1.29778 0.15 V1 -0.402778 -1.44722 0.15 V2 -0.412723 -1.48296 0.200347 + N0 -0.501718 -0.865031 -0 N1 -0.260275 -0.965535 -0 N2 -0.175561 -0.651276 -0.738253 + txt003 +STRI + V0 -0.781043 -1.32982 0.200347 V1 -1.0913 -1.0913 0.200347 V2 -1.065 -1.065 0.15 + N0 -0.338069 -0.582878 -0.738893 N1 -0.476275 -0.476275 -0.739137 N2 -0.707107 -0.707107 -0 + txt003 +STRI + V0 -1.065 -1.065 0.15 V1 -0.762222 -1.29778 0.15 V2 -0.781043 -1.32982 0.200347 + N0 -0.707107 -0.707107 -0 N1 -0.501718 -0.865031 -0 N2 -0.338069 -0.582878 -0.738893 + txt003 +STRI + V0 -1.0913 -1.0913 0.200347 V1 -1.32982 -0.781043 0.200347 V2 -1.29778 -0.762222 0.15 + N0 -0.476275 -0.476275 -0.739137 N1 -0.582878 -0.338069 -0.738893 N2 -0.865031 -0.501718 -0 + txt003 +STRI + V0 -1.29778 -0.762222 0.15 V1 -1.065 -1.065 0.15 V2 -1.0913 -1.0913 0.200347 + N0 -0.865031 -0.501718 -0 N1 -0.707107 -0.707107 -0 N2 -0.476275 -0.476275 -0.739137 + txt003 +STRI + V0 -1.32982 -0.781043 0.200347 V1 -1.48296 -0.412723 0.200347 V2 -1.44722 -0.402778 0.15 + N0 -0.582878 -0.338069 -0.738893 N1 -0.651276 -0.175561 -0.738253 N2 -0.965535 -0.260275 -0 + txt003 +STRI + V0 -1.44722 -0.402778 0.15 V1 -1.29778 -0.762222 0.15 V2 -1.32982 -0.781043 0.200347 + N0 -0.965535 -0.260275 -0 N1 -0.865031 -0.501718 -0 N2 -0.582878 -0.338069 -0.738893 + txt003 +STRI + V0 -1.48296 -0.412723 0.200347 V1 -1.53704 0 0.200347 V2 -1.5 0 0.15 + N0 -0.651276 -0.175561 -0.738253 N1 -0.675056 9.51605e-17 -0.737766 N2 -1 0 0 + txt003 +STRI + V0 -1.5 0 0.15 V1 -1.44722 -0.402778 0.15 V2 -1.48296 -0.412723 0.200347 + N0 -1 0 0 N1 -0.965535 -0.260275 -0 N2 -0.651276 -0.175561 -0.738253 + txt003 +STRI + V0 -2 0 0.9 V1 -1.92963 0.537037 0.9 V2 -1.8939 0.527092 0.693403 + N0 -1 0 0 N1 -0.965535 0.260275 0 N2 -0.905874 0.244192 -0.346067 + txt003 +STRI + V0 -1.8939 0.527092 0.693403 V1 -1.96296 0 0.693403 V2 -2 0 0.9 + N0 -0.905874 0.244192 -0.346067 N1 -0.938373 0 -0.345625 N2 -1 0 0 + txt003 +STRI + V0 -1.92963 0.537037 0.9 V1 -1.73037 1.0163 0.9 V2 -1.69833 0.997476 0.693403 + N0 -0.965535 0.260275 0 N1 -0.865031 0.501718 0 N2 -0.811395 0.470609 -0.346647 + txt003 +STRI + V0 -1.69833 0.997476 0.693403 V1 -1.8939 0.527092 0.693403 V2 -1.92963 0.537037 0.9 + N0 -0.811395 0.470609 -0.346647 N1 -0.905874 0.244192 -0.346067 N2 -0.965535 0.260275 0 + txt003 +STRI + V0 -1.73037 1.0163 0.9 V1 -1.42 1.42 0.9 V2 -1.3937 1.3937 0.693403 + N0 -0.865031 0.501718 0 N1 -0.707107 0.707107 0 N2 -0.663205 0.663205 -0.34687 + txt003 +STRI + V0 -1.3937 1.3937 0.693403 V1 -1.69833 0.997476 0.693403 V2 -1.73037 1.0163 0.9 + N0 -0.663205 0.663205 -0.34687 N1 -0.811395 0.470609 -0.346647 N2 -0.865031 0.501718 0 + txt003 +STRI + V0 -1.42 1.42 0.9 V1 -1.0163 1.73037 0.9 V2 -0.997476 1.69833 0.693403 + N0 -0.707107 0.707107 0 N1 -0.501718 0.865031 0 N2 -0.470609 0.811395 -0.346647 + txt003 +STRI + V0 -0.997476 1.69833 0.693403 V1 -1.3937 1.3937 0.693403 V2 -1.42 1.42 0.9 + N0 -0.470609 0.811395 -0.346647 N1 -0.663205 0.663205 -0.34687 N2 -0.707107 0.707107 0 + txt003 +STRI + V0 -1.0163 1.73037 0.9 V1 -0.537037 1.92963 0.9 V2 -0.527092 1.8939 0.693403 + N0 -0.501718 0.865031 0 N1 -0.260275 0.965535 0 N2 -0.244192 0.905874 -0.346067 + txt003 +STRI + V0 -0.527092 1.8939 0.693403 V1 -0.997476 1.69833 0.693403 V2 -1.0163 1.73037 0.9 + N0 -0.244192 0.905874 -0.346067 N1 -0.470609 0.811395 -0.346647 N2 -0.501718 0.865031 0 + txt003 +STRI + V0 -0.537037 1.92963 0.9 V1 0 2 0.9 V2 -2.22045e-16 1.96296 0.693403 + N0 -0.260275 0.965535 0 N1 -0 1 0 N2 3.49072e-17 0.938373 -0.345625 + txt003 +STRI + V0 -2.22045e-16 1.96296 0.693403 V1 -0.527092 1.8939 0.693403 V2 -0.537037 1.92963 0.9 + N0 3.49072e-17 0.938373 -0.345625 N1 -0.244192 0.905874 -0.346067 N2 -0.260275 0.965535 0 + txt003 +STRI + V0 -1.96296 0 0.693403 V1 -1.8939 0.527092 0.693403 V2 -1.80456 0.502229 0.522222 + N0 -0.938373 0 -0.345625 N1 -0.905874 0.244192 -0.346067 N2 -0.782908 0.211045 -0.585248 + txt003 +STRI + V0 -1.80456 0.502229 0.522222 V1 -1.87037 0 0.522222 V2 -1.96296 0 0.693403 + N0 -0.782908 0.211045 -0.585248 N1 -0.811257 0 -0.58469 N2 -0.938373 0 -0.345625 + txt003 +STRI + V0 -1.8939 0.527092 0.693403 V1 -1.69833 0.997476 0.693403 V2 -1.61822 0.950425 0.522222 + N0 -0.905874 0.244192 -0.346067 N1 -0.811395 0.470609 -0.346647 N2 -0.700957 0.406555 -0.58598 + txt003 +STRI + V0 -1.61822 0.950425 0.522222 V1 -1.80456 0.502229 0.522222 V2 -1.8939 0.527092 0.693403 + N0 -0.700957 0.406555 -0.58598 N1 -0.782908 0.211045 -0.585248 N2 -0.905874 0.244192 -0.346067 + txt003 +STRI + V0 -1.69833 0.997476 0.693403 V1 -1.3937 1.3937 0.693403 V2 -1.32796 1.32796 0.522222 + N0 -0.811395 0.470609 -0.346647 N1 -0.663205 0.663205 -0.34687 N2 -0.572843 0.572843 -0.586261 + txt003 +STRI + V0 -1.32796 1.32796 0.522222 V1 -1.61822 0.950425 0.522222 V2 -1.69833 0.997476 0.693403 + N0 -0.572843 0.572843 -0.586261 N1 -0.700957 0.406555 -0.58598 N2 -0.811395 0.470609 -0.346647 + txt003 +STRI + V0 -1.3937 1.3937 0.693403 V1 -0.997476 1.69833 0.693403 V2 -0.950425 1.61822 0.522222 + N0 -0.663205 0.663205 -0.34687 N1 -0.470609 0.811395 -0.346647 N2 -0.406555 0.700957 -0.58598 + txt003 +STRI + V0 -0.950425 1.61822 0.522222 V1 -1.32796 1.32796 0.522222 V2 -1.3937 1.3937 0.693403 + N0 -0.406555 0.700957 -0.58598 N1 -0.572843 0.572843 -0.586261 N2 -0.663205 0.663205 -0.34687 + txt003 +STRI + V0 -0.997476 1.69833 0.693403 V1 -0.527092 1.8939 0.693403 V2 -0.502229 1.80456 0.522222 + N0 -0.470609 0.811395 -0.346647 N1 -0.244192 0.905874 -0.346067 N2 -0.211045 0.782908 -0.585248 + txt003 +STRI + V0 -0.502229 1.80456 0.522222 V1 -0.950425 1.61822 0.522222 V2 -0.997476 1.69833 0.693403 + N0 -0.211045 0.782908 -0.585248 N1 -0.406555 0.700957 -0.58598 N2 -0.470609 0.811395 -0.346647 + txt003 +STRI + V0 -0.527092 1.8939 0.693403 V1 -2.22045e-16 1.96296 0.693403 V2 -2.22045e-16 1.87037 0.522222 + N0 -0.244192 0.905874 -0.346067 N1 3.49072e-17 0.938373 -0.345625 N2 6.19755e-17 0.811257 -0.58469 + txt003 +STRI + V0 -2.22045e-16 1.87037 0.522222 V1 -0.502229 1.80456 0.522222 V2 -0.527092 1.8939 0.693403 + N0 6.19755e-17 0.811257 -0.58469 N1 -0.211045 0.782908 -0.585248 N2 -0.244192 0.905874 -0.346067 + txt003 +STRI + V0 -1.87037 0 0.522222 V1 -1.80456 0.502229 0.522222 V2 -1.68843 0.469907 0.384375 + N0 -0.811257 0 -0.58469 N1 -0.782908 0.211045 -0.585248 N2 -0.673539 0.181563 -0.716506 + txt003 +STRI + V0 -1.68843 0.469907 0.384375 V1 -1.75 0 0.384375 V2 -1.87037 0 0.522222 + N0 -0.673539 0.181563 -0.716506 N1 -0.6981 0 -0.716 N2 -0.811257 0 -0.58469 + txt003 +STRI + V0 -1.80456 0.502229 0.522222 V1 -1.61822 0.950425 0.522222 V2 -1.51407 0.889259 0.384375 + N0 -0.782908 0.211045 -0.585248 N1 -0.700957 0.406555 -0.58598 N2 -0.602839 0.349647 -0.717169 + txt003 +STRI + V0 -1.51407 0.889259 0.384375 V1 -1.68843 0.469907 0.384375 V2 -1.80456 0.502229 0.522222 + N0 -0.602839 0.349647 -0.717169 N1 -0.673539 0.181563 -0.716506 N2 -0.782908 0.211045 -0.585248 + txt003 +STRI + V0 -1.61822 0.950425 0.522222 V1 -1.32796 1.32796 0.522222 V2 -1.2425 1.2425 0.384375 + N0 -0.700957 0.406555 -0.58598 N1 -0.572843 0.572843 -0.586261 N2 -0.492597 0.492597 -0.717423 + txt003 +STRI + V0 -1.2425 1.2425 0.384375 V1 -1.51407 0.889259 0.384375 V2 -1.61822 0.950425 0.522222 + N0 -0.492597 0.492597 -0.717423 N1 -0.602839 0.349647 -0.717169 N2 -0.700957 0.406555 -0.58598 + txt003 +STRI + V0 -1.32796 1.32796 0.522222 V1 -0.950425 1.61822 0.522222 V2 -0.889259 1.51407 0.384375 + N0 -0.572843 0.572843 -0.586261 N1 -0.406555 0.700957 -0.58598 N2 -0.349647 0.602839 -0.717169 + txt003 +STRI + V0 -0.889259 1.51407 0.384375 V1 -1.2425 1.2425 0.384375 V2 -1.32796 1.32796 0.522222 + N0 -0.349647 0.602839 -0.717169 N1 -0.492597 0.492597 -0.717423 N2 -0.572843 0.572843 -0.586261 + txt003 +STRI + V0 -0.950425 1.61822 0.522222 V1 -0.502229 1.80456 0.522222 V2 -0.469907 1.68843 0.384375 + N0 -0.406555 0.700957 -0.58598 N1 -0.211045 0.782908 -0.585248 N2 -0.181563 0.673539 -0.716506 + txt003 +STRI + V0 -0.469907 1.68843 0.384375 V1 -0.889259 1.51407 0.384375 V2 -0.950425 1.61822 0.522222 + N0 -0.181563 0.673539 -0.716506 N1 -0.349647 0.602839 -0.717169 N2 -0.406555 0.700957 -0.58598 + txt003 +STRI + V0 -0.502229 1.80456 0.522222 V1 -2.22045e-16 1.87037 0.522222 V2 -2.22045e-16 1.75 0.384375 + N0 -0.211045 0.782908 -0.585248 N1 6.19755e-17 0.811257 -0.58469 N2 8.11143e-17 0.6981 -0.716 + txt003 +STRI + V0 -2.22045e-16 1.75 0.384375 V1 -0.469907 1.68843 0.384375 V2 -0.502229 1.80456 0.522222 + N0 8.11143e-17 0.6981 -0.716 N1 -0.181563 0.673539 -0.716506 N2 -0.211045 0.782908 -0.585248 + txt003 +STRI + V0 -1.75 0 0.384375 V1 -1.68843 0.469907 0.384375 V2 -1.57229 0.437586 0.277778 + N0 -0.6981 0 -0.716 N1 -0.673539 0.181563 -0.716506 N2 -0.61392 0.165491 -0.771826 + txt003 +STRI + V0 -1.57229 0.437586 0.277778 V1 -1.62963 0 0.277778 V2 -1.75 0 0.384375 + N0 -0.61392 0.165491 -0.771826 N1 -0.636383 0 -0.771373 N2 -0.6981 0 -0.716 + txt003 +STRI + V0 -1.68843 0.469907 0.384375 V1 -1.51407 0.889259 0.384375 V2 -1.40993 0.828093 0.277778 + N0 -0.673539 0.181563 -0.716506 N1 -0.602839 0.349647 -0.717169 N2 -0.549392 0.318647 -0.77242 + txt003 +STRI + V0 -1.40993 0.828093 0.277778 V1 -1.57229 0.437586 0.277778 V2 -1.68843 0.469907 0.384375 + N0 -0.549392 0.318647 -0.77242 N1 -0.61392 0.165491 -0.771826 N2 -0.673539 0.181563 -0.716506 + txt003 +STRI + V0 -1.51407 0.889259 0.384375 V1 -1.2425 1.2425 0.384375 V2 -1.15704 1.15704 0.277778 + N0 -0.602839 0.349647 -0.717169 N1 -0.492597 0.492597 -0.717423 N2 -0.448897 0.448897 -0.772647 + txt003 +STRI + V0 -1.15704 1.15704 0.277778 V1 -1.40993 0.828093 0.277778 V2 -1.51407 0.889259 0.384375 + N0 -0.448897 0.448897 -0.772647 N1 -0.549392 0.318647 -0.77242 N2 -0.602839 0.349647 -0.717169 + txt003 +STRI + V0 -1.2425 1.2425 0.384375 V1 -0.889259 1.51407 0.384375 V2 -0.828093 1.40993 0.277778 + N0 -0.492597 0.492597 -0.717423 N1 -0.349647 0.602839 -0.717169 N2 -0.318647 0.549392 -0.77242 + txt003 +STRI + V0 -0.828093 1.40993 0.277778 V1 -1.15704 1.15704 0.277778 V2 -1.2425 1.2425 0.384375 + N0 -0.318647 0.549392 -0.77242 N1 -0.448897 0.448897 -0.772647 N2 -0.492597 0.492597 -0.717423 + txt003 +STRI + V0 -0.889259 1.51407 0.384375 V1 -0.469907 1.68843 0.384375 V2 -0.437586 1.57229 0.277778 + N0 -0.349647 0.602839 -0.717169 N1 -0.181563 0.673539 -0.716506 N2 -0.165491 0.61392 -0.771826 + txt003 +STRI + V0 -0.437586 1.57229 0.277778 V1 -0.828093 1.40993 0.277778 V2 -0.889259 1.51407 0.384375 + N0 -0.165491 0.61392 -0.771826 N1 -0.318647 0.549392 -0.77242 N2 -0.349647 0.602839 -0.717169 + txt003 +STRI + V0 -0.469907 1.68843 0.384375 V1 -2.22045e-16 1.75 0.384375 V2 0 1.62963 0.277778 + N0 -0.181563 0.673539 -0.716506 N1 8.11143e-17 0.6981 -0.716 N2 1.97068e-16 0.636383 -0.771373 + txt003 +STRI + V0 0 1.62963 0.277778 V1 -0.437586 1.57229 0.277778 V2 -0.469907 1.68843 0.384375 + N0 1.97068e-16 0.636383 -0.771373 N1 -0.165491 0.61392 -0.771826 N2 -0.181563 0.673539 -0.716506 + txt003 +STRI + V0 -1.62963 0 0.277778 V1 -1.57229 0.437586 0.277778 V2 -1.48296 0.412723 0.200347 + N0 -0.636383 0 -0.771373 N1 -0.61392 0.165491 -0.771826 N2 -0.651276 0.175561 -0.738253 + txt003 +STRI + V0 -1.48296 0.412723 0.200347 V1 -1.53704 0 0.200347 V2 -1.62963 0 0.277778 + N0 -0.651276 0.175561 -0.738253 N1 -0.675056 0 -0.737766 N2 -0.636383 0 -0.771373 + txt003 +STRI + V0 -1.57229 0.437586 0.277778 V1 -1.40993 0.828093 0.277778 V2 -1.32982 0.781043 0.200347 + N0 -0.61392 0.165491 -0.771826 N1 -0.549392 0.318647 -0.77242 N2 -0.582878 0.338069 -0.738893 + txt003 +STRI + V0 -1.32982 0.781043 0.200347 V1 -1.48296 0.412723 0.200347 V2 -1.57229 0.437586 0.277778 + N0 -0.582878 0.338069 -0.738893 N1 -0.651276 0.175561 -0.738253 N2 -0.61392 0.165491 -0.771826 + txt003 +STRI + V0 -1.40993 0.828093 0.277778 V1 -1.15704 1.15704 0.277778 V2 -1.0913 1.0913 0.200347 + N0 -0.549392 0.318647 -0.77242 N1 -0.448897 0.448897 -0.772647 N2 -0.476275 0.476275 -0.739137 + txt003 +STRI + V0 -1.0913 1.0913 0.200347 V1 -1.32982 0.781043 0.200347 V2 -1.40993 0.828093 0.277778 + N0 -0.476275 0.476275 -0.739137 N1 -0.582878 0.338069 -0.738893 N2 -0.549392 0.318647 -0.77242 + txt003 +STRI + V0 -1.15704 1.15704 0.277778 V1 -0.828093 1.40993 0.277778 V2 -0.781043 1.32982 0.200347 + N0 -0.448897 0.448897 -0.772647 N1 -0.318647 0.549392 -0.77242 N2 -0.338069 0.582878 -0.738893 + txt003 +STRI + V0 -0.781043 1.32982 0.200347 V1 -1.0913 1.0913 0.200347 V2 -1.15704 1.15704 0.277778 + N0 -0.338069 0.582878 -0.738893 N1 -0.476275 0.476275 -0.739137 N2 -0.448897 0.448897 -0.772647 + txt003 +STRI + V0 -0.828093 1.40993 0.277778 V1 -0.437586 1.57229 0.277778 V2 -0.412723 1.48296 0.200347 + N0 -0.318647 0.549392 -0.77242 N1 -0.165491 0.61392 -0.771826 N2 -0.175561 0.651276 -0.738253 + txt003 +STRI + V0 -0.412723 1.48296 0.200347 V1 -0.781043 1.32982 0.200347 V2 -0.828093 1.40993 0.277778 + N0 -0.175561 0.651276 -0.738253 N1 -0.338069 0.582878 -0.738893 N2 -0.318647 0.549392 -0.77242 + txt003 +STRI + V0 -0.437586 1.57229 0.277778 V1 0 1.62963 0.277778 V2 0 1.53704 0.200347 + N0 -0.165491 0.61392 -0.771826 N1 1.97068e-16 0.636383 -0.771373 N2 9.51605e-17 0.675056 -0.737766 + txt003 +STRI + V0 0 1.53704 0.200347 V1 -0.412723 1.48296 0.200347 V2 -0.437586 1.57229 0.277778 + N0 9.51605e-17 0.675056 -0.737766 N1 -0.175561 0.651276 -0.738253 N2 -0.165491 0.61392 -0.771826 + txt003 +STRI + V0 -1.53704 0 0.200347 V1 -1.48296 0.412723 0.200347 V2 -1.44722 0.402778 0.15 + N0 -0.675056 0 -0.737766 N1 -0.651276 0.175561 -0.738253 N2 -0.965535 0.260275 0 + txt003 +STRI + V0 -1.44722 0.402778 0.15 V1 -1.5 0 0.15 V2 -1.53704 0 0.200347 + N0 -0.965535 0.260275 0 N1 -1 0 0 N2 -0.675056 0 -0.737766 + txt003 +STRI + V0 -1.48296 0.412723 0.200347 V1 -1.32982 0.781043 0.200347 V2 -1.29778 0.762222 0.15 + N0 -0.651276 0.175561 -0.738253 N1 -0.582878 0.338069 -0.738893 N2 -0.865031 0.501718 0 + txt003 +STRI + V0 -1.29778 0.762222 0.15 V1 -1.44722 0.402778 0.15 V2 -1.48296 0.412723 0.200347 + N0 -0.865031 0.501718 0 N1 -0.965535 0.260275 0 N2 -0.651276 0.175561 -0.738253 + txt003 +STRI + V0 -1.32982 0.781043 0.200347 V1 -1.0913 1.0913 0.200347 V2 -1.065 1.065 0.15 + N0 -0.582878 0.338069 -0.738893 N1 -0.476275 0.476275 -0.739137 N2 -0.707107 0.707107 0 + txt003 +STRI + V0 -1.065 1.065 0.15 V1 -1.29778 0.762222 0.15 V2 -1.32982 0.781043 0.200347 + N0 -0.707107 0.707107 0 N1 -0.865031 0.501718 0 N2 -0.582878 0.338069 -0.738893 + txt003 +STRI + V0 -1.0913 1.0913 0.200347 V1 -0.781043 1.32982 0.200347 V2 -0.762222 1.29778 0.15 + N0 -0.476275 0.476275 -0.739137 N1 -0.338069 0.582878 -0.738893 N2 -0.501718 0.865031 0 + txt003 +STRI + V0 -0.762222 1.29778 0.15 V1 -1.065 1.065 0.15 V2 -1.0913 1.0913 0.200347 + N0 -0.501718 0.865031 0 N1 -0.707107 0.707107 0 N2 -0.476275 0.476275 -0.739137 + txt003 +STRI + V0 -0.781043 1.32982 0.200347 V1 -0.412723 1.48296 0.200347 V2 -0.402778 1.44722 0.15 + N0 -0.338069 0.582878 -0.738893 N1 -0.175561 0.651276 -0.738253 N2 -0.260275 0.965535 0 + txt003 +STRI + V0 -0.402778 1.44722 0.15 V1 -0.762222 1.29778 0.15 V2 -0.781043 1.32982 0.200347 + N0 -0.260275 0.965535 0 N1 -0.501718 0.865031 0 N2 -0.338069 0.582878 -0.738893 + txt003 +STRI + V0 -0.412723 1.48296 0.200347 V1 0 1.53704 0.200347 V2 0 1.5 0.15 + N0 -0.175561 0.651276 -0.738253 N1 9.51605e-17 0.675056 -0.737766 N2 -0 1 0 + txt003 +STRI + V0 0 1.5 0.15 V1 -0.402778 1.44722 0.15 V2 -0.412723 1.48296 0.200347 + N0 -0 1 0 N1 -0.260275 0.965535 0 N2 -0.175561 0.651276 -0.738253 + txt003 +STRI + V0 0 2 0.9 V1 0.537037 1.92963 0.9 V2 0.527092 1.8939 0.693403 + N0 -0 1 0 N1 0.260275 0.965535 0 N2 0.244192 0.905874 -0.346067 + txt003 +STRI + V0 0.527092 1.8939 0.693403 V1 0 1.96296 0.693403 V2 0 2 0.9 + N0 0.244192 0.905874 -0.346067 N1 0 0.938373 -0.345625 N2 -0 1 0 + txt003 +STRI + V0 0.537037 1.92963 0.9 V1 1.0163 1.73037 0.9 V2 0.997476 1.69833 0.693403 + N0 0.260275 0.965535 0 N1 0.501718 0.865031 0 N2 0.470609 0.811395 -0.346647 + txt003 +STRI + V0 0.997476 1.69833 0.693403 V1 0.527092 1.8939 0.693403 V2 0.537037 1.92963 0.9 + N0 0.470609 0.811395 -0.346647 N1 0.244192 0.905874 -0.346067 N2 0.260275 0.965535 0 + txt003 +STRI + V0 1.0163 1.73037 0.9 V1 1.42 1.42 0.9 V2 1.3937 1.3937 0.693403 + N0 0.501718 0.865031 0 N1 0.707107 0.707107 0 N2 0.663205 0.663205 -0.34687 + txt003 +STRI + V0 1.3937 1.3937 0.693403 V1 0.997476 1.69833 0.693403 V2 1.0163 1.73037 0.9 + N0 0.663205 0.663205 -0.34687 N1 0.470609 0.811395 -0.346647 N2 0.501718 0.865031 0 + txt003 +STRI + V0 1.42 1.42 0.9 V1 1.73037 1.0163 0.9 V2 1.69833 0.997476 0.693403 + N0 0.707107 0.707107 0 N1 0.865031 0.501718 0 N2 0.811395 0.470609 -0.346647 + txt003 +STRI + V0 1.69833 0.997476 0.693403 V1 1.3937 1.3937 0.693403 V2 1.42 1.42 0.9 + N0 0.811395 0.470609 -0.346647 N1 0.663205 0.663205 -0.34687 N2 0.707107 0.707107 0 + txt003 +STRI + V0 1.73037 1.0163 0.9 V1 1.92963 0.537037 0.9 V2 1.8939 0.527092 0.693403 + N0 0.865031 0.501718 0 N1 0.965535 0.260275 0 N2 0.905874 0.244192 -0.346067 + txt003 +STRI + V0 1.8939 0.527092 0.693403 V1 1.69833 0.997476 0.693403 V2 1.73037 1.0163 0.9 + N0 0.905874 0.244192 -0.346067 N1 0.811395 0.470609 -0.346647 N2 0.865031 0.501718 0 + txt003 +STRI + V0 1.92963 0.537037 0.9 V1 2 0 0.9 V2 1.96296 2.22045e-16 0.693403 + N0 0.965535 0.260275 0 N1 1 0 0 N2 0.938373 -3.49072e-17 -0.345625 + txt003 +STRI + V0 1.96296 2.22045e-16 0.693403 V1 1.8939 0.527092 0.693403 V2 1.92963 0.537037 0.9 + N0 0.938373 -3.49072e-17 -0.345625 N1 0.905874 0.244192 -0.346067 N2 0.965535 0.260275 0 + txt003 +STRI + V0 0 1.96296 0.693403 V1 0.527092 1.8939 0.693403 V2 0.502229 1.80456 0.522222 + N0 0 0.938373 -0.345625 N1 0.244192 0.905874 -0.346067 N2 0.211045 0.782908 -0.585248 + txt003 +STRI + V0 0.502229 1.80456 0.522222 V1 0 1.87037 0.522222 V2 0 1.96296 0.693403 + N0 0.211045 0.782908 -0.585248 N1 0 0.811257 -0.58469 N2 0 0.938373 -0.345625 + txt003 +STRI + V0 0.527092 1.8939 0.693403 V1 0.997476 1.69833 0.693403 V2 0.950425 1.61822 0.522222 + N0 0.244192 0.905874 -0.346067 N1 0.470609 0.811395 -0.346647 N2 0.406555 0.700957 -0.58598 + txt003 +STRI + V0 0.950425 1.61822 0.522222 V1 0.502229 1.80456 0.522222 V2 0.527092 1.8939 0.693403 + N0 0.406555 0.700957 -0.58598 N1 0.211045 0.782908 -0.585248 N2 0.244192 0.905874 -0.346067 + txt003 +STRI + V0 0.997476 1.69833 0.693403 V1 1.3937 1.3937 0.693403 V2 1.32796 1.32796 0.522222 + N0 0.470609 0.811395 -0.346647 N1 0.663205 0.663205 -0.34687 N2 0.572843 0.572843 -0.586261 + txt003 +STRI + V0 1.32796 1.32796 0.522222 V1 0.950425 1.61822 0.522222 V2 0.997476 1.69833 0.693403 + N0 0.572843 0.572843 -0.586261 N1 0.406555 0.700957 -0.58598 N2 0.470609 0.811395 -0.346647 + txt003 +STRI + V0 1.3937 1.3937 0.693403 V1 1.69833 0.997476 0.693403 V2 1.61822 0.950425 0.522222 + N0 0.663205 0.663205 -0.34687 N1 0.811395 0.470609 -0.346647 N2 0.700957 0.406555 -0.58598 + txt003 +STRI + V0 1.61822 0.950425 0.522222 V1 1.32796 1.32796 0.522222 V2 1.3937 1.3937 0.693403 + N0 0.700957 0.406555 -0.58598 N1 0.572843 0.572843 -0.586261 N2 0.663205 0.663205 -0.34687 + txt003 +STRI + V0 1.69833 0.997476 0.693403 V1 1.8939 0.527092 0.693403 V2 1.80456 0.502229 0.522222 + N0 0.811395 0.470609 -0.346647 N1 0.905874 0.244192 -0.346067 N2 0.782908 0.211045 -0.585248 + txt003 +STRI + V0 1.80456 0.502229 0.522222 V1 1.61822 0.950425 0.522222 V2 1.69833 0.997476 0.693403 + N0 0.782908 0.211045 -0.585248 N1 0.700957 0.406555 -0.58598 N2 0.811395 0.470609 -0.346647 + txt003 +STRI + V0 1.8939 0.527092 0.693403 V1 1.96296 2.22045e-16 0.693403 V2 1.87037 2.22045e-16 0.522222 + N0 0.905874 0.244192 -0.346067 N1 0.938373 -3.49072e-17 -0.345625 N2 0.811257 -6.19755e-17 -0.58469 + txt003 +STRI + V0 1.87037 2.22045e-16 0.522222 V1 1.80456 0.502229 0.522222 V2 1.8939 0.527092 0.693403 + N0 0.811257 -6.19755e-17 -0.58469 N1 0.782908 0.211045 -0.585248 N2 0.905874 0.244192 -0.346067 + txt003 +STRI + V0 0 1.87037 0.522222 V1 0.502229 1.80456 0.522222 V2 0.469907 1.68843 0.384375 + N0 0 0.811257 -0.58469 N1 0.211045 0.782908 -0.585248 N2 0.181563 0.673539 -0.716506 + txt003 +STRI + V0 0.469907 1.68843 0.384375 V1 0 1.75 0.384375 V2 0 1.87037 0.522222 + N0 0.181563 0.673539 -0.716506 N1 0 0.6981 -0.716 N2 0 0.811257 -0.58469 + txt003 +STRI + V0 0.502229 1.80456 0.522222 V1 0.950425 1.61822 0.522222 V2 0.889259 1.51407 0.384375 + N0 0.211045 0.782908 -0.585248 N1 0.406555 0.700957 -0.58598 N2 0.349647 0.602839 -0.717169 + txt003 +STRI + V0 0.889259 1.51407 0.384375 V1 0.469907 1.68843 0.384375 V2 0.502229 1.80456 0.522222 + N0 0.349647 0.602839 -0.717169 N1 0.181563 0.673539 -0.716506 N2 0.211045 0.782908 -0.585248 + txt003 +STRI + V0 0.950425 1.61822 0.522222 V1 1.32796 1.32796 0.522222 V2 1.2425 1.2425 0.384375 + N0 0.406555 0.700957 -0.58598 N1 0.572843 0.572843 -0.586261 N2 0.492597 0.492597 -0.717423 + txt003 +STRI + V0 1.2425 1.2425 0.384375 V1 0.889259 1.51407 0.384375 V2 0.950425 1.61822 0.522222 + N0 0.492597 0.492597 -0.717423 N1 0.349647 0.602839 -0.717169 N2 0.406555 0.700957 -0.58598 + txt003 +STRI + V0 1.32796 1.32796 0.522222 V1 1.61822 0.950425 0.522222 V2 1.51407 0.889259 0.384375 + N0 0.572843 0.572843 -0.586261 N1 0.700957 0.406555 -0.58598 N2 0.602839 0.349647 -0.717169 + txt003 +STRI + V0 1.51407 0.889259 0.384375 V1 1.2425 1.2425 0.384375 V2 1.32796 1.32796 0.522222 + N0 0.602839 0.349647 -0.717169 N1 0.492597 0.492597 -0.717423 N2 0.572843 0.572843 -0.586261 + txt003 +STRI + V0 1.61822 0.950425 0.522222 V1 1.80456 0.502229 0.522222 V2 1.68843 0.469907 0.384375 + N0 0.700957 0.406555 -0.58598 N1 0.782908 0.211045 -0.585248 N2 0.673539 0.181563 -0.716506 + txt003 +STRI + V0 1.68843 0.469907 0.384375 V1 1.51407 0.889259 0.384375 V2 1.61822 0.950425 0.522222 + N0 0.673539 0.181563 -0.716506 N1 0.602839 0.349647 -0.717169 N2 0.700957 0.406555 -0.58598 + txt003 +STRI + V0 1.80456 0.502229 0.522222 V1 1.87037 2.22045e-16 0.522222 V2 1.75 2.22045e-16 0.384375 + N0 0.782908 0.211045 -0.585248 N1 0.811257 -6.19755e-17 -0.58469 N2 0.6981 -8.11143e-17 -0.716 + txt003 +STRI + V0 1.75 2.22045e-16 0.384375 V1 1.68843 0.469907 0.384375 V2 1.80456 0.502229 0.522222 + N0 0.6981 -8.11143e-17 -0.716 N1 0.673539 0.181563 -0.716506 N2 0.782908 0.211045 -0.585248 + txt003 +STRI + V0 0 1.75 0.384375 V1 0.469907 1.68843 0.384375 V2 0.437586 1.57229 0.277778 + N0 0 0.6981 -0.716 N1 0.181563 0.673539 -0.716506 N2 0.165491 0.61392 -0.771826 + txt003 +STRI + V0 0.437586 1.57229 0.277778 V1 0 1.62963 0.277778 V2 0 1.75 0.384375 + N0 0.165491 0.61392 -0.771826 N1 0 0.636383 -0.771373 N2 0 0.6981 -0.716 + txt003 +STRI + V0 0.469907 1.68843 0.384375 V1 0.889259 1.51407 0.384375 V2 0.828093 1.40993 0.277778 + N0 0.181563 0.673539 -0.716506 N1 0.349647 0.602839 -0.717169 N2 0.318647 0.549392 -0.77242 + txt003 +STRI + V0 0.828093 1.40993 0.277778 V1 0.437586 1.57229 0.277778 V2 0.469907 1.68843 0.384375 + N0 0.318647 0.549392 -0.77242 N1 0.165491 0.61392 -0.771826 N2 0.181563 0.673539 -0.716506 + txt003 +STRI + V0 0.889259 1.51407 0.384375 V1 1.2425 1.2425 0.384375 V2 1.15704 1.15704 0.277778 + N0 0.349647 0.602839 -0.717169 N1 0.492597 0.492597 -0.717423 N2 0.448897 0.448897 -0.772647 + txt003 +STRI + V0 1.15704 1.15704 0.277778 V1 0.828093 1.40993 0.277778 V2 0.889259 1.51407 0.384375 + N0 0.448897 0.448897 -0.772647 N1 0.318647 0.549392 -0.77242 N2 0.349647 0.602839 -0.717169 + txt003 +STRI + V0 1.2425 1.2425 0.384375 V1 1.51407 0.889259 0.384375 V2 1.40993 0.828093 0.277778 + N0 0.492597 0.492597 -0.717423 N1 0.602839 0.349647 -0.717169 N2 0.549392 0.318647 -0.77242 + txt003 +STRI + V0 1.40993 0.828093 0.277778 V1 1.15704 1.15704 0.277778 V2 1.2425 1.2425 0.384375 + N0 0.549392 0.318647 -0.77242 N1 0.448897 0.448897 -0.772647 N2 0.492597 0.492597 -0.717423 + txt003 +STRI + V0 1.51407 0.889259 0.384375 V1 1.68843 0.469907 0.384375 V2 1.57229 0.437586 0.277778 + N0 0.602839 0.349647 -0.717169 N1 0.673539 0.181563 -0.716506 N2 0.61392 0.165491 -0.771826 + txt003 +STRI + V0 1.57229 0.437586 0.277778 V1 1.40993 0.828093 0.277778 V2 1.51407 0.889259 0.384375 + N0 0.61392 0.165491 -0.771826 N1 0.549392 0.318647 -0.77242 N2 0.602839 0.349647 -0.717169 + txt003 +STRI + V0 1.68843 0.469907 0.384375 V1 1.75 2.22045e-16 0.384375 V2 1.62963 0 0.277778 + N0 0.673539 0.181563 -0.716506 N1 0.6981 -8.11143e-17 -0.716 N2 0.636383 -1.97068e-16 -0.771373 + txt003 +STRI + V0 1.62963 0 0.277778 V1 1.57229 0.437586 0.277778 V2 1.68843 0.469907 0.384375 + N0 0.636383 -1.97068e-16 -0.771373 N1 0.61392 0.165491 -0.771826 N2 0.673539 0.181563 -0.716506 + txt003 +STRI + V0 0 1.62963 0.277778 V1 0.437586 1.57229 0.277778 V2 0.412723 1.48296 0.200347 + N0 0 0.636383 -0.771373 N1 0.165491 0.61392 -0.771826 N2 0.175561 0.651276 -0.738253 + txt003 +STRI + V0 0.412723 1.48296 0.200347 V1 0 1.53704 0.200347 V2 0 1.62963 0.277778 + N0 0.175561 0.651276 -0.738253 N1 0 0.675056 -0.737766 N2 0 0.636383 -0.771373 + txt003 +STRI + V0 0.437586 1.57229 0.277778 V1 0.828093 1.40993 0.277778 V2 0.781043 1.32982 0.200347 + N0 0.165491 0.61392 -0.771826 N1 0.318647 0.549392 -0.77242 N2 0.338069 0.582878 -0.738893 + txt003 +STRI + V0 0.781043 1.32982 0.200347 V1 0.412723 1.48296 0.200347 V2 0.437586 1.57229 0.277778 + N0 0.338069 0.582878 -0.738893 N1 0.175561 0.651276 -0.738253 N2 0.165491 0.61392 -0.771826 + txt003 +STRI + V0 0.828093 1.40993 0.277778 V1 1.15704 1.15704 0.277778 V2 1.0913 1.0913 0.200347 + N0 0.318647 0.549392 -0.77242 N1 0.448897 0.448897 -0.772647 N2 0.476275 0.476275 -0.739137 + txt003 +STRI + V0 1.0913 1.0913 0.200347 V1 0.781043 1.32982 0.200347 V2 0.828093 1.40993 0.277778 + N0 0.476275 0.476275 -0.739137 N1 0.338069 0.582878 -0.738893 N2 0.318647 0.549392 -0.77242 + txt003 +STRI + V0 1.15704 1.15704 0.277778 V1 1.40993 0.828093 0.277778 V2 1.32982 0.781043 0.200347 + N0 0.448897 0.448897 -0.772647 N1 0.549392 0.318647 -0.77242 N2 0.582878 0.338069 -0.738893 + txt003 +STRI + V0 1.32982 0.781043 0.200347 V1 1.0913 1.0913 0.200347 V2 1.15704 1.15704 0.277778 + N0 0.582878 0.338069 -0.738893 N1 0.476275 0.476275 -0.739137 N2 0.448897 0.448897 -0.772647 + txt003 +STRI + V0 1.40993 0.828093 0.277778 V1 1.57229 0.437586 0.277778 V2 1.48296 0.412723 0.200347 + N0 0.549392 0.318647 -0.77242 N1 0.61392 0.165491 -0.771826 N2 0.651276 0.175561 -0.738253 + txt003 +STRI + V0 1.48296 0.412723 0.200347 V1 1.32982 0.781043 0.200347 V2 1.40993 0.828093 0.277778 + N0 0.651276 0.175561 -0.738253 N1 0.582878 0.338069 -0.738893 N2 0.549392 0.318647 -0.77242 + txt003 +STRI + V0 1.57229 0.437586 0.277778 V1 1.62963 0 0.277778 V2 1.53704 0 0.200347 + N0 0.61392 0.165491 -0.771826 N1 0.636383 -1.97068e-16 -0.771373 N2 0.675056 -9.51605e-17 -0.737766 + txt003 +STRI + V0 1.53704 0 0.200347 V1 1.48296 0.412723 0.200347 V2 1.57229 0.437586 0.277778 + N0 0.675056 -9.51605e-17 -0.737766 N1 0.651276 0.175561 -0.738253 N2 0.61392 0.165491 -0.771826 + txt003 +STRI + V0 0 1.53704 0.200347 V1 0.412723 1.48296 0.200347 V2 0.402778 1.44722 0.15 + N0 0 0.675056 -0.737766 N1 0.175561 0.651276 -0.738253 N2 0.260275 0.965535 0 + txt003 +STRI + V0 0.402778 1.44722 0.15 V1 0 1.5 0.15 V2 0 1.53704 0.200347 + N0 0.260275 0.965535 0 N1 -0 1 0 N2 0 0.675056 -0.737766 + txt003 +STRI + V0 0.412723 1.48296 0.200347 V1 0.781043 1.32982 0.200347 V2 0.762222 1.29778 0.15 + N0 0.175561 0.651276 -0.738253 N1 0.338069 0.582878 -0.738893 N2 0.501718 0.865031 0 + txt003 +STRI + V0 0.762222 1.29778 0.15 V1 0.402778 1.44722 0.15 V2 0.412723 1.48296 0.200347 + N0 0.501718 0.865031 0 N1 0.260275 0.965535 0 N2 0.175561 0.651276 -0.738253 + txt003 +STRI + V0 0.781043 1.32982 0.200347 V1 1.0913 1.0913 0.200347 V2 1.065 1.065 0.15 + N0 0.338069 0.582878 -0.738893 N1 0.476275 0.476275 -0.739137 N2 0.707107 0.707107 0 + txt003 +STRI + V0 1.065 1.065 0.15 V1 0.762222 1.29778 0.15 V2 0.781043 1.32982 0.200347 + N0 0.707107 0.707107 0 N1 0.501718 0.865031 0 N2 0.338069 0.582878 -0.738893 + txt003 +STRI + V0 1.0913 1.0913 0.200347 V1 1.32982 0.781043 0.200347 V2 1.29778 0.762222 0.15 + N0 0.476275 0.476275 -0.739137 N1 0.582878 0.338069 -0.738893 N2 0.865031 0.501718 0 + txt003 +STRI + V0 1.29778 0.762222 0.15 V1 1.065 1.065 0.15 V2 1.0913 1.0913 0.200347 + N0 0.865031 0.501718 0 N1 0.707107 0.707107 0 N2 0.476275 0.476275 -0.739137 + txt003 +STRI + V0 1.32982 0.781043 0.200347 V1 1.48296 0.412723 0.200347 V2 1.44722 0.402778 0.15 + N0 0.582878 0.338069 -0.738893 N1 0.651276 0.175561 -0.738253 N2 0.965535 0.260275 0 + txt003 +STRI + V0 1.44722 0.402778 0.15 V1 1.29778 0.762222 0.15 V2 1.32982 0.781043 0.200347 + N0 0.965535 0.260275 0 N1 0.865031 0.501718 0 N2 0.582878 0.338069 -0.738893 + txt003 +STRI + V0 1.48296 0.412723 0.200347 V1 1.53704 0 0.200347 V2 1.5 0 0.15 + N0 0.651276 0.175561 -0.738253 N1 0.675056 -9.51605e-17 -0.737766 N2 1 0 0 + txt003 +STRI + V0 1.5 0 0.15 V1 1.44722 0.402778 0.15 V2 1.48296 0.412723 0.200347 + N0 1 0 0 N1 0.965535 0.260275 0 N2 0.651276 0.175561 -0.738253 + txt003 +STRI + V0 -1.6 0 2.025 V1 -1.59259 -0.125 2.04167 V2 -1.92704 -0.125 2.04055 + N0 -0 -0 -1 N1 -0 -0.298275 -0.95448 N2 0.0104256 -0.297446 -0.954682 + txt003 +STRI + V0 -1.92704 -0.125 2.04055 V1 -1.92454 0 2.02396 V2 -1.6 0 2.025 + N0 0.0104256 -0.297446 -0.954682 N1 0.0104645 0 -0.999945 N2 -0 -0 -1 + txt003 +STRI + V0 -1.59259 -0.125 2.04167 V1 -1.57407 -0.2 2.08333 V2 -1.9333 -0.2 2.08202 + N0 -0 -0.298275 -0.95448 N1 -0 -0.707107 -0.707107 N2 0.00846382 -0.706077 -0.708084 + txt003 +STRI + V0 -1.9333 -0.2 2.08202 V1 -1.92704 -0.125 2.04055 V2 -1.59259 -0.125 2.04167 + N0 0.00846382 -0.706077 -0.708084 N1 0.0104256 -0.297446 -0.954682 N2 -0 -0.298275 -0.95448 + txt003 +STRI + V0 -1.57407 -0.2 2.08333 V1 -1.55 -0.225 2.1375 V2 -1.94144 -0.225 2.13594 + N0 -0 -0.707107 -0.707107 N1 0 -1 0 N2 -1.61364e-18 -1 -2.43505e-19 + txt003 +STRI + V0 -1.94144 -0.225 2.13594 V1 -1.9333 -0.2 2.08202 V2 -1.57407 -0.2 2.08333 + N0 -1.61364e-18 -1 -2.43505e-19 N1 0.00846382 -0.706077 -0.708084 N2 -0 -0.707107 -0.707107 + txt003 +STRI + V0 -1.55 -0.225 2.1375 V1 -1.52593 -0.2 2.19167 V2 -1.94957 -0.2 2.18985 + N0 0 -1 0 N1 0 -0.707107 0.707107 N2 -0.00997559 -0.706181 0.707961 + txt003 +STRI + V0 -1.94957 -0.2 2.18985 V1 -1.94144 -0.225 2.13594 V2 -1.55 -0.225 2.1375 + N0 -0.00997559 -0.706181 0.707961 N1 -1.61364e-18 -1 -2.43505e-19 N2 0 -1 0 + txt003 +STRI + V0 -1.52593 -0.2 2.19167 V1 -1.50741 -0.125 2.23333 V2 -1.95583 -0.125 2.23133 + N0 0 -0.707107 0.707107 N1 0 -0.298275 0.95448 N2 -0.0140841 -0.297589 0.95459 + txt003 +STRI + V0 -1.95583 -0.125 2.23133 V1 -1.94957 -0.2 2.18985 V2 -1.52593 -0.2 2.19167 + N0 -0.0140841 -0.297589 0.95459 N1 -0.00997559 -0.706181 0.707961 N2 0 -0.707107 0.707107 + txt003 +STRI + V0 -1.50741 -0.125 2.23333 V1 -1.5 0 2.25 V2 -1.95833 0 2.24792 + N0 0 -0.298275 0.95448 N1 0 1.97373e-15 1 N2 -0.0149983 1.96426e-15 0.999888 + txt003 +STRI + V0 -1.95833 0 2.24792 V1 -1.95583 -0.125 2.23133 V2 -1.50741 -0.125 2.23333 + N0 -0.0149983 1.96426e-15 0.999888 N1 -0.0140841 -0.297589 0.95459 N2 0 -0.298275 0.95448 + txt003 +STRI + V0 -1.92454 0 2.02396 V1 -1.92704 -0.125 2.04055 V2 -2.20645 -0.125 2.03272 + N0 0.0104645 0 -0.999945 N1 0.0104256 -0.297446 -0.954682 N2 0.0510028 -0.296675 -0.953616 + txt003 +STRI + V0 -2.20645 -0.125 2.03272 V1 -2.1963 0 2.01667 V2 -1.92454 0 2.02396 + N0 0.0510028 -0.296675 -0.953616 N1 0.0510696 0 -0.998695 N2 0.0104645 0 -0.999945 + txt003 +STRI + V0 -1.92704 -0.125 2.04055 V1 -1.9333 -0.2 2.08202 V2 -2.23182 -0.2 2.07284 + N0 0.0104256 -0.297446 -0.954682 N1 0.00846382 -0.706077 -0.708084 N2 0.0415994 -0.706072 -0.706918 + txt003 +STRI + V0 -2.23182 -0.2 2.07284 V1 -2.20645 -0.125 2.03272 V2 -1.92704 -0.125 2.04055 + N0 0.0415994 -0.706072 -0.706918 N1 0.0510028 -0.296675 -0.953616 N2 0.0104256 -0.297446 -0.954682 + txt003 +STRI + V0 -1.9333 -0.2 2.08202 V1 -1.94144 -0.225 2.13594 V2 -2.26481 -0.225 2.125 + N0 0.00846382 -0.706077 -0.708084 N1 -1.61364e-18 -1 -2.43505e-19 N2 -7.69071e-18 -1 -4.86421e-18 + txt003 +STRI + V0 -2.26481 -0.225 2.125 V1 -2.23182 -0.2 2.07284 V2 -1.9333 -0.2 2.08202 + N0 -7.69071e-18 -1 -4.86421e-18 N1 0.0415994 -0.706072 -0.706918 N2 0.00846382 -0.706077 -0.708084 + txt003 +STRI + V0 -1.94144 -0.225 2.13594 V1 -1.94957 -0.2 2.18985 V2 -2.29781 -0.2 2.17716 + N0 -1.61364e-18 -1 -2.43505e-19 N1 -0.00997559 -0.706181 0.707961 N2 -0.0493858 -0.708239 0.704243 + txt003 +STRI + V0 -2.29781 -0.2 2.17716 V1 -2.26481 -0.225 2.125 V2 -1.94144 -0.225 2.13594 + N0 -0.0493858 -0.708239 0.704243 N1 -7.69071e-18 -1 -4.86421e-18 N2 -1.61364e-18 -1 -2.43505e-19 + txt003 +STRI + V0 -1.94957 -0.2 2.18985 V1 -1.95583 -0.125 2.23133 V2 -2.32318 -0.125 2.21728 + N0 -0.00997559 -0.706181 0.707961 N1 -0.0140841 -0.297589 0.95459 N2 -0.0701017 -0.299663 0.951466 + txt003 +STRI + V0 -2.32318 -0.125 2.21728 V1 -2.29781 -0.2 2.17716 V2 -1.94957 -0.2 2.18985 + N0 -0.0701017 -0.299663 0.951466 N1 -0.0493858 -0.708239 0.704243 N2 -0.00997559 -0.706181 0.707961 + txt003 +STRI + V0 -1.95583 -0.125 2.23133 V1 -1.95833 0 2.24792 V2 -2.33333 0 2.23333 + N0 -0.0140841 -0.297589 0.95459 N1 -0.0149983 1.96426e-15 0.999888 N2 -0.0747899 1.66682e-15 0.997199 + txt003 +STRI + V0 -2.33333 0 2.23333 V1 -2.32318 -0.125 2.21728 V2 -1.95583 -0.125 2.23133 + N0 -0.0747899 1.66682e-15 0.997199 N1 -0.0701017 -0.299663 0.951466 N2 -0.0140841 -0.297589 0.95459 + txt003 +STRI + V0 -2.1963 0 2.01667 V1 -2.20645 -0.125 2.03272 V2 -2.42824 -0.125 2.01146 + N0 0.0510696 0 -0.998695 N1 0.0510028 -0.296675 -0.953616 N2 0.148104 -0.301279 -0.941964 + txt003 +STRI + V0 -2.42824 -0.125 2.01146 V1 -2.4125 0 1.99687 V2 -2.1963 0 2.01667 + N0 0.148104 -0.301279 -0.941964 N1 0.14834 0 -0.988936 N2 0.0510696 0 -0.998695 + txt003 +STRI + V0 -2.20645 -0.125 2.03272 V1 -2.23182 -0.2 2.07284 V2 -2.46759 -0.2 2.04792 + N0 0.0510028 -0.296675 -0.953616 N1 0.0415994 -0.706072 -0.706918 N2 0.119688 -0.715388 -0.6884 + txt003 +STRI + V0 -2.46759 -0.2 2.04792 V1 -2.42824 -0.125 2.01146 V2 -2.20645 -0.125 2.03272 + N0 0.119688 -0.715388 -0.6884 N1 0.148104 -0.301279 -0.941964 N2 0.0510028 -0.296675 -0.953616 + txt003 +STRI + V0 -2.23182 -0.2 2.07284 V1 -2.26481 -0.225 2.125 V2 -2.51875 -0.225 2.09531 + N0 0.0415994 -0.706072 -0.706918 N1 -7.69071e-18 -1 -4.86421e-18 N2 -1.96915e-17 -1 -2.12543e-17 + txt003 +STRI + V0 -2.51875 -0.225 2.09531 V1 -2.46759 -0.2 2.04792 V2 -2.23182 -0.2 2.07284 + N0 -1.96915e-17 -1 -2.12543e-17 N1 0.119688 -0.715388 -0.6884 N2 0.0415994 -0.706072 -0.706918 + txt003 +STRI + V0 -2.26481 -0.225 2.125 V1 -2.29781 -0.2 2.17716 V2 -2.56991 -0.2 2.14271 + N0 -7.69071e-18 -1 -4.86421e-18 N1 -0.0493858 -0.708239 0.704243 N2 -0.141352 -0.724137 0.675015 + txt003 +STRI + V0 -2.56991 -0.2 2.14271 V1 -2.51875 -0.225 2.09531 V2 -2.26481 -0.225 2.125 + N0 -0.141352 -0.724137 0.675015 N1 -1.96915e-17 -1 -2.12543e-17 N2 -7.69071e-18 -1 -4.86421e-18 + txt003 +STRI + V0 -2.29781 -0.2 2.17716 V1 -2.32318 -0.125 2.21728 V2 -2.60926 -0.125 2.17917 + N0 -0.0493858 -0.708239 0.704243 N1 -0.0701017 -0.299663 0.951466 N2 -0.204668 -0.313917 0.927128 + txt003 +STRI + V0 -2.60926 -0.125 2.17917 V1 -2.56991 -0.2 2.14271 V2 -2.29781 -0.2 2.17716 + N0 -0.204668 -0.313917 0.927128 N1 -0.141352 -0.724137 0.675015 N2 -0.0493858 -0.708239 0.704243 + txt003 +STRI + V0 -2.32318 -0.125 2.21728 V1 -2.33333 0 2.23333 V2 -2.625 0 2.19375 + N0 -0.0701017 -0.299663 0.951466 N1 -0.0747899 1.66682e-15 0.997199 N2 -0.219512 1.81728e-15 0.97561 + txt003 +STRI + V0 -2.625 0 2.19375 V1 -2.60926 -0.125 2.17917 V2 -2.32318 -0.125 2.21728 + N0 -0.219512 1.81728e-15 0.97561 N1 -0.204668 -0.313917 0.927128 N2 -0.0701017 -0.299663 0.951466 + txt003 +STRI + V0 -2.4125 0 1.99687 V1 -2.42824 -0.125 2.01146 V2 -2.58985 -0.125 1.97006 + N0 0.14834 0 -0.988936 N1 0.148104 -0.301279 -0.941964 N2 0.359682 -0.323804 -0.875089 + txt003 +STRI + V0 -2.58985 -0.125 1.97006 V1 -2.57037 0 1.95833 V2 -2.4125 0 1.99687 + N0 0.359682 -0.323804 -0.875089 N1 0.364399 0 -0.931243 N2 0.14834 0 -0.988936 + txt003 +STRI + V0 -2.42824 -0.125 2.01146 V1 -2.46759 -0.2 2.04792 V2 -2.63855 -0.2 1.99938 + N0 0.148104 -0.301279 -0.941964 N1 0.119688 -0.715388 -0.6884 N2 0.275915 -0.747596 -0.604128 + txt003 +STRI + V0 -2.63855 -0.2 1.99938 V1 -2.58985 -0.125 1.97006 V2 -2.42824 -0.125 2.01146 + N0 0.275915 -0.747596 -0.604128 N1 0.359682 -0.323804 -0.875089 N2 0.148104 -0.301279 -0.941964 + txt003 +STRI + V0 -2.46759 -0.2 2.04792 V1 -2.51875 -0.225 2.09531 V2 -2.70185 -0.225 2.0375 + N0 0.119688 -0.715388 -0.6884 N1 -1.96915e-17 -1 -2.12543e-17 N2 -3.40413e-17 -1 -5.65364e-17 + txt003 +STRI + V0 -2.70185 -0.225 2.0375 V1 -2.63855 -0.2 1.99938 V2 -2.46759 -0.2 2.04792 + N0 -3.40413e-17 -1 -5.65364e-17 N1 0.275915 -0.747596 -0.604128 N2 0.119688 -0.715388 -0.6884 + txt003 +STRI + V0 -2.51875 -0.225 2.09531 V1 -2.56991 -0.2 2.14271 V2 -2.76516 -0.2 2.07562 + N0 -1.96915e-17 -1 -2.12543e-17 N1 -0.141352 -0.724137 0.675015 N2 -0.313659 -0.763673 0.564289 + txt003 +STRI + V0 -2.76516 -0.2 2.07562 V1 -2.70185 -0.225 2.0375 V2 -2.51875 -0.225 2.09531 + N0 -0.313659 -0.763673 0.564289 N1 -3.40413e-17 -1 -5.65364e-17 N2 -1.96915e-17 -1 -2.12543e-17 + txt003 +STRI + V0 -2.56991 -0.2 2.14271 V1 -2.60926 -0.125 2.17917 V2 -2.81385 -0.125 2.10494 + N0 -0.141352 -0.724137 0.675015 N1 -0.204668 -0.313917 0.927128 N2 -0.474611 -0.350859 0.807244 + txt003 +STRI + V0 -2.81385 -0.125 2.10494 V1 -2.76516 -0.2 2.07562 V2 -2.56991 -0.2 2.14271 + N0 -0.474611 -0.350859 0.807244 N1 -0.313659 -0.763673 0.564289 N2 -0.141352 -0.724137 0.675015 + txt003 +STRI + V0 -2.60926 -0.125 2.17917 V1 -2.625 0 2.19375 V2 -2.83333 0 2.11667 + N0 -0.204668 -0.313917 0.927128 N1 -0.219512 1.81728e-15 0.97561 N2 -0.514496 1.6713e-15 0.857493 + txt003 +STRI + V0 -2.83333 0 2.11667 V1 -2.81385 -0.125 2.10494 V2 -2.60926 -0.125 2.17917 + N0 -0.514496 1.6713e-15 0.857493 N1 -0.474611 -0.350859 0.807244 N2 -0.204668 -0.313917 0.927128 + txt003 +STRI + V0 -2.57037 0 1.95833 V1 -2.58985 -0.125 1.97006 V2 -2.6887 -0.125 1.90181 + N0 0.364399 0 -0.931243 N1 0.359682 -0.323804 -0.875089 N2 0.727532 -0.37029 -0.577566 + txt003 +STRI + V0 -2.6887 -0.125 1.90181 V1 -2.66713 0 1.89479 V2 -2.57037 0 1.95833 + N0 0.727532 -0.37029 -0.577566 N1 0.767382 0 -0.64119 N2 0.364399 0 -0.931243 + txt003 +STRI + V0 -2.58985 -0.125 1.97006 V1 -2.63855 -0.2 1.99938 V2 -2.74263 -0.2 1.91937 + N0 0.359682 -0.323804 -0.875089 N1 0.275915 -0.747596 -0.604128 N2 0.497152 -0.792374 -0.35353 + txt003 +STRI + V0 -2.74263 -0.2 1.91937 V1 -2.6887 -0.125 1.90181 V2 -2.58985 -0.125 1.97006 + N0 0.497152 -0.792374 -0.35353 N1 0.727532 -0.37029 -0.577566 N2 0.359682 -0.323804 -0.875089 + txt003 +STRI + V0 -2.63855 -0.2 1.99938 V1 -2.70185 -0.225 2.0375 V2 -2.81273 -0.225 1.94219 + N0 0.275915 -0.747596 -0.604128 N1 -3.40413e-17 -1 -5.65364e-17 N2 -3.3285e-17 -1 -1.02253e-16 + txt003 +STRI + V0 -2.81273 -0.225 1.94219 V1 -2.74263 -0.2 1.91937 V2 -2.63855 -0.2 1.99938 + N0 -3.3285e-17 -1 -1.02253e-16 N1 0.497152 -0.792374 -0.35353 N2 0.275915 -0.747596 -0.604128 + txt003 +STRI + V0 -2.70185 -0.225 2.0375 V1 -2.76516 -0.2 2.07562 V2 -2.88284 -0.2 1.96501 + N0 -3.40413e-17 -1 -5.65364e-17 N1 -0.313659 -0.763673 0.564289 N2 -0.519903 -0.799556 0.300684 + txt003 +STRI + V0 -2.88284 -0.2 1.96501 V1 -2.81273 -0.225 1.94219 V2 -2.70185 -0.225 2.0375 + N0 -0.519903 -0.799556 0.300684 N1 -3.3285e-17 -1 -1.02253e-16 N2 -3.40413e-17 -1 -5.65364e-17 + txt003 +STRI + V0 -2.76516 -0.2 2.07562 V1 -2.81385 -0.125 2.10494 V2 -2.93676 -0.125 1.98256 + N0 -0.313659 -0.763673 0.564289 N1 -0.474611 -0.350859 0.807244 N2 -0.810111 -0.385772 0.441476 + txt003 +STRI + V0 -2.93676 -0.125 1.98256 V1 -2.88284 -0.2 1.96501 V2 -2.76516 -0.2 2.07562 + N0 -0.810111 -0.385772 0.441476 N1 -0.519903 -0.799556 0.300684 N2 -0.313659 -0.763673 0.564289 + txt003 +STRI + V0 -2.81385 -0.125 2.10494 V1 -2.83333 0 2.11667 V2 -2.95833 0 1.98958 + N0 -0.474611 -0.350859 0.807244 N1 -0.514496 1.6713e-15 0.857493 N2 -0.882353 9.28814e-16 0.470588 + txt003 +STRI + V0 -2.95833 0 1.98958 V1 -2.93676 -0.125 1.98256 V2 -2.81385 -0.125 2.10494 + N0 -0.882353 9.28814e-16 0.470588 N1 -0.810111 -0.385772 0.441476 N2 -0.474611 -0.350859 0.807244 + txt003 +STRI + V0 -2.66713 0 1.89479 V1 -2.6887 -0.125 1.90181 V2 -2.72222 -0.125 1.8 + N0 0.767382 0 -0.64119 N1 0.727532 -0.37029 -0.577566 N2 0.923077 -0.384615 2.05733e-15 + txt003 +STRI + V0 -2.72222 -0.125 1.8 V1 -2.7 0 1.8 V2 -2.66713 0 1.89479 + N0 0.923077 -0.384615 2.05733e-15 N1 1 0 2.63164e-15 N2 0.767382 0 -0.64119 + txt003 +STRI + V0 -2.6887 -0.125 1.90181 V1 -2.74263 -0.2 1.91937 V2 -2.77778 -0.2 1.8 + N0 0.727532 -0.37029 -0.577566 N1 0.497152 -0.792374 -0.35353 N2 0.6 -0.8 8.24322e-16 + txt003 +STRI + V0 -2.77778 -0.2 1.8 V1 -2.72222 -0.125 1.8 V2 -2.6887 -0.125 1.90181 + N0 0.6 -0.8 8.24322e-16 N1 0.923077 -0.384615 2.05733e-15 N2 0.727532 -0.37029 -0.577566 + txt003 +STRI + V0 -2.74263 -0.2 1.91937 V1 -2.81273 -0.225 1.94219 V2 -2.85 -0.225 1.8 + N0 0.497152 -0.792374 -0.35353 N1 -3.3285e-17 -1 -1.02253e-16 N2 -1.21738e-31 -1 -1.23358e-16 + txt003 +STRI + V0 -2.85 -0.225 1.8 V1 -2.77778 -0.2 1.8 V2 -2.74263 -0.2 1.91937 + N0 -1.21738e-31 -1 -1.23358e-16 N1 0.6 -0.8 8.24322e-16 N2 0.497152 -0.792374 -0.35353 + txt003 +STRI + V0 -2.81273 -0.225 1.94219 V1 -2.88284 -0.2 1.96501 V2 -2.92222 -0.2 1.8 + N0 -3.3285e-17 -1 -1.02253e-16 N1 -0.519903 -0.799556 0.300684 N2 -0.6 -0.8 -3.10757e-16 + txt003 +STRI + V0 -2.92222 -0.2 1.8 V1 -2.85 -0.225 1.8 V2 -2.81273 -0.225 1.94219 + N0 -0.6 -0.8 -3.10757e-16 N1 -1.21738e-31 -1 -1.23358e-16 N2 -3.3285e-17 -1 -1.02253e-16 + txt003 +STRI + V0 -2.88284 -0.2 1.96501 V1 -2.93676 -0.125 1.98256 V2 -2.97778 -0.125 1.8 + N0 -0.519903 -0.799556 0.300684 N1 -0.810111 -0.385772 0.441476 N2 -0.923077 -0.384615 -1.1396e-16 + txt003 +STRI + V0 -2.97778 -0.125 1.8 V1 -2.92222 -0.2 1.8 V2 -2.88284 -0.2 1.96501 + N0 -0.923077 -0.384615 -1.1396e-16 N1 -0.6 -0.8 -3.10757e-16 N2 -0.519903 -0.799556 0.300684 + txt003 +STRI + V0 -2.93676 -0.125 1.98256 V1 -2.95833 0 1.98958 V2 -3 0 1.8 + N0 -0.810111 -0.385772 0.441476 N1 -0.882353 9.28814e-16 0.470588 N2 -1 -4.93432e-16 -0 + txt003 +STRI + V0 -3 0 1.8 V1 -2.97778 -0.125 1.8 V2 -2.93676 -0.125 1.98256 + N0 -1 -4.93432e-16 -0 N1 -0.923077 -0.384615 -1.1396e-16 N2 -0.810111 -0.385772 0.441476 + txt003 +STRI + V0 -1.5 0 2.25 V1 -1.50741 0.125 2.23333 V2 -1.95583 0.125 2.23133 + N0 0 -0 1 N1 0 0.298275 0.95448 N2 -0.0140841 0.297589 0.95459 + txt003 +STRI + V0 -1.95583 0.125 2.23133 V1 -1.95833 0 2.24792 V2 -1.5 0 2.25 + N0 -0.0140841 0.297589 0.95459 N1 -0.0149983 0 0.999888 N2 0 -0 1 + txt003 +STRI + V0 -1.50741 0.125 2.23333 V1 -1.52593 0.2 2.19167 V2 -1.94957 0.2 2.18985 + N0 0 0.298275 0.95448 N1 0 0.707107 0.707107 N2 -0.00997559 0.706181 0.707961 + txt003 +STRI + V0 -1.94957 0.2 2.18985 V1 -1.95583 0.125 2.23133 V2 -1.50741 0.125 2.23333 + N0 -0.00997559 0.706181 0.707961 N1 -0.0140841 0.297589 0.95459 N2 0 0.298275 0.95448 + txt003 +STRI + V0 -1.52593 0.2 2.19167 V1 -1.55 0.225 2.1375 V2 -1.94144 0.225 2.13594 + N0 0 0.707107 0.707107 N1 0 1 0 N2 -1.61364e-18 1 -2.43505e-19 + txt003 +STRI + V0 -1.94144 0.225 2.13594 V1 -1.94957 0.2 2.18985 V2 -1.52593 0.2 2.19167 + N0 -1.61364e-18 1 -2.43505e-19 N1 -0.00997559 0.706181 0.707961 N2 0 0.707107 0.707107 + txt003 +STRI + V0 -1.55 0.225 2.1375 V1 -1.57407 0.2 2.08333 V2 -1.9333 0.2 2.08202 + N0 0 1 0 N1 0 0.707107 -0.707107 N2 0.00846382 0.706077 -0.708084 + txt003 +STRI + V0 -1.9333 0.2 2.08202 V1 -1.94144 0.225 2.13594 V2 -1.55 0.225 2.1375 + N0 0.00846382 0.706077 -0.708084 N1 -1.61364e-18 1 -2.43505e-19 N2 0 1 0 + txt003 +STRI + V0 -1.57407 0.2 2.08333 V1 -1.59259 0.125 2.04167 V2 -1.92704 0.125 2.04055 + N0 0 0.707107 -0.707107 N1 0 0.298275 -0.95448 N2 0.0104256 0.297446 -0.954682 + txt003 +STRI + V0 -1.92704 0.125 2.04055 V1 -1.9333 0.2 2.08202 V2 -1.57407 0.2 2.08333 + N0 0.0104256 0.297446 -0.954682 N1 0.00846382 0.706077 -0.708084 N2 0 0.707107 -0.707107 + txt003 +STRI + V0 -1.59259 0.125 2.04167 V1 -1.6 0 2.025 V2 -1.92454 0 2.02396 + N0 0 0.298275 -0.95448 N1 -0 -4.93432e-16 -1 N2 0.0104645 -4.86951e-16 -0.999945 + txt003 +STRI + V0 -1.92454 0 2.02396 V1 -1.92704 0.125 2.04055 V2 -1.59259 0.125 2.04167 + N0 0.0104645 -4.86951e-16 -0.999945 N1 0.0104256 0.297446 -0.954682 N2 0 0.298275 -0.95448 + txt003 +STRI + V0 -1.95833 0 2.24792 V1 -1.95583 0.125 2.23133 V2 -2.32318 0.125 2.21728 + N0 -0.0149983 0 0.999888 N1 -0.0140841 0.297589 0.95459 N2 -0.0701017 0.299663 0.951466 + txt003 +STRI + V0 -2.32318 0.125 2.21728 V1 -2.33333 0 2.23333 V2 -1.95833 0 2.24792 + N0 -0.0701017 0.299663 0.951466 N1 -0.0747899 0 0.997199 N2 -0.0149983 0 0.999888 + txt003 +STRI + V0 -1.95583 0.125 2.23133 V1 -1.94957 0.2 2.18985 V2 -2.29781 0.2 2.17716 + N0 -0.0140841 0.297589 0.95459 N1 -0.00997559 0.706181 0.707961 N2 -0.0493858 0.708239 0.704243 + txt003 +STRI + V0 -2.29781 0.2 2.17716 V1 -2.32318 0.125 2.21728 V2 -1.95583 0.125 2.23133 + N0 -0.0493858 0.708239 0.704243 N1 -0.0701017 0.299663 0.951466 N2 -0.0140841 0.297589 0.95459 + txt003 +STRI + V0 -1.94957 0.2 2.18985 V1 -1.94144 0.225 2.13594 V2 -2.26481 0.225 2.125 + N0 -0.00997559 0.706181 0.707961 N1 -1.61364e-18 1 -2.43505e-19 N2 -7.69071e-18 1 -4.86421e-18 + txt003 +STRI + V0 -2.26481 0.225 2.125 V1 -2.29781 0.2 2.17716 V2 -1.94957 0.2 2.18985 + N0 -7.69071e-18 1 -4.86421e-18 N1 -0.0493858 0.708239 0.704243 N2 -0.00997559 0.706181 0.707961 + txt003 +STRI + V0 -1.94144 0.225 2.13594 V1 -1.9333 0.2 2.08202 V2 -2.23182 0.2 2.07284 + N0 -1.61364e-18 1 -2.43505e-19 N1 0.00846382 0.706077 -0.708084 N2 0.0415994 0.706072 -0.706918 + txt003 +STRI + V0 -2.23182 0.2 2.07284 V1 -2.26481 0.225 2.125 V2 -1.94144 0.225 2.13594 + N0 0.0415994 0.706072 -0.706918 N1 -7.69071e-18 1 -4.86421e-18 N2 -1.61364e-18 1 -2.43505e-19 + txt003 +STRI + V0 -1.9333 0.2 2.08202 V1 -1.92704 0.125 2.04055 V2 -2.20645 0.125 2.03272 + N0 0.00846382 0.706077 -0.708084 N1 0.0104256 0.297446 -0.954682 N2 0.0510028 0.296675 -0.953616 + txt003 +STRI + V0 -2.20645 0.125 2.03272 V1 -2.23182 0.2 2.07284 V2 -1.9333 0.2 2.08202 + N0 0.0510028 0.296675 -0.953616 N1 0.0415994 0.706072 -0.706918 N2 0.00846382 0.706077 -0.708084 + txt003 +STRI + V0 -1.92704 0.125 2.04055 V1 -1.92454 0 2.02396 V2 -2.1963 0 2.01667 + N0 0.0104256 0.297446 -0.954682 N1 0.0104645 -4.86951e-16 -0.999945 N2 0.0510696 -2.08595e-16 -0.998695 + txt003 +STRI + V0 -2.1963 0 2.01667 V1 -2.20645 0.125 2.03272 V2 -1.92704 0.125 2.04055 + N0 0.0510696 -2.08595e-16 -0.998695 N1 0.0510028 0.296675 -0.953616 N2 0.0104256 0.297446 -0.954682 + txt003 +STRI + V0 -2.33333 0 2.23333 V1 -2.32318 0.125 2.21728 V2 -2.60926 0.125 2.17917 + N0 -0.0747899 0 0.997199 N1 -0.0701017 0.299663 0.951466 N2 -0.204668 0.313917 0.927128 + txt003 +STRI + V0 -2.60926 0.125 2.17917 V1 -2.625 0 2.19375 V2 -2.33333 0 2.23333 + N0 -0.204668 0.313917 0.927128 N1 -0.219512 0 0.97561 N2 -0.0747899 0 0.997199 + txt003 +STRI + V0 -2.32318 0.125 2.21728 V1 -2.29781 0.2 2.17716 V2 -2.56991 0.2 2.14271 + N0 -0.0701017 0.299663 0.951466 N1 -0.0493858 0.708239 0.704243 N2 -0.141352 0.724137 0.675015 + txt003 +STRI + V0 -2.56991 0.2 2.14271 V1 -2.60926 0.125 2.17917 V2 -2.32318 0.125 2.21728 + N0 -0.141352 0.724137 0.675015 N1 -0.204668 0.313917 0.927128 N2 -0.0701017 0.299663 0.951466 + txt003 +STRI + V0 -2.29781 0.2 2.17716 V1 -2.26481 0.225 2.125 V2 -2.51875 0.225 2.09531 + N0 -0.0493858 0.708239 0.704243 N1 -7.69071e-18 1 -4.86421e-18 N2 -1.96915e-17 1 -2.12543e-17 + txt003 +STRI + V0 -2.51875 0.225 2.09531 V1 -2.56991 0.2 2.14271 V2 -2.29781 0.2 2.17716 + N0 -1.96915e-17 1 -2.12543e-17 N1 -0.141352 0.724137 0.675015 N2 -0.0493858 0.708239 0.704243 + txt003 +STRI + V0 -2.26481 0.225 2.125 V1 -2.23182 0.2 2.07284 V2 -2.46759 0.2 2.04792 + N0 -7.69071e-18 1 -4.86421e-18 N1 0.0415994 0.706072 -0.706918 N2 0.119688 0.715388 -0.6884 + txt003 +STRI + V0 -2.46759 0.2 2.04792 V1 -2.51875 0.225 2.09531 V2 -2.26481 0.225 2.125 + N0 0.119688 0.715388 -0.6884 N1 -1.96915e-17 1 -2.12543e-17 N2 -7.69071e-18 1 -4.86421e-18 + txt003 +STRI + V0 -2.23182 0.2 2.07284 V1 -2.20645 0.125 2.03272 V2 -2.42824 0.125 2.01146 + N0 0.0415994 0.706072 -0.706918 N1 0.0510028 0.296675 -0.953616 N2 0.148104 0.301279 -0.941964 + txt003 +STRI + V0 -2.42824 0.125 2.01146 V1 -2.46759 0.2 2.04792 V2 -2.23182 0.2 2.07284 + N0 0.148104 0.301279 -0.941964 N1 0.119688 0.715388 -0.6884 N2 0.0415994 0.706072 -0.706918 + txt003 +STRI + V0 -2.20645 0.125 2.03272 V1 -2.1963 0 2.01667 V2 -2.4125 0 1.99687 + N0 0.0510028 0.296675 -0.953616 N1 0.0510696 -2.08595e-16 -0.998695 N2 0.14834 -4.14777e-16 -0.988936 + txt003 +STRI + V0 -2.4125 0 1.99687 V1 -2.42824 0.125 2.01146 V2 -2.20645 0.125 2.03272 + N0 0.14834 -4.14777e-16 -0.988936 N1 0.148104 0.301279 -0.941964 N2 0.0510028 0.296675 -0.953616 + txt003 +STRI + V0 -2.625 0 2.19375 V1 -2.60926 0.125 2.17917 V2 -2.81385 0.125 2.10494 + N0 -0.219512 0 0.97561 N1 -0.204668 0.313917 0.927128 N2 -0.474611 0.350859 0.807244 + txt003 +STRI + V0 -2.81385 0.125 2.10494 V1 -2.83333 0 2.11667 V2 -2.625 0 2.19375 + N0 -0.474611 0.350859 0.807244 N1 -0.514496 0 0.857493 N2 -0.219512 0 0.97561 + txt003 +STRI + V0 -2.60926 0.125 2.17917 V1 -2.56991 0.2 2.14271 V2 -2.76516 0.2 2.07562 + N0 -0.204668 0.313917 0.927128 N1 -0.141352 0.724137 0.675015 N2 -0.313659 0.763673 0.564289 + txt003 +STRI + V0 -2.76516 0.2 2.07562 V1 -2.81385 0.125 2.10494 V2 -2.60926 0.125 2.17917 + N0 -0.313659 0.763673 0.564289 N1 -0.474611 0.350859 0.807244 N2 -0.204668 0.313917 0.927128 + txt003 +STRI + V0 -2.56991 0.2 2.14271 V1 -2.51875 0.225 2.09531 V2 -2.70185 0.225 2.0375 + N0 -0.141352 0.724137 0.675015 N1 -1.96915e-17 1 -2.12543e-17 N2 -3.40413e-17 1 -5.65364e-17 + txt003 +STRI + V0 -2.70185 0.225 2.0375 V1 -2.76516 0.2 2.07562 V2 -2.56991 0.2 2.14271 + N0 -3.40413e-17 1 -5.65364e-17 N1 -0.313659 0.763673 0.564289 N2 -0.141352 0.724137 0.675015 + txt003 +STRI + V0 -2.51875 0.225 2.09531 V1 -2.46759 0.2 2.04792 V2 -2.63855 0.2 1.99938 + N0 -1.96915e-17 1 -2.12543e-17 N1 0.119688 0.715388 -0.6884 N2 0.275915 0.747596 -0.604128 + txt003 +STRI + V0 -2.63855 0.2 1.99938 V1 -2.70185 0.225 2.0375 V2 -2.51875 0.225 2.09531 + N0 0.275915 0.747596 -0.604128 N1 -3.40413e-17 1 -5.65364e-17 N2 -1.96915e-17 1 -2.12543e-17 + txt003 +STRI + V0 -2.46759 0.2 2.04792 V1 -2.42824 0.125 2.01146 V2 -2.58985 0.125 1.97006 + N0 0.119688 0.715388 -0.6884 N1 0.148104 0.301279 -0.941964 N2 0.359682 0.323804 -0.875089 + txt003 +STRI + V0 -2.58985 0.125 1.97006 V1 -2.63855 0.2 1.99938 V2 -2.46759 0.2 2.04792 + N0 0.359682 0.323804 -0.875089 N1 0.275915 0.747596 -0.604128 N2 0.119688 0.715388 -0.6884 + txt003 +STRI + V0 -2.42824 0.125 2.01146 V1 -2.4125 0 1.99687 V2 -2.57037 0 1.95833 + N0 0.148104 0.301279 -0.941964 N1 0.14834 -4.14777e-16 -0.988936 N2 0.364399 -4.84479e-16 -0.931243 + txt003 +STRI + V0 -2.57037 0 1.95833 V1 -2.58985 0.125 1.97006 V2 -2.42824 0.125 2.01146 + N0 0.364399 -4.84479e-16 -0.931243 N1 0.359682 0.323804 -0.875089 N2 0.148104 0.301279 -0.941964 + txt003 +STRI + V0 -2.83333 0 2.11667 V1 -2.81385 0.125 2.10494 V2 -2.93676 0.125 1.98256 + N0 -0.514496 0 0.857493 N1 -0.474611 0.350859 0.807244 N2 -0.810111 0.385772 0.441476 + txt003 +STRI + V0 -2.93676 0.125 1.98256 V1 -2.95833 0 1.98958 V2 -2.83333 0 2.11667 + N0 -0.810111 0.385772 0.441476 N1 -0.882353 0 0.470588 N2 -0.514496 0 0.857493 + txt003 +STRI + V0 -2.81385 0.125 2.10494 V1 -2.76516 0.2 2.07562 V2 -2.88284 0.2 1.96501 + N0 -0.474611 0.350859 0.807244 N1 -0.313659 0.763673 0.564289 N2 -0.519903 0.799556 0.300684 + txt003 +STRI + V0 -2.88284 0.2 1.96501 V1 -2.93676 0.125 1.98256 V2 -2.81385 0.125 2.10494 + N0 -0.519903 0.799556 0.300684 N1 -0.810111 0.385772 0.441476 N2 -0.474611 0.350859 0.807244 + txt003 +STRI + V0 -2.76516 0.2 2.07562 V1 -2.70185 0.225 2.0375 V2 -2.81273 0.225 1.94219 + N0 -0.313659 0.763673 0.564289 N1 -3.40413e-17 1 -5.65364e-17 N2 -3.3285e-17 1 -1.02253e-16 + txt003 +STRI + V0 -2.81273 0.225 1.94219 V1 -2.88284 0.2 1.96501 V2 -2.76516 0.2 2.07562 + N0 -3.3285e-17 1 -1.02253e-16 N1 -0.519903 0.799556 0.300684 N2 -0.313659 0.763673 0.564289 + txt003 +STRI + V0 -2.70185 0.225 2.0375 V1 -2.63855 0.2 1.99938 V2 -2.74263 0.2 1.91937 + N0 -3.40413e-17 1 -5.65364e-17 N1 0.275915 0.747596 -0.604128 N2 0.497152 0.792374 -0.35353 + txt003 +STRI + V0 -2.74263 0.2 1.91937 V1 -2.81273 0.225 1.94219 V2 -2.70185 0.225 2.0375 + N0 0.497152 0.792374 -0.35353 N1 -3.3285e-17 1 -1.02253e-16 N2 -3.40413e-17 1 -5.65364e-17 + txt003 +STRI + V0 -2.63855 0.2 1.99938 V1 -2.58985 0.125 1.97006 V2 -2.6887 0.125 1.90181 + N0 0.275915 0.747596 -0.604128 N1 0.359682 0.323804 -0.875089 N2 0.727532 0.37029 -0.577566 + txt003 +STRI + V0 -2.6887 0.125 1.90181 V1 -2.74263 0.2 1.91937 V2 -2.63855 0.2 1.99938 + N0 0.727532 0.37029 -0.577566 N1 0.497152 0.792374 -0.35353 N2 0.275915 0.747596 -0.604128 + txt003 +STRI + V0 -2.58985 0.125 1.97006 V1 -2.57037 0 1.95833 V2 -2.66713 0 1.89479 + N0 0.359682 0.323804 -0.875089 N1 0.364399 -4.84479e-16 -0.931243 N2 0.767382 -3.16384e-16 -0.64119 + txt003 +STRI + V0 -2.66713 0 1.89479 V1 -2.6887 0.125 1.90181 V2 -2.58985 0.125 1.97006 + N0 0.767382 -3.16384e-16 -0.64119 N1 0.727532 0.37029 -0.577566 N2 0.359682 0.323804 -0.875089 + txt003 +STRI + V0 -2.95833 0 1.98958 V1 -2.93676 0.125 1.98256 V2 -2.97778 0.125 1.8 + N0 -0.882353 0 0.470588 N1 -0.810111 0.385772 0.441476 N2 -0.923077 0.384615 -1.1396e-16 + txt003 +STRI + V0 -2.97778 0.125 1.8 V1 -3 0 1.8 V2 -2.95833 0 1.98958 + N0 -0.923077 0.384615 -1.1396e-16 N1 -1 0 0 N2 -0.882353 0 0.470588 + txt003 +STRI + V0 -2.93676 0.125 1.98256 V1 -2.88284 0.2 1.96501 V2 -2.92222 0.2 1.8 + N0 -0.810111 0.385772 0.441476 N1 -0.519903 0.799556 0.300684 N2 -0.6 0.8 -3.10757e-16 + txt003 +STRI + V0 -2.92222 0.2 1.8 V1 -2.97778 0.125 1.8 V2 -2.93676 0.125 1.98256 + N0 -0.6 0.8 -3.10757e-16 N1 -0.923077 0.384615 -1.1396e-16 N2 -0.810111 0.385772 0.441476 + txt003 +STRI + V0 -2.88284 0.2 1.96501 V1 -2.81273 0.225 1.94219 V2 -2.85 0.225 1.8 + N0 -0.519903 0.799556 0.300684 N1 -3.3285e-17 1 -1.02253e-16 N2 -2.13041e-31 1 -1.23358e-16 + txt003 +STRI + V0 -2.85 0.225 1.8 V1 -2.92222 0.2 1.8 V2 -2.88284 0.2 1.96501 + N0 -2.13041e-31 1 -1.23358e-16 N1 -0.6 0.8 -3.10757e-16 N2 -0.519903 0.799556 0.300684 + txt003 +STRI + V0 -2.81273 0.225 1.94219 V1 -2.74263 0.2 1.91937 V2 -2.77778 0.2 1.8 + N0 -3.3285e-17 1 -1.02253e-16 N1 0.497152 0.792374 -0.35353 N2 0.6 0.8 8.24322e-16 + txt003 +STRI + V0 -2.77778 0.2 1.8 V1 -2.85 0.225 1.8 V2 -2.81273 0.225 1.94219 + N0 0.6 0.8 8.24322e-16 N1 -2.13041e-31 1 -1.23358e-16 N2 -3.3285e-17 1 -1.02253e-16 + txt003 +STRI + V0 -2.74263 0.2 1.91937 V1 -2.6887 0.125 1.90181 V2 -2.72222 0.125 1.8 + N0 0.497152 0.792374 -0.35353 N1 0.727532 0.37029 -0.577566 N2 0.923077 0.384615 2.05733e-15 + txt003 +STRI + V0 -2.72222 0.125 1.8 V1 -2.77778 0.2 1.8 V2 -2.74263 0.2 1.91937 + N0 0.923077 0.384615 2.05733e-15 N1 0.6 0.8 8.24322e-16 N2 0.497152 0.792374 -0.35353 + txt003 +STRI + V0 -2.6887 0.125 1.90181 V1 -2.66713 0 1.89479 V2 -2.7 0 1.8 + N0 0.727532 0.37029 -0.577566 N1 0.767382 -3.16384e-16 -0.64119 N2 1 4.93432e-16 2.63164e-15 + txt003 +STRI + V0 -2.7 0 1.8 V1 -2.72222 0.125 1.8 V2 -2.6887 0.125 1.90181 + N0 1 4.93432e-16 2.63164e-15 N1 0.923077 0.384615 2.05733e-15 N2 0.727532 0.37029 -0.577566 + txt003 +STRI + V0 -2.7 0 1.8 V1 -2.72222 -0.125 1.8 V2 -2.70418 -0.125 1.66398 + N0 1 0 0 N1 0.923077 -0.384615 0 N2 0.895972 -0.38623 0.219226 + txt003 +STRI + V0 -2.70418 -0.125 1.66398 V1 -2.68287 0 1.67083 V2 -2.7 0 1.8 + N0 0.895972 -0.38623 0.219226 N1 0.972045 0 0.234794 N2 1 0 0 + txt003 +STRI + V0 -2.72222 -0.125 1.8 V1 -2.77778 -0.2 1.8 V2 -2.75747 -0.2 1.64684 + N0 0.923077 -0.384615 0 N1 0.6 -0.8 0 N2 0.57987 -0.801541 0.145888 + txt003 +STRI + V0 -2.75747 -0.2 1.64684 V1 -2.70418 -0.125 1.66398 V2 -2.72222 -0.125 1.8 + N0 0.57987 -0.801541 0.145888 N1 0.895972 -0.38623 0.219226 N2 0.923077 -0.384615 0 + txt003 +STRI + V0 -2.77778 -0.2 1.8 V1 -2.85 -0.225 1.8 V2 -2.82674 -0.225 1.62457 + N0 0.6 -0.8 0 N1 -0 -1 -0 N2 9.48478e-19 -1 -2.94924e-18 + txt003 +STRI + V0 -2.82674 -0.225 1.62457 V1 -2.75747 -0.2 1.64684 V2 -2.77778 -0.2 1.8 + N0 9.48478e-19 -1 -2.94924e-18 N1 0.57987 -0.801541 0.145888 N2 0.6 -0.8 0 + txt003 +STRI + V0 -2.85 -0.225 1.8 V1 -2.92222 -0.2 1.8 V2 -2.896 -0.2 1.60229 + N0 -0 -1 -0 N1 -0.6 -0.8 -0 N2 -0.577707 -0.801752 -0.153129 + txt003 +STRI + V0 -2.896 -0.2 1.60229 V1 -2.82674 -0.225 1.62457 V2 -2.85 -0.225 1.8 + N0 -0.577707 -0.801752 -0.153129 N1 9.48478e-19 -1 -2.94924e-18 N2 -0 -1 -0 + txt003 +STRI + V0 -2.92222 -0.2 1.8 V1 -2.97778 -0.125 1.8 V2 -2.94929 -0.125 1.58515 + N0 -0.6 -0.8 -0 N1 -0.923077 -0.384615 -0 N2 -0.890548 -0.386679 -0.23959 + txt003 +STRI + V0 -2.94929 -0.125 1.58515 V1 -2.896 -0.2 1.60229 V2 -2.92222 -0.2 1.8 + N0 -0.890548 -0.386679 -0.23959 N1 -0.577707 -0.801752 -0.153129 N2 -0.6 -0.8 -0 + txt003 +STRI + V0 -2.97778 -0.125 1.8 V1 -3 0 1.8 V2 -2.9706 0 1.5783 + N0 -0.923077 -0.384615 -0 N1 -1 -9.86865e-16 -0 N2 -0.965311 -7.59377e-16 -0.261102 + txt003 +STRI + V0 -2.9706 0 1.5783 V1 -2.94929 -0.125 1.58515 V2 -2.97778 -0.125 1.8 + N0 -0.965311 -7.59377e-16 -0.261102 N1 -0.890548 -0.386679 -0.23959 N2 -0.923077 -0.384615 -0 + txt003 +STRI + V0 -2.68287 0 1.67083 V1 -2.70418 -0.125 1.66398 V2 -2.64829 -0.125 1.50535 + N0 0.972045 0 0.234794 N1 0.895972 -0.38623 0.219226 N2 0.842942 -0.376421 0.38439 + txt003 +STRI + V0 -2.64829 -0.125 1.50535 V1 -2.62963 0 1.51667 V2 -2.68287 0 1.67083 + N0 0.842942 -0.376421 0.38439 N1 0.913812 0 0.406138 N2 0.972045 0 0.234794 + txt003 +STRI + V0 -2.70418 -0.125 1.66398 V1 -2.75747 -0.2 1.64684 V2 -2.69492 -0.2 1.47706 + N0 0.895972 -0.38623 0.219226 N1 0.57987 -0.801541 0.145888 N2 0.548194 -0.793356 0.264707 + txt003 +STRI + V0 -2.69492 -0.2 1.47706 V1 -2.64829 -0.125 1.50535 V2 -2.70418 -0.125 1.66398 + N0 0.548194 -0.793356 0.264707 N1 0.842942 -0.376421 0.38439 N2 0.895972 -0.38623 0.219226 + txt003 +STRI + V0 -2.75747 -0.2 1.64684 V1 -2.82674 -0.225 1.62457 V2 -2.75556 -0.225 1.44028 + N0 0.57987 -0.801541 0.145888 N1 9.48478e-19 -1 -2.94924e-18 N2 5.73642e-18 -1 -9.4564e-18 + txt003 +STRI + V0 -2.75556 -0.225 1.44028 V1 -2.69492 -0.2 1.47706 V2 -2.75747 -0.2 1.64684 + N0 5.73642e-18 -1 -9.4564e-18 N1 0.548194 -0.793356 0.264707 N2 0.57987 -0.801541 0.145888 + txt003 +STRI + V0 -2.82674 -0.225 1.62457 V1 -2.896 -0.2 1.60229 V2 -2.81619 -0.2 1.4035 + N0 9.48478e-19 -1 -2.94924e-18 N1 -0.577707 -0.801752 -0.153129 N2 -0.534196 -0.794341 -0.289235 + txt003 +STRI + V0 -2.81619 -0.2 1.4035 V1 -2.75556 -0.225 1.44028 V2 -2.82674 -0.225 1.62457 + N0 -0.534196 -0.794341 -0.289235 N1 5.73642e-18 -1 -9.4564e-18 N2 9.48478e-19 -1 -2.94924e-18 + txt003 +STRI + V0 -2.896 -0.2 1.60229 V1 -2.94929 -0.125 1.58515 V2 -2.86283 -0.125 1.37521 + N0 -0.577707 -0.801752 -0.153129 N1 -0.890548 -0.386679 -0.23959 N2 -0.807437 -0.378466 -0.452558 + txt003 +STRI + V0 -2.86283 -0.125 1.37521 V1 -2.81619 -0.2 1.4035 V2 -2.896 -0.2 1.60229 + N0 -0.807437 -0.378466 -0.452558 N1 -0.534196 -0.794341 -0.289235 N2 -0.577707 -0.801752 -0.153129 + txt003 +STRI + V0 -2.94929 -0.125 1.58515 V1 -2.9706 0 1.5783 V2 -2.88148 0 1.36389 + N0 -0.890548 -0.386679 -0.23959 N1 -0.965311 -7.59377e-16 -0.261102 N2 -0.869653 -7.07402e-16 -0.493664 + txt003 +STRI + V0 -2.88148 0 1.36389 V1 -2.86283 -0.125 1.37521 V2 -2.94929 -0.125 1.58515 + N0 -0.869653 -7.07402e-16 -0.493664 N1 -0.807437 -0.378466 -0.452558 N2 -0.890548 -0.386679 -0.23959 + txt003 +STRI + V0 -2.62963 0 1.51667 V1 -2.64829 -0.125 1.50535 V2 -2.55185 -0.125 1.33576 + N0 0.913812 0 0.406138 N1 0.842942 -0.376421 0.38439 N2 0.772293 -0.349434 0.530527 + txt003 +STRI + V0 -2.55185 -0.125 1.33576 V1 -2.5375 0 1.35 V2 -2.62963 0 1.51667 + N0 0.772293 -0.349434 0.530527 N1 0.83205 0 0.5547 N2 0.913812 0 0.406138 + txt003 +STRI + V0 -2.64829 -0.125 1.50535 V1 -2.69492 -0.2 1.47706 V2 -2.58773 -0.2 1.30017 + N0 0.842942 -0.376421 0.38439 N1 0.548194 -0.793356 0.264707 N2 0.515846 -0.768155 0.379264 + txt003 +STRI + V0 -2.58773 -0.2 1.30017 V1 -2.55185 -0.125 1.33576 V2 -2.64829 -0.125 1.50535 + N0 0.515846 -0.768155 0.379264 N1 0.772293 -0.349434 0.530527 N2 0.842942 -0.376421 0.38439 + txt003 +STRI + V0 -2.69492 -0.2 1.47706 V1 -2.75556 -0.225 1.44028 V2 -2.63437 -0.225 1.25391 + N0 0.548194 -0.793356 0.264707 N1 5.73642e-18 -1 -9.4564e-18 N2 1.5603e-17 -1 -1.57299e-17 + txt003 +STRI + V0 -2.63437 -0.225 1.25391 V1 -2.58773 -0.2 1.30017 V2 -2.69492 -0.2 1.47706 + N0 1.5603e-17 -1 -1.57299e-17 N1 0.515846 -0.768155 0.379264 N2 0.548194 -0.793356 0.264707 + txt003 +STRI + V0 -2.75556 -0.225 1.44028 V1 -2.81619 -0.2 1.4035 V2 -2.68102 -0.2 1.20764 + N0 5.73642e-18 -1 -9.4564e-18 N1 -0.534196 -0.794341 -0.289235 N2 -0.486433 -0.770599 -0.411777 + txt003 +STRI + V0 -2.68102 -0.2 1.20764 V1 -2.63437 -0.225 1.25391 V2 -2.75556 -0.225 1.44028 + N0 -0.486433 -0.770599 -0.411777 N1 1.5603e-17 -1 -1.57299e-17 N2 5.73642e-18 -1 -9.4564e-18 + txt003 +STRI + V0 -2.81619 -0.2 1.4035 V1 -2.86283 -0.125 1.37521 V2 -2.7169 -0.125 1.17205 + N0 -0.534196 -0.794341 -0.289235 N1 -0.807437 -0.378466 -0.452558 N2 -0.700515 -0.35392 -0.619694 + txt003 +STRI + V0 -2.7169 -0.125 1.17205 V1 -2.68102 -0.2 1.20764 V2 -2.81619 -0.2 1.4035 + N0 -0.700515 -0.35392 -0.619694 N1 -0.486433 -0.770599 -0.411777 N2 -0.534196 -0.794341 -0.289235 + txt003 +STRI + V0 -2.86283 -0.125 1.37521 V1 -2.88148 0 1.36389 V2 -2.73125 0 1.15781 + N0 -0.807437 -0.378466 -0.452558 N1 -0.869653 -7.07402e-16 -0.493664 N2 -0.743581 -2.38916e-16 -0.668646 + txt003 +STRI + V0 -2.73125 0 1.15781 V1 -2.7169 -0.125 1.17205 V2 -2.86283 -0.125 1.37521 + N0 -0.743581 -2.38916e-16 -0.668646 N1 -0.700515 -0.35392 -0.619694 N2 -0.807437 -0.378466 -0.452558 + txt003 +STRI + V0 -2.5375 0 1.35 V1 -2.55185 -0.125 1.33576 V2 -2.41221 -0.125 1.16687 + N0 0.83205 0 0.5547 N1 0.772293 -0.349434 0.530527 N2 0.676612 -0.31353 0.666255 + txt003 +STRI + V0 -2.41221 -0.125 1.16687 V1 -2.4037 0 1.18333 V2 -2.5375 0 1.35 + N0 0.676612 -0.31353 0.666255 N1 0.722374 0 0.691503 N2 0.83205 0 0.5547 + txt003 +STRI + V0 -2.55185 -0.125 1.33576 V1 -2.58773 -0.2 1.30017 V2 -2.43347 -0.2 1.12572 + N0 0.772293 -0.349434 0.530527 N1 0.515846 -0.768155 0.379264 N2 0.471519 -0.729692 0.495195 + txt003 +STRI + V0 -2.43347 -0.2 1.12572 V1 -2.41221 -0.125 1.16687 V2 -2.55185 -0.125 1.33576 + N0 0.471519 -0.729692 0.495195 N1 0.676612 -0.31353 0.666255 N2 0.772293 -0.349434 0.530527 + txt003 +STRI + V0 -2.58773 -0.2 1.30017 V1 -2.63437 -0.225 1.25391 V2 -2.46111 -0.225 1.07222 + N0 0.515846 -0.768155 0.379264 N1 1.5603e-17 -1 -1.57299e-17 N2 3.17396e-17 -1 -1.63988e-17 + txt003 +STRI + V0 -2.46111 -0.225 1.07222 V1 -2.43347 -0.2 1.12572 V2 -2.58773 -0.2 1.30017 + N0 3.17396e-17 -1 -1.63988e-17 N1 0.471519 -0.729692 0.495195 N2 0.515846 -0.768155 0.379264 + txt003 +STRI + V0 -2.63437 -0.225 1.25391 V1 -2.68102 -0.2 1.20764 V2 -2.48875 -0.2 1.01872 + N0 1.5603e-17 -1 -1.57299e-17 N1 -0.486433 -0.770599 -0.411777 N2 -0.433172 -0.735531 -0.520919 + txt003 +STRI + V0 -2.48875 -0.2 1.01872 V1 -2.46111 -0.225 1.07222 V2 -2.63437 -0.225 1.25391 + N0 -0.433172 -0.735531 -0.520919 N1 3.17396e-17 -1 -1.63988e-17 N2 1.5603e-17 -1 -1.57299e-17 + txt003 +STRI + V0 -2.68102 -0.2 1.20764 V1 -2.7169 -0.125 1.17205 V2 -2.51001 -0.125 0.977572 + N0 -0.486433 -0.770599 -0.411777 N1 -0.700515 -0.35392 -0.619694 N2 -0.589822 -0.322549 -0.740319 + txt003 +STRI + V0 -2.51001 -0.125 0.977572 V1 -2.48875 -0.2 1.01872 V2 -2.68102 -0.2 1.20764 + N0 -0.589822 -0.322549 -0.740319 N1 -0.433172 -0.735531 -0.520919 N2 -0.486433 -0.770599 -0.411777 + txt003 +STRI + V0 -2.7169 -0.125 1.17205 V1 -2.73125 0 1.15781 V2 -2.51852 0 0.961111 + N0 -0.700515 -0.35392 -0.619694 N1 -0.743581 -2.38916e-16 -0.668646 N2 -0.617031 -2.64751e-17 -0.786939 + txt003 +STRI + V0 -2.51852 0 0.961111 V1 -2.51001 -0.125 0.977572 V2 -2.7169 -0.125 1.17205 + N0 -0.617031 -2.64751e-17 -0.786939 N1 -0.589822 -0.322549 -0.740319 N2 -0.700515 -0.35392 -0.619694 + txt003 +STRI + V0 -2.4037 0 1.18333 V1 -2.41221 -0.125 1.16687 V2 -2.22668 -0.125 1.01033 + N0 0.722374 0 0.691503 N1 0.676612 -0.31353 0.666255 N2 0.548733 -0.289562 0.784249 + txt003 +STRI + V0 -2.22668 -0.125 1.01033 V1 -2.22546 0 1.02917 V2 -2.4037 0 1.18333 + N0 0.548733 -0.289562 0.784249 N1 0.580973 0 0.813923 N2 0.722374 0 0.691503 + txt003 +STRI + V0 -2.41221 -0.125 1.16687 V1 -2.43347 -0.2 1.12572 V2 -2.22972 -0.2 0.963227 + N0 0.676612 -0.31353 0.666255 N1 0.471519 -0.729692 0.495195 N2 0.396971 -0.700023 0.593618 + txt003 +STRI + V0 -2.22972 -0.2 0.963227 V1 -2.22668 -0.125 1.01033 V2 -2.41221 -0.125 1.16687 + N0 0.396971 -0.700023 0.593618 N1 0.548733 -0.289562 0.784249 N2 0.676612 -0.31353 0.666255 + txt003 +STRI + V0 -2.43347 -0.2 1.12572 V1 -2.46111 -0.225 1.07222 V2 -2.23368 -0.225 0.901997 + N0 0.471519 -0.729692 0.495195 N1 3.17396e-17 -1 -1.63988e-17 N2 5.4409e-17 -1 -3.51585e-18 + txt003 +STRI + V0 -2.23368 -0.225 0.901997 V1 -2.22972 -0.2 0.963227 V2 -2.43347 -0.2 1.12572 + N0 5.4409e-17 -1 -3.51585e-18 N1 0.396971 -0.700023 0.593618 N2 0.471519 -0.729692 0.495195 + txt003 +STRI + V0 -2.46111 -0.225 1.07222 V1 -2.48875 -0.2 1.01872 V2 -2.23764 -0.2 0.840766 + N0 3.17396e-17 -1 -1.63988e-17 N1 -0.433172 -0.735531 -0.520919 N2 -0.367048 -0.708353 -0.60292 + txt003 +STRI + V0 -2.23764 -0.2 0.840766 V1 -2.23368 -0.225 0.901997 V2 -2.46111 -0.225 1.07222 + N0 -0.367048 -0.708353 -0.60292 N1 5.4409e-17 -1 -3.51585e-18 N2 3.17396e-17 -1 -1.63988e-17 + txt003 +STRI + V0 -2.48875 -0.2 1.01872 V1 -2.51001 -0.125 0.977572 V2 -2.24068 -0.125 0.793666 + N0 -0.433172 -0.735531 -0.520919 N1 -0.589822 -0.322549 -0.740319 N2 -0.485318 -0.301052 -0.820874 + txt003 +STRI + V0 -2.24068 -0.125 0.793666 V1 -2.23764 -0.2 0.840766 V2 -2.48875 -0.2 1.01872 + N0 -0.485318 -0.301052 -0.820874 N1 -0.367048 -0.708353 -0.60292 N2 -0.433172 -0.735531 -0.520919 + txt003 +STRI + V0 -2.51001 -0.125 0.977572 V1 -2.51852 0 0.961111 V2 -2.2419 0 0.774826 + N0 -0.589822 -0.322549 -0.740319 N1 -0.617031 -2.64751e-17 -0.786939 N2 -0.504836 2.02979e-16 -0.863216 + txt003 +STRI + V0 -2.2419 0 0.774826 V1 -2.24068 -0.125 0.793666 V2 -2.51001 -0.125 0.977572 + N0 -0.504836 2.02979e-16 -0.863216 N1 -0.485318 -0.301052 -0.820874 N2 -0.589822 -0.322549 -0.740319 + txt003 +STRI + V0 -2.22546 0 1.02917 V1 -2.22668 -0.125 1.01033 V2 -1.99259 -0.125 0.877778 + N0 0.580973 0 0.813923 N1 0.548733 -0.289562 0.784249 N2 0.390503 -0.30734 0.867784 + txt003 +STRI + V0 -1.99259 -0.125 0.877778 V1 -2 0 0.9 V2 -2.22546 0 1.02917 + N0 0.390503 -0.30734 0.867784 N1 0.410365 0 0.911922 N2 0.580973 0 0.813923 + txt003 +STRI + V0 -2.22668 -0.125 1.01033 V1 -2.22972 -0.2 0.963227 V2 -1.97407 -0.2 0.822222 + N0 0.548733 -0.289562 0.784249 N1 0.396971 -0.700023 0.593618 N2 0.285351 -0.718662 0.634113 + txt003 +STRI + V0 -1.97407 -0.2 0.822222 V1 -1.99259 -0.125 0.877778 V2 -2.22668 -0.125 1.01033 + N0 0.285351 -0.718662 0.634113 N1 0.390503 -0.30734 0.867784 N2 0.548733 -0.289562 0.784249 + txt003 +STRI + V0 -2.22972 -0.2 0.963227 V1 -2.23368 -0.225 0.901997 V2 -1.95 -0.225 0.75 + N0 0.396971 -0.700023 0.593618 N1 5.4409e-17 -1 -3.51585e-18 N2 7.83687e-17 -1 2.61229e-17 + txt003 +STRI + V0 -1.95 -0.225 0.75 V1 -1.97407 -0.2 0.822222 V2 -2.22972 -0.2 0.963227 + N0 7.83687e-17 -1 2.61229e-17 N1 0.285351 -0.718662 0.634113 N2 0.396971 -0.700023 0.593618 + txt003 +STRI + V0 -2.23368 -0.225 0.901997 V1 -2.23764 -0.2 0.840766 V2 -1.92593 -0.2 0.677778 + N0 5.4409e-17 -1 -3.51585e-18 N1 -0.367048 -0.708353 -0.60292 N2 -0.285351 -0.718662 -0.634113 + txt003 +STRI + V0 -1.92593 -0.2 0.677778 V1 -1.95 -0.225 0.75 V2 -2.23368 -0.225 0.901997 + N0 -0.285351 -0.718662 -0.634113 N1 7.83687e-17 -1 2.61229e-17 N2 5.4409e-17 -1 -3.51585e-18 + txt003 +STRI + V0 -2.23764 -0.2 0.840766 V1 -2.24068 -0.125 0.793666 V2 -1.90741 -0.125 0.622222 + N0 -0.367048 -0.708353 -0.60292 N1 -0.485318 -0.301052 -0.820874 N2 -0.390503 -0.30734 -0.867784 + txt003 +STRI + V0 -1.90741 -0.125 0.622222 V1 -1.92593 -0.2 0.677778 V2 -2.23764 -0.2 0.840766 + N0 -0.390503 -0.30734 -0.867784 N1 -0.285351 -0.718662 -0.634113 N2 -0.367048 -0.708353 -0.60292 + txt003 +STRI + V0 -2.24068 -0.125 0.793666 V1 -2.2419 0 0.774826 V2 -1.9 0 0.6 + N0 -0.485318 -0.301052 -0.820874 N1 -0.504836 2.02979e-16 -0.863216 N2 -0.410365 4.49972e-17 -0.911922 + txt003 +STRI + V0 -1.9 0 0.6 V1 -1.90741 -0.125 0.622222 V2 -2.24068 -0.125 0.793666 + N0 -0.410365 4.49972e-17 -0.911922 N1 -0.390503 -0.30734 -0.867784 N2 -0.485318 -0.301052 -0.820874 + txt003 +STRI + V0 -3 0 1.8 V1 -2.97778 0.125 1.8 V2 -2.94929 0.125 1.58515 + N0 -1 0 0 N1 -0.923077 0.384615 0 N2 -0.890548 0.386679 -0.23959 + txt003 +STRI + V0 -2.94929 0.125 1.58515 V1 -2.9706 0 1.5783 V2 -3 0 1.8 + N0 -0.890548 0.386679 -0.23959 N1 -0.965311 0 -0.261102 N2 -1 0 0 + txt003 +STRI + V0 -2.97778 0.125 1.8 V1 -2.92222 0.2 1.8 V2 -2.896 0.2 1.60229 + N0 -0.923077 0.384615 0 N1 -0.6 0.8 0 N2 -0.577707 0.801752 -0.153129 + txt003 +STRI + V0 -2.896 0.2 1.60229 V1 -2.94929 0.125 1.58515 V2 -2.97778 0.125 1.8 + N0 -0.577707 0.801752 -0.153129 N1 -0.890548 0.386679 -0.23959 N2 -0.923077 0.384615 0 + txt003 +STRI + V0 -2.92222 0.2 1.8 V1 -2.85 0.225 1.8 V2 -2.82674 0.225 1.62457 + N0 -0.6 0.8 0 N1 -0 1 0 N2 9.48478e-19 1 -2.94924e-18 + txt003 +STRI + V0 -2.82674 0.225 1.62457 V1 -2.896 0.2 1.60229 V2 -2.92222 0.2 1.8 + N0 9.48478e-19 1 -2.94924e-18 N1 -0.577707 0.801752 -0.153129 N2 -0.6 0.8 0 + txt003 +STRI + V0 -2.85 0.225 1.8 V1 -2.77778 0.2 1.8 V2 -2.75747 0.2 1.64684 + N0 -0 1 0 N1 0.6 0.8 0 N2 0.57987 0.801541 0.145888 + txt003 +STRI + V0 -2.75747 0.2 1.64684 V1 -2.82674 0.225 1.62457 V2 -2.85 0.225 1.8 + N0 0.57987 0.801541 0.145888 N1 9.48478e-19 1 -2.94924e-18 N2 -0 1 0 + txt003 +STRI + V0 -2.77778 0.2 1.8 V1 -2.72222 0.125 1.8 V2 -2.70418 0.125 1.66398 + N0 0.6 0.8 0 N1 0.923077 0.384615 0 N2 0.895972 0.38623 0.219226 + txt003 +STRI + V0 -2.70418 0.125 1.66398 V1 -2.75747 0.2 1.64684 V2 -2.77778 0.2 1.8 + N0 0.895972 0.38623 0.219226 N1 0.57987 0.801541 0.145888 N2 0.6 0.8 0 + txt003 +STRI + V0 -2.72222 0.125 1.8 V1 -2.7 0 1.8 V2 -2.68287 0 1.67083 + N0 0.923077 0.384615 0 N1 1 9.86865e-16 0 N2 0.972045 1.13306e-15 0.234794 + txt003 +STRI + V0 -2.68287 0 1.67083 V1 -2.70418 0.125 1.66398 V2 -2.72222 0.125 1.8 + N0 0.972045 1.13306e-15 0.234794 N1 0.895972 0.38623 0.219226 N2 0.923077 0.384615 0 + txt003 +STRI + V0 -2.9706 0 1.5783 V1 -2.94929 0.125 1.58515 V2 -2.86283 0.125 1.37521 + N0 -0.965311 0 -0.261102 N1 -0.890548 0.386679 -0.23959 N2 -0.807437 0.378466 -0.452558 + txt003 +STRI + V0 -2.86283 0.125 1.37521 V1 -2.88148 0 1.36389 V2 -2.9706 0 1.5783 + N0 -0.807437 0.378466 -0.452558 N1 -0.869653 0 -0.493664 N2 -0.965311 0 -0.261102 + txt003 +STRI + V0 -2.94929 0.125 1.58515 V1 -2.896 0.2 1.60229 V2 -2.81619 0.2 1.4035 + N0 -0.890548 0.386679 -0.23959 N1 -0.577707 0.801752 -0.153129 N2 -0.534196 0.794341 -0.289235 + txt003 +STRI + V0 -2.81619 0.2 1.4035 V1 -2.86283 0.125 1.37521 V2 -2.94929 0.125 1.58515 + N0 -0.534196 0.794341 -0.289235 N1 -0.807437 0.378466 -0.452558 N2 -0.890548 0.386679 -0.23959 + txt003 +STRI + V0 -2.896 0.2 1.60229 V1 -2.82674 0.225 1.62457 V2 -2.75556 0.225 1.44028 + N0 -0.577707 0.801752 -0.153129 N1 9.48478e-19 1 -2.94924e-18 N2 5.73642e-18 1 -9.4564e-18 + txt003 +STRI + V0 -2.75556 0.225 1.44028 V1 -2.81619 0.2 1.4035 V2 -2.896 0.2 1.60229 + N0 5.73642e-18 1 -9.4564e-18 N1 -0.534196 0.794341 -0.289235 N2 -0.577707 0.801752 -0.153129 + txt003 +STRI + V0 -2.82674 0.225 1.62457 V1 -2.75747 0.2 1.64684 V2 -2.69492 0.2 1.47706 + N0 9.48478e-19 1 -2.94924e-18 N1 0.57987 0.801541 0.145888 N2 0.548194 0.793356 0.264707 + txt003 +STRI + V0 -2.69492 0.2 1.47706 V1 -2.75556 0.225 1.44028 V2 -2.82674 0.225 1.62457 + N0 0.548194 0.793356 0.264707 N1 5.73642e-18 1 -9.4564e-18 N2 9.48478e-19 1 -2.94924e-18 + txt003 +STRI + V0 -2.75747 0.2 1.64684 V1 -2.70418 0.125 1.66398 V2 -2.64829 0.125 1.50535 + N0 0.57987 0.801541 0.145888 N1 0.895972 0.38623 0.219226 N2 0.842942 0.376421 0.38439 + txt003 +STRI + V0 -2.64829 0.125 1.50535 V1 -2.69492 0.2 1.47706 V2 -2.75747 0.2 1.64684 + N0 0.842942 0.376421 0.38439 N1 0.548194 0.793356 0.264707 N2 0.57987 0.801541 0.145888 + txt003 +STRI + V0 -2.70418 0.125 1.66398 V1 -2.68287 0 1.67083 V2 -2.62963 0 1.51667 + N0 0.895972 0.38623 0.219226 N1 0.972045 1.13306e-15 0.234794 N2 0.913812 1.42786e-15 0.406138 + txt003 +STRI + V0 -2.62963 0 1.51667 V1 -2.64829 0.125 1.50535 V2 -2.70418 0.125 1.66398 + N0 0.913812 1.42786e-15 0.406138 N1 0.842942 0.376421 0.38439 N2 0.895972 0.38623 0.219226 + txt003 +STRI + V0 -2.88148 0 1.36389 V1 -2.86283 0.125 1.37521 V2 -2.7169 0.125 1.17205 + N0 -0.869653 0 -0.493664 N1 -0.807437 0.378466 -0.452558 N2 -0.700515 0.35392 -0.619694 + txt003 +STRI + V0 -2.7169 0.125 1.17205 V1 -2.73125 0 1.15781 V2 -2.88148 0 1.36389 + N0 -0.700515 0.35392 -0.619694 N1 -0.743581 0 -0.668646 N2 -0.869653 0 -0.493664 + txt003 +STRI + V0 -2.86283 0.125 1.37521 V1 -2.81619 0.2 1.4035 V2 -2.68102 0.2 1.20764 + N0 -0.807437 0.378466 -0.452558 N1 -0.534196 0.794341 -0.289235 N2 -0.486433 0.770599 -0.411777 + txt003 +STRI + V0 -2.68102 0.2 1.20764 V1 -2.7169 0.125 1.17205 V2 -2.86283 0.125 1.37521 + N0 -0.486433 0.770599 -0.411777 N1 -0.700515 0.35392 -0.619694 N2 -0.807437 0.378466 -0.452558 + txt003 +STRI + V0 -2.81619 0.2 1.4035 V1 -2.75556 0.225 1.44028 V2 -2.63437 0.225 1.25391 + N0 -0.534196 0.794341 -0.289235 N1 5.73642e-18 1 -9.4564e-18 N2 1.5603e-17 1 -1.57299e-17 + txt003 +STRI + V0 -2.63437 0.225 1.25391 V1 -2.68102 0.2 1.20764 V2 -2.81619 0.2 1.4035 + N0 1.5603e-17 1 -1.57299e-17 N1 -0.486433 0.770599 -0.411777 N2 -0.534196 0.794341 -0.289235 + txt003 +STRI + V0 -2.75556 0.225 1.44028 V1 -2.69492 0.2 1.47706 V2 -2.58773 0.2 1.30017 + N0 5.73642e-18 1 -9.4564e-18 N1 0.548194 0.793356 0.264707 N2 0.515846 0.768155 0.379264 + txt003 +STRI + V0 -2.58773 0.2 1.30017 V1 -2.63437 0.225 1.25391 V2 -2.75556 0.225 1.44028 + N0 0.515846 0.768155 0.379264 N1 1.5603e-17 1 -1.57299e-17 N2 5.73642e-18 1 -9.4564e-18 + txt003 +STRI + V0 -2.69492 0.2 1.47706 V1 -2.64829 0.125 1.50535 V2 -2.55185 0.125 1.33576 + N0 0.548194 0.793356 0.264707 N1 0.842942 0.376421 0.38439 N2 0.772293 0.349434 0.530527 + txt003 +STRI + V0 -2.55185 0.125 1.33576 V1 -2.58773 0.2 1.30017 V2 -2.69492 0.2 1.47706 + N0 0.772293 0.349434 0.530527 N1 0.515846 0.768155 0.379264 N2 0.548194 0.793356 0.264707 + txt003 +STRI + V0 -2.64829 0.125 1.50535 V1 -2.62963 0 1.51667 V2 -2.5375 0 1.35 + N0 0.842942 0.376421 0.38439 N1 0.913812 1.42786e-15 0.406138 N2 0.83205 1.23168e-15 0.5547 + txt003 +STRI + V0 -2.5375 0 1.35 V1 -2.55185 0.125 1.33576 V2 -2.64829 0.125 1.50535 + N0 0.83205 1.23168e-15 0.5547 N1 0.772293 0.349434 0.530527 N2 0.842942 0.376421 0.38439 + txt003 +STRI + V0 -2.73125 0 1.15781 V1 -2.7169 0.125 1.17205 V2 -2.51001 0.125 0.977572 + N0 -0.743581 0 -0.668646 N1 -0.700515 0.35392 -0.619694 N2 -0.589822 0.322549 -0.740319 + txt003 +STRI + V0 -2.51001 0.125 0.977572 V1 -2.51852 0 0.961111 V2 -2.73125 0 1.15781 + N0 -0.589822 0.322549 -0.740319 N1 -0.617031 0 -0.786939 N2 -0.743581 0 -0.668646 + txt003 +STRI + V0 -2.7169 0.125 1.17205 V1 -2.68102 0.2 1.20764 V2 -2.48875 0.2 1.01872 + N0 -0.700515 0.35392 -0.619694 N1 -0.486433 0.770599 -0.411777 N2 -0.433172 0.735531 -0.520919 + txt003 +STRI + V0 -2.48875 0.2 1.01872 V1 -2.51001 0.125 0.977572 V2 -2.7169 0.125 1.17205 + N0 -0.433172 0.735531 -0.520919 N1 -0.589822 0.322549 -0.740319 N2 -0.700515 0.35392 -0.619694 + txt003 +STRI + V0 -2.68102 0.2 1.20764 V1 -2.63437 0.225 1.25391 V2 -2.46111 0.225 1.07222 + N0 -0.486433 0.770599 -0.411777 N1 1.5603e-17 1 -1.57299e-17 N2 3.17396e-17 1 -1.63988e-17 + txt003 +STRI + V0 -2.46111 0.225 1.07222 V1 -2.48875 0.2 1.01872 V2 -2.68102 0.2 1.20764 + N0 3.17396e-17 1 -1.63988e-17 N1 -0.433172 0.735531 -0.520919 N2 -0.486433 0.770599 -0.411777 + txt003 +STRI + V0 -2.63437 0.225 1.25391 V1 -2.58773 0.2 1.30017 V2 -2.43347 0.2 1.12572 + N0 1.5603e-17 1 -1.57299e-17 N1 0.515846 0.768155 0.379264 N2 0.471519 0.729692 0.495195 + txt003 +STRI + V0 -2.43347 0.2 1.12572 V1 -2.46111 0.225 1.07222 V2 -2.63437 0.225 1.25391 + N0 0.471519 0.729692 0.495195 N1 3.17396e-17 1 -1.63988e-17 N2 1.5603e-17 1 -1.57299e-17 + txt003 +STRI + V0 -2.58773 0.2 1.30017 V1 -2.55185 0.125 1.33576 V2 -2.41221 0.125 1.16687 + N0 0.515846 0.768155 0.379264 N1 0.772293 0.349434 0.530527 N2 0.676612 0.31353 0.666255 + txt003 +STRI + V0 -2.41221 0.125 1.16687 V1 -2.43347 0.2 1.12572 V2 -2.58773 0.2 1.30017 + N0 0.676612 0.31353 0.666255 N1 0.471519 0.729692 0.495195 N2 0.515846 0.768155 0.379264 + txt003 +STRI + V0 -2.55185 0.125 1.33576 V1 -2.5375 0 1.35 V2 -2.4037 0 1.18333 + N0 0.772293 0.349434 0.530527 N1 0.83205 1.23168e-15 0.5547 N2 0.722374 1.2247e-15 0.691503 + txt003 +STRI + V0 -2.4037 0 1.18333 V1 -2.41221 0.125 1.16687 V2 -2.55185 0.125 1.33576 + N0 0.722374 1.2247e-15 0.691503 N1 0.676612 0.31353 0.666255 N2 0.772293 0.349434 0.530527 + txt003 +STRI + V0 -2.51852 0 0.961111 V1 -2.51001 0.125 0.977572 V2 -2.24068 0.125 0.793666 + N0 -0.617031 0 -0.786939 N1 -0.589822 0.322549 -0.740319 N2 -0.485318 0.301052 -0.820874 + txt003 +STRI + V0 -2.24068 0.125 0.793666 V1 -2.2419 0 0.774826 V2 -2.51852 0 0.961111 + N0 -0.485318 0.301052 -0.820874 N1 -0.504836 0 -0.863216 N2 -0.617031 0 -0.786939 + txt003 +STRI + V0 -2.51001 0.125 0.977572 V1 -2.48875 0.2 1.01872 V2 -2.23764 0.2 0.840766 + N0 -0.589822 0.322549 -0.740319 N1 -0.433172 0.735531 -0.520919 N2 -0.367048 0.708353 -0.60292 + txt003 +STRI + V0 -2.23764 0.2 0.840766 V1 -2.24068 0.125 0.793666 V2 -2.51001 0.125 0.977572 + N0 -0.367048 0.708353 -0.60292 N1 -0.485318 0.301052 -0.820874 N2 -0.589822 0.322549 -0.740319 + txt003 +STRI + V0 -2.48875 0.2 1.01872 V1 -2.46111 0.225 1.07222 V2 -2.23368 0.225 0.901997 + N0 -0.433172 0.735531 -0.520919 N1 3.17396e-17 1 -1.63988e-17 N2 5.4409e-17 1 -3.51585e-18 + txt003 +STRI + V0 -2.23368 0.225 0.901997 V1 -2.23764 0.2 0.840766 V2 -2.48875 0.2 1.01872 + N0 5.4409e-17 1 -3.51585e-18 N1 -0.367048 0.708353 -0.60292 N2 -0.433172 0.735531 -0.520919 + txt003 +STRI + V0 -2.46111 0.225 1.07222 V1 -2.43347 0.2 1.12572 V2 -2.22972 0.2 0.963227 + N0 3.17396e-17 1 -1.63988e-17 N1 0.471519 0.729692 0.495195 N2 0.396971 0.700023 0.593618 + txt003 +STRI + V0 -2.22972 0.2 0.963227 V1 -2.23368 0.225 0.901997 V2 -2.46111 0.225 1.07222 + N0 0.396971 0.700023 0.593618 N1 5.4409e-17 1 -3.51585e-18 N2 3.17396e-17 1 -1.63988e-17 + txt003 +STRI + V0 -2.43347 0.2 1.12572 V1 -2.41221 0.125 1.16687 V2 -2.22668 0.125 1.01033 + N0 0.471519 0.729692 0.495195 N1 0.676612 0.31353 0.666255 N2 0.548733 0.289562 0.784249 + txt003 +STRI + V0 -2.22668 0.125 1.01033 V1 -2.22972 0.2 0.963227 V2 -2.43347 0.2 1.12572 + N0 0.548733 0.289562 0.784249 N1 0.396971 0.700023 0.593618 N2 0.471519 0.729692 0.495195 + txt003 +STRI + V0 -2.41221 0.125 1.16687 V1 -2.4037 0 1.18333 V2 -2.22546 0 1.02917 + N0 0.676612 0.31353 0.666255 N1 0.722374 1.2247e-15 0.691503 N2 0.580973 1.1041e-15 0.813923 + txt003 +STRI + V0 -2.22546 0 1.02917 V1 -2.22668 0.125 1.01033 V2 -2.41221 0.125 1.16687 + N0 0.580973 1.1041e-15 0.813923 N1 0.548733 0.289562 0.784249 N2 0.676612 0.31353 0.666255 + txt003 +STRI + V0 -2.2419 0 0.774826 V1 -2.24068 0.125 0.793666 V2 -1.90741 0.125 0.622222 + N0 -0.504836 0 -0.863216 N1 -0.485318 0.301052 -0.820874 N2 -0.390503 0.30734 -0.867784 + txt003 +STRI + V0 -1.90741 0.125 0.622222 V1 -1.9 0 0.6 V2 -2.2419 0 0.774826 + N0 -0.390503 0.30734 -0.867784 N1 -0.410365 0 -0.911922 N2 -0.504836 0 -0.863216 + txt003 +STRI + V0 -2.24068 0.125 0.793666 V1 -2.23764 0.2 0.840766 V2 -1.92593 0.2 0.677778 + N0 -0.485318 0.301052 -0.820874 N1 -0.367048 0.708353 -0.60292 N2 -0.285351 0.718662 -0.634113 + txt003 +STRI + V0 -1.92593 0.2 0.677778 V1 -1.90741 0.125 0.622222 V2 -2.24068 0.125 0.793666 + N0 -0.285351 0.718662 -0.634113 N1 -0.390503 0.30734 -0.867784 N2 -0.485318 0.301052 -0.820874 + txt003 +STRI + V0 -2.23764 0.2 0.840766 V1 -2.23368 0.225 0.901997 V2 -1.95 0.225 0.75 + N0 -0.367048 0.708353 -0.60292 N1 5.4409e-17 1 -3.51585e-18 N2 7.83687e-17 1 2.61229e-17 + txt003 +STRI + V0 -1.95 0.225 0.75 V1 -1.92593 0.2 0.677778 V2 -2.23764 0.2 0.840766 + N0 7.83687e-17 1 2.61229e-17 N1 -0.285351 0.718662 -0.634113 N2 -0.367048 0.708353 -0.60292 + txt003 +STRI + V0 -2.23368 0.225 0.901997 V1 -2.22972 0.2 0.963227 V2 -1.97407 0.2 0.822222 + N0 5.4409e-17 1 -3.51585e-18 N1 0.396971 0.700023 0.593618 N2 0.285351 0.718662 0.634113 + txt003 +STRI + V0 -1.97407 0.2 0.822222 V1 -1.95 0.225 0.75 V2 -2.23368 0.225 0.901997 + N0 0.285351 0.718662 0.634113 N1 7.83687e-17 1 2.61229e-17 N2 5.4409e-17 1 -3.51585e-18 + txt003 +STRI + V0 -2.22972 0.2 0.963227 V1 -2.22668 0.125 1.01033 V2 -1.99259 0.125 0.877778 + N0 0.396971 0.700023 0.593618 N1 0.548733 0.289562 0.784249 N2 0.390503 0.30734 0.867784 + txt003 +STRI + V0 -1.99259 0.125 0.877778 V1 -1.97407 0.2 0.822222 V2 -2.22972 0.2 0.963227 + N0 0.390503 0.30734 0.867784 N1 0.285351 0.718662 0.634113 N2 0.396971 0.700023 0.593618 + txt003 +STRI + V0 -2.22668 0.125 1.01033 V1 -2.22546 0 1.02917 V2 -2 0 0.9 + N0 0.548733 0.289562 0.784249 N1 0.580973 1.1041e-15 0.813923 N2 0.410365 1.30492e-15 0.911922 + txt003 +STRI + V0 -2 0 0.9 V1 -1.99259 0.125 0.877778 V2 -2.22668 0.125 1.01033 + N0 0.410365 1.30492e-15 0.911922 N1 0.390503 0.30734 0.867784 N2 0.548733 0.289562 0.784249 + txt003 +STRI + V0 1.7 0 1.425 V1 1.7 -0.275 1.36389 V2 2.07238 -0.262346 1.42521 + N0 -0 0 1 N1 -0.0157732 -0.461877 0.886804 N2 -0.291732 -0.426807 0.855995 + txt003 +STRI + V0 2.07238 -0.262346 1.42521 V1 2.0588 0 1.47639 V2 1.7 0 1.425 + N0 -0.291732 -0.426807 0.855995 N1 -0.333935 0 0.942596 N2 -0 0 1 + txt003 +STRI + V0 1.7 -0.275 1.36389 V1 1.7 -0.44 1.21111 V2 2.10633 -0.419753 1.29725 + N0 -0.0157732 -0.461877 0.886804 N1 -0.0291362 -0.857129 0.514277 N2 -0.135104 -0.834377 0.534381 + txt003 +STRI + V0 2.10633 -0.419753 1.29725 V1 2.07238 -0.262346 1.42521 V2 1.7 -0.275 1.36389 + N0 -0.135104 -0.834377 0.534381 N1 -0.291732 -0.426807 0.855995 N2 -0.0157732 -0.461877 0.886804 + txt003 +STRI + V0 1.7 -0.44 1.21111 V1 1.7 -0.495 1.0125 V2 2.15046 -0.472222 1.1309 + N0 -0.0291362 -0.857129 0.514277 N1 0 -1 -0 N2 0.110195 -0.99348 0.0292376 + txt003 +STRI + V0 2.15046 -0.472222 1.1309 V1 2.10633 -0.419753 1.29725 V2 1.7 -0.44 1.21111 + N0 0.110195 -0.99348 0.0292376 N1 -0.135104 -0.834377 0.534381 N2 -0.0291362 -0.857129 0.514277 + txt003 +STRI + V0 1.7 -0.495 1.0125 V1 1.7 -0.44 0.813889 V2 2.1946 -0.419753 0.964558 + N0 0 -1 -0 N1 0.0673462 -0.855546 -0.513328 N2 0.348602 -0.814337 -0.464038 + txt003 +STRI + V0 2.1946 -0.419753 0.964558 V1 2.15046 -0.472222 1.1309 V2 1.7 -0.495 1.0125 + N0 0.348602 -0.814337 -0.464038 N1 0.110195 -0.99348 0.0292376 N2 0 -1 -0 + txt003 +STRI + V0 1.7 -0.44 0.813889 V1 1.7 -0.275 0.661111 V2 2.22855 -0.262346 0.8366 + N0 0.0673462 -0.855546 -0.513328 N1 0.134339 -0.457747 -0.878875 N2 0.492146 -0.41068 -0.767551 + txt003 +STRI + V0 2.22855 -0.262346 0.8366 V1 2.1946 -0.419753 0.964558 V2 1.7 -0.44 0.813889 + N0 0.492146 -0.41068 -0.767551 N1 0.348602 -0.814337 -0.464038 N2 0.0673462 -0.855546 -0.513328 + txt003 +STRI + V0 1.7 -0.275 0.661111 V1 1.7 0 0.6 V2 2.24213 0 0.785417 + N0 0.134339 -0.457747 -0.878875 N1 0.158678 9.39168e-16 -0.98733 N2 0.528678 6.47717e-16 -0.848822 + txt003 +STRI + V0 2.24213 0 0.785417 V1 2.22855 -0.262346 0.8366 V2 1.7 -0.275 0.661111 + N0 0.528678 6.47717e-16 -0.848822 N1 0.492146 -0.41068 -0.767551 N2 0.134339 -0.457747 -0.878875 + txt003 +STRI + V0 2.0588 0 1.47639 V1 2.07238 -0.262346 1.42521 V2 2.29012 -0.23071 1.57202 + N0 -0.333935 0 0.942596 N1 -0.291732 -0.426807 0.855995 N2 -0.64585 -0.390219 0.656206 + txt003 +STRI + V0 2.29012 -0.23071 1.57202 V1 2.27037 0 1.61111 V2 2.0588 0 1.47639 + N0 -0.64585 -0.390219 0.656206 N1 -0.731055 0 0.682318 N2 -0.333935 0 0.942596 + txt003 +STRI + V0 2.07238 -0.262346 1.42521 V1 2.10633 -0.419753 1.29725 V2 2.33951 -0.369136 1.47428 + N0 -0.291732 -0.426807 0.855995 N1 -0.135104 -0.834377 0.534381 N2 -0.312511 -0.816863 0.484842 + txt003 +STRI + V0 2.33951 -0.369136 1.47428 V1 2.29012 -0.23071 1.57202 V2 2.07238 -0.262346 1.42521 + N0 -0.312511 -0.816863 0.484842 N1 -0.64585 -0.390219 0.656206 N2 -0.291732 -0.426807 0.855995 + txt003 +STRI + V0 2.10633 -0.419753 1.29725 V1 2.15046 -0.472222 1.1309 V2 2.4037 -0.415278 1.34722 + N0 -0.135104 -0.834377 0.534381 N1 0.110195 -0.99348 0.0292376 N2 0.215359 -0.970454 0.108813 + txt003 +STRI + V0 2.4037 -0.415278 1.34722 V1 2.33951 -0.369136 1.47428 V2 2.10633 -0.419753 1.29725 + N0 0.215359 -0.970454 0.108813 N1 -0.312511 -0.816863 0.484842 N2 -0.135104 -0.834377 0.534381 + txt003 +STRI + V0 2.15046 -0.472222 1.1309 V1 2.1946 -0.419753 0.964558 V2 2.4679 -0.369136 1.22016 + N0 0.110195 -0.99348 0.0292376 N1 0.348602 -0.814337 -0.464038 N2 0.627607 -0.733748 -0.260237 + txt003 +STRI + V0 2.4679 -0.369136 1.22016 V1 2.4037 -0.415278 1.34722 V2 2.15046 -0.472222 1.1309 + N0 0.627607 -0.733748 -0.260237 N1 0.215359 -0.970454 0.108813 N2 0.110195 -0.99348 0.0292376 + txt003 +STRI + V0 2.1946 -0.419753 0.964558 V1 2.22855 -0.262346 0.8366 V2 2.51728 -0.23071 1.12243 + N0 0.348602 -0.814337 -0.464038 N1 0.492146 -0.41068 -0.767551 N2 0.813963 -0.348056 -0.465103 + txt003 +STRI + V0 2.51728 -0.23071 1.12243 V1 2.4679 -0.369136 1.22016 V2 2.1946 -0.419753 0.964558 + N0 0.813963 -0.348056 -0.465103 N1 0.627607 -0.733748 -0.260237 N2 0.348602 -0.814337 -0.464038 + txt003 +STRI + V0 2.22855 -0.262346 0.8366 V1 2.24213 0 0.785417 V2 2.53704 0 1.08333 + N0 0.492146 -0.41068 -0.767551 N1 0.528678 6.47717e-16 -0.848822 N2 0.854063 9.88017e-16 -0.52017 + txt003 +STRI + V0 2.53704 0 1.08333 V1 2.51728 -0.23071 1.12243 V2 2.22855 -0.262346 0.8366 + N0 0.854063 9.88017e-16 -0.52017 N1 0.813963 -0.348056 -0.465103 N2 0.492146 -0.41068 -0.767551 + txt003 +STRI + V0 2.27037 0 1.61111 V1 2.29012 -0.23071 1.57202 V2 2.40972 -0.189583 1.77361 + N0 -0.731055 0 0.682318 N1 -0.64585 -0.390219 0.656206 N2 -0.835237 -0.363942 0.412221 + txt003 +STRI + V0 2.40972 -0.189583 1.77361 V1 2.3875 0 1.8 V2 2.27037 0 1.61111 + N0 -0.835237 -0.363942 0.412221 N1 -0.920582 0 0.39055 N2 -0.731055 0 0.682318 + txt003 +STRI + V0 2.29012 -0.23071 1.57202 V1 2.33951 -0.369136 1.47428 V2 2.46528 -0.303333 1.70764 + N0 -0.64585 -0.390219 0.656206 N1 -0.312511 -0.816863 0.484842 N2 -0.451323 -0.803033 0.38916 + txt003 +STRI + V0 2.46528 -0.303333 1.70764 V1 2.40972 -0.189583 1.77361 V2 2.29012 -0.23071 1.57202 + N0 -0.451323 -0.803033 0.38916 N1 -0.835237 -0.363942 0.412221 N2 -0.64585 -0.390219 0.656206 + txt003 +STRI + V0 2.33951 -0.369136 1.47428 V1 2.4037 -0.415278 1.34722 V2 2.5375 -0.34125 1.62187 + N0 -0.312511 -0.816863 0.484842 N1 0.215359 -0.970454 0.108813 N2 0.214084 -0.960035 0.180281 + txt003 +STRI + V0 2.5375 -0.34125 1.62187 V1 2.46528 -0.303333 1.70764 V2 2.33951 -0.369136 1.47428 + N0 0.214084 -0.960035 0.180281 N1 -0.451323 -0.803033 0.38916 N2 -0.312511 -0.816863 0.484842 + txt003 +STRI + V0 2.4037 -0.415278 1.34722 V1 2.4679 -0.369136 1.22016 V2 2.60972 -0.303333 1.53611 + N0 0.215359 -0.970454 0.108813 N1 0.627607 -0.733748 -0.260237 N2 0.705424 -0.704198 -0.0805066 + txt003 +STRI + V0 2.60972 -0.303333 1.53611 V1 2.5375 -0.34125 1.62187 V2 2.4037 -0.415278 1.34722 + N0 0.705424 -0.704198 -0.0805066 N1 0.214084 -0.960035 0.180281 N2 0.215359 -0.970454 0.108813 + txt003 +STRI + V0 2.4679 -0.369136 1.22016 V1 2.51728 -0.23071 1.12243 V2 2.66528 -0.189583 1.47014 + N0 0.627607 -0.733748 -0.260237 N1 0.813963 -0.348056 -0.465103 N2 0.913262 -0.329186 -0.239977 + txt003 +STRI + V0 2.66528 -0.189583 1.47014 V1 2.60972 -0.303333 1.53611 V2 2.4679 -0.369136 1.22016 + N0 0.913262 -0.329186 -0.239977 N1 0.705424 -0.704198 -0.0805066 N2 0.627607 -0.733748 -0.260237 + txt003 +STRI + V0 2.51728 -0.23071 1.12243 V1 2.53704 0 1.08333 V2 2.6875 0 1.44375 + N0 0.813963 -0.348056 -0.465103 N1 0.854063 9.88017e-16 -0.52017 N2 0.957826 1.83855e-15 -0.287348 + txt003 +STRI + V0 2.6875 0 1.44375 V1 2.66528 -0.189583 1.47014 V2 2.51728 -0.23071 1.12243 + N0 0.957826 1.83855e-15 -0.287348 N1 0.913262 -0.329186 -0.239977 N2 0.813963 -0.348056 -0.465103 + txt003 +STRI + V0 2.3875 0 1.8 V1 2.40972 -0.189583 1.77361 V2 2.48765 -0.148457 1.99928 + N0 -0.920582 0 0.39055 N1 -0.835237 -0.363942 0.412221 N2 -0.842821 -0.409176 0.34961 + txt003 +STRI + V0 2.48765 -0.148457 1.99928 V1 2.46296 0 2.01389 V2 2.3875 0 1.8 + N0 -0.842821 -0.409176 0.34961 N1 -0.948683 0 0.316228 N2 -0.920582 0 0.39055 + txt003 +STRI + V0 2.40972 -0.189583 1.77361 V1 2.46528 -0.303333 1.70764 V2 2.54938 -0.237531 1.96276 + N0 -0.835237 -0.363942 0.412221 N1 -0.451323 -0.803033 0.38916 N2 -0.452673 -0.821162 0.347535 + txt003 +STRI + V0 2.54938 -0.237531 1.96276 V1 2.48765 -0.148457 1.99928 V2 2.40972 -0.189583 1.77361 + N0 -0.452673 -0.821162 0.347535 N1 -0.842821 -0.409176 0.34961 N2 -0.835237 -0.363942 0.412221 + txt003 +STRI + V0 2.46528 -0.303333 1.70764 V1 2.5375 -0.34125 1.62187 V2 2.62963 -0.267222 1.91528 + N0 -0.451323 -0.803033 0.38916 N1 0.214084 -0.960035 0.180281 N2 0.113546 -0.974822 0.191909 + txt003 +STRI + V0 2.62963 -0.267222 1.91528 V1 2.54938 -0.237531 1.96276 V2 2.46528 -0.303333 1.70764 + N0 0.113546 -0.974822 0.191909 N1 -0.452673 -0.821162 0.347535 N2 -0.451323 -0.803033 0.38916 + txt003 +STRI + V0 2.5375 -0.34125 1.62187 V1 2.60972 -0.303333 1.53611 V2 2.70988 -0.237531 1.8678 + N0 0.214084 -0.960035 0.180281 N1 0.705424 -0.704198 -0.0805066 N2 0.60461 -0.794635 -0.0547983 + txt003 +STRI + V0 2.70988 -0.237531 1.8678 V1 2.62963 -0.267222 1.91528 V2 2.5375 -0.34125 1.62187 + N0 0.60461 -0.794635 -0.0547983 N1 0.113546 -0.974822 0.191909 N2 0.214084 -0.960035 0.180281 + txt003 +STRI + V0 2.60972 -0.303333 1.53611 V1 2.66528 -0.189583 1.47014 V2 2.7716 -0.148457 1.83128 + N0 0.705424 -0.704198 -0.0805066 N1 0.913262 -0.329186 -0.239977 N2 0.880144 -0.401503 -0.253261 + txt003 +STRI + V0 2.7716 -0.148457 1.83128 V1 2.70988 -0.237531 1.8678 V2 2.60972 -0.303333 1.53611 + N0 0.880144 -0.401503 -0.253261 N1 0.60461 -0.794635 -0.0547983 N2 0.705424 -0.704198 -0.0805066 + txt003 +STRI + V0 2.66528 -0.189583 1.47014 V1 2.6875 0 1.44375 V2 2.7963 0 1.81667 + N0 0.913262 -0.329186 -0.239977 N1 0.957826 1.83855e-15 -0.287348 N2 0.947588 3.02585e-15 -0.319493 + txt003 +STRI + V0 2.7963 0 1.81667 V1 2.7716 -0.148457 1.83128 V2 2.66528 -0.189583 1.47014 + N0 0.947588 3.02585e-15 -0.319493 N1 0.880144 -0.401503 -0.253261 N2 0.913262 -0.329186 -0.239977 + txt003 +STRI + V0 2.46296 0 2.01389 V1 2.48765 -0.148457 1.99928 V2 2.5804 -0.116821 2.21831 + N0 -0.948683 0 0.316228 N1 -0.842821 -0.409176 0.34961 N2 -0.723795 -0.498863 0.476715 + txt003 +STRI + V0 2.5804 -0.116821 2.21831 V1 2.54954 0 2.22361 V2 2.46296 0 2.01389 + N0 -0.723795 -0.498863 0.476715 N1 -0.874591 0 0.484861 N2 -0.948683 0 0.316228 + txt003 +STRI + V0 2.48765 -0.148457 1.99928 V1 2.54938 -0.237531 1.96276 V2 2.65756 -0.186914 2.20507 + N0 -0.842821 -0.409176 0.34961 N1 -0.452673 -0.821162 0.347535 N2 -0.365378 -0.851743 0.375544 + txt003 +STRI + V0 2.65756 -0.186914 2.20507 V1 2.5804 -0.116821 2.21831 V2 2.48765 -0.148457 1.99928 + N0 -0.365378 -0.851743 0.375544 N1 -0.723795 -0.498863 0.476715 N2 -0.842821 -0.409176 0.34961 + txt003 +STRI + V0 2.54938 -0.237531 1.96276 V1 2.62963 -0.267222 1.91528 V2 2.75787 -0.210278 2.18785 + N0 -0.452673 -0.821162 0.347535 N1 0.113546 -0.974822 0.191909 N2 0.0260102 -0.988113 0.151516 + txt003 +STRI + V0 2.75787 -0.210278 2.18785 V1 2.65756 -0.186914 2.20507 V2 2.54938 -0.237531 1.96276 + N0 0.0260102 -0.988113 0.151516 N1 -0.365378 -0.851743 0.375544 N2 -0.452673 -0.821162 0.347535 + txt003 +STRI + V0 2.62963 -0.267222 1.91528 V1 2.70988 -0.237531 1.8678 V2 2.85818 -0.186914 2.17063 + N0 0.113546 -0.974822 0.191909 N1 0.60461 -0.794635 -0.0547983 N2 0.417243 -0.88974 -0.185122 + txt003 +STRI + V0 2.85818 -0.186914 2.17063 V1 2.75787 -0.210278 2.18785 V2 2.62963 -0.267222 1.91528 + N0 0.417243 -0.88974 -0.185122 N1 0.0260102 -0.988113 0.151516 N2 0.113546 -0.974822 0.191909 + txt003 +STRI + V0 2.70988 -0.237531 1.8678 V1 2.7716 -0.148457 1.83128 V2 2.93534 -0.116821 2.15738 + N0 0.60461 -0.794635 -0.0547983 N1 0.880144 -0.401503 -0.253261 N2 0.70819 -0.492319 -0.506053 + txt003 +STRI + V0 2.93534 -0.116821 2.15738 V1 2.85818 -0.186914 2.17063 V2 2.70988 -0.237531 1.8678 + N0 0.70819 -0.492319 -0.506053 N1 0.417243 -0.88974 -0.185122 N2 0.60461 -0.794635 -0.0547983 + txt003 +STRI + V0 2.7716 -0.148457 1.83128 V1 2.7963 0 1.81667 V2 2.9662 0 2.15208 + N0 0.880144 -0.401503 -0.253261 N1 0.947588 3.02585e-15 -0.319493 N2 0.787582 4.30265e-15 -0.61621 + txt003 +STRI + V0 2.9662 0 2.15208 V1 2.93534 -0.116821 2.15738 V2 2.7716 -0.148457 1.83128 + N0 0.787582 4.30265e-15 -0.61621 N1 0.70819 -0.492319 -0.506053 N2 0.880144 -0.401503 -0.253261 + txt003 +STRI + V0 2.54954 0 2.22361 V1 2.5804 -0.116821 2.21831 V2 2.74444 -0.104167 2.4 + N0 -0.874591 0 0.484861 N1 -0.723795 -0.498863 0.476715 N2 -0.497164 -0.497164 0.711095 + txt003 +STRI + V0 2.74444 -0.104167 2.4 V1 2.7 0 2.4 V2 2.54954 0 2.22361 + N0 -0.497164 -0.497164 0.711095 N1 -0.6 0 0.8 N2 -0.874591 0 0.484861 + txt003 +STRI + V0 2.5804 -0.116821 2.21831 V1 2.65756 -0.186914 2.20507 V2 2.85556 -0.166667 2.4 + N0 -0.723795 -0.498863 0.476715 N1 -0.365378 -0.851743 0.375544 N2 -0.267368 -0.855576 0.443288 + txt003 +STRI + V0 2.85556 -0.166667 2.4 V1 2.74444 -0.104167 2.4 V2 2.5804 -0.116821 2.21831 + N0 -0.267368 -0.855576 0.443288 N1 -0.497164 -0.497164 0.711095 N2 -0.723795 -0.498863 0.476715 + txt003 +STRI + V0 2.65756 -0.186914 2.20507 V1 2.75787 -0.210278 2.18785 V2 3 -0.1875 2.4 + N0 -0.365378 -0.851743 0.375544 N1 0.0260102 -0.988113 0.151516 N2 0 -1 2.19303e-16 + txt003 +STRI + V0 3 -0.1875 2.4 V1 2.85556 -0.166667 2.4 V2 2.65756 -0.186914 2.20507 + N0 0 -1 2.19303e-16 N1 -0.267368 -0.855576 0.443288 N2 -0.365378 -0.851743 0.375544 + txt003 +STRI + V0 2.75787 -0.210278 2.18785 V1 2.85818 -0.186914 2.17063 V2 3.14444 -0.166667 2.4 + N0 0.0260102 -0.988113 0.151516 N1 0.417243 -0.88974 -0.185122 N2 0.250514 -0.801644 -0.54278 + txt003 +STRI + V0 3.14444 -0.166667 2.4 V1 3 -0.1875 2.4 V2 2.75787 -0.210278 2.18785 + N0 0.250514 -0.801644 -0.54278 N1 0 -1 2.19303e-16 N2 0.0260102 -0.988113 0.151516 + txt003 +STRI + V0 2.85818 -0.186914 2.17063 V1 2.93534 -0.116821 2.15738 V2 3.25556 -0.104167 2.4 + N0 0.417243 -0.88974 -0.185122 N1 0.70819 -0.492319 -0.506053 N2 0.366221 -0.366221 -0.855433 + txt003 +STRI + V0 3.25556 -0.104167 2.4 V1 3.14444 -0.166667 2.4 V2 2.85818 -0.186914 2.17063 + N0 0.366221 -0.366221 -0.855433 N1 0.250514 -0.801644 -0.54278 N2 0.417243 -0.88974 -0.185122 + txt003 +STRI + V0 2.93534 -0.116821 2.15738 V1 2.9662 0 2.15208 V2 3.3 0 2.4 + N0 0.70819 -0.492319 -0.506053 N1 0.787582 4.30265e-15 -0.61621 N2 0.384615 6.46776e-15 -0.923077 + txt003 +STRI + V0 3.3 0 2.4 V1 3.25556 -0.104167 2.4 V2 2.93534 -0.116821 2.15738 + N0 0.384615 6.46776e-15 -0.923077 N1 0.366221 -0.366221 -0.855433 N2 0.70819 -0.492319 -0.506053 + txt003 +STRI + V0 1.7 0 0.6 V1 1.7 0.275 0.661111 V2 2.22855 0.262346 0.8366 + N0 0.158678 0 -0.98733 N1 0.134339 0.457747 -0.878875 N2 0.492146 0.41068 -0.767551 + txt003 +STRI + V0 2.22855 0.262346 0.8366 V1 2.24213 0 0.785417 V2 1.7 0 0.6 + N0 0.492146 0.41068 -0.767551 N1 0.528678 0 -0.848822 N2 0.158678 0 -0.98733 + txt003 +STRI + V0 1.7 0.275 0.661111 V1 1.7 0.44 0.813889 V2 2.1946 0.419753 0.964558 + N0 0.134339 0.457747 -0.878875 N1 0.0673462 0.855546 -0.513328 N2 0.348602 0.814337 -0.464038 + txt003 +STRI + V0 2.1946 0.419753 0.964558 V1 2.22855 0.262346 0.8366 V2 1.7 0.275 0.661111 + N0 0.348602 0.814337 -0.464038 N1 0.492146 0.41068 -0.767551 N2 0.134339 0.457747 -0.878875 + txt003 +STRI + V0 1.7 0.44 0.813889 V1 1.7 0.495 1.0125 V2 2.15046 0.472222 1.1309 + N0 0.0673462 0.855546 -0.513328 N1 0 1 -0 N2 0.110195 0.99348 0.0292376 + txt003 +STRI + V0 2.15046 0.472222 1.1309 V1 2.1946 0.419753 0.964558 V2 1.7 0.44 0.813889 + N0 0.110195 0.99348 0.0292376 N1 0.348602 0.814337 -0.464038 N2 0.0673462 0.855546 -0.513328 + txt003 +STRI + V0 1.7 0.495 1.0125 V1 1.7 0.44 1.21111 V2 2.10633 0.419753 1.29725 + N0 0 1 -0 N1 -0.0291362 0.857129 0.514277 N2 -0.135104 0.834377 0.534381 + txt003 +STRI + V0 2.10633 0.419753 1.29725 V1 2.15046 0.472222 1.1309 V2 1.7 0.495 1.0125 + N0 -0.135104 0.834377 0.534381 N1 0.110195 0.99348 0.0292376 N2 0 1 -0 + txt003 +STRI + V0 1.7 0.44 1.21111 V1 1.7 0.275 1.36389 V2 2.07238 0.262346 1.42521 + N0 -0.0291362 0.857129 0.514277 N1 -0.0157732 0.461877 0.886804 N2 -0.291732 0.426807 0.855995 + txt003 +STRI + V0 2.07238 0.262346 1.42521 V1 2.10633 0.419753 1.29725 V2 1.7 0.44 1.21111 + N0 -0.291732 0.426807 0.855995 N1 -0.135104 0.834377 0.534381 N2 -0.0291362 0.857129 0.514277 + txt003 +STRI + V0 1.7 0.275 1.36389 V1 1.7 0 1.425 V2 2.0588 0 1.47639 + N0 -0.0157732 0.461877 0.886804 N1 0 -4.48575e-16 1 N2 -0.333935 -3.25455e-16 0.942596 + txt003 +STRI + V0 2.0588 0 1.47639 V1 2.07238 0.262346 1.42521 V2 1.7 0.275 1.36389 + N0 -0.333935 -3.25455e-16 0.942596 N1 -0.291732 0.426807 0.855995 N2 -0.0157732 0.461877 0.886804 + txt003 +STRI + V0 2.24213 0 0.785417 V1 2.22855 0.262346 0.8366 V2 2.51728 0.23071 1.12243 + N0 0.528678 0 -0.848822 N1 0.492146 0.41068 -0.767551 N2 0.813963 0.348056 -0.465103 + txt003 +STRI + V0 2.51728 0.23071 1.12243 V1 2.53704 0 1.08333 V2 2.24213 0 0.785417 + N0 0.813963 0.348056 -0.465103 N1 0.854063 0 -0.52017 N2 0.528678 0 -0.848822 + txt003 +STRI + V0 2.22855 0.262346 0.8366 V1 2.1946 0.419753 0.964558 V2 2.4679 0.369136 1.22016 + N0 0.492146 0.41068 -0.767551 N1 0.348602 0.814337 -0.464038 N2 0.627607 0.733748 -0.260237 + txt003 +STRI + V0 2.4679 0.369136 1.22016 V1 2.51728 0.23071 1.12243 V2 2.22855 0.262346 0.8366 + N0 0.627607 0.733748 -0.260237 N1 0.813963 0.348056 -0.465103 N2 0.492146 0.41068 -0.767551 + txt003 +STRI + V0 2.1946 0.419753 0.964558 V1 2.15046 0.472222 1.1309 V2 2.4037 0.415278 1.34722 + N0 0.348602 0.814337 -0.464038 N1 0.110195 0.99348 0.0292376 N2 0.215359 0.970454 0.108813 + txt003 +STRI + V0 2.4037 0.415278 1.34722 V1 2.4679 0.369136 1.22016 V2 2.1946 0.419753 0.964558 + N0 0.215359 0.970454 0.108813 N1 0.627607 0.733748 -0.260237 N2 0.348602 0.814337 -0.464038 + txt003 +STRI + V0 2.15046 0.472222 1.1309 V1 2.10633 0.419753 1.29725 V2 2.33951 0.369136 1.47428 + N0 0.110195 0.99348 0.0292376 N1 -0.135104 0.834377 0.534381 N2 -0.312511 0.816863 0.484842 + txt003 +STRI + V0 2.33951 0.369136 1.47428 V1 2.4037 0.415278 1.34722 V2 2.15046 0.472222 1.1309 + N0 -0.312511 0.816863 0.484842 N1 0.215359 0.970454 0.108813 N2 0.110195 0.99348 0.0292376 + txt003 +STRI + V0 2.10633 0.419753 1.29725 V1 2.07238 0.262346 1.42521 V2 2.29012 0.23071 1.57202 + N0 -0.135104 0.834377 0.534381 N1 -0.291732 0.426807 0.855995 N2 -0.64585 0.390219 0.656206 + txt003 +STRI + V0 2.29012 0.23071 1.57202 V1 2.33951 0.369136 1.47428 V2 2.10633 0.419753 1.29725 + N0 -0.64585 0.390219 0.656206 N1 -0.312511 0.816863 0.484842 N2 -0.135104 0.834377 0.534381 + txt003 +STRI + V0 2.07238 0.262346 1.42521 V1 2.0588 0 1.47639 V2 2.27037 0 1.61111 + N0 -0.291732 0.426807 0.855995 N1 -0.333935 -3.25455e-16 0.942596 N2 -0.731055 -1.69385e-16 0.682318 + txt003 +STRI + V0 2.27037 0 1.61111 V1 2.29012 0.23071 1.57202 V2 2.07238 0.262346 1.42521 + N0 -0.731055 -1.69385e-16 0.682318 N1 -0.64585 0.390219 0.656206 N2 -0.291732 0.426807 0.855995 + txt003 +STRI + V0 2.53704 0 1.08333 V1 2.51728 0.23071 1.12243 V2 2.66528 0.189583 1.47014 + N0 0.854063 0 -0.52017 N1 0.813963 0.348056 -0.465103 N2 0.913262 0.329186 -0.239977 + txt003 +STRI + V0 2.66528 0.189583 1.47014 V1 2.6875 0 1.44375 V2 2.53704 0 1.08333 + N0 0.913262 0.329186 -0.239977 N1 0.957826 0 -0.287348 N2 0.854063 0 -0.52017 + txt003 +STRI + V0 2.51728 0.23071 1.12243 V1 2.4679 0.369136 1.22016 V2 2.60972 0.303333 1.53611 + N0 0.813963 0.348056 -0.465103 N1 0.627607 0.733748 -0.260237 N2 0.705424 0.704198 -0.0805066 + txt003 +STRI + V0 2.60972 0.303333 1.53611 V1 2.66528 0.189583 1.47014 V2 2.51728 0.23071 1.12243 + N0 0.705424 0.704198 -0.0805066 N1 0.913262 0.329186 -0.239977 N2 0.813963 0.348056 -0.465103 + txt003 +STRI + V0 2.4679 0.369136 1.22016 V1 2.4037 0.415278 1.34722 V2 2.5375 0.34125 1.62188 + N0 0.627607 0.733748 -0.260237 N1 0.215359 0.970454 0.108813 N2 0.214084 0.960035 0.180281 + txt003 +STRI + V0 2.5375 0.34125 1.62188 V1 2.60972 0.303333 1.53611 V2 2.4679 0.369136 1.22016 + N0 0.214084 0.960035 0.180281 N1 0.705424 0.704198 -0.0805066 N2 0.627607 0.733748 -0.260237 + txt003 +STRI + V0 2.4037 0.415278 1.34722 V1 2.33951 0.369136 1.47428 V2 2.46528 0.303333 1.70764 + N0 0.215359 0.970454 0.108813 N1 -0.312511 0.816863 0.484842 N2 -0.451323 0.803033 0.38916 + txt003 +STRI + V0 2.46528 0.303333 1.70764 V1 2.5375 0.34125 1.62188 V2 2.4037 0.415278 1.34722 + N0 -0.451323 0.803033 0.38916 N1 0.214084 0.960035 0.180281 N2 0.215359 0.970454 0.108813 + txt003 +STRI + V0 2.33951 0.369136 1.47428 V1 2.29012 0.23071 1.57202 V2 2.40972 0.189583 1.77361 + N0 -0.312511 0.816863 0.484842 N1 -0.64585 0.390219 0.656206 N2 -0.835237 0.363942 0.412221 + txt003 +STRI + V0 2.40972 0.189583 1.77361 V1 2.46528 0.303333 1.70764 V2 2.33951 0.369136 1.47428 + N0 -0.835237 0.363942 0.412221 N1 -0.451323 0.803033 0.38916 N2 -0.312511 0.816863 0.484842 + txt003 +STRI + V0 2.29012 0.23071 1.57202 V1 2.27037 0 1.61111 V2 2.3875 0 1.8 + N0 -0.64585 0.390219 0.656206 N1 -0.731055 -1.69385e-16 0.682318 N2 -0.920582 -2.76813e-16 0.39055 + txt003 +STRI + V0 2.3875 0 1.8 V1 2.40972 0.189583 1.77361 V2 2.29012 0.23071 1.57202 + N0 -0.920582 -2.76813e-16 0.39055 N1 -0.835237 0.363942 0.412221 N2 -0.64585 0.390219 0.656206 + txt003 +STRI + V0 2.6875 0 1.44375 V1 2.66528 0.189583 1.47014 V2 2.7716 0.148457 1.83128 + N0 0.957826 0 -0.287348 N1 0.913262 0.329186 -0.239977 N2 0.880144 0.401503 -0.253261 + txt003 +STRI + V0 2.7716 0.148457 1.83128 V1 2.7963 0 1.81667 V2 2.6875 0 1.44375 + N0 0.880144 0.401503 -0.253261 N1 0.947588 0 -0.319493 N2 0.957826 0 -0.287348 + txt003 +STRI + V0 2.66528 0.189583 1.47014 V1 2.60972 0.303333 1.53611 V2 2.70988 0.237531 1.8678 + N0 0.913262 0.329186 -0.239977 N1 0.705424 0.704198 -0.0805066 N2 0.60461 0.794635 -0.0547983 + txt003 +STRI + V0 2.70988 0.237531 1.8678 V1 2.7716 0.148457 1.83128 V2 2.66528 0.189583 1.47014 + N0 0.60461 0.794635 -0.0547983 N1 0.880144 0.401503 -0.253261 N2 0.913262 0.329186 -0.239977 + txt003 +STRI + V0 2.60972 0.303333 1.53611 V1 2.5375 0.34125 1.62188 V2 2.62963 0.267222 1.91528 + N0 0.705424 0.704198 -0.0805066 N1 0.214084 0.960035 0.180281 N2 0.113546 0.974822 0.191909 + txt003 +STRI + V0 2.62963 0.267222 1.91528 V1 2.70988 0.237531 1.8678 V2 2.60972 0.303333 1.53611 + N0 0.113546 0.974822 0.191909 N1 0.60461 0.794635 -0.0547983 N2 0.705424 0.704198 -0.0805066 + txt003 +STRI + V0 2.5375 0.34125 1.62188 V1 2.46528 0.303333 1.70764 V2 2.54938 0.237531 1.96276 + N0 0.214084 0.960035 0.180281 N1 -0.451323 0.803033 0.38916 N2 -0.452673 0.821162 0.347535 + txt003 +STRI + V0 2.54938 0.237531 1.96276 V1 2.62963 0.267222 1.91528 V2 2.5375 0.34125 1.62188 + N0 -0.452673 0.821162 0.347535 N1 0.113546 0.974822 0.191909 N2 0.214084 0.960035 0.180281 + txt003 +STRI + V0 2.46528 0.303333 1.70764 V1 2.40972 0.189583 1.77361 V2 2.48765 0.148457 1.99928 + N0 -0.451323 0.803033 0.38916 N1 -0.835237 0.363942 0.412221 N2 -0.842821 0.409176 0.34961 + txt003 +STRI + V0 2.48765 0.148457 1.99928 V1 2.54938 0.237531 1.96276 V2 2.46528 0.303333 1.70764 + N0 -0.842821 0.409176 0.34961 N1 -0.452673 0.821162 0.347535 N2 -0.451323 0.803033 0.38916 + txt003 +STRI + V0 2.40972 0.189583 1.77361 V1 2.3875 0 1.8 V2 2.46296 0 2.01389 + N0 -0.835237 0.363942 0.412221 N1 -0.920582 -2.76813e-16 0.39055 N2 -0.948683 -4.59839e-16 0.316228 + txt003 +STRI + V0 2.46296 0 2.01389 V1 2.48765 0.148457 1.99928 V2 2.40972 0.189583 1.77361 + N0 -0.948683 -4.59839e-16 0.316228 N1 -0.842821 0.409176 0.34961 N2 -0.835237 0.363942 0.412221 + txt003 +STRI + V0 2.7963 0 1.81667 V1 2.7716 0.148457 1.83128 V2 2.93534 0.116821 2.15738 + N0 0.947588 0 -0.319493 N1 0.880144 0.401503 -0.253261 N2 0.70819 0.492319 -0.506053 + txt003 +STRI + V0 2.93534 0.116821 2.15738 V1 2.9662 0 2.15208 V2 2.7963 0 1.81667 + N0 0.70819 0.492319 -0.506053 N1 0.787582 0 -0.61621 N2 0.947588 0 -0.319493 + txt003 +STRI + V0 2.7716 0.148457 1.83128 V1 2.70988 0.237531 1.8678 V2 2.85818 0.186914 2.17063 + N0 0.880144 0.401503 -0.253261 N1 0.60461 0.794635 -0.0547983 N2 0.417243 0.88974 -0.185122 + txt003 +STRI + V0 2.85818 0.186914 2.17063 V1 2.93534 0.116821 2.15738 V2 2.7716 0.148457 1.83128 + N0 0.417243 0.88974 -0.185122 N1 0.70819 0.492319 -0.506053 N2 0.880144 0.401503 -0.253261 + txt003 +STRI + V0 2.70988 0.237531 1.8678 V1 2.62963 0.267222 1.91528 V2 2.75787 0.210278 2.18785 + N0 0.60461 0.794635 -0.0547983 N1 0.113546 0.974822 0.191909 N2 0.0260102 0.988113 0.151516 + txt003 +STRI + V0 2.75787 0.210278 2.18785 V1 2.85818 0.186914 2.17063 V2 2.70988 0.237531 1.8678 + N0 0.0260102 0.988113 0.151516 N1 0.417243 0.88974 -0.185122 N2 0.60461 0.794635 -0.0547983 + txt003 +STRI + V0 2.62963 0.267222 1.91528 V1 2.54938 0.237531 1.96276 V2 2.65756 0.186914 2.20507 + N0 0.113546 0.974822 0.191909 N1 -0.452673 0.821162 0.347535 N2 -0.365378 0.851743 0.375544 + txt003 +STRI + V0 2.65756 0.186914 2.20507 V1 2.75787 0.210278 2.18785 V2 2.62963 0.267222 1.91528 + N0 -0.365378 0.851743 0.375544 N1 0.0260102 0.988113 0.151516 N2 0.113546 0.974822 0.191909 + txt003 +STRI + V0 2.54938 0.237531 1.96276 V1 2.48765 0.148457 1.99928 V2 2.5804 0.116821 2.21831 + N0 -0.452673 0.821162 0.347535 N1 -0.842821 0.409176 0.34961 N2 -0.723795 0.498863 0.476715 + txt003 +STRI + V0 2.5804 0.116821 2.21831 V1 2.65756 0.186914 2.20507 V2 2.54938 0.237531 1.96276 + N0 -0.723795 0.498863 0.476715 N1 -0.365378 0.851743 0.375544 N2 -0.452673 0.821162 0.347535 + txt003 +STRI + V0 2.48765 0.148457 1.99928 V1 2.46296 0 2.01389 V2 2.54954 0 2.22361 + N0 -0.842821 0.409176 0.34961 N1 -0.948683 -4.59839e-16 0.316228 N2 -0.874591 -1.30753e-15 0.484861 + txt003 +STRI + V0 2.54954 0 2.22361 V1 2.5804 0.116821 2.21831 V2 2.48765 0.148457 1.99928 + N0 -0.874591 -1.30753e-15 0.484861 N1 -0.723795 0.498863 0.476715 N2 -0.842821 0.409176 0.34961 + txt003 +STRI + V0 2.9662 0 2.15208 V1 2.93534 0.116821 2.15738 V2 3.25556 0.104167 2.4 + N0 0.787582 0 -0.61621 N1 0.70819 0.492319 -0.506053 N2 0.366221 0.366221 -0.855433 + txt003 +STRI + V0 3.25556 0.104167 2.4 V1 3.3 0 2.4 V2 2.9662 0 2.15208 + N0 0.366221 0.366221 -0.855433 N1 0.384615 0 -0.923077 N2 0.787582 0 -0.61621 + txt003 +STRI + V0 2.93534 0.116821 2.15738 V1 2.85818 0.186914 2.17063 V2 3.14444 0.166667 2.4 + N0 0.70819 0.492319 -0.506053 N1 0.417243 0.88974 -0.185122 N2 0.250514 0.801644 -0.54278 + txt003 +STRI + V0 3.14444 0.166667 2.4 V1 3.25556 0.104167 2.4 V2 2.93534 0.116821 2.15738 + N0 0.250514 0.801644 -0.54278 N1 0.366221 0.366221 -0.855433 N2 0.70819 0.492319 -0.506053 + txt003 +STRI + V0 2.85818 0.186914 2.17063 V1 2.75787 0.210278 2.18785 V2 3 0.1875 2.4 + N0 0.417243 0.88974 -0.185122 N1 0.0260102 0.988113 0.151516 N2 4.05793e-32 1 2.19303e-16 + txt003 +STRI + V0 3 0.1875 2.4 V1 3.14444 0.166667 2.4 V2 2.85818 0.186914 2.17063 + N0 4.05793e-32 1 2.19303e-16 N1 0.250514 0.801644 -0.54278 N2 0.417243 0.88974 -0.185122 + txt003 +STRI + V0 2.75787 0.210278 2.18785 V1 2.65756 0.186914 2.20507 V2 2.85556 0.166667 2.4 + N0 0.0260102 0.988113 0.151516 N1 -0.365378 0.851743 0.375544 N2 -0.267368 0.855576 0.443288 + txt003 +STRI + V0 2.85556 0.166667 2.4 V1 3 0.1875 2.4 V2 2.75787 0.210278 2.18785 + N0 -0.267368 0.855576 0.443288 N1 4.05793e-32 1 2.19303e-16 N2 0.0260102 0.988113 0.151516 + txt003 +STRI + V0 2.65756 0.186914 2.20507 V1 2.5804 0.116821 2.21831 V2 2.74444 0.104167 2.4 + N0 -0.365378 0.851743 0.375544 N1 -0.723795 0.498863 0.476715 N2 -0.497164 0.497164 0.711095 + txt003 +STRI + V0 2.74444 0.104167 2.4 V1 2.85556 0.166667 2.4 V2 2.65756 0.186914 2.20507 + N0 -0.497164 0.497164 0.711095 N1 -0.267368 0.855576 0.443288 N2 -0.365378 0.851743 0.375544 + txt003 +STRI + V0 2.5804 0.116821 2.21831 V1 2.54954 0 2.22361 V2 2.7 0 2.4 + N0 -0.723795 0.498863 0.476715 N1 -0.874591 -1.30753e-15 0.484861 N2 -0.6 -3.55271e-15 0.8 + txt003 +STRI + V0 2.7 0 2.4 V1 2.74444 0.104167 2.4 V2 2.5804 0.116821 2.21831 + N0 -0.6 -3.55271e-15 0.8 N1 -0.497164 0.497164 0.711095 N2 -0.723795 0.498863 0.476715 + txt003 +STRI + V0 2.7 0 2.4 V1 2.74444 -0.104167 2.4 V2 2.79641 -0.10108 2.43193 + N0 -0.6 0 0.8 N1 -0.497164 -0.497164 0.711095 N2 -0.387052 -0.411886 0.824949 + txt003 +STRI + V0 2.79641 -0.10108 2.43193 V1 2.74907 0 2.43125 V2 2.7 0 2.4 + N0 -0.387052 -0.411886 0.824949 N1 -0.467888 0 0.883788 N2 -0.6 0 0.8 + txt003 +STRI + V0 2.74444 -0.104167 2.4 V1 2.85556 -0.166667 2.4 V2 2.91474 -0.161728 2.43361 + N0 -0.497164 -0.497164 0.711095 N1 -0.267368 -0.855576 0.443288 N2 -0.215548 -0.724209 0.655027 + txt003 +STRI + V0 2.91474 -0.161728 2.43361 V1 2.79641 -0.10108 2.43193 V2 2.74444 -0.104167 2.4 + N0 -0.215548 -0.724209 0.655027 N1 -0.387052 -0.411886 0.824949 N2 -0.497164 -0.497164 0.711095 + txt003 +STRI + V0 2.85556 -0.166667 2.4 V1 3 -0.1875 2.4 V2 3.06858 -0.181944 2.43581 + N0 -0.267368 -0.855576 0.443288 N1 0 -1 0 N2 -0.00489618 -0.939227 0.343261 + txt003 +STRI + V0 3.06858 -0.181944 2.43581 V1 2.91474 -0.161728 2.43361 V2 2.85556 -0.166667 2.4 + N0 -0.00489618 -0.939227 0.343261 N1 -0.215548 -0.724209 0.655027 N2 -0.267368 -0.855576 0.443288 + txt003 +STRI + V0 3 -0.1875 2.4 V1 3.14444 -0.166667 2.4 V2 3.22241 -0.161728 2.438 + N0 0 -1 0 N1 0.250514 -0.801644 -0.54278 N2 0.269127 -0.933284 -0.237808 + txt003 +STRI + V0 3.22241 -0.161728 2.438 V1 3.06858 -0.181944 2.43581 V2 3 -0.1875 2.4 + N0 0.269127 -0.933284 -0.237808 N1 -0.00489618 -0.939227 0.343261 N2 0 -1 0 + txt003 +STRI + V0 3.14444 -0.166667 2.4 V1 3.25556 -0.104167 2.4 V2 3.34075 -0.10108 2.43969 + N0 0.250514 -0.801644 -0.54278 N1 0.366221 -0.366221 -0.855433 N2 0.442187 -0.473386 -0.761824 + txt003 +STRI + V0 3.34075 -0.10108 2.43969 V1 3.22241 -0.161728 2.438 V2 3.14444 -0.166667 2.4 + N0 0.442187 -0.473386 -0.761824 N1 0.269127 -0.933284 -0.237808 N2 0.250514 -0.801644 -0.54278 + txt003 +STRI + V0 3.25556 -0.104167 2.4 V1 3.3 0 2.4 V2 3.38808 0 2.44036 + N0 0.366221 -0.366221 -0.855433 N1 0.384615 -2.55067e-15 -0.923077 N2 0.463425 -2.75328e-15 -0.886136 + txt003 +STRI + V0 3.38808 0 2.44036 V1 3.34075 -0.10108 2.43969 V2 3.25556 -0.104167 2.4 + N0 0.463425 -2.75328e-15 -0.886136 N1 0.442187 -0.473386 -0.761824 N2 0.366221 -0.366221 -0.855433 + txt003 +STRI + V0 2.74907 0 2.43125 V1 2.79641 -0.10108 2.43193 V2 2.83978 -0.0933642 2.45123 + N0 -0.467888 0 0.883788 N1 -0.387052 -0.411886 0.824949 N2 -0.253997 -0.272114 0.928138 + txt003 +STRI + V0 2.83978 -0.0933642 2.45123 V1 2.79259 0 2.45 V2 2.74907 0 2.43125 + N0 -0.253997 -0.272114 0.928138 N1 -0.306009 0 0.952029 N2 -0.467888 0 0.883788 + txt003 +STRI + V0 2.79641 -0.10108 2.43193 V1 2.91474 -0.161728 2.43361 V2 2.95775 -0.149383 2.45432 + N0 -0.387052 -0.411886 0.824949 N1 -0.215548 -0.724209 0.655027 N2 -0.14959 -0.481391 0.863647 + txt003 +STRI + V0 2.95775 -0.149383 2.45432 V1 2.83978 -0.0933642 2.45123 V2 2.79641 -0.10108 2.43193 + N0 -0.14959 -0.481391 0.863647 N1 -0.253997 -0.272114 0.928138 N2 -0.387052 -0.411886 0.824949 + txt003 +STRI + V0 2.91474 -0.161728 2.43361 V1 3.06858 -0.181944 2.43581 V2 3.11111 -0.168056 2.45833 + N0 -0.215548 -0.724209 0.655027 N1 -0.00489618 -0.939227 0.343261 N2 -0.0195232 -0.665415 0.746219 + txt003 +STRI + V0 3.11111 -0.168056 2.45833 V1 2.95775 -0.149383 2.45432 V2 2.91474 -0.161728 2.43361 + N0 -0.0195232 -0.665415 0.746219 N1 -0.14959 -0.481391 0.863647 N2 -0.215548 -0.724209 0.655027 + txt003 +STRI + V0 3.06858 -0.181944 2.43581 V1 3.22241 -0.161728 2.438 V2 3.26447 -0.149383 2.46235 + N0 -0.00489618 -0.939227 0.343261 N1 0.269127 -0.933284 -0.237808 N2 0.218115 -0.87054 0.44112 + txt003 +STRI + V0 3.26447 -0.149383 2.46235 V1 3.11111 -0.168056 2.45833 V2 3.06858 -0.181944 2.43581 + N0 0.218115 -0.87054 0.44112 N1 -0.0195232 -0.665415 0.746219 N2 -0.00489618 -0.939227 0.343261 + txt003 +STRI + V0 3.22241 -0.161728 2.438 V1 3.34075 -0.10108 2.43969 V2 3.38244 -0.0933642 2.46543 + N0 0.269127 -0.933284 -0.237808 N1 0.442187 -0.473386 -0.761824 N2 0.612385 -0.714958 -0.337372 + txt003 +STRI + V0 3.38244 -0.0933642 2.46543 V1 3.26447 -0.149383 2.46235 V2 3.22241 -0.161728 2.438 + N0 0.612385 -0.714958 -0.337372 N1 0.218115 -0.87054 0.44112 N2 0.269127 -0.933284 -0.237808 + txt003 +STRI + V0 3.34075 -0.10108 2.43969 V1 3.38808 0 2.44036 V2 3.42963 0 2.46667 + N0 0.442187 -0.473386 -0.761824 N1 0.463425 -2.75328e-15 -0.886136 N2 0.694136 -3.24605e-15 -0.719844 + txt003 +STRI + V0 3.42963 0 2.46667 V1 3.38244 -0.0933642 2.46543 V2 3.34075 -0.10108 2.43969 + N0 0.694136 -3.24605e-15 -0.719844 N1 0.612385 -0.714958 -0.337372 N2 0.442187 -0.473386 -0.761824 + txt003 +STRI + V0 2.79259 0 2.45 V1 2.83978 -0.0933642 2.45123 V2 2.86968 -0.0833333 2.45781 + N0 -0.306009 0 0.952029 N1 -0.253997 -0.272114 0.928138 N2 -0.0182321 0.0210195 0.999613 + txt003 +STRI + V0 2.86968 -0.0833333 2.45781 V1 2.825 0 2.45625 V2 2.79259 0 2.45 + N0 -0.0182321 0.0210195 0.999613 N1 2.22045e-15 0 1 N2 -0.306009 0 0.952029 + txt003 +STRI + V0 2.83978 -0.0933642 2.45123 V1 2.95775 -0.149383 2.45432 V2 2.98137 -0.133333 2.46172 + N0 -0.253997 -0.272114 0.928138 N1 -0.14959 -0.481391 0.863647 N2 -0.0369301 -0.00796532 0.999286 + txt003 +STRI + V0 2.98137 -0.133333 2.46172 V1 2.86968 -0.0833333 2.45781 V2 2.83978 -0.0933642 2.45123 + N0 -0.0369301 -0.00796532 0.999286 N1 -0.0182321 0.0210195 0.999613 N2 -0.253997 -0.272114 0.928138 + txt003 +STRI + V0 2.95775 -0.149383 2.45432 V1 3.11111 -0.168056 2.45833 V2 3.12656 -0.15 2.4668 + N0 -0.14959 -0.481391 0.863647 N1 -0.0195232 -0.665415 0.746219 N2 -0.0348909 -0.0594438 0.997622 + txt003 +STRI + V0 3.12656 -0.15 2.4668 V1 2.98137 -0.133333 2.46172 V2 2.95775 -0.149383 2.45432 + N0 -0.0348909 -0.0594438 0.997622 N1 -0.0369301 -0.00796532 0.999286 N2 -0.14959 -0.481391 0.863647 + txt003 +STRI + V0 3.11111 -0.168056 2.45833 V1 3.26447 -0.149383 2.46235 V2 3.27176 -0.133333 2.47187 + N0 -0.0195232 -0.665415 0.746219 N1 0.218115 -0.87054 0.44112 N2 -0.00787186 -0.108144 0.994104 + txt003 +STRI + V0 3.27176 -0.133333 2.47187 V1 3.12656 -0.15 2.4668 V2 3.11111 -0.168056 2.45833 + N0 -0.00787186 -0.108144 0.994104 N1 -0.0348909 -0.0594438 0.997622 N2 -0.0195232 -0.665415 0.746219 + txt003 +STRI + V0 3.26447 -0.149383 2.46235 V1 3.38244 -0.0933642 2.46543 V2 3.38345 -0.0833333 2.47578 + N0 0.218115 -0.87054 0.44112 N1 0.612385 -0.714958 -0.337372 N2 0.0539577 -0.111406 0.992309 + txt003 +STRI + V0 3.38345 -0.0833333 2.47578 V1 3.27176 -0.133333 2.47187 V2 3.26447 -0.149383 2.46235 + N0 0.0539577 -0.111406 0.992309 N1 -0.00787186 -0.108144 0.994104 N2 0.218115 -0.87054 0.44112 + txt003 +STRI + V0 3.38244 -0.0933642 2.46543 V1 3.42963 0 2.46667 V2 3.42813 0 2.47734 + N0 0.612385 -0.714958 -0.337372 N1 0.694136 -3.24605e-15 -0.719844 N2 0.106533 1.89241e-15 0.994309 + txt003 +STRI + V0 3.42813 0 2.47734 V1 3.38345 -0.0833333 2.47578 V2 3.38244 -0.0933642 2.46543 + N0 0.106533 1.89241e-15 0.994309 N1 0.0539577 -0.111406 0.992309 N2 0.612385 -0.714958 -0.337372 + txt003 +STRI + V0 2.825 0 2.45625 V1 2.86968 -0.0833333 2.45781 V2 2.88121 -0.0733025 2.45154 + N0 2.22045e-15 0 1 N1 -0.0182321 0.0210195 0.999613 N2 0.507715 0.682832 0.525324 + txt003 +STRI + V0 2.88121 -0.0733025 2.45154 V1 2.84074 0 2.45 V2 2.825 0 2.45625 + N0 0.507715 0.682832 0.525324 N1 0.913812 0 0.406138 N2 2.22045e-15 0 1 + txt003 +STRI + V0 2.86968 -0.0833333 2.45781 V1 2.98137 -0.133333 2.46172 V2 2.98237 -0.117284 2.4554 + N0 -0.0182321 0.0210195 0.999613 N1 -0.0369301 -0.00796532 0.999286 N2 0.148477 0.721529 0.676277 + txt003 +STRI + V0 2.98237 -0.117284 2.4554 V1 2.88121 -0.0733025 2.45154 V2 2.86968 -0.0833333 2.45781 + N0 0.148477 0.721529 0.676277 N1 0.507715 0.682832 0.525324 N2 -0.0182321 0.0210195 0.999613 + txt003 +STRI + V0 2.98137 -0.133333 2.46172 V1 3.12656 -0.15 2.4668 V2 3.11389 -0.131944 2.46042 + N0 -0.0369301 -0.00796532 0.999286 N1 -0.0348909 -0.0594438 0.997622 N2 -0.0300305 0.615625 0.787467 + txt003 +STRI + V0 3.11389 -0.131944 2.46042 V1 2.98237 -0.117284 2.4554 V2 2.98137 -0.133333 2.46172 + N0 -0.0300305 0.615625 0.787467 N1 0.148477 0.721529 0.676277 N2 -0.0369301 -0.00796532 0.999286 + txt003 +STRI + V0 3.12656 -0.15 2.4668 V1 3.27176 -0.133333 2.47187 V2 3.2454 -0.117284 2.46543 + N0 -0.0348909 -0.0594438 0.997622 N1 -0.00787186 -0.108144 0.994104 N2 -0.144371 0.459364 0.876437 + txt003 +STRI + V0 3.2454 -0.117284 2.46543 V1 3.11389 -0.131944 2.46042 V2 3.12656 -0.15 2.4668 + N0 -0.144371 0.459364 0.876437 N1 -0.0300305 0.615625 0.787467 N2 -0.0348909 -0.0594438 0.997622 + txt003 +STRI + V0 3.27176 -0.133333 2.47187 V1 3.38345 -0.0833333 2.47578 V2 3.34657 -0.0733025 2.46929 + N0 -0.00787186 -0.108144 0.994104 N1 0.0539577 -0.111406 0.992309 N2 -0.223743 0.242919 0.943891 + txt003 +STRI + V0 3.34657 -0.0733025 2.46929 V1 3.2454 -0.117284 2.46543 V2 3.27176 -0.133333 2.47187 + N0 -0.223743 0.242919 0.943891 N1 -0.144371 0.459364 0.876437 N2 -0.00787186 -0.108144 0.994104 + txt003 +STRI + V0 3.38345 -0.0833333 2.47578 V1 3.42813 0 2.47734 V2 3.38704 0 2.47083 + N0 0.0539577 -0.111406 0.992309 N1 0.106533 1.89241e-15 0.994309 N2 -0.253109 3.19224e-15 0.967438 + txt003 +STRI + V0 3.38704 0 2.47083 V1 3.34657 -0.0733025 2.46929 V2 3.38345 -0.0833333 2.47578 + N0 -0.253109 3.19224e-15 0.967438 N1 -0.223743 0.242919 0.943891 N2 0.0539577 -0.111406 0.992309 + txt003 +STRI + V0 2.84074 0 2.45 V1 2.88121 -0.0733025 2.45154 V2 2.86949 -0.0655864 2.43231 + N0 0.913812 0 0.406138 N1 0.507715 0.682832 0.525324 N2 0.577416 0.711734 -0.400031 + txt003 +STRI + V0 2.86949 -0.0655864 2.43231 V1 2.83426 0 2.43125 V2 2.84074 0 2.45 + N0 0.577416 0.711734 -0.400031 N1 0.789352 0 -0.613941 N2 0.913812 0 0.406138 + txt003 +STRI + V0 2.88121 -0.0733025 2.45154 V1 2.98237 -0.117284 2.4554 V2 2.95756 -0.104938 2.43496 + N0 0.507715 0.682832 0.525324 N1 0.148477 0.721529 0.676277 N2 0.241288 0.970358 -0.0136399 + txt003 +STRI + V0 2.95756 -0.104938 2.43496 V1 2.86949 -0.0655864 2.43231 V2 2.88121 -0.0733025 2.45154 + N0 0.241288 0.970358 -0.0136399 N1 0.577416 0.711734 -0.400031 N2 0.507715 0.682832 0.525324 + txt003 +STRI + V0 2.98237 -0.117284 2.4554 V1 3.11389 -0.131944 2.46042 V2 3.07205 -0.118056 2.43841 + N0 0.148477 0.721529 0.676277 N1 -0.0300305 0.615625 0.787467 N2 -0.0103804 0.938666 0.344672 + txt003 +STRI + V0 3.07205 -0.118056 2.43841 V1 2.95756 -0.104938 2.43496 V2 2.98237 -0.117284 2.4554 + N0 -0.0103804 0.938666 0.344672 N1 0.241288 0.970358 -0.0136399 N2 0.148477 0.721529 0.676277 + txt003 +STRI + V0 3.11389 -0.131944 2.46042 V1 3.2454 -0.117284 2.46543 V2 3.18654 -0.104938 2.44186 + N0 -0.0300305 0.615625 0.787467 N1 -0.144371 0.459364 0.876437 N2 -0.199105 0.721639 0.663019 + txt003 +STRI + V0 3.18654 -0.104938 2.44186 V1 3.07205 -0.118056 2.43841 V2 3.11389 -0.131944 2.46042 + N0 -0.199105 0.721639 0.663019 N1 -0.0103804 0.938666 0.344672 N2 -0.0300305 0.615625 0.787467 + txt003 +STRI + V0 3.2454 -0.117284 2.46543 V1 3.34657 -0.0733025 2.46929 V2 3.27461 -0.0655864 2.44451 + N0 -0.144371 0.459364 0.876437 N1 -0.223743 0.242919 0.943891 N2 -0.316294 0.364979 0.875641 + txt003 +STRI + V0 3.27461 -0.0655864 2.44451 V1 3.18654 -0.104938 2.44186 V2 3.2454 -0.117284 2.46543 + N0 -0.316294 0.364979 0.875641 N1 -0.199105 0.721639 0.663019 N2 -0.144371 0.459364 0.876437 + txt003 +STRI + V0 3.34657 -0.0733025 2.46929 V1 3.38704 0 2.47083 V2 3.30984 0 2.44557 + N0 -0.223743 0.242919 0.943891 N1 -0.253109 3.19224e-15 0.967438 N2 -0.349987 4.0695e-15 0.936755 + txt003 +STRI + V0 3.30984 0 2.44557 V1 3.27461 -0.0655864 2.44451 V2 3.34657 -0.0733025 2.46929 + N0 -0.349987 4.0695e-15 0.936755 N1 -0.316294 0.364979 0.875641 N2 -0.223743 0.242919 0.943891 + txt003 +STRI + V0 2.83426 0 2.43125 V1 2.86949 -0.0655864 2.43231 V2 2.82963 -0.0625 2.4 + N0 0.789352 0 -0.613941 N1 0.577416 0.711734 -0.400031 N2 0.483629 0.537366 -0.690899 + txt003 +STRI + V0 2.82963 -0.0625 2.4 V1 2.8 0 2.4 V2 2.83426 0 2.43125 + N0 0.483629 0.537366 -0.690899 N1 0.6 0 -0.8 N2 0.789352 0 -0.613941 + txt003 +STRI + V0 2.86949 -0.0655864 2.43231 V1 2.95756 -0.104938 2.43496 V2 2.9037 -0.1 2.4 + N0 0.577416 0.711734 -0.400031 N1 0.241288 0.970358 -0.0136399 N2 0.247465 0.879877 -0.405681 + txt003 +STRI + V0 2.9037 -0.1 2.4 V1 2.82963 -0.0625 2.4 V2 2.86949 -0.0655864 2.43231 + N0 0.247465 0.879877 -0.405681 N1 0.483629 0.537366 -0.690899 N2 0.577416 0.711734 -0.400031 + txt003 +STRI + V0 2.95756 -0.104938 2.43496 V1 3.07205 -0.118056 2.43841 V2 3 -0.1125 2.4 + N0 0.241288 0.970358 -0.0136399 N1 -0.0103804 0.938666 0.344672 N2 0 1 0 + txt003 +STRI + V0 3 -0.1125 2.4 V1 2.9037 -0.1 2.4 V2 2.95756 -0.104938 2.43496 + N0 0 1 0 N1 0.247465 0.879877 -0.405681 N2 0.241288 0.970358 -0.0136399 + txt003 +STRI + V0 3.07205 -0.118056 2.43841 V1 3.18654 -0.104938 2.44186 V2 3.0963 -0.1 2.4 + N0 -0.0103804 0.938666 0.344672 N1 -0.199105 0.721639 0.663019 N2 -0.236617 0.841304 0.486024 + txt003 +STRI + V0 3.0963 -0.1 2.4 V1 3 -0.1125 2.4 V2 3.07205 -0.118056 2.43841 + N0 -0.236617 0.841304 0.486024 N1 0 1 0 N2 -0.0103804 0.938666 0.344672 + txt003 +STRI + V0 3.18654 -0.104938 2.44186 V1 3.27461 -0.0655864 2.44451 V2 3.17037 -0.0625 2.4 + N0 -0.199105 0.721639 0.663019 N1 -0.316294 0.364979 0.875641 N2 -0.378646 0.420717 0.824393 + txt003 +STRI + V0 3.17037 -0.0625 2.4 V1 3.0963 -0.1 2.4 V2 3.18654 -0.104938 2.44186 + N0 -0.378646 0.420717 0.824393 N1 -0.236617 0.841304 0.486024 N2 -0.199105 0.721639 0.663019 + txt003 +STRI + V0 3.27461 -0.0655864 2.44451 V1 3.30984 0 2.44557 V2 3.2 0 2.4 + N0 -0.316294 0.364979 0.875641 N1 -0.349987 4.0695e-15 0.936755 N2 -0.410365 4.31973e-15 0.911922 + txt003 +STRI + V0 3.2 0 2.4 V1 3.17037 -0.0625 2.4 V2 3.27461 -0.0655864 2.44451 + N0 -0.410365 4.31973e-15 0.911922 N1 -0.378646 0.420717 0.824393 N2 -0.316294 0.364979 0.875641 + txt003 +STRI + V0 3.3 0 2.4 V1 3.25556 0.104167 2.4 V2 3.34075 0.10108 2.43969 + N0 0.384615 0 -0.923077 N1 0.366221 0.366221 -0.855433 N2 0.442187 0.473386 -0.761824 + txt003 +STRI + V0 3.34075 0.10108 2.43969 V1 3.38808 0 2.44036 V2 3.3 0 2.4 + N0 0.442187 0.473386 -0.761824 N1 0.463425 0 -0.886136 N2 0.384615 0 -0.923077 + txt003 +STRI + V0 3.25556 0.104167 2.4 V1 3.14444 0.166667 2.4 V2 3.22241 0.161728 2.438 + N0 0.366221 0.366221 -0.855433 N1 0.250514 0.801644 -0.54278 N2 0.269127 0.933284 -0.237808 + txt003 +STRI + V0 3.22241 0.161728 2.438 V1 3.34075 0.10108 2.43969 V2 3.25556 0.104167 2.4 + N0 0.269127 0.933284 -0.237808 N1 0.442187 0.473386 -0.761824 N2 0.366221 0.366221 -0.855433 + txt003 +STRI + V0 3.14444 0.166667 2.4 V1 3 0.1875 2.4 V2 3.06858 0.181944 2.43581 + N0 0.250514 0.801644 -0.54278 N1 0 1 -0 N2 -0.00489618 0.939227 0.343261 + txt003 +STRI + V0 3.06858 0.181944 2.43581 V1 3.22241 0.161728 2.438 V2 3.14444 0.166667 2.4 + N0 -0.00489618 0.939227 0.343261 N1 0.269127 0.933284 -0.237808 N2 0.250514 0.801644 -0.54278 + txt003 +STRI + V0 3 0.1875 2.4 V1 2.85556 0.166667 2.4 V2 2.91474 0.161728 2.43361 + N0 0 1 -0 N1 -0.267368 0.855576 0.443288 N2 -0.215548 0.724209 0.655027 + txt003 +STRI + V0 2.91474 0.161728 2.43361 V1 3.06858 0.181944 2.43581 V2 3 0.1875 2.4 + N0 -0.215548 0.724209 0.655027 N1 -0.00489618 0.939227 0.343261 N2 0 1 -0 + txt003 +STRI + V0 2.85556 0.166667 2.4 V1 2.74444 0.104167 2.4 V2 2.79641 0.10108 2.43193 + N0 -0.267368 0.855576 0.443288 N1 -0.497164 0.497164 0.711095 N2 -0.387052 0.411886 0.824949 + txt003 +STRI + V0 2.79641 0.10108 2.43193 V1 2.91474 0.161728 2.43361 V2 2.85556 0.166667 2.4 + N0 -0.387052 0.411886 0.824949 N1 -0.215548 0.724209 0.655027 N2 -0.267368 0.855576 0.443288 + txt003 +STRI + V0 2.74444 0.104167 2.4 V1 2.7 0 2.4 V2 2.74907 0 2.43125 + N0 -0.497164 0.497164 0.711095 N1 -0.6 2.24387e-29 0.8 N2 -0.467888 -4.75841e-16 0.883788 + txt003 +STRI + V0 2.74907 0 2.43125 V1 2.79641 0.10108 2.43193 V2 2.74444 0.104167 2.4 + N0 -0.467888 -4.75841e-16 0.883788 N1 -0.387052 0.411886 0.824949 N2 -0.497164 0.497164 0.711095 + txt003 +STRI + V0 3.38808 0 2.44036 V1 3.34075 0.10108 2.43969 V2 3.38244 0.0933642 2.46543 + N0 0.463425 0 -0.886136 N1 0.442187 0.473386 -0.761824 N2 0.612385 0.714958 -0.337372 + txt003 +STRI + V0 3.38244 0.0933642 2.46543 V1 3.42963 0 2.46667 V2 3.38808 0 2.44036 + N0 0.612385 0.714958 -0.337372 N1 0.694136 0 -0.719844 N2 0.463425 0 -0.886136 + txt003 +STRI + V0 3.34075 0.10108 2.43969 V1 3.22241 0.161728 2.438 V2 3.26447 0.149383 2.46235 + N0 0.442187 0.473386 -0.761824 N1 0.269127 0.933284 -0.237808 N2 0.218115 0.87054 0.44112 + txt003 +STRI + V0 3.26447 0.149383 2.46235 V1 3.38244 0.0933642 2.46543 V2 3.34075 0.10108 2.43969 + N0 0.218115 0.87054 0.44112 N1 0.612385 0.714958 -0.337372 N2 0.442187 0.473386 -0.761824 + txt003 +STRI + V0 3.22241 0.161728 2.438 V1 3.06858 0.181944 2.43581 V2 3.11111 0.168056 2.45833 + N0 0.269127 0.933284 -0.237808 N1 -0.00489618 0.939227 0.343261 N2 -0.0195232 0.665415 0.746219 + txt003 +STRI + V0 3.11111 0.168056 2.45833 V1 3.26447 0.149383 2.46235 V2 3.22241 0.161728 2.438 + N0 -0.0195232 0.665415 0.746219 N1 0.218115 0.87054 0.44112 N2 0.269127 0.933284 -0.237808 + txt003 +STRI + V0 3.06858 0.181944 2.43581 V1 2.91474 0.161728 2.43361 V2 2.95775 0.149383 2.45432 + N0 -0.00489618 0.939227 0.343261 N1 -0.215548 0.724209 0.655027 N2 -0.14959 0.481391 0.863647 + txt003 +STRI + V0 2.95775 0.149383 2.45432 V1 3.11111 0.168056 2.45833 V2 3.06858 0.181944 2.43581 + N0 -0.14959 0.481391 0.863647 N1 -0.0195232 0.665415 0.746219 N2 -0.00489618 0.939227 0.343261 + txt003 +STRI + V0 2.91474 0.161728 2.43361 V1 2.79641 0.10108 2.43193 V2 2.83978 0.0933642 2.45123 + N0 -0.215548 0.724209 0.655027 N1 -0.387052 0.411886 0.824949 N2 -0.253997 0.272114 0.928138 + txt003 +STRI + V0 2.83978 0.0933642 2.45123 V1 2.95775 0.149383 2.45432 V2 2.91474 0.161728 2.43361 + N0 -0.253997 0.272114 0.928138 N1 -0.14959 0.481391 0.863647 N2 -0.215548 0.724209 0.655027 + txt003 +STRI + V0 2.79641 0.10108 2.43193 V1 2.74907 0 2.43125 V2 2.79259 0 2.45 + N0 -0.387052 0.411886 0.824949 N1 -0.467888 -4.75841e-16 0.883788 N2 -0.306009 -1.09783e-15 0.952029 + txt003 +STRI + V0 2.79259 0 2.45 V1 2.83978 0.0933642 2.45123 V2 2.79641 0.10108 2.43193 + N0 -0.306009 -1.09783e-15 0.952029 N1 -0.253997 0.272114 0.928138 N2 -0.387052 0.411886 0.824949 + txt003 +STRI + V0 3.42963 0 2.46667 V1 3.38244 0.0933642 2.46543 V2 3.38345 0.0833333 2.47578 + N0 0.694136 0 -0.719844 N1 0.612385 0.714958 -0.337372 N2 0.0539577 0.111406 0.992309 + txt003 +STRI + V0 3.38345 0.0833333 2.47578 V1 3.42813 0 2.47734 V2 3.42963 0 2.46667 + N0 0.0539577 0.111406 0.992309 N1 0.106533 -0 0.994309 N2 0.694136 0 -0.719844 + txt003 +STRI + V0 3.38244 0.0933642 2.46543 V1 3.26447 0.149383 2.46235 V2 3.27176 0.133333 2.47188 + N0 0.612385 0.714958 -0.337372 N1 0.218115 0.87054 0.44112 N2 -0.00787186 0.108144 0.994104 + txt003 +STRI + V0 3.27176 0.133333 2.47188 V1 3.38345 0.0833333 2.47578 V2 3.38244 0.0933642 2.46543 + N0 -0.00787186 0.108144 0.994104 N1 0.0539577 0.111406 0.992309 N2 0.612385 0.714958 -0.337372 + txt003 +STRI + V0 3.26447 0.149383 2.46235 V1 3.11111 0.168056 2.45833 V2 3.12656 0.15 2.4668 + N0 0.218115 0.87054 0.44112 N1 -0.0195232 0.665415 0.746219 N2 -0.0348909 0.0594438 0.997622 + txt003 +STRI + V0 3.12656 0.15 2.4668 V1 3.27176 0.133333 2.47188 V2 3.26447 0.149383 2.46235 + N0 -0.0348909 0.0594438 0.997622 N1 -0.00787186 0.108144 0.994104 N2 0.218115 0.87054 0.44112 + txt003 +STRI + V0 3.11111 0.168056 2.45833 V1 2.95775 0.149383 2.45432 V2 2.98137 0.133333 2.46172 + N0 -0.0195232 0.665415 0.746219 N1 -0.14959 0.481391 0.863647 N2 -0.0369301 0.00796532 0.999286 + txt003 +STRI + V0 2.98137 0.133333 2.46172 V1 3.12656 0.15 2.4668 V2 3.11111 0.168056 2.45833 + N0 -0.0369301 0.00796532 0.999286 N1 -0.0348909 0.0594438 0.997622 N2 -0.0195232 0.665415 0.746219 + txt003 +STRI + V0 2.95775 0.149383 2.45432 V1 2.83978 0.0933642 2.45123 V2 2.86968 0.0833333 2.45781 + N0 -0.14959 0.481391 0.863647 N1 -0.253997 0.272114 0.928138 N2 -0.0182321 -0.0210195 0.999613 + txt003 +STRI + V0 2.86968 0.0833333 2.45781 V1 2.98137 0.133333 2.46172 V2 2.95775 0.149383 2.45432 + N0 -0.0182321 -0.0210195 0.999613 N1 -0.0369301 0.00796532 0.999286 N2 -0.14959 0.481391 0.863647 + txt003 +STRI + V0 2.83978 0.0933642 2.45123 V1 2.79259 0 2.45 V2 2.825 0 2.45625 + N0 -0.253997 0.272114 0.928138 N1 -0.306009 -1.09783e-15 0.952029 N2 2.22045e-15 -2.22045e-15 1 + txt003 +STRI + V0 2.825 0 2.45625 V1 2.86968 0.0833333 2.45781 V2 2.83978 0.0933642 2.45123 + N0 2.22045e-15 -2.22045e-15 1 N1 -0.0182321 -0.0210195 0.999613 N2 -0.253997 0.272114 0.928138 + txt003 +STRI + V0 3.42813 0 2.47734 V1 3.38345 0.0833333 2.47578 V2 3.34657 0.0733025 2.46929 + N0 0.106533 -0 0.994309 N1 0.0539577 0.111406 0.992309 N2 -0.223743 -0.242919 0.943891 + txt003 +STRI + V0 3.34657 0.0733025 2.46929 V1 3.38704 0 2.47083 V2 3.42813 0 2.47734 + N0 -0.223743 -0.242919 0.943891 N1 -0.253109 0 0.967438 N2 0.106533 -0 0.994309 + txt003 +STRI + V0 3.38345 0.0833333 2.47578 V1 3.27176 0.133333 2.47188 V2 3.2454 0.117284 2.46543 + N0 0.0539577 0.111406 0.992309 N1 -0.00787186 0.108144 0.994104 N2 -0.144371 -0.459364 0.876437 + txt003 +STRI + V0 3.2454 0.117284 2.46543 V1 3.34657 0.0733025 2.46929 V2 3.38345 0.0833333 2.47578 + N0 -0.144371 -0.459364 0.876437 N1 -0.223743 -0.242919 0.943891 N2 0.0539577 0.111406 0.992309 + txt003 +STRI + V0 3.27176 0.133333 2.47188 V1 3.12656 0.15 2.4668 V2 3.11389 0.131944 2.46042 + N0 -0.00787186 0.108144 0.994104 N1 -0.0348909 0.0594438 0.997622 N2 -0.0300305 -0.615625 0.787467 + txt003 +STRI + V0 3.11389 0.131944 2.46042 V1 3.2454 0.117284 2.46543 V2 3.27176 0.133333 2.47188 + N0 -0.0300305 -0.615625 0.787467 N1 -0.144371 -0.459364 0.876437 N2 -0.00787186 0.108144 0.994104 + txt003 +STRI + V0 3.12656 0.15 2.4668 V1 2.98137 0.133333 2.46172 V2 2.98237 0.117284 2.4554 + N0 -0.0348909 0.0594438 0.997622 N1 -0.0369301 0.00796532 0.999286 N2 0.148477 -0.721529 0.676277 + txt003 +STRI + V0 2.98237 0.117284 2.4554 V1 3.11389 0.131944 2.46042 V2 3.12656 0.15 2.4668 + N0 0.148477 -0.721529 0.676277 N1 -0.0300305 -0.615625 0.787467 N2 -0.0348909 0.0594438 0.997622 + txt003 +STRI + V0 2.98137 0.133333 2.46172 V1 2.86968 0.0833333 2.45781 V2 2.88121 0.0733025 2.45154 + N0 -0.0369301 0.00796532 0.999286 N1 -0.0182321 -0.0210195 0.999613 N2 0.507715 -0.682832 0.525324 + txt003 +STRI + V0 2.88121 0.0733025 2.45154 V1 2.98237 0.117284 2.4554 V2 2.98137 0.133333 2.46172 + N0 0.507715 -0.682832 0.525324 N1 0.148477 -0.721529 0.676277 N2 -0.0369301 0.00796532 0.999286 + txt003 +STRI + V0 2.86968 0.0833333 2.45781 V1 2.825 0 2.45625 V2 2.84074 0 2.45 + N0 -0.0182321 -0.0210195 0.999613 N1 2.22045e-15 -2.22045e-15 1 N2 0.913812 -4.13289e-15 0.406138 + txt003 +STRI + V0 2.84074 0 2.45 V1 2.88121 0.0733025 2.45154 V2 2.86968 0.0833333 2.45781 + N0 0.913812 -4.13289e-15 0.406138 N1 0.507715 -0.682832 0.525324 N2 -0.0182321 -0.0210195 0.999613 + txt003 +STRI + V0 3.38704 0 2.47083 V1 3.34657 0.0733025 2.46929 V2 3.27461 0.0655864 2.44451 + N0 -0.253109 0 0.967438 N1 -0.223743 -0.242919 0.943891 N2 -0.316294 -0.364979 0.875641 + txt003 +STRI + V0 3.27461 0.0655864 2.44451 V1 3.30984 0 2.44557 V2 3.38704 0 2.47083 + N0 -0.316294 -0.364979 0.875641 N1 -0.349987 0 0.936755 N2 -0.253109 0 0.967438 + txt003 +STRI + V0 3.34657 0.0733025 2.46929 V1 3.2454 0.117284 2.46543 V2 3.18654 0.104938 2.44186 + N0 -0.223743 -0.242919 0.943891 N1 -0.144371 -0.459364 0.876437 N2 -0.199105 -0.721639 0.663019 + txt003 +STRI + V0 3.18654 0.104938 2.44186 V1 3.27461 0.0655864 2.44451 V2 3.34657 0.0733025 2.46929 + N0 -0.199105 -0.721639 0.663019 N1 -0.316294 -0.364979 0.875641 N2 -0.223743 -0.242919 0.943891 + txt003 +STRI + V0 3.2454 0.117284 2.46543 V1 3.11389 0.131944 2.46042 V2 3.07205 0.118056 2.43841 + N0 -0.144371 -0.459364 0.876437 N1 -0.0300305 -0.615625 0.787467 N2 -0.0103804 -0.938666 0.344672 + txt003 +STRI + V0 3.07205 0.118056 2.43841 V1 3.18654 0.104938 2.44186 V2 3.2454 0.117284 2.46543 + N0 -0.0103804 -0.938666 0.344672 N1 -0.199105 -0.721639 0.663019 N2 -0.144371 -0.459364 0.876437 + txt003 +STRI + V0 3.11389 0.131944 2.46042 V1 2.98237 0.117284 2.4554 V2 2.95756 0.104938 2.43496 + N0 -0.0300305 -0.615625 0.787467 N1 0.148477 -0.721529 0.676277 N2 0.241288 -0.970358 -0.0136399 + txt003 +STRI + V0 2.95756 0.104938 2.43496 V1 3.07205 0.118056 2.43841 V2 3.11389 0.131944 2.46042 + N0 0.241288 -0.970358 -0.0136399 N1 -0.0103804 -0.938666 0.344672 N2 -0.0300305 -0.615625 0.787467 + txt003 +STRI + V0 2.98237 0.117284 2.4554 V1 2.88121 0.0733025 2.45154 V2 2.86949 0.0655864 2.43231 + N0 0.148477 -0.721529 0.676277 N1 0.507715 -0.682832 0.525324 N2 0.577416 -0.711734 -0.400031 + txt003 +STRI + V0 2.86949 0.0655864 2.43231 V1 2.95756 0.104938 2.43496 V2 2.98237 0.117284 2.4554 + N0 0.577416 -0.711734 -0.400031 N1 0.241288 -0.970358 -0.0136399 N2 0.148477 -0.721529 0.676277 + txt003 +STRI + V0 2.88121 0.0733025 2.45154 V1 2.84074 0 2.45 V2 2.83426 0 2.43125 + N0 0.507715 -0.682832 0.525324 N1 0.913812 -4.13289e-15 0.406138 N2 0.789352 -1.30938e-15 -0.613941 + txt003 +STRI + V0 2.83426 0 2.43125 V1 2.86949 0.0655864 2.43231 V2 2.88121 0.0733025 2.45154 + N0 0.789352 -1.30938e-15 -0.613941 N1 0.577416 -0.711734 -0.400031 N2 0.507715 -0.682832 0.525324 + txt003 +STRI + V0 3.30984 0 2.44557 V1 3.27461 0.0655864 2.44451 V2 3.17037 0.0625 2.4 + N0 -0.349987 0 0.936755 N1 -0.316294 -0.364979 0.875641 N2 -0.378646 -0.420717 0.824393 + txt003 +STRI + V0 3.17037 0.0625 2.4 V1 3.2 0 2.4 V2 3.30984 0 2.44557 + N0 -0.378646 -0.420717 0.824393 N1 -0.410365 0 0.911922 N2 -0.349987 0 0.936755 + txt003 +STRI + V0 3.27461 0.0655864 2.44451 V1 3.18654 0.104938 2.44186 V2 3.0963 0.1 2.4 + N0 -0.316294 -0.364979 0.875641 N1 -0.199105 -0.721639 0.663019 N2 -0.236617 -0.841304 0.486024 + txt003 +STRI + V0 3.0963 0.1 2.4 V1 3.17037 0.0625 2.4 V2 3.27461 0.0655864 2.44451 + N0 -0.236617 -0.841304 0.486024 N1 -0.378646 -0.420717 0.824393 N2 -0.316294 -0.364979 0.875641 + txt003 +STRI + V0 3.18654 0.104938 2.44186 V1 3.07205 0.118056 2.43841 V2 3 0.1125 2.4 + N0 -0.199105 -0.721639 0.663019 N1 -0.0103804 -0.938666 0.344672 N2 0 -1 0 + txt003 +STRI + V0 3 0.1125 2.4 V1 3.0963 0.1 2.4 V2 3.18654 0.104938 2.44186 + N0 0 -1 0 N1 -0.236617 -0.841304 0.486024 N2 -0.199105 -0.721639 0.663019 + txt003 +STRI + V0 3.07205 0.118056 2.43841 V1 2.95756 0.104938 2.43496 V2 2.9037 0.1 2.4 + N0 -0.0103804 -0.938666 0.344672 N1 0.241288 -0.970358 -0.0136399 N2 0.247465 -0.879877 -0.405681 + txt003 +STRI + V0 2.9037 0.1 2.4 V1 3 0.1125 2.4 V2 3.07205 0.118056 2.43841 + N0 0.247465 -0.879877 -0.405681 N1 0 -1 0 N2 -0.0103804 -0.938666 0.344672 + txt003 +STRI + V0 2.95756 0.104938 2.43496 V1 2.86949 0.0655864 2.43231 V2 2.82963 0.0625 2.4 + N0 0.241288 -0.970358 -0.0136399 N1 0.577416 -0.711734 -0.400031 N2 0.483629 -0.537366 -0.690899 + txt003 +STRI + V0 2.82963 0.0625 2.4 V1 2.9037 0.1 2.4 V2 2.95756 0.104938 2.43496 + N0 0.483629 -0.537366 -0.690899 N1 0.247465 -0.879877 -0.405681 N2 0.241288 -0.970358 -0.0136399 + txt003 +STRI + V0 2.86949 0.0655864 2.43231 V1 2.83426 0 2.43125 V2 2.8 0 2.4 + N0 0.577416 -0.711734 -0.400031 N1 0.789352 -1.30938e-15 -0.613941 N2 0.6 -3.73979e-29 -0.8 + txt003 +STRI + V0 2.8 0 2.4 V1 2.82963 0.0625 2.4 V2 2.86949 0.0655864 2.43231 + N0 0.6 -3.73979e-29 -0.8 N1 0.483629 -0.537366 -0.690899 N2 0.577416 -0.711734 -0.400031 + txt003 +STRI + V0 0.268946 -0.0750782 3.12708 V1 0.278704 0 3.12708 V2 0 0 3.15 + N0 0.241077 -0.0645609 0.968356 N1 0.249998 0 0.968246 N2 0 0 1 + txt003 +STRI + V0 0.241285 -0.141931 3.12708 V1 0.268946 -0.0750782 3.12708 V2 0 0 3.15 + N0 0.215548 -0.124615 0.968509 N1 0.241077 -0.0645609 0.968356 N2 0 0 1 + txt003 +STRI + V0 0.19814 -0.19814 3.12708 V1 0.241285 -0.141931 3.12708 V2 0 0 3.15 + N0 0.175885 -0.175885 0.96857 N1 0.215548 -0.124615 0.968509 N2 0 0 1 + txt003 +STRI + V0 0.141931 -0.241285 3.12708 V1 0.19814 -0.19814 3.12708 V2 0 0 3.15 + N0 0.124615 -0.215548 0.968509 N1 0.175885 -0.175885 0.96857 N2 0 0 1 + txt003 +STRI + V0 0.0750782 -0.268946 3.12708 V1 0.141931 -0.241285 3.12708 V2 0 0 3.15 + N0 0.0645609 -0.241077 0.968356 N1 0.124615 -0.215548 0.968509 N2 0 0 1 + txt003 +STRI + V0 0 -0.278704 3.12708 V1 0.0750782 -0.268946 3.12708 V2 0 0 3.15 + N0 -2.80184e-15 -0.249998 0.968246 N1 0.0645609 -0.241077 0.968356 N2 0 0 1 + txt003 +STRI + V0 0.278704 0 3.12708 V1 0.268946 -0.0750782 3.12708 V2 0.350254 -0.0977709 3.06667 + N0 0.249998 0 0.968246 N1 0.241077 -0.0645609 0.968356 N2 0.955496 -0.255913 0.146755 + txt003 +STRI + V0 0.350254 -0.0977709 3.06667 V1 0.362963 0 3.06667 V2 0.278704 0 3.12708 + N0 0.955496 -0.255913 0.146755 N1 0.989203 0 0.146549 N2 0.249998 0 0.968246 + txt003 +STRI + V0 0.268946 -0.0750782 3.12708 V1 0.241285 -0.141931 3.12708 V2 0.314228 -0.184834 3.06667 + N0 0.241077 -0.0645609 0.968356 N1 0.215548 -0.124615 0.968509 N2 0.856312 -0.495088 0.147029 + txt003 +STRI + V0 0.314228 -0.184834 3.06667 V1 0.350254 -0.0977709 3.06667 V2 0.268946 -0.0750782 3.12708 + N0 0.856312 -0.495088 0.147029 N1 0.955496 -0.255913 0.146755 N2 0.241077 -0.0645609 0.968356 + txt003 +STRI + V0 0.241285 -0.141931 3.12708 V1 0.19814 -0.19814 3.12708 V2 0.258037 -0.258037 3.06667 + N0 0.215548 -0.124615 0.968509 N1 0.175885 -0.175885 0.96857 N2 0.699411 -0.699411 0.147135 + txt003 +STRI + V0 0.258037 -0.258037 3.06667 V1 0.314228 -0.184834 3.06667 V2 0.241285 -0.141931 3.12708 + N0 0.699411 -0.699411 0.147135 N1 0.856312 -0.495088 0.147029 N2 0.215548 -0.124615 0.968509 + txt003 +STRI + V0 0.19814 -0.19814 3.12708 V1 0.141931 -0.241285 3.12708 V2 0.184834 -0.314228 3.06667 + N0 0.175885 -0.175885 0.96857 N1 0.124615 -0.215548 0.968509 N2 0.495088 -0.856312 0.147029 + txt003 +STRI + V0 0.184834 -0.314228 3.06667 V1 0.258037 -0.258037 3.06667 V2 0.19814 -0.19814 3.12708 + N0 0.495088 -0.856312 0.147029 N1 0.699411 -0.699411 0.147135 N2 0.175885 -0.175885 0.96857 + txt003 +STRI + V0 0.141931 -0.241285 3.12708 V1 0.0750782 -0.268946 3.12708 V2 0.0977709 -0.350254 3.06667 + N0 0.124615 -0.215548 0.968509 N1 0.0645609 -0.241077 0.968356 N2 0.255913 -0.955496 0.146755 + txt003 +STRI + V0 0.0977709 -0.350254 3.06667 V1 0.184834 -0.314228 3.06667 V2 0.141931 -0.241285 3.12708 + N0 0.255913 -0.955496 0.146755 N1 0.495088 -0.856312 0.147029 N2 0.124615 -0.215548 0.968509 + txt003 +STRI + V0 0.0750782 -0.268946 3.12708 V1 0 -0.278704 3.12708 V2 0 -0.362963 3.06667 + N0 0.0645609 -0.241077 0.968356 N1 -2.80184e-15 -0.249998 0.968246 N2 -4.98112e-16 -0.989203 0.146549 + txt003 +STRI + V0 0 -0.362963 3.06667 V1 0.0977709 -0.350254 3.06667 V2 0.0750782 -0.268946 3.12708 + N0 -4.98112e-16 -0.989203 0.146549 N1 0.255913 -0.955496 0.146755 N2 0.0645609 -0.241077 0.968356 + txt003 +STRI + V0 0.362963 0 3.06667 V1 0.350254 -0.0977709 3.06667 V2 0.313617 -0.0875289 2.98125 + N0 0.989203 0 0.146549 N1 0.955496 -0.255913 0.146755 N2 0.753688 -0.201937 -0.625441 + txt003 +STRI + V0 0.313617 -0.0875289 2.98125 V1 0.325 0 2.98125 V2 0.362963 0 3.06667 + N0 0.753688 -0.201937 -0.625441 N1 0.780869 0 -0.624695 N2 0.989203 0 0.146549 + txt003 +STRI + V0 0.350254 -0.0977709 3.06667 V1 0.314228 -0.184834 3.06667 V2 0.281352 -0.165481 2.98125 + N0 0.955496 -0.255913 0.146755 N1 0.856312 -0.495088 0.147029 N2 0.674735 -0.390178 -0.626493 + txt003 +STRI + V0 0.281352 -0.165481 2.98125 V1 0.313617 -0.0875289 2.98125 V2 0.350254 -0.0977709 3.06667 + N0 0.674735 -0.390178 -0.626493 N1 0.753688 -0.201937 -0.625441 N2 0.955496 -0.255913 0.146755 + txt003 +STRI + V0 0.314228 -0.184834 3.06667 V1 0.258037 -0.258037 3.06667 V2 0.231031 -0.231031 2.98125 + N0 0.856312 -0.495088 0.147029 N1 0.699411 -0.699411 0.147135 N2 0.550896 -0.550896 -0.626919 + txt003 +STRI + V0 0.231031 -0.231031 2.98125 V1 0.281352 -0.165481 2.98125 V2 0.314228 -0.184834 3.06667 + N0 0.550896 -0.550896 -0.626919 N1 0.674735 -0.390178 -0.626493 N2 0.856312 -0.495088 0.147029 + txt003 +STRI + V0 0.258037 -0.258037 3.06667 V1 0.184834 -0.314228 3.06667 V2 0.165481 -0.281352 2.98125 + N0 0.699411 -0.699411 0.147135 N1 0.495088 -0.856312 0.147029 N2 0.390178 -0.674735 -0.626493 + txt003 +STRI + V0 0.165481 -0.281352 2.98125 V1 0.231031 -0.231031 2.98125 V2 0.258037 -0.258037 3.06667 + N0 0.390178 -0.674735 -0.626493 N1 0.550896 -0.550896 -0.626919 N2 0.699411 -0.699411 0.147135 + txt003 +STRI + V0 0.184834 -0.314228 3.06667 V1 0.0977709 -0.350254 3.06667 V2 0.0875289 -0.313617 2.98125 + N0 0.495088 -0.856312 0.147029 N1 0.255913 -0.955496 0.146755 N2 0.201937 -0.753688 -0.625441 + txt003 +STRI + V0 0.0875289 -0.313617 2.98125 V1 0.165481 -0.281352 2.98125 V2 0.184834 -0.314228 3.06667 + N0 0.201937 -0.753688 -0.625441 N1 0.390178 -0.674735 -0.626493 N2 0.495088 -0.856312 0.147029 + txt003 +STRI + V0 0.0977709 -0.350254 3.06667 V1 0 -0.362963 3.06667 V2 -1.11022e-16 -0.325 2.98125 + N0 0.255913 -0.955496 0.146755 N1 -4.98112e-16 -0.989203 0.146549 N2 1.51803e-15 -0.780869 -0.624695 + txt003 +STRI + V0 -1.11022e-16 -0.325 2.98125 V1 0.0875289 -0.313617 2.98125 V2 0.0977709 -0.350254 3.06667 + N0 1.51803e-15 -0.780869 -0.624695 N1 0.201937 -0.753688 -0.625441 N2 0.255913 -0.955496 0.146755 + txt003 +STRI + V0 0.325 0 2.98125 V1 0.313617 -0.0875289 2.98125 V2 0.228728 -0.0638032 2.88333 + N0 0.780869 0 -0.624695 N1 0.753688 -0.201937 -0.625441 N2 0.721244 -0.193465 -0.665116 + txt003 +STRI + V0 0.228728 -0.0638032 2.88333 V1 0.237037 0 2.88333 V2 0.325 0 2.98125 + N0 0.721244 -0.193465 -0.665116 N1 0.747409 0 -0.664364 N2 0.780869 0 -0.624695 + txt003 +STRI + V0 0.313617 -0.0875289 2.98125 V1 0.281352 -0.165481 2.98125 V2 0.20518 -0.120647 2.88333 + N0 0.753688 -0.201937 -0.625441 N1 0.674735 -0.390178 -0.626493 N2 0.645526 -0.373497 -0.66618 + txt003 +STRI + V0 0.20518 -0.120647 2.88333 V1 0.228728 -0.0638032 2.88333 V2 0.313617 -0.0875289 2.98125 + N0 0.645526 -0.373497 -0.66618 N1 0.721244 -0.193465 -0.665116 N2 0.753688 -0.201937 -0.625441 + txt003 +STRI + V0 0.281352 -0.165481 2.98125 V1 0.231031 -0.231031 2.98125 V2 0.168463 -0.168463 2.88333 + N0 0.674735 -0.390178 -0.626493 N1 0.550896 -0.550896 -0.626919 N2 0.527081 -0.527081 -0.666611 + txt003 +STRI + V0 0.168463 -0.168463 2.88333 V1 0.20518 -0.120647 2.88333 V2 0.281352 -0.165481 2.98125 + N0 0.527081 -0.527081 -0.666611 N1 0.645526 -0.373497 -0.66618 N2 0.674735 -0.390178 -0.626493 + txt003 +STRI + V0 0.231031 -0.231031 2.98125 V1 0.165481 -0.281352 2.98125 V2 0.120647 -0.20518 2.88333 + N0 0.550896 -0.550896 -0.626919 N1 0.390178 -0.674735 -0.626493 N2 0.373497 -0.645526 -0.66618 + txt003 +STRI + V0 0.120647 -0.20518 2.88333 V1 0.168463 -0.168463 2.88333 V2 0.231031 -0.231031 2.98125 + N0 0.373497 -0.645526 -0.66618 N1 0.527081 -0.527081 -0.666611 N2 0.550896 -0.550896 -0.626919 + txt003 +STRI + V0 0.165481 -0.281352 2.98125 V1 0.0875289 -0.313617 2.98125 V2 0.0638032 -0.228728 2.88333 + N0 0.390178 -0.674735 -0.626493 N1 0.201937 -0.753688 -0.625441 N2 0.193465 -0.721244 -0.665116 + txt003 +STRI + V0 0.0638032 -0.228728 2.88333 V1 0.120647 -0.20518 2.88333 V2 0.165481 -0.281352 2.98125 + N0 0.193465 -0.721244 -0.665116 N1 0.373497 -0.645526 -0.66618 N2 0.390178 -0.674735 -0.626493 + txt003 +STRI + V0 0.0875289 -0.313617 2.98125 V1 -1.11022e-16 -0.325 2.98125 V2 -1.11022e-16 -0.237037 2.88333 + N0 0.201937 -0.753688 -0.625441 N1 1.51803e-15 -0.780869 -0.624695 N2 2.42292e-15 -0.747409 -0.664364 + txt003 +STRI + V0 -1.11022e-16 -0.237037 2.88333 V1 0.0638032 -0.228728 2.88333 V2 0.0875289 -0.313617 2.98125 + N0 2.42292e-15 -0.747409 -0.664364 N1 0.193465 -0.721244 -0.665116 N2 0.201937 -0.753688 -0.625441 + txt003 +STRI + V0 0.237037 0 2.88333 V1 0.228728 -0.0638032 2.88333 V2 0.165279 -0.0460445 2.78542 + N0 0.747409 0 -0.664364 N1 0.721244 -0.193465 -0.665116 N2 0.917897 -0.246906 -0.310647 + txt003 +STRI + V0 0.165279 -0.0460445 2.78542 V1 0.171296 0 2.78542 V2 0.237037 0 2.88333 + N0 0.917897 -0.246906 -0.310647 N1 0.950775 0 -0.309882 N2 0.747409 0 -0.664364 + txt003 +STRI + V0 0.228728 -0.0638032 2.88333 V1 0.20518 -0.120647 2.88333 V2 0.148234 -0.0871056 2.78542 + N0 0.721244 -0.193465 -0.665116 N1 0.645526 -0.373497 -0.66618 N2 0.822132 -0.476337 -0.311772 + txt003 +STRI + V0 0.148234 -0.0871056 2.78542 V1 0.165279 -0.0460445 2.78542 V2 0.228728 -0.0638032 2.88333 + N0 0.822132 -0.476337 -0.311772 N1 0.917897 -0.246906 -0.310647 N2 0.721244 -0.193465 -0.665116 + txt003 +STRI + V0 0.20518 -0.120647 2.88333 V1 0.168463 -0.168463 2.88333 V2 0.121672 -0.121672 2.78542 + N0 0.645526 -0.373497 -0.66618 N1 0.527081 -0.527081 -0.666611 N2 0.671754 -0.671754 -0.312241 + txt003 +STRI + V0 0.121672 -0.121672 2.78542 V1 0.148234 -0.0871056 2.78542 V2 0.20518 -0.120647 2.88333 + N0 0.671754 -0.671754 -0.312241 N1 0.822132 -0.476337 -0.311772 N2 0.645526 -0.373497 -0.66618 + txt003 +STRI + V0 0.168463 -0.168463 2.88333 V1 0.120647 -0.20518 2.88333 V2 0.0871056 -0.148234 2.78542 + N0 0.527081 -0.527081 -0.666611 N1 0.373497 -0.645526 -0.66618 N2 0.476337 -0.822132 -0.311772 + txt003 +STRI + V0 0.0871056 -0.148234 2.78542 V1 0.121672 -0.121672 2.78542 V2 0.168463 -0.168463 2.88333 + N0 0.476337 -0.822132 -0.311772 N1 0.671754 -0.671754 -0.312241 N2 0.527081 -0.527081 -0.666611 + txt003 +STRI + V0 0.120647 -0.20518 2.88333 V1 0.0638032 -0.228728 2.88333 V2 0.0460445 -0.165279 2.78542 + N0 0.373497 -0.645526 -0.66618 N1 0.193465 -0.721244 -0.665116 N2 0.246906 -0.917897 -0.310647 + txt003 +STRI + V0 0.0460445 -0.165279 2.78542 V1 0.0871056 -0.148234 2.78542 V2 0.120647 -0.20518 2.88333 + N0 0.246906 -0.917897 -0.310647 N1 0.476337 -0.822132 -0.311772 N2 0.373497 -0.645526 -0.66618 + txt003 +STRI + V0 0.0638032 -0.228728 2.88333 V1 -1.11022e-16 -0.237037 2.88333 V2 -6.66134e-16 -0.171296 2.78542 + N0 0.193465 -0.721244 -0.665116 N1 2.42292e-15 -0.747409 -0.664364 N2 2.16507e-15 -0.950775 -0.309882 + txt003 +STRI + V0 -6.66134e-16 -0.171296 2.78542 V1 0.0460445 -0.165279 2.78542 V2 0.0638032 -0.228728 2.88333 + N0 2.16507e-15 -0.950775 -0.309882 N1 0.246906 -0.917897 -0.310647 N2 0.193465 -0.721244 -0.665116 + txt003 +STRI + V0 0.171296 0 2.78542 V1 0.165279 -0.0460445 2.78542 V2 0.192963 -0.0537037 2.7 + N0 0.950775 0 -0.309882 N1 0.917897 -0.246906 -0.310647 N2 0.578783 -0.15602 0.800417 + txt003 +STRI + V0 0.192963 -0.0537037 2.7 V1 0.2 0 2.7 V2 0.171296 0 2.78542 + N0 0.578783 -0.15602 0.800417 N1 0.6 0 0.8 N2 0.950775 0 -0.309882 + txt003 +STRI + V0 0.165279 -0.0460445 2.78542 V1 0.148234 -0.0871056 2.78542 V2 0.173037 -0.10163 2.7 + N0 0.917897 -0.246906 -0.310647 N1 0.822132 -0.476337 -0.311772 N2 0.517905 -0.300385 0.800964 + txt003 +STRI + V0 0.173037 -0.10163 2.7 V1 0.192963 -0.0537037 2.7 V2 0.165279 -0.0460445 2.78542 + N0 0.517905 -0.300385 0.800964 N1 0.578783 -0.15602 0.800417 N2 0.917897 -0.246906 -0.310647 + txt003 +STRI + V0 0.148234 -0.0871056 2.78542 V1 0.121672 -0.121672 2.78542 V2 0.142 -0.142 2.7 + N0 0.822132 -0.476337 -0.311772 N1 0.671754 -0.671754 -0.312241 N2 0.423155 -0.423155 0.801174 + txt003 +STRI + V0 0.142 -0.142 2.7 V1 0.173037 -0.10163 2.7 V2 0.148234 -0.0871056 2.78542 + N0 0.423155 -0.423155 0.801174 N1 0.517905 -0.300385 0.800964 N2 0.822132 -0.476337 -0.311772 + txt003 +STRI + V0 0.121672 -0.121672 2.78542 V1 0.0871056 -0.148234 2.78542 V2 0.10163 -0.173037 2.7 + N0 0.671754 -0.671754 -0.312241 N1 0.476337 -0.822132 -0.311772 N2 0.300385 -0.517905 0.800964 + txt003 +STRI + V0 0.10163 -0.173037 2.7 V1 0.142 -0.142 2.7 V2 0.121672 -0.121672 2.78542 + N0 0.300385 -0.517905 0.800964 N1 0.423155 -0.423155 0.801174 N2 0.671754 -0.671754 -0.312241 + txt003 +STRI + V0 0.0871056 -0.148234 2.78542 V1 0.0460445 -0.165279 2.78542 V2 0.0537037 -0.192963 2.7 + N0 0.476337 -0.822132 -0.311772 N1 0.246906 -0.917897 -0.310647 N2 0.15602 -0.578783 0.800417 + txt003 +STRI + V0 0.0537037 -0.192963 2.7 V1 0.10163 -0.173037 2.7 V2 0.0871056 -0.148234 2.78542 + N0 0.15602 -0.578783 0.800417 N1 0.300385 -0.517905 0.800964 N2 0.476337 -0.822132 -0.311772 + txt003 +STRI + V0 0.0460445 -0.165279 2.78542 V1 -6.66134e-16 -0.171296 2.78542 V2 0 -0.2 2.7 + N0 0.246906 -0.917897 -0.310647 N1 2.16507e-15 -0.950775 -0.309882 N2 -3.17207e-15 -0.6 0.8 + txt003 +STRI + V0 0 -0.2 2.7 V1 0.0537037 -0.192963 2.7 V2 0.0460445 -0.165279 2.78542 + N0 -3.17207e-15 -0.6 0.8 N1 0.15602 -0.578783 0.800417 N2 0.246906 -0.917897 -0.310647 + txt003 +STRI + V0 -0.0750782 -0.268946 3.12708 V1 0 -0.278704 3.12708 V2 0 0 3.15 + N0 -0.0645609 -0.241077 0.968356 N1 0 -0.249998 0.968246 N2 0 0 1 + txt003 +STRI + V0 -0.141931 -0.241285 3.12708 V1 -0.0750782 -0.268946 3.12708 V2 0 0 3.15 + N0 -0.124615 -0.215548 0.968509 N1 -0.0645609 -0.241077 0.968356 N2 0 0 1 + txt003 +STRI + V0 -0.19814 -0.19814 3.12708 V1 -0.141931 -0.241285 3.12708 V2 0 0 3.15 + N0 -0.175885 -0.175885 0.96857 N1 -0.124615 -0.215548 0.968509 N2 0 0 1 + txt003 +STRI + V0 -0.241285 -0.141931 3.12708 V1 -0.19814 -0.19814 3.12708 V2 0 0 3.15 + N0 -0.215548 -0.124615 0.968509 N1 -0.175885 -0.175885 0.96857 N2 0 0 1 + txt003 +STRI + V0 -0.268946 -0.0750782 3.12708 V1 -0.241285 -0.141931 3.12708 V2 0 0 3.15 + N0 -0.241077 -0.0645609 0.968356 N1 -0.215548 -0.124615 0.968509 N2 0 0 1 + txt003 +STRI + V0 -0.278704 0 3.12708 V1 -0.268946 -0.0750782 3.12708 V2 0 0 3.15 + N0 -0.249998 2.80184e-15 0.968246 N1 -0.241077 -0.0645609 0.968356 N2 0 0 1 + txt003 +STRI + V0 0 -0.278704 3.12708 V1 -0.0750782 -0.268946 3.12708 V2 -0.0977709 -0.350254 3.06667 + N0 0 -0.249998 0.968246 N1 -0.0645609 -0.241077 0.968356 N2 -0.255913 -0.955496 0.146755 + txt003 +STRI + V0 -0.0977709 -0.350254 3.06667 V1 0 -0.362963 3.06667 V2 0 -0.278704 3.12708 + N0 -0.255913 -0.955496 0.146755 N1 0 -0.989203 0.146549 N2 0 -0.249998 0.968246 + txt003 +STRI + V0 -0.0750782 -0.268946 3.12708 V1 -0.141931 -0.241285 3.12708 V2 -0.184834 -0.314228 3.06667 + N0 -0.0645609 -0.241077 0.968356 N1 -0.124615 -0.215548 0.968509 N2 -0.495088 -0.856312 0.147029 + txt003 +STRI + V0 -0.184834 -0.314228 3.06667 V1 -0.0977709 -0.350254 3.06667 V2 -0.0750782 -0.268946 3.12708 + N0 -0.495088 -0.856312 0.147029 N1 -0.255913 -0.955496 0.146755 N2 -0.0645609 -0.241077 0.968356 + txt003 +STRI + V0 -0.141931 -0.241285 3.12708 V1 -0.19814 -0.19814 3.12708 V2 -0.258037 -0.258037 3.06667 + N0 -0.124615 -0.215548 0.968509 N1 -0.175885 -0.175885 0.96857 N2 -0.699411 -0.699411 0.147135 + txt003 +STRI + V0 -0.258037 -0.258037 3.06667 V1 -0.184834 -0.314228 3.06667 V2 -0.141931 -0.241285 3.12708 + N0 -0.699411 -0.699411 0.147135 N1 -0.495088 -0.856312 0.147029 N2 -0.124615 -0.215548 0.968509 + txt003 +STRI + V0 -0.19814 -0.19814 3.12708 V1 -0.241285 -0.141931 3.12708 V2 -0.314228 -0.184834 3.06667 + N0 -0.175885 -0.175885 0.96857 N1 -0.215548 -0.124615 0.968509 N2 -0.856312 -0.495088 0.147029 + txt003 +STRI + V0 -0.314228 -0.184834 3.06667 V1 -0.258037 -0.258037 3.06667 V2 -0.19814 -0.19814 3.12708 + N0 -0.856312 -0.495088 0.147029 N1 -0.699411 -0.699411 0.147135 N2 -0.175885 -0.175885 0.96857 + txt003 +STRI + V0 -0.241285 -0.141931 3.12708 V1 -0.268946 -0.0750782 3.12708 V2 -0.350254 -0.0977709 3.06667 + N0 -0.215548 -0.124615 0.968509 N1 -0.241077 -0.0645609 0.968356 N2 -0.955496 -0.255913 0.146755 + txt003 +STRI + V0 -0.350254 -0.0977709 3.06667 V1 -0.314228 -0.184834 3.06667 V2 -0.241285 -0.141931 3.12708 + N0 -0.955496 -0.255913 0.146755 N1 -0.856312 -0.495088 0.147029 N2 -0.215548 -0.124615 0.968509 + txt003 +STRI + V0 -0.268946 -0.0750782 3.12708 V1 -0.278704 0 3.12708 V2 -0.362963 0 3.06667 + N0 -0.241077 -0.0645609 0.968356 N1 -0.249998 2.80184e-15 0.968246 N2 -0.989203 4.98112e-16 0.146549 + txt003 +STRI + V0 -0.362963 0 3.06667 V1 -0.350254 -0.0977709 3.06667 V2 -0.268946 -0.0750782 3.12708 + N0 -0.989203 4.98112e-16 0.146549 N1 -0.955496 -0.255913 0.146755 N2 -0.241077 -0.0645609 0.968356 + txt003 +STRI + V0 0 -0.362963 3.06667 V1 -0.0977709 -0.350254 3.06667 V2 -0.0875289 -0.313617 2.98125 + N0 0 -0.989203 0.146549 N1 -0.255913 -0.955496 0.146755 N2 -0.201937 -0.753688 -0.625441 + txt003 +STRI + V0 -0.0875289 -0.313617 2.98125 V1 0 -0.325 2.98125 V2 0 -0.362963 3.06667 + N0 -0.201937 -0.753688 -0.625441 N1 -0 -0.780869 -0.624695 N2 0 -0.989203 0.146549 + txt003 +STRI + V0 -0.0977709 -0.350254 3.06667 V1 -0.184834 -0.314228 3.06667 V2 -0.165481 -0.281352 2.98125 + N0 -0.255913 -0.955496 0.146755 N1 -0.495088 -0.856312 0.147029 N2 -0.390178 -0.674735 -0.626493 + txt003 +STRI + V0 -0.165481 -0.281352 2.98125 V1 -0.0875289 -0.313617 2.98125 V2 -0.0977709 -0.350254 3.06667 + N0 -0.390178 -0.674735 -0.626493 N1 -0.201937 -0.753688 -0.625441 N2 -0.255913 -0.955496 0.146755 + txt003 +STRI + V0 -0.184834 -0.314228 3.06667 V1 -0.258037 -0.258037 3.06667 V2 -0.231031 -0.231031 2.98125 + N0 -0.495088 -0.856312 0.147029 N1 -0.699411 -0.699411 0.147135 N2 -0.550896 -0.550896 -0.626919 + txt003 +STRI + V0 -0.231031 -0.231031 2.98125 V1 -0.165481 -0.281352 2.98125 V2 -0.184834 -0.314228 3.06667 + N0 -0.550896 -0.550896 -0.626919 N1 -0.390178 -0.674735 -0.626493 N2 -0.495088 -0.856312 0.147029 + txt003 +STRI + V0 -0.258037 -0.258037 3.06667 V1 -0.314228 -0.184834 3.06667 V2 -0.281352 -0.165481 2.98125 + N0 -0.699411 -0.699411 0.147135 N1 -0.856312 -0.495088 0.147029 N2 -0.674735 -0.390178 -0.626493 + txt003 +STRI + V0 -0.281352 -0.165481 2.98125 V1 -0.231031 -0.231031 2.98125 V2 -0.258037 -0.258037 3.06667 + N0 -0.674735 -0.390178 -0.626493 N1 -0.550896 -0.550896 -0.626919 N2 -0.699411 -0.699411 0.147135 + txt003 +STRI + V0 -0.314228 -0.184834 3.06667 V1 -0.350254 -0.0977709 3.06667 V2 -0.313617 -0.0875289 2.98125 + N0 -0.856312 -0.495088 0.147029 N1 -0.955496 -0.255913 0.146755 N2 -0.753688 -0.201937 -0.625441 + txt003 +STRI + V0 -0.313617 -0.0875289 2.98125 V1 -0.281352 -0.165481 2.98125 V2 -0.314228 -0.184834 3.06667 + N0 -0.753688 -0.201937 -0.625441 N1 -0.674735 -0.390178 -0.626493 N2 -0.856312 -0.495088 0.147029 + txt003 +STRI + V0 -0.350254 -0.0977709 3.06667 V1 -0.362963 0 3.06667 V2 -0.325 1.11022e-16 2.98125 + N0 -0.955496 -0.255913 0.146755 N1 -0.989203 4.98112e-16 0.146549 N2 -0.780869 -1.51803e-15 -0.624695 + txt003 +STRI + V0 -0.325 1.11022e-16 2.98125 V1 -0.313617 -0.0875289 2.98125 V2 -0.350254 -0.0977709 3.06667 + N0 -0.780869 -1.51803e-15 -0.624695 N1 -0.753688 -0.201937 -0.625441 N2 -0.955496 -0.255913 0.146755 + txt003 +STRI + V0 0 -0.325 2.98125 V1 -0.0875289 -0.313617 2.98125 V2 -0.0638032 -0.228728 2.88333 + N0 -0 -0.780869 -0.624695 N1 -0.201937 -0.753688 -0.625441 N2 -0.193465 -0.721244 -0.665116 + txt003 +STRI + V0 -0.0638032 -0.228728 2.88333 V1 0 -0.237037 2.88333 V2 0 -0.325 2.98125 + N0 -0.193465 -0.721244 -0.665116 N1 -0 -0.747409 -0.664364 N2 -0 -0.780869 -0.624695 + txt003 +STRI + V0 -0.0875289 -0.313617 2.98125 V1 -0.165481 -0.281352 2.98125 V2 -0.120647 -0.20518 2.88333 + N0 -0.201937 -0.753688 -0.625441 N1 -0.390178 -0.674735 -0.626493 N2 -0.373497 -0.645526 -0.66618 + txt003 +STRI + V0 -0.120647 -0.20518 2.88333 V1 -0.0638032 -0.228728 2.88333 V2 -0.0875289 -0.313617 2.98125 + N0 -0.373497 -0.645526 -0.66618 N1 -0.193465 -0.721244 -0.665116 N2 -0.201937 -0.753688 -0.625441 + txt003 +STRI + V0 -0.165481 -0.281352 2.98125 V1 -0.231031 -0.231031 2.98125 V2 -0.168463 -0.168463 2.88333 + N0 -0.390178 -0.674735 -0.626493 N1 -0.550896 -0.550896 -0.626919 N2 -0.527081 -0.527081 -0.666611 + txt003 +STRI + V0 -0.168463 -0.168463 2.88333 V1 -0.120647 -0.20518 2.88333 V2 -0.165481 -0.281352 2.98125 + N0 -0.527081 -0.527081 -0.666611 N1 -0.373497 -0.645526 -0.66618 N2 -0.390178 -0.674735 -0.626493 + txt003 +STRI + V0 -0.231031 -0.231031 2.98125 V1 -0.281352 -0.165481 2.98125 V2 -0.20518 -0.120647 2.88333 + N0 -0.550896 -0.550896 -0.626919 N1 -0.674735 -0.390178 -0.626493 N2 -0.645526 -0.373497 -0.66618 + txt003 +STRI + V0 -0.20518 -0.120647 2.88333 V1 -0.168463 -0.168463 2.88333 V2 -0.231031 -0.231031 2.98125 + N0 -0.645526 -0.373497 -0.66618 N1 -0.527081 -0.527081 -0.666611 N2 -0.550896 -0.550896 -0.626919 + txt003 +STRI + V0 -0.281352 -0.165481 2.98125 V1 -0.313617 -0.0875289 2.98125 V2 -0.228728 -0.0638032 2.88333 + N0 -0.674735 -0.390178 -0.626493 N1 -0.753688 -0.201937 -0.625441 N2 -0.721244 -0.193465 -0.665116 + txt003 +STRI + V0 -0.228728 -0.0638032 2.88333 V1 -0.20518 -0.120647 2.88333 V2 -0.281352 -0.165481 2.98125 + N0 -0.721244 -0.193465 -0.665116 N1 -0.645526 -0.373497 -0.66618 N2 -0.674735 -0.390178 -0.626493 + txt003 +STRI + V0 -0.313617 -0.0875289 2.98125 V1 -0.325 1.11022e-16 2.98125 V2 -0.237037 1.11022e-16 2.88333 + N0 -0.753688 -0.201937 -0.625441 N1 -0.780869 -1.51803e-15 -0.624695 N2 -0.747409 -2.42292e-15 -0.664364 + txt003 +STRI + V0 -0.237037 1.11022e-16 2.88333 V1 -0.228728 -0.0638032 2.88333 V2 -0.313617 -0.0875289 2.98125 + N0 -0.747409 -2.42292e-15 -0.664364 N1 -0.721244 -0.193465 -0.665116 N2 -0.753688 -0.201937 -0.625441 + txt003 +STRI + V0 0 -0.237037 2.88333 V1 -0.0638032 -0.228728 2.88333 V2 -0.0460445 -0.165279 2.78542 + N0 -0 -0.747409 -0.664364 N1 -0.193465 -0.721244 -0.665116 N2 -0.246906 -0.917897 -0.310647 + txt003 +STRI + V0 -0.0460445 -0.165279 2.78542 V1 0 -0.171296 2.78542 V2 0 -0.237037 2.88333 + N0 -0.246906 -0.917897 -0.310647 N1 -0 -0.950775 -0.309882 N2 -0 -0.747409 -0.664364 + txt003 +STRI + V0 -0.0638032 -0.228728 2.88333 V1 -0.120647 -0.20518 2.88333 V2 -0.0871056 -0.148234 2.78542 + N0 -0.193465 -0.721244 -0.665116 N1 -0.373497 -0.645526 -0.66618 N2 -0.476337 -0.822132 -0.311772 + txt003 +STRI + V0 -0.0871056 -0.148234 2.78542 V1 -0.0460445 -0.165279 2.78542 V2 -0.0638032 -0.228728 2.88333 + N0 -0.476337 -0.822132 -0.311772 N1 -0.246906 -0.917897 -0.310647 N2 -0.193465 -0.721244 -0.665116 + txt003 +STRI + V0 -0.120647 -0.20518 2.88333 V1 -0.168463 -0.168463 2.88333 V2 -0.121672 -0.121672 2.78542 + N0 -0.373497 -0.645526 -0.66618 N1 -0.527081 -0.527081 -0.666611 N2 -0.671754 -0.671754 -0.312241 + txt003 +STRI + V0 -0.121672 -0.121672 2.78542 V1 -0.0871056 -0.148234 2.78542 V2 -0.120647 -0.20518 2.88333 + N0 -0.671754 -0.671754 -0.312241 N1 -0.476337 -0.822132 -0.311772 N2 -0.373497 -0.645526 -0.66618 + txt003 +STRI + V0 -0.168463 -0.168463 2.88333 V1 -0.20518 -0.120647 2.88333 V2 -0.148234 -0.0871056 2.78542 + N0 -0.527081 -0.527081 -0.666611 N1 -0.645526 -0.373497 -0.66618 N2 -0.822132 -0.476337 -0.311772 + txt003 +STRI + V0 -0.148234 -0.0871056 2.78542 V1 -0.121672 -0.121672 2.78542 V2 -0.168463 -0.168463 2.88333 + N0 -0.822132 -0.476337 -0.311772 N1 -0.671754 -0.671754 -0.312241 N2 -0.527081 -0.527081 -0.666611 + txt003 +STRI + V0 -0.20518 -0.120647 2.88333 V1 -0.228728 -0.0638032 2.88333 V2 -0.165279 -0.0460445 2.78542 + N0 -0.645526 -0.373497 -0.66618 N1 -0.721244 -0.193465 -0.665116 N2 -0.917897 -0.246906 -0.310647 + txt003 +STRI + V0 -0.165279 -0.0460445 2.78542 V1 -0.148234 -0.0871056 2.78542 V2 -0.20518 -0.120647 2.88333 + N0 -0.917897 -0.246906 -0.310647 N1 -0.822132 -0.476337 -0.311772 N2 -0.645526 -0.373497 -0.66618 + txt003 +STRI + V0 -0.228728 -0.0638032 2.88333 V1 -0.237037 1.11022e-16 2.88333 V2 -0.171296 6.66134e-16 2.78542 + N0 -0.721244 -0.193465 -0.665116 N1 -0.747409 -2.42292e-15 -0.664364 N2 -0.950775 -2.16507e-15 -0.309882 + txt003 +STRI + V0 -0.171296 6.66134e-16 2.78542 V1 -0.165279 -0.0460445 2.78542 V2 -0.228728 -0.0638032 2.88333 + N0 -0.950775 -2.16507e-15 -0.309882 N1 -0.917897 -0.246906 -0.310647 N2 -0.721244 -0.193465 -0.665116 + txt003 +STRI + V0 0 -0.171296 2.78542 V1 -0.0460445 -0.165279 2.78542 V2 -0.0537037 -0.192963 2.7 + N0 -0 -0.950775 -0.309882 N1 -0.246906 -0.917897 -0.310647 N2 -0.15602 -0.578783 0.800417 + txt003 +STRI + V0 -0.0537037 -0.192963 2.7 V1 0 -0.2 2.7 V2 0 -0.171296 2.78542 + N0 -0.15602 -0.578783 0.800417 N1 0 -0.6 0.8 N2 -0 -0.950775 -0.309882 + txt003 +STRI + V0 -0.0460445 -0.165279 2.78542 V1 -0.0871056 -0.148234 2.78542 V2 -0.10163 -0.173037 2.7 + N0 -0.246906 -0.917897 -0.310647 N1 -0.476337 -0.822132 -0.311772 N2 -0.300385 -0.517905 0.800964 + txt003 +STRI + V0 -0.10163 -0.173037 2.7 V1 -0.0537037 -0.192963 2.7 V2 -0.0460445 -0.165279 2.78542 + N0 -0.300385 -0.517905 0.800964 N1 -0.15602 -0.578783 0.800417 N2 -0.246906 -0.917897 -0.310647 + txt003 +STRI + V0 -0.0871056 -0.148234 2.78542 V1 -0.121672 -0.121672 2.78542 V2 -0.142 -0.142 2.7 + N0 -0.476337 -0.822132 -0.311772 N1 -0.671754 -0.671754 -0.312241 N2 -0.423155 -0.423155 0.801174 + txt003 +STRI + V0 -0.142 -0.142 2.7 V1 -0.10163 -0.173037 2.7 V2 -0.0871056 -0.148234 2.78542 + N0 -0.423155 -0.423155 0.801174 N1 -0.300385 -0.517905 0.800964 N2 -0.476337 -0.822132 -0.311772 + txt003 +STRI + V0 -0.121672 -0.121672 2.78542 V1 -0.148234 -0.0871056 2.78542 V2 -0.173037 -0.10163 2.7 + N0 -0.671754 -0.671754 -0.312241 N1 -0.822132 -0.476337 -0.311772 N2 -0.517905 -0.300385 0.800964 + txt003 +STRI + V0 -0.173037 -0.10163 2.7 V1 -0.142 -0.142 2.7 V2 -0.121672 -0.121672 2.78542 + N0 -0.517905 -0.300385 0.800964 N1 -0.423155 -0.423155 0.801174 N2 -0.671754 -0.671754 -0.312241 + txt003 +STRI + V0 -0.148234 -0.0871056 2.78542 V1 -0.165279 -0.0460445 2.78542 V2 -0.192963 -0.0537037 2.7 + N0 -0.822132 -0.476337 -0.311772 N1 -0.917897 -0.246906 -0.310647 N2 -0.578783 -0.15602 0.800417 + txt003 +STRI + V0 -0.192963 -0.0537037 2.7 V1 -0.173037 -0.10163 2.7 V2 -0.148234 -0.0871056 2.78542 + N0 -0.578783 -0.15602 0.800417 N1 -0.517905 -0.300385 0.800964 N2 -0.822132 -0.476337 -0.311772 + txt003 +STRI + V0 -0.165279 -0.0460445 2.78542 V1 -0.171296 6.66134e-16 2.78542 V2 -0.2 0 2.7 + N0 -0.917897 -0.246906 -0.310647 N1 -0.950775 -2.16507e-15 -0.309882 N2 -0.6 3.17207e-15 0.8 + txt003 +STRI + V0 -0.2 0 2.7 V1 -0.192963 -0.0537037 2.7 V2 -0.165279 -0.0460445 2.78542 + N0 -0.6 3.17207e-15 0.8 N1 -0.578783 -0.15602 0.800417 N2 -0.917897 -0.246906 -0.310647 + txt003 +STRI + V0 -0.268946 0.0750782 3.12708 V1 -0.278704 0 3.12708 V2 0 0 3.15 + N0 -0.241077 0.0645609 0.968356 N1 -0.249998 0 0.968246 N2 0 0 1 + txt003 +STRI + V0 -0.241285 0.141931 3.12708 V1 -0.268946 0.0750782 3.12708 V2 0 0 3.15 + N0 -0.215548 0.124615 0.968509 N1 -0.241077 0.0645609 0.968356 N2 0 0 1 + txt003 +STRI + V0 -0.19814 0.19814 3.12708 V1 -0.241285 0.141931 3.12708 V2 0 0 3.15 + N0 -0.175885 0.175885 0.96857 N1 -0.215548 0.124615 0.968509 N2 0 0 1 + txt003 +STRI + V0 -0.141931 0.241285 3.12708 V1 -0.19814 0.19814 3.12708 V2 0 0 3.15 + N0 -0.124615 0.215548 0.968509 N1 -0.175885 0.175885 0.96857 N2 0 0 1 + txt003 +STRI + V0 -0.0750782 0.268946 3.12708 V1 -0.141931 0.241285 3.12708 V2 0 0 3.15 + N0 -0.0645609 0.241077 0.968356 N1 -0.124615 0.215548 0.968509 N2 0 0 1 + txt003 +STRI + V0 0 0.278704 3.12708 V1 -0.0750782 0.268946 3.12708 V2 0 0 3.15 + N0 2.80184e-15 0.249998 0.968246 N1 -0.0645609 0.241077 0.968356 N2 0 0 1 + txt003 +STRI + V0 -0.278704 0 3.12708 V1 -0.268946 0.0750782 3.12708 V2 -0.350254 0.0977709 3.06667 + N0 -0.249998 0 0.968246 N1 -0.241077 0.0645609 0.968356 N2 -0.955496 0.255913 0.146755 + txt003 +STRI + V0 -0.350254 0.0977709 3.06667 V1 -0.362963 0 3.06667 V2 -0.278704 0 3.12708 + N0 -0.955496 0.255913 0.146755 N1 -0.989203 0 0.146549 N2 -0.249998 0 0.968246 + txt003 +STRI + V0 -0.268946 0.0750782 3.12708 V1 -0.241285 0.141931 3.12708 V2 -0.314228 0.184834 3.06667 + N0 -0.241077 0.0645609 0.968356 N1 -0.215548 0.124615 0.968509 N2 -0.856312 0.495088 0.147029 + txt003 +STRI + V0 -0.314228 0.184834 3.06667 V1 -0.350254 0.0977709 3.06667 V2 -0.268946 0.0750782 3.12708 + N0 -0.856312 0.495088 0.147029 N1 -0.955496 0.255913 0.146755 N2 -0.241077 0.0645609 0.968356 + txt003 +STRI + V0 -0.241285 0.141931 3.12708 V1 -0.19814 0.19814 3.12708 V2 -0.258037 0.258037 3.06667 + N0 -0.215548 0.124615 0.968509 N1 -0.175885 0.175885 0.96857 N2 -0.699411 0.699411 0.147135 + txt003 +STRI + V0 -0.258037 0.258037 3.06667 V1 -0.314228 0.184834 3.06667 V2 -0.241285 0.141931 3.12708 + N0 -0.699411 0.699411 0.147135 N1 -0.856312 0.495088 0.147029 N2 -0.215548 0.124615 0.968509 + txt003 +STRI + V0 -0.19814 0.19814 3.12708 V1 -0.141931 0.241285 3.12708 V2 -0.184834 0.314228 3.06667 + N0 -0.175885 0.175885 0.96857 N1 -0.124615 0.215548 0.968509 N2 -0.495088 0.856312 0.147029 + txt003 +STRI + V0 -0.184834 0.314228 3.06667 V1 -0.258037 0.258037 3.06667 V2 -0.19814 0.19814 3.12708 + N0 -0.495088 0.856312 0.147029 N1 -0.699411 0.699411 0.147135 N2 -0.175885 0.175885 0.96857 + txt003 +STRI + V0 -0.141931 0.241285 3.12708 V1 -0.0750782 0.268946 3.12708 V2 -0.0977709 0.350254 3.06667 + N0 -0.124615 0.215548 0.968509 N1 -0.0645609 0.241077 0.968356 N2 -0.255913 0.955496 0.146755 + txt003 +STRI + V0 -0.0977709 0.350254 3.06667 V1 -0.184834 0.314228 3.06667 V2 -0.141931 0.241285 3.12708 + N0 -0.255913 0.955496 0.146755 N1 -0.495088 0.856312 0.147029 N2 -0.124615 0.215548 0.968509 + txt003 +STRI + V0 -0.0750782 0.268946 3.12708 V1 0 0.278704 3.12708 V2 0 0.362963 3.06667 + N0 -0.0645609 0.241077 0.968356 N1 2.80184e-15 0.249998 0.968246 N2 4.98112e-16 0.989203 0.146549 + txt003 +STRI + V0 0 0.362963 3.06667 V1 -0.0977709 0.350254 3.06667 V2 -0.0750782 0.268946 3.12708 + N0 4.98112e-16 0.989203 0.146549 N1 -0.255913 0.955496 0.146755 N2 -0.0645609 0.241077 0.968356 + txt003 +STRI + V0 -0.362963 0 3.06667 V1 -0.350254 0.0977709 3.06667 V2 -0.313617 0.0875289 2.98125 + N0 -0.989203 0 0.146549 N1 -0.955496 0.255913 0.146755 N2 -0.753688 0.201937 -0.625441 + txt003 +STRI + V0 -0.313617 0.0875289 2.98125 V1 -0.325 0 2.98125 V2 -0.362963 0 3.06667 + N0 -0.753688 0.201937 -0.625441 N1 -0.780869 0 -0.624695 N2 -0.989203 0 0.146549 + txt003 +STRI + V0 -0.350254 0.0977709 3.06667 V1 -0.314228 0.184834 3.06667 V2 -0.281352 0.165481 2.98125 + N0 -0.955496 0.255913 0.146755 N1 -0.856312 0.495088 0.147029 N2 -0.674735 0.390178 -0.626493 + txt003 +STRI + V0 -0.281352 0.165481 2.98125 V1 -0.313617 0.0875289 2.98125 V2 -0.350254 0.0977709 3.06667 + N0 -0.674735 0.390178 -0.626493 N1 -0.753688 0.201937 -0.625441 N2 -0.955496 0.255913 0.146755 + txt003 +STRI + V0 -0.314228 0.184834 3.06667 V1 -0.258037 0.258037 3.06667 V2 -0.231031 0.231031 2.98125 + N0 -0.856312 0.495088 0.147029 N1 -0.699411 0.699411 0.147135 N2 -0.550896 0.550896 -0.626919 + txt003 +STRI + V0 -0.231031 0.231031 2.98125 V1 -0.281352 0.165481 2.98125 V2 -0.314228 0.184834 3.06667 + N0 -0.550896 0.550896 -0.626919 N1 -0.674735 0.390178 -0.626493 N2 -0.856312 0.495088 0.147029 + txt003 +STRI + V0 -0.258037 0.258037 3.06667 V1 -0.184834 0.314228 3.06667 V2 -0.165481 0.281352 2.98125 + N0 -0.699411 0.699411 0.147135 N1 -0.495088 0.856312 0.147029 N2 -0.390178 0.674735 -0.626493 + txt003 +STRI + V0 -0.165481 0.281352 2.98125 V1 -0.231031 0.231031 2.98125 V2 -0.258037 0.258037 3.06667 + N0 -0.390178 0.674735 -0.626493 N1 -0.550896 0.550896 -0.626919 N2 -0.699411 0.699411 0.147135 + txt003 +STRI + V0 -0.184834 0.314228 3.06667 V1 -0.0977709 0.350254 3.06667 V2 -0.0875289 0.313617 2.98125 + N0 -0.495088 0.856312 0.147029 N1 -0.255913 0.955496 0.146755 N2 -0.201937 0.753688 -0.625441 + txt003 +STRI + V0 -0.0875289 0.313617 2.98125 V1 -0.165481 0.281352 2.98125 V2 -0.184834 0.314228 3.06667 + N0 -0.201937 0.753688 -0.625441 N1 -0.390178 0.674735 -0.626493 N2 -0.495088 0.856312 0.147029 + txt003 +STRI + V0 -0.0977709 0.350254 3.06667 V1 0 0.362963 3.06667 V2 1.11022e-16 0.325 2.98125 + N0 -0.255913 0.955496 0.146755 N1 4.98112e-16 0.989203 0.146549 N2 -1.51803e-15 0.780869 -0.624695 + txt003 +STRI + V0 1.11022e-16 0.325 2.98125 V1 -0.0875289 0.313617 2.98125 V2 -0.0977709 0.350254 3.06667 + N0 -1.51803e-15 0.780869 -0.624695 N1 -0.201937 0.753688 -0.625441 N2 -0.255913 0.955496 0.146755 + txt003 +STRI + V0 -0.325 0 2.98125 V1 -0.313617 0.0875289 2.98125 V2 -0.228728 0.0638032 2.88333 + N0 -0.780869 0 -0.624695 N1 -0.753688 0.201937 -0.625441 N2 -0.721244 0.193465 -0.665116 + txt003 +STRI + V0 -0.228728 0.0638032 2.88333 V1 -0.237037 0 2.88333 V2 -0.325 0 2.98125 + N0 -0.721244 0.193465 -0.665116 N1 -0.747409 0 -0.664364 N2 -0.780869 0 -0.624695 + txt003 +STRI + V0 -0.313617 0.0875289 2.98125 V1 -0.281352 0.165481 2.98125 V2 -0.20518 0.120647 2.88333 + N0 -0.753688 0.201937 -0.625441 N1 -0.674735 0.390178 -0.626493 N2 -0.645526 0.373497 -0.66618 + txt003 +STRI + V0 -0.20518 0.120647 2.88333 V1 -0.228728 0.0638032 2.88333 V2 -0.313617 0.0875289 2.98125 + N0 -0.645526 0.373497 -0.66618 N1 -0.721244 0.193465 -0.665116 N2 -0.753688 0.201937 -0.625441 + txt003 +STRI + V0 -0.281352 0.165481 2.98125 V1 -0.231031 0.231031 2.98125 V2 -0.168463 0.168463 2.88333 + N0 -0.674735 0.390178 -0.626493 N1 -0.550896 0.550896 -0.626919 N2 -0.527081 0.527081 -0.666611 + txt003 +STRI + V0 -0.168463 0.168463 2.88333 V1 -0.20518 0.120647 2.88333 V2 -0.281352 0.165481 2.98125 + N0 -0.527081 0.527081 -0.666611 N1 -0.645526 0.373497 -0.66618 N2 -0.674735 0.390178 -0.626493 + txt003 +STRI + V0 -0.231031 0.231031 2.98125 V1 -0.165481 0.281352 2.98125 V2 -0.120647 0.20518 2.88333 + N0 -0.550896 0.550896 -0.626919 N1 -0.390178 0.674735 -0.626493 N2 -0.373497 0.645526 -0.66618 + txt003 +STRI + V0 -0.120647 0.20518 2.88333 V1 -0.168463 0.168463 2.88333 V2 -0.231031 0.231031 2.98125 + N0 -0.373497 0.645526 -0.66618 N1 -0.527081 0.527081 -0.666611 N2 -0.550896 0.550896 -0.626919 + txt003 +STRI + V0 -0.165481 0.281352 2.98125 V1 -0.0875289 0.313617 2.98125 V2 -0.0638032 0.228728 2.88333 + N0 -0.390178 0.674735 -0.626493 N1 -0.201937 0.753688 -0.625441 N2 -0.193465 0.721244 -0.665116 + txt003 +STRI + V0 -0.0638032 0.228728 2.88333 V1 -0.120647 0.20518 2.88333 V2 -0.165481 0.281352 2.98125 + N0 -0.193465 0.721244 -0.665116 N1 -0.373497 0.645526 -0.66618 N2 -0.390178 0.674735 -0.626493 + txt003 +STRI + V0 -0.0875289 0.313617 2.98125 V1 1.11022e-16 0.325 2.98125 V2 1.11022e-16 0.237037 2.88333 + N0 -0.201937 0.753688 -0.625441 N1 -1.51803e-15 0.780869 -0.624695 N2 -2.42292e-15 0.747409 -0.664364 + txt003 +STRI + V0 1.11022e-16 0.237037 2.88333 V1 -0.0638032 0.228728 2.88333 V2 -0.0875289 0.313617 2.98125 + N0 -2.42292e-15 0.747409 -0.664364 N1 -0.193465 0.721244 -0.665116 N2 -0.201937 0.753688 -0.625441 + txt003 +STRI + V0 -0.237037 0 2.88333 V1 -0.228728 0.0638032 2.88333 V2 -0.165279 0.0460445 2.78542 + N0 -0.747409 0 -0.664364 N1 -0.721244 0.193465 -0.665116 N2 -0.917897 0.246906 -0.310647 + txt003 +STRI + V0 -0.165279 0.0460445 2.78542 V1 -0.171296 0 2.78542 V2 -0.237037 0 2.88333 + N0 -0.917897 0.246906 -0.310647 N1 -0.950775 0 -0.309882 N2 -0.747409 0 -0.664364 + txt003 +STRI + V0 -0.228728 0.0638032 2.88333 V1 -0.20518 0.120647 2.88333 V2 -0.148234 0.0871056 2.78542 + N0 -0.721244 0.193465 -0.665116 N1 -0.645526 0.373497 -0.66618 N2 -0.822132 0.476337 -0.311772 + txt003 +STRI + V0 -0.148234 0.0871056 2.78542 V1 -0.165279 0.0460445 2.78542 V2 -0.228728 0.0638032 2.88333 + N0 -0.822132 0.476337 -0.311772 N1 -0.917897 0.246906 -0.310647 N2 -0.721244 0.193465 -0.665116 + txt003 +STRI + V0 -0.20518 0.120647 2.88333 V1 -0.168463 0.168463 2.88333 V2 -0.121672 0.121672 2.78542 + N0 -0.645526 0.373497 -0.66618 N1 -0.527081 0.527081 -0.666611 N2 -0.671754 0.671754 -0.312241 + txt003 +STRI + V0 -0.121672 0.121672 2.78542 V1 -0.148234 0.0871056 2.78542 V2 -0.20518 0.120647 2.88333 + N0 -0.671754 0.671754 -0.312241 N1 -0.822132 0.476337 -0.311772 N2 -0.645526 0.373497 -0.66618 + txt003 +STRI + V0 -0.168463 0.168463 2.88333 V1 -0.120647 0.20518 2.88333 V2 -0.0871056 0.148234 2.78542 + N0 -0.527081 0.527081 -0.666611 N1 -0.373497 0.645526 -0.66618 N2 -0.476337 0.822132 -0.311772 + txt003 +STRI + V0 -0.0871056 0.148234 2.78542 V1 -0.121672 0.121672 2.78542 V2 -0.168463 0.168463 2.88333 + N0 -0.476337 0.822132 -0.311772 N1 -0.671754 0.671754 -0.312241 N2 -0.527081 0.527081 -0.666611 + txt003 +STRI + V0 -0.120647 0.20518 2.88333 V1 -0.0638032 0.228728 2.88333 V2 -0.0460445 0.165279 2.78542 + N0 -0.373497 0.645526 -0.66618 N1 -0.193465 0.721244 -0.665116 N2 -0.246906 0.917897 -0.310647 + txt003 +STRI + V0 -0.0460445 0.165279 2.78542 V1 -0.0871056 0.148234 2.78542 V2 -0.120647 0.20518 2.88333 + N0 -0.246906 0.917897 -0.310647 N1 -0.476337 0.822132 -0.311772 N2 -0.373497 0.645526 -0.66618 + txt003 +STRI + V0 -0.0638032 0.228728 2.88333 V1 1.11022e-16 0.237037 2.88333 V2 6.66134e-16 0.171296 2.78542 + N0 -0.193465 0.721244 -0.665116 N1 -2.42292e-15 0.747409 -0.664364 N2 -2.16507e-15 0.950775 -0.309882 + txt003 +STRI + V0 6.66134e-16 0.171296 2.78542 V1 -0.0460445 0.165279 2.78542 V2 -0.0638032 0.228728 2.88333 + N0 -2.16507e-15 0.950775 -0.309882 N1 -0.246906 0.917897 -0.310647 N2 -0.193465 0.721244 -0.665116 + txt003 +STRI + V0 -0.171296 0 2.78542 V1 -0.165279 0.0460445 2.78542 V2 -0.192963 0.0537037 2.7 + N0 -0.950775 0 -0.309882 N1 -0.917897 0.246906 -0.310647 N2 -0.578783 0.15602 0.800417 + txt003 +STRI + V0 -0.192963 0.0537037 2.7 V1 -0.2 0 2.7 V2 -0.171296 0 2.78542 + N0 -0.578783 0.15602 0.800417 N1 -0.6 0 0.8 N2 -0.950775 0 -0.309882 + txt003 +STRI + V0 -0.165279 0.0460445 2.78542 V1 -0.148234 0.0871056 2.78542 V2 -0.173037 0.10163 2.7 + N0 -0.917897 0.246906 -0.310647 N1 -0.822132 0.476337 -0.311772 N2 -0.517905 0.300385 0.800964 + txt003 +STRI + V0 -0.173037 0.10163 2.7 V1 -0.192963 0.0537037 2.7 V2 -0.165279 0.0460445 2.78542 + N0 -0.517905 0.300385 0.800964 N1 -0.578783 0.15602 0.800417 N2 -0.917897 0.246906 -0.310647 + txt003 +STRI + V0 -0.148234 0.0871056 2.78542 V1 -0.121672 0.121672 2.78542 V2 -0.142 0.142 2.7 + N0 -0.822132 0.476337 -0.311772 N1 -0.671754 0.671754 -0.312241 N2 -0.423155 0.423155 0.801174 + txt003 +STRI + V0 -0.142 0.142 2.7 V1 -0.173037 0.10163 2.7 V2 -0.148234 0.0871056 2.78542 + N0 -0.423155 0.423155 0.801174 N1 -0.517905 0.300385 0.800964 N2 -0.822132 0.476337 -0.311772 + txt003 +STRI + V0 -0.121672 0.121672 2.78542 V1 -0.0871056 0.148234 2.78542 V2 -0.10163 0.173037 2.7 + N0 -0.671754 0.671754 -0.312241 N1 -0.476337 0.822132 -0.311772 N2 -0.300385 0.517905 0.800964 + txt003 +STRI + V0 -0.10163 0.173037 2.7 V1 -0.142 0.142 2.7 V2 -0.121672 0.121672 2.78542 + N0 -0.300385 0.517905 0.800964 N1 -0.423155 0.423155 0.801174 N2 -0.671754 0.671754 -0.312241 + txt003 +STRI + V0 -0.0871056 0.148234 2.78542 V1 -0.0460445 0.165279 2.78542 V2 -0.0537037 0.192963 2.7 + N0 -0.476337 0.822132 -0.311772 N1 -0.246906 0.917897 -0.310647 N2 -0.15602 0.578783 0.800417 + txt003 +STRI + V0 -0.0537037 0.192963 2.7 V1 -0.10163 0.173037 2.7 V2 -0.0871056 0.148234 2.78542 + N0 -0.15602 0.578783 0.800417 N1 -0.300385 0.517905 0.800964 N2 -0.476337 0.822132 -0.311772 + txt003 +STRI + V0 -0.0460445 0.165279 2.78542 V1 6.66134e-16 0.171296 2.78542 V2 0 0.2 2.7 + N0 -0.246906 0.917897 -0.310647 N1 -2.16507e-15 0.950775 -0.309882 N2 3.17207e-15 0.6 0.8 + txt003 +STRI + V0 0 0.2 2.7 V1 -0.0537037 0.192963 2.7 V2 -0.0460445 0.165279 2.78542 + N0 3.17207e-15 0.6 0.8 N1 -0.15602 0.578783 0.800417 N2 -0.246906 0.917897 -0.310647 + txt003 +STRI + V0 0.0750782 0.268946 3.12708 V1 0 0.278704 3.12708 V2 0 0 3.15 + N0 0.0645609 0.241077 0.968356 N1 -0 0.249998 0.968246 N2 0 0 1 + txt003 +STRI + V0 0.141931 0.241285 3.12708 V1 0.0750782 0.268946 3.12708 V2 0 0 3.15 + N0 0.124615 0.215548 0.968509 N1 0.0645609 0.241077 0.968356 N2 0 0 1 + txt003 +STRI + V0 0.19814 0.19814 3.12708 V1 0.141931 0.241285 3.12708 V2 0 0 3.15 + N0 0.175885 0.175885 0.96857 N1 0.124615 0.215548 0.968509 N2 0 0 1 + txt003 +STRI + V0 0.241285 0.141931 3.12708 V1 0.19814 0.19814 3.12708 V2 0 0 3.15 + N0 0.215548 0.124615 0.968509 N1 0.175885 0.175885 0.96857 N2 0 0 1 + txt003 +STRI + V0 0.268946 0.0750782 3.12708 V1 0.241285 0.141931 3.12708 V2 0 0 3.15 + N0 0.241077 0.0645609 0.968356 N1 0.215548 0.124615 0.968509 N2 0 0 1 + txt003 +STRI + V0 0.278704 0 3.12708 V1 0.268946 0.0750782 3.12708 V2 0 0 3.15 + N0 0.249998 -2.80184e-15 0.968246 N1 0.241077 0.0645609 0.968356 N2 0 0 1 + txt003 +STRI + V0 0 0.278704 3.12708 V1 0.0750782 0.268946 3.12708 V2 0.0977709 0.350254 3.06667 + N0 -0 0.249998 0.968246 N1 0.0645609 0.241077 0.968356 N2 0.255913 0.955496 0.146755 + txt003 +STRI + V0 0.0977709 0.350254 3.06667 V1 0 0.362963 3.06667 V2 0 0.278704 3.12708 + N0 0.255913 0.955496 0.146755 N1 -0 0.989203 0.146549 N2 -0 0.249998 0.968246 + txt003 +STRI + V0 0.0750782 0.268946 3.12708 V1 0.141931 0.241285 3.12708 V2 0.184834 0.314228 3.06667 + N0 0.0645609 0.241077 0.968356 N1 0.124615 0.215548 0.968509 N2 0.495088 0.856312 0.147029 + txt003 +STRI + V0 0.184834 0.314228 3.06667 V1 0.0977709 0.350254 3.06667 V2 0.0750782 0.268946 3.12708 + N0 0.495088 0.856312 0.147029 N1 0.255913 0.955496 0.146755 N2 0.0645609 0.241077 0.968356 + txt003 +STRI + V0 0.141931 0.241285 3.12708 V1 0.19814 0.19814 3.12708 V2 0.258037 0.258037 3.06667 + N0 0.124615 0.215548 0.968509 N1 0.175885 0.175885 0.96857 N2 0.699411 0.699411 0.147135 + txt003 +STRI + V0 0.258037 0.258037 3.06667 V1 0.184834 0.314228 3.06667 V2 0.141931 0.241285 3.12708 + N0 0.699411 0.699411 0.147135 N1 0.495088 0.856312 0.147029 N2 0.124615 0.215548 0.968509 + txt003 +STRI + V0 0.19814 0.19814 3.12708 V1 0.241285 0.141931 3.12708 V2 0.314228 0.184834 3.06667 + N0 0.175885 0.175885 0.96857 N1 0.215548 0.124615 0.968509 N2 0.856312 0.495088 0.147029 + txt003 +STRI + V0 0.314228 0.184834 3.06667 V1 0.258037 0.258037 3.06667 V2 0.19814 0.19814 3.12708 + N0 0.856312 0.495088 0.147029 N1 0.699411 0.699411 0.147135 N2 0.175885 0.175885 0.96857 + txt003 +STRI + V0 0.241285 0.141931 3.12708 V1 0.268946 0.0750782 3.12708 V2 0.350254 0.0977709 3.06667 + N0 0.215548 0.124615 0.968509 N1 0.241077 0.0645609 0.968356 N2 0.955496 0.255913 0.146755 + txt003 +STRI + V0 0.350254 0.0977709 3.06667 V1 0.314228 0.184834 3.06667 V2 0.241285 0.141931 3.12708 + N0 0.955496 0.255913 0.146755 N1 0.856312 0.495088 0.147029 N2 0.215548 0.124615 0.968509 + txt003 +STRI + V0 0.268946 0.0750782 3.12708 V1 0.278704 0 3.12708 V2 0.362963 0 3.06667 + N0 0.241077 0.0645609 0.968356 N1 0.249998 -2.80184e-15 0.968246 N2 0.989203 -4.98112e-16 0.146549 + txt003 +STRI + V0 0.362963 0 3.06667 V1 0.350254 0.0977709 3.06667 V2 0.268946 0.0750782 3.12708 + N0 0.989203 -4.98112e-16 0.146549 N1 0.955496 0.255913 0.146755 N2 0.241077 0.0645609 0.968356 + txt003 +STRI + V0 0 0.362963 3.06667 V1 0.0977709 0.350254 3.06667 V2 0.0875289 0.313617 2.98125 + N0 -0 0.989203 0.146549 N1 0.255913 0.955496 0.146755 N2 0.201937 0.753688 -0.625441 + txt003 +STRI + V0 0.0875289 0.313617 2.98125 V1 0 0.325 2.98125 V2 0 0.362963 3.06667 + N0 0.201937 0.753688 -0.625441 N1 0 0.780869 -0.624695 N2 -0 0.989203 0.146549 + txt003 +STRI + V0 0.0977709 0.350254 3.06667 V1 0.184834 0.314228 3.06667 V2 0.165481 0.281352 2.98125 + N0 0.255913 0.955496 0.146755 N1 0.495088 0.856312 0.147029 N2 0.390178 0.674735 -0.626493 + txt003 +STRI + V0 0.165481 0.281352 2.98125 V1 0.0875289 0.313617 2.98125 V2 0.0977709 0.350254 3.06667 + N0 0.390178 0.674735 -0.626493 N1 0.201937 0.753688 -0.625441 N2 0.255913 0.955496 0.146755 + txt003 +STRI + V0 0.184834 0.314228 3.06667 V1 0.258037 0.258037 3.06667 V2 0.231031 0.231031 2.98125 + N0 0.495088 0.856312 0.147029 N1 0.699411 0.699411 0.147135 N2 0.550896 0.550896 -0.626919 + txt003 +STRI + V0 0.231031 0.231031 2.98125 V1 0.165481 0.281352 2.98125 V2 0.184834 0.314228 3.06667 + N0 0.550896 0.550896 -0.626919 N1 0.390178 0.674735 -0.626493 N2 0.495088 0.856312 0.147029 + txt003 +STRI + V0 0.258037 0.258037 3.06667 V1 0.314228 0.184834 3.06667 V2 0.281352 0.165481 2.98125 + N0 0.699411 0.699411 0.147135 N1 0.856312 0.495088 0.147029 N2 0.674735 0.390178 -0.626493 + txt003 +STRI + V0 0.281352 0.165481 2.98125 V1 0.231031 0.231031 2.98125 V2 0.258037 0.258037 3.06667 + N0 0.674735 0.390178 -0.626493 N1 0.550896 0.550896 -0.626919 N2 0.699411 0.699411 0.147135 + txt003 +STRI + V0 0.314228 0.184834 3.06667 V1 0.350254 0.0977709 3.06667 V2 0.313617 0.0875289 2.98125 + N0 0.856312 0.495088 0.147029 N1 0.955496 0.255913 0.146755 N2 0.753688 0.201937 -0.625441 + txt003 +STRI + V0 0.313617 0.0875289 2.98125 V1 0.281352 0.165481 2.98125 V2 0.314228 0.184834 3.06667 + N0 0.753688 0.201937 -0.625441 N1 0.674735 0.390178 -0.626493 N2 0.856312 0.495088 0.147029 + txt003 +STRI + V0 0.350254 0.0977709 3.06667 V1 0.362963 0 3.06667 V2 0.325 -1.11022e-16 2.98125 + N0 0.955496 0.255913 0.146755 N1 0.989203 -4.98112e-16 0.146549 N2 0.780869 1.51803e-15 -0.624695 + txt003 +STRI + V0 0.325 -1.11022e-16 2.98125 V1 0.313617 0.0875289 2.98125 V2 0.350254 0.0977709 3.06667 + N0 0.780869 1.51803e-15 -0.624695 N1 0.753688 0.201937 -0.625441 N2 0.955496 0.255913 0.146755 + txt003 +STRI + V0 0 0.325 2.98125 V1 0.0875289 0.313617 2.98125 V2 0.0638032 0.228728 2.88333 + N0 0 0.780869 -0.624695 N1 0.201937 0.753688 -0.625441 N2 0.193465 0.721244 -0.665116 + txt003 +STRI + V0 0.0638032 0.228728 2.88333 V1 0 0.237037 2.88333 V2 0 0.325 2.98125 + N0 0.193465 0.721244 -0.665116 N1 0 0.747409 -0.664364 N2 0 0.780869 -0.624695 + txt003 +STRI + V0 0.0875289 0.313617 2.98125 V1 0.165481 0.281352 2.98125 V2 0.120647 0.20518 2.88333 + N0 0.201937 0.753688 -0.625441 N1 0.390178 0.674735 -0.626493 N2 0.373497 0.645526 -0.66618 + txt003 +STRI + V0 0.120647 0.20518 2.88333 V1 0.0638032 0.228728 2.88333 V2 0.0875289 0.313617 2.98125 + N0 0.373497 0.645526 -0.66618 N1 0.193465 0.721244 -0.665116 N2 0.201937 0.753688 -0.625441 + txt003 +STRI + V0 0.165481 0.281352 2.98125 V1 0.231031 0.231031 2.98125 V2 0.168463 0.168463 2.88333 + N0 0.390178 0.674735 -0.626493 N1 0.550896 0.550896 -0.626919 N2 0.527081 0.527081 -0.666611 + txt003 +STRI + V0 0.168463 0.168463 2.88333 V1 0.120647 0.20518 2.88333 V2 0.165481 0.281352 2.98125 + N0 0.527081 0.527081 -0.666611 N1 0.373497 0.645526 -0.66618 N2 0.390178 0.674735 -0.626493 + txt003 +STRI + V0 0.231031 0.231031 2.98125 V1 0.281352 0.165481 2.98125 V2 0.20518 0.120647 2.88333 + N0 0.550896 0.550896 -0.626919 N1 0.674735 0.390178 -0.626493 N2 0.645526 0.373497 -0.66618 + txt003 +STRI + V0 0.20518 0.120647 2.88333 V1 0.168463 0.168463 2.88333 V2 0.231031 0.231031 2.98125 + N0 0.645526 0.373497 -0.66618 N1 0.527081 0.527081 -0.666611 N2 0.550896 0.550896 -0.626919 + txt003 +STRI + V0 0.281352 0.165481 2.98125 V1 0.313617 0.0875289 2.98125 V2 0.228728 0.0638032 2.88333 + N0 0.674735 0.390178 -0.626493 N1 0.753688 0.201937 -0.625441 N2 0.721244 0.193465 -0.665116 + txt003 +STRI + V0 0.228728 0.0638032 2.88333 V1 0.20518 0.120647 2.88333 V2 0.281352 0.165481 2.98125 + N0 0.721244 0.193465 -0.665116 N1 0.645526 0.373497 -0.66618 N2 0.674735 0.390178 -0.626493 + txt003 +STRI + V0 0.313617 0.0875289 2.98125 V1 0.325 -1.11022e-16 2.98125 V2 0.237037 -1.11022e-16 2.88333 + N0 0.753688 0.201937 -0.625441 N1 0.780869 1.51803e-15 -0.624695 N2 0.747409 2.42292e-15 -0.664364 + txt003 +STRI + V0 0.237037 -1.11022e-16 2.88333 V1 0.228728 0.0638032 2.88333 V2 0.313617 0.0875289 2.98125 + N0 0.747409 2.42292e-15 -0.664364 N1 0.721244 0.193465 -0.665116 N2 0.753688 0.201937 -0.625441 + txt003 +STRI + V0 0 0.237037 2.88333 V1 0.0638032 0.228728 2.88333 V2 0.0460445 0.165279 2.78542 + N0 0 0.747409 -0.664364 N1 0.193465 0.721244 -0.665116 N2 0.246906 0.917897 -0.310647 + txt003 +STRI + V0 0.0460445 0.165279 2.78542 V1 0 0.171296 2.78542 V2 0 0.237037 2.88333 + N0 0.246906 0.917897 -0.310647 N1 0 0.950775 -0.309882 N2 0 0.747409 -0.664364 + txt003 +STRI + V0 0.0638032 0.228728 2.88333 V1 0.120647 0.20518 2.88333 V2 0.0871056 0.148234 2.78542 + N0 0.193465 0.721244 -0.665116 N1 0.373497 0.645526 -0.66618 N2 0.476337 0.822132 -0.311772 + txt003 +STRI + V0 0.0871056 0.148234 2.78542 V1 0.0460445 0.165279 2.78542 V2 0.0638032 0.228728 2.88333 + N0 0.476337 0.822132 -0.311772 N1 0.246906 0.917897 -0.310647 N2 0.193465 0.721244 -0.665116 + txt003 +STRI + V0 0.120647 0.20518 2.88333 V1 0.168463 0.168463 2.88333 V2 0.121672 0.121672 2.78542 + N0 0.373497 0.645526 -0.66618 N1 0.527081 0.527081 -0.666611 N2 0.671754 0.671754 -0.312241 + txt003 +STRI + V0 0.121672 0.121672 2.78542 V1 0.0871056 0.148234 2.78542 V2 0.120647 0.20518 2.88333 + N0 0.671754 0.671754 -0.312241 N1 0.476337 0.822132 -0.311772 N2 0.373497 0.645526 -0.66618 + txt003 +STRI + V0 0.168463 0.168463 2.88333 V1 0.20518 0.120647 2.88333 V2 0.148234 0.0871056 2.78542 + N0 0.527081 0.527081 -0.666611 N1 0.645526 0.373497 -0.66618 N2 0.822132 0.476337 -0.311772 + txt003 +STRI + V0 0.148234 0.0871056 2.78542 V1 0.121672 0.121672 2.78542 V2 0.168463 0.168463 2.88333 + N0 0.822132 0.476337 -0.311772 N1 0.671754 0.671754 -0.312241 N2 0.527081 0.527081 -0.666611 + txt003 +STRI + V0 0.20518 0.120647 2.88333 V1 0.228728 0.0638032 2.88333 V2 0.165279 0.0460445 2.78542 + N0 0.645526 0.373497 -0.66618 N1 0.721244 0.193465 -0.665116 N2 0.917897 0.246906 -0.310647 + txt003 +STRI + V0 0.165279 0.0460445 2.78542 V1 0.148234 0.0871056 2.78542 V2 0.20518 0.120647 2.88333 + N0 0.917897 0.246906 -0.310647 N1 0.822132 0.476337 -0.311772 N2 0.645526 0.373497 -0.66618 + txt003 +STRI + V0 0.228728 0.0638032 2.88333 V1 0.237037 -1.11022e-16 2.88333 V2 0.171296 -6.66134e-16 2.78542 + N0 0.721244 0.193465 -0.665116 N1 0.747409 2.42292e-15 -0.664364 N2 0.950775 2.16507e-15 -0.309882 + txt003 +STRI + V0 0.171296 -6.66134e-16 2.78542 V1 0.165279 0.0460445 2.78542 V2 0.228728 0.0638032 2.88333 + N0 0.950775 2.16507e-15 -0.309882 N1 0.917897 0.246906 -0.310647 N2 0.721244 0.193465 -0.665116 + txt003 +STRI + V0 0 0.171296 2.78542 V1 0.0460445 0.165279 2.78542 V2 0.0537037 0.192963 2.7 + N0 0 0.950775 -0.309882 N1 0.246906 0.917897 -0.310647 N2 0.15602 0.578783 0.800417 + txt003 +STRI + V0 0.0537037 0.192963 2.7 V1 0 0.2 2.7 V2 0 0.171296 2.78542 + N0 0.15602 0.578783 0.800417 N1 -0 0.6 0.8 N2 0 0.950775 -0.309882 + txt003 +STRI + V0 0.0460445 0.165279 2.78542 V1 0.0871056 0.148234 2.78542 V2 0.10163 0.173037 2.7 + N0 0.246906 0.917897 -0.310647 N1 0.476337 0.822132 -0.311772 N2 0.300385 0.517905 0.800964 + txt003 +STRI + V0 0.10163 0.173037 2.7 V1 0.0537037 0.192963 2.7 V2 0.0460445 0.165279 2.78542 + N0 0.300385 0.517905 0.800964 N1 0.15602 0.578783 0.800417 N2 0.246906 0.917897 -0.310647 + txt003 +STRI + V0 0.0871056 0.148234 2.78542 V1 0.121672 0.121672 2.78542 V2 0.142 0.142 2.7 + N0 0.476337 0.822132 -0.311772 N1 0.671754 0.671754 -0.312241 N2 0.423155 0.423155 0.801174 + txt003 +STRI + V0 0.142 0.142 2.7 V1 0.10163 0.173037 2.7 V2 0.0871056 0.148234 2.78542 + N0 0.423155 0.423155 0.801174 N1 0.300385 0.517905 0.800964 N2 0.476337 0.822132 -0.311772 + txt003 +STRI + V0 0.121672 0.121672 2.78542 V1 0.148234 0.0871056 2.78542 V2 0.173037 0.10163 2.7 + N0 0.671754 0.671754 -0.312241 N1 0.822132 0.476337 -0.311772 N2 0.517905 0.300385 0.800964 + txt003 +STRI + V0 0.173037 0.10163 2.7 V1 0.142 0.142 2.7 V2 0.121672 0.121672 2.78542 + N0 0.517905 0.300385 0.800964 N1 0.423155 0.423155 0.801174 N2 0.671754 0.671754 -0.312241 + txt003 +STRI + V0 0.148234 0.0871056 2.78542 V1 0.165279 0.0460445 2.78542 V2 0.192963 0.0537037 2.7 + N0 0.822132 0.476337 -0.311772 N1 0.917897 0.246906 -0.310647 N2 0.578783 0.15602 0.800417 + txt003 +STRI + V0 0.192963 0.0537037 2.7 V1 0.173037 0.10163 2.7 V2 0.148234 0.0871056 2.78542 + N0 0.578783 0.15602 0.800417 N1 0.517905 0.300385 0.800964 N2 0.822132 0.476337 -0.311772 + txt003 +STRI + V0 0.165279 0.0460445 2.78542 V1 0.171296 -6.66134e-16 2.78542 V2 0.2 0 2.7 + N0 0.917897 0.246906 -0.310647 N1 0.950775 2.16507e-15 -0.309882 N2 0.6 -3.17207e-15 0.8 + txt003 +STRI + V0 0.2 0 2.7 V1 0.192963 0.0537037 2.7 V2 0.165279 0.0460445 2.78542 + N0 0.6 -3.17207e-15 0.8 N1 0.578783 0.15602 0.800417 N2 0.917897 0.246906 -0.310647 + txt003 +STRI + V0 0.2 0 2.7 V1 0.192963 -0.0537037 2.7 V2 0.338579 -0.0942301 2.63611 + N0 0.6 0 0.8 N1 0.578783 -0.15602 0.800417 N2 0.258756 -0.0697517 0.963421 + txt003 +STRI + V0 0.338579 -0.0942301 2.63611 V1 0.350926 0 2.63611 V2 0.2 0 2.7 + N0 0.258756 -0.0697517 0.963421 N1 0.268354 0 0.96332 N2 0.6 0 0.8 + txt003 +STRI + V0 0.192963 -0.0537037 2.7 V1 0.173037 -0.10163 2.7 V2 0.303616 -0.178322 2.63611 + N0 0.578783 -0.15602 0.800417 N1 0.517905 -0.300385 0.800964 N2 0.231413 -0.134219 0.963552 + txt003 +STRI + V0 0.303616 -0.178322 2.63611 V1 0.338579 -0.0942301 2.63611 V2 0.192963 -0.0537037 2.7 + N0 0.231413 -0.134219 0.963552 N1 0.258756 -0.0697517 0.963421 N2 0.578783 -0.15602 0.800417 + txt003 +STRI + V0 0.173037 -0.10163 2.7 V1 0.142 -0.142 2.7 V2 0.249157 -0.249157 2.63611 + N0 0.517905 -0.300385 0.800964 N1 0.423155 -0.423155 0.801174 N2 0.189037 -0.189037 0.963603 + txt003 +STRI + V0 0.249157 -0.249157 2.63611 V1 0.303616 -0.178322 2.63611 V2 0.173037 -0.10163 2.7 + N0 0.189037 -0.189037 0.963603 N1 0.231413 -0.134219 0.963552 N2 0.517905 -0.300385 0.800964 + txt003 +STRI + V0 0.142 -0.142 2.7 V1 0.10163 -0.173037 2.7 V2 0.178322 -0.303616 2.63611 + N0 0.423155 -0.423155 0.801174 N1 0.300385 -0.517905 0.800964 N2 0.134219 -0.231413 0.963552 + txt003 +STRI + V0 0.178322 -0.303616 2.63611 V1 0.249157 -0.249157 2.63611 V2 0.142 -0.142 2.7 + N0 0.134219 -0.231413 0.963552 N1 0.189037 -0.189037 0.963603 N2 0.423155 -0.423155 0.801174 + txt003 +STRI + V0 0.10163 -0.173037 2.7 V1 0.0537037 -0.192963 2.7 V2 0.0942301 -0.338579 2.63611 + N0 0.300385 -0.517905 0.800964 N1 0.15602 -0.578783 0.800417 N2 0.0697517 -0.258756 0.963421 + txt003 +STRI + V0 0.0942301 -0.338579 2.63611 V1 0.178322 -0.303616 2.63611 V2 0.10163 -0.173037 2.7 + N0 0.0697517 -0.258756 0.963421 N1 0.134219 -0.231413 0.963552 N2 0.300385 -0.517905 0.800964 + txt003 +STRI + V0 0.0537037 -0.192963 2.7 V1 0 -0.2 2.7 V2 5.55112e-17 -0.350926 2.63611 + N0 0.15602 -0.578783 0.800417 N1 -9.91271e-17 -0.6 0.8 N2 0 -0.268354 0.96332 + txt003 +STRI + V0 5.55112e-17 -0.350926 2.63611 V1 0.0942301 -0.338579 2.63611 V2 0.0537037 -0.192963 2.7 + N0 0 -0.268354 0.96332 N1 0.0697517 -0.258756 0.963421 N2 0.15602 -0.578783 0.800417 + txt003 +STRI + V0 0.350926 0 2.63611 V1 0.338579 -0.0942301 2.63611 V2 0.553875 -0.15415 2.58889 + N0 0.268354 0 0.96332 N1 0.258756 -0.0697517 0.963421 N2 0.162011 -0.0436726 0.985822 + txt003 +STRI + V0 0.553875 -0.15415 2.58889 V1 0.574074 0 2.58889 V2 0.350926 0 2.63611 + N0 0.162011 -0.0436726 0.985822 N1 0.168031 0 0.985782 N2 0.268354 0 0.96332 + txt003 +STRI + V0 0.338579 -0.0942301 2.63611 V1 0.303616 -0.178322 2.63611 V2 0.49668 -0.291715 2.58889 + N0 0.258756 -0.0697517 0.963421 N1 0.231413 -0.134219 0.963552 N2 0.144879 -0.0840299 0.985875 + txt003 +STRI + V0 0.49668 -0.291715 2.58889 V1 0.553875 -0.15415 2.58889 V2 0.338579 -0.0942301 2.63611 + N0 0.144879 -0.0840299 0.985875 N1 0.162011 -0.0436726 0.985822 N2 0.258756 -0.0697517 0.963421 + txt003 +STRI + V0 0.303616 -0.178322 2.63611 V1 0.249157 -0.249157 2.63611 V2 0.407593 -0.407593 2.58889 + N0 0.231413 -0.134219 0.963552 N1 0.189037 -0.189037 0.963603 N2 0.118345 -0.118345 0.985895 + txt003 +STRI + V0 0.407593 -0.407593 2.58889 V1 0.49668 -0.291715 2.58889 V2 0.303616 -0.178322 2.63611 + N0 0.118345 -0.118345 0.985895 N1 0.144879 -0.0840299 0.985875 N2 0.231413 -0.134219 0.963552 + txt003 +STRI + V0 0.249157 -0.249157 2.63611 V1 0.178322 -0.303616 2.63611 V2 0.291715 -0.49668 2.58889 + N0 0.189037 -0.189037 0.963603 N1 0.134219 -0.231413 0.963552 N2 0.0840299 -0.144879 0.985875 + txt003 +STRI + V0 0.291715 -0.49668 2.58889 V1 0.407593 -0.407593 2.58889 V2 0.249157 -0.249157 2.63611 + N0 0.0840299 -0.144879 0.985875 N1 0.118345 -0.118345 0.985895 N2 0.189037 -0.189037 0.963603 + txt003 +STRI + V0 0.178322 -0.303616 2.63611 V1 0.0942301 -0.338579 2.63611 V2 0.15415 -0.553875 2.58889 + N0 0.134219 -0.231413 0.963552 N1 0.0697517 -0.258756 0.963421 N2 0.0436726 -0.162011 0.985822 + txt003 +STRI + V0 0.15415 -0.553875 2.58889 V1 0.291715 -0.49668 2.58889 V2 0.178322 -0.303616 2.63611 + N0 0.0436726 -0.162011 0.985822 N1 0.0840299 -0.144879 0.985875 N2 0.134219 -0.231413 0.963552 + txt003 +STRI + V0 0.0942301 -0.338579 2.63611 V1 5.55112e-17 -0.350926 2.63611 V2 2.22045e-16 -0.574074 2.58889 + N0 0.0697517 -0.258756 0.963421 N1 0 -0.268354 0.96332 N2 -1.93429e-17 -0.168031 0.985782 + txt003 +STRI + V0 2.22045e-16 -0.574074 2.58889 V1 0.15415 -0.553875 2.58889 V2 0.0942301 -0.338579 2.63611 + N0 -1.93429e-17 -0.168031 0.985782 N1 0.0436726 -0.162011 0.985822 N2 0.0697517 -0.258756 0.963421 + txt003 +STRI + V0 0.574074 0 2.58889 V1 0.553875 -0.15415 2.58889 V2 0.795972 -0.221528 2.55 + N0 0.168031 0 0.985782 N1 0.162011 -0.0436726 0.985822 N2 0.143025 -0.0385545 0.988968 + txt003 +STRI + V0 0.795972 -0.221528 2.55 V1 0.825 0 2.55 V2 0.574074 0 2.58889 + N0 0.143025 -0.0385545 0.988968 N1 0.14834 0 0.988936 N2 0.168031 0 0.985782 + txt003 +STRI + V0 0.553875 -0.15415 2.58889 V1 0.49668 -0.291715 2.58889 V2 0.713778 -0.419222 2.55 + N0 0.162011 -0.0436726 0.985822 N1 0.144879 -0.0840299 0.985875 N2 0.127899 -0.0741814 0.989009 + txt003 +STRI + V0 0.713778 -0.419222 2.55 V1 0.795972 -0.221528 2.55 V2 0.553875 -0.15415 2.58889 + N0 0.127899 -0.0741814 0.989009 N1 0.143025 -0.0385545 0.988968 N2 0.162011 -0.0436726 0.985822 + txt003 +STRI + V0 0.49668 -0.291715 2.58889 V1 0.407593 -0.407593 2.58889 V2 0.58575 -0.58575 2.55 + N0 0.144879 -0.0840299 0.985875 N1 0.118345 -0.118345 0.985895 N2 0.104474 -0.104474 0.989025 + txt003 +STRI + V0 0.58575 -0.58575 2.55 V1 0.713778 -0.419222 2.55 V2 0.49668 -0.291715 2.58889 + N0 0.104474 -0.104474 0.989025 N1 0.127899 -0.0741814 0.989009 N2 0.144879 -0.0840299 0.985875 + txt003 +STRI + V0 0.407593 -0.407593 2.58889 V1 0.291715 -0.49668 2.58889 V2 0.419222 -0.713778 2.55 + N0 0.118345 -0.118345 0.985895 N1 0.0840299 -0.144879 0.985875 N2 0.0741814 -0.127899 0.989009 + txt003 +STRI + V0 0.419222 -0.713778 2.55 V1 0.58575 -0.58575 2.55 V2 0.407593 -0.407593 2.58889 + N0 0.0741814 -0.127899 0.989009 N1 0.104474 -0.104474 0.989025 N2 0.118345 -0.118345 0.985895 + txt003 +STRI + V0 0.291715 -0.49668 2.58889 V1 0.15415 -0.553875 2.58889 V2 0.221528 -0.795972 2.55 + N0 0.0840299 -0.144879 0.985875 N1 0.0436726 -0.162011 0.985822 N2 0.0385545 -0.143025 0.988968 + txt003 +STRI + V0 0.221528 -0.795972 2.55 V1 0.419222 -0.713778 2.55 V2 0.291715 -0.49668 2.58889 + N0 0.0385545 -0.143025 0.988968 N1 0.0741814 -0.127899 0.989009 N2 0.0840299 -0.144879 0.985875 + txt003 +STRI + V0 0.15415 -0.553875 2.58889 V1 2.22045e-16 -0.574074 2.58889 V2 1.11022e-16 -0.825 2.55 + N0 0.0436726 -0.162011 0.985822 N1 -1.93429e-17 -0.168031 0.985782 N2 -2.37649e-17 -0.14834 0.988936 + txt003 +STRI + V0 1.11022e-16 -0.825 2.55 V1 0.221528 -0.795972 2.55 V2 0.15415 -0.553875 2.58889 + N0 -2.37649e-17 -0.14834 0.988936 N1 0.0385545 -0.143025 0.988968 N2 0.0436726 -0.162011 0.985822 + txt003 +STRI + V0 0.825 0 2.55 V1 0.795972 -0.221528 2.55 V2 1.02199 -0.284431 2.51111 + N0 0.14834 0 0.988936 N1 0.143025 -0.0385545 0.988968 N2 0.186699 -0.0503275 0.981127 + txt003 +STRI + V0 1.02199 -0.284431 2.51111 V1 1.05926 0 2.51111 V2 0.825 0 2.55 + N0 0.186699 -0.0503275 0.981127 N1 0.193633 0 0.981074 N2 0.14834 0 0.988936 + txt003 +STRI + V0 0.795972 -0.221528 2.55 V1 0.713778 -0.419222 2.55 V2 0.916455 -0.538261 2.51111 + N0 0.143025 -0.0385545 0.988968 N1 0.127899 -0.0741814 0.989009 N2 0.166959 -0.0968361 0.981197 + txt003 +STRI + V0 0.916455 -0.538261 2.51111 V1 1.02199 -0.284431 2.51111 V2 0.795972 -0.221528 2.55 + N0 0.166959 -0.0968361 0.981197 N1 0.186699 -0.0503275 0.981127 N2 0.143025 -0.0385545 0.988968 + txt003 +STRI + V0 0.713778 -0.419222 2.55 V1 0.58575 -0.58575 2.55 V2 0.752074 -0.752074 2.51111 + N0 0.127899 -0.0741814 0.989009 N1 0.104474 -0.104474 0.989025 N2 0.136382 -0.136382 0.981224 + txt003 +STRI + V0 0.752074 -0.752074 2.51111 V1 0.916455 -0.538261 2.51111 V2 0.713778 -0.419222 2.55 + N0 0.136382 -0.136382 0.981224 N1 0.166959 -0.0968361 0.981197 N2 0.127899 -0.0741814 0.989009 + txt003 +STRI + V0 0.58575 -0.58575 2.55 V1 0.419222 -0.713778 2.55 V2 0.538261 -0.916455 2.51111 + N0 0.104474 -0.104474 0.989025 N1 0.0741814 -0.127899 0.989009 N2 0.0968361 -0.166959 0.981197 + txt003 +STRI + V0 0.538261 -0.916455 2.51111 V1 0.752074 -0.752074 2.51111 V2 0.58575 -0.58575 2.55 + N0 0.0968361 -0.166959 0.981197 N1 0.136382 -0.136382 0.981224 N2 0.104474 -0.104474 0.989025 + txt003 +STRI + V0 0.419222 -0.713778 2.55 V1 0.221528 -0.795972 2.55 V2 0.284431 -1.02199 2.51111 + N0 0.0741814 -0.127899 0.989009 N1 0.0385545 -0.143025 0.988968 N2 0.0503275 -0.186699 0.981127 + txt003 +STRI + V0 0.284431 -1.02199 2.51111 V1 0.538261 -0.916455 2.51111 V2 0.419222 -0.713778 2.55 + N0 0.0503275 -0.186699 0.981127 N1 0.0968361 -0.166959 0.981197 N2 0.0741814 -0.127899 0.989009 + txt003 +STRI + V0 0.221528 -0.795972 2.55 V1 1.11022e-16 -0.825 2.55 V2 4.44089e-16 -1.05926 2.51111 + N0 0.0385545 -0.143025 0.988968 N1 -2.37649e-17 -0.14834 0.988936 N2 -7.24819e-17 -0.193633 0.981074 + txt003 +STRI + V0 4.44089e-16 -1.05926 2.51111 V1 0.284431 -1.02199 2.51111 V2 0.221528 -0.795972 2.55 + N0 -7.24819e-17 -0.193633 0.981074 N1 0.0503275 -0.186699 0.981127 N2 0.0385545 -0.143025 0.988968 + txt003 +STRI + V0 1.05926 0 2.51111 V1 1.02199 -0.284431 2.51111 V2 1.18904 -0.330924 2.46389 + N0 0.193633 0 0.981074 N1 0.186699 -0.0503275 0.981127 N2 0.376378 -0.101459 0.920894 + txt003 +STRI + V0 1.18904 -0.330924 2.46389 V1 1.23241 0 2.46389 V2 1.05926 0 2.51111 + N0 0.376378 -0.101459 0.920894 N1 0.390293 0 0.920691 N2 0.193633 0 0.981074 + txt003 +STRI + V0 1.02199 -0.284431 2.51111 V1 0.916455 -0.538261 2.51111 V2 1.06626 -0.626246 2.46389 + N0 0.186699 -0.0503275 0.981127 N1 0.166959 -0.0968361 0.981197 N2 0.336657 -0.195261 0.92116 + txt003 +STRI + V0 1.06626 -0.626246 2.46389 V1 1.18904 -0.330924 2.46389 V2 1.02199 -0.284431 2.51111 + N0 0.336657 -0.195261 0.92116 N1 0.376378 -0.101459 0.920894 N2 0.186699 -0.0503275 0.981127 + txt003 +STRI + V0 0.916455 -0.538261 2.51111 V1 0.752074 -0.752074 2.51111 V2 0.875009 -0.875009 2.46389 + N0 0.166959 -0.0968361 0.981197 N1 0.136382 -0.136382 0.981224 N2 0.275025 -0.275025 0.921262 + txt003 +STRI + V0 0.875009 -0.875009 2.46389 V1 1.06626 -0.626246 2.46389 V2 0.916455 -0.538261 2.51111 + N0 0.275025 -0.275025 0.921262 N1 0.336657 -0.195261 0.92116 N2 0.166959 -0.0968361 0.981197 + txt003 +STRI + V0 0.752074 -0.752074 2.51111 V1 0.538261 -0.916455 2.51111 V2 0.626246 -1.06626 2.46389 + N0 0.136382 -0.136382 0.981224 N1 0.0968361 -0.166959 0.981197 N2 0.195261 -0.336657 0.92116 + txt003 +STRI + V0 0.626246 -1.06626 2.46389 V1 0.875009 -0.875009 2.46389 V2 0.752074 -0.752074 2.51111 + N0 0.195261 -0.336657 0.92116 N1 0.275025 -0.275025 0.921262 N2 0.136382 -0.136382 0.981224 + txt003 +STRI + V0 0.538261 -0.916455 2.51111 V1 0.284431 -1.02199 2.51111 V2 0.330924 -1.18904 2.46389 + N0 0.0968361 -0.166959 0.981197 N1 0.0503275 -0.186699 0.981127 N2 0.101459 -0.376378 0.920894 + txt003 +STRI + V0 0.330924 -1.18904 2.46389 V1 0.626246 -1.06626 2.46389 V2 0.538261 -0.916455 2.51111 + N0 0.101459 -0.376378 0.920894 N1 0.195261 -0.336657 0.92116 N2 0.0968361 -0.166959 0.981197 + txt003 +STRI + V0 0.284431 -1.02199 2.51111 V1 4.44089e-16 -1.05926 2.51111 V2 4.44089e-16 -1.23241 2.46389 + N0 0.0503275 -0.186699 0.981127 N1 -7.24819e-17 -0.193633 0.981074 N2 -8.37138e-17 -0.390293 0.920691 + txt003 +STRI + V0 4.44089e-16 -1.23241 2.46389 V1 0.330924 -1.18904 2.46389 V2 0.284431 -1.02199 2.51111 + N0 -8.37138e-17 -0.390293 0.920691 N1 0.101459 -0.376378 0.920894 N2 0.0503275 -0.186699 0.981127 + txt003 +STRI + V0 1.23241 0 2.46389 V1 1.18904 -0.330924 2.46389 V2 1.25426 -0.349074 2.4 + N0 0.390293 0 0.920691 N1 0.376378 -0.101459 0.920894 N2 0.965535 -0.260275 -1.02004e-15 + txt003 +STRI + V0 1.25426 -0.349074 2.4 V1 1.3 0 2.4 V2 1.23241 0 2.46389 + N0 0.965535 -0.260275 -1.02004e-15 N1 1 0 -9.86865e-16 N2 0.390293 0 0.920691 + txt003 +STRI + V0 1.18904 -0.330924 2.46389 V1 1.06626 -0.626246 2.46389 V2 1.12474 -0.660593 2.4 + N0 0.376378 -0.101459 0.920894 N1 0.336657 -0.195261 0.92116 N2 0.865031 -0.501718 -9.69705e-16 + txt003 +STRI + V0 1.12474 -0.660593 2.4 V1 1.25426 -0.349074 2.4 V2 1.18904 -0.330924 2.46389 + N0 0.865031 -0.501718 -9.69705e-16 N1 0.965535 -0.260275 -1.02004e-15 N2 0.376378 -0.101459 0.920894 + txt003 +STRI + V0 1.06626 -0.626246 2.46389 V1 0.875009 -0.875009 2.46389 V2 0.923 -0.923 2.4 + N0 0.336657 -0.195261 0.92116 N1 0.275025 -0.275025 0.921262 N2 0.707107 -0.707107 -7.41433e-16 + txt003 +STRI + V0 0.923 -0.923 2.4 V1 1.12474 -0.660593 2.4 V2 1.06626 -0.626246 2.46389 + N0 0.707107 -0.707107 -7.41433e-16 N1 0.865031 -0.501718 -9.69705e-16 N2 0.336657 -0.195261 0.92116 + txt003 +STRI + V0 0.875009 -0.875009 2.46389 V1 0.626246 -1.06626 2.46389 V2 0.660593 -1.12474 2.4 + N0 0.275025 -0.275025 0.921262 N1 0.195261 -0.336657 0.92116 N2 0.501718 -0.865031 -4.67305e-16 + txt003 +STRI + V0 0.660593 -1.12474 2.4 V1 0.923 -0.923 2.4 V2 0.875009 -0.875009 2.46389 + N0 0.501718 -0.865031 -4.67305e-16 N1 0.707107 -0.707107 -7.41433e-16 N2 0.275025 -0.275025 0.921262 + txt003 +STRI + V0 0.626246 -1.06626 2.46389 V1 0.330924 -1.18904 2.46389 V2 0.349074 -1.25426 2.4 + N0 0.195261 -0.336657 0.92116 N1 0.101459 -0.376378 0.920894 N2 0.260275 -0.965535 -5.24893e-16 + txt003 +STRI + V0 0.349074 -1.25426 2.4 V1 0.660593 -1.12474 2.4 V2 0.626246 -1.06626 2.46389 + N0 0.260275 -0.965535 -5.24893e-16 N1 0.501718 -0.865031 -4.67305e-16 N2 0.195261 -0.336657 0.92116 + txt003 +STRI + V0 0.330924 -1.18904 2.46389 V1 4.44089e-16 -1.23241 2.46389 V2 6.66134e-16 -1.3 2.4 + N0 0.101459 -0.376378 0.920894 N1 -8.37138e-17 -0.390293 0.920691 N2 -4.06675e-16 -1 -1.4803e-15 + txt003 +STRI + V0 6.66134e-16 -1.3 2.4 V1 0.349074 -1.25426 2.4 V2 0.330924 -1.18904 2.46389 + N0 -4.06675e-16 -1 -1.4803e-15 N1 0.260275 -0.965535 -5.24893e-16 N2 0.101459 -0.376378 0.920894 + txt003 +STRI + V0 0 -0.2 2.7 V1 -0.0537037 -0.192963 2.7 V2 -0.0942301 -0.338579 2.63611 + N0 0 -0.6 0.8 N1 -0.15602 -0.578783 0.800417 N2 -0.0697517 -0.258756 0.963421 + txt003 +STRI + V0 -0.0942301 -0.338579 2.63611 V1 0 -0.350926 2.63611 V2 0 -0.2 2.7 + N0 -0.0697517 -0.258756 0.963421 N1 0 -0.268354 0.96332 N2 0 -0.6 0.8 + txt003 +STRI + V0 -0.0537037 -0.192963 2.7 V1 -0.10163 -0.173037 2.7 V2 -0.178322 -0.303616 2.63611 + N0 -0.15602 -0.578783 0.800417 N1 -0.300385 -0.517905 0.800964 N2 -0.134219 -0.231413 0.963552 + txt003 +STRI + V0 -0.178322 -0.303616 2.63611 V1 -0.0942301 -0.338579 2.63611 V2 -0.0537037 -0.192963 2.7 + N0 -0.134219 -0.231413 0.963552 N1 -0.0697517 -0.258756 0.963421 N2 -0.15602 -0.578783 0.800417 + txt003 +STRI + V0 -0.10163 -0.173037 2.7 V1 -0.142 -0.142 2.7 V2 -0.249157 -0.249157 2.63611 + N0 -0.300385 -0.517905 0.800964 N1 -0.423155 -0.423155 0.801174 N2 -0.189037 -0.189037 0.963603 + txt003 +STRI + V0 -0.249157 -0.249157 2.63611 V1 -0.178322 -0.303616 2.63611 V2 -0.10163 -0.173037 2.7 + N0 -0.189037 -0.189037 0.963603 N1 -0.134219 -0.231413 0.963552 N2 -0.300385 -0.517905 0.800964 + txt003 +STRI + V0 -0.142 -0.142 2.7 V1 -0.173037 -0.10163 2.7 V2 -0.303616 -0.178322 2.63611 + N0 -0.423155 -0.423155 0.801174 N1 -0.517905 -0.300385 0.800964 N2 -0.231413 -0.134219 0.963552 + txt003 +STRI + V0 -0.303616 -0.178322 2.63611 V1 -0.249157 -0.249157 2.63611 V2 -0.142 -0.142 2.7 + N0 -0.231413 -0.134219 0.963552 N1 -0.189037 -0.189037 0.963603 N2 -0.423155 -0.423155 0.801174 + txt003 +STRI + V0 -0.173037 -0.10163 2.7 V1 -0.192963 -0.0537037 2.7 V2 -0.338579 -0.0942301 2.63611 + N0 -0.517905 -0.300385 0.800964 N1 -0.578783 -0.15602 0.800417 N2 -0.258756 -0.0697517 0.963421 + txt003 +STRI + V0 -0.338579 -0.0942301 2.63611 V1 -0.303616 -0.178322 2.63611 V2 -0.173037 -0.10163 2.7 + N0 -0.258756 -0.0697517 0.963421 N1 -0.231413 -0.134219 0.963552 N2 -0.517905 -0.300385 0.800964 + txt003 +STRI + V0 -0.192963 -0.0537037 2.7 V1 -0.2 0 2.7 V2 -0.350926 -5.55112e-17 2.63611 + N0 -0.578783 -0.15602 0.800417 N1 -0.6 9.91271e-17 0.8 N2 -0.268354 0 0.96332 + txt003 +STRI + V0 -0.350926 -5.55112e-17 2.63611 V1 -0.338579 -0.0942301 2.63611 V2 -0.192963 -0.0537037 2.7 + N0 -0.268354 0 0.96332 N1 -0.258756 -0.0697517 0.963421 N2 -0.578783 -0.15602 0.800417 + txt003 +STRI + V0 0 -0.350926 2.63611 V1 -0.0942301 -0.338579 2.63611 V2 -0.15415 -0.553875 2.58889 + N0 0 -0.268354 0.96332 N1 -0.0697517 -0.258756 0.963421 N2 -0.0436726 -0.162011 0.985822 + txt003 +STRI + V0 -0.15415 -0.553875 2.58889 V1 0 -0.574074 2.58889 V2 0 -0.350926 2.63611 + N0 -0.0436726 -0.162011 0.985822 N1 0 -0.168031 0.985782 N2 0 -0.268354 0.96332 + txt003 +STRI + V0 -0.0942301 -0.338579 2.63611 V1 -0.178322 -0.303616 2.63611 V2 -0.291715 -0.49668 2.58889 + N0 -0.0697517 -0.258756 0.963421 N1 -0.134219 -0.231413 0.963552 N2 -0.0840299 -0.144879 0.985875 + txt003 +STRI + V0 -0.291715 -0.49668 2.58889 V1 -0.15415 -0.553875 2.58889 V2 -0.0942301 -0.338579 2.63611 + N0 -0.0840299 -0.144879 0.985875 N1 -0.0436726 -0.162011 0.985822 N2 -0.0697517 -0.258756 0.963421 + txt003 +STRI + V0 -0.178322 -0.303616 2.63611 V1 -0.249157 -0.249157 2.63611 V2 -0.407593 -0.407593 2.58889 + N0 -0.134219 -0.231413 0.963552 N1 -0.189037 -0.189037 0.963603 N2 -0.118345 -0.118345 0.985895 + txt003 +STRI + V0 -0.407593 -0.407593 2.58889 V1 -0.291715 -0.49668 2.58889 V2 -0.178322 -0.303616 2.63611 + N0 -0.118345 -0.118345 0.985895 N1 -0.0840299 -0.144879 0.985875 N2 -0.134219 -0.231413 0.963552 + txt003 +STRI + V0 -0.249157 -0.249157 2.63611 V1 -0.303616 -0.178322 2.63611 V2 -0.49668 -0.291715 2.58889 + N0 -0.189037 -0.189037 0.963603 N1 -0.231413 -0.134219 0.963552 N2 -0.144879 -0.0840299 0.985875 + txt003 +STRI + V0 -0.49668 -0.291715 2.58889 V1 -0.407593 -0.407593 2.58889 V2 -0.249157 -0.249157 2.63611 + N0 -0.144879 -0.0840299 0.985875 N1 -0.118345 -0.118345 0.985895 N2 -0.189037 -0.189037 0.963603 + txt003 +STRI + V0 -0.303616 -0.178322 2.63611 V1 -0.338579 -0.0942301 2.63611 V2 -0.553875 -0.15415 2.58889 + N0 -0.231413 -0.134219 0.963552 N1 -0.258756 -0.0697517 0.963421 N2 -0.162011 -0.0436726 0.985822 + txt003 +STRI + V0 -0.553875 -0.15415 2.58889 V1 -0.49668 -0.291715 2.58889 V2 -0.303616 -0.178322 2.63611 + N0 -0.162011 -0.0436726 0.985822 N1 -0.144879 -0.0840299 0.985875 N2 -0.231413 -0.134219 0.963552 + txt003 +STRI + V0 -0.338579 -0.0942301 2.63611 V1 -0.350926 -5.55112e-17 2.63611 V2 -0.574074 -2.22045e-16 2.58889 + N0 -0.258756 -0.0697517 0.963421 N1 -0.268354 0 0.96332 N2 -0.168031 1.93429e-17 0.985782 + txt003 +STRI + V0 -0.574074 -2.22045e-16 2.58889 V1 -0.553875 -0.15415 2.58889 V2 -0.338579 -0.0942301 2.63611 + N0 -0.168031 1.93429e-17 0.985782 N1 -0.162011 -0.0436726 0.985822 N2 -0.258756 -0.0697517 0.963421 + txt003 +STRI + V0 0 -0.574074 2.58889 V1 -0.15415 -0.553875 2.58889 V2 -0.221528 -0.795972 2.55 + N0 0 -0.168031 0.985782 N1 -0.0436726 -0.162011 0.985822 N2 -0.0385545 -0.143025 0.988968 + txt003 +STRI + V0 -0.221528 -0.795972 2.55 V1 0 -0.825 2.55 V2 0 -0.574074 2.58889 + N0 -0.0385545 -0.143025 0.988968 N1 0 -0.14834 0.988936 N2 0 -0.168031 0.985782 + txt003 +STRI + V0 -0.15415 -0.553875 2.58889 V1 -0.291715 -0.49668 2.58889 V2 -0.419222 -0.713778 2.55 + N0 -0.0436726 -0.162011 0.985822 N1 -0.0840299 -0.144879 0.985875 N2 -0.0741814 -0.127899 0.989009 + txt003 +STRI + V0 -0.419222 -0.713778 2.55 V1 -0.221528 -0.795972 2.55 V2 -0.15415 -0.553875 2.58889 + N0 -0.0741814 -0.127899 0.989009 N1 -0.0385545 -0.143025 0.988968 N2 -0.0436726 -0.162011 0.985822 + txt003 +STRI + V0 -0.291715 -0.49668 2.58889 V1 -0.407593 -0.407593 2.58889 V2 -0.58575 -0.58575 2.55 + N0 -0.0840299 -0.144879 0.985875 N1 -0.118345 -0.118345 0.985895 N2 -0.104474 -0.104474 0.989025 + txt003 +STRI + V0 -0.58575 -0.58575 2.55 V1 -0.419222 -0.713778 2.55 V2 -0.291715 -0.49668 2.58889 + N0 -0.104474 -0.104474 0.989025 N1 -0.0741814 -0.127899 0.989009 N2 -0.0840299 -0.144879 0.985875 + txt003 +STRI + V0 -0.407593 -0.407593 2.58889 V1 -0.49668 -0.291715 2.58889 V2 -0.713778 -0.419222 2.55 + N0 -0.118345 -0.118345 0.985895 N1 -0.144879 -0.0840299 0.985875 N2 -0.127899 -0.0741814 0.989009 + txt003 +STRI + V0 -0.713778 -0.419222 2.55 V1 -0.58575 -0.58575 2.55 V2 -0.407593 -0.407593 2.58889 + N0 -0.127899 -0.0741814 0.989009 N1 -0.104474 -0.104474 0.989025 N2 -0.118345 -0.118345 0.985895 + txt003 +STRI + V0 -0.49668 -0.291715 2.58889 V1 -0.553875 -0.15415 2.58889 V2 -0.795972 -0.221528 2.55 + N0 -0.144879 -0.0840299 0.985875 N1 -0.162011 -0.0436726 0.985822 N2 -0.143025 -0.0385545 0.988968 + txt003 +STRI + V0 -0.795972 -0.221528 2.55 V1 -0.713778 -0.419222 2.55 V2 -0.49668 -0.291715 2.58889 + N0 -0.143025 -0.0385545 0.988968 N1 -0.127899 -0.0741814 0.989009 N2 -0.144879 -0.0840299 0.985875 + txt003 +STRI + V0 -0.553875 -0.15415 2.58889 V1 -0.574074 -2.22045e-16 2.58889 V2 -0.825 -1.11022e-16 2.55 + N0 -0.162011 -0.0436726 0.985822 N1 -0.168031 1.93429e-17 0.985782 N2 -0.14834 2.37649e-17 0.988936 + txt003 +STRI + V0 -0.825 -1.11022e-16 2.55 V1 -0.795972 -0.221528 2.55 V2 -0.553875 -0.15415 2.58889 + N0 -0.14834 2.37649e-17 0.988936 N1 -0.143025 -0.0385545 0.988968 N2 -0.162011 -0.0436726 0.985822 + txt003 +STRI + V0 0 -0.825 2.55 V1 -0.221528 -0.795972 2.55 V2 -0.284431 -1.02199 2.51111 + N0 0 -0.14834 0.988936 N1 -0.0385545 -0.143025 0.988968 N2 -0.0503275 -0.186699 0.981127 + txt003 +STRI + V0 -0.284431 -1.02199 2.51111 V1 0 -1.05926 2.51111 V2 0 -0.825 2.55 + N0 -0.0503275 -0.186699 0.981127 N1 0 -0.193633 0.981074 N2 0 -0.14834 0.988936 + txt003 +STRI + V0 -0.221528 -0.795972 2.55 V1 -0.419222 -0.713778 2.55 V2 -0.538261 -0.916455 2.51111 + N0 -0.0385545 -0.143025 0.988968 N1 -0.0741814 -0.127899 0.989009 N2 -0.0968361 -0.166959 0.981197 + txt003 +STRI + V0 -0.538261 -0.916455 2.51111 V1 -0.284431 -1.02199 2.51111 V2 -0.221528 -0.795972 2.55 + N0 -0.0968361 -0.166959 0.981197 N1 -0.0503275 -0.186699 0.981127 N2 -0.0385545 -0.143025 0.988968 + txt003 +STRI + V0 -0.419222 -0.713778 2.55 V1 -0.58575 -0.58575 2.55 V2 -0.752074 -0.752074 2.51111 + N0 -0.0741814 -0.127899 0.989009 N1 -0.104474 -0.104474 0.989025 N2 -0.136382 -0.136382 0.981224 + txt003 +STRI + V0 -0.752074 -0.752074 2.51111 V1 -0.538261 -0.916455 2.51111 V2 -0.419222 -0.713778 2.55 + N0 -0.136382 -0.136382 0.981224 N1 -0.0968361 -0.166959 0.981197 N2 -0.0741814 -0.127899 0.989009 + txt003 +STRI + V0 -0.58575 -0.58575 2.55 V1 -0.713778 -0.419222 2.55 V2 -0.916455 -0.538261 2.51111 + N0 -0.104474 -0.104474 0.989025 N1 -0.127899 -0.0741814 0.989009 N2 -0.166959 -0.0968361 0.981197 + txt003 +STRI + V0 -0.916455 -0.538261 2.51111 V1 -0.752074 -0.752074 2.51111 V2 -0.58575 -0.58575 2.55 + N0 -0.166959 -0.0968361 0.981197 N1 -0.136382 -0.136382 0.981224 N2 -0.104474 -0.104474 0.989025 + txt003 +STRI + V0 -0.713778 -0.419222 2.55 V1 -0.795972 -0.221528 2.55 V2 -1.02199 -0.284431 2.51111 + N0 -0.127899 -0.0741814 0.989009 N1 -0.143025 -0.0385545 0.988968 N2 -0.186699 -0.0503275 0.981127 + txt003 +STRI + V0 -1.02199 -0.284431 2.51111 V1 -0.916455 -0.538261 2.51111 V2 -0.713778 -0.419222 2.55 + N0 -0.186699 -0.0503275 0.981127 N1 -0.166959 -0.0968361 0.981197 N2 -0.127899 -0.0741814 0.989009 + txt003 +STRI + V0 -0.795972 -0.221528 2.55 V1 -0.825 -1.11022e-16 2.55 V2 -1.05926 -4.44089e-16 2.51111 + N0 -0.143025 -0.0385545 0.988968 N1 -0.14834 2.37649e-17 0.988936 N2 -0.193633 7.24819e-17 0.981074 + txt003 +STRI + V0 -1.05926 -4.44089e-16 2.51111 V1 -1.02199 -0.284431 2.51111 V2 -0.795972 -0.221528 2.55 + N0 -0.193633 7.24819e-17 0.981074 N1 -0.186699 -0.0503275 0.981127 N2 -0.143025 -0.0385545 0.988968 + txt003 +STRI + V0 0 -1.05926 2.51111 V1 -0.284431 -1.02199 2.51111 V2 -0.330924 -1.18904 2.46389 + N0 0 -0.193633 0.981074 N1 -0.0503275 -0.186699 0.981127 N2 -0.101459 -0.376378 0.920894 + txt003 +STRI + V0 -0.330924 -1.18904 2.46389 V1 0 -1.23241 2.46389 V2 0 -1.05926 2.51111 + N0 -0.101459 -0.376378 0.920894 N1 0 -0.390293 0.920691 N2 0 -0.193633 0.981074 + txt003 +STRI + V0 -0.284431 -1.02199 2.51111 V1 -0.538261 -0.916455 2.51111 V2 -0.626246 -1.06626 2.46389 + N0 -0.0503275 -0.186699 0.981127 N1 -0.0968361 -0.166959 0.981197 N2 -0.195261 -0.336657 0.92116 + txt003 +STRI + V0 -0.626246 -1.06626 2.46389 V1 -0.330924 -1.18904 2.46389 V2 -0.284431 -1.02199 2.51111 + N0 -0.195261 -0.336657 0.92116 N1 -0.101459 -0.376378 0.920894 N2 -0.0503275 -0.186699 0.981127 + txt003 +STRI + V0 -0.538261 -0.916455 2.51111 V1 -0.752074 -0.752074 2.51111 V2 -0.875009 -0.875009 2.46389 + N0 -0.0968361 -0.166959 0.981197 N1 -0.136382 -0.136382 0.981224 N2 -0.275025 -0.275025 0.921262 + txt003 +STRI + V0 -0.875009 -0.875009 2.46389 V1 -0.626246 -1.06626 2.46389 V2 -0.538261 -0.916455 2.51111 + N0 -0.275025 -0.275025 0.921262 N1 -0.195261 -0.336657 0.92116 N2 -0.0968361 -0.166959 0.981197 + txt003 +STRI + V0 -0.752074 -0.752074 2.51111 V1 -0.916455 -0.538261 2.51111 V2 -1.06626 -0.626246 2.46389 + N0 -0.136382 -0.136382 0.981224 N1 -0.166959 -0.0968361 0.981197 N2 -0.336657 -0.195261 0.92116 + txt003 +STRI + V0 -1.06626 -0.626246 2.46389 V1 -0.875009 -0.875009 2.46389 V2 -0.752074 -0.752074 2.51111 + N0 -0.336657 -0.195261 0.92116 N1 -0.275025 -0.275025 0.921262 N2 -0.136382 -0.136382 0.981224 + txt003 +STRI + V0 -0.916455 -0.538261 2.51111 V1 -1.02199 -0.284431 2.51111 V2 -1.18904 -0.330924 2.46389 + N0 -0.166959 -0.0968361 0.981197 N1 -0.186699 -0.0503275 0.981127 N2 -0.376378 -0.101459 0.920894 + txt003 +STRI + V0 -1.18904 -0.330924 2.46389 V1 -1.06626 -0.626246 2.46389 V2 -0.916455 -0.538261 2.51111 + N0 -0.376378 -0.101459 0.920894 N1 -0.336657 -0.195261 0.92116 N2 -0.166959 -0.0968361 0.981197 + txt003 +STRI + V0 -1.02199 -0.284431 2.51111 V1 -1.05926 -4.44089e-16 2.51111 V2 -1.23241 -4.44089e-16 2.46389 + N0 -0.186699 -0.0503275 0.981127 N1 -0.193633 7.24819e-17 0.981074 N2 -0.390293 8.37138e-17 0.920691 + txt003 +STRI + V0 -1.23241 -4.44089e-16 2.46389 V1 -1.18904 -0.330924 2.46389 V2 -1.02199 -0.284431 2.51111 + N0 -0.390293 8.37138e-17 0.920691 N1 -0.376378 -0.101459 0.920894 N2 -0.186699 -0.0503275 0.981127 + txt003 +STRI + V0 0 -1.23241 2.46389 V1 -0.330924 -1.18904 2.46389 V2 -0.349074 -1.25426 2.4 + N0 0 -0.390293 0.920691 N1 -0.101459 -0.376378 0.920894 N2 -0.260275 -0.965535 -1.02004e-15 + txt003 +STRI + V0 -0.349074 -1.25426 2.4 V1 0 -1.3 2.4 V2 0 -1.23241 2.46389 + N0 -0.260275 -0.965535 -1.02004e-15 N1 -0 -1 -9.86865e-16 N2 0 -0.390293 0.920691 + txt003 +STRI + V0 -0.330924 -1.18904 2.46389 V1 -0.626246 -1.06626 2.46389 V2 -0.660593 -1.12474 2.4 + N0 -0.101459 -0.376378 0.920894 N1 -0.195261 -0.336657 0.92116 N2 -0.501718 -0.865031 -9.69705e-16 + txt003 +STRI + V0 -0.660593 -1.12474 2.4 V1 -0.349074 -1.25426 2.4 V2 -0.330924 -1.18904 2.46389 + N0 -0.501718 -0.865031 -9.69705e-16 N1 -0.260275 -0.965535 -1.02004e-15 N2 -0.101459 -0.376378 0.920894 + txt003 +STRI + V0 -0.626246 -1.06626 2.46389 V1 -0.875009 -0.875009 2.46389 V2 -0.923 -0.923 2.4 + N0 -0.195261 -0.336657 0.92116 N1 -0.275025 -0.275025 0.921262 N2 -0.707107 -0.707107 -7.41433e-16 + txt003 +STRI + V0 -0.923 -0.923 2.4 V1 -0.660593 -1.12474 2.4 V2 -0.626246 -1.06626 2.46389 + N0 -0.707107 -0.707107 -7.41433e-16 N1 -0.501718 -0.865031 -9.69705e-16 N2 -0.195261 -0.336657 0.92116 + txt003 +STRI + V0 -0.875009 -0.875009 2.46389 V1 -1.06626 -0.626246 2.46389 V2 -1.12474 -0.660593 2.4 + N0 -0.275025 -0.275025 0.921262 N1 -0.336657 -0.195261 0.92116 N2 -0.865031 -0.501718 -4.67305e-16 + txt003 +STRI + V0 -1.12474 -0.660593 2.4 V1 -0.923 -0.923 2.4 V2 -0.875009 -0.875009 2.46389 + N0 -0.865031 -0.501718 -4.67305e-16 N1 -0.707107 -0.707107 -7.41433e-16 N2 -0.275025 -0.275025 0.921262 + txt003 +STRI + V0 -1.06626 -0.626246 2.46389 V1 -1.18904 -0.330924 2.46389 V2 -1.25426 -0.349074 2.4 + N0 -0.336657 -0.195261 0.92116 N1 -0.376378 -0.101459 0.920894 N2 -0.965535 -0.260275 -5.24893e-16 + txt003 +STRI + V0 -1.25426 -0.349074 2.4 V1 -1.12474 -0.660593 2.4 V2 -1.06626 -0.626246 2.46389 + N0 -0.965535 -0.260275 -5.24893e-16 N1 -0.865031 -0.501718 -4.67305e-16 N2 -0.336657 -0.195261 0.92116 + txt003 +STRI + V0 -1.18904 -0.330924 2.46389 V1 -1.23241 -4.44089e-16 2.46389 V2 -1.3 -6.66134e-16 2.4 + N0 -0.376378 -0.101459 0.920894 N1 -0.390293 8.37138e-17 0.920691 N2 -1 4.06675e-16 -1.4803e-15 + txt003 +STRI + V0 -1.3 -6.66134e-16 2.4 V1 -1.25426 -0.349074 2.4 V2 -1.18904 -0.330924 2.46389 + N0 -1 4.06675e-16 -1.4803e-15 N1 -0.965535 -0.260275 -5.24893e-16 N2 -0.376378 -0.101459 0.920894 + txt003 +STRI + V0 -0.2 0 2.7 V1 -0.192963 0.0537037 2.7 V2 -0.338579 0.0942301 2.63611 + N0 -0.6 0 0.8 N1 -0.578783 0.15602 0.800417 N2 -0.258756 0.0697517 0.963421 + txt003 +STRI + V0 -0.338579 0.0942301 2.63611 V1 -0.350926 0 2.63611 V2 -0.2 0 2.7 + N0 -0.258756 0.0697517 0.963421 N1 -0.268354 0 0.96332 N2 -0.6 0 0.8 + txt003 +STRI + V0 -0.192963 0.0537037 2.7 V1 -0.173037 0.10163 2.7 V2 -0.303616 0.178322 2.63611 + N0 -0.578783 0.15602 0.800417 N1 -0.517905 0.300385 0.800964 N2 -0.231413 0.134219 0.963552 + txt003 +STRI + V0 -0.303616 0.178322 2.63611 V1 -0.338579 0.0942301 2.63611 V2 -0.192963 0.0537037 2.7 + N0 -0.231413 0.134219 0.963552 N1 -0.258756 0.0697517 0.963421 N2 -0.578783 0.15602 0.800417 + txt003 +STRI + V0 -0.173037 0.10163 2.7 V1 -0.142 0.142 2.7 V2 -0.249157 0.249157 2.63611 + N0 -0.517905 0.300385 0.800964 N1 -0.423155 0.423155 0.801174 N2 -0.189037 0.189037 0.963603 + txt003 +STRI + V0 -0.249157 0.249157 2.63611 V1 -0.303616 0.178322 2.63611 V2 -0.173037 0.10163 2.7 + N0 -0.189037 0.189037 0.963603 N1 -0.231413 0.134219 0.963552 N2 -0.517905 0.300385 0.800964 + txt003 +STRI + V0 -0.142 0.142 2.7 V1 -0.10163 0.173037 2.7 V2 -0.178322 0.303616 2.63611 + N0 -0.423155 0.423155 0.801174 N1 -0.300385 0.517905 0.800964 N2 -0.134219 0.231413 0.963552 + txt003 +STRI + V0 -0.178322 0.303616 2.63611 V1 -0.249157 0.249157 2.63611 V2 -0.142 0.142 2.7 + N0 -0.134219 0.231413 0.963552 N1 -0.189037 0.189037 0.963603 N2 -0.423155 0.423155 0.801174 + txt003 +STRI + V0 -0.10163 0.173037 2.7 V1 -0.0537037 0.192963 2.7 V2 -0.0942301 0.338579 2.63611 + N0 -0.300385 0.517905 0.800964 N1 -0.15602 0.578783 0.800417 N2 -0.0697517 0.258756 0.963421 + txt003 +STRI + V0 -0.0942301 0.338579 2.63611 V1 -0.178322 0.303616 2.63611 V2 -0.10163 0.173037 2.7 + N0 -0.0697517 0.258756 0.963421 N1 -0.134219 0.231413 0.963552 N2 -0.300385 0.517905 0.800964 + txt003 +STRI + V0 -0.0537037 0.192963 2.7 V1 0 0.2 2.7 V2 -5.55112e-17 0.350926 2.63611 + N0 -0.15602 0.578783 0.800417 N1 9.91271e-17 0.6 0.8 N2 -0 0.268354 0.96332 + txt003 +STRI + V0 -5.55112e-17 0.350926 2.63611 V1 -0.0942301 0.338579 2.63611 V2 -0.0537037 0.192963 2.7 + N0 -0 0.268354 0.96332 N1 -0.0697517 0.258756 0.963421 N2 -0.15602 0.578783 0.800417 + txt003 +STRI + V0 -0.350926 0 2.63611 V1 -0.338579 0.0942301 2.63611 V2 -0.553875 0.15415 2.58889 + N0 -0.268354 0 0.96332 N1 -0.258756 0.0697517 0.963421 N2 -0.162011 0.0436726 0.985822 + txt003 +STRI + V0 -0.553875 0.15415 2.58889 V1 -0.574074 0 2.58889 V2 -0.350926 0 2.63611 + N0 -0.162011 0.0436726 0.985822 N1 -0.168031 0 0.985782 N2 -0.268354 0 0.96332 + txt003 +STRI + V0 -0.338579 0.0942301 2.63611 V1 -0.303616 0.178322 2.63611 V2 -0.49668 0.291715 2.58889 + N0 -0.258756 0.0697517 0.963421 N1 -0.231413 0.134219 0.963552 N2 -0.144879 0.0840299 0.985875 + txt003 +STRI + V0 -0.49668 0.291715 2.58889 V1 -0.553875 0.15415 2.58889 V2 -0.338579 0.0942301 2.63611 + N0 -0.144879 0.0840299 0.985875 N1 -0.162011 0.0436726 0.985822 N2 -0.258756 0.0697517 0.963421 + txt003 +STRI + V0 -0.303616 0.178322 2.63611 V1 -0.249157 0.249157 2.63611 V2 -0.407593 0.407593 2.58889 + N0 -0.231413 0.134219 0.963552 N1 -0.189037 0.189037 0.963603 N2 -0.118345 0.118345 0.985895 + txt003 +STRI + V0 -0.407593 0.407593 2.58889 V1 -0.49668 0.291715 2.58889 V2 -0.303616 0.178322 2.63611 + N0 -0.118345 0.118345 0.985895 N1 -0.144879 0.0840299 0.985875 N2 -0.231413 0.134219 0.963552 + txt003 +STRI + V0 -0.249157 0.249157 2.63611 V1 -0.178322 0.303616 2.63611 V2 -0.291715 0.49668 2.58889 + N0 -0.189037 0.189037 0.963603 N1 -0.134219 0.231413 0.963552 N2 -0.0840299 0.144879 0.985875 + txt003 +STRI + V0 -0.291715 0.49668 2.58889 V1 -0.407593 0.407593 2.58889 V2 -0.249157 0.249157 2.63611 + N0 -0.0840299 0.144879 0.985875 N1 -0.118345 0.118345 0.985895 N2 -0.189037 0.189037 0.963603 + txt003 +STRI + V0 -0.178322 0.303616 2.63611 V1 -0.0942301 0.338579 2.63611 V2 -0.15415 0.553875 2.58889 + N0 -0.134219 0.231413 0.963552 N1 -0.0697517 0.258756 0.963421 N2 -0.0436726 0.162011 0.985822 + txt003 +STRI + V0 -0.15415 0.553875 2.58889 V1 -0.291715 0.49668 2.58889 V2 -0.178322 0.303616 2.63611 + N0 -0.0436726 0.162011 0.985822 N1 -0.0840299 0.144879 0.985875 N2 -0.134219 0.231413 0.963552 + txt003 +STRI + V0 -0.0942301 0.338579 2.63611 V1 -5.55112e-17 0.350926 2.63611 V2 -2.22045e-16 0.574074 2.58889 + N0 -0.0697517 0.258756 0.963421 N1 -0 0.268354 0.96332 N2 1.93429e-17 0.168031 0.985782 + txt003 +STRI + V0 -2.22045e-16 0.574074 2.58889 V1 -0.15415 0.553875 2.58889 V2 -0.0942301 0.338579 2.63611 + N0 1.93429e-17 0.168031 0.985782 N1 -0.0436726 0.162011 0.985822 N2 -0.0697517 0.258756 0.963421 + txt003 +STRI + V0 -0.574074 0 2.58889 V1 -0.553875 0.15415 2.58889 V2 -0.795972 0.221528 2.55 + N0 -0.168031 0 0.985782 N1 -0.162011 0.0436726 0.985822 N2 -0.143025 0.0385545 0.988968 + txt003 +STRI + V0 -0.795972 0.221528 2.55 V1 -0.825 0 2.55 V2 -0.574074 0 2.58889 + N0 -0.143025 0.0385545 0.988968 N1 -0.14834 0 0.988936 N2 -0.168031 0 0.985782 + txt003 +STRI + V0 -0.553875 0.15415 2.58889 V1 -0.49668 0.291715 2.58889 V2 -0.713778 0.419222 2.55 + N0 -0.162011 0.0436726 0.985822 N1 -0.144879 0.0840299 0.985875 N2 -0.127899 0.0741814 0.989009 + txt003 +STRI + V0 -0.713778 0.419222 2.55 V1 -0.795972 0.221528 2.55 V2 -0.553875 0.15415 2.58889 + N0 -0.127899 0.0741814 0.989009 N1 -0.143025 0.0385545 0.988968 N2 -0.162011 0.0436726 0.985822 + txt003 +STRI + V0 -0.49668 0.291715 2.58889 V1 -0.407593 0.407593 2.58889 V2 -0.58575 0.58575 2.55 + N0 -0.144879 0.0840299 0.985875 N1 -0.118345 0.118345 0.985895 N2 -0.104474 0.104474 0.989025 + txt003 +STRI + V0 -0.58575 0.58575 2.55 V1 -0.713778 0.419222 2.55 V2 -0.49668 0.291715 2.58889 + N0 -0.104474 0.104474 0.989025 N1 -0.127899 0.0741814 0.989009 N2 -0.144879 0.0840299 0.985875 + txt003 +STRI + V0 -0.407593 0.407593 2.58889 V1 -0.291715 0.49668 2.58889 V2 -0.419222 0.713778 2.55 + N0 -0.118345 0.118345 0.985895 N1 -0.0840299 0.144879 0.985875 N2 -0.0741814 0.127899 0.989009 + txt003 +STRI + V0 -0.419222 0.713778 2.55 V1 -0.58575 0.58575 2.55 V2 -0.407593 0.407593 2.58889 + N0 -0.0741814 0.127899 0.989009 N1 -0.104474 0.104474 0.989025 N2 -0.118345 0.118345 0.985895 + txt003 +STRI + V0 -0.291715 0.49668 2.58889 V1 -0.15415 0.553875 2.58889 V2 -0.221528 0.795972 2.55 + N0 -0.0840299 0.144879 0.985875 N1 -0.0436726 0.162011 0.985822 N2 -0.0385545 0.143025 0.988968 + txt003 +STRI + V0 -0.221528 0.795972 2.55 V1 -0.419222 0.713778 2.55 V2 -0.291715 0.49668 2.58889 + N0 -0.0385545 0.143025 0.988968 N1 -0.0741814 0.127899 0.989009 N2 -0.0840299 0.144879 0.985875 + txt003 +STRI + V0 -0.15415 0.553875 2.58889 V1 -2.22045e-16 0.574074 2.58889 V2 -1.11022e-16 0.825 2.55 + N0 -0.0436726 0.162011 0.985822 N1 1.93429e-17 0.168031 0.985782 N2 2.37649e-17 0.14834 0.988936 + txt003 +STRI + V0 -1.11022e-16 0.825 2.55 V1 -0.221528 0.795972 2.55 V2 -0.15415 0.553875 2.58889 + N0 2.37649e-17 0.14834 0.988936 N1 -0.0385545 0.143025 0.988968 N2 -0.0436726 0.162011 0.985822 + txt003 +STRI + V0 -0.825 0 2.55 V1 -0.795972 0.221528 2.55 V2 -1.02199 0.284431 2.51111 + N0 -0.14834 0 0.988936 N1 -0.143025 0.0385545 0.988968 N2 -0.186699 0.0503275 0.981127 + txt003 +STRI + V0 -1.02199 0.284431 2.51111 V1 -1.05926 0 2.51111 V2 -0.825 0 2.55 + N0 -0.186699 0.0503275 0.981127 N1 -0.193633 0 0.981074 N2 -0.14834 0 0.988936 + txt003 +STRI + V0 -0.795972 0.221528 2.55 V1 -0.713778 0.419222 2.55 V2 -0.916455 0.538261 2.51111 + N0 -0.143025 0.0385545 0.988968 N1 -0.127899 0.0741814 0.989009 N2 -0.166959 0.0968361 0.981197 + txt003 +STRI + V0 -0.916455 0.538261 2.51111 V1 -1.02199 0.284431 2.51111 V2 -0.795972 0.221528 2.55 + N0 -0.166959 0.0968361 0.981197 N1 -0.186699 0.0503275 0.981127 N2 -0.143025 0.0385545 0.988968 + txt003 +STRI + V0 -0.713778 0.419222 2.55 V1 -0.58575 0.58575 2.55 V2 -0.752074 0.752074 2.51111 + N0 -0.127899 0.0741814 0.989009 N1 -0.104474 0.104474 0.989025 N2 -0.136382 0.136382 0.981224 + txt003 +STRI + V0 -0.752074 0.752074 2.51111 V1 -0.916455 0.538261 2.51111 V2 -0.713778 0.419222 2.55 + N0 -0.136382 0.136382 0.981224 N1 -0.166959 0.0968361 0.981197 N2 -0.127899 0.0741814 0.989009 + txt003 +STRI + V0 -0.58575 0.58575 2.55 V1 -0.419222 0.713778 2.55 V2 -0.538261 0.916455 2.51111 + N0 -0.104474 0.104474 0.989025 N1 -0.0741814 0.127899 0.989009 N2 -0.0968361 0.166959 0.981197 + txt003 +STRI + V0 -0.538261 0.916455 2.51111 V1 -0.752074 0.752074 2.51111 V2 -0.58575 0.58575 2.55 + N0 -0.0968361 0.166959 0.981197 N1 -0.136382 0.136382 0.981224 N2 -0.104474 0.104474 0.989025 + txt003 +STRI + V0 -0.419222 0.713778 2.55 V1 -0.221528 0.795972 2.55 V2 -0.284431 1.02199 2.51111 + N0 -0.0741814 0.127899 0.989009 N1 -0.0385545 0.143025 0.988968 N2 -0.0503275 0.186699 0.981127 + txt003 +STRI + V0 -0.284431 1.02199 2.51111 V1 -0.538261 0.916455 2.51111 V2 -0.419222 0.713778 2.55 + N0 -0.0503275 0.186699 0.981127 N1 -0.0968361 0.166959 0.981197 N2 -0.0741814 0.127899 0.989009 + txt003 +STRI + V0 -0.221528 0.795972 2.55 V1 -1.11022e-16 0.825 2.55 V2 -4.44089e-16 1.05926 2.51111 + N0 -0.0385545 0.143025 0.988968 N1 2.37649e-17 0.14834 0.988936 N2 7.24819e-17 0.193633 0.981074 + txt003 +STRI + V0 -4.44089e-16 1.05926 2.51111 V1 -0.284431 1.02199 2.51111 V2 -0.221528 0.795972 2.55 + N0 7.24819e-17 0.193633 0.981074 N1 -0.0503275 0.186699 0.981127 N2 -0.0385545 0.143025 0.988968 + txt003 +STRI + V0 -1.05926 0 2.51111 V1 -1.02199 0.284431 2.51111 V2 -1.18904 0.330924 2.46389 + N0 -0.193633 0 0.981074 N1 -0.186699 0.0503275 0.981127 N2 -0.376378 0.101459 0.920894 + txt003 +STRI + V0 -1.18904 0.330924 2.46389 V1 -1.23241 0 2.46389 V2 -1.05926 0 2.51111 + N0 -0.376378 0.101459 0.920894 N1 -0.390293 0 0.920691 N2 -0.193633 0 0.981074 + txt003 +STRI + V0 -1.02199 0.284431 2.51111 V1 -0.916455 0.538261 2.51111 V2 -1.06626 0.626246 2.46389 + N0 -0.186699 0.0503275 0.981127 N1 -0.166959 0.0968361 0.981197 N2 -0.336657 0.195261 0.92116 + txt003 +STRI + V0 -1.06626 0.626246 2.46389 V1 -1.18904 0.330924 2.46389 V2 -1.02199 0.284431 2.51111 + N0 -0.336657 0.195261 0.92116 N1 -0.376378 0.101459 0.920894 N2 -0.186699 0.0503275 0.981127 + txt003 +STRI + V0 -0.916455 0.538261 2.51111 V1 -0.752074 0.752074 2.51111 V2 -0.875009 0.875009 2.46389 + N0 -0.166959 0.0968361 0.981197 N1 -0.136382 0.136382 0.981224 N2 -0.275025 0.275025 0.921262 + txt003 +STRI + V0 -0.875009 0.875009 2.46389 V1 -1.06626 0.626246 2.46389 V2 -0.916455 0.538261 2.51111 + N0 -0.275025 0.275025 0.921262 N1 -0.336657 0.195261 0.92116 N2 -0.166959 0.0968361 0.981197 + txt003 +STRI + V0 -0.752074 0.752074 2.51111 V1 -0.538261 0.916455 2.51111 V2 -0.626246 1.06626 2.46389 + N0 -0.136382 0.136382 0.981224 N1 -0.0968361 0.166959 0.981197 N2 -0.195261 0.336657 0.92116 + txt003 +STRI + V0 -0.626246 1.06626 2.46389 V1 -0.875009 0.875009 2.46389 V2 -0.752074 0.752074 2.51111 + N0 -0.195261 0.336657 0.92116 N1 -0.275025 0.275025 0.921262 N2 -0.136382 0.136382 0.981224 + txt003 +STRI + V0 -0.538261 0.916455 2.51111 V1 -0.284431 1.02199 2.51111 V2 -0.330924 1.18904 2.46389 + N0 -0.0968361 0.166959 0.981197 N1 -0.0503275 0.186699 0.981127 N2 -0.101459 0.376378 0.920894 + txt003 +STRI + V0 -0.330924 1.18904 2.46389 V1 -0.626246 1.06626 2.46389 V2 -0.538261 0.916455 2.51111 + N0 -0.101459 0.376378 0.920894 N1 -0.195261 0.336657 0.92116 N2 -0.0968361 0.166959 0.981197 + txt003 +STRI + V0 -0.284431 1.02199 2.51111 V1 -4.44089e-16 1.05926 2.51111 V2 -4.44089e-16 1.23241 2.46389 + N0 -0.0503275 0.186699 0.981127 N1 7.24819e-17 0.193633 0.981074 N2 8.37138e-17 0.390293 0.920691 + txt003 +STRI + V0 -4.44089e-16 1.23241 2.46389 V1 -0.330924 1.18904 2.46389 V2 -0.284431 1.02199 2.51111 + N0 8.37138e-17 0.390293 0.920691 N1 -0.101459 0.376378 0.920894 N2 -0.0503275 0.186699 0.981127 + txt003 +STRI + V0 -1.23241 0 2.46389 V1 -1.18904 0.330924 2.46389 V2 -1.25426 0.349074 2.4 + N0 -0.390293 0 0.920691 N1 -0.376378 0.101459 0.920894 N2 -0.965535 0.260275 -1.02004e-15 + txt003 +STRI + V0 -1.25426 0.349074 2.4 V1 -1.3 0 2.4 V2 -1.23241 0 2.46389 + N0 -0.965535 0.260275 -1.02004e-15 N1 -1 0 -9.86865e-16 N2 -0.390293 0 0.920691 + txt003 +STRI + V0 -1.18904 0.330924 2.46389 V1 -1.06626 0.626246 2.46389 V2 -1.12474 0.660593 2.4 + N0 -0.376378 0.101459 0.920894 N1 -0.336657 0.195261 0.92116 N2 -0.865031 0.501718 -9.69705e-16 + txt003 +STRI + V0 -1.12474 0.660593 2.4 V1 -1.25426 0.349074 2.4 V2 -1.18904 0.330924 2.46389 + N0 -0.865031 0.501718 -9.69705e-16 N1 -0.965535 0.260275 -1.02004e-15 N2 -0.376378 0.101459 0.920894 + txt003 +STRI + V0 -1.06626 0.626246 2.46389 V1 -0.875009 0.875009 2.46389 V2 -0.923 0.923 2.4 + N0 -0.336657 0.195261 0.92116 N1 -0.275025 0.275025 0.921262 N2 -0.707107 0.707107 -7.41433e-16 + txt003 +STRI + V0 -0.923 0.923 2.4 V1 -1.12474 0.660593 2.4 V2 -1.06626 0.626246 2.46389 + N0 -0.707107 0.707107 -7.41433e-16 N1 -0.865031 0.501718 -9.69705e-16 N2 -0.336657 0.195261 0.92116 + txt003 +STRI + V0 -0.875009 0.875009 2.46389 V1 -0.626246 1.06626 2.46389 V2 -0.660593 1.12474 2.4 + N0 -0.275025 0.275025 0.921262 N1 -0.195261 0.336657 0.92116 N2 -0.501718 0.865031 -4.67305e-16 + txt003 +STRI + V0 -0.660593 1.12474 2.4 V1 -0.923 0.923 2.4 V2 -0.875009 0.875009 2.46389 + N0 -0.501718 0.865031 -4.67305e-16 N1 -0.707107 0.707107 -7.41433e-16 N2 -0.275025 0.275025 0.921262 + txt003 +STRI + V0 -0.626246 1.06626 2.46389 V1 -0.330924 1.18904 2.46389 V2 -0.349074 1.25426 2.4 + N0 -0.195261 0.336657 0.92116 N1 -0.101459 0.376378 0.920894 N2 -0.260275 0.965535 -5.24893e-16 + txt003 +STRI + V0 -0.349074 1.25426 2.4 V1 -0.660593 1.12474 2.4 V2 -0.626246 1.06626 2.46389 + N0 -0.260275 0.965535 -5.24893e-16 N1 -0.501718 0.865031 -4.67305e-16 N2 -0.195261 0.336657 0.92116 + txt003 +STRI + V0 -0.330924 1.18904 2.46389 V1 -4.44089e-16 1.23241 2.46389 V2 -6.66134e-16 1.3 2.4 + N0 -0.101459 0.376378 0.920894 N1 8.37138e-17 0.390293 0.920691 N2 4.06675e-16 1 -1.4803e-15 + txt003 +STRI + V0 -6.66134e-16 1.3 2.4 V1 -0.349074 1.25426 2.4 V2 -0.330924 1.18904 2.46389 + N0 4.06675e-16 1 -1.4803e-15 N1 -0.260275 0.965535 -5.24893e-16 N2 -0.101459 0.376378 0.920894 + txt003 +STRI + V0 0 0.2 2.7 V1 0.0537037 0.192963 2.7 V2 0.0942301 0.338579 2.63611 + N0 -0 0.6 0.8 N1 0.15602 0.578783 0.800417 N2 0.0697517 0.258756 0.963421 + txt003 +STRI + V0 0.0942301 0.338579 2.63611 V1 0 0.350926 2.63611 V2 0 0.2 2.7 + N0 0.0697517 0.258756 0.963421 N1 -0 0.268354 0.96332 N2 -0 0.6 0.8 + txt003 +STRI + V0 0.0537037 0.192963 2.7 V1 0.10163 0.173037 2.7 V2 0.178322 0.303616 2.63611 + N0 0.15602 0.578783 0.800417 N1 0.300385 0.517905 0.800964 N2 0.134219 0.231413 0.963552 + txt003 +STRI + V0 0.178322 0.303616 2.63611 V1 0.0942301 0.338579 2.63611 V2 0.0537037 0.192963 2.7 + N0 0.134219 0.231413 0.963552 N1 0.0697517 0.258756 0.963421 N2 0.15602 0.578783 0.800417 + txt003 +STRI + V0 0.10163 0.173037 2.7 V1 0.142 0.142 2.7 V2 0.249157 0.249157 2.63611 + N0 0.300385 0.517905 0.800964 N1 0.423155 0.423155 0.801174 N2 0.189037 0.189037 0.963603 + txt003 +STRI + V0 0.249157 0.249157 2.63611 V1 0.178322 0.303616 2.63611 V2 0.10163 0.173037 2.7 + N0 0.189037 0.189037 0.963603 N1 0.134219 0.231413 0.963552 N2 0.300385 0.517905 0.800964 + txt003 +STRI + V0 0.142 0.142 2.7 V1 0.173037 0.10163 2.7 V2 0.303616 0.178322 2.63611 + N0 0.423155 0.423155 0.801174 N1 0.517905 0.300385 0.800964 N2 0.231413 0.134219 0.963552 + txt003 +STRI + V0 0.303616 0.178322 2.63611 V1 0.249157 0.249157 2.63611 V2 0.142 0.142 2.7 + N0 0.231413 0.134219 0.963552 N1 0.189037 0.189037 0.963603 N2 0.423155 0.423155 0.801174 + txt003 +STRI + V0 0.173037 0.10163 2.7 V1 0.192963 0.0537037 2.7 V2 0.338579 0.0942301 2.63611 + N0 0.517905 0.300385 0.800964 N1 0.578783 0.15602 0.800417 N2 0.258756 0.0697517 0.963421 + txt003 +STRI + V0 0.338579 0.0942301 2.63611 V1 0.303616 0.178322 2.63611 V2 0.173037 0.10163 2.7 + N0 0.258756 0.0697517 0.963421 N1 0.231413 0.134219 0.963552 N2 0.517905 0.300385 0.800964 + txt003 +STRI + V0 0.192963 0.0537037 2.7 V1 0.2 0 2.7 V2 0.350926 5.55112e-17 2.63611 + N0 0.578783 0.15602 0.800417 N1 0.6 -9.91271e-17 0.8 N2 0.268354 0 0.96332 + txt003 +STRI + V0 0.350926 5.55112e-17 2.63611 V1 0.338579 0.0942301 2.63611 V2 0.192963 0.0537037 2.7 + N0 0.268354 0 0.96332 N1 0.258756 0.0697517 0.963421 N2 0.578783 0.15602 0.800417 + txt003 +STRI + V0 0 0.350926 2.63611 V1 0.0942301 0.338579 2.63611 V2 0.15415 0.553875 2.58889 + N0 -0 0.268354 0.96332 N1 0.0697517 0.258756 0.963421 N2 0.0436726 0.162011 0.985822 + txt003 +STRI + V0 0.15415 0.553875 2.58889 V1 0 0.574074 2.58889 V2 0 0.350926 2.63611 + N0 0.0436726 0.162011 0.985822 N1 -0 0.168031 0.985782 N2 -0 0.268354 0.96332 + txt003 +STRI + V0 0.0942301 0.338579 2.63611 V1 0.178322 0.303616 2.63611 V2 0.291715 0.49668 2.58889 + N0 0.0697517 0.258756 0.963421 N1 0.134219 0.231413 0.963552 N2 0.0840299 0.144879 0.985875 + txt003 +STRI + V0 0.291715 0.49668 2.58889 V1 0.15415 0.553875 2.58889 V2 0.0942301 0.338579 2.63611 + N0 0.0840299 0.144879 0.985875 N1 0.0436726 0.162011 0.985822 N2 0.0697517 0.258756 0.963421 + txt003 +STRI + V0 0.178322 0.303616 2.63611 V1 0.249157 0.249157 2.63611 V2 0.407593 0.407593 2.58889 + N0 0.134219 0.231413 0.963552 N1 0.189037 0.189037 0.963603 N2 0.118345 0.118345 0.985895 + txt003 +STRI + V0 0.407593 0.407593 2.58889 V1 0.291715 0.49668 2.58889 V2 0.178322 0.303616 2.63611 + N0 0.118345 0.118345 0.985895 N1 0.0840299 0.144879 0.985875 N2 0.134219 0.231413 0.963552 + txt003 +STRI + V0 0.249157 0.249157 2.63611 V1 0.303616 0.178322 2.63611 V2 0.49668 0.291715 2.58889 + N0 0.189037 0.189037 0.963603 N1 0.231413 0.134219 0.963552 N2 0.144879 0.0840299 0.985875 + txt003 +STRI + V0 0.49668 0.291715 2.58889 V1 0.407593 0.407593 2.58889 V2 0.249157 0.249157 2.63611 + N0 0.144879 0.0840299 0.985875 N1 0.118345 0.118345 0.985895 N2 0.189037 0.189037 0.963603 + txt003 +STRI + V0 0.303616 0.178322 2.63611 V1 0.338579 0.0942301 2.63611 V2 0.553875 0.15415 2.58889 + N0 0.231413 0.134219 0.963552 N1 0.258756 0.0697517 0.963421 N2 0.162011 0.0436726 0.985822 + txt003 +STRI + V0 0.553875 0.15415 2.58889 V1 0.49668 0.291715 2.58889 V2 0.303616 0.178322 2.63611 + N0 0.162011 0.0436726 0.985822 N1 0.144879 0.0840299 0.985875 N2 0.231413 0.134219 0.963552 + txt003 +STRI + V0 0.338579 0.0942301 2.63611 V1 0.350926 5.55112e-17 2.63611 V2 0.574074 2.22045e-16 2.58889 + N0 0.258756 0.0697517 0.963421 N1 0.268354 0 0.96332 N2 0.168031 -1.93429e-17 0.985782 + txt003 +STRI + V0 0.574074 2.22045e-16 2.58889 V1 0.553875 0.15415 2.58889 V2 0.338579 0.0942301 2.63611 + N0 0.168031 -1.93429e-17 0.985782 N1 0.162011 0.0436726 0.985822 N2 0.258756 0.0697517 0.963421 + txt003 +STRI + V0 0 0.574074 2.58889 V1 0.15415 0.553875 2.58889 V2 0.221528 0.795972 2.55 + N0 -0 0.168031 0.985782 N1 0.0436726 0.162011 0.985822 N2 0.0385545 0.143025 0.988968 + txt003 +STRI + V0 0.221528 0.795972 2.55 V1 0 0.825 2.55 V2 0 0.574074 2.58889 + N0 0.0385545 0.143025 0.988968 N1 -0 0.14834 0.988936 N2 -0 0.168031 0.985782 + txt003 +STRI + V0 0.15415 0.553875 2.58889 V1 0.291715 0.49668 2.58889 V2 0.419222 0.713778 2.55 + N0 0.0436726 0.162011 0.985822 N1 0.0840299 0.144879 0.985875 N2 0.0741814 0.127899 0.989009 + txt003 +STRI + V0 0.419222 0.713778 2.55 V1 0.221528 0.795972 2.55 V2 0.15415 0.553875 2.58889 + N0 0.0741814 0.127899 0.989009 N1 0.0385545 0.143025 0.988968 N2 0.0436726 0.162011 0.985822 + txt003 +STRI + V0 0.291715 0.49668 2.58889 V1 0.407593 0.407593 2.58889 V2 0.58575 0.58575 2.55 + N0 0.0840299 0.144879 0.985875 N1 0.118345 0.118345 0.985895 N2 0.104474 0.104474 0.989025 + txt003 +STRI + V0 0.58575 0.58575 2.55 V1 0.419222 0.713778 2.55 V2 0.291715 0.49668 2.58889 + N0 0.104474 0.104474 0.989025 N1 0.0741814 0.127899 0.989009 N2 0.0840299 0.144879 0.985875 + txt003 +STRI + V0 0.407593 0.407593 2.58889 V1 0.49668 0.291715 2.58889 V2 0.713778 0.419222 2.55 + N0 0.118345 0.118345 0.985895 N1 0.144879 0.0840299 0.985875 N2 0.127899 0.0741814 0.989009 + txt003 +STRI + V0 0.713778 0.419222 2.55 V1 0.58575 0.58575 2.55 V2 0.407593 0.407593 2.58889 + N0 0.127899 0.0741814 0.989009 N1 0.104474 0.104474 0.989025 N2 0.118345 0.118345 0.985895 + txt003 +STRI + V0 0.49668 0.291715 2.58889 V1 0.553875 0.15415 2.58889 V2 0.795972 0.221528 2.55 + N0 0.144879 0.0840299 0.985875 N1 0.162011 0.0436726 0.985822 N2 0.143025 0.0385545 0.988968 + txt003 +STRI + V0 0.795972 0.221528 2.55 V1 0.713778 0.419222 2.55 V2 0.49668 0.291715 2.58889 + N0 0.143025 0.0385545 0.988968 N1 0.127899 0.0741814 0.989009 N2 0.144879 0.0840299 0.985875 + txt003 +STRI + V0 0.553875 0.15415 2.58889 V1 0.574074 2.22045e-16 2.58889 V2 0.825 1.11022e-16 2.55 + N0 0.162011 0.0436726 0.985822 N1 0.168031 -1.93429e-17 0.985782 N2 0.14834 -2.37649e-17 0.988936 + txt003 +STRI + V0 0.825 1.11022e-16 2.55 V1 0.795972 0.221528 2.55 V2 0.553875 0.15415 2.58889 + N0 0.14834 -2.37649e-17 0.988936 N1 0.143025 0.0385545 0.988968 N2 0.162011 0.0436726 0.985822 + txt003 +STRI + V0 0 0.825 2.55 V1 0.221528 0.795972 2.55 V2 0.284431 1.02199 2.51111 + N0 -0 0.14834 0.988936 N1 0.0385545 0.143025 0.988968 N2 0.0503275 0.186699 0.981127 + txt003 +STRI + V0 0.284431 1.02199 2.51111 V1 0 1.05926 2.51111 V2 0 0.825 2.55 + N0 0.0503275 0.186699 0.981127 N1 -0 0.193633 0.981074 N2 -0 0.14834 0.988936 + txt003 +STRI + V0 0.221528 0.795972 2.55 V1 0.419222 0.713778 2.55 V2 0.538261 0.916455 2.51111 + N0 0.0385545 0.143025 0.988968 N1 0.0741814 0.127899 0.989009 N2 0.0968361 0.166959 0.981197 + txt003 +STRI + V0 0.538261 0.916455 2.51111 V1 0.284431 1.02199 2.51111 V2 0.221528 0.795972 2.55 + N0 0.0968361 0.166959 0.981197 N1 0.0503275 0.186699 0.981127 N2 0.0385545 0.143025 0.988968 + txt003 +STRI + V0 0.419222 0.713778 2.55 V1 0.58575 0.58575 2.55 V2 0.752074 0.752074 2.51111 + N0 0.0741814 0.127899 0.989009 N1 0.104474 0.104474 0.989025 N2 0.136382 0.136382 0.981224 + txt003 +STRI + V0 0.752074 0.752074 2.51111 V1 0.538261 0.916455 2.51111 V2 0.419222 0.713778 2.55 + N0 0.136382 0.136382 0.981224 N1 0.0968361 0.166959 0.981197 N2 0.0741814 0.127899 0.989009 + txt003 +STRI + V0 0.58575 0.58575 2.55 V1 0.713778 0.419222 2.55 V2 0.916455 0.538261 2.51111 + N0 0.104474 0.104474 0.989025 N1 0.127899 0.0741814 0.989009 N2 0.166959 0.0968361 0.981197 + txt003 +STRI + V0 0.916455 0.538261 2.51111 V1 0.752074 0.752074 2.51111 V2 0.58575 0.58575 2.55 + N0 0.166959 0.0968361 0.981197 N1 0.136382 0.136382 0.981224 N2 0.104474 0.104474 0.989025 + txt003 +STRI + V0 0.713778 0.419222 2.55 V1 0.795972 0.221528 2.55 V2 1.02199 0.284431 2.51111 + N0 0.127899 0.0741814 0.989009 N1 0.143025 0.0385545 0.988968 N2 0.186699 0.0503275 0.981127 + txt003 +STRI + V0 1.02199 0.284431 2.51111 V1 0.916455 0.538261 2.51111 V2 0.713778 0.419222 2.55 + N0 0.186699 0.0503275 0.981127 N1 0.166959 0.0968361 0.981197 N2 0.127899 0.0741814 0.989009 + txt003 +STRI + V0 0.795972 0.221528 2.55 V1 0.825 1.11022e-16 2.55 V2 1.05926 4.44089e-16 2.51111 + N0 0.143025 0.0385545 0.988968 N1 0.14834 -2.37649e-17 0.988936 N2 0.193633 -7.24819e-17 0.981074 + txt003 +STRI + V0 1.05926 4.44089e-16 2.51111 V1 1.02199 0.284431 2.51111 V2 0.795972 0.221528 2.55 + N0 0.193633 -7.24819e-17 0.981074 N1 0.186699 0.0503275 0.981127 N2 0.143025 0.0385545 0.988968 + txt003 +STRI + V0 0 1.05926 2.51111 V1 0.284431 1.02199 2.51111 V2 0.330924 1.18904 2.46389 + N0 -0 0.193633 0.981074 N1 0.0503275 0.186699 0.981127 N2 0.101459 0.376378 0.920894 + txt003 +STRI + V0 0.330924 1.18904 2.46389 V1 0 1.23241 2.46389 V2 0 1.05926 2.51111 + N0 0.101459 0.376378 0.920894 N1 -0 0.390293 0.920691 N2 -0 0.193633 0.981074 + txt003 +STRI + V0 0.284431 1.02199 2.51111 V1 0.538261 0.916455 2.51111 V2 0.626246 1.06626 2.46389 + N0 0.0503275 0.186699 0.981127 N1 0.0968361 0.166959 0.981197 N2 0.195261 0.336657 0.92116 + txt003 +STRI + V0 0.626246 1.06626 2.46389 V1 0.330924 1.18904 2.46389 V2 0.284431 1.02199 2.51111 + N0 0.195261 0.336657 0.92116 N1 0.101459 0.376378 0.920894 N2 0.0503275 0.186699 0.981127 + txt003 +STRI + V0 0.538261 0.916455 2.51111 V1 0.752074 0.752074 2.51111 V2 0.875009 0.875009 2.46389 + N0 0.0968361 0.166959 0.981197 N1 0.136382 0.136382 0.981224 N2 0.275025 0.275025 0.921262 + txt003 +STRI + V0 0.875009 0.875009 2.46389 V1 0.626246 1.06626 2.46389 V2 0.538261 0.916455 2.51111 + N0 0.275025 0.275025 0.921262 N1 0.195261 0.336657 0.92116 N2 0.0968361 0.166959 0.981197 + txt003 +STRI + V0 0.752074 0.752074 2.51111 V1 0.916455 0.538261 2.51111 V2 1.06626 0.626246 2.46389 + N0 0.136382 0.136382 0.981224 N1 0.166959 0.0968361 0.981197 N2 0.336657 0.195261 0.92116 + txt003 +STRI + V0 1.06626 0.626246 2.46389 V1 0.875009 0.875009 2.46389 V2 0.752074 0.752074 2.51111 + N0 0.336657 0.195261 0.92116 N1 0.275025 0.275025 0.921262 N2 0.136382 0.136382 0.981224 + txt003 +STRI + V0 0.916455 0.538261 2.51111 V1 1.02199 0.284431 2.51111 V2 1.18904 0.330924 2.46389 + N0 0.166959 0.0968361 0.981197 N1 0.186699 0.0503275 0.981127 N2 0.376378 0.101459 0.920894 + txt003 +STRI + V0 1.18904 0.330924 2.46389 V1 1.06626 0.626246 2.46389 V2 0.916455 0.538261 2.51111 + N0 0.376378 0.101459 0.920894 N1 0.336657 0.195261 0.92116 N2 0.166959 0.0968361 0.981197 + txt003 +STRI + V0 1.02199 0.284431 2.51111 V1 1.05926 4.44089e-16 2.51111 V2 1.23241 4.44089e-16 2.46389 + N0 0.186699 0.0503275 0.981127 N1 0.193633 -7.24819e-17 0.981074 N2 0.390293 -8.37138e-17 0.920691 + txt003 +STRI + V0 1.23241 4.44089e-16 2.46389 V1 1.18904 0.330924 2.46389 V2 1.02199 0.284431 2.51111 + N0 0.390293 -8.37138e-17 0.920691 N1 0.376378 0.101459 0.920894 N2 0.186699 0.0503275 0.981127 + txt003 +STRI + V0 0 1.23241 2.46389 V1 0.330924 1.18904 2.46389 V2 0.349074 1.25426 2.4 + N0 -0 0.390293 0.920691 N1 0.101459 0.376378 0.920894 N2 0.260275 0.965535 -1.02004e-15 + txt003 +STRI + V0 0.349074 1.25426 2.4 V1 0 1.3 2.4 V2 0 1.23241 2.46389 + N0 0.260275 0.965535 -1.02004e-15 N1 0 1 -9.86865e-16 N2 -0 0.390293 0.920691 + txt003 +STRI + V0 0.330924 1.18904 2.46389 V1 0.626246 1.06626 2.46389 V2 0.660593 1.12474 2.4 + N0 0.101459 0.376378 0.920894 N1 0.195261 0.336657 0.92116 N2 0.501718 0.865031 -9.69705e-16 + txt003 +STRI + V0 0.660593 1.12474 2.4 V1 0.349074 1.25426 2.4 V2 0.330924 1.18904 2.46389 + N0 0.501718 0.865031 -9.69705e-16 N1 0.260275 0.965535 -1.02004e-15 N2 0.101459 0.376378 0.920894 + txt003 +STRI + V0 0.626246 1.06626 2.46389 V1 0.875009 0.875009 2.46389 V2 0.923 0.923 2.4 + N0 0.195261 0.336657 0.92116 N1 0.275025 0.275025 0.921262 N2 0.707107 0.707107 -7.41433e-16 + txt003 +STRI + V0 0.923 0.923 2.4 V1 0.660593 1.12474 2.4 V2 0.626246 1.06626 2.46389 + N0 0.707107 0.707107 -7.41433e-16 N1 0.501718 0.865031 -9.69705e-16 N2 0.195261 0.336657 0.92116 + txt003 +STRI + V0 0.875009 0.875009 2.46389 V1 1.06626 0.626246 2.46389 V2 1.12474 0.660593 2.4 + N0 0.275025 0.275025 0.921262 N1 0.336657 0.195261 0.92116 N2 0.865031 0.501718 -4.67305e-16 + txt003 +STRI + V0 1.12474 0.660593 2.4 V1 0.923 0.923 2.4 V2 0.875009 0.875009 2.46389 + N0 0.865031 0.501718 -4.67305e-16 N1 0.707107 0.707107 -7.41433e-16 N2 0.275025 0.275025 0.921262 + txt003 +STRI + V0 1.06626 0.626246 2.46389 V1 1.18904 0.330924 2.46389 V2 1.25426 0.349074 2.4 + N0 0.336657 0.195261 0.92116 N1 0.376378 0.101459 0.920894 N2 0.965535 0.260275 -5.24893e-16 + txt003 +STRI + V0 1.25426 0.349074 2.4 V1 1.12474 0.660593 2.4 V2 1.06626 0.626246 2.46389 + N0 0.965535 0.260275 -5.24893e-16 N1 0.865031 0.501718 -4.67305e-16 N2 0.336657 0.195261 0.92116 + txt003 +STRI + V0 1.18904 0.330924 2.46389 V1 1.23241 4.44089e-16 2.46389 V2 1.3 6.66134e-16 2.4 + N0 0.376378 0.101459 0.920894 N1 0.390293 -8.37138e-17 0.920691 N2 1 -4.06675e-16 -1.4803e-15 + txt003 +STRI + V0 1.3 6.66134e-16 2.4 V1 1.25426 0.349074 2.4 V2 1.18904 0.330924 2.46389 + N0 1 -4.06675e-16 -1.4803e-15 N1 0.965535 0.260275 -5.24893e-16 N2 0.376378 0.101459 0.920894 + txt003 +STRI + V0 0.584584 0.162696 0.00590278 V1 0.605903 0 0.00590278 V2 0 0 0 + N0 0.0218614 0.00589307 -0.999744 N1 0.0226746 0 -0.999743 N2 0 0 -1 + txt003 +STRI + V0 0.524218 0.307888 0.00590278 V1 0.584584 0.162696 0.00590278 V2 0 0 0 + N0 0.0195486 0.0113382 -0.999745 N1 0.0218614 0.00589307 -0.999744 N2 0 0 -1 + txt003 +STRI + V0 0.430191 0.430191 0.00590278 V1 0.524218 0.307888 0.00590278 V2 0 0 0 + N0 0.015968 0.015968 -0.999745 N1 0.0195486 0.0113382 -0.999745 N2 0 0 -1 + txt003 +STRI + V0 0.307888 0.524218 0.00590278 V1 0.430191 0.430191 0.00590278 V2 0 0 0 + N0 0.0113382 0.0195486 -0.999745 N1 0.015968 0.015968 -0.999745 N2 0 0 -1 + txt003 +STRI + V0 0.162696 0.584584 0.00590278 V1 0.307888 0.524218 0.00590278 V2 0 0 0 + N0 0.00589307 0.0218614 -0.999744 N1 0.0113382 0.0195486 -0.999745 N2 0 0 -1 + txt003 +STRI + V0 0 0.605903 0.00590278 V1 0.162696 0.584584 0.00590278 V2 0 0 0 + N0 4.94615e-18 0.0226746 -0.999743 N1 0.00589307 0.0218614 -0.999744 N2 0 0 -1 + txt003 +STRI + V0 0.605903 0 0.00590278 V1 0.584584 0.162696 0.00590278 V2 0.986255 0.274486 0.0222222 + N0 0.0226746 0 -0.999743 N1 0.0218614 0.00589307 -0.999744 N2 0.0601415 0.0162121 -0.998058 + txt003 +STRI + V0 0.986255 0.274486 0.0222222 V1 1.02222 0 0.0222222 V2 0.605903 0 0.00590278 + N0 0.0601415 0.0162121 -0.998058 N1 0.0623783 0 -0.998053 N2 0.0226746 0 -0.999743 + txt003 +STRI + V0 0.584584 0.162696 0.00590278 V1 0.524218 0.307888 0.00590278 V2 0.884412 0.51944 0.0222222 + N0 0.0218614 0.00589307 -0.999744 N1 0.0195486 0.0113382 -0.999745 N2 0.0537792 0.0311919 -0.998066 + txt003 +STRI + V0 0.884412 0.51944 0.0222222 V1 0.986255 0.274486 0.0222222 V2 0.584584 0.162696 0.00590278 + N0 0.0537792 0.0311919 -0.998066 N1 0.0601415 0.0162121 -0.998058 N2 0.0218614 0.00589307 -0.999744 + txt003 +STRI + V0 0.524218 0.307888 0.00590278 V1 0.430191 0.430191 0.00590278 V2 0.725778 0.725778 0.0222222 + N0 0.0195486 0.0113382 -0.999745 N1 0.015968 0.015968 -0.999745 N2 0.0439291 0.0439291 -0.998068 + txt003 +STRI + V0 0.725778 0.725778 0.0222222 V1 0.884412 0.51944 0.0222222 V2 0.524218 0.307888 0.00590278 + N0 0.0439291 0.0439291 -0.998068 N1 0.0537792 0.0311919 -0.998066 N2 0.0195486 0.0113382 -0.999745 + txt003 +STRI + V0 0.430191 0.430191 0.00590278 V1 0.307888 0.524218 0.00590278 V2 0.51944 0.884412 0.0222222 + N0 0.015968 0.015968 -0.999745 N1 0.0113382 0.0195486 -0.999745 N2 0.0311919 0.0537792 -0.998066 + txt003 +STRI + V0 0.51944 0.884412 0.0222222 V1 0.725778 0.725778 0.0222222 V2 0.430191 0.430191 0.00590278 + N0 0.0311919 0.0537792 -0.998066 N1 0.0439291 0.0439291 -0.998068 N2 0.015968 0.015968 -0.999745 + txt003 +STRI + V0 0.307888 0.524218 0.00590278 V1 0.162696 0.584584 0.00590278 V2 0.274486 0.986255 0.0222222 + N0 0.0113382 0.0195486 -0.999745 N1 0.00589307 0.0218614 -0.999744 N2 0.0162121 0.0601415 -0.998058 + txt003 +STRI + V0 0.274486 0.986255 0.0222222 V1 0.51944 0.884412 0.0222222 V2 0.307888 0.524218 0.00590278 + N0 0.0162121 0.0601415 -0.998058 N1 0.0311919 0.0537792 -0.998066 N2 0.0113382 0.0195486 -0.999745 + txt003 +STRI + V0 0.162696 0.584584 0.00590278 V1 0 0.605903 0.00590278 V2 -2.22045e-16 1.02222 0.0222222 + N0 0.00589307 0.0218614 -0.999744 N1 4.94615e-18 0.0226746 -0.999743 N2 0 0.0623783 -0.998053 + txt003 +STRI + V0 -2.22045e-16 1.02222 0.0222222 V1 0.274486 0.986255 0.0222222 V2 0.162696 0.584584 0.00590278 + N0 0 0.0623783 -0.998053 N1 0.0162121 0.0601415 -0.998058 N2 0.00589307 0.0218614 -0.999744 + txt003 +STRI + V0 1.02222 0 0.0222222 V1 0.986255 0.274486 0.0222222 V2 1.23918 0.344878 0.046875 + N0 0.0623783 0 -0.998053 N1 0.0601415 0.0162121 -0.998058 N2 0.136353 0.0367561 -0.989978 + txt003 +STRI + V0 1.23918 0.344878 0.046875 V1 1.28438 0 0.046875 V2 1.02222 0 0.0222222 + N0 0.136353 0.0367561 -0.989978 N1 0.141421 0 -0.989949 N2 0.0623783 0 -0.998053 + txt003 +STRI + V0 0.986255 0.274486 0.0222222 V1 0.884412 0.51944 0.0222222 V2 1.11122 0.652653 0.046875 + N0 0.0601415 0.0162121 -0.998058 N1 0.0537792 0.0311919 -0.998066 N2 0.121932 0.0707208 -0.990016 + txt003 +STRI + V0 1.11122 0.652653 0.046875 V1 1.23918 0.344878 0.046875 V2 0.986255 0.274486 0.0222222 + N0 0.121932 0.0707208 -0.990016 N1 0.136353 0.0367561 -0.989978 N2 0.0601415 0.0162121 -0.998058 + txt003 +STRI + V0 0.884412 0.51944 0.0222222 V1 0.725778 0.725778 0.0222222 V2 0.911906 0.911906 0.046875 + N0 0.0537792 0.0311919 -0.998066 N1 0.0439291 0.0439291 -0.998068 N2 0.0996006 0.0996006 -0.99003 + txt003 +STRI + V0 0.911906 0.911906 0.046875 V1 1.11122 0.652653 0.046875 V2 0.884412 0.51944 0.0222222 + N0 0.0996006 0.0996006 -0.99003 N1 0.121932 0.0707208 -0.990016 N2 0.0537792 0.0311919 -0.998066 + txt003 +STRI + V0 0.725778 0.725778 0.0222222 V1 0.51944 0.884412 0.0222222 V2 0.652653 1.11122 0.046875 + N0 0.0439291 0.0439291 -0.998068 N1 0.0311919 0.0537792 -0.998066 N2 0.0707208 0.121932 -0.990016 + txt003 +STRI + V0 0.652653 1.11122 0.046875 V1 0.911906 0.911906 0.046875 V2 0.725778 0.725778 0.0222222 + N0 0.0707208 0.121932 -0.990016 N1 0.0996006 0.0996006 -0.99003 N2 0.0439291 0.0439291 -0.998068 + txt003 +STRI + V0 0.51944 0.884412 0.0222222 V1 0.274486 0.986255 0.0222222 V2 0.344878 1.23918 0.046875 + N0 0.0311919 0.0537792 -0.998066 N1 0.0162121 0.0601415 -0.998058 N2 0.0367561 0.136353 -0.989978 + txt003 +STRI + V0 0.344878 1.23918 0.046875 V1 0.652653 1.11122 0.046875 V2 0.51944 0.884412 0.0222222 + N0 0.0367561 0.136353 -0.989978 N1 0.0707208 0.121932 -0.990016 N2 0.0311919 0.0537792 -0.998066 + txt003 +STRI + V0 0.274486 0.986255 0.0222222 V1 -2.22045e-16 1.02222 0.0222222 V2 2.22045e-16 1.28437 0.046875 + N0 0.0162121 0.0601415 -0.998058 N1 0 0.0623783 -0.998053 N2 0 0.141421 -0.989949 + txt003 +STRI + V0 2.22045e-16 1.28437 0.046875 V1 0.344878 1.23918 0.046875 V2 0.274486 0.986255 0.0222222 + N0 0 0.141421 -0.989949 N1 0.0367561 0.136353 -0.989978 N2 0.0162121 0.0601415 -0.998058 + txt003 +STRI + V0 1.28438 0 0.046875 V1 1.23918 0.344878 0.046875 V2 1.37754 0.383385 0.0777778 + N0 0.141421 0 -0.989949 N1 0.136353 0.0367561 -0.989978 N2 0.316788 0.085395 -0.944644 + txt003 +STRI + V0 1.37754 0.383385 0.0777778 V1 1.42778 0 0.0777778 V2 1.28438 0 0.046875 + N0 0.316788 0.085395 -0.944644 N1 0.328521 0 -0.944497 N2 0.141421 0 -0.989949 + txt003 +STRI + V0 1.23918 0.344878 0.046875 V1 1.11122 0.652653 0.046875 V2 1.23529 0.725523 0.0777778 + N0 0.136353 0.0367561 -0.989978 N1 0.121932 0.0707208 -0.990016 N2 0.283331 0.164332 -0.944838 + txt003 +STRI + V0 1.23529 0.725523 0.0777778 V1 1.37754 0.383385 0.0777778 V2 1.23918 0.344878 0.046875 + N0 0.283331 0.164332 -0.944838 N1 0.316788 0.085395 -0.944644 N2 0.136353 0.0367561 -0.989978 + txt003 +STRI + V0 1.11122 0.652653 0.046875 V1 0.911906 0.911906 0.046875 V2 1.01372 1.01372 0.0777778 + N0 0.121932 0.0707208 -0.990016 N1 0.0996006 0.0996006 -0.99003 N2 0.231454 0.231454 -0.944912 + txt003 +STRI + V0 1.01372 1.01372 0.0777778 V1 1.23529 0.725523 0.0777778 V2 1.11122 0.652653 0.046875 + N0 0.231454 0.231454 -0.944912 N1 0.283331 0.164332 -0.944838 N2 0.121932 0.0707208 -0.990016 + txt003 +STRI + V0 0.911906 0.911906 0.046875 V1 0.652653 1.11122 0.046875 V2 0.725523 1.23529 0.0777778 + N0 0.0996006 0.0996006 -0.99003 N1 0.0707208 0.121932 -0.990016 N2 0.164332 0.283331 -0.944838 + txt003 +STRI + V0 0.725523 1.23529 0.0777778 V1 1.01372 1.01372 0.0777778 V2 0.911906 0.911906 0.046875 + N0 0.164332 0.283331 -0.944838 N1 0.231454 0.231454 -0.944912 N2 0.0996006 0.0996006 -0.99003 + txt003 +STRI + V0 0.652653 1.11122 0.046875 V1 0.344878 1.23918 0.046875 V2 0.383385 1.37754 0.0777778 + N0 0.0707208 0.121932 -0.990016 N1 0.0367561 0.136353 -0.989978 N2 0.085395 0.316788 -0.944644 + txt003 +STRI + V0 0.383385 1.37754 0.0777778 V1 0.725523 1.23529 0.0777778 V2 0.652653 1.11122 0.046875 + N0 0.085395 0.316788 -0.944644 N1 0.164332 0.283331 -0.944838 N2 0.0707208 0.121932 -0.990016 + txt003 +STRI + V0 0.344878 1.23918 0.046875 V1 2.22045e-16 1.28437 0.046875 V2 -2.22045e-16 1.42778 0.0777778 + N0 0.0367561 0.136353 -0.989978 N1 0 0.141421 -0.989949 N2 6.08223e-17 0.328521 -0.944497 + txt003 +STRI + V0 -2.22045e-16 1.42778 0.0777778 V1 0.383385 1.37754 0.0777778 V2 0.344878 1.23918 0.046875 + N0 6.08223e-17 0.328521 -0.944497 N1 0.085395 0.316788 -0.944644 N2 0.0367561 0.136353 -0.989978 + txt003 +STRI + V0 1.42778 0 0.0777778 V1 1.37754 0.383385 0.0777778 V2 1.4355 0.399515 0.112847 + N0 0.328521 0 -0.944497 N1 0.316788 0.085395 -0.944644 N2 0.743044 0.200299 -0.638566 + txt003 +STRI + V0 1.4355 0.399515 0.112847 V1 1.48785 0 0.112847 V2 1.42778 0 0.0777778 + N0 0.743044 0.200299 -0.638566 N1 0.770022 0 -0.638018 N2 0.328521 0 -0.944497 + txt003 +STRI + V0 1.37754 0.383385 0.0777778 V1 1.23529 0.725523 0.0777778 V2 1.28726 0.756047 0.112847 + N0 0.316788 0.085395 -0.944644 N1 0.283331 0.164332 -0.944838 N2 0.665182 0.385806 -0.639286 + txt003 +STRI + V0 1.28726 0.756047 0.112847 V1 1.4355 0.399515 0.112847 V2 1.37754 0.383385 0.0777778 + N0 0.665182 0.385806 -0.639286 N1 0.743044 0.200299 -0.638566 N2 0.316788 0.085395 -0.944644 + txt003 +STRI + V0 1.23529 0.725523 0.0777778 V1 1.01372 1.01372 0.0777778 V2 1.05637 1.05637 0.112847 + N0 0.283331 0.164332 -0.944838 N1 0.231454 0.231454 -0.944912 N2 0.543581 0.543581 -0.639562 + txt003 +STRI + V0 1.05637 1.05637 0.112847 V1 1.28726 0.756047 0.112847 V2 1.23529 0.725523 0.0777778 + N0 0.543581 0.543581 -0.639562 N1 0.665182 0.385806 -0.639286 N2 0.283331 0.164332 -0.944838 + txt003 +STRI + V0 1.01372 1.01372 0.0777778 V1 0.725523 1.23529 0.0777778 V2 0.756047 1.28726 0.112847 + N0 0.231454 0.231454 -0.944912 N1 0.164332 0.283331 -0.944838 N2 0.385806 0.665182 -0.639286 + txt003 +STRI + V0 0.756047 1.28726 0.112847 V1 1.05637 1.05637 0.112847 V2 1.01372 1.01372 0.0777778 + N0 0.385806 0.665182 -0.639286 N1 0.543581 0.543581 -0.639562 N2 0.231454 0.231454 -0.944912 + txt003 +STRI + V0 0.725523 1.23529 0.0777778 V1 0.383385 1.37754 0.0777778 V2 0.399515 1.4355 0.112847 + N0 0.164332 0.283331 -0.944838 N1 0.085395 0.316788 -0.944644 N2 0.200299 0.743044 -0.638566 + txt003 +STRI + V0 0.399515 1.4355 0.112847 V1 0.756047 1.28726 0.112847 V2 0.725523 1.23529 0.0777778 + N0 0.200299 0.743044 -0.638566 N1 0.385806 0.665182 -0.639286 N2 0.164332 0.283331 -0.944838 + txt003 +STRI + V0 0.383385 1.37754 0.0777778 V1 -2.22045e-16 1.42778 0.0777778 V2 0 1.48785 0.112847 + N0 0.085395 0.316788 -0.944644 N1 6.08223e-17 0.328521 -0.944497 N2 1.36806e-16 0.770022 -0.638018 + txt003 +STRI + V0 0 1.48785 0.112847 V1 0.399515 1.4355 0.112847 V2 0.383385 1.37754 0.0777778 + N0 1.36806e-16 0.770022 -0.638018 N1 0.200299 0.743044 -0.638566 N2 0.085395 0.316788 -0.944644 + txt003 +STRI + V0 1.48785 0 0.112847 V1 1.4355 0.399515 0.112847 V2 1.44722 0.402778 0.15 + N0 0.770022 0 -0.638018 N1 0.743044 0.200299 -0.638566 N2 0.965535 0.260275 -2.07142e-16 + txt003 +STRI + V0 1.44722 0.402778 0.15 V1 1.5 0 0.15 V2 1.48785 0 0.112847 + N0 0.965535 0.260275 -2.07142e-16 N1 1 0 0 N2 0.770022 0 -0.638018 + txt003 +STRI + V0 1.4355 0.399515 0.112847 V1 1.28726 0.756047 0.112847 V2 1.29778 0.762222 0.15 + N0 0.743044 0.200299 -0.638566 N1 0.665182 0.385806 -0.639286 N2 0.865031 0.501718 -5.46348e-16 + txt003 +STRI + V0 1.29778 0.762222 0.15 V1 1.44722 0.402778 0.15 V2 1.4355 0.399515 0.112847 + N0 0.865031 0.501718 -5.46348e-16 N1 0.965535 0.260275 -2.07142e-16 N2 0.743044 0.200299 -0.638566 + txt003 +STRI + V0 1.28726 0.756047 0.112847 V1 1.05637 1.05637 0.112847 V2 1.065 1.065 0.15 + N0 0.665182 0.385806 -0.639286 N1 0.543581 0.543581 -0.639562 N2 0.707107 0.707107 -6.97819e-16 + txt003 +STRI + V0 1.065 1.065 0.15 V1 1.29778 0.762222 0.15 V2 1.28726 0.756047 0.112847 + N0 0.707107 0.707107 -6.97819e-16 N1 0.865031 0.501718 -5.46348e-16 N2 0.665182 0.385806 -0.639286 + txt003 +STRI + V0 1.05637 1.05637 0.112847 V1 0.756047 1.28726 0.112847 V2 0.762222 1.29778 0.15 + N0 0.543581 0.543581 -0.639562 N1 0.385806 0.665182 -0.639286 N2 0.501718 0.865031 -5.46348e-16 + txt003 +STRI + V0 0.762222 1.29778 0.15 V1 1.065 1.065 0.15 V2 1.05637 1.05637 0.112847 + N0 0.501718 0.865031 -5.46348e-16 N1 0.707107 0.707107 -6.97819e-16 N2 0.543581 0.543581 -0.639562 + txt003 +STRI + V0 0.756047 1.28726 0.112847 V1 0.399515 1.4355 0.112847 V2 0.402778 1.44722 0.15 + N0 0.385806 0.665182 -0.639286 N1 0.200299 0.743044 -0.638566 N2 0.260275 0.965535 -2.07142e-16 + txt003 +STRI + V0 0.402778 1.44722 0.15 V1 0.762222 1.29778 0.15 V2 0.756047 1.28726 0.112847 + N0 0.260275 0.965535 -2.07142e-16 N1 0.501718 0.865031 -5.46348e-16 N2 0.385806 0.665182 -0.639286 + txt003 +STRI + V0 0.399515 1.4355 0.112847 V1 0 1.48785 0.112847 V2 0 1.5 0.15 + N0 0.200299 0.743044 -0.638566 N1 1.36806e-16 0.770022 -0.638018 N2 0 1 -0 + txt003 +STRI + V0 0 1.5 0.15 V1 0.402778 1.44722 0.15 V2 0.399515 1.4355 0.112847 + N0 0 1 -0 N1 0.260275 0.965535 -2.07142e-16 N2 0.200299 0.743044 -0.638566 + txt003 +STRI + V0 -0.162696 0.584584 0.00590278 V1 0 0.605903 0.00590278 V2 0 0 0 + N0 -0.00589307 0.0218614 -0.999744 N1 0 0.0226746 -0.999743 N2 0 0 -1 + txt003 +STRI + V0 -0.307888 0.524218 0.00590278 V1 -0.162696 0.584584 0.00590278 V2 0 0 0 + N0 -0.0113382 0.0195486 -0.999745 N1 -0.00589307 0.0218614 -0.999744 N2 0 0 -1 + txt003 +STRI + V0 -0.430191 0.430191 0.00590278 V1 -0.307888 0.524218 0.00590278 V2 0 0 0 + N0 -0.015968 0.015968 -0.999745 N1 -0.0113382 0.0195486 -0.999745 N2 0 0 -1 + txt003 +STRI + V0 -0.524218 0.307888 0.00590278 V1 -0.430191 0.430191 0.00590278 V2 0 0 0 + N0 -0.0195486 0.0113382 -0.999745 N1 -0.015968 0.015968 -0.999745 N2 0 0 -1 + txt003 +STRI + V0 -0.584584 0.162696 0.00590278 V1 -0.524218 0.307888 0.00590278 V2 0 0 0 + N0 -0.0218614 0.00589307 -0.999744 N1 -0.0195486 0.0113382 -0.999745 N2 0 0 -1 + txt003 +STRI + V0 -0.605903 0 0.00590278 V1 -0.584584 0.162696 0.00590278 V2 0 0 0 + N0 -0.0226746 4.94615e-18 -0.999743 N1 -0.0218614 0.00589307 -0.999744 N2 0 0 -1 + txt003 +STRI + V0 0 0.605903 0.00590278 V1 -0.162696 0.584584 0.00590278 V2 -0.274486 0.986255 0.0222222 + N0 0 0.0226746 -0.999743 N1 -0.00589307 0.0218614 -0.999744 N2 -0.0162121 0.0601415 -0.998058 + txt003 +STRI + V0 -0.274486 0.986255 0.0222222 V1 0 1.02222 0.0222222 V2 0 0.605903 0.00590278 + N0 -0.0162121 0.0601415 -0.998058 N1 0 0.0623783 -0.998053 N2 0 0.0226746 -0.999743 + txt003 +STRI + V0 -0.162696 0.584584 0.00590278 V1 -0.307888 0.524218 0.00590278 V2 -0.51944 0.884412 0.0222222 + N0 -0.00589307 0.0218614 -0.999744 N1 -0.0113382 0.0195486 -0.999745 N2 -0.0311919 0.0537792 -0.998066 + txt003 +STRI + V0 -0.51944 0.884412 0.0222222 V1 -0.274486 0.986255 0.0222222 V2 -0.162696 0.584584 0.00590278 + N0 -0.0311919 0.0537792 -0.998066 N1 -0.0162121 0.0601415 -0.998058 N2 -0.00589307 0.0218614 -0.999744 + txt003 +STRI + V0 -0.307888 0.524218 0.00590278 V1 -0.430191 0.430191 0.00590278 V2 -0.725778 0.725778 0.0222222 + N0 -0.0113382 0.0195486 -0.999745 N1 -0.015968 0.015968 -0.999745 N2 -0.0439291 0.0439291 -0.998068 + txt003 +STRI + V0 -0.725778 0.725778 0.0222222 V1 -0.51944 0.884412 0.0222222 V2 -0.307888 0.524218 0.00590278 + N0 -0.0439291 0.0439291 -0.998068 N1 -0.0311919 0.0537792 -0.998066 N2 -0.0113382 0.0195486 -0.999745 + txt003 +STRI + V0 -0.430191 0.430191 0.00590278 V1 -0.524218 0.307888 0.00590278 V2 -0.884412 0.51944 0.0222222 + N0 -0.015968 0.015968 -0.999745 N1 -0.0195486 0.0113382 -0.999745 N2 -0.0537792 0.0311919 -0.998066 + txt003 +STRI + V0 -0.884412 0.51944 0.0222222 V1 -0.725778 0.725778 0.0222222 V2 -0.430191 0.430191 0.00590278 + N0 -0.0537792 0.0311919 -0.998066 N1 -0.0439291 0.0439291 -0.998068 N2 -0.015968 0.015968 -0.999745 + txt003 +STRI + V0 -0.524218 0.307888 0.00590278 V1 -0.584584 0.162696 0.00590278 V2 -0.986255 0.274486 0.0222222 + N0 -0.0195486 0.0113382 -0.999745 N1 -0.0218614 0.00589307 -0.999744 N2 -0.0601415 0.0162121 -0.998058 + txt003 +STRI + V0 -0.986255 0.274486 0.0222222 V1 -0.884412 0.51944 0.0222222 V2 -0.524218 0.307888 0.00590278 + N0 -0.0601415 0.0162121 -0.998058 N1 -0.0537792 0.0311919 -0.998066 N2 -0.0195486 0.0113382 -0.999745 + txt003 +STRI + V0 -0.584584 0.162696 0.00590278 V1 -0.605903 0 0.00590278 V2 -1.02222 -2.22045e-16 0.0222222 + N0 -0.0218614 0.00589307 -0.999744 N1 -0.0226746 4.94615e-18 -0.999743 N2 -0.0623783 -0 -0.998053 + txt003 +STRI + V0 -1.02222 -2.22045e-16 0.0222222 V1 -0.986255 0.274486 0.0222222 V2 -0.584584 0.162696 0.00590278 + N0 -0.0623783 -0 -0.998053 N1 -0.0601415 0.0162121 -0.998058 N2 -0.0218614 0.00589307 -0.999744 + txt003 +STRI + V0 0 1.02222 0.0222222 V1 -0.274486 0.986255 0.0222222 V2 -0.344878 1.23918 0.046875 + N0 0 0.0623783 -0.998053 N1 -0.0162121 0.0601415 -0.998058 N2 -0.0367561 0.136353 -0.989978 + txt003 +STRI + V0 -0.344878 1.23918 0.046875 V1 0 1.28438 0.046875 V2 0 1.02222 0.0222222 + N0 -0.0367561 0.136353 -0.989978 N1 0 0.141421 -0.989949 N2 0 0.0623783 -0.998053 + txt003 +STRI + V0 -0.274486 0.986255 0.0222222 V1 -0.51944 0.884412 0.0222222 V2 -0.652653 1.11122 0.046875 + N0 -0.0162121 0.0601415 -0.998058 N1 -0.0311919 0.0537792 -0.998066 N2 -0.0707208 0.121932 -0.990016 + txt003 +STRI + V0 -0.652653 1.11122 0.046875 V1 -0.344878 1.23918 0.046875 V2 -0.274486 0.986255 0.0222222 + N0 -0.0707208 0.121932 -0.990016 N1 -0.0367561 0.136353 -0.989978 N2 -0.0162121 0.0601415 -0.998058 + txt003 +STRI + V0 -0.51944 0.884412 0.0222222 V1 -0.725778 0.725778 0.0222222 V2 -0.911906 0.911906 0.046875 + N0 -0.0311919 0.0537792 -0.998066 N1 -0.0439291 0.0439291 -0.998068 N2 -0.0996006 0.0996006 -0.99003 + txt003 +STRI + V0 -0.911906 0.911906 0.046875 V1 -0.652653 1.11122 0.046875 V2 -0.51944 0.884412 0.0222222 + N0 -0.0996006 0.0996006 -0.99003 N1 -0.0707208 0.121932 -0.990016 N2 -0.0311919 0.0537792 -0.998066 + txt003 +STRI + V0 -0.725778 0.725778 0.0222222 V1 -0.884412 0.51944 0.0222222 V2 -1.11122 0.652653 0.046875 + N0 -0.0439291 0.0439291 -0.998068 N1 -0.0537792 0.0311919 -0.998066 N2 -0.121932 0.0707208 -0.990016 + txt003 +STRI + V0 -1.11122 0.652653 0.046875 V1 -0.911906 0.911906 0.046875 V2 -0.725778 0.725778 0.0222222 + N0 -0.121932 0.0707208 -0.990016 N1 -0.0996006 0.0996006 -0.99003 N2 -0.0439291 0.0439291 -0.998068 + txt003 +STRI + V0 -0.884412 0.51944 0.0222222 V1 -0.986255 0.274486 0.0222222 V2 -1.23918 0.344878 0.046875 + N0 -0.0537792 0.0311919 -0.998066 N1 -0.0601415 0.0162121 -0.998058 N2 -0.136353 0.0367561 -0.989978 + txt003 +STRI + V0 -1.23918 0.344878 0.046875 V1 -1.11122 0.652653 0.046875 V2 -0.884412 0.51944 0.0222222 + N0 -0.136353 0.0367561 -0.989978 N1 -0.121932 0.0707208 -0.990016 N2 -0.0537792 0.0311919 -0.998066 + txt003 +STRI + V0 -0.986255 0.274486 0.0222222 V1 -1.02222 -2.22045e-16 0.0222222 V2 -1.28437 2.22045e-16 0.046875 + N0 -0.0601415 0.0162121 -0.998058 N1 -0.0623783 -0 -0.998053 N2 -0.141421 -0 -0.989949 + txt003 +STRI + V0 -1.28437 2.22045e-16 0.046875 V1 -1.23918 0.344878 0.046875 V2 -0.986255 0.274486 0.0222222 + N0 -0.141421 -0 -0.989949 N1 -0.136353 0.0367561 -0.989978 N2 -0.0601415 0.0162121 -0.998058 + txt003 +STRI + V0 0 1.28438 0.046875 V1 -0.344878 1.23918 0.046875 V2 -0.383385 1.37754 0.0777778 + N0 0 0.141421 -0.989949 N1 -0.0367561 0.136353 -0.989978 N2 -0.085395 0.316788 -0.944644 + txt003 +STRI + V0 -0.383385 1.37754 0.0777778 V1 0 1.42778 0.0777778 V2 0 1.28438 0.046875 + N0 -0.085395 0.316788 -0.944644 N1 0 0.328521 -0.944497 N2 0 0.141421 -0.989949 + txt003 +STRI + V0 -0.344878 1.23918 0.046875 V1 -0.652653 1.11122 0.046875 V2 -0.725523 1.23529 0.0777778 + N0 -0.0367561 0.136353 -0.989978 N1 -0.0707208 0.121932 -0.990016 N2 -0.164332 0.283331 -0.944838 + txt003 +STRI + V0 -0.725523 1.23529 0.0777778 V1 -0.383385 1.37754 0.0777778 V2 -0.344878 1.23918 0.046875 + N0 -0.164332 0.283331 -0.944838 N1 -0.085395 0.316788 -0.944644 N2 -0.0367561 0.136353 -0.989978 + txt003 +STRI + V0 -0.652653 1.11122 0.046875 V1 -0.911906 0.911906 0.046875 V2 -1.01372 1.01372 0.0777778 + N0 -0.0707208 0.121932 -0.990016 N1 -0.0996006 0.0996006 -0.99003 N2 -0.231454 0.231454 -0.944912 + txt003 +STRI + V0 -1.01372 1.01372 0.0777778 V1 -0.725523 1.23529 0.0777778 V2 -0.652653 1.11122 0.046875 + N0 -0.231454 0.231454 -0.944912 N1 -0.164332 0.283331 -0.944838 N2 -0.0707208 0.121932 -0.990016 + txt003 +STRI + V0 -0.911906 0.911906 0.046875 V1 -1.11122 0.652653 0.046875 V2 -1.23529 0.725523 0.0777778 + N0 -0.0996006 0.0996006 -0.99003 N1 -0.121932 0.0707208 -0.990016 N2 -0.283331 0.164332 -0.944838 + txt003 +STRI + V0 -1.23529 0.725523 0.0777778 V1 -1.01372 1.01372 0.0777778 V2 -0.911906 0.911906 0.046875 + N0 -0.283331 0.164332 -0.944838 N1 -0.231454 0.231454 -0.944912 N2 -0.0996006 0.0996006 -0.99003 + txt003 +STRI + V0 -1.11122 0.652653 0.046875 V1 -1.23918 0.344878 0.046875 V2 -1.37754 0.383385 0.0777778 + N0 -0.121932 0.0707208 -0.990016 N1 -0.136353 0.0367561 -0.989978 N2 -0.316788 0.085395 -0.944644 + txt003 +STRI + V0 -1.37754 0.383385 0.0777778 V1 -1.23529 0.725523 0.0777778 V2 -1.11122 0.652653 0.046875 + N0 -0.316788 0.085395 -0.944644 N1 -0.283331 0.164332 -0.944838 N2 -0.121932 0.0707208 -0.990016 + txt003 +STRI + V0 -1.23918 0.344878 0.046875 V1 -1.28437 2.22045e-16 0.046875 V2 -1.42778 -2.22045e-16 0.0777778 + N0 -0.136353 0.0367561 -0.989978 N1 -0.141421 -0 -0.989949 N2 -0.328521 6.08223e-17 -0.944497 + txt003 +STRI + V0 -1.42778 -2.22045e-16 0.0777778 V1 -1.37754 0.383385 0.0777778 V2 -1.23918 0.344878 0.046875 + N0 -0.328521 6.08223e-17 -0.944497 N1 -0.316788 0.085395 -0.944644 N2 -0.136353 0.0367561 -0.989978 + txt003 +STRI + V0 0 1.42778 0.0777778 V1 -0.383385 1.37754 0.0777778 V2 -0.399515 1.4355 0.112847 + N0 0 0.328521 -0.944497 N1 -0.085395 0.316788 -0.944644 N2 -0.200299 0.743044 -0.638566 + txt003 +STRI + V0 -0.399515 1.4355 0.112847 V1 0 1.48785 0.112847 V2 0 1.42778 0.0777778 + N0 -0.200299 0.743044 -0.638566 N1 0 0.770022 -0.638018 N2 0 0.328521 -0.944497 + txt003 +STRI + V0 -0.383385 1.37754 0.0777778 V1 -0.725523 1.23529 0.0777778 V2 -0.756047 1.28726 0.112847 + N0 -0.085395 0.316788 -0.944644 N1 -0.164332 0.283331 -0.944838 N2 -0.385806 0.665182 -0.639286 + txt003 +STRI + V0 -0.756047 1.28726 0.112847 V1 -0.399515 1.4355 0.112847 V2 -0.383385 1.37754 0.0777778 + N0 -0.385806 0.665182 -0.639286 N1 -0.200299 0.743044 -0.638566 N2 -0.085395 0.316788 -0.944644 + txt003 +STRI + V0 -0.725523 1.23529 0.0777778 V1 -1.01372 1.01372 0.0777778 V2 -1.05637 1.05637 0.112847 + N0 -0.164332 0.283331 -0.944838 N1 -0.231454 0.231454 -0.944912 N2 -0.543581 0.543581 -0.639562 + txt003 +STRI + V0 -1.05637 1.05637 0.112847 V1 -0.756047 1.28726 0.112847 V2 -0.725523 1.23529 0.0777778 + N0 -0.543581 0.543581 -0.639562 N1 -0.385806 0.665182 -0.639286 N2 -0.164332 0.283331 -0.944838 + txt003 +STRI + V0 -1.01372 1.01372 0.0777778 V1 -1.23529 0.725523 0.0777778 V2 -1.28726 0.756047 0.112847 + N0 -0.231454 0.231454 -0.944912 N1 -0.283331 0.164332 -0.944838 N2 -0.665182 0.385806 -0.639286 + txt003 +STRI + V0 -1.28726 0.756047 0.112847 V1 -1.05637 1.05637 0.112847 V2 -1.01372 1.01372 0.0777778 + N0 -0.665182 0.385806 -0.639286 N1 -0.543581 0.543581 -0.639562 N2 -0.231454 0.231454 -0.944912 + txt003 +STRI + V0 -1.23529 0.725523 0.0777778 V1 -1.37754 0.383385 0.0777778 V2 -1.4355 0.399515 0.112847 + N0 -0.283331 0.164332 -0.944838 N1 -0.316788 0.085395 -0.944644 N2 -0.743044 0.200299 -0.638566 + txt003 +STRI + V0 -1.4355 0.399515 0.112847 V1 -1.28726 0.756047 0.112847 V2 -1.23529 0.725523 0.0777778 + N0 -0.743044 0.200299 -0.638566 N1 -0.665182 0.385806 -0.639286 N2 -0.283331 0.164332 -0.944838 + txt003 +STRI + V0 -1.37754 0.383385 0.0777778 V1 -1.42778 -2.22045e-16 0.0777778 V2 -1.48785 0 0.112847 + N0 -0.316788 0.085395 -0.944644 N1 -0.328521 6.08223e-17 -0.944497 N2 -0.770022 1.36806e-16 -0.638018 + txt003 +STRI + V0 -1.48785 0 0.112847 V1 -1.4355 0.399515 0.112847 V2 -1.37754 0.383385 0.0777778 + N0 -0.770022 1.36806e-16 -0.638018 N1 -0.743044 0.200299 -0.638566 N2 -0.316788 0.085395 -0.944644 + txt003 +STRI + V0 0 1.48785 0.112847 V1 -0.399515 1.4355 0.112847 V2 -0.402778 1.44722 0.15 + N0 0 0.770022 -0.638018 N1 -0.200299 0.743044 -0.638566 N2 -0.260275 0.965535 -2.07142e-16 + txt003 +STRI + V0 -0.402778 1.44722 0.15 V1 0 1.5 0.15 V2 0 1.48785 0.112847 + N0 -0.260275 0.965535 -2.07142e-16 N1 0 1 -0 N2 0 0.770022 -0.638018 + txt003 +STRI + V0 -0.399515 1.4355 0.112847 V1 -0.756047 1.28726 0.112847 V2 -0.762222 1.29778 0.15 + N0 -0.200299 0.743044 -0.638566 N1 -0.385806 0.665182 -0.639286 N2 -0.501718 0.865031 -5.46348e-16 + txt003 +STRI + V0 -0.762222 1.29778 0.15 V1 -0.402778 1.44722 0.15 V2 -0.399515 1.4355 0.112847 + N0 -0.501718 0.865031 -5.46348e-16 N1 -0.260275 0.965535 -2.07142e-16 N2 -0.200299 0.743044 -0.638566 + txt003 +STRI + V0 -0.756047 1.28726 0.112847 V1 -1.05637 1.05637 0.112847 V2 -1.065 1.065 0.15 + N0 -0.385806 0.665182 -0.639286 N1 -0.543581 0.543581 -0.639562 N2 -0.707107 0.707107 -6.97819e-16 + txt003 +STRI + V0 -1.065 1.065 0.15 V1 -0.762222 1.29778 0.15 V2 -0.756047 1.28726 0.112847 + N0 -0.707107 0.707107 -6.97819e-16 N1 -0.501718 0.865031 -5.46348e-16 N2 -0.385806 0.665182 -0.639286 + txt003 +STRI + V0 -1.05637 1.05637 0.112847 V1 -1.28726 0.756047 0.112847 V2 -1.29778 0.762222 0.15 + N0 -0.543581 0.543581 -0.639562 N1 -0.665182 0.385806 -0.639286 N2 -0.865031 0.501718 -5.46348e-16 + txt003 +STRI + V0 -1.29778 0.762222 0.15 V1 -1.065 1.065 0.15 V2 -1.05637 1.05637 0.112847 + N0 -0.865031 0.501718 -5.46348e-16 N1 -0.707107 0.707107 -6.97819e-16 N2 -0.543581 0.543581 -0.639562 + txt003 +STRI + V0 -1.28726 0.756047 0.112847 V1 -1.4355 0.399515 0.112847 V2 -1.44722 0.402778 0.15 + N0 -0.665182 0.385806 -0.639286 N1 -0.743044 0.200299 -0.638566 N2 -0.965535 0.260275 -2.07142e-16 + txt003 +STRI + V0 -1.44722 0.402778 0.15 V1 -1.29778 0.762222 0.15 V2 -1.28726 0.756047 0.112847 + N0 -0.965535 0.260275 -2.07142e-16 N1 -0.865031 0.501718 -5.46348e-16 N2 -0.665182 0.385806 -0.639286 + txt003 +STRI + V0 -1.4355 0.399515 0.112847 V1 -1.48785 0 0.112847 V2 -1.5 0 0.15 + N0 -0.743044 0.200299 -0.638566 N1 -0.770022 1.36806e-16 -0.638018 N2 -1 0 0 + txt003 +STRI + V0 -1.5 0 0.15 V1 -1.44722 0.402778 0.15 V2 -1.4355 0.399515 0.112847 + N0 -1 0 0 N1 -0.965535 0.260275 -2.07142e-16 N2 -0.743044 0.200299 -0.638566 + txt003 +STRI + V0 -0.584584 -0.162696 0.00590278 V1 -0.605903 0 0.00590278 V2 0 0 0 + N0 -0.0218614 -0.00589307 -0.999744 N1 -0.0226746 -0 -0.999743 N2 0 0 -1 + txt003 +STRI + V0 -0.524218 -0.307888 0.00590278 V1 -0.584584 -0.162696 0.00590278 V2 0 0 0 + N0 -0.0195486 -0.0113382 -0.999745 N1 -0.0218614 -0.00589307 -0.999744 N2 0 0 -1 + txt003 +STRI + V0 -0.430191 -0.430191 0.00590278 V1 -0.524218 -0.307888 0.00590278 V2 0 0 0 + N0 -0.015968 -0.015968 -0.999745 N1 -0.0195486 -0.0113382 -0.999745 N2 0 0 -1 + txt003 +STRI + V0 -0.307888 -0.524218 0.00590278 V1 -0.430191 -0.430191 0.00590278 V2 0 0 0 + N0 -0.0113382 -0.0195486 -0.999745 N1 -0.015968 -0.015968 -0.999745 N2 0 0 -1 + txt003 +STRI + V0 -0.162696 -0.584584 0.00590278 V1 -0.307888 -0.524218 0.00590278 V2 0 0 0 + N0 -0.00589307 -0.0218614 -0.999744 N1 -0.0113382 -0.0195486 -0.999745 N2 0 0 -1 + txt003 +STRI + V0 0 -0.605903 0.00590278 V1 -0.162696 -0.584584 0.00590278 V2 0 0 0 + N0 -4.94615e-18 -0.0226746 -0.999743 N1 -0.00589307 -0.0218614 -0.999744 N2 0 0 -1 + txt003 +STRI + V0 -0.605903 0 0.00590278 V1 -0.584584 -0.162696 0.00590278 V2 -0.986255 -0.274486 0.0222222 + N0 -0.0226746 -0 -0.999743 N1 -0.0218614 -0.00589307 -0.999744 N2 -0.0601415 -0.0162121 -0.998058 + txt003 +STRI + V0 -0.986255 -0.274486 0.0222222 V1 -1.02222 0 0.0222222 V2 -0.605903 0 0.00590278 + N0 -0.0601415 -0.0162121 -0.998058 N1 -0.0623783 -0 -0.998053 N2 -0.0226746 -0 -0.999743 + txt003 +STRI + V0 -0.584584 -0.162696 0.00590278 V1 -0.524218 -0.307888 0.00590278 V2 -0.884412 -0.51944 0.0222222 + N0 -0.0218614 -0.00589307 -0.999744 N1 -0.0195486 -0.0113382 -0.999745 N2 -0.0537792 -0.0311919 -0.998066 + txt003 +STRI + V0 -0.884412 -0.51944 0.0222222 V1 -0.986255 -0.274486 0.0222222 V2 -0.584584 -0.162696 0.00590278 + N0 -0.0537792 -0.0311919 -0.998066 N1 -0.0601415 -0.0162121 -0.998058 N2 -0.0218614 -0.00589307 -0.999744 + txt003 +STRI + V0 -0.524218 -0.307888 0.00590278 V1 -0.430191 -0.430191 0.00590278 V2 -0.725778 -0.725778 0.0222222 + N0 -0.0195486 -0.0113382 -0.999745 N1 -0.015968 -0.015968 -0.999745 N2 -0.0439291 -0.0439291 -0.998068 + txt003 +STRI + V0 -0.725778 -0.725778 0.0222222 V1 -0.884412 -0.51944 0.0222222 V2 -0.524218 -0.307888 0.00590278 + N0 -0.0439291 -0.0439291 -0.998068 N1 -0.0537792 -0.0311919 -0.998066 N2 -0.0195486 -0.0113382 -0.999745 + txt003 +STRI + V0 -0.430191 -0.430191 0.00590278 V1 -0.307888 -0.524218 0.00590278 V2 -0.51944 -0.884412 0.0222222 + N0 -0.015968 -0.015968 -0.999745 N1 -0.0113382 -0.0195486 -0.999745 N2 -0.0311919 -0.0537792 -0.998066 + txt003 +STRI + V0 -0.51944 -0.884412 0.0222222 V1 -0.725778 -0.725778 0.0222222 V2 -0.430191 -0.430191 0.00590278 + N0 -0.0311919 -0.0537792 -0.998066 N1 -0.0439291 -0.0439291 -0.998068 N2 -0.015968 -0.015968 -0.999745 + txt003 +STRI + V0 -0.307888 -0.524218 0.00590278 V1 -0.162696 -0.584584 0.00590278 V2 -0.274486 -0.986255 0.0222222 + N0 -0.0113382 -0.0195486 -0.999745 N1 -0.00589307 -0.0218614 -0.999744 N2 -0.0162121 -0.0601415 -0.998058 + txt003 +STRI + V0 -0.274486 -0.986255 0.0222222 V1 -0.51944 -0.884412 0.0222222 V2 -0.307888 -0.524218 0.00590278 + N0 -0.0162121 -0.0601415 -0.998058 N1 -0.0311919 -0.0537792 -0.998066 N2 -0.0113382 -0.0195486 -0.999745 + txt003 +STRI + V0 -0.162696 -0.584584 0.00590278 V1 0 -0.605903 0.00590278 V2 2.22045e-16 -1.02222 0.0222222 + N0 -0.00589307 -0.0218614 -0.999744 N1 -4.94615e-18 -0.0226746 -0.999743 N2 0 -0.0623783 -0.998053 + txt003 +STRI + V0 2.22045e-16 -1.02222 0.0222222 V1 -0.274486 -0.986255 0.0222222 V2 -0.162696 -0.584584 0.00590278 + N0 0 -0.0623783 -0.998053 N1 -0.0162121 -0.0601415 -0.998058 N2 -0.00589307 -0.0218614 -0.999744 + txt003 +STRI + V0 -1.02222 0 0.0222222 V1 -0.986255 -0.274486 0.0222222 V2 -1.23918 -0.344878 0.046875 + N0 -0.0623783 -0 -0.998053 N1 -0.0601415 -0.0162121 -0.998058 N2 -0.136353 -0.0367561 -0.989978 + txt003 +STRI + V0 -1.23918 -0.344878 0.046875 V1 -1.28438 0 0.046875 V2 -1.02222 0 0.0222222 + N0 -0.136353 -0.0367561 -0.989978 N1 -0.141421 -0 -0.989949 N2 -0.0623783 -0 -0.998053 + txt003 +STRI + V0 -0.986255 -0.274486 0.0222222 V1 -0.884412 -0.51944 0.0222222 V2 -1.11122 -0.652653 0.046875 + N0 -0.0601415 -0.0162121 -0.998058 N1 -0.0537792 -0.0311919 -0.998066 N2 -0.121932 -0.0707208 -0.990016 + txt003 +STRI + V0 -1.11122 -0.652653 0.046875 V1 -1.23918 -0.344878 0.046875 V2 -0.986255 -0.274486 0.0222222 + N0 -0.121932 -0.0707208 -0.990016 N1 -0.136353 -0.0367561 -0.989978 N2 -0.0601415 -0.0162121 -0.998058 + txt003 +STRI + V0 -0.884412 -0.51944 0.0222222 V1 -0.725778 -0.725778 0.0222222 V2 -0.911906 -0.911906 0.046875 + N0 -0.0537792 -0.0311919 -0.998066 N1 -0.0439291 -0.0439291 -0.998068 N2 -0.0996006 -0.0996006 -0.99003 + txt003 +STRI + V0 -0.911906 -0.911906 0.046875 V1 -1.11122 -0.652653 0.046875 V2 -0.884412 -0.51944 0.0222222 + N0 -0.0996006 -0.0996006 -0.99003 N1 -0.121932 -0.0707208 -0.990016 N2 -0.0537792 -0.0311919 -0.998066 + txt003 +STRI + V0 -0.725778 -0.725778 0.0222222 V1 -0.51944 -0.884412 0.0222222 V2 -0.652653 -1.11122 0.046875 + N0 -0.0439291 -0.0439291 -0.998068 N1 -0.0311919 -0.0537792 -0.998066 N2 -0.0707208 -0.121932 -0.990016 + txt003 +STRI + V0 -0.652653 -1.11122 0.046875 V1 -0.911906 -0.911906 0.046875 V2 -0.725778 -0.725778 0.0222222 + N0 -0.0707208 -0.121932 -0.990016 N1 -0.0996006 -0.0996006 -0.99003 N2 -0.0439291 -0.0439291 -0.998068 + txt003 +STRI + V0 -0.51944 -0.884412 0.0222222 V1 -0.274486 -0.986255 0.0222222 V2 -0.344878 -1.23918 0.046875 + N0 -0.0311919 -0.0537792 -0.998066 N1 -0.0162121 -0.0601415 -0.998058 N2 -0.0367561 -0.136353 -0.989978 + txt003 +STRI + V0 -0.344878 -1.23918 0.046875 V1 -0.652653 -1.11122 0.046875 V2 -0.51944 -0.884412 0.0222222 + N0 -0.0367561 -0.136353 -0.989978 N1 -0.0707208 -0.121932 -0.990016 N2 -0.0311919 -0.0537792 -0.998066 + txt003 +STRI + V0 -0.274486 -0.986255 0.0222222 V1 2.22045e-16 -1.02222 0.0222222 V2 -2.22045e-16 -1.28437 0.046875 + N0 -0.0162121 -0.0601415 -0.998058 N1 0 -0.0623783 -0.998053 N2 0 -0.141421 -0.989949 + txt003 +STRI + V0 -2.22045e-16 -1.28437 0.046875 V1 -0.344878 -1.23918 0.046875 V2 -0.274486 -0.986255 0.0222222 + N0 0 -0.141421 -0.989949 N1 -0.0367561 -0.136353 -0.989978 N2 -0.0162121 -0.0601415 -0.998058 + txt003 +STRI + V0 -1.28438 0 0.046875 V1 -1.23918 -0.344878 0.046875 V2 -1.37754 -0.383385 0.0777778 + N0 -0.141421 -0 -0.989949 N1 -0.136353 -0.0367561 -0.989978 N2 -0.316788 -0.085395 -0.944644 + txt003 +STRI + V0 -1.37754 -0.383385 0.0777778 V1 -1.42778 0 0.0777778 V2 -1.28438 0 0.046875 + N0 -0.316788 -0.085395 -0.944644 N1 -0.328521 -0 -0.944497 N2 -0.141421 -0 -0.989949 + txt003 +STRI + V0 -1.23918 -0.344878 0.046875 V1 -1.11122 -0.652653 0.046875 V2 -1.23529 -0.725523 0.0777778 + N0 -0.136353 -0.0367561 -0.989978 N1 -0.121932 -0.0707208 -0.990016 N2 -0.283331 -0.164332 -0.944838 + txt003 +STRI + V0 -1.23529 -0.725523 0.0777778 V1 -1.37754 -0.383385 0.0777778 V2 -1.23918 -0.344878 0.046875 + N0 -0.283331 -0.164332 -0.944838 N1 -0.316788 -0.085395 -0.944644 N2 -0.136353 -0.0367561 -0.989978 + txt003 +STRI + V0 -1.11122 -0.652653 0.046875 V1 -0.911906 -0.911906 0.046875 V2 -1.01372 -1.01372 0.0777778 + N0 -0.121932 -0.0707208 -0.990016 N1 -0.0996006 -0.0996006 -0.99003 N2 -0.231454 -0.231454 -0.944912 + txt003 +STRI + V0 -1.01372 -1.01372 0.0777778 V1 -1.23529 -0.725523 0.0777778 V2 -1.11122 -0.652653 0.046875 + N0 -0.231454 -0.231454 -0.944912 N1 -0.283331 -0.164332 -0.944838 N2 -0.121932 -0.0707208 -0.990016 + txt003 +STRI + V0 -0.911906 -0.911906 0.046875 V1 -0.652653 -1.11122 0.046875 V2 -0.725523 -1.23529 0.0777778 + N0 -0.0996006 -0.0996006 -0.99003 N1 -0.0707208 -0.121932 -0.990016 N2 -0.164332 -0.283331 -0.944838 + txt003 +STRI + V0 -0.725523 -1.23529 0.0777778 V1 -1.01372 -1.01372 0.0777778 V2 -0.911906 -0.911906 0.046875 + N0 -0.164332 -0.283331 -0.944838 N1 -0.231454 -0.231454 -0.944912 N2 -0.0996006 -0.0996006 -0.99003 + txt003 +STRI + V0 -0.652653 -1.11122 0.046875 V1 -0.344878 -1.23918 0.046875 V2 -0.383385 -1.37754 0.0777778 + N0 -0.0707208 -0.121932 -0.990016 N1 -0.0367561 -0.136353 -0.989978 N2 -0.085395 -0.316788 -0.944644 + txt003 +STRI + V0 -0.383385 -1.37754 0.0777778 V1 -0.725523 -1.23529 0.0777778 V2 -0.652653 -1.11122 0.046875 + N0 -0.085395 -0.316788 -0.944644 N1 -0.164332 -0.283331 -0.944838 N2 -0.0707208 -0.121932 -0.990016 + txt003 +STRI + V0 -0.344878 -1.23918 0.046875 V1 -2.22045e-16 -1.28437 0.046875 V2 2.22045e-16 -1.42778 0.0777778 + N0 -0.0367561 -0.136353 -0.989978 N1 0 -0.141421 -0.989949 N2 -6.08223e-17 -0.328521 -0.944497 + txt003 +STRI + V0 2.22045e-16 -1.42778 0.0777778 V1 -0.383385 -1.37754 0.0777778 V2 -0.344878 -1.23918 0.046875 + N0 -6.08223e-17 -0.328521 -0.944497 N1 -0.085395 -0.316788 -0.944644 N2 -0.0367561 -0.136353 -0.989978 + txt003 +STRI + V0 -1.42778 0 0.0777778 V1 -1.37754 -0.383385 0.0777778 V2 -1.4355 -0.399515 0.112847 + N0 -0.328521 -0 -0.944497 N1 -0.316788 -0.085395 -0.944644 N2 -0.743044 -0.200299 -0.638566 + txt003 +STRI + V0 -1.4355 -0.399515 0.112847 V1 -1.48785 0 0.112847 V2 -1.42778 0 0.0777778 + N0 -0.743044 -0.200299 -0.638566 N1 -0.770022 -0 -0.638018 N2 -0.328521 -0 -0.944497 + txt003 +STRI + V0 -1.37754 -0.383385 0.0777778 V1 -1.23529 -0.725523 0.0777778 V2 -1.28726 -0.756047 0.112847 + N0 -0.316788 -0.085395 -0.944644 N1 -0.283331 -0.164332 -0.944838 N2 -0.665182 -0.385806 -0.639286 + txt003 +STRI + V0 -1.28726 -0.756047 0.112847 V1 -1.4355 -0.399515 0.112847 V2 -1.37754 -0.383385 0.0777778 + N0 -0.665182 -0.385806 -0.639286 N1 -0.743044 -0.200299 -0.638566 N2 -0.316788 -0.085395 -0.944644 + txt003 +STRI + V0 -1.23529 -0.725523 0.0777778 V1 -1.01372 -1.01372 0.0777778 V2 -1.05637 -1.05637 0.112847 + N0 -0.283331 -0.164332 -0.944838 N1 -0.231454 -0.231454 -0.944912 N2 -0.543581 -0.543581 -0.639562 + txt003 +STRI + V0 -1.05637 -1.05637 0.112847 V1 -1.28726 -0.756047 0.112847 V2 -1.23529 -0.725523 0.0777778 + N0 -0.543581 -0.543581 -0.639562 N1 -0.665182 -0.385806 -0.639286 N2 -0.283331 -0.164332 -0.944838 + txt003 +STRI + V0 -1.01372 -1.01372 0.0777778 V1 -0.725523 -1.23529 0.0777778 V2 -0.756047 -1.28726 0.112847 + N0 -0.231454 -0.231454 -0.944912 N1 -0.164332 -0.283331 -0.944838 N2 -0.385806 -0.665182 -0.639286 + txt003 +STRI + V0 -0.756047 -1.28726 0.112847 V1 -1.05637 -1.05637 0.112847 V2 -1.01372 -1.01372 0.0777778 + N0 -0.385806 -0.665182 -0.639286 N1 -0.543581 -0.543581 -0.639562 N2 -0.231454 -0.231454 -0.944912 + txt003 +STRI + V0 -0.725523 -1.23529 0.0777778 V1 -0.383385 -1.37754 0.0777778 V2 -0.399515 -1.4355 0.112847 + N0 -0.164332 -0.283331 -0.944838 N1 -0.085395 -0.316788 -0.944644 N2 -0.200299 -0.743044 -0.638566 + txt003 +STRI + V0 -0.399515 -1.4355 0.112847 V1 -0.756047 -1.28726 0.112847 V2 -0.725523 -1.23529 0.0777778 + N0 -0.200299 -0.743044 -0.638566 N1 -0.385806 -0.665182 -0.639286 N2 -0.164332 -0.283331 -0.944838 + txt003 +STRI + V0 -0.383385 -1.37754 0.0777778 V1 2.22045e-16 -1.42778 0.0777778 V2 0 -1.48785 0.112847 + N0 -0.085395 -0.316788 -0.944644 N1 -6.08223e-17 -0.328521 -0.944497 N2 -1.36806e-16 -0.770022 -0.638018 + txt003 +STRI + V0 0 -1.48785 0.112847 V1 -0.399515 -1.4355 0.112847 V2 -0.383385 -1.37754 0.0777778 + N0 -1.36806e-16 -0.770022 -0.638018 N1 -0.200299 -0.743044 -0.638566 N2 -0.085395 -0.316788 -0.944644 + txt003 +STRI + V0 -1.48785 0 0.112847 V1 -1.4355 -0.399515 0.112847 V2 -1.44722 -0.402778 0.15 + N0 -0.770022 -0 -0.638018 N1 -0.743044 -0.200299 -0.638566 N2 -0.965535 -0.260275 -2.07142e-16 + txt003 +STRI + V0 -1.44722 -0.402778 0.15 V1 -1.5 0 0.15 V2 -1.48785 0 0.112847 + N0 -0.965535 -0.260275 -2.07142e-16 N1 -1 0 0 N2 -0.770022 -0 -0.638018 + txt003 +STRI + V0 -1.4355 -0.399515 0.112847 V1 -1.28726 -0.756047 0.112847 V2 -1.29778 -0.762222 0.15 + N0 -0.743044 -0.200299 -0.638566 N1 -0.665182 -0.385806 -0.639286 N2 -0.865031 -0.501718 -5.46348e-16 + txt003 +STRI + V0 -1.29778 -0.762222 0.15 V1 -1.44722 -0.402778 0.15 V2 -1.4355 -0.399515 0.112847 + N0 -0.865031 -0.501718 -5.46348e-16 N1 -0.965535 -0.260275 -2.07142e-16 N2 -0.743044 -0.200299 -0.638566 + txt003 +STRI + V0 -1.28726 -0.756047 0.112847 V1 -1.05637 -1.05637 0.112847 V2 -1.065 -1.065 0.15 + N0 -0.665182 -0.385806 -0.639286 N1 -0.543581 -0.543581 -0.639562 N2 -0.707107 -0.707107 -6.97819e-16 + txt003 +STRI + V0 -1.065 -1.065 0.15 V1 -1.29778 -0.762222 0.15 V2 -1.28726 -0.756047 0.112847 + N0 -0.707107 -0.707107 -6.97819e-16 N1 -0.865031 -0.501718 -5.46348e-16 N2 -0.665182 -0.385806 -0.639286 + txt003 +STRI + V0 -1.05637 -1.05637 0.112847 V1 -0.756047 -1.28726 0.112847 V2 -0.762222 -1.29778 0.15 + N0 -0.543581 -0.543581 -0.639562 N1 -0.385806 -0.665182 -0.639286 N2 -0.501718 -0.865031 -5.46348e-16 + txt003 +STRI + V0 -0.762222 -1.29778 0.15 V1 -1.065 -1.065 0.15 V2 -1.05637 -1.05637 0.112847 + N0 -0.501718 -0.865031 -5.46348e-16 N1 -0.707107 -0.707107 -6.97819e-16 N2 -0.543581 -0.543581 -0.639562 + txt003 +STRI + V0 -0.756047 -1.28726 0.112847 V1 -0.399515 -1.4355 0.112847 V2 -0.402778 -1.44722 0.15 + N0 -0.385806 -0.665182 -0.639286 N1 -0.200299 -0.743044 -0.638566 N2 -0.260275 -0.965535 -2.07142e-16 + txt003 +STRI + V0 -0.402778 -1.44722 0.15 V1 -0.762222 -1.29778 0.15 V2 -0.756047 -1.28726 0.112847 + N0 -0.260275 -0.965535 -2.07142e-16 N1 -0.501718 -0.865031 -5.46348e-16 N2 -0.385806 -0.665182 -0.639286 + txt003 +STRI + V0 -0.399515 -1.4355 0.112847 V1 0 -1.48785 0.112847 V2 0 -1.5 0.15 + N0 -0.200299 -0.743044 -0.638566 N1 -1.36806e-16 -0.770022 -0.638018 N2 0 -1 0 + txt003 +STRI + V0 0 -1.5 0.15 V1 -0.402778 -1.44722 0.15 V2 -0.399515 -1.4355 0.112847 + N0 0 -1 0 N1 -0.260275 -0.965535 -2.07142e-16 N2 -0.200299 -0.743044 -0.638566 + txt003 +STRI + V0 0.162696 -0.584584 0.00590278 V1 0 -0.605903 0.00590278 V2 0 0 0 + N0 0.00589307 -0.0218614 -0.999744 N1 0 -0.0226746 -0.999743 N2 0 0 -1 + txt003 +STRI + V0 0.307888 -0.524218 0.00590278 V1 0.162696 -0.584584 0.00590278 V2 0 0 0 + N0 0.0113382 -0.0195486 -0.999745 N1 0.00589307 -0.0218614 -0.999744 N2 0 0 -1 + txt003 +STRI + V0 0.430191 -0.430191 0.00590278 V1 0.307888 -0.524218 0.00590278 V2 0 0 0 + N0 0.015968 -0.015968 -0.999745 N1 0.0113382 -0.0195486 -0.999745 N2 0 0 -1 + txt003 +STRI + V0 0.524218 -0.307888 0.00590278 V1 0.430191 -0.430191 0.00590278 V2 0 0 0 + N0 0.0195486 -0.0113382 -0.999745 N1 0.015968 -0.015968 -0.999745 N2 0 0 -1 + txt003 +STRI + V0 0.584584 -0.162696 0.00590278 V1 0.524218 -0.307888 0.00590278 V2 0 0 0 + N0 0.0218614 -0.00589307 -0.999744 N1 0.0195486 -0.0113382 -0.999745 N2 0 0 -1 + txt003 +STRI + V0 0.605903 0 0.00590278 V1 0.584584 -0.162696 0.00590278 V2 0 0 0 + N0 0.0226746 -4.94615e-18 -0.999743 N1 0.0218614 -0.00589307 -0.999744 N2 0 0 -1 + txt003 +STRI + V0 0 -0.605903 0.00590278 V1 0.162696 -0.584584 0.00590278 V2 0.274486 -0.986255 0.0222222 + N0 0 -0.0226746 -0.999743 N1 0.00589307 -0.0218614 -0.999744 N2 0.0162121 -0.0601415 -0.998058 + txt003 +STRI + V0 0.274486 -0.986255 0.0222222 V1 0 -1.02222 0.0222222 V2 0 -0.605903 0.00590278 + N0 0.0162121 -0.0601415 -0.998058 N1 0 -0.0623783 -0.998053 N2 0 -0.0226746 -0.999743 + txt003 +STRI + V0 0.162696 -0.584584 0.00590278 V1 0.307888 -0.524218 0.00590278 V2 0.51944 -0.884412 0.0222222 + N0 0.00589307 -0.0218614 -0.999744 N1 0.0113382 -0.0195486 -0.999745 N2 0.0311919 -0.0537792 -0.998066 + txt003 +STRI + V0 0.51944 -0.884412 0.0222222 V1 0.274486 -0.986255 0.0222222 V2 0.162696 -0.584584 0.00590278 + N0 0.0311919 -0.0537792 -0.998066 N1 0.0162121 -0.0601415 -0.998058 N2 0.00589307 -0.0218614 -0.999744 + txt003 +STRI + V0 0.307888 -0.524218 0.00590278 V1 0.430191 -0.430191 0.00590278 V2 0.725778 -0.725778 0.0222222 + N0 0.0113382 -0.0195486 -0.999745 N1 0.015968 -0.015968 -0.999745 N2 0.0439291 -0.0439291 -0.998068 + txt003 +STRI + V0 0.725778 -0.725778 0.0222222 V1 0.51944 -0.884412 0.0222222 V2 0.307888 -0.524218 0.00590278 + N0 0.0439291 -0.0439291 -0.998068 N1 0.0311919 -0.0537792 -0.998066 N2 0.0113382 -0.0195486 -0.999745 + txt003 +STRI + V0 0.430191 -0.430191 0.00590278 V1 0.524218 -0.307888 0.00590278 V2 0.884412 -0.51944 0.0222222 + N0 0.015968 -0.015968 -0.999745 N1 0.0195486 -0.0113382 -0.999745 N2 0.0537792 -0.0311919 -0.998066 + txt003 +STRI + V0 0.884412 -0.51944 0.0222222 V1 0.725778 -0.725778 0.0222222 V2 0.430191 -0.430191 0.00590278 + N0 0.0537792 -0.0311919 -0.998066 N1 0.0439291 -0.0439291 -0.998068 N2 0.015968 -0.015968 -0.999745 + txt003 +STRI + V0 0.524218 -0.307888 0.00590278 V1 0.584584 -0.162696 0.00590278 V2 0.986255 -0.274486 0.0222222 + N0 0.0195486 -0.0113382 -0.999745 N1 0.0218614 -0.00589307 -0.999744 N2 0.0601415 -0.0162121 -0.998058 + txt003 +STRI + V0 0.986255 -0.274486 0.0222222 V1 0.884412 -0.51944 0.0222222 V2 0.524218 -0.307888 0.00590278 + N0 0.0601415 -0.0162121 -0.998058 N1 0.0537792 -0.0311919 -0.998066 N2 0.0195486 -0.0113382 -0.999745 + txt003 +STRI + V0 0.584584 -0.162696 0.00590278 V1 0.605903 0 0.00590278 V2 1.02222 2.22045e-16 0.0222222 + N0 0.0218614 -0.00589307 -0.999744 N1 0.0226746 -4.94615e-18 -0.999743 N2 0.0623783 0 -0.998053 + txt003 +STRI + V0 1.02222 2.22045e-16 0.0222222 V1 0.986255 -0.274486 0.0222222 V2 0.584584 -0.162696 0.00590278 + N0 0.0623783 0 -0.998053 N1 0.0601415 -0.0162121 -0.998058 N2 0.0218614 -0.00589307 -0.999744 + txt003 +STRI + V0 0 -1.02222 0.0222222 V1 0.274486 -0.986255 0.0222222 V2 0.344878 -1.23918 0.046875 + N0 0 -0.0623783 -0.998053 N1 0.0162121 -0.0601415 -0.998058 N2 0.0367561 -0.136353 -0.989978 + txt003 +STRI + V0 0.344878 -1.23918 0.046875 V1 0 -1.28438 0.046875 V2 0 -1.02222 0.0222222 + N0 0.0367561 -0.136353 -0.989978 N1 0 -0.141421 -0.989949 N2 0 -0.0623783 -0.998053 + txt003 +STRI + V0 0.274486 -0.986255 0.0222222 V1 0.51944 -0.884412 0.0222222 V2 0.652653 -1.11122 0.046875 + N0 0.0162121 -0.0601415 -0.998058 N1 0.0311919 -0.0537792 -0.998066 N2 0.0707208 -0.121932 -0.990016 + txt003 +STRI + V0 0.652653 -1.11122 0.046875 V1 0.344878 -1.23918 0.046875 V2 0.274486 -0.986255 0.0222222 + N0 0.0707208 -0.121932 -0.990016 N1 0.0367561 -0.136353 -0.989978 N2 0.0162121 -0.0601415 -0.998058 + txt003 +STRI + V0 0.51944 -0.884412 0.0222222 V1 0.725778 -0.725778 0.0222222 V2 0.911906 -0.911906 0.046875 + N0 0.0311919 -0.0537792 -0.998066 N1 0.0439291 -0.0439291 -0.998068 N2 0.0996006 -0.0996006 -0.99003 + txt003 +STRI + V0 0.911906 -0.911906 0.046875 V1 0.652653 -1.11122 0.046875 V2 0.51944 -0.884412 0.0222222 + N0 0.0996006 -0.0996006 -0.99003 N1 0.0707208 -0.121932 -0.990016 N2 0.0311919 -0.0537792 -0.998066 + txt003 +STRI + V0 0.725778 -0.725778 0.0222222 V1 0.884412 -0.51944 0.0222222 V2 1.11122 -0.652653 0.046875 + N0 0.0439291 -0.0439291 -0.998068 N1 0.0537792 -0.0311919 -0.998066 N2 0.121932 -0.0707208 -0.990016 + txt003 +STRI + V0 1.11122 -0.652653 0.046875 V1 0.911906 -0.911906 0.046875 V2 0.725778 -0.725778 0.0222222 + N0 0.121932 -0.0707208 -0.990016 N1 0.0996006 -0.0996006 -0.99003 N2 0.0439291 -0.0439291 -0.998068 + txt003 +STRI + V0 0.884412 -0.51944 0.0222222 V1 0.986255 -0.274486 0.0222222 V2 1.23918 -0.344878 0.046875 + N0 0.0537792 -0.0311919 -0.998066 N1 0.0601415 -0.0162121 -0.998058 N2 0.136353 -0.0367561 -0.989978 + txt003 +STRI + V0 1.23918 -0.344878 0.046875 V1 1.11122 -0.652653 0.046875 V2 0.884412 -0.51944 0.0222222 + N0 0.136353 -0.0367561 -0.989978 N1 0.121932 -0.0707208 -0.990016 N2 0.0537792 -0.0311919 -0.998066 + txt003 +STRI + V0 0.986255 -0.274486 0.0222222 V1 1.02222 2.22045e-16 0.0222222 V2 1.28437 -2.22045e-16 0.046875 + N0 0.0601415 -0.0162121 -0.998058 N1 0.0623783 0 -0.998053 N2 0.141421 0 -0.989949 + txt003 +STRI + V0 1.28437 -2.22045e-16 0.046875 V1 1.23918 -0.344878 0.046875 V2 0.986255 -0.274486 0.0222222 + N0 0.141421 0 -0.989949 N1 0.136353 -0.0367561 -0.989978 N2 0.0601415 -0.0162121 -0.998058 + txt003 +STRI + V0 0 -1.28438 0.046875 V1 0.344878 -1.23918 0.046875 V2 0.383385 -1.37754 0.0777778 + N0 0 -0.141421 -0.989949 N1 0.0367561 -0.136353 -0.989978 N2 0.085395 -0.316788 -0.944644 + txt003 +STRI + V0 0.383385 -1.37754 0.0777778 V1 0 -1.42778 0.0777778 V2 0 -1.28438 0.046875 + N0 0.085395 -0.316788 -0.944644 N1 0 -0.328521 -0.944497 N2 0 -0.141421 -0.989949 + txt003 +STRI + V0 0.344878 -1.23918 0.046875 V1 0.652653 -1.11122 0.046875 V2 0.725523 -1.23529 0.0777778 + N0 0.0367561 -0.136353 -0.989978 N1 0.0707208 -0.121932 -0.990016 N2 0.164332 -0.283331 -0.944838 + txt003 +STRI + V0 0.725523 -1.23529 0.0777778 V1 0.383385 -1.37754 0.0777778 V2 0.344878 -1.23918 0.046875 + N0 0.164332 -0.283331 -0.944838 N1 0.085395 -0.316788 -0.944644 N2 0.0367561 -0.136353 -0.989978 + txt003 +STRI + V0 0.652653 -1.11122 0.046875 V1 0.911906 -0.911906 0.046875 V2 1.01372 -1.01372 0.0777778 + N0 0.0707208 -0.121932 -0.990016 N1 0.0996006 -0.0996006 -0.99003 N2 0.231454 -0.231454 -0.944912 + txt003 +STRI + V0 1.01372 -1.01372 0.0777778 V1 0.725523 -1.23529 0.0777778 V2 0.652653 -1.11122 0.046875 + N0 0.231454 -0.231454 -0.944912 N1 0.164332 -0.283331 -0.944838 N2 0.0707208 -0.121932 -0.990016 + txt003 +STRI + V0 0.911906 -0.911906 0.046875 V1 1.11122 -0.652653 0.046875 V2 1.23529 -0.725523 0.0777778 + N0 0.0996006 -0.0996006 -0.99003 N1 0.121932 -0.0707208 -0.990016 N2 0.283331 -0.164332 -0.944838 + txt003 +STRI + V0 1.23529 -0.725523 0.0777778 V1 1.01372 -1.01372 0.0777778 V2 0.911906 -0.911906 0.046875 + N0 0.283331 -0.164332 -0.944838 N1 0.231454 -0.231454 -0.944912 N2 0.0996006 -0.0996006 -0.99003 + txt003 +STRI + V0 1.11122 -0.652653 0.046875 V1 1.23918 -0.344878 0.046875 V2 1.37754 -0.383385 0.0777778 + N0 0.121932 -0.0707208 -0.990016 N1 0.136353 -0.0367561 -0.989978 N2 0.316788 -0.085395 -0.944644 + txt003 +STRI + V0 1.37754 -0.383385 0.0777778 V1 1.23529 -0.725523 0.0777778 V2 1.11122 -0.652653 0.046875 + N0 0.316788 -0.085395 -0.944644 N1 0.283331 -0.164332 -0.944838 N2 0.121932 -0.0707208 -0.990016 + txt003 +STRI + V0 1.23918 -0.344878 0.046875 V1 1.28437 -2.22045e-16 0.046875 V2 1.42778 2.22045e-16 0.0777778 + N0 0.136353 -0.0367561 -0.989978 N1 0.141421 0 -0.989949 N2 0.328521 -6.08223e-17 -0.944497 + txt003 +STRI + V0 1.42778 2.22045e-16 0.0777778 V1 1.37754 -0.383385 0.0777778 V2 1.23918 -0.344878 0.046875 + N0 0.328521 -6.08223e-17 -0.944497 N1 0.316788 -0.085395 -0.944644 N2 0.136353 -0.0367561 -0.989978 + txt003 +STRI + V0 0 -1.42778 0.0777778 V1 0.383385 -1.37754 0.0777778 V2 0.399515 -1.4355 0.112847 + N0 0 -0.328521 -0.944497 N1 0.085395 -0.316788 -0.944644 N2 0.200299 -0.743044 -0.638566 + txt003 +STRI + V0 0.399515 -1.4355 0.112847 V1 0 -1.48785 0.112847 V2 0 -1.42778 0.0777778 + N0 0.200299 -0.743044 -0.638566 N1 0 -0.770022 -0.638018 N2 0 -0.328521 -0.944497 + txt003 +STRI + V0 0.383385 -1.37754 0.0777778 V1 0.725523 -1.23529 0.0777778 V2 0.756047 -1.28726 0.112847 + N0 0.085395 -0.316788 -0.944644 N1 0.164332 -0.283331 -0.944838 N2 0.385806 -0.665182 -0.639286 + txt003 +STRI + V0 0.756047 -1.28726 0.112847 V1 0.399515 -1.4355 0.112847 V2 0.383385 -1.37754 0.0777778 + N0 0.385806 -0.665182 -0.639286 N1 0.200299 -0.743044 -0.638566 N2 0.085395 -0.316788 -0.944644 + txt003 +STRI + V0 0.725523 -1.23529 0.0777778 V1 1.01372 -1.01372 0.0777778 V2 1.05637 -1.05637 0.112847 + N0 0.164332 -0.283331 -0.944838 N1 0.231454 -0.231454 -0.944912 N2 0.543581 -0.543581 -0.639562 + txt003 +STRI + V0 1.05637 -1.05637 0.112847 V1 0.756047 -1.28726 0.112847 V2 0.725523 -1.23529 0.0777778 + N0 0.543581 -0.543581 -0.639562 N1 0.385806 -0.665182 -0.639286 N2 0.164332 -0.283331 -0.944838 + txt003 +STRI + V0 1.01372 -1.01372 0.0777778 V1 1.23529 -0.725523 0.0777778 V2 1.28726 -0.756047 0.112847 + N0 0.231454 -0.231454 -0.944912 N1 0.283331 -0.164332 -0.944838 N2 0.665182 -0.385806 -0.639286 + txt003 +STRI + V0 1.28726 -0.756047 0.112847 V1 1.05637 -1.05637 0.112847 V2 1.01372 -1.01372 0.0777778 + N0 0.665182 -0.385806 -0.639286 N1 0.543581 -0.543581 -0.639562 N2 0.231454 -0.231454 -0.944912 + txt003 +STRI + V0 1.23529 -0.725523 0.0777778 V1 1.37754 -0.383385 0.0777778 V2 1.4355 -0.399515 0.112847 + N0 0.283331 -0.164332 -0.944838 N1 0.316788 -0.085395 -0.944644 N2 0.743044 -0.200299 -0.638566 + txt003 +STRI + V0 1.4355 -0.399515 0.112847 V1 1.28726 -0.756047 0.112847 V2 1.23529 -0.725523 0.0777778 + N0 0.743044 -0.200299 -0.638566 N1 0.665182 -0.385806 -0.639286 N2 0.283331 -0.164332 -0.944838 + txt003 +STRI + V0 1.37754 -0.383385 0.0777778 V1 1.42778 2.22045e-16 0.0777778 V2 1.48785 0 0.112847 + N0 0.316788 -0.085395 -0.944644 N1 0.328521 -6.08223e-17 -0.944497 N2 0.770022 -1.36806e-16 -0.638018 + txt003 +STRI + V0 1.48785 0 0.112847 V1 1.4355 -0.399515 0.112847 V2 1.37754 -0.383385 0.0777778 + N0 0.770022 -1.36806e-16 -0.638018 N1 0.743044 -0.200299 -0.638566 N2 0.316788 -0.085395 -0.944644 + txt003 +STRI + V0 0 -1.48785 0.112847 V1 0.399515 -1.4355 0.112847 V2 0.402778 -1.44722 0.15 + N0 0 -0.770022 -0.638018 N1 0.200299 -0.743044 -0.638566 N2 0.260275 -0.965535 -2.07142e-16 + txt003 +STRI + V0 0.402778 -1.44722 0.15 V1 0 -1.5 0.15 V2 0 -1.48785 0.112847 + N0 0.260275 -0.965535 -2.07142e-16 N1 0 -1 0 N2 0 -0.770022 -0.638018 + txt003 +STRI + V0 0.399515 -1.4355 0.112847 V1 0.756047 -1.28726 0.112847 V2 0.762222 -1.29778 0.15 + N0 0.200299 -0.743044 -0.638566 N1 0.385806 -0.665182 -0.639286 N2 0.501718 -0.865031 -5.46348e-16 + txt003 +STRI + V0 0.762222 -1.29778 0.15 V1 0.402778 -1.44722 0.15 V2 0.399515 -1.4355 0.112847 + N0 0.501718 -0.865031 -5.46348e-16 N1 0.260275 -0.965535 -2.07142e-16 N2 0.200299 -0.743044 -0.638566 + txt003 +STRI + V0 0.756047 -1.28726 0.112847 V1 1.05637 -1.05637 0.112847 V2 1.065 -1.065 0.15 + N0 0.385806 -0.665182 -0.639286 N1 0.543581 -0.543581 -0.639562 N2 0.707107 -0.707107 -6.97819e-16 + txt003 +STRI + V0 1.065 -1.065 0.15 V1 0.762222 -1.29778 0.15 V2 0.756047 -1.28726 0.112847 + N0 0.707107 -0.707107 -6.97819e-16 N1 0.501718 -0.865031 -5.46348e-16 N2 0.385806 -0.665182 -0.639286 + txt003 +STRI + V0 1.05637 -1.05637 0.112847 V1 1.28726 -0.756047 0.112847 V2 1.29778 -0.762222 0.15 + N0 0.543581 -0.543581 -0.639562 N1 0.665182 -0.385806 -0.639286 N2 0.865031 -0.501718 -5.46348e-16 + txt003 +STRI + V0 1.29778 -0.762222 0.15 V1 1.065 -1.065 0.15 V2 1.05637 -1.05637 0.112847 + N0 0.865031 -0.501718 -5.46348e-16 N1 0.707107 -0.707107 -6.97819e-16 N2 0.543581 -0.543581 -0.639562 + txt003 +STRI + V0 1.28726 -0.756047 0.112847 V1 1.4355 -0.399515 0.112847 V2 1.44722 -0.402778 0.15 + N0 0.665182 -0.385806 -0.639286 N1 0.743044 -0.200299 -0.638566 N2 0.965535 -0.260275 -2.07142e-16 + txt003 +STRI + V0 1.44722 -0.402778 0.15 V1 1.29778 -0.762222 0.15 V2 1.28726 -0.756047 0.112847 + N0 0.965535 -0.260275 -2.07142e-16 N1 0.865031 -0.501718 -5.46348e-16 N2 0.665182 -0.385806 -0.639286 + txt003 +STRI + V0 1.4355 -0.399515 0.112847 V1 1.48785 0 0.112847 V2 1.5 0 0.15 + N0 0.743044 -0.200299 -0.638566 N1 0.770022 -1.36806e-16 -0.638018 N2 1 0 0 + txt003 +STRI + V0 1.5 0 0.15 V1 1.44722 -0.402778 0.15 V2 1.4355 -0.399515 0.112847 + N0 1 0 0 N1 0.965535 -0.260275 -2.07142e-16 N2 0.743044 -0.200299 -0.638566 + txt003 + +END_SCENE diff --git a/src/tbb/examples/parallel_for/tachyon/dat/trypsin4pti.dat b/src/tbb/examples/parallel_for/tachyon/dat/trypsin4pti.dat new file mode 100644 index 0000000..7d547f2 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/dat/trypsin4pti.dat @@ -0,0 +1,538 @@ +BEGIN_SCENE + OUTFILE /dev/null + RESOLUTION 768 768 + VERBOSE 0 + +CAMERA + ZOOM 1.0 + ASPECTRATIO 1.0 + ANTIALIASING 0 + RAYDEPTH 4 + CENTER 15.0 20.0 -50.0 + VIEWDIR 0.0 0.0 1.0 + UPDIR 0.0 1.0 0.0 +END_CAMERA + + +LIGHT + CENTER 40.0 50.0 -40.0 + RAD 0.2 + COLOR 0.5 0.5 0.5 + +LIGHT + CENTER -40.0 20.0 -40.0 + RAD 0.2 + COLOR 0.5 0.5 0.5 + + +TEXDEF O AMBIENT 0.1 DIFFUSE 0.9 SPECULAR 0.0 OPACITY 1.0 + PHONG PLASTIC 0.5 PHONG_SIZE 24.8 + COLOR 1.0 0.0 0.0 TEXFUNC 0 +TEXALIAS OH O +TEXALIAS OD1 O +TEXALIAS OD2 O +TEXALIAS OE1 O +TEXALIAS OE2 O +TEXALIAS OG O +TEXALIAS OG1 O +TEXALIAS OG2 O +TEXALIAS OXT O + +TEXDEF C AMBIENT 0.1 DIFFUSE 0.5 SPECULAR 0.0 OPACITY 1.0 + PHONG PLASTIC 0.5 PHONG_SIZE 24.8 + COLOR 0.5 0.5 0.5 TEXFUNC 0 +TEXALIAS CA C +TEXALIAS CB C +TEXALIAS CD C +TEXALIAS CD1 C +TEXALIAS CD2 C +TEXALIAS CE C +TEXALIAS CE1 C +TEXALIAS CE2 C +TEXALIAS CG C +TEXALIAS CG1 C +TEXALIAS CG2 C +TEXALIAS CZ C + +TEXDEF N AMBIENT 0.1 DIFFUSE 0.9 SPECULAR 0.0 OPACITY 1.0 + PHONG PLASTIC 0.5 PHONG_SIZE 24.8 + COLOR 0.5 0.5 1.0 TEXFUNC 0 +TEXALIAS ND2 N +TEXALIAS NH1 N +TEXALIAS NH2 N +TEXALIAS NE N +TEXALIAS NE2 N +TEXALIAS NZ N + +TEXDEF SD AMBIENT 0.1 DIFFUSE 0.9 SPECULAR 0.0 OPACITY 1.0 + PHONG METAL 0.5 PHONG_SIZE 24.8 + COLOR 1.0 1.0 1.0 TEXFUNC 0 + +TEXDEF SG AMBIENT 0.1 DIFFUSE 0.9 SPECULAR 0.0 OPACITY 1.0 + PHONG PLASTIC 0.5 PHONG_SIZE 24.8 + COLOR 1.0 1.0 1.0 TEXFUNC 0 + +SPHERE CENTER 26.465000 27.452000 -2.490000 RAD 1.0 N +SPHERE CENTER 25.497000 26.862000 -1.573000 RAD 1.0 CA +SPHERE CENTER 26.193001 26.179001 -0.437000 RAD 1.0 C +SPHERE CENTER 27.270000 25.549000 -0.624000 RAD 1.0 O +SPHERE CENTER 24.583000 25.804001 -2.239000 RAD 1.0 CB +SPHERE CENTER 25.091000 24.375000 -2.409000 RAD 1.0 CG +SPHERE CENTER 24.018999 23.427999 -2.996000 RAD 1.0 CD +SPHERE CENTER 23.591000 24.028000 -4.287000 RAD 1.0 NE +SPHERE CENTER 24.299000 23.972000 -5.389000 RAD 1.0 CZ +SPHERE CENTER 25.431999 23.261000 -5.440000 RAD 1.0 NH1 +SPHERE CENTER 23.721001 24.372999 -6.467000 RAD 1.0 NH2 +SPHERE CENTER 25.667000 26.396000 0.708000 RAD 1.0 N +SPHERE CENTER 26.222000 25.760000 1.891000 RAD 1.0 CA +SPHERE CENTER 26.207001 24.242001 1.830000 RAD 1.0 C +SPHERE CENTER 25.400000 23.576000 1.139000 RAD 1.0 O +SPHERE CENTER 25.260000 26.207001 3.033000 RAD 1.0 CB +SPHERE CENTER 24.511999 27.427999 2.493000 RAD 1.0 CG +SPHERE CENTER 24.606001 27.382000 0.978000 RAD 1.0 CD +SPHERE CENTER 27.170000 23.634001 2.462000 RAD 1.0 N +SPHERE CENTER 27.284000 22.163000 2.498000 RAD 1.0 CA +SPHERE CENTER 26.042999 21.506001 3.085000 RAD 1.0 C +SPHERE CENTER 25.752001 20.350000 2.705000 RAD 1.0 O +SPHERE CENTER 28.424999 21.747000 3.461000 RAD 1.0 CB +SPHERE CENTER 29.791000 21.886000 2.787000 RAD 1.0 CG +SPHERE CENTER 29.875000 22.104000 1.543000 RAD 1.0 OD1 +SPHERE CENTER 30.806000 21.500999 3.431000 RAD 1.0 OD2 +SPHERE CENTER 25.393999 22.184000 4.041000 RAD 1.0 N +SPHERE CENTER 24.172001 21.584999 4.618000 RAD 1.0 CA +SPHERE CENTER 23.009001 21.375000 3.624000 RAD 1.0 C +SPHERE CENTER 22.082001 20.603001 3.921000 RAD 1.0 O +SPHERE CENTER 23.691999 22.330999 5.862000 RAD 1.0 CB +SPHERE CENTER 23.191999 23.778999 5.639000 RAD 1.0 CG +SPHERE CENTER 21.961000 24.002001 5.060000 RAD 1.0 CD1 +SPHERE CENTER 23.951000 24.841000 6.050000 RAD 1.0 CD2 +SPHERE CENTER 21.497000 25.281000 4.869000 RAD 1.0 CE1 +SPHERE CENTER 23.510000 26.124001 5.854000 RAD 1.0 CE2 +SPHERE CENTER 22.277000 26.363001 5.249000 RAD 1.0 CZ +SPHERE CENTER 23.094999 22.004000 2.522000 RAD 1.0 N +SPHERE CENTER 22.106001 21.863001 1.467000 RAD 1.0 CA +SPHERE CENTER 22.191999 20.518000 0.830000 RAD 1.0 C +SPHERE CENTER 21.230000 20.068001 0.167000 RAD 1.0 O +SPHERE CENTER 22.358000 22.903999 0.371000 RAD 1.0 CB +SPHERE CENTER 22.145000 24.591999 0.888000 RAD 1.0 SG +SPHERE CENTER 23.326000 19.826000 1.008000 RAD 1.0 N +SPHERE CENTER 23.436001 18.459999 0.459000 RAD 1.0 CA +SPHERE CENTER 22.958000 17.365000 1.407000 RAD 1.0 C +SPHERE CENTER 22.938000 16.180000 0.999000 RAD 1.0 O +SPHERE CENTER 24.898001 18.084000 0.131000 RAD 1.0 CB +SPHERE CENTER 25.572001 19.129000 -0.776000 RAD 1.0 CG +SPHERE CENTER 27.037001 18.695000 -1.116000 RAD 1.0 CD1 +SPHERE CENTER 24.791000 19.488001 -2.049000 RAD 1.0 CD2 +SPHERE CENTER 22.545000 17.716000 2.628000 RAD 1.0 N +SPHERE CENTER 22.039000 16.646000 3.528000 RAD 1.0 CA +SPHERE CENTER 20.615999 16.285000 3.113000 RAD 1.0 C +SPHERE CENTER 19.860001 17.136000 2.576000 RAD 1.0 O +SPHERE CENTER 21.764000 17.216999 4.920000 RAD 1.0 CB +SPHERE CENTER 22.813999 18.035000 5.647000 RAD 1.0 CG +SPHERE CENTER 22.152000 18.707001 6.870000 RAD 1.0 CD +SPHERE CENTER 22.980000 19.100000 7.718000 RAD 1.0 OE1 +SPHERE CENTER 21.086000 19.403999 6.779000 RAD 1.0 OE2 +SPHERE CENTER 20.254000 15.031000 3.334000 RAD 1.0 N +SPHERE CENTER 18.892000 14.554000 3.034000 RAD 1.0 CA +SPHERE CENTER 17.954000 15.160000 4.079000 RAD 1.0 C +SPHERE CENTER 18.443001 15.606000 5.146000 RAD 1.0 O +SPHERE CENTER 18.910000 13.045000 3.274000 RAD 1.0 CB +SPHERE CENTER 20.226000 12.742000 4.021000 RAD 1.0 CG +SPHERE CENTER 21.107000 14.009000 3.934000 RAD 1.0 CD +SPHERE CENTER 16.681999 15.232000 3.767000 RAD 1.0 N +SPHERE CENTER 15.690000 15.852000 4.661000 RAD 1.0 CA +SPHERE CENTER 15.550000 15.006000 5.916000 RAD 1.0 C +SPHERE CENTER 15.693000 13.769000 5.836000 RAD 1.0 O +SPHERE CENTER 14.367000 15.707000 3.867000 RAD 1.0 CB +SPHERE CENTER 14.571000 14.716000 2.710000 RAD 1.0 CG +SPHERE CENTER 16.090000 14.597000 2.574000 RAD 1.0 CD +SPHERE CENTER 15.365000 15.630000 7.042000 RAD 1.0 N +SPHERE CENTER 15.310000 14.908000 8.298000 RAD 1.0 CA +SPHERE CENTER 13.953000 15.177000 8.952000 RAD 1.0 C +SPHERE CENTER 13.699000 16.320000 9.382000 RAD 1.0 O +SPHERE CENTER 16.532000 15.383000 9.122000 RAD 1.0 CB +SPHERE CENTER 16.608000 14.781000 10.525000 RAD 1.0 CG +SPHERE CENTER 17.132000 13.535000 10.707000 RAD 1.0 CD1 +SPHERE CENTER 16.155001 15.523000 11.588000 RAD 1.0 CD2 +SPHERE CENTER 17.216000 12.999000 11.982000 RAD 1.0 CE1 +SPHERE CENTER 16.266001 14.985000 12.862000 RAD 1.0 CE2 +SPHERE CENTER 16.808001 13.746000 13.047000 RAD 1.0 CZ +SPHERE CENTER 16.878000 13.192000 14.372000 RAD 1.0 OH +SPHERE CENTER 13.161000 14.146000 9.088000 RAD 1.0 N +SPHERE CENTER 11.802000 14.321000 9.642000 RAD 1.0 CA +SPHERE CENTER 11.855000 14.484000 11.146000 RAD 1.0 C +SPHERE CENTER 11.105000 15.314000 11.759000 RAD 1.0 O +SPHERE CENTER 10.963000 13.105000 9.273000 RAD 1.0 CB +SPHERE CENTER 10.706000 13.192000 7.854000 RAD 1.0 OG1 +SPHERE CENTER 9.611000 13.152000 10.045000 RAD 1.0 CG2 +SPHERE CENTER 12.789000 13.760000 11.726000 RAD 1.0 N +SPHERE CENTER 13.002000 13.922000 13.198000 RAD 1.0 CA +SPHERE CENTER 12.107000 12.944000 13.909000 RAD 1.0 C +SPHERE CENTER 11.333000 12.212000 13.239000 RAD 1.0 O +SPHERE CENTER 12.235000 12.905000 15.210000 RAD 1.0 N +SPHERE CENTER 11.516000 11.958000 16.066999 RAD 1.0 CA +SPHERE CENTER 10.094000 12.319000 16.468000 RAD 1.0 C +SPHERE CENTER 9.440000 11.442000 17.052000 RAD 1.0 O +SPHERE CENTER 12.272000 11.936000 17.370001 RAD 1.0 CB +SPHERE CENTER 13.164000 13.172000 17.399000 RAD 1.0 CG +SPHERE CENTER 13.281000 13.627000 15.925000 RAD 1.0 CD +SPHERE CENTER 9.629000 13.519000 16.214001 RAD 1.0 N +SPHERE CENTER 8.290000 13.980000 16.615999 RAD 1.0 CA +SPHERE CENTER 7.268000 13.720000 15.515000 RAD 1.0 C +SPHERE CENTER 7.672000 13.397000 14.387000 RAD 1.0 O +SPHERE CENTER 8.279000 15.441000 16.966999 RAD 1.0 CB +SPHERE CENTER 9.221000 15.735000 18.490000 RAD 1.0 SG +SPHERE CENTER 6.027000 13.680000 15.869000 RAD 1.0 N +SPHERE CENTER 5.005000 13.220000 14.945000 RAD 1.0 CA +SPHERE CENTER 3.964000 14.283000 14.630000 RAD 1.0 C +SPHERE CENTER 2.777000 13.949000 14.377000 RAD 1.0 O +SPHERE CENTER 4.310000 11.998000 15.592000 RAD 1.0 CB +SPHERE CENTER 5.273000 10.848000 15.913000 RAD 1.0 CG +SPHERE CENTER 5.781000 10.034000 14.702000 RAD 1.0 CD +SPHERE CENTER 6.855000 9.016000 15.126000 RAD 1.0 CE +SPHERE CENTER 7.357000 8.291000 13.953000 RAD 1.0 NZ +SPHERE CENTER 4.325000 15.549000 14.618000 RAD 1.0 N +SPHERE CENTER 3.513000 16.639999 14.122000 RAD 1.0 CA +SPHERE CENTER 3.561000 16.615000 12.586000 RAD 1.0 C +SPHERE CENTER 4.270000 15.752000 12.023000 RAD 1.0 O +SPHERE CENTER 3.984000 17.995001 14.670000 RAD 1.0 CB +SPHERE CENTER 2.781000 17.424999 11.943000 RAD 1.0 N +SPHERE CENTER 2.700000 17.355000 10.457000 RAD 1.0 CA +SPHERE CENTER 2.875000 18.731001 9.887000 RAD 1.0 C +SPHERE CENTER 1.878000 19.469999 9.653000 RAD 1.0 O +SPHERE CENTER 1.320000 16.787001 9.970000 RAD 1.0 CB +SPHERE CENTER 1.186000 15.339000 10.395000 RAD 1.0 CG +SPHERE CENTER -0.170000 14.751000 9.963000 RAD 1.0 CD +SPHERE CENTER -1.132000 15.455000 10.801000 RAD 1.0 NE +SPHERE CENTER -1.531000 14.913000 11.939000 RAD 1.0 CZ +SPHERE CENTER -1.172000 13.658000 12.165000 RAD 1.0 NH1 +SPHERE CENTER -2.202000 15.647000 12.795000 RAD 1.0 NH2 +SPHERE CENTER 4.154000 19.110001 9.817000 RAD 1.0 N +SPHERE CENTER 4.595000 20.444000 9.391000 RAD 1.0 CA +SPHERE CENTER 5.249000 20.388000 8.012000 RAD 1.0 C +SPHERE CENTER 6.193000 19.612000 7.834000 RAD 1.0 O +SPHERE CENTER 5.590000 20.988001 10.452000 RAD 1.0 CB +SPHERE CENTER 4.792000 21.062000 11.815000 RAD 1.0 CG1 +SPHERE CENTER 5.985000 22.451000 10.085000 RAD 1.0 CG2 +SPHERE CENTER 5.689000 21.535999 12.955000 RAD 1.0 CD1 +SPHERE CENTER 4.586000 20.955999 7.035000 RAD 1.0 N +SPHERE CENTER 5.154000 20.879000 5.697000 RAD 1.0 CA +SPHERE CENTER 6.286000 21.912001 5.572000 RAD 1.0 C +SPHERE CENTER 6.156000 23.146000 5.785000 RAD 1.0 O +SPHERE CENTER 4.095000 21.205000 4.648000 RAD 1.0 CB +SPHERE CENTER 2.836000 20.316999 4.886000 RAD 1.0 CG1 +SPHERE CENTER 4.655000 20.930000 3.250000 RAD 1.0 CG2 +SPHERE CENTER 3.122000 18.813999 4.850000 RAD 1.0 CD1 +SPHERE CENTER 7.451000 21.372000 5.297000 RAD 1.0 N +SPHERE CENTER 8.602000 22.257000 5.060000 RAD 1.0 CA +SPHERE CENTER 9.150000 21.950001 3.673000 RAD 1.0 C +SPHERE CENTER 8.840000 20.896000 3.088000 RAD 1.0 O +SPHERE CENTER 9.698000 21.896999 6.092000 RAD 1.0 CB +SPHERE CENTER 9.226000 22.299999 7.493000 RAD 1.0 CG +SPHERE CENTER 9.248000 23.850000 7.622000 RAD 1.0 CD +SPHERE CENTER 8.810000 24.311001 8.962000 RAD 1.0 NE +SPHERE CENTER 9.575000 24.336000 10.075000 RAD 1.0 CZ +SPHERE CENTER 10.888000 24.077000 10.044000 RAD 1.0 NH1 +SPHERE CENTER 9.050000 24.893000 11.170000 RAD 1.0 NH2 +SPHERE CENTER 10.178000 22.695000 3.318000 RAD 1.0 N +SPHERE CENTER 10.959000 22.444000 2.085000 RAD 1.0 CA +SPHERE CENTER 12.407000 22.010000 2.386000 RAD 1.0 C +SPHERE CENTER 12.987000 22.511999 3.378000 RAD 1.0 O +SPHERE CENTER 10.997000 23.770000 1.282000 RAD 1.0 CB +SPHERE CENTER 9.641000 24.038000 0.627000 RAD 1.0 CG +SPHERE CENTER 8.639000 24.591999 1.399000 RAD 1.0 CD1 +SPHERE CENTER 9.451000 23.725000 -0.691000 RAD 1.0 CD2 +SPHERE CENTER 7.403000 24.861000 0.831000 RAD 1.0 CE1 +SPHERE CENTER 8.213000 23.993000 -1.249000 RAD 1.0 CE2 +SPHERE CENTER 7.215000 24.576000 -0.494000 RAD 1.0 CZ +SPHERE CENTER 5.879000 24.768999 -1.060000 RAD 1.0 OH +SPHERE CENTER 12.977000 21.141001 1.535000 RAD 1.0 N +SPHERE CENTER 14.449000 20.892000 1.626000 RAD 1.0 CA +SPHERE CENTER 15.018000 21.045000 0.237000 RAD 1.0 C +SPHERE CENTER 14.250000 20.837000 -0.740000 RAD 1.0 O +SPHERE CENTER 14.664000 19.434999 2.142000 RAD 1.0 CB +SPHERE CENTER 14.283000 18.275999 1.191000 RAD 1.0 CG +SPHERE CENTER 15.290000 17.639000 0.506000 RAD 1.0 CD1 +SPHERE CENTER 12.962000 17.907000 0.976000 RAD 1.0 CD2 +SPHERE CENTER 14.981000 16.632000 -0.392000 RAD 1.0 CE1 +SPHERE CENTER 12.638000 16.909000 0.061000 RAD 1.0 CE2 +SPHERE CENTER 13.673000 16.261999 -0.626000 RAD 1.0 CZ +SPHERE CENTER 16.336000 21.281000 0.152000 RAD 1.0 N +SPHERE CENTER 16.948000 21.292000 -1.153000 RAD 1.0 CA +SPHERE CENTER 17.365000 19.888000 -1.542000 RAD 1.0 C +SPHERE CENTER 18.009001 19.184000 -0.744000 RAD 1.0 O +SPHERE CENTER 18.188000 22.194000 -1.071000 RAD 1.0 CB +SPHERE CENTER 18.906000 22.263000 -2.442000 RAD 1.0 CG +SPHERE CENTER 20.089001 21.621000 -2.663000 RAD 1.0 CD1 +SPHERE CENTER 18.361000 23.033001 -3.436000 RAD 1.0 CD2 +SPHERE CENTER 20.733000 21.778999 -3.896000 RAD 1.0 CE1 +SPHERE CENTER 18.990999 23.184999 -4.662000 RAD 1.0 CE2 +SPHERE CENTER 20.184999 22.562000 -4.864000 RAD 1.0 CZ +SPHERE CENTER 20.826000 22.768000 -6.115000 RAD 1.0 OH +SPHERE CENTER 16.913000 19.452999 -2.726000 RAD 1.0 N +SPHERE CENTER 17.295000 18.160000 -3.291000 RAD 1.0 CA +SPHERE CENTER 18.406000 18.332001 -4.341000 RAD 1.0 C +SPHERE CENTER 18.166000 18.843000 -5.464000 RAD 1.0 O +SPHERE CENTER 16.052000 17.558001 -3.946000 RAD 1.0 CB +SPHERE CENTER 16.354000 16.226999 -4.626000 RAD 1.0 CG +SPHERE CENTER 17.531000 15.754000 -4.725000 RAD 1.0 OD1 +SPHERE CENTER 15.234000 15.549000 -4.870000 RAD 1.0 ND2 +SPHERE CENTER 19.655001 18.124001 -3.871000 RAD 1.0 N +SPHERE CENTER 20.851000 18.420000 -4.681000 RAD 1.0 CA +SPHERE CENTER 20.920000 17.650000 -6.010000 RAD 1.0 C +SPHERE CENTER 21.385000 18.257000 -6.997000 RAD 1.0 O +SPHERE CENTER 22.112000 18.070999 -3.866000 RAD 1.0 CB +SPHERE CENTER 20.333000 16.480000 -6.081000 RAD 1.0 N +SPHERE CENTER 20.243999 15.784000 -7.383000 RAD 1.0 CA +SPHERE CENTER 19.287001 16.482000 -8.327000 RAD 1.0 C +SPHERE CENTER 19.478001 16.368999 -9.556000 RAD 1.0 O +SPHERE CENTER 19.732000 14.353000 -7.259000 RAD 1.0 CB +SPHERE CENTER 20.799999 13.485000 -6.626000 RAD 1.0 CG +SPHERE CENTER 20.299000 12.037000 -6.533000 RAD 1.0 CD +SPHERE CENTER 21.386999 11.067000 -6.033000 RAD 1.0 CE +SPHERE CENTER 21.820999 11.437000 -4.681000 RAD 1.0 NZ +SPHERE CENTER 18.212999 17.041000 -7.772000 RAD 1.0 N +SPHERE CENTER 17.181999 17.617001 -8.631000 RAD 1.0 CA +SPHERE CENTER 17.468000 19.070000 -8.921000 RAD 1.0 C +SPHERE CENTER 16.909000 19.707001 -9.863000 RAD 1.0 O +SPHERE CENTER 15.833000 17.423000 -7.901000 RAD 1.0 CB +SPHERE CENTER 18.299000 19.622000 -8.061000 RAD 1.0 N +SPHERE CENTER 18.625999 21.035999 -8.237000 RAD 1.0 CA +SPHERE CENTER 17.587999 22.051001 -7.738000 RAD 1.0 C +SPHERE CENTER 17.702000 23.257999 -8.056000 RAD 1.0 O +SPHERE CENTER 16.632000 21.566000 -6.970000 RAD 1.0 N +SPHERE CENTER 15.576000 22.431999 -6.478000 RAD 1.0 CA +SPHERE CENTER 14.947000 21.879999 -5.199000 RAD 1.0 C +SPHERE CENTER 15.304000 20.784000 -4.719000 RAD 1.0 O +SPHERE CENTER 14.553000 22.764999 -7.568000 RAD 1.0 CB +SPHERE CENTER 14.018000 21.514000 -8.283000 RAD 1.0 CG +SPHERE CENTER 13.211000 20.593000 -7.394000 RAD 1.0 CD1 +SPHERE CENTER 13.189000 21.898001 -9.518000 RAD 1.0 CD2 +SPHERE CENTER 14.114000 22.691999 -4.605000 RAD 1.0 N +SPHERE CENTER 13.591000 22.299999 -3.306000 RAD 1.0 CA +SPHERE CENTER 12.246000 21.612000 -3.398000 RAD 1.0 C +SPHERE CENTER 11.508000 21.862000 -4.381000 RAD 1.0 O +SPHERE CENTER 13.406000 23.628000 -2.540000 RAD 1.0 CB +SPHERE CENTER 14.977000 24.433001 -2.196000 RAD 1.0 SG +SPHERE CENTER 12.005000 20.672001 -2.530000 RAD 1.0 N +SPHERE CENTER 10.813000 19.820999 -2.569000 RAD 1.0 CA +SPHERE CENTER 10.208000 19.822001 -1.167000 RAD 1.0 C +SPHERE CENTER 10.918000 20.218000 -0.210000 RAD 1.0 O +SPHERE CENTER 11.110000 18.377001 -3.007000 RAD 1.0 CB +SPHERE CENTER 11.604000 18.464001 -4.496000 RAD 1.0 CG +SPHERE CENTER 12.041000 17.093000 -4.992000 RAD 1.0 CD +SPHERE CENTER 12.104000 16.884001 -6.223000 RAD 1.0 OE1 +SPHERE CENTER 12.461000 16.246000 -4.115000 RAD 1.0 NE2 +SPHERE CENTER 8.983000 19.459000 -1.072000 RAD 1.0 N +SPHERE CENTER 8.377000 19.427999 0.280000 RAD 1.0 CA +SPHERE CENTER 8.573000 18.100000 0.950000 RAD 1.0 C +SPHERE CENTER 8.785000 17.013000 0.347000 RAD 1.0 O +SPHERE CENTER 6.844000 19.700001 0.273000 RAD 1.0 CB +SPHERE CENTER 6.304000 18.825001 -0.706000 RAD 1.0 OG1 +SPHERE CENTER 6.585000 21.149000 -0.177000 RAD 1.0 CG2 +SPHERE CENTER 8.526000 18.187000 2.280000 RAD 1.0 N +SPHERE CENTER 8.582000 16.999001 3.087000 RAD 1.0 CA +SPHERE CENTER 7.801000 17.273001 4.382000 RAD 1.0 C +SPHERE CENTER 7.554000 18.469000 4.665000 RAD 1.0 O +SPHERE CENTER 10.066000 16.503000 3.399000 RAD 1.0 CB +SPHERE CENTER 10.840000 17.323999 4.462000 RAD 1.0 CG +SPHERE CENTER 11.188000 16.711000 5.670000 RAD 1.0 CD1 +SPHERE CENTER 11.224000 18.618999 4.188000 RAD 1.0 CD2 +SPHERE CENTER 11.912000 17.452999 6.617000 RAD 1.0 CE1 +SPHERE CENTER 11.948000 19.333000 5.129000 RAD 1.0 CE2 +SPHERE CENTER 12.277000 18.763000 6.344000 RAD 1.0 CZ +SPHERE CENTER 7.455000 16.219999 5.116000 RAD 1.0 N +SPHERE CENTER 6.756000 16.414000 6.390000 RAD 1.0 CA +SPHERE CENTER 7.798000 16.358999 7.491000 RAD 1.0 C +SPHERE CENTER 8.422000 15.296000 7.692000 RAD 1.0 O +SPHERE CENTER 5.716000 15.281000 6.557000 RAD 1.0 CB +SPHERE CENTER 4.973000 15.432000 7.882000 RAD 1.0 CG1 +SPHERE CENTER 4.667000 15.326000 5.371000 RAD 1.0 CG2 +SPHERE CENTER 7.953000 17.509001 8.095000 RAD 1.0 N +SPHERE CENTER 8.816000 17.659000 9.286000 RAD 1.0 CA +SPHERE CENTER 7.941000 17.294001 10.498000 RAD 1.0 C +SPHERE CENTER 6.818000 17.832001 10.661000 RAD 1.0 O +SPHERE CENTER 9.260000 19.136000 9.274000 RAD 1.0 CB +SPHERE CENTER 10.066000 19.506001 10.540000 RAD 1.0 CG +SPHERE CENTER 11.058000 18.667999 11.032000 RAD 1.0 CD1 +SPHERE CENTER 9.728000 20.677999 11.181000 RAD 1.0 CD2 +SPHERE CENTER 11.713000 19.021999 12.217000 RAD 1.0 CE1 +SPHERE CENTER 10.401000 21.042000 12.346000 RAD 1.0 CE2 +SPHERE CENTER 11.371000 20.211000 12.851000 RAD 1.0 CZ +SPHERE CENTER 12.040000 20.579000 14.049000 RAD 1.0 OH +SPHERE CENTER 8.505000 16.504999 11.400000 RAD 1.0 N +SPHERE CENTER 7.774000 16.076000 12.622000 RAD 1.0 CA +SPHERE CENTER 7.696000 17.099001 13.728000 RAD 1.0 C +SPHERE CENTER 6.978000 16.834999 14.718000 RAD 1.0 O +SPHERE CENTER 8.385000 18.202000 13.646000 RAD 1.0 N +SPHERE CENTER 8.275000 19.365999 14.533000 RAD 1.0 CA +SPHERE CENTER 9.338000 19.430000 15.620000 RAD 1.0 C +SPHERE CENTER 9.309000 20.379999 16.415001 RAD 1.0 O +SPHERE CENTER 10.317000 18.555000 15.610000 RAD 1.0 N +SPHERE CENTER 11.453000 18.707001 16.541000 RAD 1.0 CA +SPHERE CENTER 12.763000 18.232000 15.950000 RAD 1.0 C +SPHERE CENTER 12.753000 17.224001 15.201000 RAD 1.0 O +SPHERE CENTER 11.179000 18.055000 17.937000 RAD 1.0 CB +SPHERE CENTER 11.154000 16.283001 17.922001 RAD 1.0 SG +SPHERE CENTER 13.828000 18.788000 16.528999 RAD 1.0 N +SPHERE CENTER 15.222000 18.386999 16.261999 RAD 1.0 CA +SPHERE CENTER 15.644000 18.605000 14.798000 RAD 1.0 C +SPHERE CENTER 16.306000 17.708000 14.224000 RAD 1.0 O +SPHERE CENTER 15.486000 16.941000 16.719000 RAD 1.0 CB +SPHERE CENTER 14.949000 16.624001 18.146999 RAD 1.0 CG +SPHERE CENTER 15.484000 17.593000 19.195000 RAD 1.0 CD +SPHERE CENTER 15.081000 17.068001 20.497000 RAD 1.0 NE +SPHERE CENTER 15.268000 17.830999 21.573999 RAD 1.0 CZ +SPHERE CENTER 15.870000 19.020000 21.452999 RAD 1.0 NH1 +SPHERE CENTER 14.930000 17.320999 22.753000 RAD 1.0 NH2 +SPHERE CENTER 15.154000 19.670000 14.180000 RAD 1.0 N +SPHERE CENTER 15.461000 19.893999 12.733000 RAD 1.0 CA +SPHERE CENTER 16.969000 19.924000 12.482000 RAD 1.0 C +SPHERE CENTER 17.752001 20.431000 13.327000 RAD 1.0 O +SPHERE CENTER 14.918000 21.275000 12.366000 RAD 1.0 CB +SPHERE CENTER 17.282000 19.622000 11.271000 RAD 1.0 N +SPHERE CENTER 18.584999 19.886999 10.687000 RAD 1.0 CA +SPHERE CENTER 18.461000 21.087000 9.753000 RAD 1.0 C +SPHERE CENTER 17.371000 21.708000 9.790000 RAD 1.0 O +SPHERE CENTER 18.961000 18.612000 9.934000 RAD 1.0 CB +SPHERE CENTER 19.486000 17.514999 10.843000 RAD 1.0 CG +SPHERE CENTER 20.042999 16.424999 9.926000 RAD 1.0 CD +SPHERE CENTER 20.782000 15.386000 10.779000 RAD 1.0 CE +SPHERE CENTER 20.985001 14.137000 10.021000 RAD 1.0 NZ +SPHERE CENTER 19.577000 21.643999 9.215000 RAD 1.0 N +SPHERE CENTER 19.570999 22.903000 8.543000 RAD 1.0 CA +SPHERE CENTER 18.898001 22.847000 7.144000 RAD 1.0 C +SPHERE CENTER 18.476000 23.930000 6.690000 RAD 1.0 O +SPHERE CENTER 20.981001 23.469999 8.429000 RAD 1.0 CB +SPHERE CENTER 21.461000 24.047001 9.786000 RAD 1.0 CG +SPHERE CENTER 22.614000 25.047001 9.608000 RAD 1.0 CD +SPHERE CENTER 22.118999 26.403999 9.384000 RAD 1.0 NE +SPHERE CENTER 22.948000 27.426001 9.370000 RAD 1.0 CZ +SPHERE CENTER 24.253000 27.187000 9.415000 RAD 1.0 NH1 +SPHERE CENTER 22.472000 28.634001 9.297000 RAD 1.0 NH2 +SPHERE CENTER 18.870001 21.715000 6.474000 RAD 1.0 N +SPHERE CENTER 18.209999 21.712999 5.169000 RAD 1.0 CA +SPHERE CENTER 16.671000 21.559000 5.372000 RAD 1.0 C +SPHERE CENTER 16.068001 20.466000 5.197000 RAD 1.0 O +SPHERE CENTER 18.745001 20.506001 4.379000 RAD 1.0 CB +SPHERE CENTER 18.295000 20.591999 2.909000 RAD 1.0 CG +SPHERE CENTER 17.721001 21.629000 2.499000 RAD 1.0 OD1 +SPHERE CENTER 18.664000 19.563999 2.134000 RAD 1.0 ND2 +SPHERE CENTER 16.097000 22.643000 5.820000 RAD 1.0 N +SPHERE CENTER 14.676000 22.662001 6.349000 RAD 1.0 CA +SPHERE CENTER 14.157000 24.101999 6.384000 RAD 1.0 C +SPHERE CENTER 14.715000 24.959000 7.120000 RAD 1.0 O +SPHERE CENTER 14.577000 21.951000 7.736000 RAD 1.0 CB +SPHERE CENTER 13.128000 21.861000 8.301000 RAD 1.0 CG +SPHERE CENTER 12.432000 22.889000 8.208000 RAD 1.0 OD1 +SPHERE CENTER 12.975000 21.035000 9.288000 RAD 1.0 ND2 +SPHERE CENTER 13.324000 24.438000 5.381000 RAD 1.0 N +SPHERE CENTER 12.918000 25.816999 5.120000 RAD 1.0 CA +SPHERE CENTER 11.388000 25.961000 5.164000 RAD 1.0 C +SPHERE CENTER 10.669000 24.966000 4.915000 RAD 1.0 O +SPHERE CENTER 13.372000 26.372999 3.741000 RAD 1.0 CB +SPHERE CENTER 14.913000 26.191999 3.701000 RAD 1.0 CG +SPHERE CENTER 15.492000 25.002001 3.268000 RAD 1.0 CD1 +SPHERE CENTER 15.705000 27.252001 4.053000 RAD 1.0 CD2 +SPHERE CENTER 16.877001 24.881001 3.132000 RAD 1.0 CE1 +SPHERE CENTER 17.108999 27.125999 3.941000 RAD 1.0 CE2 +SPHERE CENTER 17.659000 25.957001 3.487000 RAD 1.0 CZ +SPHERE CENTER 10.949000 27.146999 5.460000 RAD 1.0 N +SPHERE CENTER 9.480000 27.343000 5.498000 RAD 1.0 CA +SPHERE CENTER 8.875000 27.670000 4.157000 RAD 1.0 C +SPHERE CENTER 7.634000 27.622999 4.057000 RAD 1.0 O +SPHERE CENTER 9.045000 28.475000 6.433000 RAD 1.0 CB +SPHERE CENTER 9.258000 27.945999 7.875000 RAD 1.0 CG +SPHERE CENTER 9.119000 29.052000 8.948000 RAD 1.0 CD +SPHERE CENTER 10.025000 28.736000 10.167000 RAD 1.0 CE +SPHERE CENTER 9.826000 29.728001 11.231000 RAD 1.0 NZ +SPHERE CENTER 9.687000 27.909000 3.152000 RAD 1.0 N +SPHERE CENTER 9.124000 28.167999 1.840000 RAD 1.0 CA +SPHERE CENTER 10.108000 27.719000 0.765000 RAD 1.0 C +SPHERE CENTER 11.332000 27.660000 1.047000 RAD 1.0 O +SPHERE CENTER 8.778000 29.648001 1.642000 RAD 1.0 CB +SPHERE CENTER 10.000000 30.391001 1.484000 RAD 1.0 OG +SPHERE CENTER 9.604000 27.471001 -0.422000 RAD 1.0 N +SPHERE CENTER 10.526000 27.160999 -1.512000 RAD 1.0 CA +SPHERE CENTER 11.423000 28.346001 -1.863000 RAD 1.0 C +SPHERE CENTER 12.634000 28.115000 -2.136000 RAD 1.0 O +SPHERE CENTER 9.782000 26.679001 -2.783000 RAD 1.0 CB +SPHERE CENTER 10.966000 29.570000 -1.682000 RAD 1.0 N +SPHERE CENTER 11.751000 30.764000 -1.998000 RAD 1.0 CA +SPHERE CENTER 12.900000 30.964001 -1.040000 RAD 1.0 C +SPHERE CENTER 14.032000 31.282000 -1.463000 RAD 1.0 O +SPHERE CENTER 10.871000 32.021999 -2.024000 RAD 1.0 CB +SPHERE CENTER 9.868000 32.069000 -3.200000 RAD 1.0 CG +SPHERE CENTER 8.525000 31.417000 -2.847000 RAD 1.0 CD +SPHERE CENTER 7.573000 31.562000 -3.638000 RAD 1.0 OE1 +SPHERE CENTER 8.368000 30.636999 -1.865000 RAD 1.0 OE2 +SPHERE CENTER 12.658000 30.686001 0.225000 RAD 1.0 N +SPHERE CENTER 13.804000 30.775000 1.163000 RAD 1.0 CA +SPHERE CENTER 14.824000 29.667000 0.941000 RAD 1.0 C +SPHERE CENTER 16.058001 29.903999 1.049000 RAD 1.0 O +SPHERE CENTER 13.347000 30.500000 2.601000 RAD 1.0 CB +SPHERE CENTER 12.813000 31.775999 3.236000 RAD 1.0 CG +SPHERE CENTER 12.716000 32.875000 2.613000 RAD 1.0 OD1 +SPHERE CENTER 12.096000 31.598000 4.247000 RAD 1.0 OD2 +SPHERE CENTER 14.305000 28.478001 0.644000 RAD 1.0 N +SPHERE CENTER 15.128000 27.301001 0.379000 RAD 1.0 CA +SPHERE CENTER 16.006001 27.523001 -0.852000 RAD 1.0 C +SPHERE CENTER 17.247999 27.267000 -0.809000 RAD 1.0 O +SPHERE CENTER 14.238000 26.045000 0.259000 RAD 1.0 CB +SPHERE CENTER 15.047000 24.530001 -0.176000 RAD 1.0 SG +SPHERE CENTER 15.384000 28.062000 -1.870000 RAD 1.0 N +SPHERE CENTER 16.191999 28.302000 -3.048000 RAD 1.0 CA +SPHERE CENTER 17.171000 29.452999 -2.841000 RAD 1.0 C +SPHERE CENTER 18.246000 29.474001 -3.490000 RAD 1.0 O +SPHERE CENTER 15.267000 28.570999 -4.266000 RAD 1.0 CB +SPHERE CENTER 14.634000 27.261000 -4.708000 RAD 1.0 CG +SPHERE CENTER 15.759000 25.962000 -5.253000 RAD 1.0 SD +SPHERE CENTER 16.306999 26.625000 -6.805000 RAD 1.0 CE +SPHERE CENTER 16.775999 30.469999 -2.099000 RAD 1.0 N +SPHERE CENTER 17.652000 31.617001 -1.869000 RAD 1.0 CA +SPHERE CENTER 18.910000 31.125999 -1.141000 RAD 1.0 C +SPHERE CENTER 20.049999 31.469999 -1.556000 RAD 1.0 O +SPHERE CENTER 16.934000 32.595001 -0.930000 RAD 1.0 CB +SPHERE CENTER 17.721001 33.839001 -0.540000 RAD 1.0 CG +SPHERE CENTER 16.740999 35.039001 -0.291000 RAD 1.0 CD +SPHERE CENTER 15.472000 34.667999 0.404000 RAD 1.0 NE +SPHERE CENTER 14.256000 34.889999 -0.074000 RAD 1.0 CZ +SPHERE CENTER 13.983000 35.465000 -1.233000 RAD 1.0 NH1 +SPHERE CENTER 13.260000 34.542999 0.660000 RAD 1.0 NH2 +SPHERE CENTER 18.726999 30.198999 -0.237000 RAD 1.0 N +SPHERE CENTER 19.889999 29.693001 0.496000 RAD 1.0 CA +SPHERE CENTER 20.636999 28.649000 -0.297000 RAD 1.0 C +SPHERE CENTER 21.871000 28.686001 -0.287000 RAD 1.0 O +SPHERE CENTER 19.416000 29.106001 1.823000 RAD 1.0 CB +SPHERE CENTER 18.643999 30.132000 2.537000 RAD 1.0 OG1 +SPHERE CENTER 20.615999 28.506001 2.662000 RAD 1.0 CG2 +SPHERE CENTER 19.988001 27.747000 -0.961000 RAD 1.0 N +SPHERE CENTER 20.669001 26.563999 -1.471000 RAD 1.0 CA +SPHERE CENTER 20.773001 26.534000 -2.963000 RAD 1.0 C +SPHERE CENTER 21.341000 25.552999 -3.498000 RAD 1.0 O +SPHERE CENTER 19.955999 25.260000 -1.056000 RAD 1.0 CB +SPHERE CENTER 20.128000 24.914000 0.713000 RAD 1.0 SG +SPHERE CENTER 20.132000 27.441999 -3.608000 RAD 1.0 N +SPHERE CENTER 19.987000 27.268000 -5.071000 RAD 1.0 CA +SPHERE CENTER 21.257000 27.575001 -5.849000 RAD 1.0 C +SPHERE CENTER 21.386000 27.129000 -7.018000 RAD 1.0 O +SPHERE CENTER 22.225000 28.049999 -5.113000 RAD 1.0 N +SPHERE CENTER 23.639000 28.131001 -5.505000 RAD 1.0 CA +SPHERE CENTER 23.886999 29.393000 -6.316000 RAD 1.0 C +SPHERE CENTER 22.948999 30.065001 -6.822000 RAD 1.0 O +SPHERE CENTER 25.146000 29.681000 -6.493000 RAD 1.0 N +SPHERE CENTER 25.617001 30.840000 -7.256000 RAD 1.0 CA +SPHERE CENTER 25.247999 30.735001 -8.729000 RAD 1.0 C +SPHERE CENTER 24.962000 31.791000 -9.369000 RAD 1.0 O +SPHERE CENTER 27.160000 30.980000 -7.146000 RAD 1.0 CB +SPHERE CENTER 24.919001 29.594000 -9.172000 RAD 1.0 OXT + +PLANE + CENTER 0.0 -25.0 0.0 + NORMAL 0.0 1.0 0.0 + TEXTURE + AMBIENT 0.1 DIFFUSE 0.9 SPECULAR 0.0 OPACITY 1.0 + COLOR 1.0 1.0 1.0 + TEXFUNC 0 + +END_SCENE diff --git a/src/tbb/examples/parallel_for/tachyon/index.html b/src/tbb/examples/parallel_for/tachyon/index.html new file mode 100644 index 0000000..8d07c41 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/index.html @@ -0,0 +1,219 @@ + + + +

    Overview

    +Parallel raytracer / renderer that demonstrates the use of parallel_for. + +

    +This example includes software developed by John E. Stone. See +here for copyright information. +

    + +

    +This example is a 2-D raytracer/renderer that visually shows different parallel scheduling +methods and their resulting speedup. The code was parallelized by speculating +that each pixel could be rendered in parallel. The resulting parallel code was +then checked for correctness by using Intel® Thread Checker, which +pointed out where synchronization was needed. Minimal synchronization was then +inserted into the parallel code. The resulting parallel code exhibits good speedup. +

    + +

    +The following versions of the example are provided: +

    +
    serial +
    Original sequential version. +
    tbb1d +
    Parallel version that uses Intel® Threading Building Blocks (Intel TBB) and blocked_range to parallelize + over tasks that are groups of scan-lines. +
      +
    • By default, this version uses one thread per available processor. To change this + default, set the TBB_NUM_THREADS environment variable to the desired number of threads before running. +
    • This version uses the preview feature: auto_range_partitioner. No grain size is provided to blocked_range. + The blocked_range class uses a default grain size of 1 when none is provided. However, the auto_range_partitioner + controls the amount of range splitting dynamically at runtime, resulting in sub-ranges of varying sizes. +
    +
    tbb +
    Parallel version that uses Intel TBB and blocked_range2d to parallelize + over tasks that are rectangular sub-areas. +
      +
    • By default, this version uses one thread per available processor. To change this + default, set the TBB_NUM_THREADS environment variable to the desired number of threads before running. +
    • This version uses a reasonable task grain size by default. To change this default, + set the TBB_GRAINSIZE environment variable to the desired grain size before running. + The grain size corresponds to the number of pixels (in the X or Y direction, for a + rectangular sub-area) in each parallel task. +
    +
    +

    + +

    Files

    +
    +
    src/main.cpp +
    Main program which parses command line options and runs the raytracer. +
    src/tachyon_video.cpp +
    Source code for GUI interfaces. +
    src/trace.serial.cpp +
    Source code for original sequential version of example. +
    src/trace.tbb1d.cpp +
    Source code for Intel TBB blocked_range (scan-line) version of example. +
    src/trace.tbb.cpp +
    Source code for Intel TBB blocked_range2d (rectangular sub-area) version of example. +
    (src/*.cpp) +
    Remainder of source code for example. +
    (src/*.h) +
    Remainder of include files for example. +
    Makefile +
    Makefile for building example. +
    + +

    Directories

    +
    +
    src +
    Contains source code and include files for the example. +
    dat +
    Contains data sets for running the example. +
    msvs +
    Contains Microsoft* Visual Studio* 2005 workspace for building and running the + example (Windows* systems only).
    xcode +
    Contains Xcode* IDE workspace for building and running the example (Mac OS* X + systems only).
    + +

    To Build

    +General build directions can be found here. + +

    +For Windows* systems Microsoft* Visual Studio* projects are provided for each of the above + example versions. +

    + +

    +The Makefile supports the following build targets (in addition to the general ones). +Here, <version> is one of the above versions of the example, i.e., {serial, tbb1d, tbb}. +

    +
    +
    make <version>[_debug] +
    Build and run a single version (release or debug). + Equivalent to 'make build_<version>[_debug] run_<version>'. +
    make build_<version>[_debug] +
    Compile and link a single version (release or debug). + The resulting executable is left in the directory for the example. +
    make run_<version> +
    Run a single version previously produced by one of the above commands. +
    make [(above options or targets)] DATASET={820spheres, balls, balls3, lattice, model2, + teapot, trypsin4pti} +
    Build and run as above, but run with the specified data set. +
    make [(above options or targets)] ARGS=-D +
    Build and run as above, but run with disabled run-time display updating for use in making performance measurements + (strongly recommended when measuring performance or scalability; see note below). +
    make [(above options or targets)] UI={con, gdi, dd, d2d, x, mac} +
    Build and run as usual, but build with the specified GUI driver: console, GDI+*, DirectDraw*, + Direct2D*, X11, or OpenGL* + (see the description of the common GUI code + for more information on available graphics support). + For Linux* and Mac OS* X systems, the best available driver is detected automatically by the Makefile. + For Windows* systems, UI=gdi is the default GUI driver; compiling with UI=dd or + UI=d2d may offer superior + performance, but can only be used if the Microsoft* DirectX* SDK is installed on your system. + Use UI=con to build without the GUI for use in making performance measurements + (strongly recommended when measuring performance or scalability; see note below). +
    make [(above options or targets)] XARCH=x64 +
    Build and run as above, but + also specify XARCH=x64 (or XARCH=AMD64 for older compilers) when building the example on Windows* as a 64-bit binary. +
    make [(above options or targets)] DDLIB_DIR=<specify path to library directory of Direct Draw* SDK here> +
    If you experience ddraw.lib linking problems, specify the correct library directory via this option. +
    + +

    Usage

    +Building via the above make commands, or via Visual Studio projects on Windows* systems, produces executable files +named tachyon.<version>.exe. To run these executables directly, use one or more of the following commands. +
    +
    tachyon.<version> -h +
    Prints the help for command line options +
    tachyon.<version> [dataset=value] [boundthresh=value] [no-display-updating] [nobounding] [silent] +
    tachyon.<version> [dataset [boundthresh]] [no-display-updating] [nobounding] [silent] +
    dataset is the path/name of one of the *.dat files in the dat directory for the example.
    + boundthresh is a bounding threshold value.
    + no-display-updating - disable run-time display updating.
    + no-bounding - disable bounding technique.
    + silent - no output except elapsed time.
    +
    tachyon.<version> [dataset] [no-display-updating] +
    Run this version (release or debug), but run with disabled run-time display updating + for use in making performance measurements + (strongly recommended when measuring performance or scalability; see note below). +
    To run a short version of this example, e.g., for use with Intel® Parallel Inspector: +
    Build a debug version of the tbb example with the GUI turned off + (e.g., make UI=con tbb_debug; see also the build directions above). +
    Run it with a small dataset, e.g., tachyon.tbb.exe dat/820spheres.dat no-display-updating. +
    + +

    Keys

    +While running with the GUI display turned on the following keyboard keys can be used: +
    +
    ESC +
    Interrupt the rendering and exit +
    Any key +
    Enable repetition of rendering after the pause. Press ESC to stop the application. +
    Space +
    Toggle run-time display updating mode while rendering (see no-display-updating above). +
    p +
    Holds the picture after rendering completion. Press 'p' again to continue. +
    + +

    Notes

    +
      +
    • While running with the GUI display turned on should yield reasonable performance in most cases, running with the GUI + display turned off is strongly recommended in order to demonstrate the full performance and scalability of the example. +
    + + + +
    +
    Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + +

    +The original source for this example is +Copyright (c) 1994-2008 John E. Stone +All rights reserved. +

    + +

    +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +

      +
    1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +
    2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +
    3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. +
    +

    + +

    +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. +

    +
    + + + diff --git a/src/tbb/examples/parallel_for/tachyon/msvs/gui.ico b/src/tbb/examples/parallel_for/tachyon/msvs/gui.ico new file mode 100644 index 0000000000000000000000000000000000000000..d551aa3aaf80adf9b7760e2eb8de95a5c3e53df6 GIT binary patch literal 23558 zcmeI430zgx+QuJHKtxbe5gbu*030B5$VyGcDGSFOalkY&2LuvC5pp(7&2XNl96=@z zNXGH2`|DO#nx)3nwUq43A>_N=+wHsYe$U#6ePmShD&p^B>2uySylbs@uYIPy&-w#c zpc-6UYC)x+ErDgUwQ8BlZ7hIURRB*7exZ#T}AXG2* z=^weGTI5~Inq#r?3QZRh5>Vvy7AqDy*^i;1p6BY7;LQSXZ{;g>M z?fm5AM!1uJ~14CP5-;mbWJGeF0 z_iurN!(6GBI54yo4h(CB{j~e(6Em$hj*V=Fqpvo{5$e#07L+U2`wvFkn8s8S#Efo= z^|!}o{tozLT1|Z7UlaSMxZ(5FgK^Rilm(Khv|vko7i5X}36?lI))Ggklas69 zVxSe$=33+10BfA^v%)uXY;b;dHGCaV4e6oPadwt1PEE7L#SjO4G`kKy33kG#^P1yK zcx(J^Ra<Ti+?95-JJvGIWK0JnTs;vs^DcXy)=jK$w z=lme~e0CM~SM61i7E+Zy6!Vv8(?YCpX|5H%3$bS21{dbq;8I96Tne>C8jm-9o*mM| z?2r~#1K&~U^BwT@ygK+I#1UDG8sIO%&iE*}A+E1$jbGNa!S(fRas9ovxba>)TBY{5 zxxo`Rq9|oIDtY0?rjE#1t!!u9+}s5>w|2#i&D55z%y+}h?JrQ>af9~O4zA^n9=Nr$ z7jEt9gPXg&@$23JxV49(y|Q~4emOiI-)H_6dH=qKoBYhlq5e+&PW_AegZf|U-_)N} z9@RJC3MS7vp?yXL1qC4>AOQaU{+Kjr5++WZhzS!Wz}MFoW5Wxo&I+1!G$zZHn#$;`!98-<yjHIyy#~ zd!^|5sm6LSF)_!K%8;V#rWzZU(N_%@(#Q5Ewg{KRHI95 zY?=LIo2D9@#Ky*zb^O>SmHu~IE44l?Dgh-;K81z)WLJ`;4wqn z_ZrZ%LmzL?wy3kD_lL%jZ@l`n*YIJJ=8o?=KVm^dc=tK8XTNSrUK1xwofb5!|4WPJ z4;&O=5uecStt8`&$o&U)@7lX>*XEsj-g|fBj_upFZrx%^n^vq{{r0M5OP8-%`Odni z4ek1_pUw~WS3(xf3w~KkBmDdVRSL~dfr0)bOf7sI@n%@?lm1=c0pd4Z&T02Hm@RH2 z)we;5{I7(S*0d0%twR;wLsA|##n-X4buN70s`TsBg@MbpxknH6!QPjfV-K~P+VA6v z_lLE?{$Xwi?eB?&gE}IlpC>|?5A<%2&;edpIl33d4IhkA?7Qcs#@NdnYWsbf({dao zjuAS*69M!eGt37G)4CyX#*2ub-V>ij1>vuo!mzs+z)KgL@b7{zHqOE48v-$!zJ3#Y zv6uJbc6$T6dQ*KU=65px!K_Y5n$a2Cr*_9zn`Ys&O+gqt+y{pT0q+l>1_JwOKM87w zj|1D|zXCjwI@=4Ewok|DRTFSw+Z#B)bq3CDnTav%mol33yacQq;D9qB?)YqOTV(8< zhO{02IO`82u>Hs|UYpK$#ksIn_%f8&v3sW=YtK}ip9y^Z1~r3H`B~I#;2iDQ=@jeE zsP;Kl_%^%|E=9QF`(^IPTIr6TH*`S`ui5^ww+}9?dJfr}dg8{OA;>xEhiiu?LYUzwb+T)8Ci=PAZtkjWKvm68X{|HBivlm3|Y&X;^sP6+GhB5eJk92w>5I2 z+$j(Ix}hC1827D>9dK(?2jp()h@8zG@!QT$$l2N%x3+e|?QJ|JOre?J8PhnJ%Ni~CLrzWB&44|iS%zyB8@if zn`DaR3m@|O^QyPhwX#dzrgIKY+OQIBHLeiIw|EP z&VT0+jvL~&)rdRJe}-vnAIJ6*Q-ZDH1N-*w-gRv2&ZLw99b3D3xO=#{xw*T!wQ+Oz@bGBcd0?|n&$#sN_2S8-lrFX#RqEa{~iIg60Iwp0)kazxeJo zgX#N&>G3k(9Zpk`k46?8yGp_NR9<~gx%0b2>EBc6h6N*s;*a0{2Wy6O#7ZA8q(u55 zXmAg#9`ZC+QBk9x#nSQpa4CKpR!sCp#>stnXRBl-)qQFW^fsryy=(Z?FI2AS<5;lV$HB*W zpm$$$hhFu3THa~z+qYL;AE$u>2QZl)2G;Ru)3f^vUAny3rOUHDp6~jct50i}CXE|6 zZPK7&qvp+?vT*b1+^M5y`wmZgdAPT0`%H^xiXL6DvWOu*60xx;u6V#Q2{0r8adCy( zEn;IuV&g28p4jI>W#CW53OF&!CsAr~RottogHM>&s@S>DKq|7h|3SD9 zqF9XiYwfgmNUJRFhY%(1o6xLY)@?;QKJMM%9Zv1};>0~2!r#}0zp0zW`xNH9UeDj( zg}=XRQtjm}{_d~Eq+;bB6m$ICmr^L!lH$^jp`^CQQOEr>=J>f^rrg)^KRssd^D)QI zeLuo|80KTp^Sb>{=X%)v)pLRSmCW&T|B@EJinpT1Tyzb%m&zPJ_g4w`z?hFg`Rd1_ z>Wj7&9jm;{DmLy1Gsn+8Vp@!PtSTNouWWh8cdz+W{M_4Sj-PwjDs;R>k4LR3_uiS~ z=YBll{weJklr8FC(aI`*?jJPA&pn00ytW2@1pNNmFr)z)}MRaMZIsT^P*Jr zd{v~ficiI=V%Fb3xlf-prc}}2|5bcSDrP-?@&@_Qn~c8Rs-)*Df-M*%`H0H+%lZ72 zvi{EGQOr#h;dxS84CWx2AwMJBn{b$~fyU%&3N}@!=X}9qDHtRuG5tUm68j-~fkG1sqOUyGmYlwPgb z2OYaS`ssnHnDzL{f$7y1HvU2ZvOsRl96y=1qRkb)O#V)fzZuy)A>;K#iJYK%{YIx)`7mahDM1B1t%cm9kaZNYkD4X_DC9qd+$8->B5TQhB} zPLpFP(T5^y$$V8IA1dTRh5V#84>?gGBg(O=3b|S#mnh^Cg)FI%vsB;THmdl^aSGW> zA@3;U9fcgEkcSj)tKX)y|CMyJ9 zWMGAisgNZVGNwZIRLI7bES?uKuA0cIN->306SAtME58p}SdPK5N}H!(y?QQ$SPR)# zEw=cH;9p8myVEOE~ZJrY}3iIg?0rP&%LTBp=}8h@I%TXv<9-xUO`%}-uWt5a*E=2Z6^)Nip$4?6}mrb=W3r9pMm{N(?%I<=0f{ZX!iK0oKQ1d^EdG#^%`N>O4Lp#&)lc_BC`N?cbBh&ou z$Ha>#mE4>Z3XbJ2L!+Nt++W%XmzCnEDKwe#1XEVN#&9kX7z*Ba>aDt~p(O7d58 ztNMbLMIj4qo}V1Gs?t)?V|bWl{j*<9L>}8bKN)V*HyMT)&Xn7jpKpqbGz6zmVk@{(S%;moMb= zg`B=PIy$QPUCF}>xq2agFXZoq+`W*w*DN`FAuBIr%G&-D!IW`F9}` zFJ#_@jJ%MQmz-@~sV+i3UdYL7B1xFE+kg*rC_sn}}eaYVo*?J*YFZ>$;!oOJ{ z{QCgB-)1FF4i?imzkPZz{4Rvr{h7I>sgUu{%LsSK%b0JUml0-1RnN;GSP!(-+jpO%JopO`B((dnpK-(&yRaUJ6F; zchnE_k$Wv1f4{oG;*T$8Vx5|ss!Wf01@yO_$nuNBLZ4Gvb)Vu6x9f7RD3t3{RPFna z@~=**zWfUs8kYPPZCSL4e)B1xT|TXnSM+U>y|{O?8%m4vtzIr_BVKg5vCP}`*3dR} z&a!{N#n>%>kU18z!$Q_q$meQ#RW3=oZ=knFmg=8&V&`qOUg~p1N&lWwnpHmPb9YW3 zw+z)kIP(xwOMAJX5{|A*v__uZdtvV;w2rOkgeCCc1i z#a5Q%Amc3IgIa3+fBIm(x&OWTs_~Un|HxNN{coH$#m{POUDev^Dy>e{FMhe1Y5iiu zZ_N=+wHsYe$U#6ePmShD&p^B>2uySylbs@uYIPy&-w#c zpc-6UYC)x+ErDgUwQ8BlZ7hIURRB*7exZ#T}AXG2* z=^weGTI5~Inq#r?3QZRh5>Vvy7AqDy*^i;1p6BY7;LQSXZ{;g>M z?fm5AM!1uJ~14CP5-;mbWJGeF0 z_iurN!(6GBI54yo4h(CB{j~e(6Em$hj*V=Fqpvo{5$e#07L+U2`wvFkn8s8S#Efo= z^|!}o{tozLT1|Z7UlaSMxZ(5FgK^Rilm(Khv|vko7i5X}36?lI))Ggklas69 zVxSe$=33+10BfA^v%)uXY;b;dHGCaV4e6oPadwt1PEE7L#SjO4G`kKy33kG#^P1yK zcx(J^Ra<Ti+?95-JJvGIWK0JnTs;vs^DcXy)=jK$w z=lme~e0CM~SM61i7E+Zy6!Vv8(?YCpX|5H%3$bS21{dbq;8I96Tne>C8jm-9o*mM| z?2r~#1K&~U^BwT@ygK+I#1UDG8sIO%&iE*}A+E1$jbGNa!S(fRas9ovxba>)TBY{5 zxxo`Rq9|oIDtY0?rjE#1t!!u9+}s5>w|2#i&D55z%y+}h?JrQ>af9~O4zA^n9=Nr$ z7jEt9gPXg&@$23JxV49(y|Q~4emOiI-)H_6dH=qKoBYhlq5e+&PW_AegZf|U-_)N} z9@RJC3MS7vp?yXL1qC4>AOQaU{+Kjr5++WZhzS!Wz}MFoW5Wxo&I+1!G$zZHn#$;`!98-<yjHIyy#~ zd!^|5sm6LSF)_!K%8;V#rWzZU(N_%@(#Q5Ewg{KRHI95 zY?=LIo2D9@#Ky*zb^O>SmHu~IE44l?Dgh-;K81z)WLJ`;4wqn z_ZrZ%LmzL?wy3kD_lL%jZ@l`n*YIJJ=8o?=KVm^dc=tK8XTNSrUK1xwofb5!|4WPJ z4;&O=5uecStt8`&$o&U)@7lX>*XEsj-g|fBj_upFZrx%^n^vq{{r0M5OP8-%`Odni z4ek1_pUw~WS3(xf3w~KkBmDdVRSL~dfr0)bOf7sI@n%@?lm1=c0pd4Z&T02Hm@RH2 z)we;5{I7(S*0d0%twR;wLsA|##n-X4buN70s`TsBg@MbpxknH6!QPjfV-K~P+VA6v z_lLE?{$Xwi?eB?&gE}IlpC>|?5A<%2&;edpIl33d4IhkA?7Qcs#@NdnYWsbf({dao zjuAS*69M!eGt37G)4CyX#*2ub-V>ij1>vuo!mzs+z)KgL@b7{zHqOE48v-$!zJ3#Y zv6uJbc6$T6dQ*KU=65px!K_Y5n$a2Cr*_9zn`Ys&O+gqt+y{pT0q+l>1_JwOKM87w zj|1D|zXCjwI@=4Ewok|DRTFSw+Z#B)bq3CDnTav%mol33yacQq;D9qB?)YqOTV(8< zhO{02IO`82u>Hs|UYpK$#ksIn_%f8&v3sW=YtK}ip9y^Z1~r3H`B~I#;2iDQ=@jeE zsP;Kl_%^%|E=9QF`(^IPTIr6TH*`S`ui5^ww+}9?dJfr}dg8{OA;>xEhiiu?LYUzwb+T)8Ci=PAZtkjWKvm68X{|HBivlm3|Y&X;^sP6+GhB5eJk92w>5I2 z+$j(Ix}hC1827D>9dK(?2jp()h@8zG@!QT$$l2N%x3+e|?QJ|JOre?J8PhnJ%Ni~CLrzWB&44|iS%zyB8@if zn`DaR3m@|O^QyPhwX#dzrgIKY+OQIBHLeiIw|EP z&VT0+jvL~&)rdRJe}-vnAIJ6*Q-ZDH1N-*w-gRv2&ZLw99b3D3xO=#{xw*T!wQ+Oz@bGBcd0?|n&$#sN_2S8-lrFX#RqEa{~iIg60Iwp0)kazxeJo zgX#N&>G3k(9Zpk`k46?8yGp_NR9<~gx%0b2>EBc6h6N*s;*a0{2Wy6O#7ZA8q(u55 zXmAg#9`ZC+QBk9x#nSQpa4CKpR!sCp#>stnXRBl-)qQFW^fsryy=(Z?FI2AS<5;lV$HB*W zpm$$$hhFu3THa~z+qYL;AE$u>2QZl)2G;Ru)3f^vUAny3rOUHDp6~jct50i}CXE|6 zZPK7&qvp+?vT*b1+^M5y`wmZgdAPT0`%H^xiXL6DvWOu*60xx;u6V#Q2{0r8adCy( zEn;IuV&g28p4jI>W#CW53OF&!CsAr~RottogHM>&s@S>DKq|7h|3SD9 zqF9XiYwfgmNUJRFhY%(1o6xLY)@?;QKJMM%9Zv1};>0~2!r#}0zp0zW`xNH9UeDj( zg}=XRQtjm}{_d~Eq+;bB6m$ICmr^L!lH$^jp`^CQQOEr>=J>f^rrg)^KRssd^D)QI zeLuo|80KTp^Sb>{=X%)v)pLRSmCW&T|B@EJinpT1Tyzb%m&zPJ_g4w`z?hFg`Rd1_ z>Wj7&9jm;{DmLy1Gsn+8Vp@!PtSTNouWWh8cdz+W{M_4Sj-PwjDs;R>k4LR3_uiS~ z=YBll{weJklr8FC(aI`*?jJPA&pn00ytW2@1pNNmFr)z)}MRaMZIsT^P*Jr zd{v~ficiI=V%Fb3xlf-prc}}2|5bcSDrP-?@&@_Qn~c8Rs-)*Df-M*%`H0H+%lZ72 zvi{EGQOr#h;dxS84CWx2AwMJBn{b$~fyU%&3N}@!=X}9qDHtRuG5tUm68j-~fkG1sqOUyGmYlwPgb z2OYaS`ssnHnDzL{f$7y1HvU2ZvOsRl96y=1qRkb)O#V)fzZuy)A>;K#iJYK%{YIx)`7mahDM1B1t%cm9kaZNYkD4X_DC9qd+$8->B5TQhB} zPLpFP(T5^y$$V8IA1dTRh5V#84>?gGBg(O=3b|S#mnh^Cg)FI%vsB;THmdl^aSGW> zA@3;U9fcgEkcSj)tKX)y|CMyJ9 zWMGAisgNZVGNwZIRLI7bES?uKuA0cIN->306SAtME58p}SdPK5N}H!(y?QQ$SPR)# zEw=cH;9p8myVEOE~ZJrY}3iIg?0rP&%LTBp=}8h@I%TXv<9-xUO`%}-uWt5a*E=2Z6^)Nip$4?6}mrb=W3r9pMm{N(?%I<=0f{ZX!iK0oKQ1d^EdG#^%`N>O4Lp#&)lc_BC`N?cbBh&ou z$Ha>#mE4>Z3XbJ2L!+Nt++W%XmzCnEDKwe#1XEVN#&9kX7z*Ba>aDt~p(O7d58 ztNMbLMIj4qo}V1Gs?t)?V|bWl{j*<9L>}8bKN)V*HyMT)&Xn7jpKpqbGz6zmVk@{(S%;moMb= zg`B=PIy$QPUCF}>xq2agFXZoq+`W*w*DN`FAuBIr%G&-D!IW`F9}` zFJ#_@jJ%MQmz-@~sV+i3UdYL7B1xFE+kg*rC_sn}}eaYVo*?J*YFZ>$;!oOJ{ z{QCgB-)1FF4i?imzkPZz{4Rvr{h7I>sgUu{%LsSK%b0JUml0-1RnN;GSP!(-+jpO%JopO`B((dnpK-(&yRaUJ6F; zchnE_k$Wv1f4{oG;*T$8Vx5|ss!Wf01@yO_$nuNBLZ4Gvb)Vu6x9f7RD3t3{RPFna z@~=**zWfUs8kYPPZCSL4e)B1xT|TXnSM+U>y|{O?8%m4vtzIr_BVKg5vCP}`*3dR} z&a!{N#n>%>kU18z!$Q_q$meQ#RW3=oZ=knFmg=8&V&`qOUg~p1N&lWwnpHmPb9YW3 zw+z)kIP(xwOMAJX5{|A*v__uZdtvV;w2rOkgeCCc1i z#a5Q%Amc3IgIa3+fBIm(x&OWTs_~Un|HxNN{coH$#m{POUDev^Dy>e{FMhe1Y5iiu zZ + + + + diff --git a/src/tbb/examples/parallel_for/tachyon/msvs/tachyon.serial.icproj b/src/tbb/examples/parallel_for/tachyon/msvs/tachyon.serial.icproj new file mode 100644 index 0000000..c449959 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/msvs/tachyon.serial.icproj @@ -0,0 +1,11 @@ + + + + + diff --git a/src/tbb/examples/parallel_for/tachyon/msvs/tachyon.serial.vcproj b/src/tbb/examples/parallel_for/tachyon/msvs/tachyon.serial.vcproj new file mode 100644 index 0000000..e5a13b2 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/msvs/tachyon.serial.vcproj @@ -0,0 +1,695 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/parallel_for/tachyon/msvs/tachyon.tbb.icproj b/src/tbb/examples/parallel_for/tachyon/msvs/tachyon.tbb.icproj new file mode 100644 index 0000000..58ec5c6 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/msvs/tachyon.tbb.icproj @@ -0,0 +1,11 @@ + + + + + diff --git a/src/tbb/examples/parallel_for/tachyon/msvs/tachyon.tbb.vcproj b/src/tbb/examples/parallel_for/tachyon/msvs/tachyon.tbb.vcproj new file mode 100644 index 0000000..2e4a465 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/msvs/tachyon.tbb.vcproj @@ -0,0 +1,731 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/parallel_for/tachyon/msvs/tachyon.tbb1d.icproj b/src/tbb/examples/parallel_for/tachyon/msvs/tachyon.tbb1d.icproj new file mode 100644 index 0000000..1c0f608 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/msvs/tachyon.tbb1d.icproj @@ -0,0 +1,11 @@ + + + + + diff --git a/src/tbb/examples/parallel_for/tachyon/msvs/tachyon.tbb1d.vcproj b/src/tbb/examples/parallel_for/tachyon/msvs/tachyon.tbb1d.vcproj new file mode 100644 index 0000000..5044e56 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/msvs/tachyon.tbb1d.vcproj @@ -0,0 +1,731 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/parallel_for/tachyon/msvs/tachyon.vcproj b/src/tbb/examples/parallel_for/tachyon/msvs/tachyon.vcproj new file mode 100644 index 0000000..ec91a77 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/msvs/tachyon.vcproj @@ -0,0 +1,1046 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/parallel_for/tachyon/msvs/tachyon_cl.sln b/src/tbb/examples/parallel_for/tachyon/msvs/tachyon_cl.sln new file mode 100644 index 0000000..8b2ff25 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/msvs/tachyon_cl.sln @@ -0,0 +1,92 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tachyon.tbb", "tachyon.tbb.vcproj", "{6E9B1702-78E0-4D64-B771-8B274D963B58}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tachyon.common", "tachyon.vcproj", "{924517DF-2B6A-47D5-8A11-CC247CC4D810}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tachyon.serial", "tachyon.serial.vcproj", "{924517DF-2B6A-47D5-8A11-CC047CC4D8E9}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tachyon.tbb1d", "tachyon.tbb1d.vcproj", "{924517DF-2B6A-47D5-8A11-CC347CC4D8E9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + DD Debug|Win32 = DD Debug|Win32 + DD Debug|x64 = DD Debug|x64 + DD Release|Win32 = DD Release|Win32 + DD Release|x64 = DD Release|x64 + GDI Debug|Win32 = GDI Debug|Win32 + GDI Debug|x64 = GDI Debug|x64 + _GDI Release|Win32 = _GDI Release|Win32 + _GDI Release|x64 = _GDI Release|x64 + Description = Tachyon ray-tracer example + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.DD Debug|Win32.Build.0 = DDDebug|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.DD Debug|x64.Build.0 = DDDebug|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.DD Release|Win32.Build.0 = DDRelease|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.DD Release|x64.ActiveCfg = DDRelease|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.DD Release|x64.Build.0 = DDRelease|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.GDI Debug|Win32.Build.0 = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.GDI Debug|x64.ActiveCfg = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.GDI Debug|x64.Build.0 = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}._GDI Release|Win32.ActiveCfg = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}._GDI Release|Win32.Build.0 = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}._GDI Release|x64.ActiveCfg = Release|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}._GDI Release|x64.Build.0 = Release|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.DD Debug|Win32.Build.0 = DDDebug|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.DD Debug|x64.Build.0 = DDDebug|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.DD Release|Win32.Build.0 = DDRelease|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.DD Release|x64.ActiveCfg = DDRelease|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.DD Release|x64.Build.0 = DDRelease|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.GDI Debug|Win32.Build.0 = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.GDI Debug|x64.ActiveCfg = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.GDI Debug|x64.Build.0 = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}._GDI Release|Win32.ActiveCfg = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}._GDI Release|Win32.Build.0 = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}._GDI Release|x64.ActiveCfg = Release|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}._GDI Release|x64.Build.0 = Release|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.DD Debug|Win32.Build.0 = DDDebug|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.DD Debug|x64.Build.0 = DDDebug|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.DD Release|Win32.Build.0 = DDRelease|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.DD Release|x64.ActiveCfg = DDRelease|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.DD Release|x64.Build.0 = DDRelease|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.GDI Debug|Win32.Build.0 = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.GDI Debug|x64.ActiveCfg = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.GDI Debug|x64.Build.0 = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}._GDI Release|Win32.ActiveCfg = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}._GDI Release|Win32.Build.0 = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}._GDI Release|x64.ActiveCfg = Release|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}._GDI Release|x64.Build.0 = Release|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.DD Debug|Win32.Build.0 = DDDebug|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.DD Debug|x64.Build.0 = DDDebug|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.DD Release|Win32.Build.0 = DDRelease|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.DD Release|x64.ActiveCfg = DDRelease|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.DD Release|x64.Build.0 = DDRelease|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.GDI Debug|Win32.Build.0 = Debug|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.GDI Debug|x64.ActiveCfg = Debug|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.GDI Debug|x64.Build.0 = Debug|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}._GDI Release|Win32.ActiveCfg = Release|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}._GDI Release|Win32.Build.0 = Release|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}._GDI Release|x64.ActiveCfg = Release|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}._GDI Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/parallel_for/tachyon/msvs/tachyon_icl.sln b/src/tbb/examples/parallel_for/tachyon/msvs/tachyon_icl.sln new file mode 100644 index 0000000..f4eca61 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/msvs/tachyon_icl.sln @@ -0,0 +1,149 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "tachyon.tbb", "tachyon.tbb.icproj", "{2D08E05F-D0E0-48A7-9597-28B95ACE70B6}" + ProjectSection(ProjectDependencies) = postProject + {5F685DBD-9A04-4E94-A1CA-FC48FE799830} = {5F685DBD-9A04-4E94-A1CA-FC48FE799830} + EndProjectSection +EndProject +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "tachyon.common", "tachyon.icproj", "{5F685DBD-9A04-4E94-A1CA-FC48FE799830}" +EndProject +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "tachyon.serial", "tachyon.serial.icproj", "{E085A8DB-75D4-4927-9631-6368E6D0EE72}" + ProjectSection(ProjectDependencies) = postProject + {5F685DBD-9A04-4E94-A1CA-FC48FE799830} = {5F685DBD-9A04-4E94-A1CA-FC48FE799830} + EndProjectSection +EndProject +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "tachyon.tbb1d", "tachyon.tbb1d.icproj", "{4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}" + ProjectSection(ProjectDependencies) = postProject + {5F685DBD-9A04-4E94-A1CA-FC48FE799830} = {5F685DBD-9A04-4E94-A1CA-FC48FE799830} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + DD Debug|Win32 = DD Debug|Win32 + DD Debug|x64 = DD Debug|x64 + DD Release|Win32 = DD Release|Win32 + DD Release|x64 = DD Release|x64 + GDI Debug|Win32 = GDI Debug|Win32 + GDI Debug|x64 = GDI Debug|x64 + _GDI Release|Win32 = _GDI Release|Win32 + _GDI Release|x64 = _GDI Release|x64 + Description = Tachyon ray-tracer example + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.DD Debug|Win32.Build.0 = DDDebug|Win32 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.DD Debug|x64.Build.0 = DDDebug|x64 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.DD Release|Win32.Build.0 = DDRelease|Win32 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.DD Release|x64.ActiveCfg = DDRelease|x64 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.DD Release|x64.Build.0 = DDRelease|x64 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.GDI Debug|Win32.Build.0 = Debug|Win32 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.GDI Debug|x64.ActiveCfg = Debug|x64 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}.GDI Debug|x64.Build.0 = Debug|x64 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}._GDI Release|Win32.ActiveCfg = Release|Win32 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}._GDI Release|Win32.Build.0 = Release|Win32 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}._GDI Release|x64.ActiveCfg = Release|x64 + {2D08E05F-D0E0-48A7-9597-28B95ACE70B6}._GDI Release|x64.Build.0 = Release|x64 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.DD Debug|Win32.Build.0 = DDDebug|Win32 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.DD Debug|x64.Build.0 = DDDebug|x64 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.DD Release|Win32.Build.0 = DDRelease|Win32 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.DD Release|x64.ActiveCfg = DDRelease|x64 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.DD Release|x64.Build.0 = DDRelease|x64 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.GDI Debug|Win32.Build.0 = Debug|Win32 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.GDI Debug|x64.ActiveCfg = Debug|x64 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}.GDI Debug|x64.Build.0 = Debug|x64 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}._GDI Release|Win32.ActiveCfg = Release|Win32 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}._GDI Release|Win32.Build.0 = Release|Win32 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}._GDI Release|x64.ActiveCfg = Release|x64 + {5F685DBD-9A04-4E94-A1CA-FC48FE799830}._GDI Release|x64.Build.0 = Release|x64 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.DD Debug|Win32.Build.0 = DDDebug|Win32 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.DD Debug|x64.Build.0 = DDDebug|x64 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.DD Release|Win32.Build.0 = DDRelease|Win32 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.DD Release|x64.ActiveCfg = DDRelease|x64 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.DD Release|x64.Build.0 = DDRelease|x64 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.GDI Debug|Win32.Build.0 = Debug|Win32 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.GDI Debug|x64.ActiveCfg = Debug|x64 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}.GDI Debug|x64.Build.0 = Debug|x64 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}._GDI Release|Win32.ActiveCfg = Release|Win32 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}._GDI Release|Win32.Build.0 = Release|Win32 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}._GDI Release|x64.ActiveCfg = Release|x64 + {E085A8DB-75D4-4927-9631-6368E6D0EE72}._GDI Release|x64.Build.0 = Release|x64 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.DD Debug|Win32.Build.0 = DDDebug|Win32 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.DD Debug|x64.Build.0 = DDDebug|x64 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.DD Release|Win32.Build.0 = DDRelease|Win32 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.DD Release|x64.ActiveCfg = DDRelease|x64 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.DD Release|x64.Build.0 = DDRelease|x64 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.GDI Debug|Win32.Build.0 = Debug|Win32 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.GDI Debug|x64.ActiveCfg = Debug|x64 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}.GDI Debug|x64.Build.0 = Debug|x64 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}._GDI Release|Win32.ActiveCfg = Release|Win32 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}._GDI Release|Win32.Build.0 = Release|Win32 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}._GDI Release|x64.ActiveCfg = Release|x64 + {4F173D3A-AE8C-4F7E-A4D0-6527F46B8495}._GDI Release|x64.Build.0 = Release|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.DD Release|x64.ActiveCfg = DDRelease|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.GDI Debug|Win32.Build.0 = Debug|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.GDI Debug|x64.ActiveCfg = Debug|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}.GDI Debug|x64.Build.0 = Debug|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}._GDI Release|Win32.ActiveCfg = Release|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}._GDI Release|Win32.Build.0 = Release|Win32 + {6E9B1702-78E0-4D64-B771-8B274D963B58}._GDI Release|x64.ActiveCfg = Release|x64 + {6E9B1702-78E0-4D64-B771-8B274D963B58}._GDI Release|x64.Build.0 = Release|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.DD Release|x64.ActiveCfg = DDRelease|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.GDI Debug|Win32.Build.0 = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.GDI Debug|x64.ActiveCfg = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}.GDI Debug|x64.Build.0 = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}._GDI Release|Win32.ActiveCfg = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}._GDI Release|Win32.Build.0 = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}._GDI Release|x64.ActiveCfg = Release|x64 + {924517DF-2B6A-47D5-8A11-CC247CC4D810}._GDI Release|x64.Build.0 = Release|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.DD Release|x64.ActiveCfg = DDRelease|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.GDI Debug|Win32.Build.0 = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.GDI Debug|x64.ActiveCfg = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}.GDI Debug|x64.Build.0 = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}._GDI Release|Win32.ActiveCfg = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}._GDI Release|Win32.Build.0 = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}._GDI Release|x64.ActiveCfg = Release|x64 + {924517DF-2B6A-47D5-8A11-CC047CC4D8E9}._GDI Release|x64.Build.0 = Release|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.DD Release|x64.ActiveCfg = DDRelease|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.GDI Debug|Win32.ActiveCfg = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.GDI Debug|Win32.Build.0 = Debug|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.GDI Debug|x64.ActiveCfg = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}.GDI Debug|x64.Build.0 = Debug|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}._GDI Release|Win32.ActiveCfg = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}._GDI Release|Win32.Build.0 = Release|Win32 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}._GDI Release|x64.ActiveCfg = Release|x64 + {924517DF-2B6A-47D5-8A11-CC347CC4D8E9}._GDI Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/parallel_for/tachyon/src/api.cpp b/src/tbb/examples/parallel_for/tachyon/src/api.cpp new file mode 100644 index 0000000..1aac39a --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/api.cpp @@ -0,0 +1,428 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * api.c - This file contains all of the API calls that are defined for + * external driver code to use. + * + * $Id: api.cpp,v 1.5 2007-02-22 17:54:14 Exp $ + */ + +#include "machine.h" +#include "types.h" +#include "macros.h" + +#include "box.h" +#include "cylinder.h" +#include "plane.h" +#include "quadric.h" +#include "ring.h" +#include "sphere.h" +#include "triangle.h" +#include "vol.h" +#include "extvol.h" + +#include "texture.h" +#include "light.h" +#include "render.h" +#include "camera.h" +#include "vector.h" +#include "intersect.h" +#include "shade.h" +#include "util.h" +#include "imap.h" +#include "global.h" + +#include "tachyon_video.h" + +typedef void * SceneHandle; +#include "api.h" + + +vector rt_vector(apiflt x, apiflt y, apiflt z) { + vector v; + + v.x = x; + v.y = y; + v.z = z; + + return v; +} + +color rt_color(apiflt r, apiflt g, apiflt b) { + color c; + + c.r = r; + c.g = g; + c.b = b; + + return c; +} + +void rt_initialize() { + rpcmsg msg; + + reset_object(); + reset_lights(); + InitTextures(); + + if (!parinitted) { + parinitted=1; + + msg.type=1; /* setup a ping message */ + } +} + +void rt_renderscene(SceneHandle voidscene) { + scenedef * scene = (scenedef *) voidscene; + renderscene(*scene); +} + +void rt_camerasetup(SceneHandle voidscene, apiflt zoom, apiflt aspectratio, + int antialiasing, int raydepth, + vector camcent, vector viewvec, vector upvec) { + scenedef * scene = (scenedef *) voidscene; + + vector newupvec; + vector newviewvec; + vector newrightvec; + + VCross((vector *) &upvec, &viewvec, &newrightvec); + VNorm(&newrightvec); + + VCross((vector *) &viewvec, &newrightvec, &newupvec); + VNorm(&newupvec); + + newviewvec=viewvec; + VNorm(&newviewvec); + + + scene->camzoom=zoom; + scene->aspectratio=aspectratio; + scene->antialiasing=antialiasing; + scene->raydepth=raydepth; + scene->camcent=camcent; + scene->camviewvec=newviewvec; + scene->camrightvec=newrightvec; + scene->camupvec=newupvec; +} + +void rt_outputfile(SceneHandle voidscene, const char * outname) { + scenedef * scene = (scenedef *) voidscene; + strcpy((char *) &scene->outfilename, outname); +} + +void rt_resolution(SceneHandle voidscene, int hres, int vres) { + scenedef * scene = (scenedef *) voidscene; + scene->hres=hres; + scene->vres=vres; +} + +void rt_verbose(SceneHandle voidscene, int v) { + scenedef * scene = (scenedef *) voidscene; + scene->verbosemode = v; +} + +void rt_rawimage(SceneHandle voidscene, unsigned char *rawimage) { + scenedef * scene = (scenedef *) voidscene; + scene->rawimage = rawimage; +} + +void rt_background(SceneHandle voidscene, color col) { + scenedef * scene = (scenedef *) voidscene; + scene->background.r = col.r; + scene->background.g = col.g; + scene->background.b = col.b; +} + +void rt_boundmode(SceneHandle voidscene, int mode) { + scenedef * scene = (scenedef *) voidscene; + scene->boundmode = mode; +} + +void rt_boundthresh(SceneHandle voidscene, int threshold) { + scenedef * scene = (scenedef *) voidscene; + + if (threshold > 1) { + scene->boundthresh = threshold; + } + else { + rtmesg("Ignoring out-of-range automatic bounding threshold.\n"); + rtmesg("Automatic bounding threshold reset to default.\n"); + scene->boundthresh = MAXOCTNODES; + } +} + +void rt_displaymode(SceneHandle voidscene, int mode) { + scenedef * scene = (scenedef *) voidscene; + scene->displaymode = mode; +} + + +void rt_scenesetup(SceneHandle voidscene, char * outname, int hres, int vres, int verbose) { + rt_outputfile(voidscene, outname); + rt_resolution(voidscene, hres, vres); + rt_verbose(voidscene, verbose); +} + +SceneHandle rt_newscene(void) { + scenedef * scene; + SceneHandle voidscene; + + scene = (scenedef *) malloc(sizeof(scenedef)); + memset(scene, 0, sizeof(scenedef)); /* clear all valuas to 0 */ + + voidscene = (SceneHandle) scene; + + rt_outputfile(voidscene, "/dev/null"); /* default output file (.tga) */ + rt_resolution(voidscene, 512, 512); /* 512x512 resolution */ + rt_verbose(voidscene, 0); /* verbose messages off */ + rt_rawimage(voidscene, NULL); /* raw image output off */ + rt_boundmode(voidscene, RT_BOUNDING_ENABLED); /* spatial subdivision on */ + rt_boundthresh(voidscene, MAXOCTNODES); /* default threshold */ + rt_displaymode(voidscene, RT_DISPLAY_ENABLED); /* video output on */ + rt_camerasetup(voidscene, 1.0, 1.0, 0, 6, + rt_vector(0.0, 0.0, 0.0), + rt_vector(0.0, 0.0, 1.0), + rt_vector(0.0, 1.0, 0.0)); + + return scene; +} + +void rt_deletescene(SceneHandle scene) { + if (scene != NULL) + free(scene); +} + +void apitextotex(apitexture * apitex, texture * tex) { + switch(apitex->texturefunc) { + case 0: + tex->texfunc=(color(*)(void *, void *, void *))(standard_texture); + break; + + case 1: + tex->texfunc=(color(*)(void *, void *, void *))(checker_texture); + break; + + case 2: + tex->texfunc=(color(*)(void *, void *, void *))(grit_texture); + break; + + case 3: + tex->texfunc=(color(*)(void *, void *, void *))(marble_texture); + break; + + case 4: + tex->texfunc=(color(*)(void *, void *, void *))(wood_texture); + break; + + case 5: + tex->texfunc=(color(*)(void *, void *, void *))(gnoise_texture); + break; + + case 6: + tex->texfunc=(color(*)(void *, void *, void *))(cyl_checker_texture); + break; + + case 7: + tex->texfunc=(color(*)(void *, void *, void *))(image_sphere_texture); + tex->img=AllocateImage((char *)apitex->imap); + break; + + case 8: + tex->texfunc=(color(*)(void *, void *, void *))(image_cyl_texture); + tex->img=AllocateImage((char *)apitex->imap); + break; + + case 9: + tex->texfunc=(color(*)(void *, void *, void *))(image_plane_texture); + tex->img=AllocateImage((char *)apitex->imap); + break; + + default: + tex->texfunc=(color(*)(void *, void *, void *))(standard_texture); + break; + } + + tex->ctr = apitex->ctr; + tex->rot = apitex->rot; + tex->scale = apitex->scale; + tex->uaxs = apitex->uaxs; + tex->vaxs = apitex->vaxs; + tex->ambient = apitex->ambient; + tex->diffuse = apitex->diffuse; + tex->specular = apitex->specular; + tex->opacity = apitex->opacity; + tex->col = apitex->col; + + tex->islight = 0; + tex->shadowcast = 1; + tex->phong = 0.0; + tex->phongexp = 0.0; + tex->phongtype = 0; +} + +void * rt_texture(apitexture * apitex) { + texture * tex; + + tex=(texture *)rt_getmem(sizeof(texture)); + apitextotex(apitex, tex); + return(tex); +} + +void rt_tex_color(void * voidtex, color col) { + texture * tex = (texture *) voidtex; + tex->col = col; +} + +void rt_tex_phong(void * voidtex, apiflt phong, apiflt phongexp, int type) { + texture * tex = (texture *) voidtex; + tex->phong = phong; + tex->phongexp = phongexp; + tex->phongtype = type; +} + +void rt_light(void * tex, vector ctr, apiflt rad) { + point_light * li; + + li=newlight(tex, (vector) ctr, rad); + + li->tex->islight=1; + li->tex->shadowcast=1; + li->tex->diffuse=0.0; + li->tex->specular=0.0; + li->tex->opacity=1.0; + + add_light(li); + add_object((object *)li); +} + +void rt_scalarvol(void * tex, vector min, vector max, + int xs, int ys, int zs, char * fname, void * invol) { + add_object((object *) newscalarvol(tex, (vector)min, (vector)max, xs, ys, zs, fname, (scalarvol *) invol)); +} + +void rt_extvol(void * tex, vector min, vector max, int samples, flt (* evaluator)(flt, flt, flt)) { + add_object((object *) newextvol(tex, (vector)min, (vector)max, samples, evaluator)); +} + +void rt_box(void * tex, vector min, vector max) { + add_object((object *) newbox(tex, (vector)min, (vector)max)); +} + +void rt_cylinder(void * tex, vector ctr, vector axis, apiflt rad) { + add_object(newcylinder(tex, (vector)ctr, (vector)axis, rad)); +} + +void rt_fcylinder(void * tex, vector ctr, vector axis, apiflt rad) { + add_object(newfcylinder(tex, (vector)ctr, (vector)axis, rad)); +} + +void rt_plane(void * tex, vector ctr, vector norm) { + add_object(newplane(tex, (vector)ctr, (vector)norm)); +} + +void rt_ring(void * tex, vector ctr, vector norm, apiflt a, apiflt b) { + add_object(newring(tex, (vector)ctr, (vector)norm, a, b)); +} + +void rt_sphere(void * tex, vector ctr, apiflt rad) { + add_object(newsphere(tex, (vector)ctr, rad)); +} + +void rt_tri(void * tex, vector v0, vector v1, vector v2) { + object * trn; + + trn = newtri(tex, (vector)v0, (vector)v1, (vector)v2); + + if (trn != NULL) { + add_object(trn); + } +} + +void rt_stri(void * tex, vector v0, vector v1, vector v2, + vector n0, vector n1, vector n2) { + object * trn; + + trn = newstri(tex, (vector)v0, (vector)v1, (vector)v2, (vector)n0, (vector)n1, (vector)n2); + + if (trn != NULL) { + add_object(trn); + } +} + +void rt_quadsphere(void * tex, vector ctr, apiflt rad) { + quadric * q; + flt factor; + q=(quadric *) newquadric(); + factor= 1.0 / (rad*rad); + q->tex=(texture *)tex; + q->ctr=ctr; + + q->mat.a=factor; + q->mat.b=0.0; + q->mat.c=0.0; + q->mat.d=0.0; + q->mat.e=factor; + q->mat.f=0.0; + q->mat.g=0.0; + q->mat.h=factor; + q->mat.i=0.0; + q->mat.j=-1.0; + + add_object((object *)q); +} diff --git a/src/tbb/examples/parallel_for/tachyon/src/api.h b/src/tbb/examples/parallel_for/tachyon/src/api.h new file mode 100644 index 0000000..94f7b2d --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/api.h @@ -0,0 +1,216 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/***************************************************************************** + * api.h - The declarations and prototypes needed so that 3rd party driver * + * code can run the raytracer. Third party driver code should * + * only use the functions in this header file to interface with * + * the rendering engine. * + *************************************************************************** */ + + +/* + * $Id: api.h,v 1.2 2007-02-22 17:54:15 Exp $ + */ + + +/********************************************/ +/* Types defined for use with the API calls */ +/********************************************/ + +#ifdef USESINGLEFLT +typedef float apiflt; /* generic floating point number */ +#else +typedef double apiflt; /* generic floating point number */ +#endif + +typedef void * SceneHandle; + +typedef struct { + int texturefunc; /* which texture function to use */ + color col; /* base object color */ + int shadowcast; /* does the object cast a shadow */ + apiflt ambient; /* ambient lighting */ + apiflt diffuse; /* diffuse reflection */ + apiflt specular; /* specular reflection */ + apiflt opacity; /* how opaque the object is */ + vector ctr; /* origin of texture */ + vector rot; /* rotation of texture around origin */ + vector scale; /* scale of texture in x,y,z */ + vector uaxs; /* planar map u axis */ + vector vaxs; /* planar map v axis */ + char imap[96]; /* name of image map */ +} apitexture; + + +/******************************************************************* + * NOTE: The value passed in apitexture.texturefunc corresponds to + * the meanings given in this table: + * + * 0 - No texture function is applied other than standard lighting. + * 1 - 3D checkerboard texture. Red & Blue checkers through 3d space. + * 2 - Grit texture, roughens up the surface of the object a bit. + * 3 - 3D marble texture. Makes a 3D swirl pattern through the object. + * 4 - 3D wood texture. Makes a 3D wood pattern through the object. + * 5 - 3D gradient noise function. + * 6 - I've forgotten :-) + * 7 - Cylindrical Image Map **** IMAGE MAPS REQUIRE the filename + * 8 - Spherical Image Map of the image be put in imap[] + * 9 - Planar Image Map part of the texture... + * planar requires uaxs, and vaxs.. + * + *******************************************************************/ + +/********************************************/ +/* Functions implemented to provide the API */ +/********************************************/ + +vector rt_vector(apiflt x, apiflt y, apiflt z); /* helper to make vectors */ +color rt_color(apiflt r, apiflt g, apiflt b); /* helper to make colors */ + +void rt_initialize();/* reset raytracer, memory deallocation */ +void rt_finalize(void); /* close down for good.. */ + +SceneHandle rt_newscene(void); /* allocate new scene */ +void rt_deletescene(SceneHandle); /* delete a scene */ +void rt_renderscene(SceneHandle); /* raytrace the current scene */ +void rt_outputfile(SceneHandle, const char * outname); +void rt_resolution(SceneHandle, int hres, int vres); +void rt_verbose(SceneHandle, int v); +void rt_rawimage(SceneHandle, unsigned char *rawimage); +void rt_background(SceneHandle, color); + +/* Parameter values for rt_boundmode() */ +#define RT_BOUNDING_DISABLED 0 +#define RT_BOUNDING_ENABLED 1 + +void rt_boundmode(SceneHandle, int); +void rt_boundthresh(SceneHandle, int); + +/* Parameter values for rt_displaymode() */ +#define RT_DISPLAY_DISABLED 0 +#define RT_DISPLAY_ENABLED 1 + +void rt_displaymode(SceneHandle, int); + +void rt_scenesetup(SceneHandle, char *, int, int, int); + /* scene, output filename, horizontal resolution, vertical resolution, + verbose mode */ + + +void rt_camerasetup(SceneHandle, apiflt, apiflt, int, int, + vector, vector, vector); + /* camera parms: scene, zoom, aspectratio, antialiasing, raydepth, + camera center, view direction, up direction */ + + + +void * rt_texture(apitexture *); + /* pointer to the texture struct that would have been passed to each + object() call in older revisions.. */ + + + + +void rt_light(void * , vector, apiflt); /* add a light */ + /* light parms: texture, center, radius */ + +void rt_sphere(void *, vector, apiflt); /* add a sphere */ + /* sphere parms: texture, center, radius */ + +void rt_scalarvol(void *, vector, vector, + int, int, int, char *, void *); + +void rt_extvol(void *, vector, vector, int, apiflt (* evaluator)(apiflt, apiflt, apiflt)); + +void rt_box(void *, vector, vector); + /* box parms: texture, min, max */ + +void rt_plane(void *, vector, vector); + /* plane parms: texture, center, normal */ + +void rt_ring(void *, vector, vector, apiflt, apiflt); + /* ring parms: texture, center, normal, inner, outer */ + +void rt_tri(void *, vector, vector, vector); + /* tri parms: texture, vertex 0, vertex 1, vertex 2 */ + +void rt_stri(void *, vector, vector, vector, + vector, vector, vector); + /* stri parms: texture, vertex 0, vertex 1, vertex 2, norm 0, norm 1, norm 2 */ + +void rt_heightfield(void *, vector, int, int, apiflt *, apiflt, apiflt); + /* field parms: texture, center, m, n, field, wx, wy */ + +void rt_landscape(void *, int, int, vector, apiflt, apiflt); + +void rt_quadsphere(void *, vector, apiflt); /* add quadric sphere */ + /* sphere parms: texture, center, radius */ + +void rt_cylinder(void *, vector, vector, apiflt); + +void rt_fcylinder(void *, vector, vector, apiflt); + +void rt_polycylinder(void *, vector *, int, apiflt); + + +/* new texture handling routines */ +void rt_tex_color(void * voidtex, color col); + +#define RT_PHONG_PLASTIC 0 +#define RT_PHONG_METAL 1 +void rt_tex_phong(void * voidtex, apiflt phong, apiflt phongexp, int type); diff --git a/src/tbb/examples/parallel_for/tachyon/src/apigeom.cpp b/src/tbb/examples/parallel_for/tachyon/src/apigeom.cpp new file mode 100644 index 0000000..f07a2b5 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/apigeom.cpp @@ -0,0 +1,278 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * api.c - This file contains all of the API calls that are defined for + * external driver code to use. + * + * $Id: apigeom.cpp,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +#include "machine.h" +#include "types.h" +#include "api.h" +#include "macros.h" +#include "vector.h" + +#define MyVNorm(a) VNorm ((vector *) a) + +void rt_polycylinder(void * tex, vector * points, int numpts, apiflt rad) { + vector a; + int i; + + if ((points == NULL) || (numpts == 0)) { + return; + } + + if (numpts > 0) { + rt_sphere(tex, points[0], rad); + + if (numpts > 1) { + for (i=1; i (xres + yres)) v=(xres + yres); + base[x + (xres * y)]=v; + } +} + +static void subdivide(apiflt *base, int xres, int yres, apiflt wx, apiflt wy, + int x1, int y1, int x2, int y2) { + long x,y; + + if (((x2 - x1) < 2) && ((y2 - y1) < 2)) { return; } + + x=(x1 + x2) / 2; + y=(y1 + y2) / 2; + + adjust(base, xres, yres, wx, wy, x1, y1, x, y1, x2, y1); + adjust(base, xres, yres, wx, wy, x2, y1, x2, y, x2, y2); + adjust(base, xres, yres, wx, wy, x1, y2, x, y2, x2, y2); + adjust(base, xres, yres, wx, wy, x1, y1, x1, y, x1, y2); + + + if (base[x + xres*y]==0.0) { + base[x + (xres * y)]=(base[x1 + xres*y1] + base[x2 + xres*y1] + + base[x2 + xres*y2] + base[x1 + xres*y2] )/4.0; + } + + subdivide(base, xres, yres, wx, wy, x1, y1 ,x ,y); + subdivide(base, xres, yres, wx, wy, x, y1, x2, y); + subdivide(base, xres, yres, wx, wy, x, y, x2, y2); + subdivide(base, xres, yres, wx, wy, x1, y, x, y2); +} + +void rt_landscape(void * tex, int m, int n, + vector ctr, apiflt wx, apiflt wy) { + int totalsize, x, y; + apiflt * field; + + totalsize=m*n; + + srand(totalsize); + + field=(apiflt *) malloc(totalsize*sizeof(apiflt)); + + for (y=0; ymin=min; + b->max=max; + b->methods = &bndbox_methods; + + b->objlist=NULL; + b->tex=NULL; + b->nextobj=NULL; + return b; +} + + +static int bndbox_bbox(void * obj, vector * min, vector * max) { + bndbox * b = (bndbox *) obj; + + *min = b->min; + *max = b->max; + + return 1; +} + + +static void free_bndbox(void * v) { + bndbox * b = (bndbox *) v; + + free_objects(b->objlist); + + free(b); +} + + +static void bndbox_intersect(bndbox * bx, ray * ry) { + flt a, tx1, tx2, ty1, ty2, tz1, tz2; + flt tnear, tfar; + object * obj; + ray newray; + + /* eliminate bounded rays whose bounds do not intersect */ + /* the bounds of the box.. */ + if (ry->flags |= RT_RAY_BOUNDED) { + if ((ry->s.x > bx->max.x) && (ry->e.x > bx->max.x)) return; + if ((ry->s.x < bx->min.x) && (ry->e.x < bx->min.x)) return; + + if ((ry->s.y > bx->max.y) && (ry->e.y > bx->max.y)) return; + if ((ry->s.y < bx->min.y) && (ry->e.y < bx->min.y)) return; + + if ((ry->s.z > bx->max.z) && (ry->e.z > bx->max.z)) return; + if ((ry->s.z < bx->min.z) && (ry->e.z < bx->min.z)) return; + } + + tnear= -FHUGE; + tfar= FHUGE; + + if (ry->d.x == 0.0) { + if ((ry->o.x < bx->min.x) || (ry->o.x > bx->max.x)) return; + } + else { + tx1 = (bx->min.x - ry->o.x) / ry->d.x; + tx2 = (bx->max.x - ry->o.x) / ry->d.x; + if (tx1 > tx2) { a=tx1; tx1=tx2; tx2=a; } + if (tx1 > tnear) tnear=tx1; + if (tx2 < tfar) tfar=tx2; + } + if (tnear > tfar) return; + if (tfar < 0.0) return; + + if (ry->d.y == 0.0) { + if ((ry->o.y < bx->min.y) || (ry->o.y > bx->max.y)) return; + } + else { + ty1 = (bx->min.y - ry->o.y) / ry->d.y; + ty2 = (bx->max.y - ry->o.y) / ry->d.y; + if (ty1 > ty2) { a=ty1; ty1=ty2; ty2=a; } + if (ty1 > tnear) tnear=ty1; + if (ty2 < tfar) tfar=ty2; + } + if (tnear > tfar) return; + if (tfar < 0.0) return; + + if (ry->d.z == 0.0) { + if ((ry->o.z < bx->min.z) || (ry->o.z > bx->max.z)) return; + } + else { + tz1 = (bx->min.z - ry->o.z) / ry->d.z; + tz2 = (bx->max.z - ry->o.z) / ry->d.z; + if (tz1 > tz2) { a=tz1; tz1=tz2; tz2=a; } + if (tz1 > tnear) tnear=tz1; + if (tz2 < tfar) tfar=tz2; + } + if (tnear > tfar) return; + if (tfar < 0.0) return; + + + /* intersect all of the enclosed objects */ + newray=*ry; + newray.flags |= RT_RAY_BOUNDED; + + RAYPNT(newray.s , (*ry) , tnear); + RAYPNT(newray.e , (*ry) , (tfar + EPSILON)); + + obj = bx->objlist; + while (obj != NULL) { + obj->methods->intersect(obj, &newray); + obj = (object *)obj->nextobj; + } +} + diff --git a/src/tbb/examples/parallel_for/tachyon/src/bndbox.h b/src/tbb/examples/parallel_for/tachyon/src/bndbox.h new file mode 100644 index 0000000..6bcfcf6 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/bndbox.h @@ -0,0 +1,82 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * bndbox.h - This file contains the defines for bounding boxes etc. + * + * $Id: bndbox.h,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +typedef struct { + unsigned int id; /* Unique Object serial number */ + void * nextobj; /* pointer to next object in list */ + object_methods * methods; /* this object's methods */ + texture * tex; /* object texture */ + vector min; + vector max; + object * objlist; +} bndbox; + +bndbox * newbndbox(vector min, vector max); + +#ifdef BNDBOX_PRIVATE + +static int bndbox_bbox(void * obj, vector * min, vector * max); +static void free_bndbox(void * v); +static void bndbox_intersect(bndbox *, ray *); + +#endif diff --git a/src/tbb/examples/parallel_for/tachyon/src/box.cpp b/src/tbb/examples/parallel_for/tachyon/src/box.cpp new file mode 100644 index 0000000..c90f1c8 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/box.cpp @@ -0,0 +1,178 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * box.c - This file contains the functions for dealing with boxes. + * + * $Id: box.cpp,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +#include "machine.h" +#include "types.h" +#include "macros.h" +#include "box.h" +#include "vector.h" +#include "intersect.h" +#include "util.h" + +int box_bbox(void * obj, vector * min, vector * max) { + box * b = (box *) obj; + + *min = b->min; + *max = b->max; + + return 1; +} + +static object_methods box_methods = { + (void (*)(void *, void *))(box_intersect), + (void (*)(void *, void *, void *, void *))(box_normal), + box_bbox, + free +}; + +box * newbox(void * tex, vector min, vector max) { + box * b; + + b=(box *) rt_getmem(sizeof(box)); + memset(b, 0, sizeof(box)); + b->methods = &box_methods; + b->tex = (texture *)tex; + b->min = min; + b->max = max; + + return b; +} + +void box_intersect(box * bx, ray * ry) { + flt a, tx1, tx2, ty1, ty2, tz1, tz2; + flt tnear, tfar; + + tnear= -FHUGE; + tfar= FHUGE; + + if (ry->d.x == 0.0) { + if ((ry->o.x < bx->min.x) || (ry->o.x > bx->max.x)) return; + } + else { + tx1 = (bx->min.x - ry->o.x) / ry->d.x; + tx2 = (bx->max.x - ry->o.x) / ry->d.x; + if (tx1 > tx2) { a=tx1; tx1=tx2; tx2=a; } + if (tx1 > tnear) tnear=tx1; + if (tx2 < tfar) tfar=tx2; + } + if (tnear > tfar) return; + if (tfar < 0.0) return; + + if (ry->d.y == 0.0) { + if ((ry->o.y < bx->min.y) || (ry->o.y > bx->max.y)) return; + } + else { + ty1 = (bx->min.y - ry->o.y) / ry->d.y; + ty2 = (bx->max.y - ry->o.y) / ry->d.y; + if (ty1 > ty2) { a=ty1; ty1=ty2; ty2=a; } + if (ty1 > tnear) tnear=ty1; + if (ty2 < tfar) tfar=ty2; + } + if (tnear > tfar) return; + if (tfar < 0.0) return; + + if (ry->d.z == 0.0) { + if ((ry->o.z < bx->min.z) || (ry->o.z > bx->max.z)) return; + } + else { + tz1 = (bx->min.z - ry->o.z) / ry->d.z; + tz2 = (bx->max.z - ry->o.z) / ry->d.z; + if (tz1 > tz2) { a=tz1; tz1=tz2; tz2=a; } + if (tz1 > tnear) tnear=tz1; + if (tz2 < tfar) tfar=tz2; + } + if (tnear > tfar) return; + if (tfar < 0.0) return; + + add_intersection(tnear, (object *) bx, ry); + add_intersection(tfar, (object *) bx, ry); +} + +void box_normal(box * bx, vector * pnt, ray * incident, vector * N) { + vector a, b, c; + flt t; + + c.x=(bx->max.x + bx->min.x) / 2.0; + c.y=(bx->max.y + bx->min.y) / 2.0; + c.z=(bx->max.z + bx->min.z) / 2.0; + + VSub((vector *) pnt, &c, N); + b=(*N); + + a.x=fabs(N->x); + a.y=fabs(N->y); + a.z=fabs(N->z); + + N->x=0.0; N->y=0.0; N->z=0.0; + + t=MYMAX(a.x, MYMAX(a.y, a.z)); + + if (t==a.x) N->x=b.x; + + if (t==a.y) N->y=b.y; + + if (t==a.z) N->z=b.z; + + VNorm(N); +} + diff --git a/src/tbb/examples/parallel_for/tachyon/src/box.h b/src/tbb/examples/parallel_for/tachyon/src/box.h new file mode 100644 index 0000000..db3d073 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/box.h @@ -0,0 +1,77 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * box.h - This file contains the defines for boxes etc. + * + * $Id: box.h,v 1.2 2007-02-22 17:54:15 Exp $ + */ + + +typedef struct { + unsigned int id; /* Unique Object serial number */ + void * nextobj; /* pointer to next object in list */ + object_methods * methods; /* this object's methods */ + texture * tex; /* object texture */ + vector min; + vector max; +} box; + + +box * newbox(void * tex, vector min, vector max); +void box_intersect(box *, ray *); +void box_normal(box *, vector *, ray * incident, vector *); diff --git a/src/tbb/examples/parallel_for/tachyon/src/camera.cpp b/src/tbb/examples/parallel_for/tachyon/src/camera.cpp new file mode 100644 index 0000000..a5a9053 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/camera.cpp @@ -0,0 +1,119 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * camera.c - This file contains all of the functions for doing camera work. + * + * $Id: camera.cpp,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +#include "machine.h" +#include "types.h" +#include "macros.h" +#include "vector.h" +#include "camera.h" +#include "util.h" + +ray camray(scenedef *scene, int x, int y) { + ray ray1, newray; + vector projcent; + vector projpixel; + flt px, py, sx, sy; + + sx = (flt) scene->hres; + sy = (flt) scene->vres; + + /* calculate the width and height of the image plane given the */ + /* aspect ratio, image resolution, and zoom factor */ + + px=((sx / sy) / scene->aspectratio) / scene->camzoom; + py=1.0 / scene->camzoom; + + /* assuming viewvec is a unit vector, then the center of the */ + /* image plane is the camera center + vievec */ + projcent.x = scene->camcent.x + scene->camviewvec.x; + projcent.y = scene->camcent.y + scene->camviewvec.y; + projcent.z = scene->camcent.z + scene->camviewvec.z; + + /* starting from the center of the image plane, we move the */ + /* center of the pel we're calculating, to */ + /* projcent + (rightvec * x distance) */ + ray1.o=projcent; + ray1.d=scene->camrightvec; + projpixel=Raypnt(&ray1, ((x*px/sx) - (px / 2.0))); + + /* starting from the horizontally translated pel, we move the */ + /* center of the pel we're calculating, to */ + /* projcent + (upvec * y distance) */ + ray1.o=projpixel; + ray1.d=scene->camupvec; + projpixel=Raypnt(&ray1, ((y*py/sy) - (py / 2.0))); + + /* now that we have the exact pel center in the image plane */ + /* we create the real primary ray that will be used by the */ + /* rest of the system. */ + /* The ray is expected to be re-normalized elsewhere, we're */ + /* only really concerned about getting its direction right. */ + newray.o=scene->camcent; + VSub(&projpixel, &scene->camcent, &newray.d); + newray.depth = scene->raydepth; + newray.flags = RT_RAY_REGULAR; /* camera only generates primary rays */ + + return newray; +} + + diff --git a/src/tbb/examples/parallel_for/tachyon/src/camera.h b/src/tbb/examples/parallel_for/tachyon/src/camera.h new file mode 100644 index 0000000..d75abb2 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/camera.h @@ -0,0 +1,64 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * camera.h - This file contains the defines for camera routines etc. + * + * $Id: camera.h,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +ray camray(scenedef *, int, int); diff --git a/src/tbb/examples/parallel_for/tachyon/src/coordsys.cpp b/src/tbb/examples/parallel_for/tachyon/src/coordsys.cpp new file mode 100644 index 0000000..c21c00a --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/coordsys.cpp @@ -0,0 +1,106 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * coordsys.c - Routines to translate from one coordinate system to another. + * + * $Id: coordsys.cpp,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +#include "machine.h" +#include "types.h" +#include "coordsys.h" + +void xytopolar(flt x, flt y, flt rad, flt * u, flt * v) { + flt r1; + r1=x*x + y*y; + *v=sqrt(r1 / (rad*rad)); + if (y<0.0) + *u=1.0 - acos(x/sqrt(r1))/TWOPI; + else + *u= acos(x/sqrt(r1))/TWOPI; +} + +void xyztocyl(vector pnt, flt height, flt * u, flt * v) { + flt r1; + + r1=pnt.x*pnt.x + pnt.y*pnt.y; + + *v=pnt.z / height; + if (pnt.y<0.0) + *u=1.0 - acos(pnt.x/sqrt(r1))/TWOPI; + else + *u=acos(pnt.x/sqrt(r1))/TWOPI; +} + +void xyztospr(vector pnt, flt * u, flt * v) { + flt r1, phi, theta; + + r1=sqrt(pnt.x*pnt.x + pnt.y*pnt.y + pnt.z*pnt.z); + + phi=acos(-pnt.y/r1); + *v=phi/3.1415926; + + theta=acos((pnt.x/r1)/sin(phi))/TWOPI; + + if (pnt.z > 0.0) + *u = theta; + else + *u = 1 - theta; +} + + diff --git a/src/tbb/examples/parallel_for/tachyon/src/coordsys.h b/src/tbb/examples/parallel_for/tachyon/src/coordsys.h new file mode 100644 index 0000000..32870a5 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/coordsys.h @@ -0,0 +1,68 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * coordsys.h - defines for coordinate system routines. + * + * $Id: coordsys.h,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +#define TWOPI 6.2831853 + +void xytopolar(flt, flt, flt, flt *, flt *); +void xyztocyl(vector, flt, flt *, flt *); +void xyztospr(vector, flt *, flt *); diff --git a/src/tbb/examples/parallel_for/tachyon/src/cylinder.cpp b/src/tbb/examples/parallel_for/tachyon/src/cylinder.cpp new file mode 100644 index 0000000..07822a0 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/cylinder.cpp @@ -0,0 +1,281 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * cylinder.c - This file contains the functions for dealing with cylinders. + * + * $Id: cylinder.cpp,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +#include "machine.h" +#include "types.h" +#include "macros.h" +#include "vector.h" +#include "intersect.h" +#include "util.h" + +#define CYLINDER_PRIVATE +#include "cylinder.h" + +static object_methods cylinder_methods = { + (void (*)(void *, void *))(cylinder_intersect), + (void (*)(void *, void *, void *, void *))(cylinder_normal), + cylinder_bbox, + free +}; + +static object_methods fcylinder_methods = { + (void (*)(void *, void *))(fcylinder_intersect), + (void (*)(void *, void *, void *, void *))(cylinder_normal), + fcylinder_bbox, + free +}; + + +object * newcylinder(void * tex, vector ctr, vector axis, flt rad) { + cylinder * c; + + c=(cylinder *) rt_getmem(sizeof(cylinder)); + memset(c, 0, sizeof(cylinder)); + c->methods = &cylinder_methods; + + c->tex=(texture *) tex; + c->ctr=ctr; + c->axis=axis; + c->rad=rad; + return (object *) c; +} + +static int cylinder_bbox(void * obj, vector * min, vector * max) { + return 0; /* infinite / unbounded object */ +} + +static void cylinder_intersect(cylinder * cyl, ray * ry) { + vector rc, n, D, O; + flt t, s, tin, tout, ln, d; + + rc.x = ry->o.x - cyl->ctr.x; + rc.y = ry->o.y - cyl->ctr.y; + rc.z = ry->o.z - cyl->ctr.z; + + VCross(&ry->d, &cyl->axis, &n); + + VDOT(ln, n, n); + ln=sqrt(ln); /* finish length calculation */ + + if (ln == 0.0) { /* ray is parallel to the cylinder.. */ + VDOT(d, rc, cyl->axis); + D.x = rc.x - d * cyl->axis.x; + D.y = rc.y - d * cyl->axis.y; + D.z = rc.z - d * cyl->axis.z; + VDOT(d, D, D); + d = sqrt(d); + tin = -FHUGE; + tout = FHUGE; + /* if (d <= cyl->rad) then ray is inside cylinder.. else outside */ + } + + VNorm(&n); + VDOT(d, rc, n); + d = fabs(d); + + if (d <= cyl->rad) { /* ray intersects cylinder.. */ + VCross(&rc, &cyl->axis, &O); + VDOT(t, O, n); + t = - t / ln; + VCross(&n, &cyl->axis, &O); + VNorm(&O); + VDOT(s, ry->d, O); + s = fabs(sqrt(cyl->rad*cyl->rad - d*d) / s); + tin = t - s; + add_intersection(tin, (object *) cyl, ry); + tout = t + s; + add_intersection(tout, (object *) cyl, ry); + } +} + +static void cylinder_normal(cylinder * cyl, vector * pnt, ray * incident, vector * N) { + vector a,b,c; + flt t; + + VSub((vector *) pnt, &(cyl->ctr), &a); + + c=cyl->axis; + + VNorm(&c); + + VDOT(t, a, c); + + b.x = c.x * t + cyl->ctr.x; + b.y = c.y * t + cyl->ctr.y; + b.z = c.z * t + cyl->ctr.z; + + VSub(pnt, &b, N); + VNorm(N); + + if (VDot(N, &(incident->d)) > 0.0) { /* make cylinder double sided */ + N->x=-N->x; + N->y=-N->y; + N->z=-N->z; + } +} + +object * newfcylinder(void * tex, vector ctr, vector axis, flt rad) { + cylinder * c; + + c=(cylinder *) rt_getmem(sizeof(cylinder)); + memset(c, 0, sizeof(cylinder)); + c->methods = &fcylinder_methods; + + c->tex=(texture *) tex; + c->ctr=ctr; + c->axis=axis; + c->rad=rad; + + return (object *) c; +} + +static int fcylinder_bbox(void * obj, vector * min, vector * max) { + cylinder * c = (cylinder *) obj; + vector mintmp, maxtmp; + + mintmp.x = c->ctr.x; + mintmp.y = c->ctr.y; + mintmp.z = c->ctr.z; + maxtmp.x = c->ctr.x + c->axis.x; + maxtmp.y = c->ctr.y + c->axis.y; + maxtmp.z = c->ctr.z + c->axis.z; + + min->x = MYMIN(mintmp.x, maxtmp.x); + min->y = MYMIN(mintmp.y, maxtmp.y); + min->z = MYMIN(mintmp.z, maxtmp.z); + min->x -= c->rad; + min->y -= c->rad; + min->z -= c->rad; + + max->x = MYMAX(mintmp.x, maxtmp.x); + max->y = MYMAX(mintmp.y, maxtmp.y); + max->z = MYMAX(mintmp.z, maxtmp.z); + max->x += c->rad; + max->y += c->rad; + max->z += c->rad; + + return 1; +} + + +static void fcylinder_intersect(cylinder * cyl, ray * ry) { + vector rc, n, O, hit, tmp2, ctmp4; + flt t, s, tin, tout, ln, d, tmp, tmp3; + + rc.x = ry->o.x - cyl->ctr.x; + rc.y = ry->o.y - cyl->ctr.y; + rc.z = ry->o.z - cyl->ctr.z; + + VCross(&ry->d, &cyl->axis, &n); + + VDOT(ln, n, n); + ln=sqrt(ln); /* finish length calculation */ + + if (ln == 0.0) { /* ray is parallel to the cylinder.. */ + return; /* in this case, we want to miss or go through the "hole" */ + } + + VNorm(&n); + VDOT(d, rc, n); + d = fabs(d); + + if (d <= cyl->rad) { /* ray intersects cylinder.. */ + VCross(&rc, &cyl->axis, &O); + VDOT(t, O, n); + t = - t / ln; + VCross(&n, &cyl->axis, &O); + VNorm(&O); + VDOT(s, ry->d, O); + s = fabs(sqrt(cyl->rad*cyl->rad - d*d) / s); + tin = t - s; + + RAYPNT(hit, (*ry), tin); + + ctmp4=cyl->axis; + VNorm(&ctmp4); + + tmp2.x = hit.x - cyl->ctr.x; + tmp2.y = hit.y - cyl->ctr.y; + tmp2.z = hit.z - cyl->ctr.z; + + VDOT(tmp, tmp2, ctmp4); + VDOT(tmp3, cyl->axis, cyl->axis); + + if ((tmp > 0.0) && (tmp < sqrt(tmp3))) + add_intersection(tin, (object *) cyl, ry); + tout = t + s; + + RAYPNT(hit, (*ry), tout); + + tmp2.x = hit.x - cyl->ctr.x; + tmp2.y = hit.y - cyl->ctr.y; + tmp2.z = hit.z - cyl->ctr.z; + + VDOT(tmp, tmp2, ctmp4); + VDOT(tmp3, cyl->axis, cyl->axis); + + if ((tmp > 0.0) && (tmp < sqrt(tmp3))) + add_intersection(tout, (object *) cyl, ry); + } +} + diff --git a/src/tbb/examples/parallel_for/tachyon/src/cylinder.h b/src/tbb/examples/parallel_for/tachyon/src/cylinder.h new file mode 100644 index 0000000..3f92778 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/cylinder.h @@ -0,0 +1,86 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * cylinder.h - This file contains the defines for cylinders etc. + * + * $Id: cylinder.h,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +object * newcylinder(void *, vector, vector, flt); +object * newfcylinder(void *, vector, vector, flt); + +#ifdef CYLINDER_PRIVATE + +typedef struct { + unsigned int id; /* Unique Object serial number */ + void * nextobj; /* pointer to next object in list */ + object_methods * methods; /* this object's methods */ + texture * tex; /* object texture */ + vector ctr; + vector axis; + flt rad; +} cylinder; + +static void cylinder_intersect(cylinder *, ray *); +static void fcylinder_intersect(cylinder *, ray *); + +static int cylinder_bbox(void * obj, vector * min, vector * max); +static int fcylinder_bbox(void * obj, vector * min, vector * max); + +static void cylinder_normal(cylinder *, vector *, ray *, vector *); +#endif diff --git a/src/tbb/examples/parallel_for/tachyon/src/extvol.cpp b/src/tbb/examples/parallel_for/tachyon/src/extvol.cpp new file mode 100644 index 0000000..33c6489 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/extvol.cpp @@ -0,0 +1,321 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * extvol.c - Volume rendering helper routines etc. + * + * $Id: extvol.cpp,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +#include + +#include "machine.h" +#include "types.h" +#include "macros.h" +#include "vector.h" +#include "util.h" +#include "box.h" +#include "extvol.h" +#include "trace.h" +#include "sphere.h" +#include "light.h" +#include "shade.h" +#include "global.h" + + +int extvol_bbox(void * obj, vector * min, vector * max) { + box * b = (box *) obj; + + *min = b->min; + *max = b->max; + + return 1; +} + +static object_methods extvol_methods = { + (void (*)(void *, void *))(box_intersect), + (void (*)(void *, void *, void *, void *))(box_normal), + extvol_bbox, + free +}; + +extvol * newextvol(void * voidtex, vector min, vector max, + int samples, flt (* evaluator)(flt, flt, flt)) { + extvol * xvol; + texture * tex; + + tex = (texture *) voidtex; + + xvol = (extvol *) rt_getmem(sizeof(extvol)); + memset(xvol, 0, sizeof(extvol)); + + xvol->methods = &extvol_methods; + + xvol->min=min; + xvol->max=max; + xvol->evaluator = evaluator; + xvol->ambient = tex->ambient; + xvol->diffuse = tex->diffuse; + xvol->opacity = tex->opacity; + xvol->samples = samples; + + xvol->tex = (texture *)rt_getmem(sizeof(texture)); + memset(xvol->tex, 0, sizeof(texture)); + + xvol->tex->ctr.x = 0.0; + xvol->tex->ctr.y = 0.0; + xvol->tex->ctr.z = 0.0; + xvol->tex->rot = xvol->tex->ctr; + xvol->tex->scale = xvol->tex->ctr; + xvol->tex->uaxs = xvol->tex->ctr; + xvol->tex->vaxs = xvol->tex->ctr; + xvol->tex->islight = 0; + xvol->tex->shadowcast = 0; + + xvol->tex->col=tex->col; + xvol->tex->ambient=1.0; + xvol->tex->diffuse=0.0; + xvol->tex->specular=0.0; + xvol->tex->opacity=1.0; + xvol->tex->img=NULL; + xvol->tex->texfunc=(color(*)(void *, void *, void *))(ext_volume_texture); + xvol->tex->obj = (void *) xvol; /* XXX hack! */ + + return xvol; +} + +color ExtVoxelColor(flt scalar) { + color col; + + if (scalar > 1.0) + scalar = 1.0; + + if (scalar < 0.0) + scalar = 0.0; + + if (scalar < 0.5) { + col.g = 0.0; + } + else { + col.g = (scalar - 0.5) * 2.0; + } + + col.r = scalar; + col.b = 1.0 - (scalar / 2.0); + + return col; +} + +color ext_volume_texture(vector * hit, texture * tex, ray * ry) { + color col, col2; + box * bx; + extvol * xvol; + flt a, tx1, tx2, ty1, ty2, tz1, tz2; + flt tnear, tfar; + flt t, tdist, dt, ddt, sum, tt; + vector pnt, bln; + flt scalar, transval; + int i; + point_light * li; + color diffint; + vector N, L; + flt inten; + + col.r = 0.0; + col.g = 0.0; + col.b = 0.0; + + bx = (box *) tex->obj; + xvol = (extvol *) tex->obj; + + tnear= -FHUGE; + tfar= FHUGE; + + if (ry->d.x == 0.0) { + if ((ry->o.x < bx->min.x) || (ry->o.x > bx->max.x)) return col; + } + else { + tx1 = (bx->min.x - ry->o.x) / ry->d.x; + tx2 = (bx->max.x - ry->o.x) / ry->d.x; + if (tx1 > tx2) { a=tx1; tx1=tx2; tx2=a; } + if (tx1 > tnear) tnear=tx1; + if (tx2 < tfar) tfar=tx2; + } + if (tnear > tfar) return col; + if (tfar < 0.0) return col; + + if (ry->d.y == 0.0) { + if ((ry->o.y < bx->min.y) || (ry->o.y > bx->max.y)) return col; + } + else { + ty1 = (bx->min.y - ry->o.y) / ry->d.y; + ty2 = (bx->max.y - ry->o.y) / ry->d.y; + if (ty1 > ty2) { a=ty1; ty1=ty2; ty2=a; } + if (ty1 > tnear) tnear=ty1; + if (ty2 < tfar) tfar=ty2; + } + if (tnear > tfar) return col; + if (tfar < 0.0) return col; + + if (ry->d.z == 0.0) { + if ((ry->o.z < bx->min.z) || (ry->o.z > bx->max.z)) return col; + } + else { + tz1 = (bx->min.z - ry->o.z) / ry->d.z; + tz2 = (bx->max.z - ry->o.z) / ry->d.z; + if (tz1 > tz2) { a=tz1; tz1=tz2; tz2=a; } + if (tz1 > tnear) tnear=tz1; + if (tz2 < tfar) tfar=tz2; + } + if (tnear > tfar) return col; + if (tfar < 0.0) return col; + + if (tnear < 0.0) tnear=0.0; + + tdist = xvol->samples; + + tt = (xvol->opacity / tdist); + + bln.x=fabs(bx->min.x - bx->max.x); + bln.y=fabs(bx->min.y - bx->max.y); + bln.z=fabs(bx->min.z - bx->max.z); + + dt = 1.0 / tdist; + sum = 0.0; + +/* Accumulate color as the ray passes through the voxels */ + for (t=tnear; t<=tfar; t+=dt) { + if (sum < 1.0) { + pnt.x=((ry->o.x + (ry->d.x * t)) - bx->min.x) / bln.x; + pnt.y=((ry->o.y + (ry->d.y * t)) - bx->min.y) / bln.y; + pnt.z=((ry->o.z + (ry->d.z * t)) - bx->min.z) / bln.z; + + /* call external evaluator assume 0.0 -> 1.0 range.. */ + scalar = xvol->evaluator(pnt.x, pnt.y, pnt.z); + + transval = tt * scalar; + sum += transval; + + col2 = ExtVoxelColor(scalar); + + col.r += transval * col2.r * xvol->ambient; + col.g += transval * col2.g * xvol->ambient; + col.b += transval * col2.b * xvol->ambient; + + ddt = dt; + + /* Add in diffuse shaded light sources (no shadows) */ + if (xvol->diffuse > 0.0) { + + /* Calculate the Volume gradient at the voxel */ + N.x = (xvol->evaluator(pnt.x - ddt, pnt.y, pnt.z) - + xvol->evaluator(pnt.x + ddt, pnt.y, pnt.z)) * 8.0 * tt; + + N.y = (xvol->evaluator(pnt.x, pnt.y - ddt, pnt.z) - + xvol->evaluator(pnt.x, pnt.y + ddt, pnt.z)) * 8.0 * tt; + + N.z = (xvol->evaluator(pnt.x, pnt.y, pnt.z - ddt) - + xvol->evaluator(pnt.x, pnt.y, pnt.z + ddt)) * 8.0 * tt; + + /* only light surfaces with enough of a normal.. */ + if ((N.x*N.x + N.y*N.y + N.z*N.z) > 0.0) { + diffint.r = 0.0; + diffint.g = 0.0; + diffint.b = 0.0; + + /* add the contribution of each of the lights.. */ + for (i=0; ictr, (*hit), L) + VNorm(&L); + VDOT(inten, N, L) + + /* only add light if its from the front of the surface */ + /* could add back-lighting if we wanted to later.. */ + if (inten > 0.0) { + diffint.r += inten*li->tex->col.r; + diffint.g += inten*li->tex->col.g; + diffint.b += inten*li->tex->col.b; + } + } + col.r += col2.r * diffint.r * xvol->diffuse; + col.g += col2.g * diffint.g * xvol->diffuse; + col.b += col2.b * diffint.b * xvol->diffuse; + } + } + } + else { + sum=1.0; + } + } + + /* Add in transmitted ray from outside environment */ + if (sum < 1.0) { /* spawn transmission rays / refraction */ + color transcol; + + transcol = shade_transmission(ry, hit, 1.0 - sum); + + col.r += transcol.r; /* add the transmitted ray */ + col.g += transcol.g; /* to the diffuse and */ + col.b += transcol.b; /* transmission total.. */ + } + + return col; +} + + + diff --git a/src/tbb/examples/parallel_for/tachyon/src/extvol.h b/src/tbb/examples/parallel_for/tachyon/src/extvol.h new file mode 100644 index 0000000..e973278 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/extvol.h @@ -0,0 +1,81 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * vol.h - Volume rendering definitions etc. + * + * + * $Id: extvol.h,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +typedef struct { + unsigned int id; /* Unique Object serial number */ + void * nextobj; /* pointer to next object in list */ + object_methods * methods; /* this object's methods */ + texture * tex; /* object texture */ + vector min; + vector max; + flt ambient; + flt diffuse; + flt opacity; + int samples; + flt (* evaluator)(flt, flt, flt); +} extvol; + +extvol * newextvol(void * voidtex, vector min, vector max, + int samples, flt (* evaluator)(flt, flt, flt)); +color ext_volume_texture(vector *, texture *, ray *); diff --git a/src/tbb/examples/parallel_for/tachyon/src/global.cpp b/src/tbb/examples/parallel_for/tachyon/src/global.cpp new file mode 100644 index 0000000..05d4be1 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/global.cpp @@ -0,0 +1,85 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * global.c - any/all global data items etc should be in this file + * + * $Id: global.cpp,v 1.2 2007-02-22 17:54:15 Exp $ + * + */ + +#include "types.h" +#include "machine.h" +#include "sphere.h" +#include "light.h" + +/* stuff moved from intersect.c */ +object * rootobj = NULL; /* starts out empty. */ + +point_light * lightlist[MAXLIGHTS]; +int numlights = 0; + +unsigned int numobjects = 0; /* used to assign unique object ID's */ + +/* used in util.c */ +unsigned int rt_mem_in_use = 0; + +/* used in api.c */ +int parinitted = 0; + +int graphicswindowopen = 0; + diff --git a/src/tbb/examples/parallel_for/tachyon/src/global.h b/src/tbb/examples/parallel_for/tachyon/src/global.h new file mode 100644 index 0000000..ebfbc95 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/global.h @@ -0,0 +1,76 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * global.h - any/all global data items etc should be in this file + * + * $Id: global.h,v 1.2 2007-02-22 17:54:15 Exp $ + * + */ + +/* stuff moved from intersect.c */ +extern object * rootobj; + +extern point_light * lightlist[MAXLIGHTS]; +extern int numlights; + +extern unsigned int numobjects; + +extern unsigned int rt_mem_in_use; +extern int parinitted; + +extern int graphicswindowopen; diff --git a/src/tbb/examples/parallel_for/tachyon/src/grid.cpp b/src/tbb/examples/parallel_for/tachyon/src/grid.cpp new file mode 100644 index 0000000..b96989d --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/grid.cpp @@ -0,0 +1,690 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * grid.c - spatial subdivision efficiency structures + * + * $Id: grid.cpp,v 1.2 2007-02-22 17:54:15 Exp $ + * + */ + +#include "machine.h" +#include "types.h" +#include "macros.h" +#include "vector.h" +#include "intersect.h" +#include "util.h" + +#define GRID_PRIVATE +#include "grid.h" + +#ifndef cbrt +#define cbrt(x) ((x) > 0.0 ? pow((double)(x), 1.0/3.0) : \ + ((x) < 0.0 ? -pow((double)-(x), 1.0/3.0) : 0.0)) + +#define qbrt(x) ((x) > 0.0 ? pow((double)(x), 1.0/4.0) : \ + ((x) < 0.0 ? -pow((double)-(x), 1.0/4.0) : 0.0)) + +#endif + +static object_methods grid_methods = { + (void (*)(void *, void *))(grid_intersect), + (void (*)(void *, void *, void *, void *))(NULL), + grid_bbox, + grid_free +}; + +extern bool silent_mode; + +object * newgrid(int xsize, int ysize, int zsize, vector min, vector max) { + grid * g; + + g = (grid *) rt_getmem(sizeof(grid)); + memset(g, 0, sizeof(grid)); + + g->methods = &grid_methods; + g->id = new_objectid(); + + g->xsize = xsize; + g->ysize = ysize; + g->zsize = zsize; + + g->min = min; + g->max = max; + + VSub(&g->max, &g->min, &g->voxsize); + g->voxsize.x /= (flt) g->xsize; + g->voxsize.y /= (flt) g->ysize; + g->voxsize.z /= (flt) g->zsize; + + g->cells = (objectlist **) rt_getmem(xsize*ysize*zsize*sizeof(objectlist *)); + memset(g->cells, 0, xsize*ysize*zsize * sizeof(objectlist *)); + +/* fprintf(stderr, "New grid, size: %8d %8d %8d\n", g->xsize, g->ysize, g->zsize); */ + + return (object *) g; +} + +static int grid_bbox(void * obj, vector * min, vector * max) { + grid * g = (grid *) obj; + + *min = g->min; + *max = g->max; + + return 1; +} + +static void grid_free(void * v) { + int i, numvoxels; + grid * g = (grid *) v; + + /* loop through all voxels and free the object lists */ + numvoxels = g->xsize * g->ysize * g->zsize; + for (i=0; icells[i]; + while (lcur != NULL) { + lnext = lcur->next; + free(lcur); + } + } + + /* free the grid cells */ + free(g->cells); + + /* free all objects on the grid object list */ + free_objects(g->objects); + + free(g); +} + +static void globalbound(object ** rootlist, vector * gmin, vector * gmax) { + vector min, max; + object * cur; + + if (*rootlist == NULL) /* don't bound non-existant objects */ + return; + + gmin->x = FHUGE; gmin->y = FHUGE; gmin->z = FHUGE; + gmax->x = -FHUGE; gmax->y = -FHUGE; gmax->z = -FHUGE; + + cur=*rootlist; + while (cur != NULL) { /* Go! */ + min.x = -FHUGE; min.y = -FHUGE; min.z = -FHUGE; + max.x = FHUGE; max.y = FHUGE; max.z = FHUGE; + + if (cur->methods->bbox((void *) cur, &min, &max)) { + gmin->x = MYMIN( gmin->x , min.x); + gmin->y = MYMIN( gmin->y , min.y); + gmin->z = MYMIN( gmin->z , min.z); + + gmax->x = MYMAX( gmax->x , max.x); + gmax->y = MYMAX( gmax->y , max.y); + gmax->z = MYMAX( gmax->z , max.z); + } + + cur=(object *)cur->nextobj; + } +} + + +static int cellbound(grid *g, gridindex *index, vector * cmin, vector * cmax) { + vector min, max, cellmin, cellmax; + objectlist * cur; + int numinbounds = 0; + + cur = g->cells[index->z*g->xsize*g->ysize + index->y*g->xsize + index->x]; + + if (cur == NULL) /* don't bound non-existant objects */ + return 0; + + cellmin.x = voxel2x(g, index->x); + cellmin.y = voxel2y(g, index->y); + cellmin.z = voxel2z(g, index->z); + + cellmax.x = cellmin.x + g->voxsize.x; + cellmax.y = cellmin.y + g->voxsize.y; + cellmax.z = cellmin.z + g->voxsize.z; + + cmin->x = FHUGE; cmin->y = FHUGE; cmin->z = FHUGE; + cmax->x = -FHUGE; cmax->y = -FHUGE; cmax->z = -FHUGE; + + while (cur != NULL) { /* Go! */ + min.x = -FHUGE; min.y = -FHUGE; min.z = -FHUGE; + max.x = FHUGE; max.y = FHUGE; max.z = FHUGE; + + if (cur->obj->methods->bbox((void *) cur->obj, &min, &max)) { + if ((min.x >= cellmin.x) && (max.x <= cellmax.x) && + (min.y >= cellmin.y) && (max.y <= cellmax.y) && + (min.z >= cellmin.z) && (max.z <= cellmax.z)) { + + cmin->x = MYMIN( cmin->x , min.x); + cmin->y = MYMIN( cmin->y , min.y); + cmin->z = MYMIN( cmin->z , min.z); + + cmax->x = MYMAX( cmax->x , max.x); + cmax->y = MYMAX( cmax->y , max.y); + cmax->z = MYMAX( cmax->z , max.z); + + numinbounds++; + } + } + + cur=cur->next; + } + + /* in case we get a 0.0 sized axis on the cell bounds, we'll */ + /* use the original cell bounds */ + if ((cmax->x - cmin->x) < EPSILON) { + cmax->x += EPSILON; + cmin->x -= EPSILON; + } + if ((cmax->y - cmin->y) < EPSILON) { + cmax->y += EPSILON; + cmin->y -= EPSILON; + } + if ((cmax->z - cmin->z) < EPSILON) { + cmax->z += EPSILON; + cmin->z -= EPSILON; + } + + return numinbounds; +} + +static int countobj(object * root) { + object * cur; /* counts the number of objects on a list */ + int numobj; + + numobj=0; + cur=root; + + while (cur != NULL) { + cur=(object *)cur->nextobj; + numobj++; + } + return numobj; +} + +static int countobjlist(objectlist * root) { + objectlist * cur; + int numobj; + + numobj=0; + cur = root; + + while (cur != NULL) { + cur = cur->next; + numobj++; + } + return numobj; +} + +int engrid_scene(object ** list) { + grid * g; + int numobj, numcbrt; + vector gmin, gmax; + gridindex index; + + if (*list == NULL) + return 0; + + numobj = countobj(*list); + + if ( !silent_mode ) + fprintf(stderr, "Scene contains %d bounded objects.\n", numobj); + + if (numobj > 16) { + numcbrt = (int) cbrt(4*numobj); + globalbound(list, &gmin, &gmax); + + g = (grid *) newgrid(numcbrt, numcbrt, numcbrt, gmin, gmax); + engrid_objlist(g, list); + + numobj = countobj(*list); + g->nextobj = *list; + *list = (object *) g; + + /* now create subgrids.. */ + for (index.z=0; index.zzsize; index.z++) { + for (index.y=0; index.yysize; index.y++) { + for (index.x=0; index.xxsize; index.x++) { + engrid_cell(g, &index); + } + } + } + } + + return 1; +} + + +void engrid_objlist(grid * g, object ** list) { + object * cur, * next, **prev; + + if (*list == NULL) + return; + + prev = list; + cur = *list; + + while (cur != NULL) { + next = (object *)cur->nextobj; + + if (engrid_object(g, cur)) + *prev = next; + else + prev = (object **) &cur->nextobj; + + cur = next; + } +} + +static int engrid_cell(grid * gold, gridindex *index) { + vector gmin, gmax, gsize; + flt len; + int numobj, numcbrt, xs, ys, zs; + grid * g; + objectlist **list; + objectlist * newobj; + + list = &gold->cells[index->z*gold->xsize*gold->ysize + + index->y*gold->xsize + index->x]; + + if (*list == NULL) + return 0; + + numobj = cellbound(gold, index, &gmin, &gmax); + + VSub(&gmax, &gmin, &gsize); + len = 1.0 / (MYMAX( MYMAX(gsize.x, gsize.y), gsize.z )); + gsize.x *= len; + gsize.y *= len; + gsize.z *= len; + + if (numobj > 16) { + numcbrt = (int) cbrt(2*numobj); + + xs = (int) ((flt) numcbrt * gsize.x); + if (xs < 1) xs = 1; + ys = (int) ((flt) numcbrt * gsize.y); + if (ys < 1) ys = 1; + zs = (int) ((flt) numcbrt * gsize.z); + if (zs < 1) zs = 1; + + g = (grid *) newgrid(xs, ys, zs, gmin, gmax); + engrid_objectlist(g, list); + + newobj = (objectlist *) rt_getmem(sizeof(objectlist)); + newobj->obj = (object *) g; + newobj->next = *list; + *list = newobj; + + g->nextobj = gold->objects; + gold->objects = (object *) g; + } + + return 1; +} + +static int engrid_objectlist(grid * g, objectlist ** list) { + objectlist * cur, * next, **prev; + int numsucceeded = 0; + + if (*list == NULL) + return 0; + + prev = list; + cur = *list; + + while (cur != NULL) { + next = cur->next; + + if (engrid_object(g, cur->obj)) { + *prev = next; + free(cur); + numsucceeded++; + } + else { + prev = &cur->next; + } + + cur = next; + } + + return numsucceeded; +} + + + +static int engrid_object(grid * g, object * obj) { + vector omin, omax; + gridindex low, high; + int x, y, z, zindex, yindex, voxindex; + objectlist * tmp; + + if (obj->methods->bbox(obj, &omin, &omax)) { + if (!pos2grid(g, &omin, &low) || !pos2grid(g, &omax, &high)) { + return 0; /* object is not wholly contained in the grid */ + } + } + else { + return 0; /* object is unbounded */ + } + + /* add the object to the complete list of objects in the grid */ + obj->nextobj = g->objects; + g->objects = obj; + + /* add this object to all voxels it inhabits */ + for (z=low.z; z<=high.z; z++) { + zindex = z * g->xsize * g->ysize; + for (y=low.y; y<=high.y; y++) { + yindex = y * g->xsize; + for (x=low.x; x<=high.x; x++) { + voxindex = x + yindex + zindex; + tmp = (objectlist *) rt_getmem(sizeof(objectlist)); + tmp->next = g->cells[voxindex]; + tmp->obj = obj; + g->cells[voxindex] = tmp; + } + } + } + + return 1; +} + +static int pos2grid(grid * g, vector * pos, gridindex * index) { + index->x = (int) ((pos->x - g->min.x) / g->voxsize.x); + index->y = (int) ((pos->y - g->min.y) / g->voxsize.y); + index->z = (int) ((pos->z - g->min.z) / g->voxsize.z); + + if (index->x == g->xsize) + index->x--; + if (index->y == g->ysize) + index->y--; + if (index->z == g->zsize) + index->z--; + + if (index->x < 0 || index->x > g->xsize || + index->y < 0 || index->y > g->ysize || + index->z < 0 || index->z > g->zsize) + return 0; + + if (pos->x < g->min.x || pos->x > g->max.x || + pos->y < g->min.y || pos->y > g->max.y || + pos->z < g->min.z || pos->z > g->max.z) + return 0; + + return 1; +} + + +/* the real thing */ +static void grid_intersect(grid * g, ray * ry) { + flt tnear, tfar, offset; + vector curpos, tmax, tdelta, pdeltaX, pdeltaY, pdeltaZ, nXp, nYp, nZp; + gridindex curvox, step, out; + int voxindex; + objectlist * cur; + + if (ry->flags & RT_RAY_FINISHED) + return; + + if (!grid_bounds_intersect(g, ry, &tnear, &tfar)) + return; + + if (ry->maxdist < tnear) + return; + + curpos = Raypnt(ry, tnear); + pos2grid(g, &curpos, &curvox); + offset = tnear; + + /* Setup X iterator stuff */ + if (fabs(ry->d.x) < EPSILON) { + tmax.x = FHUGE; + tdelta.x = 0.0; + step.x = 0; + out.x = 0; /* never goes out of bounds on this axis */ + } + else if (ry->d.x < 0.0) { + tmax.x = offset + ((voxel2x(g, curvox.x) - curpos.x) / ry->d.x); + tdelta.x = g->voxsize.x / - ry->d.x; + step.x = out.x = -1; + } + else { + tmax.x = offset + ((voxel2x(g, curvox.x + 1) - curpos.x) / ry->d.x); + tdelta.x = g->voxsize.x / ry->d.x; + step.x = 1; + out.x = g->xsize; + } + + /* Setup Y iterator stuff */ + if (fabs(ry->d.y) < EPSILON) { + tmax.y = FHUGE; + tdelta.y = 0.0; + step.y = 0; + out.y = 0; /* never goes out of bounds on this axis */ + } + else if (ry->d.y < 0.0) { + tmax.y = offset + ((voxel2y(g, curvox.y) - curpos.y) / ry->d.y); + tdelta.y = g->voxsize.y / - ry->d.y; + step.y = out.y = -1; + } + else { + tmax.y = offset + ((voxel2y(g, curvox.y + 1) - curpos.y) / ry->d.y); + tdelta.y = g->voxsize.y / ry->d.y; + step.y = 1; + out.y = g->ysize; + } + + /* Setup Z iterator stuff */ + if (fabs(ry->d.z) < EPSILON) { + tmax.z = FHUGE; + tdelta.z = 0.0; + step.z = 0; + out.z = 0; /* never goes out of bounds on this axis */ + } + else if (ry->d.z < 0.0) { + tmax.z = offset + ((voxel2z(g, curvox.z) - curpos.z) / ry->d.z); + tdelta.z = g->voxsize.z / - ry->d.z; + step.z = out.z = -1; + } + else { + tmax.z = offset + ((voxel2z(g, curvox.z + 1) - curpos.z) / ry->d.z); + tdelta.z = g->voxsize.z / ry->d.z; + step.z = 1; + out.z = g->zsize; + } + + pdeltaX = ry->d; + VScale(&pdeltaX, tdelta.x); + pdeltaY = ry->d; + VScale(&pdeltaY, tdelta.y); + pdeltaZ = ry->d; + VScale(&pdeltaZ, tdelta.z); + + nXp = Raypnt(ry, tmax.x); + nYp = Raypnt(ry, tmax.y); + nZp = Raypnt(ry, tmax.z); + + voxindex = curvox.z*g->xsize*g->ysize + curvox.y*g->xsize + curvox.x; + while (1) { + if (tmax.x < tmax.y && tmax.x < tmax.z) { + cur = g->cells[voxindex]; + while (cur != NULL) { + if (ry->mbox[cur->obj->id] != ry->serial) { + ry->mbox[cur->obj->id] = ry->serial; + cur->obj->methods->intersect(cur->obj, ry); + } + cur = cur->next; + } + curvox.x += step.x; + if (ry->maxdist < tmax.x || curvox.x == out.x) + break; + voxindex += step.x; + tmax.x += tdelta.x; + curpos = nXp; + nXp.x += pdeltaX.x; + nXp.y += pdeltaX.y; + nXp.z += pdeltaX.z; + } + else if (tmax.z < tmax.y) { + cur = g->cells[voxindex]; + while (cur != NULL) { + if (ry->mbox[cur->obj->id] != ry->serial) { + ry->mbox[cur->obj->id] = ry->serial; + cur->obj->methods->intersect(cur->obj, ry); + } + cur = cur->next; + } + curvox.z += step.z; + if (ry->maxdist < tmax.z || curvox.z == out.z) + break; + voxindex += step.z*g->xsize*g->ysize; + tmax.z += tdelta.z; + curpos = nZp; + nZp.x += pdeltaZ.x; + nZp.y += pdeltaZ.y; + nZp.z += pdeltaZ.z; + } + else { + cur = g->cells[voxindex]; + while (cur != NULL) { + if (ry->mbox[cur->obj->id] != ry->serial) { + ry->mbox[cur->obj->id] = ry->serial; + cur->obj->methods->intersect(cur->obj, ry); + } + cur = cur->next; + } + curvox.y += step.y; + if (ry->maxdist < tmax.y || curvox.y == out.y) + break; + voxindex += step.y*g->xsize; + tmax.y += tdelta.y; + curpos = nYp; + nYp.x += pdeltaY.x; + nYp.y += pdeltaY.y; + nYp.z += pdeltaY.z; + } + + if (ry->flags & RT_RAY_FINISHED) + break; + } +} + +static void voxel_intersect(grid * g, ray * ry, int voxindex) { + objectlist * cur; + + cur = g->cells[voxindex]; + while (cur != NULL) { + cur->obj->methods->intersect(cur->obj, ry); + cur = cur->next; + } +} + +static int grid_bounds_intersect(grid * g, ray * ry, flt *nr, flt *fr) { + flt a, tx1, tx2, ty1, ty2, tz1, tz2; + flt tnear, tfar; + + tnear= -FHUGE; + tfar= FHUGE; + + if (ry->d.x == 0.0) { + if ((ry->o.x < g->min.x) || (ry->o.x > g->max.x)) return 0; + } + else { + tx1 = (g->min.x - ry->o.x) / ry->d.x; + tx2 = (g->max.x - ry->o.x) / ry->d.x; + if (tx1 > tx2) { a=tx1; tx1=tx2; tx2=a; } + if (tx1 > tnear) tnear=tx1; + if (tx2 < tfar) tfar=tx2; + } + if (tnear > tfar) return 0; + if (tfar < 0.0) return 0; + + if (ry->d.y == 0.0) { + if ((ry->o.y < g->min.y) || (ry->o.y > g->max.y)) return 0; + } + else { + ty1 = (g->min.y - ry->o.y) / ry->d.y; + ty2 = (g->max.y - ry->o.y) / ry->d.y; + if (ty1 > ty2) { a=ty1; ty1=ty2; ty2=a; } + if (ty1 > tnear) tnear=ty1; + if (ty2 < tfar) tfar=ty2; + } + if (tnear > tfar) return 0; + if (tfar < 0.0) return 0; + + if (ry->d.z == 0.0) { + if ((ry->o.z < g->min.z) || (ry->o.z > g->max.z)) return 0; + } + else { + tz1 = (g->min.z - ry->o.z) / ry->d.z; + tz2 = (g->max.z - ry->o.z) / ry->d.z; + if (tz1 > tz2) { a=tz1; tz1=tz2; tz2=a; } + if (tz1 > tnear) tnear=tz1; + if (tz2 < tfar) tfar=tz2; + } + if (tnear > tfar) return 0; + if (tfar < 0.0) return 0; + + *nr = tnear; + *fr = tfar; + return 1; +} diff --git a/src/tbb/examples/parallel_for/tachyon/src/grid.h b/src/tbb/examples/parallel_for/tachyon/src/grid.h new file mode 100644 index 0000000..3670313 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/grid.h @@ -0,0 +1,128 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * grid.h - spatial subdivision efficiency structures + * + * $Id: grid.h,v 1.2 2007-02-22 17:54:15 Exp $ + * + */ + +int engrid_scene(object ** list); +object * newgrid(int xsize, int ysize, int zsize, vector min, vector max); + +#ifdef GRID_PRIVATE + +typedef struct objectlist { + struct objectlist * next; /* next link in the list */ + object * obj; /* the actual object */ +} objectlist; + +typedef struct { + unsigned int id; /* Unique Object serial number */ + void * nextobj; /* pointer to next object in list */ + object_methods * methods; /* this object's methods */ + texture * tex; /* object texture */ + int xsize; /* number of cells along the X direction */ + int ysize; /* number of cells along the Y direction */ + int zsize; /* number of cells along the Z direction */ + vector min; /* the minimum coords for the box containing the grid */ + vector max; /* the maximum coords for the box containing the grid */ + vector voxsize; /* the size of a grid cell/voxel */ + object * objects; /* all objects contained in the grid */ + objectlist ** cells; /* the grid cells themselves */ +} grid; + +typedef struct { + int x; /* Voxel X address */ + int y; /* Voxel Y address */ + int z; /* Voxel Z address */ +} gridindex; + +/* + * Convert from voxel number along X/Y/Z to corresponding coordinate. + */ +#define voxel2x(g,X) ((X) * (g->voxsize.x) + (g->min.x)) +#define voxel2y(g,Y) ((Y) * (g->voxsize.y) + (g->min.y)) +#define voxel2z(g,Z) ((Z) * (g->voxsize.z) + (g->min.z)) + +/* + * And vice-versa. + */ +#define x2voxel(g,x) (((x) - g->min.x) / g->voxsize.x) +#define y2voxel(g,y) (((y) - g->min.y) / g->voxsize.y) +#define z2voxel(g,z) (((z) - g->min.z) / g->voxsize.z) + + +static int grid_bbox(void * obj, vector * min, vector * max); +static void grid_free(void * v); + +static int cellbound(grid *g, gridindex *index, vector * cmin, vector * cmax); + +void engrid_objlist(grid * g, object ** list); +static int engrid_object(grid * g, object * obj); + +static int engrid_objectlist(grid * g, objectlist ** list); +static int engrid_cell(grid *, gridindex *); + +static int pos2grid(grid * g, vector * pos, gridindex * index); +static void grid_intersect(grid *, ray *); +static void voxel_intersect(grid * g, ray * ry, int voxaddr); +static int grid_bounds_intersect(grid * g, ray * ry, flt *near, flt *far); + + +#endif diff --git a/src/tbb/examples/parallel_for/tachyon/src/imageio.cpp b/src/tbb/examples/parallel_for/tachyon/src/imageio.cpp new file mode 100644 index 0000000..f405418 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/imageio.cpp @@ -0,0 +1,157 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * imageio.c - This file deals with reading/writing image files + * + * $Id: imageio.cpp,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +/* For our puposes, we're interested only in the 3 byte per pixel 24 bit + * truecolor sort of file.. + */ + +#include +#include "machine.h" +#include "types.h" +#include "util.h" +#include "imageio.h" +#include "ppm.h" /* PPM files */ +#include "tgafile.h" /* Truevision Targa files */ +#include "jpeg.h" /* JPEG files */ + +static +int fakeimage(char * name, int * xres, int * yres, unsigned char ** imgdata) { + int i, imgsize; + + fprintf(stderr, "Error loading image %s. Faking it.\n", name); + + *xres = 2; + *yres = 2; + imgsize = 3 * (*xres) * (*yres); + *imgdata = (unsigned char *)rt_getmem(imgsize); + for (i=0; iname; + + if (strstr(name, ".ppm")) { + rc = readppm(name, &xres, &yres, &imgdata); + } + else if (strstr(name, ".tga")) { + rc = readtga(name, &xres, &yres, &imgdata); + } + else if (strstr(name, ".jpg")) { + rc = readjpeg(name, &xres, &yres, &imgdata); + } + else if (strstr(name, ".gif")) { + rc = IMAGEUNSUP; + } + else if (strstr(name, ".png")) { + rc = IMAGEUNSUP; + } + else if (strstr(name, ".tiff")) { + rc = IMAGEUNSUP; + } + else if (strstr(name, ".rgb")) { + rc = IMAGEUNSUP; + } + else if (strstr(name, ".xpm")) { + rc = IMAGEUNSUP; + } + else { + rc = readppm(name, &xres, &yres, &imgdata); + } + + switch (rc) { + case IMAGEREADERR: + fprintf(stderr, "Short read encountered while loading image %s\n", name); + rc = IMAGENOERR; /* remap to non-fatal error */ + break; + + case IMAGEUNSUP: + fprintf(stderr, "Cannot read unsupported image format for image %s\n", name); + break; + } + + /* If the image load failed, create a tiny white colored image to fake it */ + /* this allows a scene to render even when a file can't be loaded */ + if (rc != IMAGENOERR) { + rc = fakeimage(name, &xres, &yres, &imgdata); + } + + /* If we succeeded in loading the image, return it. */ + if (rc == IMAGENOERR) { + img->xres = xres; + img->yres = yres; + img->bpp = 3; + img->data = imgdata; + } + + return rc; +} + + diff --git a/src/tbb/examples/parallel_for/tachyon/src/imageio.h b/src/tbb/examples/parallel_for/tachyon/src/imageio.h new file mode 100644 index 0000000..f28117e --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/imageio.h @@ -0,0 +1,73 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * imageio.h - This file deals with reading/writing image files + * + * $Id: imageio.h,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +/* For our puposes, we're interested only in the 3 byte per pixel 24 bit + truecolor sort of file.. */ + +#define IMAGENOERR 0 /* no error */ +#define IMAGEBADFILE 1 /* can't find or can't open the file */ +#define IMAGEUNSUP 2 /* the image file is an unsupported format */ +#define IMAGEALLOCERR 3 /* not enough remaining memory to load this image */ +#define IMAGEREADERR 4 /* failed read, short reads etc */ + +int readimage(rawimage *); diff --git a/src/tbb/examples/parallel_for/tachyon/src/imap.cpp b/src/tbb/examples/parallel_for/tachyon/src/imap.cpp new file mode 100644 index 0000000..663be61 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/imap.cpp @@ -0,0 +1,177 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * imap.c - This file contains code for doing image map type things. + * + * $Id: imap.cpp,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +#include "machine.h" +#include "types.h" +#include "imap.h" +#include "util.h" +#include "imageio.h" + +rawimage * imagelist[MAXIMGS]; +int numimages; + +void ResetImages(void) { + int i; + numimages=0; + for (i=0; iloaded) { + readimage(image); + image->loaded=1; + } +} + +color ImageMap(rawimage * image, flt u, flt v) { + color col, colx, colx2; + flt x,y, px, py; + int x1, x2, y1, y2; + unsigned char * ptr; + unsigned char * ptr2; + + if (!image->loaded) { + LoadImage(image); + image->loaded=1; + } + + if ((u <= 1.0) && (u >=0.0) && (v <= 1.0) && (v >= 0.0)) { + x=(image->xres - 1.0) * u; /* floating point X location */ + y=(image->yres - 1.0) * v; /* floating point Y location */ + + px = x - ((int) x); + py = y - ((int) y); + + x1 = (int) x; + x2 = x1 + 1; + + y1 = (int) y; + y2 = y1 + 1; + + ptr = image->data + ((image->xres * y1) + x1) * 3; + ptr2 = image->data + ((image->xres * y1) + x2) * 3; + + colx.r = (flt) ((flt)ptr[0] + px*((flt)ptr2[0] - (flt) ptr[0])) / 255.0; + colx.g = (flt) ((flt)ptr[1] + px*((flt)ptr2[1] - (flt) ptr[1])) / 255.0; + colx.b = (flt) ((flt)ptr[2] + px*((flt)ptr2[2] - (flt) ptr[2])) / 255.0; + + ptr = image->data + ((image->xres * y2) + x1) * 3; + ptr2 = image->data + ((image->xres * y2) + x2) * 3; + + colx2.r = ((flt)ptr[0] + px*((flt)ptr2[0] - (flt)ptr[0])) / 255.0; + colx2.g = ((flt)ptr[1] + px*((flt)ptr2[1] - (flt)ptr[1])) / 255.0; + colx2.b = ((flt)ptr[2] + px*((flt)ptr2[2] - (flt)ptr[2])) / 255.0; + + col.r = colx.r + py*(colx2.r - colx.r); + col.g = colx.g + py*(colx2.g - colx.g); + col.b = colx.b + py*(colx2.b - colx.b); + + } + else { + col.r=0.0; + col.g=0.0; + col.b=0.0; + } + return col; +} + +rawimage * AllocateImage(char * filename) { + rawimage * newimage = NULL; + int i, len, intable; + + intable=0; + if (numimages!=0) { + for (i=0; iname)) { + newimage=imagelist[i]; + intable=1; + } + } + } + + if (!intable) { + newimage=(rawimage *)rt_getmem(sizeof(rawimage)); + newimage->loaded=0; + newimage->xres=0; + newimage->yres=0; + newimage->bpp=0; + newimage->data=NULL; + len=strlen(filename); + if (len > 80) rtbomb("Filename too long in image map!!"); + strcpy(newimage->name, filename); + + imagelist[numimages]=newimage; /* add new one to the table */ + numimages++; /* increment the number of images */ + } + + return newimage; +} + +void DeallocateImage(rawimage * image) { + image->loaded=0; + rt_freemem(image->data); +} + + diff --git a/src/tbb/examples/parallel_for/tachyon/src/imap.h b/src/tbb/examples/parallel_for/tachyon/src/imap.h new file mode 100644 index 0000000..824928b --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/imap.h @@ -0,0 +1,69 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * imap.h - This file contains defines etc for doing image map type things. + * + * $Id: imap.h,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +void ResetImage(void); +void LoadImage(rawimage *); +color ImageMap(rawimage *, flt, flt); +rawimage * AllocateImage(char *); +void DeallocateImage(rawimage *); +void ResetImages(void); diff --git a/src/tbb/examples/parallel_for/tachyon/src/intersect.cpp b/src/tbb/examples/parallel_for/tachyon/src/intersect.cpp new file mode 100644 index 0000000..8c719fd --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/intersect.cpp @@ -0,0 +1,187 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * intersect.c - This file contains code for CSG and intersection routines. + * + * $Id: intersect.cpp,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +#include "machine.h" +#include "types.h" +#include "intersect.h" +#include "light.h" +#include "util.h" +#include "global.h" + +unsigned int new_objectid(void) { + return numobjects++; /* global used to generate unique object ID's */ +} + +unsigned int max_objectid(void) { + return numobjects; +} + +void add_object(object * obj) { + object * objtemp; + + if (obj == NULL) + return; + + obj->id = new_objectid(); + + objtemp = rootobj; + rootobj = obj; + obj->nextobj = objtemp; +} + +void free_objects(object * start) { + object * cur; + object * cur2; + + cur=start; + while (cur->nextobj != NULL) { + cur2=(object *)cur->nextobj; + cur->methods->free(cur); + cur=cur2; + } + free(cur); + +} + +void reset_object(void) { + if (rootobj != NULL) + free_objects(rootobj); + + rootobj = NULL; + numobjects = 0; /* set number of objects back to 0 */ +} + +void intersect_objects(ray * intray) { + object * cur; + object temp; + + temp.nextobj = rootobj; /* setup the initial object pointers.. */ + cur = &temp; /* ready, set */ + + while ((cur=(object *)cur->nextobj) != NULL) + cur->methods->intersect(cur, intray); +} + +void reset_intersection(intersectstruct * intstruct) { + intstruct->num = 0; + intstruct->list[0].t = FHUGE; + intstruct->list[0].obj = NULL; + intstruct->list[1].t = FHUGE; + intstruct->list[1].obj = NULL; +} + +void add_intersection(flt t, object * obj, ray * ry) { + intersectstruct * intstruct = ry->intstruct; + + if (t > EPSILON) { + + /* if we hit something before maxdist update maxdist */ + if (t < ry->maxdist) { + ry->maxdist = t; + + /* if we hit *anything* before maxdist, and we're firing a */ + /* shadow ray, then we are finished ray tracing the shadow */ + if (ry->flags & RT_RAY_SHADOW) + ry->flags |= RT_RAY_FINISHED; + } + + intstruct->num++; + intstruct->list[intstruct->num].obj = obj; + intstruct->list[intstruct->num].t = t; + } +} + + +int closest_intersection(flt * t, object ** obj, intersectstruct * intstruct) { + int i; + *t=FHUGE; + + for (i=1; i<=intstruct->num; i++) { + if (intstruct->list[i].t < *t) { + *t=intstruct->list[i].t; + *obj=intstruct->list[i].obj; + } + } + + return intstruct->num; +} + +int shadow_intersection(intersectstruct * intstruct, flt maxdist) { + int i; + + if (intstruct->num > 0) { + for (i=1; i<=intstruct->num; i++) { + if ((intstruct->list[i].t < maxdist) && + (intstruct->list[i].obj->tex->shadowcast == 1)) { + return 1; + } + } + } + + return 0; +} + + + + + diff --git a/src/tbb/examples/parallel_for/tachyon/src/intersect.h b/src/tbb/examples/parallel_for/tachyon/src/intersect.h new file mode 100644 index 0000000..a783cc4 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/intersect.h @@ -0,0 +1,75 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * intersect.h - This file contains the declarations and defines for the + * functions that manage intersection, bounding and CSG.. + * + * $Id: intersect.h,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +unsigned int new_objectid(void); +unsigned int max_objectid(void); +void add_object(object *); +void reset_object(void); +void free_objects(object *); +void intersect_objects(ray *); +void reset_intersection(intersectstruct *); +void add_intersection(flt, object *, ray *); +int closest_intersection(flt *, object **, intersectstruct *); +int next_intersection(object **, object *, intersectstruct *); +int shadow_intersection(intersectstruct * intstruct, flt maxdist); diff --git a/src/tbb/examples/parallel_for/tachyon/src/jpeg.cpp b/src/tbb/examples/parallel_for/tachyon/src/jpeg.cpp new file mode 100644 index 0000000..d2c3a82 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/jpeg.cpp @@ -0,0 +1,139 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * jpeg.c - This file deals with JPEG format image files (reading/writing) + * + * $Id: jpeg.cpp,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +/* + * This code requires support from the Independent JPEG Group's libjpeg. + * For our puposes, we're interested only in the 3 byte per pixel 24 bit + * RGB output. Probably won't implement any decent checking at this point. + */ + +#include +#include "machine.h" +#include "types.h" +#include "util.h" +#include "imageio.h" /* error codes etc */ +#include "jpeg.h" /* the protos for this file */ + +#if !defined(USEJPEG) + +int readjpeg(char * name, int * xres, int * yres, unsigned char **imgdata) { + return IMAGEUNSUP; +} + +#else + +#include "jpeglib.h" /* the IJG jpeg library headers */ + +int readjpeg(char * name, int * xres, int * yres, unsigned char **imgdata) { + FILE * ifp; + struct jpeg_decompress_struct cinfo; /* JPEG decompression struct */ + struct jpeg_error_mgr jerr; /* JPEG Error handler */ + JSAMPROW row_pointer[1]; /* output row buffer */ + int row_stride; /* physical row width in output buf */ + + /* open input file before doing any JPEG decompression setup */ + if ((ifp = fopen(name, "rb")) == NULL) + return IMAGEBADFILE; /* Could not open image, return error */ + + /* + * Note: The Independent JPEG Group's library does not have a way + * of returning errors without the use of setjmp/longjmp. + * This is a problem in multi-threaded environment, since setjmp + * and longjmp are declared thread-unsafe by many vendors currently. + * For now, JPEG decompression errors will result in the "default" + * error handling provided by the JPEG library, which is an error + * message and a fatal call to exit(). I'll have to work around this + * or find a reasonably thread-safe way of doing setjmp/longjmp.. + */ + + cinfo.err = jpeg_std_error(&jerr); /* Set JPEG error handler to default */ + + jpeg_create_decompress(&cinfo); /* Create decompression context */ + jpeg_stdio_src(&cinfo, ifp); /* Set input mechanism to stdio type */ + jpeg_read_header(&cinfo, TRUE); /* Read the JPEG header for info */ + jpeg_start_decompress(&cinfo); /* Prepare for actual decompression */ + + *xres = cinfo.output_width; /* set returned image width */ + *yres = cinfo.output_height; /* set returned image height */ + + /* Calculate the size of a row in the image */ + row_stride = cinfo.output_width * cinfo.output_components; + + /* Allocate the image buffer which will be returned to the ray tracer */ + *imgdata = (unsigned char *) malloc(row_stride * cinfo.output_height); + + /* decompress the JPEG, one scanline at a time into the buffer */ + while (cinfo.output_scanline < cinfo.output_height) { + row_pointer[0] = &((*imgdata)[(cinfo.output_scanline)*row_stride]); + jpeg_read_scanlines(&cinfo, row_pointer, 1); + } + + jpeg_finish_decompress(&cinfo); /* Tell the JPEG library to cleanup */ + jpeg_destroy_decompress(&cinfo); /* Destroy JPEG decompression context */ + + fclose(ifp); /* Close the input file */ + + return IMAGENOERR; /* No fatal errors */ +} + +#endif diff --git a/src/tbb/examples/parallel_for/tachyon/src/jpeg.h b/src/tbb/examples/parallel_for/tachyon/src/jpeg.h new file mode 100644 index 0000000..d6b99dc --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/jpeg.h @@ -0,0 +1,64 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * jpeg.h - This file deals with JPEG format image files (reading/writing) + * + * $Id: jpeg.h,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +int readjpeg(char * name, int * xres, int * yres, unsigned char **imgdata); diff --git a/src/tbb/examples/parallel_for/tachyon/src/light.cpp b/src/tbb/examples/parallel_for/tachyon/src/light.cpp new file mode 100644 index 0000000..eac02a2 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/light.cpp @@ -0,0 +1,138 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * light.c - This file contains declarations and defines for light sources. + * + * $Id: light.cpp,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +#include "machine.h" +#include "types.h" +#include "macros.h" +#include "vector.h" +#include "intersect.h" +#include "util.h" + +#define LIGHT_PRIVATE +#include "light.h" + +static object_methods light_methods = { + (void (*)(void *, void *))(light_intersect), + (void (*)(void *, void *, void *, void *))(light_normal), + light_bbox, + free +}; + +point_light * newlight(void * tex, vector ctr, flt rad) { + point_light * l; + + l=(point_light *) rt_getmem(sizeof(point_light)); + memset(l, 0, sizeof(point_light)); + l->methods = &light_methods; + + l->tex=(texture *)tex; + l->ctr=ctr; + l->rad=rad; + + return l; +} + +static int light_bbox(void * obj, vector * min, vector * max) { + return 0; /* lights are unbounded currently */ +} + +static void light_intersect(point_light * l, ray * ry) { + flt b, disc, t1, t2, temp; + vector V; + + /* Lights do not cast shadows.. */ + if (ry->flags & RT_RAY_SHADOW) + return; + + VSUB(l->ctr, ry->o, V); + VDOT(b, V, ry->d); + VDOT(temp, V, V); + + disc=b*b + l->rad*l->rad - temp; + + if (disc<=0.0) return; + disc=sqrt(disc); + + t2=b+disc; + if (t2 <= SPEPSILON) + return; + add_intersection(t2, (object *) l, ry); + + t1=b-disc; + if (t1 > SPEPSILON) + add_intersection(t1, (object *) l, ry); +} + +static void light_normal(point_light * l, vector * pnt, ray * incident, vector * N) { + VSub((vector *) pnt, &(l->ctr), N); + + VNorm(N); + + if (VDot(N, &(incident->d)) > 0.0) { + N->x=-N->x; + N->y=-N->y; + N->z=-N->z; + } +} + + diff --git a/src/tbb/examples/parallel_for/tachyon/src/light.h b/src/tbb/examples/parallel_for/tachyon/src/light.h new file mode 100644 index 0000000..404ee13 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/light.h @@ -0,0 +1,79 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * light.h - this file includes declarations and defines for light sources. + * + * $Id: light.h,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +typedef struct { + unsigned int id; /* Unique Object serial number */ + void * nextobj; /* pointer to next object in list */ + object_methods * methods; /* this object's methods */ + texture * tex; /* object texture */ + vector ctr; + flt rad; +} point_light; + +point_light * newlight(void *, vector, flt); + +#ifdef LIGHT_PRIVATE +static int light_bbox(void * obj, vector * min, vector * max); +static void light_intersect(point_light *, ray *); +static void light_normal(point_light *, vector *, ray *, vector *); +#endif diff --git a/src/tbb/examples/parallel_for/tachyon/src/machine.h b/src/tbb/examples/parallel_for/tachyon/src/machine.h new file mode 100644 index 0000000..e8e4196 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/machine.h @@ -0,0 +1,74 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * machine.h - This is the machine specific include file + * + * $Id: machine.h,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +#define STDTIME diff --git a/src/tbb/examples/parallel_for/tachyon/src/macros.h b/src/tbb/examples/parallel_for/tachyon/src/macros.h new file mode 100644 index 0000000..c7d8a3e --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/macros.h @@ -0,0 +1,87 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * macros.h - This file contains macro versions of functions that would be best + * used as inlined code rather than function calls. + * + * $Id: macros.h,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +#define MYMAX(a , b) ((a) > (b) ? (a) : (b)) +#define MYMIN(a , b) ((a) < (b) ? (a) : (b)) + +#define VDOT(return, a, b) \ + return=(a.x * b.x + a.y * b.y + a.z * b.z); \ + +#define RAYPNT(c, a, b) \ +c.x = a.o.x + ( a.d.x * b ); \ +c.y = a.o.y + ( a.d.y * b ); \ +c.z = a.o.z + ( a.d.z * b ); \ + + +#define VSUB(a, b, c) \ +c.x = (a.x - b.x); \ +c.y = (a.y - b.y); \ +c.z = (a.z - b.z); \ + + +#define VCROSS(a, b, c) \ + c->x = (a->y * b->z) - (a->z * b->y); \ + c->y = (a->z * b->x) - (a->x * b->z); \ + c->z = (a->x * b->y) - (a->y * b->x); \ + diff --git a/src/tbb/examples/parallel_for/tachyon/src/main.cpp b/src/tbb/examples/parallel_for/tachyon/src/main.cpp new file mode 100644 index 0000000..ef4483b --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/main.cpp @@ -0,0 +1,257 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#include +#include +#include + +#define VIDEO_WINMAIN_ARGS +#include "types.h" +#include "api.h" /* The ray tracing library API */ +#include "parse.h" /* Support for my own file format */ +#include "ui.h" +#include "util.h" +#include "tachyon_video.h" +#include "../../../common/utility/utility.h" + +SceneHandle global_scene; +int global_xsize; /* size of graphic image rendered in window (from hres, vres) */ +int global_ysize; +int global_xwinsize; /* size of window (may be larger than above) */ +int global_ywinsize; +char *global_window_title; +bool global_usegraphics; + +bool silent_mode = false; /* silent mode */ + +class tachyon_video *video = 0; + +typedef struct { + int foundfilename; /* was a model file name found in the args? */ + char filename[1024]; /* model file to render */ + int useoutfilename; /* command line override of output filename */ + char outfilename[1024]; /* name of output image file */ + int verbosemode; /* verbose flags */ + int antialiasing; /* antialiasing setting */ + int displaymode; /* display mode */ + int boundmode; /* bounding mode */ + int boundthresh; /* bounding threshold */ + int usecamfile; /* use camera file */ + char camfilename[1024]; /* camera filename */ +} argoptions; + +static char *window_title_string (int argc, const char **argv) +{ + int i; + char *name; + + name = (char *) malloc (8192); + char *title = getenv ("TITLE"); + if( title ) strcpy( name, title ); + else { + if(strrchr(argv[0], '\\')) strcpy (name, strrchr(argv[0], '\\')+1); + else if(strrchr(argv[0], '/')) strcpy (name, strrchr(argv[0], '/')+1); + else strcpy (name, *argv[0]?argv[0]:"Tachyon"); + } + for (i = 1; i < argc; i++) { + strcat (name, " "); + strcat (name, argv[i]); + } +#ifdef _DEBUG + strcat (name, " (DEBUG BUILD)"); +#endif + return name; +} + +void initoptions(argoptions * opt) { + memset(opt, 0, sizeof(argoptions)); + opt->foundfilename = -1; + opt->useoutfilename = -1; + opt->verbosemode = -1; + opt->antialiasing = -1; + opt->displaymode = -1; + opt->boundmode = -1; + opt->boundthresh = -1; + opt->usecamfile = -1; +} + +int useoptions(argoptions * opt, SceneHandle scene) { + if (opt->useoutfilename == 1) { + rt_outputfile(scene, opt->outfilename); + } + + if (opt->verbosemode == 1) { + rt_verbose(scene, 1); + } + + if (opt->antialiasing != -1) { + /* need new api code for this */ + } + + if (opt->displaymode != -1) { + rt_displaymode(scene, opt->displaymode); + } + + if (opt->boundmode != -1) { + rt_boundmode(scene, opt->boundmode); + } + + if (opt->boundthresh != -1) { + rt_boundthresh(scene, opt->boundthresh); + } + + return 0; +} + +argoptions ParseCommandLine(int argc, const char *argv[]) { + argoptions opt; + + initoptions(&opt); + + bool nobounding = false; + bool nodisp = false; + + string filename; + + utility::parse_cli_arguments(argc,argv, + utility::cli_argument_pack() + .positional_arg(filename,"dataset", "Model file") + .positional_arg(opt.boundthresh,"boundthresh","bounding threshold value") + .arg(nodisp,"no-display-updating","disable run-time display updating") + .arg(nobounding,"no-bounding","disable bounding technique") + .arg(silent_mode,"silent","no output except elapsed time") + ); + + strcpy(opt.filename, filename.c_str()); + + opt.displaymode = nodisp ? RT_DISPLAY_DISABLED : RT_DISPLAY_ENABLED; + opt.boundmode = nobounding ? RT_BOUNDING_DISABLED : RT_BOUNDING_ENABLED; + + return opt; +} + +int CreateScene(argoptions &opt) { + char *filename; + + global_scene = rt_newscene(); + rt_initialize(); + + /* process command line overrides */ + useoptions(&opt, global_scene); + +#ifdef DEFAULT_MODELFILE +#if _WIN32||_WIN64 +#define _GLUE_FILENAME(x) "..\\dat\\" #x +#else +#define _GLUE_FILENAME(x) #x +#endif +#define GLUE_FILENAME(x) _GLUE_FILENAME(x) + if(opt.foundfilename == -1) + filename = GLUE_FILENAME(DEFAULT_MODELFILE); + else +#endif//DEFAULT_MODELFILE + filename = opt.filename; + + if ( readmodel(filename, global_scene) != 0 ) { + fprintf(stderr, "Parser returned a non-zero error code reading %s\n", filename); + fprintf(stderr, "Aborting Render...\n"); + rt_finalize(); + return -1; + } + + // need these early for create_graphics_window() so grab these here... + scenedef *scene = (scenedef *) global_scene; + global_xsize = scene->hres; + global_ysize = scene->vres; + global_xwinsize = global_xsize; + global_ywinsize = global_ysize; // add some here to leave extra blank space on bottom for status etc. + + return 0; +} + +int main (int argc, char *argv[]) { + try { + timer mainStartTime = gettimer(); + + global_window_title = window_title_string (argc, (const char**)argv); + + argoptions opt = ParseCommandLine(argc, (const char**)argv); + + if ( CreateScene(opt) != 0 ) + return -1; + + tachyon_video tachyon; + tachyon.threaded = true; + tachyon.init_console(); + + tachyon.title = global_window_title; + // always using window even if(!global_usegraphics) + global_usegraphics = + tachyon.init_window(global_xwinsize, global_ywinsize); + if(!tachyon.running) + return -1; + + video = &tachyon; + tachyon.main_loop(); + + utility::report_elapsed_time(timertime(mainStartTime, gettimer())); + return 0; + } catch ( std::exception& e ) { + std::cerr<<"error occurred. error text is :\"" <x = FHUGE; gmin->y = FHUGE; gmin->z = FHUGE; + gmax->x = -FHUGE; gmax->y = -FHUGE; gmax->z = -FHUGE; + + cur=*rootlist; + while (cur != NULL) { /* Go! */ + min.x = -FHUGE; min.y = -FHUGE; min.z = -FHUGE; + max.x = FHUGE; max.y = FHUGE; max.z = FHUGE; + + cur->methods->bbox((void *) cur, &min, &max); + + gmin->x = MYMIN( gmin->x , min.x); + gmin->y = MYMIN( gmin->y , min.y); + gmin->z = MYMIN( gmin->z , min.z); + + gmax->x = MYMAX( gmax->x , max.x); + gmax->y = MYMAX( gmax->y , max.y); + gmax->z = MYMAX( gmax->z , max.z); + + cur=(object *)cur->nextobj; + } +} + +static int objinside(object * obj, vector * min, vector * max) { + vector omin, omax; + + if (obj == NULL) /* non-existant object, shouldn't get here */ + return 0; + + if (obj->methods->bbox((void *) obj, &omin, &omax)) { + if ((min->x <= omin.x) && (min->y <= omin.y) && (min->z <= omin.z) && + (max->x >= omax.x) && (max->y >= omax.y) && (max->z >= omax.z)) { + return 1; + } + } + return 0; +} + +static int countobj(object * root) { + object * cur; /* counts the number of objects on a list */ + int numobj; + + numobj=0; + cur=root; + + while (cur != NULL) { + cur=(object *)cur->nextobj; + numobj++; + } + return numobj; +} + +static void movenextobj(object * thisobj, object ** root) { + object * cur, * tmp; + + /* move the object after thisobj to the front of the object list */ + /* headed by root */ + if (thisobj != NULL) { + if (thisobj->nextobj != NULL) { + cur=(object *)thisobj->nextobj; /* the object to be moved */ + thisobj->nextobj = cur->nextobj; /* link around the moved obj */ + tmp=*root; /* store the root node */ + cur->nextobj=tmp; /* attach root to cur */ + *root=cur; /* make cur, the new root */ + } + } +} + +static void octreespace(object ** rootlist, int maxoctnodes) { + object * cur; + vector gmin, gmax, gctr; + vector cmin1, cmin2, cmin3, cmin4, cmin5, cmin6, cmin7, cmin8; + vector cmax1, cmax2, cmax3, cmax4, cmax5, cmax6, cmax7, cmax8; + bndbox * box1, * box2, * box3, * box4; + bndbox * box5, * box6, * box7, * box8; + int skipobj; + + if (*rootlist == NULL) /* don't subdivide non-existant data */ + return; + + skipobj=0; + globalbound(rootlist, &gmin, &gmax); /* find global min and max */ + + gctr.x = ((gmax.x - gmin.x) / 2.0) + gmin.x; + gctr.y = ((gmax.y - gmin.y) / 2.0) + gmin.y; + gctr.z = ((gmax.z - gmin.z) / 2.0) + gmin.z; + + cmin1=gmin; + cmax1=gctr; + box1 = newbndbox(cmin1, cmax1); + + cmin2=gmin; + cmin2.x=gctr.x; + cmax2=gmax; + cmax2.y=gctr.y; + cmax2.z=gctr.z; + box2 = newbndbox(cmin2, cmax2); + + cmin3=gmin; + cmin3.y=gctr.y; + cmax3=gmax; + cmax3.x=gctr.x; + cmax3.z=gctr.z; + box3 = newbndbox(cmin3, cmax3); + + cmin4=gmin; + cmin4.x=gctr.x; + cmin4.y=gctr.y; + cmax4=gmax; + cmax4.z=gctr.z; + box4 = newbndbox(cmin4, cmax4); + + cmin5=gmin; + cmin5.z=gctr.z; + cmax5=gctr; + cmax5.z=gmax.z; + box5 = newbndbox(cmin5, cmax5); + + cmin6=gctr; + cmin6.y=gmin.y; + cmax6=gmax; + cmax6.y=gctr.y; + box6 = newbndbox(cmin6, cmax6); + + cmin7=gctr; + cmin7.x=gmin.x; + cmax7=gctr; + cmax7.y=gmax.y; + cmax7.z=gmax.z; + box7 = newbndbox(cmin7, cmax7); + + cmin8=gctr; + cmax8=gmax; + box8 = newbndbox(cmin8, cmax8); + + cur = *rootlist; + while (cur != NULL) { + if (objinside((object *)cur->nextobj, &cmin1, &cmax1)) { + movenextobj(cur, &box1->objlist); + } + else if (objinside((object *)cur->nextobj, &cmin2, &cmax2)) { + movenextobj(cur, &box2->objlist); + } + else if (objinside((object *)cur->nextobj, &cmin3, &cmax3)) { + movenextobj(cur, &box3->objlist); + } + else if (objinside((object *)cur->nextobj, &cmin4, &cmax4)) { + movenextobj(cur, &box4->objlist); + } + else if (objinside((object *)cur->nextobj, &cmin5, &cmax5)) { + movenextobj(cur, &box5->objlist); + } + else if (objinside((object *)cur->nextobj, &cmin6, &cmax6)) { + movenextobj(cur, &box6->objlist); + } + else if (objinside((object *)cur->nextobj, &cmin7, &cmax7)) { + movenextobj(cur, &box7->objlist); + } + else if (objinside((object *)cur->nextobj, &cmin8, &cmax8)) { + movenextobj(cur, &box8->objlist); + } + else { + skipobj++; + cur=(object *)cur->nextobj; + } + } + +/* new scope, for redefinition of cur, and old */ + { bndbox * cur, * old; + old=box1; + cur=box2; + if (countobj(cur->objlist) > 0) { + old->nextobj=cur; + globalbound(&cur->objlist, &cur->min, &cur->max); + old=cur; + } + cur=box3; + if (countobj(cur->objlist) > 0) { + old->nextobj=cur; + globalbound(&cur->objlist, &cur->min, &cur->max); + old=cur; + } + cur=box4; + if (countobj(cur->objlist) > 0) { + old->nextobj=cur; + globalbound(&cur->objlist, &cur->min, &cur->max); + old=cur; + } + cur=box5; + if (countobj(cur->objlist) > 0) { + old->nextobj=cur; + globalbound(&cur->objlist, &cur->min, &cur->max); + old=cur; + } + cur=box6; + if (countobj(cur->objlist) > 0) { + old->nextobj=cur; + globalbound(&cur->objlist, &cur->min, &cur->max); + old=cur; + } + cur=box7; + if (countobj(cur->objlist) > 0) { + old->nextobj=cur; + globalbound(&cur->objlist, &cur->min, &cur->max); + old=cur; + } + cur=box8; + if (countobj(cur->objlist) > 0) { + old->nextobj=cur; + globalbound(&cur->objlist, &cur->min, &cur->max); + old=cur; + } + + old->nextobj=*rootlist; + + if (countobj(box1->objlist) > 0) { + globalbound(&box1->objlist, &box1->min, &box1->max); + *rootlist=(object *) box1; + } + else { + *rootlist=(object *) box1->nextobj; + } + + } /**** end of special cur and old scope */ + + if (countobj(box1->objlist) > maxoctnodes) { + octreespace(&box1->objlist, maxoctnodes); + } + if (countobj(box2->objlist) > maxoctnodes) { + octreespace(&box2->objlist, maxoctnodes); + } + if (countobj(box3->objlist) > maxoctnodes) { + octreespace(&box3->objlist, maxoctnodes); + } + if (countobj(box4->objlist) > maxoctnodes) { + octreespace(&box4->objlist, maxoctnodes); + } + if (countobj(box5->objlist) > maxoctnodes) { + octreespace(&box5->objlist, maxoctnodes); + } + if (countobj(box6->objlist) > maxoctnodes) { + octreespace(&box6->objlist, maxoctnodes); + } + if (countobj(box7->objlist) > maxoctnodes) { + octreespace(&box7->objlist, maxoctnodes); + } + if (countobj(box8->objlist) > maxoctnodes) { + octreespace(&box8->objlist, maxoctnodes); + } +} + +void dividespace(int maxoctnodes, object **toplist) { + bndbox * gbox; + vector gmin, gmax; + + if (countobj(*toplist) > maxoctnodes) { + globalbound(toplist, &gmin, &gmax); + + octreespace(toplist, maxoctnodes); + + gbox = newbndbox(gmin, gmax); + gbox->objlist = NULL; + gbox->tex = NULL; + gbox->nextobj=NULL; + gbox->objlist=*toplist; + *toplist=(object *) gbox; + } +} diff --git a/src/tbb/examples/parallel_for/tachyon/src/objbound.h b/src/tbb/examples/parallel_for/tachyon/src/objbound.h new file mode 100644 index 0000000..c2b7535 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/objbound.h @@ -0,0 +1,74 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * objbound.h - defines for object bounding code. + * + * $Id: objbound.h,v 1.2 2007-02-22 17:54:15 Exp $ + */ + +void dividespace(int, object **); + +#ifdef OBJBOUND_PRIVATE + +static void globalbound(object **, vector *, vector *); +static int objinside(object * obj, vector * min, vector * max); +static int countobj(object *); +static void movenextobj(object *, object **); +static void octreespace(object **, int); + +#endif diff --git a/src/tbb/examples/parallel_for/tachyon/src/parse.cpp b/src/tbb/examples/parallel_for/tachyon/src/parse.cpp new file mode 100644 index 0000000..cc4083c --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/parse.cpp @@ -0,0 +1,871 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * parse.c - an UltraLame (tm) parser for simple data files... + * + * $Id: parse.cpp,v 1.3 2007-02-22 17:54:15 Exp $ + */ + +// Try preventing lots of GCC warnings about ignored results of fscanf etc. +#if !__INTEL_COMPILER + +#if __GNUC__<4 || __GNUC__==4 && __GNUC_MINOR__<5 +// For older versions of GCC, disable use of __wur in GLIBC +#undef _FORTIFY_SOURCE +#define _FORTIFY_SOURCE 0 +#else +// Starting from 4.5, GCC has a suppression option +#pragma GCC diagnostic ignored "-Wunused-result" +#endif + +#endif //__INTEL_COMPILER + +#include +#include +#include +#include +#include /* needed for toupper(), macro.. */ + +#include "types.h" +#include "api.h" /* rendering API */ + +#define PARSE_INTERNAL +#include "parse.h" /* self protos */ +#undef PARSE_INTERNAL + +static texentry textable[NUMTEXS]; /* texture lookup table */ +static texentry defaulttex; /* The default texture when a lookup fails */ +static int numtextures; /* number of TEXDEF textures */ +static int numobjectsparsed; /* total number of objects parsed so far */ +static color scenebackcol; /* scene background color */ + +static int stringcmp(const char * a, const char * b) { + int i, s, l; + + s=strlen(a); + l=strlen(b); + + if (s != l) + return 1; + + for (i=0; i NUMTEXS) { + fprintf(stderr, "Parse: %d textures allocated, texture slots full!\n", numtextures); + numtextures--; /* keep writing over last texture if we've run out.. */ + return PARSEALLOCERR; + } + + return PARSENOERR; +} + +static void * find_texture(char name[TEXNAMELEN]) { + int i; + + for (i=0; ix); + tmp.y=degtorad(degvec->y); + tmp.z=degtorad(degvec->z); + *degvec=tmp; +} + +static void InitRot3d(RotMat * rot, apiflt x, apiflt y, apiflt z) { + rot->rx1=cos(y)*cos(z); + rot->rx2=sin(x)*sin(y)*cos(z) - cos(x)*sin(z); + rot->rx3=sin(x)*sin(z) + cos(x)*cos(z)*sin(y); + + rot->ry1=cos(y)*sin(z); + rot->ry2=cos(x)*cos(z) + sin(x)*sin(y)*sin(z); + rot->ry3=cos(x)*sin(y)*sin(z) - sin(x)*cos(z); + + rot->rz1=sin(y); + rot->rz2=sin(x)*cos(y); + rot->rz3=cos(x)*cos(y); +} + +static void Rotate3d(RotMat * rot, vector * vec) { + vector tmp; + tmp.x=(vec->x*(rot->rx1) + vec->y*(rot->rx2) + vec->z*(rot->rx3)); + tmp.y=(vec->x*(rot->ry1) + vec->y*(rot->ry2) + vec->z*(rot->ry3)); + tmp.z=(vec->x*(rot->rz1) + vec->y*(rot->rz2) + vec->z*(rot->rz3)); + *vec=tmp; +} + +static void Scale3d(vector * scale, vector * vec) { + vec->x=vec->x * scale->x; + vec->y=vec->y * scale->y; + vec->z=vec->z * scale->z; +} + +static void Trans3d(vector * trans, vector * vec) { + vec->x+=trans->x; + vec->y+=trans->y; + vec->z+=trans->z; +} + +static errcode GetString(FILE * dfile, const char * string) { + char data[255]; + + fscanf(dfile,"%s",data); + if (stringcmp(data, string) != 0) { + fprintf(stderr, "parse: Expected %s, got %s \n",string, data); + fprintf(stderr, "parse: Error while parsing object: %d \n",numobjectsparsed); + return PARSEBADSYNTAX; + } + + return PARSENOERR; +} + +unsigned int readmodel(char * modelfile, SceneHandle scene) { + FILE * dfile; + errcode rc; + + reset_tex_table(); + dfile=NULL; + + dfile=fopen(modelfile,"r"); + if (dfile==NULL) { + return PARSEBADFILE; + } + + rc = GetScenedefs(dfile, scene); + if (rc != PARSENOERR) + return rc; + + scenebackcol.r = 0.0; /* default background is black */ + scenebackcol.g = 0.0; + scenebackcol.b = 0.0; + + numobjectsparsed=0; + while ((rc = GetObject(dfile, scene)) == PARSENOERR) { + numobjectsparsed++; + } + fclose(dfile); + + if (rc == PARSEEOF) + rc = PARSENOERR; + + rt_background(scene, scenebackcol); + + return rc; +} + + +static errcode GetScenedefs(FILE * dfile, SceneHandle scene) { + vector Ccenter, Cview, Cup; + apiflt zoom, aspectratio; + int raydepth, antialiasing; + char outfilename[200]; + int xres, yres, verbose; + float a,b,c; + errcode rc = PARSENOERR; + + rc |= GetString(dfile, "BEGIN_SCENE"); + + rc |= GetString(dfile, "OUTFILE"); + fscanf(dfile, "%s", outfilename); +#ifdef _WIN32 + if (strcmp (outfilename, "/dev/null") == 0) { + strcpy (outfilename, "NUL:"); + } +#endif + + rc |= GetString(dfile, "RESOLUTION"); + fscanf(dfile, "%d %d", &xres, &yres); + + rc |= GetString(dfile, "VERBOSE"); + fscanf(dfile, "%d", &verbose); + + rt_scenesetup(scene, outfilename, xres, yres, verbose); + + rc |= GetString(dfile, "CAMERA"); + + rc |= GetString(dfile, "ZOOM"); + fscanf(dfile, "%f", &a); + zoom=a; + + rc |= GetString(dfile, "ASPECTRATIO"); + fscanf(dfile, "%f", &b); + aspectratio=b; + + rc |= GetString(dfile, "ANTIALIASING"); + fscanf(dfile, "%d", &antialiasing); + + rc |= GetString(dfile, "RAYDEPTH"); + fscanf(dfile, "%d", &raydepth); + + rc |= GetString(dfile, "CENTER"); + fscanf(dfile,"%f %f %f", &a, &b, &c); + Ccenter.x = a; + Ccenter.y = b; + Ccenter.z = c; + + rc |= GetString(dfile, "VIEWDIR"); + fscanf(dfile,"%f %f %f", &a, &b, &c); + Cview.x = a; + Cview.y = b; + Cview.z = c; + + rc |= GetString(dfile, "UPDIR"); + fscanf(dfile,"%f %f %f", &a, &b, &c); + Cup.x = a; + Cup.y = b; + Cup.z = c; + + rc |= GetString(dfile, "END_CAMERA"); + + rt_camerasetup(scene, zoom, aspectratio, antialiasing, raydepth, + Ccenter, Cview, Cup); + + + return rc; +} + +static errcode GetObject(FILE * dfile, SceneHandle scene) { + char objtype[80]; + + fscanf(dfile, "%s", objtype); + if (!stringcmp(objtype, "END_SCENE")) { + return PARSEEOF; /* end parsing */ + } + if (!stringcmp(objtype, "TEXDEF")) { + return GetTexDef(dfile); + } + if (!stringcmp(objtype, "TEXALIAS")) { + return GetTexAlias(dfile); + } + if (!stringcmp(objtype, "BACKGROUND")) { + return GetBackGnd(dfile); + } + if (!stringcmp(objtype, "CYLINDER")) { + return GetCylinder(dfile); + } + if (!stringcmp(objtype, "FCYLINDER")) { + return GetFCylinder(dfile); + } + if (!stringcmp(objtype, "POLYCYLINDER")) { + return GetPolyCylinder(dfile); + } + if (!stringcmp(objtype, "SPHERE")) { + return GetSphere(dfile); + } + if (!stringcmp(objtype, "PLANE")) { + return GetPlane(dfile); + } + if (!stringcmp(objtype, "RING")) { + return GetRing(dfile); + } + if (!stringcmp(objtype, "BOX")) { + return GetBox(dfile); + } + if (!stringcmp(objtype, "SCALARVOL")) { + return GetVol(dfile); + } + if (!stringcmp(objtype, "TRI")) { + return GetTri(dfile); + } + if (!stringcmp(objtype, "STRI")) { + return GetSTri(dfile); + } + if (!stringcmp(objtype, "LIGHT")) { + return GetLight(dfile); + } + if (!stringcmp(objtype, "SCAPE")) { + return GetLandScape(dfile); + } + if (!stringcmp(objtype, "TPOLYFILE")) { + return GetTPolyFile(dfile); + } + + fprintf(stderr, "Found bad token: %s expected an object type\n", objtype); + return PARSEBADSYNTAX; +} + +static errcode GetVector(FILE * dfile, vector * v1) { + float a, b, c; + + fscanf(dfile, "%f %f %f", &a, &b, &c); + v1->x=a; + v1->y=b; + v1->z=c; + + return PARSENOERR; +} + +static errcode GetColor(FILE * dfile, color * c1) { + float r, g, b; + int rc; + + rc = GetString(dfile, "COLOR"); + fscanf(dfile, "%f %f %f", &r, &g, &b); + c1->r=r; + c1->g=g; + c1->b=b; + + return rc; +} + +static errcode GetTexDef(FILE * dfile) { + char texname[TEXNAMELEN]; + + fscanf(dfile, "%s", texname); + add_texture(GetTexBody(dfile), texname); + + return PARSENOERR; +} + +static errcode GetTexAlias(FILE * dfile) { + char texname[TEXNAMELEN]; + char aliasname[TEXNAMELEN]; + + fscanf(dfile, "%s", texname); + fscanf(dfile, "%s", aliasname); + add_texture(find_texture(aliasname), texname); + + return PARSENOERR; +} + + +static errcode GetTexture(FILE * dfile, void ** tex) { + char tmp[255]; + errcode rc = PARSENOERR; + + fscanf(dfile, "%s", tmp); + if (!stringcmp("TEXTURE", tmp)) { + *tex = GetTexBody(dfile); + } + else + *tex = find_texture(tmp); + + return rc; +} + +void * GetTexBody(FILE * dfile) { + char tmp[255]; + float a,b,c,d, phong, phongexp, phongtype; + apitexture tex; + void * voidtex; + errcode rc; + + rc = GetString(dfile, "AMBIENT"); + fscanf(dfile, "%f", &a); + tex.ambient=a; + + rc |= GetString(dfile, "DIFFUSE"); + fscanf(dfile, "%f", &b); + tex.diffuse=b; + + rc |= GetString(dfile, "SPECULAR"); + fscanf(dfile, "%f", &c); + tex.specular=c; + + rc |= GetString(dfile, "OPACITY"); + fscanf(dfile, "%f", &d); + tex.opacity=d; + + fscanf(dfile, "%s", tmp); + if (!stringcmp("PHONG", tmp)) { + fscanf(dfile, "%s", tmp); + if (!stringcmp("METAL", tmp)) { + phongtype = RT_PHONG_METAL; + } + else if (!stringcmp("PLASTIC", tmp)) { + phongtype = RT_PHONG_PLASTIC; + } + else { + phongtype = RT_PHONG_PLASTIC; + } + + fscanf(dfile, "%f", &phong); + GetString(dfile, "PHONG_SIZE"); + fscanf(dfile, "%f", &phongexp); + fscanf(dfile, "%s", tmp); + } + else { + phong = 0.0; + phongexp = 100.0; + phongtype = RT_PHONG_PLASTIC; + } + + fscanf(dfile, "%f %f %f", &a, &b, &c); + tex.col.r = a; + tex.col.g = b; + tex.col.b = c; + + rc |= GetString(dfile, "TEXFUNC"); + fscanf(dfile, "%d", &tex.texturefunc); + if (tex.texturefunc >= 7) { /* if its an image map, we need a filename */ + fscanf(dfile, "%s", tex.imap); + } + if (tex.texturefunc != 0) { + rc |= GetString(dfile, "CENTER"); + rc |= GetVector(dfile, &tex.ctr); + rc |= GetString(dfile, "ROTATE"); + rc |= GetVector(dfile, &tex.rot); + rc |= GetString(dfile, "SCALE"); + rc |= GetVector(dfile, &tex.scale); + } + if (tex.texturefunc == 9) { + rc |= GetString(dfile, "UAXIS"); + rc |= GetVector(dfile, &tex.uaxs); + rc |= GetString(dfile, "VAXIS"); + rc |= GetVector(dfile, &tex.vaxs); + } + + voidtex = rt_texture(&tex); + rt_tex_phong(voidtex, phong, phongexp, (int) phongtype); + + return voidtex; +} + +static errcode GetLight(FILE * dfile) { + apiflt rad; + vector ctr; + apitexture tex; + float a; + errcode rc; + + memset(&tex, 0, sizeof(apitexture)); + + rc = GetString(dfile,"CENTER"); + rc |= GetVector(dfile, &ctr); + rc |= GetString(dfile,"RAD"); + fscanf(dfile,"%f",&a); /* read in radius */ + rad=a; + + rc |= GetColor(dfile, &tex.col); + + rt_light(rt_texture(&tex), ctr, rad); + + return rc; +} + +static errcode GetBackGnd(FILE * dfile) { + float r,g,b; + + fscanf(dfile, "%f %f %f", &r, &g, &b); + + scenebackcol.r=r; + scenebackcol.g=g; + scenebackcol.b=b; + + return PARSENOERR; +} + +static errcode GetCylinder(FILE * dfile) { + apiflt rad; + vector ctr, axis; + void * tex; + float a; + errcode rc; + + rc = GetString(dfile, "CENTER"); + rc |= GetVector(dfile, &ctr); + rc |= GetString(dfile, "AXIS"); + rc |= GetVector(dfile, &axis); + rc |= GetString(dfile, "RAD"); + fscanf(dfile, "%f", &a); + rad=a; + + rc |= GetTexture(dfile, &tex); + rt_cylinder(tex, ctr, axis, rad); + + return rc; +} + +static errcode GetFCylinder(FILE * dfile) { + apiflt rad; + vector ctr, axis; + vector pnt1, pnt2; + void * tex; + float a; + errcode rc; + + rc = GetString(dfile, "BASE"); + rc |= GetVector(dfile, &pnt1); + rc |= GetString(dfile, "APEX"); + rc |= GetVector(dfile, &pnt2); + + ctr=pnt1; + axis.x=pnt2.x - pnt1.x; + axis.y=pnt2.y - pnt1.y; + axis.z=pnt2.z - pnt1.z; + + rc |= GetString(dfile, "RAD"); + fscanf(dfile, "%f", &a); + rad=a; + + rc |= GetTexture(dfile, &tex); + rt_fcylinder(tex, ctr, axis, rad); + + return rc; +} + +static errcode GetPolyCylinder(FILE * dfile) { + apiflt rad; + vector * temp; + void * tex; + float a; + int numpts, i; + errcode rc; + + rc = GetString(dfile, "POINTS"); + fscanf(dfile, "%d", &numpts); + + temp = (vector *) malloc(numpts * sizeof(vector)); + + for (i=0; imethods = &plane_methods; + + p->tex = (texture *)tex; + p->norm = norm; + VNorm(&p->norm); + p->d = -VDot(&ctr, &p->norm); + + return (object *) p; +} + +static int plane_bbox(void * obj, vector * min, vector * max) { + return 0; +} + +static void plane_intersect(plane * pln, ray * ry) { + flt t,td; + + t=-(pln->d + VDot(&pln->norm, &ry->o)); + td=VDot(&pln->norm, &ry->d); + if (td != 0.0) { + t /= td; + if (t > 0.0) + add_intersection(t,(object *) pln, ry); + } +} + +static void plane_normal(plane * pln, vector * pnt, ray * incident, vector * N) { + *N=pln->norm; +} + diff --git a/src/tbb/examples/parallel_for/tachyon/src/plane.h b/src/tbb/examples/parallel_for/tachyon/src/plane.h new file mode 100644 index 0000000..050e7e5 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/plane.h @@ -0,0 +1,80 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * plane.h - This file contains the defines for planes etc. + * + * $Id: plane.h,v 1.2 2007-02-22 17:54:16 Exp $ + */ + + +object * newplane(void * tex, vector ctr, vector norm); + +#ifdef PLANE_PRIVATE +typedef struct { + unsigned int id; /* Unique Object serial number */ + void * nextobj; /* pointer to next object in list */ + object_methods * methods; /* this object's methods */ + texture * tex; /* object texture */ + flt d; + vector norm; +} plane; + +static void plane_intersect(plane *, ray *); +static int plane_bbox(void * obj, vector * min, vector * max); +static void plane_normal(plane *, vector *, ray * incident, vector *); +#endif diff --git a/src/tbb/examples/parallel_for/tachyon/src/ppm.cpp b/src/tbb/examples/parallel_for/tachyon/src/ppm.cpp new file mode 100644 index 0000000..c3e99db --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/ppm.cpp @@ -0,0 +1,138 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * ppm.c - This file deals with PPM format image files (reading/writing) + * + * $Id: ppm.cpp,v 1.2 2007-02-22 17:54:16 Exp $ + */ + +/* For our puposes, we're interested only in the 3 byte per pixel 24 bit + truecolor sort of file.. Probably won't implement any decent checking + at this point, probably choke on things like the # comments.. */ + +// Try preventing lots of GCC warnings about ignored results of fscanf etc. +#if !__INTEL_COMPILER + +#if __GNUC__<4 || __GNUC__==4 && __GNUC_MINOR__<5 +// For older versions of GCC, disable use of __wur in GLIBC +#undef _FORTIFY_SOURCE +#define _FORTIFY_SOURCE 0 +#else +// Starting from 4.5, GCC has a suppression option +#pragma GCC diagnostic ignored "-Wunused-result" +#endif + +#endif //__INTEL_COMPILER + +#include +#include "machine.h" +#include "types.h" +#include "util.h" +#include "imageio.h" /* error codes etc */ +#include "ppm.h" + +static int getint(FILE * dfile) { + char ch[200]; + int i; + int num; + + num=0; + while (num==0) { + fscanf(dfile, "%s", ch); + while (ch[0]=='#') { + fgets(ch, 200, dfile); + } + num=sscanf(ch, "%d", &i); + } + return i; +} + +int readppm(char * name, int * xres, int * yres, unsigned char **imgdata) { + char data[200]; + FILE * ifp; + int i, bytesread; + int datasize; + + ifp=fopen(name, "r"); + if (ifp==NULL) { + return IMAGEBADFILE; /* couldn't open the file */ + } + fscanf(ifp, "%s", data); + + if (strcmp(data, "P6")) { + fclose(ifp); + return IMAGEUNSUP; /* not a format we support */ + } + + *xres=getint(ifp); + *yres=getint(ifp); + i=getint(ifp); /* eat the maxval number */ + fread(&i, 1, 1, ifp); /* eat the newline */ + datasize = 3 * (*xres) * (*yres); + + *imgdata=(unsigned char *)rt_getmem(datasize); + + bytesread=fread(*imgdata, 1, datasize, ifp); + + fclose(ifp); + + if (bytesread != datasize) + return IMAGEREADERR; + + return IMAGENOERR; +} diff --git a/src/tbb/examples/parallel_for/tachyon/src/ppm.h b/src/tbb/examples/parallel_for/tachyon/src/ppm.h new file mode 100644 index 0000000..a13c21f --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/ppm.h @@ -0,0 +1,68 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * ppm.h - This file deals with PPM format image files (reading/writing) + * + * $Id: ppm.h,v 1.2 2007-02-22 17:54:16 Exp $ + */ + +/* For our puposes, we're interested only in the 3 byte per pixel 24 bit + truecolor sort of file.. Probably won't implement any decent checking + at this point, probably choke on things like the # comments.. */ + +int readppm(char * name, int * xres, int * yres, unsigned char **imgdata); diff --git a/src/tbb/examples/parallel_for/tachyon/src/pthread.cpp b/src/tbb/examples/parallel_for/tachyon/src/pthread.cpp new file mode 100644 index 0000000..93b7f2a --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/pthread.cpp @@ -0,0 +1,164 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#ifdef EMULATE_PTHREADS + +#include +#include "pthread.h" + +/* + Basics +*/ + +int +pthread_create (pthread_t *thread, pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) +{ + pthread_t th; + + if (thread == NULL) return EINVAL; + *thread = NULL; + + if (start_routine == NULL) return EINVAL; + + th = (pthread_t) malloc (sizeof (pthread_s)); + memset (th, 0, sizeof (pthread_s)); + + th->winthread_handle = CreateThread ( + NULL, + 0, + (LPTHREAD_START_ROUTINE) start_routine, + arg, + 0, + &th->winthread_id); + if (th->winthread_handle == NULL) return EAGAIN; /* GetLastError() */ + + *thread = th; + return 0; +} + +int +pthread_join (pthread_t th, void **thread_return) +{ + BOOL b_ret; + DWORD dw_ret; + + if (thread_return) *thread_return = NULL; + + if ((th == NULL) || (th->winthread_handle == NULL)) return EINVAL; + + dw_ret = WaitForSingleObject (th->winthread_handle, INFINITE); + if (dw_ret != WAIT_OBJECT_0) return ERROR_PTHREAD; /* dw_ret == WAIT_FAILED; GetLastError() */ + + if (thread_return) { + BOOL e_ret; + DWORD exit_val; + e_ret = GetExitCodeThread (th->winthread_handle, &exit_val); + if (!e_ret) return ERROR_PTHREAD; /* GetLastError() */ + *thread_return = (void *)(size_t) exit_val; + } + + b_ret = CloseHandle (th->winthread_handle); + if (!b_ret) return ERROR_PTHREAD; /* GetLastError() */ + memset (th, 0, sizeof (pthread_s)); + free (th); + th = NULL; + + return 0; +} + +void +pthread_exit (void *retval) +{ + /* specific to PTHREAD_TO_WINTHREAD */ + + ExitThread ((DWORD) ((size_t) retval)); /* thread becomes signalled so its death can be waited upon */ + /*NOTREACHED*/ + assert (0); return; /* void fnc; can't return an error code */ +} + +/* + Mutex +*/ + +int +pthread_mutex_init (pthread_mutex_t *mutex, pthread_mutexattr_t *mutex_attr) +{ + InitializeCriticalSection (&mutex->critsec); + return 0; +} + +int +pthread_mutex_destroy (pthread_mutex_t *mutex) +{ + return 0; +} + +int +pthread_mutex_lock (pthread_mutex_t *mutex) +{ + EnterCriticalSection (&mutex->critsec); + return 0; +} + +int +pthread_mutex_unlock (pthread_mutex_t *mutex) +{ + LeaveCriticalSection (&mutex->critsec); + return 0; +} + +#endif /* EMULATE_PTHREADS */ diff --git a/src/tbb/examples/parallel_for/tachyon/src/pthread.h b/src/tbb/examples/parallel_for/tachyon/src/pthread.h new file mode 100644 index 0000000..1f518fd --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/pthread.h @@ -0,0 +1,117 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#ifdef EMULATE_PTHREADS + +#ifndef _PTHREAD_H_DEFINED +#define _PTHREAD_H_DEFINED + +#include +#include +#ifndef ENOTSUP +#define ENOTSUP EPERM +#endif + +/* just need on Windows to get size_t defined */ +#include + +#define ERROR_PTHREAD 1000 +#define ERROR_MODE 1001 +#define ERROR_UNIMPL 1002 + +/* + Basics +*/ + +struct pthread_s { + HANDLE winthread_handle; + DWORD winthread_id; +}; +typedef struct pthread_s *pthread_t; /* one of the few types that's pointer, not struct */ + +typedef struct { + int i; /* not yet defined... */ +} pthread_attr_t; + +/* + Mutex +*/ + +typedef struct { + int i; /* not yet defined... */ +} pthread_mutexattr_t; + +typedef struct { + CRITICAL_SECTION critsec; +} pthread_mutex_t; + +/* + Function prototypes +*/ + +extern int pthread_create (pthread_t *thread, pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); +extern int pthread_join (pthread_t th, void **thread_return); +extern void pthread_exit (void *retval); + +extern int pthread_mutex_init (pthread_mutex_t *mutex, pthread_mutexattr_t *mutex_attr); +extern int pthread_mutex_destroy (pthread_mutex_t *mutex); +extern int pthread_mutex_lock (pthread_mutex_t *mutex); +extern int pthread_mutex_unlock (pthread_mutex_t *mutex); + +#endif /* _PTHREAD_H_DEFINED */ + +#endif /* EMULATE_PTHREADS */ diff --git a/src/tbb/examples/parallel_for/tachyon/src/quadric.cpp b/src/tbb/examples/parallel_for/tachyon/src/quadric.cpp new file mode 100644 index 0000000..5d6ac8a --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/quadric.cpp @@ -0,0 +1,180 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * quadric.c - This file contains the functions for dealing with quadrics. + * + * $Id: quadric.cpp,v 1.2 2007-02-22 17:54:16 Exp $ + */ + +#include "machine.h" +#include "types.h" +#include "macros.h" +#include "quadric.h" +#include "vector.h" +#include "intersect.h" +#include "util.h" + +int quadric_bbox(void * obj, vector * min, vector * max) { + return 0; +} + +static object_methods quadric_methods = { + (void (*)(void *, void *))(quadric_intersect), + (void (*)(void *, void *, void *, void *))(quadric_normal), + quadric_bbox, + free +}; + +quadric * newquadric() { + quadric * q; + + q=(quadric *) rt_getmem(sizeof(quadric)); + memset(q, 0, sizeof(quadric)); + q->ctr.x=0.0; + q->ctr.y=0.0; + q->ctr.z=0.0; + q->methods = &quadric_methods; + + return q; +} + +void quadric_intersect(quadric * q, ray * ry) { + flt Aq, Bq, Cq; + flt t1, t2; + flt disc; + vector rd; + vector ro; + + rd=ry->d; + VNorm(&rd); + + ro.x = ry->o.x - q->ctr.x; + ro.y = ry->o.y - q->ctr.y; + ro.z = ry->o.z - q->ctr.z; + + + Aq = (q->mat.a*(rd.x * rd.x)) + + (2.0 * q->mat.b * rd.x * rd.y) + + (2.0 * q->mat.c * rd.x * rd.z) + + (q->mat.e * (rd.y * rd.y)) + + (2.0 * q->mat.f * rd.y * rd.z) + + (q->mat.h * (rd.z * rd.z)); + + Bq = 2.0 * ( + (q->mat.a * ro.x * rd.x) + + (q->mat.b * ((ro.x * rd.y) + (rd.x * ro.y))) + + (q->mat.c * ((ro.x * rd.z) + (rd.x * ro.z))) + + (q->mat.d * rd.x) + + (q->mat.e * ro.y * rd.y) + + (q->mat.f * ((ro.y * rd.z) + (rd.y * ro.z))) + + (q->mat.g * rd.y) + + (q->mat.h * ro.z * rd.z) + + (q->mat.i * rd.z) + ); + + Cq = (q->mat.a * (ro.x * ro.x)) + + (2.0 * q->mat.b * ro.x * ro.y) + + (2.0 * q->mat.c * ro.x * ro.z) + + (2.0 * q->mat.d * ro.x) + + (q->mat.e * (ro.y * ro.y)) + + (2.0 * q->mat.f * ro.y * ro.z) + + (2.0 * q->mat.g * ro.y) + + (q->mat.h * (ro.z * ro.z)) + + (2.0 * q->mat.i * ro.z) + + q->mat.j; + + if (Aq == 0.0) { + t1 = - Cq / Bq; + add_intersection(t1, (object *) q, ry); + } + else { + disc=(Bq*Bq - 4.0 * Aq * Cq); + if (disc > 0.0) { + disc=sqrt(disc); + t1 = (-Bq + disc) / (2.0 * Aq); + t2 = (-Bq - disc) / (2.0 * Aq); + add_intersection(t1, (object *) q, ry); + add_intersection(t2, (object *) q, ry); + } + } +} + +void quadric_normal(quadric * q, vector * pnt, ray * incident, vector * N) { + + N->x = (q->mat.a*(pnt->x - q->ctr.x) + + q->mat.b*(pnt->y - q->ctr.y) + + q->mat.c*(pnt->z - q->ctr.z) + q->mat.d); + + N->y = (q->mat.b*(pnt->x - q->ctr.x) + + q->mat.e*(pnt->y - q->ctr.y) + + q->mat.f*(pnt->z - q->ctr.z) + q->mat.g); + + N->z = (q->mat.c*(pnt->x - q->ctr.x) + + q->mat.f*(pnt->y - q->ctr.y) + + q->mat.h*(pnt->z - q->ctr.z) + q->mat.i); + + VNorm(N); + + if (VDot(N, &(incident->d)) > 0.0) { + N->x=-N->x; + N->y=-N->y; + N->z=-N->z; + } +} + + diff --git a/src/tbb/examples/parallel_for/tachyon/src/quadric.h b/src/tbb/examples/parallel_for/tachyon/src/quadric.h new file mode 100644 index 0000000..508546a --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/quadric.h @@ -0,0 +1,83 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * quadric.h - This file contains the defines for quadrics. + * + * $Id: quadric.h,v 1.2 2007-02-22 17:54:16 Exp $ + */ + +typedef struct { + flt a; flt b; flt c; + flt d; flt e; flt f; + flt g; flt h; flt i; flt j; +} quadmatrix; + + +typedef struct { + unsigned int id; /* Unique Object serial number */ + void * nextobj; /* pointer to next object in list */ + object_methods * methods; /* this object's methods */ + texture * tex; /* object texture */ + vector ctr; + quadmatrix mat; +} quadric; + + +quadric * newquadric(void); +void quadric_intersect(quadric *, ray *); +void quadric_normal(quadric *, vector *, ray *, vector *); diff --git a/src/tbb/examples/parallel_for/tachyon/src/render.cpp b/src/tbb/examples/parallel_for/tachyon/src/render.cpp new file mode 100644 index 0000000..3ad0f2f --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/render.cpp @@ -0,0 +1,101 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * render.c - This file contains the main program and driver for the raytracer. + * + * $Id: render.cpp,v 1.5 2007-02-22 18:17:51 amalakho Exp $ + */ + +#include "machine.h" +#include "types.h" +#include "macros.h" +#include "tgafile.h" +#include "trace.h" +#include "render.h" +#include "util.h" +#include "light.h" +#include "global.h" +#include "ui.h" +#include "tachyon_video.h" +#include "objbound.h" +#include "grid.h" + +/* how many pieces to divide each scanline into */ +#define NUMHORZDIV 1 + +void renderscene(scenedef scene) { + //char msgtxt[2048]; + //void * outfile; + /* Grid based accerlation scheme */ + if (scene.boundmode == RT_BOUNDING_ENABLED) + engrid_scene(&rootobj); /* grid */ + /* Not used now + if (scene.verbosemode) { + sprintf(msgtxt, "Opening %s for output.", scene.outfilename); + rt_ui_message(MSG_0, msgtxt); + } + + createtgafile(scene.outfilename, + (unsigned short) scene.hres, + (unsigned short) scene.vres); + outfile = opentgafile(scene.outfilename); + */ + + trace_region (scene, 0/*outfile*/, 0, 0, scene.hres, scene.vres); + //fclose((FILE *)outfile); +} /* end of renderscene() */ diff --git a/src/tbb/examples/parallel_for/tachyon/src/render.h b/src/tbb/examples/parallel_for/tachyon/src/render.h new file mode 100644 index 0000000..30990bb --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/render.h @@ -0,0 +1,65 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * render.h - This file contains the defines for the top level functions + * + * $Id: render.h,v 1.2 2007-02-22 17:54:16 Exp $ + */ + + +void renderscene(scenedef); diff --git a/src/tbb/examples/parallel_for/tachyon/src/ring.cpp b/src/tbb/examples/parallel_for/tachyon/src/ring.cpp new file mode 100644 index 0000000..f8ec449 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/ring.cpp @@ -0,0 +1,141 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * ring.c - This file contains the functions for dealing with rings. + * + * $Id: ring.cpp,v 1.2 2007-02-22 17:54:16 Exp $ + */ + +#include "machine.h" +#include "types.h" +#include "macros.h" +#include "vector.h" +#include "intersect.h" +#include "util.h" + +#define RING_PRIVATE +#include "ring.h" + +static object_methods ring_methods = { + (void (*)(void *, void *))(ring_intersect), + (void (*)(void *, void *, void *, void *))(ring_normal), + ring_bbox, + free +}; + +object * newring(void * tex, vector ctr, vector norm, flt inrad, flt outrad) { + ring * r; + + r=(ring *) rt_getmem(sizeof(ring)); + memset(r, 0, sizeof(ring)); + r->methods = &ring_methods; + + r->tex = (texture *)tex; + r->ctr = ctr; + r->norm = norm; + r->inrad = inrad; + r->outrad= outrad; + + return (object *) r; +} + +static int ring_bbox(void * obj, vector * min, vector * max) { + ring * r = (ring *) obj; + + min->x = r->ctr.x - r->outrad; + min->y = r->ctr.y - r->outrad; + min->z = r->ctr.z - r->outrad; + max->x = r->ctr.x + r->outrad; + max->y = r->ctr.y + r->outrad; + max->z = r->ctr.z + r->outrad; + + return 1; +} + +static void ring_intersect(ring * rng, ray * ry) { + flt d; + flt t,td; + vector hit, pnt; + + d = -VDot(&(rng->ctr), &(rng->norm)); + + t=-(d+VDot(&(rng->norm), &(ry->o))); + td=VDot(&(rng->norm),&(ry->d)); + if (td != 0.0) { + t= t / td; + if (t>=0.0) { + hit=Raypnt(ry, t); + VSUB(hit, rng->ctr, pnt); + VDOT(td, pnt, pnt); + td=sqrt(td); + if ((td > rng->inrad) && (td < rng->outrad)) + add_intersection(t,(object *) rng, ry); + } + } +} + +static void ring_normal(ring * rng, vector * pnt, ray * incident, vector * N) { + *N=rng->norm; + VNorm(N); + if (VDot(N, &(incident->d)) > 0.0) { + N->x=-N->x; + N->y=-N->y; + N->z=-N->z; + } +} + diff --git a/src/tbb/examples/parallel_for/tachyon/src/ring.h b/src/tbb/examples/parallel_for/tachyon/src/ring.h new file mode 100644 index 0000000..b3b66be --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/ring.h @@ -0,0 +1,81 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * ring.h - This file contains the defines for rings etc. + * + * $Id: ring.h,v 1.2 2007-02-22 17:54:16 Exp $ + */ + +object * newring(void * tex, vector ctr, vector norm, flt in, flt out); + +#ifdef RING_PRIVATE +typedef struct { + unsigned int id; /* Unique Object serial number */ + void * nextobj; /* pointer to next object in list */ + object_methods * methods; /* this object's methods */ + texture * tex; /* object texture */ + vector ctr; + vector norm; + flt inrad; + flt outrad; +} ring; + +static int ring_bbox(void * obj, vector * min, vector * max); +static void ring_intersect(ring *, ray *); +static void ring_normal(ring *, vector *, ray * incident, vector *); +#endif diff --git a/src/tbb/examples/parallel_for/tachyon/src/shade.cpp b/src/tbb/examples/parallel_for/tachyon/src/shade.cpp new file mode 100644 index 0000000..c081680 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/shade.cpp @@ -0,0 +1,268 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * shade.c - This file contains the functions that perform surface shading. + * + * $Id: shade.cpp,v 1.3 2007-02-22 17:54:16 Exp $ + */ + +#include "machine.h" +#include "types.h" +#include "macros.h" +#include "light.h" +#include "intersect.h" +#include "vector.h" +#include "trace.h" +#include "global.h" +#include "shade.h" + +void reset_lights(void) { + numlights=0; +} + +void add_light(point_light * li) { + lightlist[numlights]=li; + numlights++; +} + +color shader(ray * incident) { + color col, diffuse, phongcol; + vector N, L, hit; + ray shadowray; + flt inten, t, Llen; + object * obj; + int numints, i; + point_light * li; + + + numints=closest_intersection(&t, &obj, incident->intstruct); + /* find the number of intersections */ + /* and return the closest one. */ + + if (numints < 1) { + /* if there weren't any object intersections then return the */ + /* background color for the pixel color. */ + return incident->scene->background; + } + + if (obj->tex->islight) { /* if the current object is a light, then we */ + return obj->tex->col; /* will only use the objects ambient color */ + } + + RAYPNT(hit, (*incident), t) /* find the point of intersection from t */ + obj->methods->normal(obj, &hit, incident, &N); /* find the surface normal */ + + /* execute the object's texture function */ + col = obj->tex->texfunc(&hit, obj->tex, incident); + + diffuse.r = 0.0; + diffuse.g = 0.0; + diffuse.b = 0.0; + phongcol = diffuse; + + if ((obj->tex->diffuse > 0.0) || (obj->tex->phong > 0.0)) { + for (i=0; ictr, hit, L) /* find the light vector */ + + /* calculate the distance to the light from the hit point */ + Llen = sqrt(L.x*L.x + L.y*L.y + L.z*L.z) + EPSILON; + + L.x /= Llen; /* normalize the light direction vector */ + L.y /= Llen; + L.z /= Llen; + + VDOT(inten, N, L) /* light intensity */ + + /* add in diffuse lighting for this light if we're facing it */ + if (inten > 0.0) { + /* test for a shadow */ + shadowray.intstruct = incident->intstruct; + shadowray.flags = RT_RAY_SHADOW | RT_RAY_BOUNDED; + incident->serial++; + shadowray.serial = incident->serial; + shadowray.mbox = incident->mbox; + shadowray.o = hit; + shadowray.d = L; + shadowray.maxdist = Llen; + shadowray.s = hit; + shadowray.e = li->ctr; + shadowray.scene = incident->scene; + reset_intersection(incident->intstruct); + intersect_objects(&shadowray); + + if (!shadow_intersection(incident->intstruct, Llen)) { + /* XXX now that opacity is in the code, have to be more careful */ + ColorAddS(&diffuse, &li->tex->col, inten); + + /* phong type specular highlights */ + if (obj->tex->phong > 0.0) { + flt phongval; + phongval = shade_phong(incident, &hit, &N, &L, obj->tex->phongexp); + if (obj->tex->phongtype) + ColorAddS(&phongcol, &col, phongval); + else + ColorAddS(&phongcol, &(li->tex->col), phongval); + } + } + } + } + } + + ColorScale(&diffuse, obj->tex->diffuse); + + col.r *= (diffuse.r + obj->tex->ambient); /* do a product of the */ + col.g *= (diffuse.g + obj->tex->ambient); /* diffuse intensity with */ + col.b *= (diffuse.b + obj->tex->ambient); /* object color + ambient */ + + if (obj->tex->phong > 0.0) { + ColorAccum(&col, &phongcol); + } + + /* spawn reflection rays if necessary */ + /* note: this will overwrite the old intersection list */ + if (obj->tex->specular > 0.0) { + color specol; + specol = shade_reflection(incident, &hit, &N, obj->tex->specular); + ColorAccum(&col, &specol); + } + + /* spawn transmission rays / refraction */ + /* note: this will overwrite the old intersection list */ + if (obj->tex->opacity < 1.0) { + color transcol; + transcol = shade_transmission(incident, &hit, 1.0 - obj->tex->opacity); + ColorAccum(&col, &transcol); + } + + return col; /* return the color of the shaded pixel... */ +} + + +color shade_reflection(ray * incident, vector * hit, vector * N, flt specular) { + ray specray; + color col; + vector R; + + VAddS(-2.0 * (incident->d.x * N->x + + incident->d.y * N->y + + incident->d.z * N->z), N, &incident->d, &R); + + specray.intstruct=incident->intstruct; /* what thread are we */ + specray.depth=incident->depth - 1; /* go up a level in recursion depth */ + specray.flags = RT_RAY_REGULAR; /* infinite ray, to start with */ + specray.serial = incident->serial + 1; /* next serial number */ + specray.mbox = incident->mbox; + specray.o=*hit; + specray.d=R; /* reflect incident ray about normal */ + specray.o=Raypnt(&specray, EPSILON); /* avoid numerical precision bugs */ + specray.maxdist = FHUGE; /* take any intersection */ + specray.scene=incident->scene; /* global scenedef info */ + col=trace(&specray); /* trace specular reflection ray */ + + incident->serial = specray.serial; /* update the serial number */ + + ColorScale(&col, specular); + + return col; +} + + +color shade_transmission(ray * incident, vector * hit, flt trans) { + ray transray; + color col; + + transray.intstruct=incident->intstruct; /* what thread are we */ + transray.depth=incident->depth - 1; /* go up a level in recursion depth */ + transray.flags = RT_RAY_REGULAR; /* infinite ray, to start with */ + transray.serial = incident->serial + 1; /* update serial number */ + transray.mbox = incident->mbox; + transray.o=*hit; + transray.d=incident->d; /* ray continues along incident path */ + transray.o=Raypnt(&transray, EPSILON); /* avoid numerical precision bugs */ + transray.maxdist = FHUGE; /* take any intersection */ + transray.scene=incident->scene; /* global scenedef info */ + col=trace(&transray); /* trace transmission ray */ + + incident->serial = transray.serial; + + ColorScale(&col, trans); + + return col; +} + +flt shade_phong(ray * incident, vector * hit, + vector * N, vector * L, flt specpower){ + vector H, V; + flt inten; + + V = incident->d; + VScale(&V, -1.0); + VAdd(&V, L, &H); + VScale(&H, 0.5); + VNorm(&H); + inten = VDot(N, &H); + if (inten > 0.0) + inten = pow(inten, specpower); + else + inten = 0.0; + + return inten; +} + + diff --git a/src/tbb/examples/parallel_for/tachyon/src/shade.h b/src/tbb/examples/parallel_for/tachyon/src/shade.h new file mode 100644 index 0000000..6d3a736 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/shade.h @@ -0,0 +1,70 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * shade.h - This file contains declarations and definitions for the shader. + * + * $Id: shade.h,v 1.2 2007-02-22 17:54:16 Exp $ + */ + +void reset_lights(void); +void add_light(point_light *); + +color shader(ray *); +color shade_reflection(ray *, vector *, vector *, flt); +color shade_transmission(ray *, vector *, flt); +flt shade_phong(ray * incident, vector * hit, vector * N, vector * L, flt specpower); diff --git a/src/tbb/examples/parallel_for/tachyon/src/sphere.cpp b/src/tbb/examples/parallel_for/tachyon/src/sphere.cpp new file mode 100644 index 0000000..b71bb19 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/sphere.cpp @@ -0,0 +1,143 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * sphere.c - This file contains the functions for dealing with spheres. + * + * $Id: sphere.cpp,v 1.2 2007-02-22 17:54:16 Exp $ + */ + +#include "machine.h" +#include "types.h" +#include "macros.h" +#include "vector.h" +#include "intersect.h" +#include "util.h" + +#define SPHERE_PRIVATE +#include "sphere.h" + +static object_methods sphere_methods = { + (void (*)(void *, void *))(sphere_intersect), + (void (*)(void *, void *, void *, void *))(sphere_normal), + sphere_bbox, + free +}; + +object * newsphere(void * tex, vector ctr, flt rad) { + sphere * s; + + s=(sphere *) rt_getmem(sizeof(sphere)); + memset(s, 0, sizeof(sphere)); + s->methods = &sphere_methods; + + s->tex=(texture *)tex; + s->ctr=ctr; + s->rad=rad; + + return (object *) s; +} + +static int sphere_bbox(void * obj, vector * min, vector * max) { + sphere * s = (sphere *) obj; + + min->x = s->ctr.x - s->rad; + min->y = s->ctr.y - s->rad; + min->z = s->ctr.z - s->rad; + max->x = s->ctr.x + s->rad; + max->y = s->ctr.y + s->rad; + max->z = s->ctr.z + s->rad; + + return 1; +} + +static void sphere_intersect(sphere * spr, ray * ry) { + flt b, disc, t1, t2, temp; + vector V; + + VSUB(spr->ctr, ry->o, V); + VDOT(b, V, ry->d); + VDOT(temp, V, V); + + disc=b*b + spr->rad*spr->rad - temp; + + if (disc<=0.0) return; + disc=sqrt(disc); + + t2=b+disc; + if (t2 <= SPEPSILON) + return; + add_intersection(t2, (object *) spr, ry); + + t1=b-disc; + if (t1 > SPEPSILON) + add_intersection(t1, (object *) spr, ry); +} + +static void sphere_normal(sphere * spr, vector * pnt, ray * incident, vector * N) { + VSub((vector *) pnt, &(spr->ctr), N); + + VNorm(N); + + if (VDot(N, &(incident->d)) > 0.0) { + N->x=-N->x; + N->y=-N->y; + N->z=-N->z; + } +} + + diff --git a/src/tbb/examples/parallel_for/tachyon/src/sphere.h b/src/tbb/examples/parallel_for/tachyon/src/sphere.h new file mode 100644 index 0000000..4d25441 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/sphere.h @@ -0,0 +1,81 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * sphere.h - This file contains the defines for spheres etc. + * + * $Id: sphere.h,v 1.2 2007-02-22 17:54:16 Exp $ + */ + +object * newsphere(void *, vector, flt); + +#ifdef SPHERE_PRIVATE + +typedef struct { + unsigned int id; /* Unique Object serial number */ + void * nextobj; /* pointer to next object in list */ + object_methods * methods; /* this object's methods */ + texture * tex; /* object texture */ + vector ctr; + flt rad; +} sphere; + +static int sphere_bbox(void * obj, vector * min, vector * max); +static void sphere_intersect(sphere *, ray *); +static void sphere_normal(sphere *, vector *, ray *, vector *); + +#endif /* SPHERE_PRIVATE */ diff --git a/src/tbb/examples/parallel_for/tachyon/src/tachyon_video.cpp b/src/tbb/examples/parallel_for/tachyon/src/tachyon_video.cpp new file mode 100644 index 0000000..64ee65e --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/tachyon_video.cpp @@ -0,0 +1,128 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#include +#include +#include + +#include "types.h" +#include "api.h" /* The ray tracing library API */ +#include "ui.h" +#include "util.h" +#include "tachyon_video.h" + +extern SceneHandle global_scene; +extern char *global_window_title; +extern bool global_usegraphics; + +void tachyon_video::on_process() { + char buf[8192]; + flt runtime; + scenedef *scene = (scenedef *) global_scene; + updating_mode = scene->displaymode == RT_DISPLAY_ENABLED; + recycling = false; + pausing = false; + do { + updating = updating_mode; + timer start_timer = gettimer(); + rt_renderscene(global_scene); + timer end_timer = gettimer(); + runtime = timertime(start_timer, end_timer); + sprintf(buf, "%s: %.3f seconds", global_window_title, runtime); + rt_ui_message(MSG_0, buf); + title = buf; show_title(); // show time spent for rendering + if(!updating) { + updating = true; + drawing_memory dm = get_drawing_memory(); + drawing_area drawing(0, 0, dm.sizex, dm.sizey);// invalidate whole screen + } + rt_finalize(); + title = global_window_title; show_title(); // reset title to default + } while(recycling && running); +} + +void tachyon_video::on_key(int key) { + key &= 0xff; + recycling = true; + if(key == esc_key) running = false; + else if(key == ' ') { + if(!updating) { + updating = true; + drawing_memory dm = get_drawing_memory(); + drawing_area drawing(0, 0, dm.sizex, dm.sizey);// invalidate whole screen + } + updating = updating_mode = !updating_mode; + } + else if(key == 'p') { + pausing = !pausing; + if(pausing) { + title = "Press ESC to exit or 'p' to continue after rendering completion"; + show_title(); + } + } +} + +void rt_finalize(void) { + timer t0, t1; + t0 = gettimer(); + if(global_usegraphics) + do { rt_sleep(1); t1 = gettimer(); } + while( (timertime(t0, t1) < 10 || video->pausing) && video->next_frame()); +#ifdef _WINDOWS + else rt_sleep(10000); +#endif +} diff --git a/src/tbb/examples/parallel_for/tachyon/src/tachyon_video.h b/src/tbb/examples/parallel_for/tachyon/src/tachyon_video.h new file mode 100644 index 0000000..e87157b --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/tachyon_video.h @@ -0,0 +1,70 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#include "../../../common/gui/video.h" + +class tachyon_video : public video +{ +public: + bool updating_mode; + bool recycling; + bool pausing; + void on_process(); + void on_key(int key); +}; + +extern class tachyon_video *video; diff --git a/src/tbb/examples/parallel_for/tachyon/src/texture.cpp b/src/tbb/examples/parallel_for/tachyon/src/texture.cpp new file mode 100644 index 0000000..5849c3a --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/texture.cpp @@ -0,0 +1,395 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * texture.c - This file contains functions for implementing textures. + * + * $Id: texture.cpp,v 1.2 2007-02-22 17:54:16 Exp $ + */ + +#include "machine.h" +#include "types.h" +#include "macros.h" +#include "texture.h" +#include "coordsys.h" +#include "imap.h" +#include "vector.h" +#include "box.h" + +/* plain vanilla texture solely based on object color */ +color standard_texture(vector * hit, texture * tex, ray * ry) { + return tex->col; +} + +/* cylindrical image map */ +color image_cyl_texture(vector * hit, texture * tex, ray * ry) { + vector rh; + flt u,v; + + rh.x=hit->x - tex->ctr.x; + rh.z=hit->y - tex->ctr.y; + rh.y=hit->z - tex->ctr.z; + + xyztocyl(rh, 1.0, &u, &v); + + u = u * tex->scale.x; + u = u + tex->rot.x; + u=fmod(u, 1.0); + if (u < 0.0) u+=1.0; + + v = v * tex->scale.y; + v = v + tex->rot.y; + v=fmod(v, 1.0); + if (v < 0.0) v+=1.0; + + return ImageMap((rawimage *)tex->img, u, v); +} + +/* spherical image map */ +color image_sphere_texture(vector * hit, texture * tex, ray * ry) { + vector rh; + flt u,v; + + rh.x=hit->x - tex->ctr.x; + rh.y=hit->y - tex->ctr.y; + rh.z=hit->z - tex->ctr.z; + + xyztospr(rh, &u, &v); + + u = u * tex->scale.x; + u = u + tex->rot.x; + u=fmod(u, 1.0); + if (u < 0.0) u+=1.0; + + v = v * tex->scale.y; + v = v + tex->rot.y; + v=fmod(v, 1.0); + if (v < 0.0) v+=1.0; + + return ImageMap((rawimage *)tex->img, u, v); +} + +/* planar image map */ +color image_plane_texture(vector * hit, texture * tex, ray * ry) { + vector pnt; + flt u,v; + + pnt.x=hit->x - tex->ctr.x; + pnt.y=hit->y - tex->ctr.y; + pnt.z=hit->z - tex->ctr.z; + + VDOT(u, tex->uaxs, pnt); +/* VDOT(len, tex->uaxs, tex->uaxs); + u = u / sqrt(len); */ + + VDOT(v, tex->vaxs, pnt); +/* VDOT(len, tex->vaxs, tex->vaxs); + v = v / sqrt(len); */ + + + u = u * tex->scale.x; + u = u + tex->rot.x; + u = fmod(u, 1.0); + if (u < 0.0) u += 1.0; + + v = v * tex->scale.y; + v = v + tex->rot.y; + v = fmod(v, 1.0); + if (v < 0.0) v += 1.0; + + return ImageMap((rawimage *)tex->img, u, v); +} + +color grit_texture(vector * hit, texture * tex, ray * ry) { + int rnum; + flt fnum; + color col; + + rnum=rand() % 4096; + fnum=(rnum / 4096.0 * 0.2) + 0.8; + + col.r=tex->col.r * fnum; + col.g=tex->col.g * fnum; + col.b=tex->col.b * fnum; + + return col; +} + +color checker_texture(vector * hit, texture * tex, ray * ry) { + long x,y,z; + flt xh,yh,zh; + color col; + + xh=hit->x - tex->ctr.x; + x=(long) ((fabs(xh) * 3) + 0.5); + x=x % 2; + yh=hit->y - tex->ctr.y; + y=(long) ((fabs(yh) * 3) + 0.5); + y=y % 2; + zh=hit->z - tex->ctr.z; + z=(long) ((fabs(zh) * 3) + 0.5); + z=z % 2; + + if (((x + y + z) % 2)==1) { + col.r=1.0; + col.g=0.2; + col.b=0.0; + } + else { + col.r=0.0; + col.g=0.2; + col.b=1.0; + } + + return col; +} + +color cyl_checker_texture(vector * hit, texture * tex, ray * ry) { + long x,y; + vector rh; + flt u,v; + color col; + + rh.x=hit->x - tex->ctr.x; + rh.y=hit->y - tex->ctr.y; + rh.z=hit->z - tex->ctr.z; + + xyztocyl(rh, 1.0, &u, &v); + + x=(long) (fabs(u) * 18.0); + x=x % 2; + y=(long) (fabs(v) * 10.0); + y=y % 2; + + if (((x + y) % 2)==1) { + col.r=1.0; + col.g=0.2; + col.b=0.0; + } + else { + col.r=0.0; + col.g=0.2; + col.b=1.0; + } + + return col; +} + + +color wood_texture(vector * hit, texture * tex, ray * ry) { + flt radius, angle; + int grain; + color col; + flt x,y,z; + + x=(hit->x - tex->ctr.x) * 1000; + y=(hit->y - tex->ctr.y) * 1000; + z=(hit->z - tex->ctr.z) * 1000; + + radius=sqrt(x*x + z*z); + if (z == 0.0) + angle=3.1415926/2.0; + else + angle=atan(x / z); + + radius=radius + 3.0 * sin(20 * angle + y / 150.0); + grain=((int) (radius + 0.5)) % 60; + if (grain < 40) { + col.r=0.8; + col.g=1.0; + col.b=0.2; + } + else { + col.r=0.0; + col.g=0.0; + col.b=0.0; + } + + return col; +} + + + +#define NMAX 28 +short int NoiseMatrix[NMAX][NMAX][NMAX]; + +void InitNoise(void) { + byte x,y,z,i,j,k; + + for (x=0; xx; + y=hit->y; + z=hit->z; + + x=x * 1.0; + + d=x + 0.0006 * Noise(x, (y * 1.0), (z * 1.0)); + d=d*(((int) d) % 25); + i=0.0 + 0.10 * fabs(d - 10.0 - 20.0 * ((int) d * 0.05)); + if (i > 1.0) i=1.0; + if (i < 0.0) i=0.0; + +/* + col.r=i * tex->col.r; + col.g=i * tex->col.g; + col.b=i * tex->col.b; +*/ + + col.r = (1.0 + sin(i * 6.28)) / 2.0; + col.g = (1.0 + sin(i * 16.28)) / 2.0; + col.b = (1.0 + cos(i * 30.28)) / 2.0; + + return col; +} + + +color gnoise_texture(vector * hit, texture * tex, ray * ry) { + color col; + flt f; + + f=Noise((hit->x - tex->ctr.x), + (hit->y - tex->ctr.y), + (hit->z - tex->ctr.z)); + + if (f < 0.01) f=0.01; + if (f > 1.0) f=1.0; + + col.r=tex->col.r * f; + col.g=tex->col.g * f; + col.b=tex->col.b * f; + + return col; +} + +void InitTextures(void) { + InitNoise(); + ResetImages(); +} + diff --git a/src/tbb/examples/parallel_for/tachyon/src/texture.h b/src/tbb/examples/parallel_for/tachyon/src/texture.h new file mode 100644 index 0000000..6b825d7 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/texture.h @@ -0,0 +1,77 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * texture.h This file contains all of the includes and defines for the texture + * mapping part of the shader. + * + * $Id: texture.h,v 1.2 2007-02-22 17:54:16 Exp $ + */ + +void InitTextures(void); +color standard_texture(vector *, texture *, ray *); +color image_cyl_texture(vector *, texture *, ray *); +color image_sphere_texture(vector *, texture *, ray *); +color image_plane_texture(vector *, texture *, ray *); +color checker_texture(vector *, texture *, ray *); +color cyl_checker_texture(vector *, texture *, ray *); +color grit_texture(vector *, texture *, ray *); +color wood_texture(vector *, texture *, ray *); +color marble_texture(vector *, texture *, ray *); +color gnoise_texture(vector *, texture *, ray *); +int Noise(flt, flt, flt); +void InitTextures(void); diff --git a/src/tbb/examples/parallel_for/tachyon/src/tgafile.cpp b/src/tbb/examples/parallel_for/tachyon/src/tgafile.cpp new file mode 100644 index 0000000..895ec53 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/tgafile.cpp @@ -0,0 +1,245 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * tgafile.c - This file contains the code to write 24 bit targa files... + * + * $Id: tgafile.cpp,v 1.2 2007-02-22 17:54:16 Exp $ + */ + +#include "machine.h" +#include "types.h" +#include "util.h" +#include "ui.h" +#include "imageio.h" +#include "tgafile.h" + +void createtgafile(char *name, unsigned short width, unsigned short height) { + int filesize; + FILE * ofp; + + filesize = 3*width*height + 18 - 10; + + if (name==NULL) + exit(1); + else { + ofp=fopen(name, "w+b"); + if (ofp == NULL) { + char msgtxt[2048]; + sprintf(msgtxt, "Cannot create %s for output!", name); + rt_ui_message(MSG_ERR, msgtxt); + rt_ui_message(MSG_ABORT, "Rendering Aborted."); + exit(1); + } + + fputc(0, ofp); /* IdLength */ + fputc(0, ofp); /* ColorMapType */ + fputc(2, ofp); /* ImageTypeCode */ + fputc(0, ofp); /* ColorMapOrigin, low byte */ + fputc(0, ofp); /* ColorMapOrigin, high byte */ + fputc(0, ofp); /* ColorMapLength, low byte */ + fputc(0, ofp); /* ColorMapLength, high byte */ + fputc(0, ofp); /* ColorMapEntrySize */ + fputc(0, ofp); /* XOrigin, low byte */ + fputc(0, ofp); /* XOrigin, high byte */ + fputc(0, ofp); /* YOrigin, low byte */ + fputc(0, ofp); /* YOrigin, high byte */ + fputc((width & 0xff), ofp); /* Width, low byte */ + fputc(((width >> 8) & 0xff), ofp); /* Width, high byte */ + fputc((height & 0xff), ofp); /* Height, low byte */ + fputc(((height >> 8) & 0xff), ofp); /* Height, high byte */ + fputc(24, ofp); /* ImagePixelSize */ + fputc(0x20, ofp); /* ImageDescriptorByte 0x20 == flip vertically */ + + fseek(ofp, filesize, 0); + fprintf(ofp, "9876543210"); + + fclose(ofp); + } +} + +void * opentgafile(char * filename) { + FILE * ofp; + + ofp=fopen(filename, "r+b"); + if (ofp == NULL) { + char msgtxt[2048]; + sprintf(msgtxt, "Cannot open %s for output!", filename); + rt_ui_message(MSG_ERR, msgtxt); + rt_ui_message(MSG_ABORT, "Rendering Aborted."); + exit(1); + } + + return ofp; +} + +void writetgaregion(void * voidofp, + int iwidth, int iheight, + int startx, int starty, + int stopx, int stopy, char * buffer) { + int y, totalx, totaly; + char * bufpos; + int filepos, numbytes; + FILE * ofp = (FILE *) voidofp; + + totalx = stopx - startx + 1; + totaly = stopy - starty + 1; + + for (y=0; y= 18) { + fseek(ofp, filepos, 0); + numbytes = fwrite(bufpos, 3, totalx, ofp); + + if (numbytes != totalx) { + char msgtxt[256]; + sprintf(msgtxt, "File write problem, %d bytes written.", numbytes); + rt_ui_message(MSG_ERR, msgtxt); + } + } + else { + rt_ui_message(MSG_ERR, "writetgaregion: file ptr out of range!!!\n"); + return; /* don't try to continue */ + } + } +} + + +int readtga(char * name, int * xres, int * yres, unsigned char **imgdata) { + int format, width, height, w1, w2, h1, h2, depth, flags; + int imgsize, bytesread, i, tmp; + FILE * ifp; + + ifp=fopen(name, "r"); + if (ifp==NULL) { + return IMAGEBADFILE; /* couldn't open the file */ + } + + /* read the targa header */ + getc(ifp); /* ID length */ + getc(ifp); /* colormap type */ + format = getc(ifp); /* image type */ + getc(ifp); /* color map origin */ + getc(ifp); /* color map origin */ + getc(ifp); /* color map length */ + getc(ifp); /* color map length */ + getc(ifp); /* color map entry size */ + getc(ifp); /* x origin */ + getc(ifp); /* x origin */ + getc(ifp); /* y origin */ + getc(ifp); /* y origin */ + w1 = getc(ifp); /* width (low) */ + w2 = getc(ifp); /* width (hi) */ + h1 = getc(ifp); /* height (low) */ + h2 = getc(ifp); /* height (hi) */ + depth = getc(ifp); /* image pixel size */ + flags = getc(ifp); /* image descriptor byte */ + + if ((format != 2) || (depth != 24)) { + fclose(ifp); + return IMAGEUNSUP; /* unsupported targa format */ + } + + + width = ((w2 << 8) | w1); + height = ((h2 << 8) | h1); + + imgsize = 3 * width * height; + *imgdata = (unsigned char *)rt_getmem(imgsize); + bytesread = fread(*imgdata, 1, imgsize, ifp); + fclose(ifp); + + /* flip image vertically */ + if (flags == 0x20) { + int rowsize = 3 * width; + unsigned char * copytmp; + + copytmp = (unsigned char *)malloc(rowsize); + + for (i=0; i 0) { + for (alias=0; alias < scene.antialiasing; alias++) { + + serial++; /* increment serial number */ + sample=primary; /* copy the regular primary ray to start with */ + sample.serial = serial; + + { + sample.d.x+=((std::rand() % 100) - 50) / jitterscale; + sample.d.y+=((std::rand() % 100) - 50) / jitterscale; + sample.d.z+=((std::rand() % 100) - 50) / jitterscale; + } + + avcol=trace(&sample); + + serial = sample.serial; /* update our overall serial # */ + + col.r += avcol.r; + col.g += avcol.g; + col.b += avcol.b; + } + + col.r /= (scene.antialiasing + 1.0); + col.g /= (scene.antialiasing + 1.0); + col.b /= (scene.antialiasing + 1.0); + } + + /* Handle overexposure and underexposure here... */ + R=(int) (col.r*255); + if (R > 255) R = 255; + else if (R < 0) R = 0; + + G=(int) (col.g*255); + if (G > 255) G = 255; + else if (G < 0) G = 0; + + B=(int) (col.b*255); + if (B > 255) B = 255; + else if (B < 0) B = 0; + + return video->get_color(R, G, B); + +} + +static void parallel_thread (void) +{ + // thread-local storage + unsigned int serial = 1; + unsigned int mboxsize = sizeof(unsigned int)*(max_objectid() + 20); + unsigned int * local_mbox = (unsigned int *) alloca(mboxsize); + memset(local_mbox,0,mboxsize); + + for (int y = starty; y < stopy; y++) { { + drawing_area drawing(startx, totaly-y, stopx-startx, 1); + for (int x = startx; x < stopx; x++) { + color_t c = render_one_pixel (x, y, local_mbox, serial, startx, stopx, starty, stopy); + drawing.put_pixel(c); + } } + if(!video->next_frame()) return; + } +} + +void * thread_trace(thr_parms * parms) +{ + // shared but read-only so could be private too + all_parms = parms; + scene = parms->scene; + startx = parms->startx; + stopx = parms->stopx; + starty = parms->starty; + stopy = parms->stopy; + jitterscale = 40.0*(scene.hres + scene.vres); + totaly = parms->scene.vres-1; + + parallel_thread (); + + return(NULL); +} diff --git a/src/tbb/examples/parallel_for/tachyon/src/trace.tbb.cpp b/src/tbb/examples/parallel_for/tachyon/src/trace.tbb.cpp new file mode 100644 index 0000000..ea6fb0e --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/trace.tbb.cpp @@ -0,0 +1,271 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#include "machine.h" +#include "types.h" +#include "macros.h" +#include "vector.h" +#include "tgafile.h" +#include "trace.h" +#include "light.h" +#include "shade.h" +#include "camera.h" +#include "util.h" +#include "intersect.h" +#include "global.h" +#include "ui.h" +#include "tachyon_video.h" + +// shared but read-only so could be private too +static thr_parms *all_parms; +static scenedef scene; +static int startx; +static int stopx; +static int starty; +static int stopy; +static flt jitterscale; +static int totaly; + +#ifdef MARK_RENDERING_AREA + +// rgb colors list for coloring image by each thread +static const float inner_alpha = 0.3; +static const float border_alpha = 0.5; +#define NUM_COLORS 24 +static int colors[NUM_COLORS][3] = { + {255,110,0}, {220,254,0}, {102,254,0}, {0,21,254}, {97,0,254}, {254,30,0}, + {20,41,8}, {144,238,38}, {184,214,139}, {28,95,20}, {139,173,148}, {188,228,183}, + {145,47,56}, {204,147,193}, {45,202,143}, {204,171,143}, {143,160,204}, {220,173,3}, + {1,152,231}, {79,235,237}, {52,193,72}, {67,136,151}, {78,87,179}, {143,255,9}, +}; + +#include "tbb/atomic.h" +#include "tbb/enumerable_thread_specific.h" +// storage and counter for thread numbers in order of first task run +typedef tbb::enumerable_thread_specific< int > thread_id_t; +thread_id_t thread_ids (-1); +tbb::atomic thread_number; + +#endif + +#include "tbb/task_scheduler_init.h" +#include "tbb/parallel_for.h" +#include "tbb/spin_mutex.h" +#include "tbb/blocked_range2d.h" + +static tbb::spin_mutex MyMutex, MyMutex2; + +static color_t render_one_pixel (int x, int y, unsigned int *local_mbox, unsigned int &serial, + int startx, int stopx, int starty, int stopy +#ifdef MARK_RENDERING_AREA + , int *blend, float alpha +#endif +) +{ + /* private vars moved inside loop */ + ray primary, sample; + color col, avcol; + int R,G,B; + intersectstruct local_intersections; + int alias; + /* end private */ + + primary=camray(&scene, x, y); + primary.intstruct = &local_intersections; + primary.flags = RT_RAY_REGULAR; + + serial++; + primary.serial = serial; + primary.mbox = local_mbox; + primary.maxdist = FHUGE; + primary.scene = &scene; + col=trace(&primary); + + serial = primary.serial; + + /* perform antialiasing if enabled.. */ + if (scene.antialiasing > 0) { + for (alias=0; alias < scene.antialiasing; alias++) { + + serial++; /* increment serial number */ + sample=primary; /* copy the regular primary ray to start with */ + sample.serial = serial; + + { + tbb::spin_mutex::scoped_lock lock (MyMutex); + sample.d.x+=((rand() % 100) - 50) / jitterscale; + sample.d.y+=((rand() % 100) - 50) / jitterscale; + sample.d.z+=((rand() % 100) - 50) / jitterscale; + } + + avcol=trace(&sample); + + serial = sample.serial; /* update our overall serial # */ + + col.r += avcol.r; + col.g += avcol.g; + col.b += avcol.b; + } + + col.r /= (scene.antialiasing + 1.0); + col.g /= (scene.antialiasing + 1.0); + col.b /= (scene.antialiasing + 1.0); + } + + /* Handle overexposure and underexposure here... */ + R=(int) (col.r*255); + if (R > 255) R = 255; + else if (R < 0) R = 0; + + G=(int) (col.g*255); + if (G > 255) G = 255; + else if (G < 0) G = 0; + + B=(int) (col.b*255); + if (B > 255) B = 255; + else if (B < 0) B = 0; + +#ifdef MARK_RENDERING_AREA + R = int((1.0 - alpha) * R + alpha * blend[0]); + G = int((1.0 - alpha) * G + alpha * blend[1]); + B = int((1.0 - alpha) * B + alpha * blend[2]); +#endif + + return video->get_color(R, G, B); +} + +class parallel_task { +public: + void operator() (const tbb::blocked_range2d &r) const + { + // task-local storage + unsigned int serial = 1; + unsigned int mboxsize = sizeof(unsigned int)*(max_objectid() + 20); + unsigned int * local_mbox = (unsigned int *) alloca(mboxsize); + memset(local_mbox,0,mboxsize); +#ifdef MARK_RENDERING_AREA + // compute thread number while first task run + thread_id_t::reference thread_id = thread_ids.local(); + if (thread_id == -1) thread_id = thread_number++; + // choose thread color + int pos = thread_id % NUM_COLORS; + if(video->running) { + drawing_area drawing(r.cols().begin(), totaly-r.rows().end(), r.cols().end() - r.cols().begin(), r.rows().end()-r.rows().begin()); + for (int i = 1, y = r.rows().begin(); y != r.rows().end(); ++y, i++) { + drawing.set_pos(0, drawing.size_y-i); + for (int x = r.cols().begin(); x != r.cols().end(); x++) { + int d = (y % 3 == 0) ? 2 : 1; + drawing.put_pixel(video->get_color(colors[pos][0]/d, colors[pos][1]/d, colors[pos][2]/d)); + } + } + } +#endif + if(video->next_frame()) { + drawing_area drawing(r.cols().begin(), totaly-r.rows().end(), r.cols().end() - r.cols().begin(), r.rows().end()-r.rows().begin()); + for (int i = 1, y = r.rows().begin(); y != r.rows().end(); ++y, i++) { + drawing.set_pos(0, drawing.size_y-i); + for (int x = r.cols().begin(); x != r.cols().end(); x++) { +#ifdef MARK_RENDERING_AREA + float alpha = y==r.rows().begin()||y==r.rows().end()-1||x==r.cols().begin()||x==r.cols().end()-1 + ? border_alpha : inner_alpha; + color_t c = render_one_pixel (x, y, local_mbox, serial, startx, stopx, starty, stopy, colors[pos], alpha); +#else + color_t c = render_one_pixel (x, y, local_mbox, serial, startx, stopx, starty, stopy); +#endif + drawing.put_pixel(c); + } + } + } + } + + parallel_task () {} +}; + +void * thread_trace(thr_parms * parms) +{ + int n, nthreads = tbb::task_scheduler_init::automatic; + char *nthreads_str = getenv ("TBB_NUM_THREADS"); + if (nthreads_str && (sscanf (nthreads_str, "%d", &n) > 0) && (n > 0)) nthreads = n; + tbb::task_scheduler_init init (nthreads); + + // shared but read-only so could be private too + all_parms = parms; + scene = parms->scene; + startx = parms->startx; + stopx = parms->stopx; + starty = parms->starty; + stopy = parms->stopy; + jitterscale = 40.0*(scene.hres + scene.vres); + totaly = parms->scene.vres; +#ifdef MARK_RENDERING_AREA + thread_ids.clear(); +#endif + + int g, grain_size = 8; + char *grain_str = getenv ("TBB_GRAINSIZE"); + if (grain_str && (sscanf (grain_str, "%d", &g) > 0) && (g > 0)) grain_size = g; + char *sched_str = getenv ("TBB_PARTITIONER"); + static tbb::affinity_partitioner g_ap; // reused across calls to thread_trace + if ( sched_str && !strncmp(sched_str, "aff", 3) ) + tbb::parallel_for (tbb::blocked_range2d (starty, stopy, grain_size, startx, stopx, grain_size), parallel_task (), g_ap); + else if ( sched_str && !strncmp(sched_str, "simp", 4) ) + tbb::parallel_for (tbb::blocked_range2d (starty, stopy, grain_size, startx, stopx, grain_size), parallel_task (), tbb::simple_partitioner()); + else + tbb::parallel_for (tbb::blocked_range2d (starty, stopy, grain_size, startx, stopx, grain_size), parallel_task (), tbb::auto_partitioner()); + + return(NULL); +} diff --git a/src/tbb/examples/parallel_for/tachyon/src/trace.tbb1d.cpp b/src/tbb/examples/parallel_for/tachyon/src/trace.tbb1d.cpp new file mode 100644 index 0000000..0f93f36 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/trace.tbb1d.cpp @@ -0,0 +1,213 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#include "machine.h" +#include "types.h" +#include "macros.h" +#include "vector.h" +#include "tgafile.h" +#include "trace.h" +#include "light.h" +#include "shade.h" +#include "camera.h" +#include "util.h" +#include "intersect.h" +#include "global.h" +#include "ui.h" +#include "tachyon_video.h" + +// shared but read-only so could be private too +static thr_parms *all_parms; +static scenedef scene; +static int startx; +static int stopx; +static int starty; +static int stopy; +static flt jitterscale; +static int totaly; + +#include "tbb/task_scheduler_init.h" +#include "tbb/parallel_for.h" +#include "tbb/spin_mutex.h" +#include "tbb/blocked_range.h" + +static tbb::spin_mutex MyMutex, MyMutex2; + +static color_t render_one_pixel (int x, int y, unsigned int *local_mbox, unsigned int &serial, + int startx, int stopx, int starty, int stopy) +{ + /* private vars moved inside loop */ + ray primary, sample; + color col, avcol; + int R,G,B; + intersectstruct local_intersections; + int alias; + /* end private */ + + primary=camray(&scene, x, y); + primary.intstruct = &local_intersections; + primary.flags = RT_RAY_REGULAR; + + serial++; + primary.serial = serial; + primary.mbox = local_mbox; + primary.maxdist = FHUGE; + primary.scene = &scene; + col=trace(&primary); + + serial = primary.serial; + + /* perform antialiasing if enabled.. */ + if (scene.antialiasing > 0) { + for (alias=0; alias < scene.antialiasing; alias++) { + + serial++; /* increment serial number */ + sample=primary; /* copy the regular primary ray to start with */ + sample.serial = serial; + + { + tbb::spin_mutex::scoped_lock lock (MyMutex); + sample.d.x+=((rand() % 100) - 50) / jitterscale; + sample.d.y+=((rand() % 100) - 50) / jitterscale; + sample.d.z+=((rand() % 100) - 50) / jitterscale; + } + + avcol=trace(&sample); + + serial = sample.serial; /* update our overall serial # */ + + col.r += avcol.r; + col.g += avcol.g; + col.b += avcol.b; + } + + col.r /= (scene.antialiasing + 1.0); + col.g /= (scene.antialiasing + 1.0); + col.b /= (scene.antialiasing + 1.0); + } + + /* Handle overexposure and underexposure here... */ + R=(int) (col.r*255); + if (R > 255) R = 255; + else if (R < 0) R = 0; + + G=(int) (col.g*255); + if (G > 255) G = 255; + else if (G < 0) G = 0; + + B=(int) (col.b*255); + if (B > 255) B = 255; + else if (B < 0) B = 0; + + return video->get_color(R, G, B); + +} + +class parallel_task { +public: + void operator() (const tbb::blocked_range &r) const + { + // task-local storage + unsigned int serial = 1; + unsigned int mboxsize = sizeof(unsigned int)*(max_objectid() + 20); + unsigned int * local_mbox = (unsigned int *) alloca(mboxsize); + memset(local_mbox,0,mboxsize); + + for (int y = r.begin(); y != r.end(); ++y) { { + drawing_area drawing(startx, totaly-y, stopx-startx, 1); + for (int x = startx; x < stopx; x++) { + color_t c = render_one_pixel (x, y, local_mbox, serial, startx, stopx, starty, stopy); + drawing.put_pixel(c); + } } + if(!video->next_frame()) return; + } + } + + parallel_task () {} +}; + +void * thread_trace(thr_parms * parms) +{ + int n, nthreads = tbb::task_scheduler_init::automatic; + char *nthreads_str = getenv ("TBB_NUM_THREADS"); + if (nthreads_str && (sscanf (nthreads_str, "%d", &n) > 0) && (n > 0)) nthreads = n; + tbb::task_scheduler_init init (nthreads); + + // shared but read-only so could be private too + all_parms = parms; + scene = parms->scene; + startx = parms->startx; + stopx = parms->stopx; + starty = parms->starty; + stopy = parms->stopy; + jitterscale = 40.0*(scene.hres + scene.vres); + totaly = parms->scene.vres-1; + + int g, grain_size = 1; + char *grain_str = getenv ("TBB_GRAINSIZE"); + if (grain_str && (sscanf (grain_str, "%d", &g) > 0) && (g > 0)) grain_size = g; + char *sched_str = getenv ("TBB_PARTITIONER"); + static tbb::affinity_partitioner g_ap; + if ( sched_str && !strncmp(sched_str, "aff", 3) ) + tbb::parallel_for (tbb::blocked_range (starty, stopy, grain_size), parallel_task (), g_ap ); + else if ( sched_str && !strncmp(sched_str, "simp", 4) ) + tbb::parallel_for (tbb::blocked_range (starty, stopy, grain_size), parallel_task (), tbb::simple_partitioner() ); + else + tbb::parallel_for (tbb::blocked_range (starty, stopy, grain_size), parallel_task (), tbb::auto_partitioner() ); + + return(NULL); +} diff --git a/src/tbb/examples/parallel_for/tachyon/src/trace_rest.cpp b/src/tbb/examples/parallel_for/tachyon/src/trace_rest.cpp new file mode 100644 index 0000000..00ca172 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/trace_rest.cpp @@ -0,0 +1,148 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * trace.c - This file contains the functions for firing primary rays + * and handling subsequent calculations + * + * $Id: trace_rest.cpp,v 1.4 2007-02-22 17:54:16 Exp $ + */ + +#include "machine.h" +#include "types.h" +#include "macros.h" +#include "vector.h" +#include "tgafile.h" +#include "trace.h" +#include "light.h" +#include "shade.h" +#include "camera.h" +#include "util.h" +#include "intersect.h" +#include "global.h" +#include "ui.h" +#include "tachyon_video.h" + +color trace(ray * primary) { + if (primary->depth > 0) { + VNorm(&primary->d); + reset_intersection(primary->intstruct); + intersect_objects(primary); + return shader(primary); + } + + /* if ray is truncated, return the background as its color */ + return primary->scene->background; +} + +void * thread_io(void * parms) { + thr_io_parms p; + + p= *((thr_io_parms *) parms); + writetgaregion(p.tga, p.iwidth, p.iheight, p.startx, p.starty, + p.stopx, p.stopy, p.buffer); + free(p.buffer); /* free the buffer once we are done with it.. */ + free(parms); + + return(NULL); +} + +void trace_shm(scenedef scene, /*char * buffer, */ int startx, int stopx, int starty, int stopy) { + + thr_parms * parms; + + parms = (thr_parms *) rt_getmem(sizeof(thr_parms)); + + parms->tid=0; + parms->nthr=1; + parms->scene=scene; + parms->startx=startx; + parms->stopx=stopx; + parms->starty=starty; + parms->stopy=stopy; + + thread_trace(parms); + + rt_freemem(parms); +} + +void trace_region(scenedef scene, void * tga, int startx, int starty, int stopx, int stopy) { + + if (scene.verbosemode) { + char msgtxt[2048]; + sprintf(msgtxt, "Node %3d tracing region %4d, %4d ---> %4d, %4d \n", 0, startx,starty,stopx,stopy); + rt_ui_message(MSG_0, msgtxt); + } + + trace_shm(scene, /*buffer,*/ startx, stopx, starty, stopy); +/* not used now + writetgaregion(tga, scene.hres, scene.vres, + startx, starty, stopx, stopy, global_buffer); + + if (scene.rawimage != NULL) { + int x, y; + int totalx = stopx - startx + 1; + for (y=starty; y<=stopy; y++) { + for (x=0; x= EPSILON) && + (VLength(&edge2) >= EPSILON) && + (VLength(&edge3) >= EPSILON)) { + + t=(tri *) rt_getmem(sizeof(tri)); + + t->nextobj = NULL; + t->methods = &tri_methods; + + t->tex = (texture *)tex; + t->v0 = v0; + t->edge1 = edge1; + t->edge2 = edge2; + + return (object *) t; + } + + return NULL; /* was a degenerate triangle */ +} + + +object * newstri(void * tex, vector v0, vector v1, vector v2, + vector n0, vector n1, vector n2) { + stri * t; + vector edge1, edge2, edge3; + + VSub(&v1, &v0, &edge1); + VSub(&v2, &v0, &edge2); + VSub(&v2, &v1, &edge3); + + /* check to see if this will be a degenerate triangle before creation */ + if ((VLength(&edge1) >= EPSILON) && + (VLength(&edge2) >= EPSILON) && + (VLength(&edge3) >= EPSILON)) { + + t=(stri *) rt_getmem(sizeof(stri)); + + t->nextobj = NULL; + t->methods = &stri_methods; + + t->tex = (texture *)tex; + t->v0 = v0; + t->edge1 = edge1; + t->edge2 = edge2; + t->n0 = n0; + t->n1 = n1; + t->n2 = n2; + + return (object *) t; + } + + return NULL; /* was a degenerate triangle */ +} + +#define CROSS(dest,v1,v2) \ + dest.x=v1.y*v2.z-v1.z*v2.y; \ + dest.y=v1.z*v2.x-v1.x*v2.z; \ + dest.z=v1.x*v2.y-v1.y*v2.x; + +#define DOT(v1,v2) (v1.x*v2.x+v1.y*v2.y+v1.z*v2.z) + +#define SUB(dest,v1,v2) \ + dest.x=v1.x-v2.x; \ + dest.y=v1.y-v2.y; \ + dest.z=v1.z-v2.z; + +static int tri_bbox(void * obj, vector * min, vector * max) { + tri * t = (tri *) obj; + vector v1, v2; + + VAdd(&t->v0, &t->edge1, &v1); + VAdd(&t->v0, &t->edge2, &v2); + + min->x = MYMIN( t->v0.x , MYMIN( v1.x , v2.x )); + min->y = MYMIN( t->v0.y , MYMIN( v1.y , v2.y )); + min->z = MYMIN( t->v0.z , MYMIN( v1.z , v2.z )); + + max->x = MYMAX( t->v0.x , MYMAX( v1.x , v2.x )); + max->y = MYMAX( t->v0.y , MYMAX( v1.y , v2.y )); + max->z = MYMAX( t->v0.z , MYMAX( v1.z , v2.z )); + + return 1; +} + +static void tri_intersect(tri * trn, ray * ry) { + vector tvec, pvec, qvec; + flt det, inv_det, t, u, v; + + /* begin calculating determinant - also used to calculate U parameter */ + CROSS(pvec, ry->d, trn->edge2); + + /* if determinant is near zero, ray lies in plane of triangle */ + det = DOT(trn->edge1, pvec); + + if (det > -EPSILON && det < EPSILON) + return; + + inv_det = 1.0 / det; + + /* calculate distance from vert0 to ray origin */ + SUB(tvec, ry->o, trn->v0); + + /* calculate U parameter and test bounds */ + u = DOT(tvec, pvec) * inv_det; + if (u < 0.0 || u > 1.0) + return; + + /* prepare to test V parameter */ + CROSS(qvec, tvec, trn->edge1); + + /* calculate V parameter and test bounds */ + v = DOT(ry->d, qvec) * inv_det; + if (v < 0.0 || u + v > 1.0) + return; + + /* calculate t, ray intersects triangle */ + t = DOT(trn->edge2, qvec) * inv_det; + + add_intersection(t,(object *) trn, ry); +} + + +static void tri_normal(tri * trn, vector * pnt, ray * incident, vector * N) { + + CROSS((*N), trn->edge1, trn->edge2); + + VNorm(N); + + if (VDot(N, &(incident->d)) > 0.0) { + N->x=-N->x; + N->y=-N->y; + N->z=-N->z; + } +} + +static void stri_normal(stri * trn, vector * pnt, ray * incident, vector * N) { + flt U, V, W, lensqr; + vector P, tmp, norm; + + CROSS(norm, trn->edge1, trn->edge2); + lensqr = DOT(norm, norm); + + VSUB((*pnt), trn->v0, P); + + CROSS(tmp, P, trn->edge2); + U = DOT(tmp, norm) / lensqr; + + CROSS(tmp, trn->edge1, P); + V = DOT(tmp, norm) / lensqr; + + W = 1.0 - (U + V); + + N->x = W*trn->n0.x + U*trn->n1.x + V*trn->n2.x; + N->y = W*trn->n0.y + U*trn->n1.y + V*trn->n2.y; + N->z = W*trn->n0.z + U*trn->n1.z + V*trn->n2.z; + + VNorm(N); +} + diff --git a/src/tbb/examples/parallel_for/tachyon/src/triangle.h b/src/tbb/examples/parallel_for/tachyon/src/triangle.h new file mode 100644 index 0000000..d3e71aa --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/triangle.h @@ -0,0 +1,102 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * triangle.h - This file contains the defines for triangles etc. + * + * $Id: triangle.h,v 1.2 2007-02-22 17:54:16 Exp $ + */ + +object * newtri(void *, vector, vector, vector); +object * newstri(void *, vector, vector, vector, vector, vector, vector); + +#ifdef TRIANGLE_PRIVATE + +#define TRIXMAJOR 0 +#define TRIYMAJOR 1 +#define TRIZMAJOR 2 + +typedef struct { + unsigned int id; /* Unique Object serial number */ + void * nextobj; /* pointer to next object in list */ + object_methods * methods; /* this object's methods */ + texture * tex; /* object texture */ + vector edge2; + vector edge1; + vector v0; +} tri; + +typedef struct { + unsigned int id; /* Unique Object serial number */ + void * nextobj; /* pointer to next object in list */ + object_methods * methods; /* this object's methods */ + texture * tex; /* object texture */ + vector edge2; + vector edge1; + vector v0; + vector n0; + vector n1; + vector n2; +} stri; + +static int tri_bbox(void * obj, vector * min, vector * max); + +static void tri_intersect(tri *, ray *); + +static void tri_normal(tri *, vector *, ray *, vector *); +static void stri_normal(stri *, vector *, ray *, vector *); +#endif diff --git a/src/tbb/examples/parallel_for/tachyon/src/types.h b/src/tbb/examples/parallel_for/tachyon/src/types.h new file mode 100644 index 0000000..273493e --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/types.h @@ -0,0 +1,234 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#if __MINGW32__ +#include +#elif _WIN32 +#include +#define alloca _alloca +#elif __FreeBSD__||__NetBSD__ +#include +#else +#include +#endif + +/* + * types.h - This file contains all of the type definitions for the raytracer + * + * $Id: types.h,v 1.2 2007-02-22 17:54:16 Exp $ + */ + +#define MAXOCTNODES 25 /* subdivide octants /w > # of children */ +#define SPEPSILON 0.000001 /* amount to crawl down a ray */ +#define EPSILON 0.000001 /* amount to crawl down a ray */ +#define TWOPI 6.2831853 /* guess */ +#define FHUGE 1e18 /* biggest fp number we can represent */ + +/* Maximum internal table sizes */ +/* Use prime numbers for best memory system performance */ +#define INTTBSIZE 1024 /* maximum intersections we can hold */ +#define MAXLIGHTS 39 /* maximum number of lights in a scene */ +#define MAXIMGS 39 /* maxiumum number of distinct images */ +#define RPCQSIZE 113 /* number of RPC messages to queue */ + +/* Parameter values for rt_boundmode() */ +#define RT_BOUNDING_DISABLED 0 /* spatial subdivision/bounding disabled */ +#define RT_BOUNDING_ENABLED 1 /* spatial subdivision/bounding enabled */ + +/* Parameter values for rt_displaymode() */ +#define RT_DISPLAY_DISABLED 0 /* video output enabled */ +#define RT_DISPLAY_ENABLED 1 /* video output disabled */ + +/* Ray flags */ +#define RT_RAY_REGULAR 1 +#define RT_RAY_SHADOW 2 +#define RT_RAY_BOUNDED 4 +#define RT_RAY_FINISHED 8 + +#ifdef USESINGLEFLT +typedef float flt; /* generic floating point number, using float */ +#else +typedef double flt; /* generic floating point number, using double */ +#endif + +typedef unsigned char byte; /* 1 byte */ +typedef signed int word; /* 32 bit integer */ + +typedef struct { + flt x; /* X coordinate value */ + flt y; /* Y coordinate value */ + flt z; /* Z coordinate value */ +} vector; + +typedef struct { + flt r; /* Red component */ + flt g; /* Green component */ + flt b; /* Blue component */ +} color; + +typedef struct { + byte r; /* Red component */ + byte g; /* Green component */ + byte b; /* Blue component */ +} bytecolor; + +typedef struct { /* Raw 24 bit image structure, for tga, ppm etc */ + int loaded; /* image memory residence flag */ + int xres; /* image X axis size */ + int yres; /* image Y axis size */ + int bpp; /* image bits per pixel */ + char name[96]; /* image filename (with path) */ + unsigned char * data; /* pointer to raw byte image data */ +} rawimage; + +typedef struct { /* Scalar Volume Data */ + int loaded; /* Volume data memory residence flag */ + int xres; /* volume X axis size */ + int yres; /* volume Y axis size */ + int zres; /* volume Z axis size */ + flt opacity; /* opacity per unit length */ + char name[96]; /* Volume data filename */ + unsigned char * data; /* pointer to raw byte volume data */ +} scalarvol; + +typedef struct { + color (* texfunc)(void *, void *, void *); + int shadowcast; /* does the object cast a shadow */ + int islight; /* light flag... */ + color col; /* base object color */ + flt ambient; /* ambient lighting */ + flt diffuse; /* diffuse reflection */ + flt phong; /* phong specular highlights */ + flt phongexp; /* phong exponent/shininess factor */ + int phongtype; /* phong type: 0 == plastic, nonzero == metal */ + flt specular; /* specular reflection */ + flt opacity; /* how opaque the object is */ + vector ctr; /* origin of texture */ + vector rot; /* rotation of texture about origin */ + vector scale; /* scale of texture in x,y,z */ + vector uaxs; /* planar map U axis */ + vector vaxs; /* planar map V axis */ + void * img; /* pointer to image for image mapping */ + void * obj; /* object ptr, hack for volume shaders for now */ +} texture; + +typedef struct { + void (* intersect)(void *, void *); /* intersection func ptr */ + void (* normal)(void *, void *, void *, void *); /* normal function ptr */ + int (* bbox)(void *, vector *, vector *); /* return the object bbox */ + void (* free)(void *); /* free the object */ +} object_methods; + +typedef struct { + unsigned int id; /* Unique Object serial number */ + void * nextobj; /* pointer to next object in list */ + object_methods * methods; /* this object's methods */ + texture * tex; /* object texture */ +} object; + +typedef struct { + object * obj; /* to object we hit */ + flt t; /* distance along the ray to the hit point */ +} intersection; + +typedef struct { + int num; /* number of intersections */ + intersection closest; /* closest intersection > 0.0 */ + intersection list[INTTBSIZE]; /* list of all intersections */ +} intersectstruct; + +typedef struct { + char outfilename[200]; /* name of the output image */ + unsigned char * rawimage; /* pointer to a raw rgb image to be stored */ + int hres; /* horizontal output image resolution */ + int vres; /* vertical output image resolution */ + flt aspectratio; /* aspect ratio of output image */ + int raydepth; /* maximum recursion depth */ + int antialiasing; /* number of antialiasing rays to fire */ + int verbosemode; /* verbose reporting flag */ + int boundmode; /* automatic spatial subdivision flag */ + int boundthresh; /* threshold number of subobjects */ + int displaymode; /* run-time X11 display flag */ + vector camcent; /* center of the camera in world coords */ + vector camviewvec; /* view direction of the camera (Z axis) */ + vector camrightvec; /* right axis for the camera (X axis) */ + vector camupvec; /* up axis for the camera (Y axis) */ + flt camzoom; /* zoom factor for the camera */ + color background; /* scene background color */ +} scenedef; + +typedef struct { + intersectstruct * intstruct; /* ptr to thread's intersection data */ + unsigned int depth; /* levels left to recurse.. (maxdepth - curdepth) */ + unsigned int flags; /* ray flags, any special treatment needed etc */ + unsigned int serial; /* serial number of the ray */ + unsigned int * mbox; /* mailbox array for optimizing intersections */ + vector o; /* origin of the ray X,Y,Z */ + vector d; /* normalized direction of the ray */ + flt maxdist; /* maximum distance to search for intersections */ + vector s; /* startpoint of the ray (may differ from origin */ + vector e; /* endpoint of the ray if bounded */ + scenedef * scene; /* pointer to the scene, for global parms such as */ + /* background colors etc */ +} ray; + +typedef struct { + int type; /* RPC call type */ + int from; /* Sending processor */ + int len; /* length of parms in bytes */ + void * parms; /* Parameters to RPC */ +} rpcmsg; diff --git a/src/tbb/examples/parallel_for/tachyon/src/ui.cpp b/src/tbb/examples/parallel_for/tachyon/src/ui.cpp new file mode 100644 index 0000000..160d96c --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/ui.cpp @@ -0,0 +1,125 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * ui.c - Contains functions for dealing with user interfaces + * + * $Id: ui.cpp,v 1.2 2007-02-22 17:54:16 Exp $ + */ + +#include "machine.h" +#include "types.h" +#include "macros.h" +#include "util.h" +#include "ui.h" + +static void (* rt_static_ui_message) (int, const char *) = NULL; +static void (* rt_static_ui_progress) (int) = NULL; +static int (* rt_static_ui_checkaction) (void) = NULL; + +extern bool silent_mode; + +void set_rt_ui_message(void (* func) (int, const char *)) { + rt_static_ui_message = func; +} + +void set_rt_ui_progress(void (* func) (int)) { + rt_static_ui_progress = func; +} + +void rt_ui_message(int level, const char * msg) { + if (rt_static_ui_message == NULL) { + if ( !silent_mode ) { + fprintf(stderr, "%s\n", msg); + fflush (stderr); + } + } else { + rt_static_ui_message(level, msg); + } +} + +void rt_ui_progress(int percent) { + if (rt_static_ui_progress != NULL) + rt_static_ui_progress(percent); + else { + if ( !silent_mode ) { + fprintf(stderr, "\r %3d%% Complete \r", percent); + fflush(stderr); + } + } +} + +int rt_ui_checkaction(void) { + if (rt_static_ui_checkaction != NULL) + return rt_static_ui_checkaction(); + else + return 0; +} + + + + + + + + + + + + + + diff --git a/src/tbb/examples/parallel_for/tachyon/src/ui.h b/src/tbb/examples/parallel_for/tachyon/src/ui.h new file mode 100644 index 0000000..b3a7f3c --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/ui.h @@ -0,0 +1,76 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * ui.h - defines for user interface functions + * + * $Id: ui.h,v 1.2 2007-02-22 17:54:16 Exp $ + */ + +/* Different types of message, for levels of verbosity etc */ +#define MSG_0 100 +#define MSG_1 101 +#define MSG_2 102 +#define MSG_3 103 +#define MSG_4 104 +#define MSG_5 105 +#define MSG_ERR 200 +#define MSG_ABORT 300 + +void rt_ui_message(int, const char *); +void rt_ui_progress(int); +int rt_ui_checkaction(void); diff --git a/src/tbb/examples/parallel_for/tachyon/src/util.cpp b/src/tbb/examples/parallel_for/tachyon/src/util.cpp new file mode 100644 index 0000000..de2e83a --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/util.cpp @@ -0,0 +1,182 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * util.c - Contains all of the timing functions for various platforms. + * + * $Id: util.cpp,v 1.6 2007-02-22 18:17:51 amalakho Exp $ + */ + +#include "machine.h" +#include "types.h" +#include "macros.h" +#include "util.h" +#include "light.h" +#include "global.h" +#include "ui.h" + +void rt_finalize(void); + +#if !defined( _WIN32 ) +#include +#include + +void rt_sleep(int msec) { + usleep(msec*1000); +} + +#else //_WIN32 + +#undef OLDUNIXTIME +#undef STDTIME + +#include + +void rt_sleep(int msec) { + Sleep(msec); +} + +timer gettimer(void) { + return GetTickCount (); +} + +flt timertime(timer st, timer fn) { + double ttime, start, end; + + start = ((double) st) / ((double) 1000.00); + end = ((double) fn) / ((double) 1000.00); + ttime = end - start; + + return ttime; +} +#endif /* _WIN32 */ + +/* if we're on a Unix with gettimeofday() we'll use newer timers */ +#if defined( STDTIME ) + struct timezone tz; + +timer gettimer(void) { + timer t; + gettimeofday(&t, &tz); + return t; +} + +flt timertime(timer st, timer fn) { + double ttime, start, end; + + start = (st.tv_sec+1.0*st.tv_usec / 1000000.0); + end = (fn.tv_sec+1.0*fn.tv_usec / 1000000.0); + ttime = end - start; + + return ttime; +} +#endif /* STDTIME */ + + + +/* use the old fashioned Unix time functions */ +#if defined( OLDUNIXTIME ) +timer gettimer(void) { + return time(NULL); +} + +flt timertime(timer st, timer fn) { + return difftime(fn, st);; +} +#endif /* OLDUNIXTIME */ + + + +/* random other helper utility functions */ +int rt_meminuse(void) { + return rt_mem_in_use; +} + +void * rt_getmem(unsigned int bytes) { + void * mem; + + mem=malloc( bytes ); + if (mem!=NULL) { + rt_mem_in_use += bytes; + } + else { + rtbomb("No more memory!!!!"); + } + return mem; +} + +unsigned int rt_freemem(void * addr) { + unsigned int bytes; + + free(addr); + + bytes=0; + rt_mem_in_use -= bytes; + return bytes; +} + +void rtbomb(const char * msg) { + rt_ui_message(MSG_ERR, msg); + rt_ui_message(MSG_ABORT, "Rendering Aborted."); + + rt_finalize(); + exit(1); +} + +void rtmesg(const char * msg) { + rt_ui_message(MSG_0, msg); +} diff --git a/src/tbb/examples/parallel_for/tachyon/src/util.h b/src/tbb/examples/parallel_for/tachyon/src/util.h new file mode 100644 index 0000000..26b7ef6 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/util.h @@ -0,0 +1,86 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * util.h - This file contains defines for the timer functions... + * + * $Id: util.h,v 1.3 2007-02-22 17:54:17 Exp $ + */ + +#include "machine.h" + +#if defined( _WIN32 ) + #include + typedef DWORD timer; +#else + #include + #include + #if defined( STDTIME ) + typedef timeval timer; + #elif defined ( OLDUNIXTIME ) + typedef time_t timer; + #endif /* OLDUNIXTIME */ /* STDTIME */ + #endif /* _WIN32 */ + +timer gettimer(void); +flt timertime(timer st, timer fn); +void rt_sleep(int); +int rt_meminuse(void); +void * rt_getmem(unsigned int); +unsigned int rt_freemem(void *); +void rtbomb(const char *); +void rtmesg(const char *); diff --git a/src/tbb/examples/parallel_for/tachyon/src/vector.cpp b/src/tbb/examples/parallel_for/tachyon/src/vector.cpp new file mode 100644 index 0000000..a7dff76 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/vector.cpp @@ -0,0 +1,144 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * vector.c - This file contains all of the vector arithmetic functions. + * + * $Id: vector.cpp,v 1.2 2007-02-22 17:54:17 Exp $ + */ + +#include "machine.h" +#include "types.h" +#include "macros.h" + +flt VDot(vector *a, vector *b) { + return (a->x*b->x + a->y*b->y + a->z*b->z); +} + +void VCross(vector * a, vector * b, vector * c) { + c->x = (a->y * b->z) - (a->z * b->y); + c->y = (a->z * b->x) - (a->x * b->z); + c->z = (a->x * b->y) - (a->y * b->x); +} + +flt VLength(vector * a) { + return (flt) sqrt((a->x * a->x) + (a->y * a->y) + (a->z * a->z)); +} + +void VNorm(vector * a) { + flt len; + + len=sqrt((a->x * a->x) + (a->y * a->y) + (a->z * a->z)); + if (len != 0.0) { + a->x /= len; + a->y /= len; + a->z /= len; + } +} + +void VAdd(vector * a, vector * b, vector * c) { + c->x = (a->x + b->x); + c->y = (a->y + b->y); + c->z = (a->z + b->z); +} + +void VSub(vector * a, vector * b, vector * c) { + c->x = (a->x - b->x); + c->y = (a->y - b->y); + c->z = (a->z - b->z); +} + +void VAddS(flt a, vector * A, vector * B, vector * C) { + C->x = (a * A->x) + B->x; + C->y = (a * A->y) + B->y; + C->z = (a * A->z) + B->z; +} + +vector Raypnt(ray * a, flt t) { + vector temp; + + temp.x=a->o.x + (a->d.x * t); + temp.y=a->o.y + (a->d.y * t); + temp.z=a->o.z + (a->d.z * t); + + return temp; +} + +void VScale(vector * a, flt s) { + a->x *= s; + a->y *= s; + a->z *= s; +} + +void ColorAddS(color * a, color * b, flt s) { + a->r += b->r * s; + a->g += b->g * s; + a->b += b->b * s; +} + +void ColorAccum(color * a, color * b) { + a->r += b->r; + a->g += b->g; + a->b += b->b; +} + +void ColorScale(color * a, flt s) { + a->r *= s; + a->g *= s; + a->b *= s; +} + diff --git a/src/tbb/examples/parallel_for/tachyon/src/vector.h b/src/tbb/examples/parallel_for/tachyon/src/vector.h new file mode 100644 index 0000000..5b7e659 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/vector.h @@ -0,0 +1,76 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * vector.h - This file contains declarations of vector functions + * + * $Id: vector.h,v 1.2 2007-02-22 17:54:17 Exp $ + */ + +flt VDot(vector *, vector *); +void VCross(vector *, vector *, vector *); +flt VLength(vector *); +void VNorm(vector *); +void VAdd(vector *, vector *, vector *); +void VSub(vector *, vector *, vector *); +void VAddS(flt, vector *, vector *, vector *); +vector Raypnt(ray *, flt); +void VScale(vector * a, flt s); + +void ColorAddS(color * a, color * b, flt s); +void ColorAccum(color * a, color * b); +void ColorScale(color * a, flt s); diff --git a/src/tbb/examples/parallel_for/tachyon/src/vol.cpp b/src/tbb/examples/parallel_for/tachyon/src/vol.cpp new file mode 100644 index 0000000..7a33172 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/vol.cpp @@ -0,0 +1,312 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * vol.c - Volume rendering helper routines etc. + * + * + * $Id: vol.cpp,v 1.3 2007-02-22 18:17:51 amalakho Exp $ + */ + +#include +#include "machine.h" +#include "types.h" +#include "macros.h" +#include "vector.h" +#include "util.h" +#include "vol.h" +#include "box.h" +#include "trace.h" +#include "ui.h" +#include "light.h" +#include "shade.h" + +int scalarvol_bbox(void * obj, vector * min, vector * max) { + box * b = (box *) obj; + + *min = b->min; + *max = b->max; + + return 1; +} + +void * newscalarvol(void * intex, vector min, vector max, + int xs, int ys, int zs, char * fname, scalarvol * invol) { + box * bx; + texture * tx, * tex; + scalarvol * vol; + + tex=(texture *)intex; + tex->shadowcast = 0; /* doesn't cast a shadow */ + + tx=(texture *)rt_getmem(sizeof(texture)); + + /* is the volume data already loaded? */ + if (invol==NULL) { + vol=(scalarvol *)rt_getmem(sizeof(scalarvol)); + vol->loaded=0; + vol->data=NULL; + } + else + vol=invol; + + vol->opacity=tex->opacity; + vol->xres=xs; + vol->yres=ys; + vol->zres=zs; + strcpy(vol->name, fname); + + tx->ctr.x = 0.0; + tx->ctr.y = 0.0; + tx->ctr.z = 0.0; + tx->rot = tx->ctr; + tx->scale = tx->ctr; + tx->uaxs = tx->ctr; + tx->vaxs = tx->ctr; + + tx->islight = 0; + tx->shadowcast = 0; /* doesn't cast a shadow */ + + tx->col = tex->col; + tx->ambient = 1.0; + tx->diffuse = 0.0; + tx->specular = 0.0; + tx->opacity = 1.0; + tx->img = vol; + tx->texfunc = (color(*)(void *, void *, void *))(scalar_volume_texture); + + bx=newbox(tx, min, max); + tx->obj = (void *) bx; /* XXX hack! */ + + return (void *) bx; +} + + +color VoxelColor(flt scalar) { + color col; + + if (scalar > 1.0) + scalar = 1.0; + + if (scalar < 0.0) + scalar = 0.0; + + if (scalar < 0.25) { + col.r = scalar * 4.0; + col.g = 0.0; + col.b = 0.0; + } + else { + if (scalar < 0.75) { + col.r = 1.0; + col.g = (scalar - 0.25) * 2.0; + col.b = 0.0; + } + else { + col.r = 1.0; + col.g = 1.0; + col.b = (scalar - 0.75) * 4.0; + } + } + + return col; +} + +color scalar_volume_texture(vector * hit, texture * tex, ray * ry) { + color col, col2; + box * bx; + flt a, tx1, tx2, ty1, ty2, tz1, tz2; + flt tnear, tfar; + flt t, tdist, dt, sum, tt; + vector pnt, bln; + scalarvol * vol; + flt scalar, transval; + int x, y, z; + unsigned char * ptr; + + bx=(box *) tex->obj; + vol=(scalarvol *)bx->tex->img; + + col.r=0.0; + col.g=0.0; + col.b=0.0; + + tnear= -FHUGE; + tfar= FHUGE; + + if (ry->d.x == 0.0) { + if ((ry->o.x < bx->min.x) || (ry->o.x > bx->max.x)) return col; + } + else { + tx1 = (bx->min.x - ry->o.x) / ry->d.x; + tx2 = (bx->max.x - ry->o.x) / ry->d.x; + if (tx1 > tx2) { a=tx1; tx1=tx2; tx2=a; } + if (tx1 > tnear) tnear=tx1; + if (tx2 < tfar) tfar=tx2; + } + if (tnear > tfar) return col; + if (tfar < 0.0) return col; + + if (ry->d.y == 0.0) { + if ((ry->o.y < bx->min.y) || (ry->o.y > bx->max.y)) return col; + } + else { + ty1 = (bx->min.y - ry->o.y) / ry->d.y; + ty2 = (bx->max.y - ry->o.y) / ry->d.y; + if (ty1 > ty2) { a=ty1; ty1=ty2; ty2=a; } + if (ty1 > tnear) tnear=ty1; + if (ty2 < tfar) tfar=ty2; + } + if (tnear > tfar) return col; + if (tfar < 0.0) return col; + + if (ry->d.z == 0.0) { + if ((ry->o.z < bx->min.z) || (ry->o.z > bx->max.z)) return col; + } + else { + tz1 = (bx->min.z - ry->o.z) / ry->d.z; + tz2 = (bx->max.z - ry->o.z) / ry->d.z; + if (tz1 > tz2) { a=tz1; tz1=tz2; tz2=a; } + if (tz1 > tnear) tnear=tz1; + if (tz2 < tfar) tfar=tz2; + } + if (tnear > tfar) return col; + if (tfar < 0.0) return col; + + if (tnear < 0.0) tnear=0.0; + + tdist=sqrt((flt) (vol->xres*vol->xres + vol->yres*vol->yres + vol->zres*vol->zres)); + tt = (vol->opacity / tdist); + + bln.x=fabs(bx->min.x - bx->max.x); + bln.y=fabs(bx->min.y - bx->max.y); + bln.z=fabs(bx->min.z - bx->max.z); + + dt=sqrt(bln.x*bln.x + bln.y*bln.y + bln.z*bln.z) / tdist; + sum=0.0; + + /* move the volume residency check out of loop.. */ + if (!vol->loaded) { + LoadVol(vol); + vol->loaded=1; + } + + for (t=tnear; t<=tfar; t+=dt) { + pnt.x=((ry->o.x + (ry->d.x * t)) - bx->min.x) / bln.x; + pnt.y=((ry->o.y + (ry->d.y * t)) - bx->min.y) / bln.y; + pnt.z=((ry->o.z + (ry->d.z * t)) - bx->min.z) / bln.z; + + x=(int) ((vol->xres - 1.5) * pnt.x + 0.5); + y=(int) ((vol->yres - 1.5) * pnt.y + 0.5); + z=(int) ((vol->zres - 1.5) * pnt.z + 0.5); + + ptr = vol->data + ((vol->xres * vol->yres * z) + (vol->xres * y) + x); + + scalar = (flt) ((flt) 1.0 * ((int) ptr[0])) / 255.0; + + sum += tt * scalar; + + transval = tt * scalar; + + col2 = VoxelColor(scalar); + + if (sum < 1.0) { + col.r += transval * col2.r; + col.g += transval * col2.g; + col.b += transval * col2.b; + if (sum < 0.0) sum=0.0; + } + else { + sum=1.0; + } + } + + if (sum < 1.0) { /* spawn transmission rays / refraction */ + color transcol; + + transcol = shade_transmission(ry, hit, 1.0 - sum); + + col.r += transcol.r; /* add the transmitted ray */ + col.g += transcol.g; /* to the diffuse and */ + col.b += transcol.b; /* transmission total.. */ + } + + return col; +} + +void LoadVol(scalarvol * vol) { + FILE * dfile; + int status; + char msgtxt[2048]; + + dfile=fopen(vol->name, "r"); + if (dfile==NULL) { + char msgtxt[2048]; + sprintf(msgtxt, "Vol: can't open %s for input!!! Aborting\n",vol->name); + rt_ui_message(MSG_ERR, msgtxt); + rt_ui_message(MSG_ABORT, "Rendering Aborted."); + exit(1); + } + + sprintf(msgtxt, "loading %dx%dx%d volume set from %s", + vol->xres, vol->yres, vol->zres, vol->name); + rt_ui_message(MSG_0, msgtxt); + + vol->data = (unsigned char *)rt_getmem(vol->xres * vol->yres * vol->zres); + + status=fread(vol->data, 1, (vol->xres * vol->yres * vol->zres), dfile); +} diff --git a/src/tbb/examples/parallel_for/tachyon/src/vol.h b/src/tbb/examples/parallel_for/tachyon/src/vol.h new file mode 100644 index 0000000..130608a --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/src/vol.h @@ -0,0 +1,71 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + The original source for this example is + Copyright (c) 1994-2008 John E. Stone + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * vol.h - Volume rendering definitions etc. + * + * + * $Id: vol.h,v 1.2 2007-02-22 17:54:17 Exp $ + */ + + +void * newscalarvol(void * intex, vector min, vector max, + int xs, int ys, int zs, + char * fname, scalarvol * invol); + +void LoadVol(scalarvol *); +color scalar_volume_texture(vector *, texture *, ray *); diff --git a/src/tbb/examples/parallel_for/tachyon/xcode/tachyon.xcodeproj/project.pbxproj b/src/tbb/examples/parallel_for/tachyon/xcode/tachyon.xcodeproj/project.pbxproj new file mode 100644 index 0000000..b4ee8cc --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/xcode/tachyon.xcodeproj/project.pbxproj @@ -0,0 +1,938 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 840116E1152CBBF600B07E4D /* api.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116B6152CBBF600B07E4D /* api.cpp */; }; + 840116E2152CBBF600B07E4D /* apigeom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116B7152CBBF600B07E4D /* apigeom.cpp */; }; + 840116E3152CBBF600B07E4D /* apitrigeom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116B8152CBBF600B07E4D /* apitrigeom.cpp */; }; + 840116E4152CBBF600B07E4D /* bndbox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116B9152CBBF600B07E4D /* bndbox.cpp */; }; + 840116E5152CBBF600B07E4D /* box.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116BA152CBBF600B07E4D /* box.cpp */; }; + 840116E6152CBBF600B07E4D /* camera.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116BB152CBBF600B07E4D /* camera.cpp */; }; + 840116E7152CBBF600B07E4D /* coordsys.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116BC152CBBF600B07E4D /* coordsys.cpp */; }; + 840116E8152CBBF600B07E4D /* cylinder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116BD152CBBF600B07E4D /* cylinder.cpp */; }; + 840116E9152CBBF600B07E4D /* extvol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116BE152CBBF600B07E4D /* extvol.cpp */; }; + 840116EA152CBBF600B07E4D /* global.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116BF152CBBF600B07E4D /* global.cpp */; }; + 840116EB152CBBF600B07E4D /* grid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C0152CBBF600B07E4D /* grid.cpp */; }; + 840116EC152CBBF600B07E4D /* imageio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C1152CBBF600B07E4D /* imageio.cpp */; }; + 840116ED152CBBF600B07E4D /* imap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C2152CBBF600B07E4D /* imap.cpp */; }; + 840116EE152CBBF600B07E4D /* intersect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C3152CBBF600B07E4D /* intersect.cpp */; }; + 840116EF152CBBF600B07E4D /* jpeg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C4152CBBF600B07E4D /* jpeg.cpp */; }; + 840116F0152CBBF600B07E4D /* light.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C5152CBBF600B07E4D /* light.cpp */; }; + 840116F1152CBBF600B07E4D /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C6152CBBF600B07E4D /* main.cpp */; }; + 840116F2152CBBF600B07E4D /* objbound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C7152CBBF600B07E4D /* objbound.cpp */; }; + 840116F3152CBBF600B07E4D /* parse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C8152CBBF600B07E4D /* parse.cpp */; }; + 840116F4152CBBF600B07E4D /* plane.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C9152CBBF600B07E4D /* plane.cpp */; }; + 840116F5152CBBF600B07E4D /* ppm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116CA152CBBF600B07E4D /* ppm.cpp */; }; + 840116F6152CBBF600B07E4D /* pthread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116CB152CBBF600B07E4D /* pthread.cpp */; }; + 840116F7152CBBF600B07E4D /* quadric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116CC152CBBF600B07E4D /* quadric.cpp */; }; + 840116F8152CBBF600B07E4D /* render.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116CD152CBBF600B07E4D /* render.cpp */; }; + 840116F9152CBBF600B07E4D /* ring.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116CE152CBBF600B07E4D /* ring.cpp */; }; + 840116FA152CBBF600B07E4D /* shade.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116CF152CBBF600B07E4D /* shade.cpp */; }; + 840116FB152CBBF600B07E4D /* sphere.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116D0152CBBF600B07E4D /* sphere.cpp */; }; + 840116FC152CBBF600B07E4D /* tachyon_video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116D1152CBBF600B07E4D /* tachyon_video.cpp */; }; + 840116FD152CBBF600B07E4D /* texture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116D2152CBBF600B07E4D /* texture.cpp */; }; + 840116FE152CBBF600B07E4D /* tgafile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116D3152CBBF600B07E4D /* tgafile.cpp */; }; + 840116FF152CBBF600B07E4D /* trace_rest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116D4152CBBF600B07E4D /* trace_rest.cpp */; }; + 84011707152CBBF600B07E4D /* triangle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116DC152CBBF600B07E4D /* triangle.cpp */; }; + 84011708152CBBF600B07E4D /* ui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116DD152CBBF600B07E4D /* ui.cpp */; }; + 84011709152CBBF600B07E4D /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116DE152CBBF600B07E4D /* util.cpp */; }; + 8401170A152CBBF600B07E4D /* vector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116DF152CBBF600B07E4D /* vector.cpp */; }; + 8401170B152CBBF600B07E4D /* vol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116E0152CBBF600B07E4D /* vol.cpp */; }; + 8401172A152D6E3E00B07E4D /* trace.tbb.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84011729152D6E3E00B07E4D /* trace.tbb.cpp */; }; + 8401172D152D6F6C00B07E4D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA6F152CA90100D59B95 /* main.m */; }; + 8401172E152D6F6C00B07E4D /* OpenGLView.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA71152CA90100D59B95 /* OpenGLView.m */; }; + 8401172F152D6F6C00B07E4D /* tbbAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA73152CA90100D59B95 /* tbbAppDelegate.m */; }; + 84011730152D6F6C00B07E4D /* macvideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA99152CADF400D59B95 /* macvideo.cpp */; }; + 84011731152D6F6C00B07E4D /* api.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116B6152CBBF600B07E4D /* api.cpp */; }; + 84011732152D6F6C00B07E4D /* apigeom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116B7152CBBF600B07E4D /* apigeom.cpp */; }; + 84011733152D6F6C00B07E4D /* apitrigeom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116B8152CBBF600B07E4D /* apitrigeom.cpp */; }; + 84011734152D6F6C00B07E4D /* bndbox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116B9152CBBF600B07E4D /* bndbox.cpp */; }; + 84011735152D6F6C00B07E4D /* box.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116BA152CBBF600B07E4D /* box.cpp */; }; + 84011736152D6F6C00B07E4D /* camera.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116BB152CBBF600B07E4D /* camera.cpp */; }; + 84011737152D6F6C00B07E4D /* coordsys.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116BC152CBBF600B07E4D /* coordsys.cpp */; }; + 84011738152D6F6C00B07E4D /* cylinder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116BD152CBBF600B07E4D /* cylinder.cpp */; }; + 84011739152D6F6C00B07E4D /* extvol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116BE152CBBF600B07E4D /* extvol.cpp */; }; + 8401173A152D6F6C00B07E4D /* global.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116BF152CBBF600B07E4D /* global.cpp */; }; + 8401173B152D6F6C00B07E4D /* grid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C0152CBBF600B07E4D /* grid.cpp */; }; + 8401173C152D6F6C00B07E4D /* imageio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C1152CBBF600B07E4D /* imageio.cpp */; }; + 8401173D152D6F6C00B07E4D /* imap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C2152CBBF600B07E4D /* imap.cpp */; }; + 8401173E152D6F6C00B07E4D /* intersect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C3152CBBF600B07E4D /* intersect.cpp */; }; + 8401173F152D6F6C00B07E4D /* jpeg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C4152CBBF600B07E4D /* jpeg.cpp */; }; + 84011740152D6F6C00B07E4D /* light.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C5152CBBF600B07E4D /* light.cpp */; }; + 84011741152D6F6C00B07E4D /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C6152CBBF600B07E4D /* main.cpp */; }; + 84011742152D6F6C00B07E4D /* objbound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C7152CBBF600B07E4D /* objbound.cpp */; }; + 84011743152D6F6C00B07E4D /* parse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C8152CBBF600B07E4D /* parse.cpp */; }; + 84011744152D6F6C00B07E4D /* plane.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C9152CBBF600B07E4D /* plane.cpp */; }; + 84011745152D6F6C00B07E4D /* ppm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116CA152CBBF600B07E4D /* ppm.cpp */; }; + 84011746152D6F6C00B07E4D /* pthread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116CB152CBBF600B07E4D /* pthread.cpp */; }; + 84011747152D6F6C00B07E4D /* quadric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116CC152CBBF600B07E4D /* quadric.cpp */; }; + 84011748152D6F6C00B07E4D /* render.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116CD152CBBF600B07E4D /* render.cpp */; }; + 84011749152D6F6C00B07E4D /* ring.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116CE152CBBF600B07E4D /* ring.cpp */; }; + 8401174A152D6F6C00B07E4D /* shade.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116CF152CBBF600B07E4D /* shade.cpp */; }; + 8401174B152D6F6C00B07E4D /* sphere.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116D0152CBBF600B07E4D /* sphere.cpp */; }; + 8401174C152D6F6C00B07E4D /* tachyon_video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116D1152CBBF600B07E4D /* tachyon_video.cpp */; }; + 8401174D152D6F6C00B07E4D /* texture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116D2152CBBF600B07E4D /* texture.cpp */; }; + 8401174E152D6F6C00B07E4D /* tgafile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116D3152CBBF600B07E4D /* tgafile.cpp */; }; + 8401174F152D6F6C00B07E4D /* trace_rest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116D4152CBBF600B07E4D /* trace_rest.cpp */; }; + 84011750152D6F6C00B07E4D /* triangle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116DC152CBBF600B07E4D /* triangle.cpp */; }; + 84011751152D6F6C00B07E4D /* ui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116DD152CBBF600B07E4D /* ui.cpp */; }; + 84011752152D6F6C00B07E4D /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116DE152CBBF600B07E4D /* util.cpp */; }; + 84011753152D6F6C00B07E4D /* vector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116DF152CBBF600B07E4D /* vector.cpp */; }; + 84011754152D6F6C00B07E4D /* vol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116E0152CBBF600B07E4D /* vol.cpp */; }; + 84011757152D6F6C00B07E4D /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84D01775152744BD0008A4E0 /* OpenGL.framework */; }; + 84011758152D6F6C00B07E4D /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84D017551527431F0008A4E0 /* Cocoa.framework */; }; + 84011759152D6F6C00B07E4D /* libtbb.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 84B8DA13152C9AC600D59B95 /* libtbb.dylib */; }; + 8401175B152D6F6C00B07E4D /* (null) in Resources */ = {isa = PBXBuildFile; }; + 8401175C152D6F6C00B07E4D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 84B8DA7C152CA97B00D59B95 /* InfoPlist.strings */; }; + 8401175D152D6F6C00B07E4D /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 84B8DA7E152CA97B00D59B95 /* MainMenu.xib */; }; + 84011766152D6F8400B07E4D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA6F152CA90100D59B95 /* main.m */; }; + 84011767152D6F8400B07E4D /* OpenGLView.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA71152CA90100D59B95 /* OpenGLView.m */; }; + 84011768152D6F8400B07E4D /* tbbAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA73152CA90100D59B95 /* tbbAppDelegate.m */; }; + 84011769152D6F8400B07E4D /* macvideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA99152CADF400D59B95 /* macvideo.cpp */; }; + 8401176A152D6F8400B07E4D /* api.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116B6152CBBF600B07E4D /* api.cpp */; }; + 8401176B152D6F8400B07E4D /* apigeom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116B7152CBBF600B07E4D /* apigeom.cpp */; }; + 8401176C152D6F8400B07E4D /* apitrigeom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116B8152CBBF600B07E4D /* apitrigeom.cpp */; }; + 8401176D152D6F8400B07E4D /* bndbox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116B9152CBBF600B07E4D /* bndbox.cpp */; }; + 8401176E152D6F8400B07E4D /* box.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116BA152CBBF600B07E4D /* box.cpp */; }; + 8401176F152D6F8400B07E4D /* camera.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116BB152CBBF600B07E4D /* camera.cpp */; }; + 84011770152D6F8400B07E4D /* coordsys.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116BC152CBBF600B07E4D /* coordsys.cpp */; }; + 84011771152D6F8400B07E4D /* cylinder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116BD152CBBF600B07E4D /* cylinder.cpp */; }; + 84011772152D6F8400B07E4D /* extvol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116BE152CBBF600B07E4D /* extvol.cpp */; }; + 84011773152D6F8400B07E4D /* global.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116BF152CBBF600B07E4D /* global.cpp */; }; + 84011774152D6F8400B07E4D /* grid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C0152CBBF600B07E4D /* grid.cpp */; }; + 84011775152D6F8400B07E4D /* imageio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C1152CBBF600B07E4D /* imageio.cpp */; }; + 84011776152D6F8400B07E4D /* imap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C2152CBBF600B07E4D /* imap.cpp */; }; + 84011777152D6F8400B07E4D /* intersect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C3152CBBF600B07E4D /* intersect.cpp */; }; + 84011778152D6F8400B07E4D /* jpeg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C4152CBBF600B07E4D /* jpeg.cpp */; }; + 84011779152D6F8400B07E4D /* light.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C5152CBBF600B07E4D /* light.cpp */; }; + 8401177A152D6F8400B07E4D /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C6152CBBF600B07E4D /* main.cpp */; }; + 8401177B152D6F8400B07E4D /* objbound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C7152CBBF600B07E4D /* objbound.cpp */; }; + 8401177C152D6F8400B07E4D /* parse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C8152CBBF600B07E4D /* parse.cpp */; }; + 8401177D152D6F8400B07E4D /* plane.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116C9152CBBF600B07E4D /* plane.cpp */; }; + 8401177E152D6F8400B07E4D /* ppm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116CA152CBBF600B07E4D /* ppm.cpp */; }; + 8401177F152D6F8400B07E4D /* pthread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116CB152CBBF600B07E4D /* pthread.cpp */; }; + 84011780152D6F8400B07E4D /* quadric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116CC152CBBF600B07E4D /* quadric.cpp */; }; + 84011781152D6F8400B07E4D /* render.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116CD152CBBF600B07E4D /* render.cpp */; }; + 84011782152D6F8400B07E4D /* ring.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116CE152CBBF600B07E4D /* ring.cpp */; }; + 84011783152D6F8400B07E4D /* shade.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116CF152CBBF600B07E4D /* shade.cpp */; }; + 84011784152D6F8400B07E4D /* sphere.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116D0152CBBF600B07E4D /* sphere.cpp */; }; + 84011785152D6F8400B07E4D /* tachyon_video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116D1152CBBF600B07E4D /* tachyon_video.cpp */; }; + 84011786152D6F8400B07E4D /* texture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116D2152CBBF600B07E4D /* texture.cpp */; }; + 84011787152D6F8400B07E4D /* tgafile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116D3152CBBF600B07E4D /* tgafile.cpp */; }; + 84011788152D6F8400B07E4D /* trace_rest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116D4152CBBF600B07E4D /* trace_rest.cpp */; }; + 84011789152D6F8400B07E4D /* triangle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116DC152CBBF600B07E4D /* triangle.cpp */; }; + 8401178A152D6F8400B07E4D /* ui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116DD152CBBF600B07E4D /* ui.cpp */; }; + 8401178B152D6F8400B07E4D /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116DE152CBBF600B07E4D /* util.cpp */; }; + 8401178C152D6F8400B07E4D /* vector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116DF152CBBF600B07E4D /* vector.cpp */; }; + 8401178D152D6F8400B07E4D /* vol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 840116E0152CBBF600B07E4D /* vol.cpp */; }; + 84011790152D6F8400B07E4D /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84D01775152744BD0008A4E0 /* OpenGL.framework */; }; + 84011791152D6F8400B07E4D /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84D017551527431F0008A4E0 /* Cocoa.framework */; }; + 84011792152D6F8400B07E4D /* libtbb.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 84B8DA13152C9AC600D59B95 /* libtbb.dylib */; }; + 84011794152D6F8400B07E4D /* (null) in Resources */ = {isa = PBXBuildFile; }; + 84011795152D6F8400B07E4D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 84B8DA7C152CA97B00D59B95 /* InfoPlist.strings */; }; + 84011796152D6F8400B07E4D /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 84B8DA7E152CA97B00D59B95 /* MainMenu.xib */; }; + 840117A1152D6FF900B07E4D /* trace.serial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8401179F152D6FD100B07E4D /* trace.serial.cpp */; }; + 840117A2152D701A00B07E4D /* trace.tbb1d.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8401179D152D6FC600B07E4D /* trace.tbb1d.cpp */; }; + 84B8DA19152C9AC600D59B95 /* libtbb.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 84B8DA13152C9AC600D59B95 /* libtbb.dylib */; }; + 84B8DA77152CA90100D59B95 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA6F152CA90100D59B95 /* main.m */; }; + 84B8DA78152CA90100D59B95 /* OpenGLView.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA71152CA90100D59B95 /* OpenGLView.m */; }; + 84B8DA79152CA90100D59B95 /* tbbAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA73152CA90100D59B95 /* tbbAppDelegate.m */; }; + 84B8DA7A152CA90100D59B95 /* (null) in Resources */ = {isa = PBXBuildFile; }; + 84B8DA80152CA97B00D59B95 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 84B8DA7C152CA97B00D59B95 /* InfoPlist.strings */; }; + 84B8DA81152CA97B00D59B95 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 84B8DA7E152CA97B00D59B95 /* MainMenu.xib */; }; + 84B8DA9A152CADF400D59B95 /* macvideo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84B8DA99152CADF400D59B95 /* macvideo.cpp */; }; + 84D017561527431F0008A4E0 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84D017551527431F0008A4E0 /* Cocoa.framework */; }; + 84D01776152744BD0008A4E0 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84D01775152744BD0008A4E0 /* OpenGL.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 84011691152CBBC900B07E4D /* api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = api.h; path = ../src/api.h; sourceTree = ""; }; + 84011692152CBBC900B07E4D /* apitrigeom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = apitrigeom.h; path = ../src/apitrigeom.h; sourceTree = ""; }; + 84011693152CBBC900B07E4D /* bndbox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bndbox.h; path = ../src/bndbox.h; sourceTree = ""; }; + 84011694152CBBC900B07E4D /* box.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = box.h; path = ../src/box.h; sourceTree = ""; }; + 84011695152CBBC900B07E4D /* camera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = camera.h; path = ../src/camera.h; sourceTree = ""; }; + 84011696152CBBC900B07E4D /* coordsys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = coordsys.h; path = ../src/coordsys.h; sourceTree = ""; }; + 84011697152CBBC900B07E4D /* cylinder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cylinder.h; path = ../src/cylinder.h; sourceTree = ""; }; + 84011698152CBBC900B07E4D /* extvol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = extvol.h; path = ../src/extvol.h; sourceTree = ""; }; + 84011699152CBBC900B07E4D /* global.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = global.h; path = ../src/global.h; sourceTree = ""; }; + 8401169A152CBBC900B07E4D /* grid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = grid.h; path = ../src/grid.h; sourceTree = ""; }; + 8401169B152CBBC900B07E4D /* imageio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imageio.h; path = ../src/imageio.h; sourceTree = ""; }; + 8401169C152CBBC900B07E4D /* imap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imap.h; path = ../src/imap.h; sourceTree = ""; }; + 8401169D152CBBC900B07E4D /* intersect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = intersect.h; path = ../src/intersect.h; sourceTree = ""; }; + 8401169E152CBBC900B07E4D /* jpeg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = jpeg.h; path = ../src/jpeg.h; sourceTree = ""; }; + 8401169F152CBBC900B07E4D /* light.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = light.h; path = ../src/light.h; sourceTree = ""; }; + 840116A0152CBBC900B07E4D /* machine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = machine.h; path = ../src/machine.h; sourceTree = ""; }; + 840116A1152CBBC900B07E4D /* macros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = macros.h; path = ../src/macros.h; sourceTree = ""; }; + 840116A2152CBBC900B07E4D /* objbound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = objbound.h; path = ../src/objbound.h; sourceTree = ""; }; + 840116A3152CBBC900B07E4D /* parse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = parse.h; path = ../src/parse.h; sourceTree = ""; }; + 840116A4152CBBC900B07E4D /* plane.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = plane.h; path = ../src/plane.h; sourceTree = ""; }; + 840116A5152CBBC900B07E4D /* ppm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ppm.h; path = ../src/ppm.h; sourceTree = ""; }; + 840116A7152CBBC900B07E4D /* quadric.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = quadric.h; path = ../src/quadric.h; sourceTree = ""; }; + 840116A8152CBBC900B07E4D /* render.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = render.h; path = ../src/render.h; sourceTree = ""; }; + 840116A9152CBBC900B07E4D /* ring.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ring.h; path = ../src/ring.h; sourceTree = ""; }; + 840116AA152CBBC900B07E4D /* shade.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = shade.h; path = ../src/shade.h; sourceTree = ""; }; + 840116AB152CBBC900B07E4D /* sphere.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sphere.h; path = ../src/sphere.h; sourceTree = ""; }; + 840116AC152CBBC900B07E4D /* tachyon_video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tachyon_video.h; path = ../src/tachyon_video.h; sourceTree = ""; }; + 840116AD152CBBC900B07E4D /* texture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = texture.h; path = ../src/texture.h; sourceTree = ""; }; + 840116AE152CBBC900B07E4D /* tgafile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tgafile.h; path = ../src/tgafile.h; sourceTree = ""; }; + 840116AF152CBBC900B07E4D /* trace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = trace.h; path = ../src/trace.h; sourceTree = ""; }; + 840116B0152CBBC900B07E4D /* triangle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = triangle.h; path = ../src/triangle.h; sourceTree = ""; }; + 840116B1152CBBC900B07E4D /* types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = types.h; path = ../src/types.h; sourceTree = ""; }; + 840116B2152CBBC900B07E4D /* ui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ui.h; path = ../src/ui.h; sourceTree = ""; }; + 840116B3152CBBC900B07E4D /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = util.h; path = ../src/util.h; sourceTree = ""; }; + 840116B4152CBBC900B07E4D /* vector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vector.h; path = ../src/vector.h; sourceTree = ""; }; + 840116B5152CBBC900B07E4D /* vol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vol.h; path = ../src/vol.h; sourceTree = ""; }; + 840116B6152CBBF600B07E4D /* api.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = api.cpp; sourceTree = ""; }; + 840116B7152CBBF600B07E4D /* apigeom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = apigeom.cpp; sourceTree = ""; }; + 840116B8152CBBF600B07E4D /* apitrigeom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = apitrigeom.cpp; sourceTree = ""; }; + 840116B9152CBBF600B07E4D /* bndbox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bndbox.cpp; sourceTree = ""; }; + 840116BA152CBBF600B07E4D /* box.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = box.cpp; sourceTree = ""; }; + 840116BB152CBBF600B07E4D /* camera.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = camera.cpp; sourceTree = ""; }; + 840116BC152CBBF600B07E4D /* coordsys.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = coordsys.cpp; sourceTree = ""; }; + 840116BD152CBBF600B07E4D /* cylinder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cylinder.cpp; sourceTree = ""; }; + 840116BE152CBBF600B07E4D /* extvol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = extvol.cpp; sourceTree = ""; }; + 840116BF152CBBF600B07E4D /* global.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = global.cpp; sourceTree = ""; }; + 840116C0152CBBF600B07E4D /* grid.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = grid.cpp; sourceTree = ""; }; + 840116C1152CBBF600B07E4D /* imageio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imageio.cpp; sourceTree = ""; }; + 840116C2152CBBF600B07E4D /* imap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imap.cpp; sourceTree = ""; }; + 840116C3152CBBF600B07E4D /* intersect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = intersect.cpp; sourceTree = ""; }; + 840116C4152CBBF600B07E4D /* jpeg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = jpeg.cpp; sourceTree = ""; }; + 840116C5152CBBF600B07E4D /* light.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = light.cpp; sourceTree = ""; }; + 840116C6152CBBF600B07E4D /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 840116C7152CBBF600B07E4D /* objbound.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = objbound.cpp; sourceTree = ""; }; + 840116C8152CBBF600B07E4D /* parse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parse.cpp; sourceTree = ""; }; + 840116C9152CBBF600B07E4D /* plane.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = plane.cpp; sourceTree = ""; }; + 840116CA152CBBF600B07E4D /* ppm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ppm.cpp; sourceTree = ""; }; + 840116CB152CBBF600B07E4D /* pthread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pthread.cpp; sourceTree = ""; }; + 840116CC152CBBF600B07E4D /* quadric.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = quadric.cpp; sourceTree = ""; }; + 840116CD152CBBF600B07E4D /* render.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = render.cpp; sourceTree = ""; }; + 840116CE152CBBF600B07E4D /* ring.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ring.cpp; sourceTree = ""; }; + 840116CF152CBBF600B07E4D /* shade.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shade.cpp; sourceTree = ""; }; + 840116D0152CBBF600B07E4D /* sphere.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sphere.cpp; sourceTree = ""; }; + 840116D1152CBBF600B07E4D /* tachyon_video.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tachyon_video.cpp; sourceTree = ""; }; + 840116D2152CBBF600B07E4D /* texture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = texture.cpp; sourceTree = ""; }; + 840116D3152CBBF600B07E4D /* tgafile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tgafile.cpp; sourceTree = ""; }; + 840116D4152CBBF600B07E4D /* trace_rest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = trace_rest.cpp; sourceTree = ""; }; + 840116DC152CBBF600B07E4D /* triangle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = triangle.cpp; sourceTree = ""; }; + 840116DD152CBBF600B07E4D /* ui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ui.cpp; sourceTree = ""; }; + 840116DE152CBBF600B07E4D /* util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = util.cpp; sourceTree = ""; }; + 840116DF152CBBF600B07E4D /* vector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vector.cpp; sourceTree = ""; }; + 840116E0152CBBF600B07E4D /* vol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vol.cpp; sourceTree = ""; }; + 84011729152D6E3E00B07E4D /* trace.tbb.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = trace.tbb.cpp; sourceTree = ""; }; + 84011761152D6F6C00B07E4D /* tachyon.serial.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = tachyon.serial.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 8401179A152D6F8400B07E4D /* tachyon.tbb1d.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = tachyon.tbb1d.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 8401179D152D6FC600B07E4D /* trace.tbb1d.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = trace.tbb1d.cpp; sourceTree = ""; }; + 8401179F152D6FD100B07E4D /* trace.serial.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = trace.serial.cpp; sourceTree = ""; }; + 84B8DA13152C9AC600D59B95 /* libtbb.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtbb.dylib; path = ../../../../lib/libtbb.dylib; sourceTree = ""; }; + 84B8DA6F152CA90100D59B95 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = ../../../common/gui/xcode/tbbExample/main.m; sourceTree = ""; }; + 84B8DA70152CA90100D59B95 /* OpenGLView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenGLView.h; path = ../../../common/gui/xcode/tbbExample/OpenGLView.h; sourceTree = ""; }; + 84B8DA71152CA90100D59B95 /* OpenGLView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OpenGLView.m; path = ../../../common/gui/xcode/tbbExample/OpenGLView.m; sourceTree = ""; }; + 84B8DA72152CA90100D59B95 /* tbbAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tbbAppDelegate.h; path = ../../../common/gui/xcode/tbbExample/tbbAppDelegate.h; sourceTree = ""; }; + 84B8DA73152CA90100D59B95 /* tbbAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = tbbAppDelegate.m; path = ../../../common/gui/xcode/tbbExample/tbbAppDelegate.m; sourceTree = ""; }; + 84B8DA75152CA90100D59B95 /* tbbExample-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "tbbExample-Prefix.pch"; path = "../../../common/gui/xcode/tbbExample/tbbExample-Prefix.pch"; sourceTree = ""; }; + 84B8DA7D152CA97B00D59B95 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = InfoPlist.strings; sourceTree = ""; }; + 84B8DA7F152CA97B00D59B95 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = MainMenu.xib; sourceTree = ""; }; + 84B8DA99152CADF400D59B95 /* macvideo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = macvideo.cpp; path = ../../../common/gui/macvideo.cpp; sourceTree = ""; }; + 84D017511527431F0008A4E0 /* tbbExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = tbbExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 84D017551527431F0008A4E0 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + 84D017581527431F0008A4E0 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + 84D017591527431F0008A4E0 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; + 84D0175A1527431F0008A4E0 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 84D01775152744BD0008A4E0 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 84011756152D6F6C00B07E4D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 84011757152D6F6C00B07E4D /* OpenGL.framework in Frameworks */, + 84011758152D6F6C00B07E4D /* Cocoa.framework in Frameworks */, + 84011759152D6F6C00B07E4D /* libtbb.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8401178F152D6F8400B07E4D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 84011790152D6F8400B07E4D /* OpenGL.framework in Frameworks */, + 84011791152D6F8400B07E4D /* Cocoa.framework in Frameworks */, + 84011792152D6F8400B07E4D /* libtbb.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84D0174E1527431F0008A4E0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 84D01776152744BD0008A4E0 /* OpenGL.framework in Frameworks */, + 84D017561527431F0008A4E0 /* Cocoa.framework in Frameworks */, + 84B8DA19152C9AC600D59B95 /* libtbb.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 8401160E152CB8A600B07E4D /* Sources */ = { + isa = PBXGroup; + children = ( + 8401179F152D6FD100B07E4D /* trace.serial.cpp */, + 8401179D152D6FC600B07E4D /* trace.tbb1d.cpp */, + 84011729152D6E3E00B07E4D /* trace.tbb.cpp */, + 840116B6152CBBF600B07E4D /* api.cpp */, + 840116B7152CBBF600B07E4D /* apigeom.cpp */, + 840116B8152CBBF600B07E4D /* apitrigeom.cpp */, + 840116B9152CBBF600B07E4D /* bndbox.cpp */, + 840116BA152CBBF600B07E4D /* box.cpp */, + 840116BB152CBBF600B07E4D /* camera.cpp */, + 840116BC152CBBF600B07E4D /* coordsys.cpp */, + 840116BD152CBBF600B07E4D /* cylinder.cpp */, + 840116BE152CBBF600B07E4D /* extvol.cpp */, + 840116BF152CBBF600B07E4D /* global.cpp */, + 840116C0152CBBF600B07E4D /* grid.cpp */, + 840116C1152CBBF600B07E4D /* imageio.cpp */, + 840116C2152CBBF600B07E4D /* imap.cpp */, + 840116C3152CBBF600B07E4D /* intersect.cpp */, + 840116C4152CBBF600B07E4D /* jpeg.cpp */, + 840116C5152CBBF600B07E4D /* light.cpp */, + 840116C6152CBBF600B07E4D /* main.cpp */, + 840116C7152CBBF600B07E4D /* objbound.cpp */, + 840116C8152CBBF600B07E4D /* parse.cpp */, + 840116C9152CBBF600B07E4D /* plane.cpp */, + 840116CA152CBBF600B07E4D /* ppm.cpp */, + 840116CB152CBBF600B07E4D /* pthread.cpp */, + 840116CC152CBBF600B07E4D /* quadric.cpp */, + 840116CD152CBBF600B07E4D /* render.cpp */, + 840116CE152CBBF600B07E4D /* ring.cpp */, + 840116CF152CBBF600B07E4D /* shade.cpp */, + 840116D0152CBBF600B07E4D /* sphere.cpp */, + 840116D1152CBBF600B07E4D /* tachyon_video.cpp */, + 840116D2152CBBF600B07E4D /* texture.cpp */, + 840116D3152CBBF600B07E4D /* tgafile.cpp */, + 840116D4152CBBF600B07E4D /* trace_rest.cpp */, + 840116DC152CBBF600B07E4D /* triangle.cpp */, + 840116DD152CBBF600B07E4D /* ui.cpp */, + 840116DE152CBBF600B07E4D /* util.cpp */, + 840116DF152CBBF600B07E4D /* vector.cpp */, + 840116E0152CBBF600B07E4D /* vol.cpp */, + ); + name = Sources; + path = ../src; + sourceTree = ""; + }; + 84011690152CBB3C00B07E4D /* Headers */ = { + isa = PBXGroup; + children = ( + 84011691152CBBC900B07E4D /* api.h */, + 84011692152CBBC900B07E4D /* apitrigeom.h */, + 84011693152CBBC900B07E4D /* bndbox.h */, + 84011694152CBBC900B07E4D /* box.h */, + 84011695152CBBC900B07E4D /* camera.h */, + 84011696152CBBC900B07E4D /* coordsys.h */, + 84011697152CBBC900B07E4D /* cylinder.h */, + 84011698152CBBC900B07E4D /* extvol.h */, + 84011699152CBBC900B07E4D /* global.h */, + 8401169A152CBBC900B07E4D /* grid.h */, + 8401169B152CBBC900B07E4D /* imageio.h */, + 8401169C152CBBC900B07E4D /* imap.h */, + 8401169D152CBBC900B07E4D /* intersect.h */, + 8401169E152CBBC900B07E4D /* jpeg.h */, + 8401169F152CBBC900B07E4D /* light.h */, + 840116A0152CBBC900B07E4D /* machine.h */, + 840116A1152CBBC900B07E4D /* macros.h */, + 840116A2152CBBC900B07E4D /* objbound.h */, + 840116A3152CBBC900B07E4D /* parse.h */, + 840116A4152CBBC900B07E4D /* plane.h */, + 840116A5152CBBC900B07E4D /* ppm.h */, + 840116A7152CBBC900B07E4D /* quadric.h */, + 840116A8152CBBC900B07E4D /* render.h */, + 840116A9152CBBC900B07E4D /* ring.h */, + 840116AA152CBBC900B07E4D /* shade.h */, + 840116AB152CBBC900B07E4D /* sphere.h */, + 840116AC152CBBC900B07E4D /* tachyon_video.h */, + 840116AD152CBBC900B07E4D /* texture.h */, + 840116AE152CBBC900B07E4D /* tgafile.h */, + 840116AF152CBBC900B07E4D /* trace.h */, + 840116B0152CBBC900B07E4D /* triangle.h */, + 840116B1152CBBC900B07E4D /* types.h */, + 840116B2152CBBC900B07E4D /* ui.h */, + 840116B3152CBBC900B07E4D /* util.h */, + 840116B4152CBBC900B07E4D /* vector.h */, + 840116B5152CBBC900B07E4D /* vol.h */, + ); + name = Headers; + sourceTree = ""; + }; + 84B8DA6C152CA8D900D59B95 /* tbbExample */ = { + isa = PBXGroup; + children = ( + 84011690152CBB3C00B07E4D /* Headers */, + 8401160E152CB8A600B07E4D /* Sources */, + 84B8DA98152CAD8600D59B95 /* Gui layer */, + 84B8DA7B152CA97B00D59B95 /* Resources */, + ); + name = tbbExample; + sourceTree = ""; + }; + 84B8DA7B152CA97B00D59B95 /* Resources */ = { + isa = PBXGroup; + children = ( + 84B8DA7C152CA97B00D59B95 /* InfoPlist.strings */, + 84B8DA7E152CA97B00D59B95 /* MainMenu.xib */, + ); + name = Resources; + path = ../../../common/gui/xcode/tbbExample/en.lproj; + sourceTree = ""; + }; + 84B8DA98152CAD8600D59B95 /* Gui layer */ = { + isa = PBXGroup; + children = ( + 84B8DA99152CADF400D59B95 /* macvideo.cpp */, + 84B8DA6F152CA90100D59B95 /* main.m */, + 84B8DA70152CA90100D59B95 /* OpenGLView.h */, + 84B8DA71152CA90100D59B95 /* OpenGLView.m */, + 84B8DA72152CA90100D59B95 /* tbbAppDelegate.h */, + 84B8DA73152CA90100D59B95 /* tbbAppDelegate.m */, + 84B8DA75152CA90100D59B95 /* tbbExample-Prefix.pch */, + ); + name = "Gui layer"; + sourceTree = ""; + }; + 84D017461527431F0008A4E0 = { + isa = PBXGroup; + children = ( + 84B8DA6C152CA8D900D59B95 /* tbbExample */, + 84D017541527431F0008A4E0 /* Frameworks */, + 84D017521527431F0008A4E0 /* Products */, + 84011763152D6F6D00B07E4D /* tbbExample copy-Info.plist */, + 8401179C152D6F8500B07E4D /* tbbExample copy copy-Info.plist */, + ); + sourceTree = ""; + }; + 84D017521527431F0008A4E0 /* Products */ = { + isa = PBXGroup; + children = ( + 84D017511527431F0008A4E0 /* tbbExample.app */, + 84011761152D6F6C00B07E4D /* tachyon.serial.app */, + 8401179A152D6F8400B07E4D /* tachyon.tbb1d.app */, + ); + name = Products; + sourceTree = ""; + }; + 84D017541527431F0008A4E0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 84D01775152744BD0008A4E0 /* OpenGL.framework */, + 84D017551527431F0008A4E0 /* Cocoa.framework */, + 84D017571527431F0008A4E0 /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; + 84D017571527431F0008A4E0 /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 84B8DA13152C9AC600D59B95 /* libtbb.dylib */, + 84D017581527431F0008A4E0 /* AppKit.framework */, + 84D017591527431F0008A4E0 /* CoreData.framework */, + 84D0175A1527431F0008A4E0 /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8401172B152D6F6C00B07E4D /* tachyon.serial */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8401175E152D6F6C00B07E4D /* Build configuration list for PBXNativeTarget "tachyon.serial" */; + buildPhases = ( + 8401172C152D6F6C00B07E4D /* Sources */, + 84011756152D6F6C00B07E4D /* Frameworks */, + 8401175A152D6F6C00B07E4D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = tachyon.serial; + productName = tbbExample; + productReference = 84011761152D6F6C00B07E4D /* tachyon.serial.app */; + productType = "com.apple.product-type.application"; + }; + 84011764152D6F8400B07E4D /* tachyon.tbb1d */ = { + isa = PBXNativeTarget; + buildConfigurationList = 84011797152D6F8400B07E4D /* Build configuration list for PBXNativeTarget "tachyon.tbb1d" */; + buildPhases = ( + 84011765152D6F8400B07E4D /* Sources */, + 8401178F152D6F8400B07E4D /* Frameworks */, + 84011793152D6F8400B07E4D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = tachyon.tbb1d; + productName = tbbExample; + productReference = 8401179A152D6F8400B07E4D /* tachyon.tbb1d.app */; + productType = "com.apple.product-type.application"; + }; + 84D017501527431F0008A4E0 /* tachyon.tbb */ = { + isa = PBXNativeTarget; + buildConfigurationList = 84D01772152743200008A4E0 /* Build configuration list for PBXNativeTarget "tachyon.tbb" */; + buildPhases = ( + 84D0174D1527431F0008A4E0 /* Sources */, + 84D0174E1527431F0008A4E0 /* Frameworks */, + 84D0174F1527431F0008A4E0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = tachyon.tbb; + productName = tbbExample; + productReference = 84D017511527431F0008A4E0 /* tbbExample.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 84D017481527431F0008A4E0 /* Project object */ = { + isa = PBXProject; + attributes = { + CLASSPREFIX = tbb; + LastUpgradeCheck = 0430; + }; + buildConfigurationList = 84D0174B1527431F0008A4E0 /* Build configuration list for PBXProject "tachyon" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 84D017461527431F0008A4E0; + productRefGroup = 84D017521527431F0008A4E0 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 84D017501527431F0008A4E0 /* tachyon.tbb */, + 8401172B152D6F6C00B07E4D /* tachyon.serial */, + 84011764152D6F8400B07E4D /* tachyon.tbb1d */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 8401175A152D6F6C00B07E4D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8401175B152D6F6C00B07E4D /* (null) in Resources */, + 8401175C152D6F6C00B07E4D /* InfoPlist.strings in Resources */, + 8401175D152D6F6C00B07E4D /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84011793152D6F8400B07E4D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 84011794152D6F8400B07E4D /* (null) in Resources */, + 84011795152D6F8400B07E4D /* InfoPlist.strings in Resources */, + 84011796152D6F8400B07E4D /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84D0174F1527431F0008A4E0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 84B8DA7A152CA90100D59B95 /* (null) in Resources */, + 84B8DA80152CA97B00D59B95 /* InfoPlist.strings in Resources */, + 84B8DA81152CA97B00D59B95 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8401172C152D6F6C00B07E4D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 840117A1152D6FF900B07E4D /* trace.serial.cpp in Sources */, + 8401172D152D6F6C00B07E4D /* main.m in Sources */, + 8401172E152D6F6C00B07E4D /* OpenGLView.m in Sources */, + 8401172F152D6F6C00B07E4D /* tbbAppDelegate.m in Sources */, + 84011730152D6F6C00B07E4D /* macvideo.cpp in Sources */, + 84011731152D6F6C00B07E4D /* api.cpp in Sources */, + 84011732152D6F6C00B07E4D /* apigeom.cpp in Sources */, + 84011733152D6F6C00B07E4D /* apitrigeom.cpp in Sources */, + 84011734152D6F6C00B07E4D /* bndbox.cpp in Sources */, + 84011735152D6F6C00B07E4D /* box.cpp in Sources */, + 84011736152D6F6C00B07E4D /* camera.cpp in Sources */, + 84011737152D6F6C00B07E4D /* coordsys.cpp in Sources */, + 84011738152D6F6C00B07E4D /* cylinder.cpp in Sources */, + 84011739152D6F6C00B07E4D /* extvol.cpp in Sources */, + 8401173A152D6F6C00B07E4D /* global.cpp in Sources */, + 8401173B152D6F6C00B07E4D /* grid.cpp in Sources */, + 8401173C152D6F6C00B07E4D /* imageio.cpp in Sources */, + 8401173D152D6F6C00B07E4D /* imap.cpp in Sources */, + 8401173E152D6F6C00B07E4D /* intersect.cpp in Sources */, + 8401173F152D6F6C00B07E4D /* jpeg.cpp in Sources */, + 84011740152D6F6C00B07E4D /* light.cpp in Sources */, + 84011741152D6F6C00B07E4D /* main.cpp in Sources */, + 84011742152D6F6C00B07E4D /* objbound.cpp in Sources */, + 84011743152D6F6C00B07E4D /* parse.cpp in Sources */, + 84011744152D6F6C00B07E4D /* plane.cpp in Sources */, + 84011745152D6F6C00B07E4D /* ppm.cpp in Sources */, + 84011746152D6F6C00B07E4D /* pthread.cpp in Sources */, + 84011747152D6F6C00B07E4D /* quadric.cpp in Sources */, + 84011748152D6F6C00B07E4D /* render.cpp in Sources */, + 84011749152D6F6C00B07E4D /* ring.cpp in Sources */, + 8401174A152D6F6C00B07E4D /* shade.cpp in Sources */, + 8401174B152D6F6C00B07E4D /* sphere.cpp in Sources */, + 8401174C152D6F6C00B07E4D /* tachyon_video.cpp in Sources */, + 8401174D152D6F6C00B07E4D /* texture.cpp in Sources */, + 8401174E152D6F6C00B07E4D /* tgafile.cpp in Sources */, + 8401174F152D6F6C00B07E4D /* trace_rest.cpp in Sources */, + 84011750152D6F6C00B07E4D /* triangle.cpp in Sources */, + 84011751152D6F6C00B07E4D /* ui.cpp in Sources */, + 84011752152D6F6C00B07E4D /* util.cpp in Sources */, + 84011753152D6F6C00B07E4D /* vector.cpp in Sources */, + 84011754152D6F6C00B07E4D /* vol.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84011765152D6F8400B07E4D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 840117A2152D701A00B07E4D /* trace.tbb1d.cpp in Sources */, + 84011766152D6F8400B07E4D /* main.m in Sources */, + 84011767152D6F8400B07E4D /* OpenGLView.m in Sources */, + 84011768152D6F8400B07E4D /* tbbAppDelegate.m in Sources */, + 84011769152D6F8400B07E4D /* macvideo.cpp in Sources */, + 8401176A152D6F8400B07E4D /* api.cpp in Sources */, + 8401176B152D6F8400B07E4D /* apigeom.cpp in Sources */, + 8401176C152D6F8400B07E4D /* apitrigeom.cpp in Sources */, + 8401176D152D6F8400B07E4D /* bndbox.cpp in Sources */, + 8401176E152D6F8400B07E4D /* box.cpp in Sources */, + 8401176F152D6F8400B07E4D /* camera.cpp in Sources */, + 84011770152D6F8400B07E4D /* coordsys.cpp in Sources */, + 84011771152D6F8400B07E4D /* cylinder.cpp in Sources */, + 84011772152D6F8400B07E4D /* extvol.cpp in Sources */, + 84011773152D6F8400B07E4D /* global.cpp in Sources */, + 84011774152D6F8400B07E4D /* grid.cpp in Sources */, + 84011775152D6F8400B07E4D /* imageio.cpp in Sources */, + 84011776152D6F8400B07E4D /* imap.cpp in Sources */, + 84011777152D6F8400B07E4D /* intersect.cpp in Sources */, + 84011778152D6F8400B07E4D /* jpeg.cpp in Sources */, + 84011779152D6F8400B07E4D /* light.cpp in Sources */, + 8401177A152D6F8400B07E4D /* main.cpp in Sources */, + 8401177B152D6F8400B07E4D /* objbound.cpp in Sources */, + 8401177C152D6F8400B07E4D /* parse.cpp in Sources */, + 8401177D152D6F8400B07E4D /* plane.cpp in Sources */, + 8401177E152D6F8400B07E4D /* ppm.cpp in Sources */, + 8401177F152D6F8400B07E4D /* pthread.cpp in Sources */, + 84011780152D6F8400B07E4D /* quadric.cpp in Sources */, + 84011781152D6F8400B07E4D /* render.cpp in Sources */, + 84011782152D6F8400B07E4D /* ring.cpp in Sources */, + 84011783152D6F8400B07E4D /* shade.cpp in Sources */, + 84011784152D6F8400B07E4D /* sphere.cpp in Sources */, + 84011785152D6F8400B07E4D /* tachyon_video.cpp in Sources */, + 84011786152D6F8400B07E4D /* texture.cpp in Sources */, + 84011787152D6F8400B07E4D /* tgafile.cpp in Sources */, + 84011788152D6F8400B07E4D /* trace_rest.cpp in Sources */, + 84011789152D6F8400B07E4D /* triangle.cpp in Sources */, + 8401178A152D6F8400B07E4D /* ui.cpp in Sources */, + 8401178B152D6F8400B07E4D /* util.cpp in Sources */, + 8401178C152D6F8400B07E4D /* vector.cpp in Sources */, + 8401178D152D6F8400B07E4D /* vol.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84D0174D1527431F0008A4E0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 84B8DA77152CA90100D59B95 /* main.m in Sources */, + 84B8DA78152CA90100D59B95 /* OpenGLView.m in Sources */, + 84B8DA79152CA90100D59B95 /* tbbAppDelegate.m in Sources */, + 84B8DA9A152CADF400D59B95 /* macvideo.cpp in Sources */, + 840116E1152CBBF600B07E4D /* api.cpp in Sources */, + 840116E2152CBBF600B07E4D /* apigeom.cpp in Sources */, + 840116E3152CBBF600B07E4D /* apitrigeom.cpp in Sources */, + 840116E4152CBBF600B07E4D /* bndbox.cpp in Sources */, + 840116E5152CBBF600B07E4D /* box.cpp in Sources */, + 840116E6152CBBF600B07E4D /* camera.cpp in Sources */, + 840116E7152CBBF600B07E4D /* coordsys.cpp in Sources */, + 840116E8152CBBF600B07E4D /* cylinder.cpp in Sources */, + 840116E9152CBBF600B07E4D /* extvol.cpp in Sources */, + 840116EA152CBBF600B07E4D /* global.cpp in Sources */, + 840116EB152CBBF600B07E4D /* grid.cpp in Sources */, + 840116EC152CBBF600B07E4D /* imageio.cpp in Sources */, + 840116ED152CBBF600B07E4D /* imap.cpp in Sources */, + 840116EE152CBBF600B07E4D /* intersect.cpp in Sources */, + 840116EF152CBBF600B07E4D /* jpeg.cpp in Sources */, + 840116F0152CBBF600B07E4D /* light.cpp in Sources */, + 840116F1152CBBF600B07E4D /* main.cpp in Sources */, + 840116F2152CBBF600B07E4D /* objbound.cpp in Sources */, + 840116F3152CBBF600B07E4D /* parse.cpp in Sources */, + 840116F4152CBBF600B07E4D /* plane.cpp in Sources */, + 840116F5152CBBF600B07E4D /* ppm.cpp in Sources */, + 840116F6152CBBF600B07E4D /* pthread.cpp in Sources */, + 840116F7152CBBF600B07E4D /* quadric.cpp in Sources */, + 840116F8152CBBF600B07E4D /* render.cpp in Sources */, + 840116F9152CBBF600B07E4D /* ring.cpp in Sources */, + 840116FA152CBBF600B07E4D /* shade.cpp in Sources */, + 840116FB152CBBF600B07E4D /* sphere.cpp in Sources */, + 840116FC152CBBF600B07E4D /* tachyon_video.cpp in Sources */, + 840116FD152CBBF600B07E4D /* texture.cpp in Sources */, + 840116FE152CBBF600B07E4D /* tgafile.cpp in Sources */, + 840116FF152CBBF600B07E4D /* trace_rest.cpp in Sources */, + 84011707152CBBF600B07E4D /* triangle.cpp in Sources */, + 84011708152CBBF600B07E4D /* ui.cpp in Sources */, + 84011709152CBBF600B07E4D /* util.cpp in Sources */, + 8401170A152CBBF600B07E4D /* vector.cpp in Sources */, + 8401170B152CBBF600B07E4D /* vol.cpp in Sources */, + 8401172A152D6E3E00B07E4D /* trace.tbb.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 84B8DA7C152CA97B00D59B95 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 84B8DA7D152CA97B00D59B95 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 84B8DA7E152CA97B00D59B95 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 84B8DA7F152CA97B00D59B95 /* en */, + ); + name = MainMenu.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 8401175F152D6F6C00B07E4D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "../../../common/gui/xcode/tbbExample/tbbExample-Prefix.pch"; + HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../include\""; + INFOPLIST_FILE = "../../../common/gui/xcode/tbbExample/tbbExample-Info.plist"; + LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/../../../../lib\""; + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_NAME = tachyon.serial; + RUN_CLANG_STATIC_ANALYZER = YES; + USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../include\""; + VERSION_INFO_BUILDER = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 84011760152D6F6C00B07E4D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "../../../common/gui/xcode/tbbExample/tbbExample-Prefix.pch"; + HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../include\""; + INFOPLIST_FILE = "../../../common/gui/xcode/tbbExample/tbbExample-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "\"$(SRCROOT)/../../../../lib\"", + "\"$(SRCROOT)\"", + ); + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_NAME = tachyon.serial; + RUN_CLANG_STATIC_ANALYZER = YES; + USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../include\""; + VERSION_INFO_BUILDER = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; + 84011798152D6F8400B07E4D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "../../../common/gui/xcode/tbbExample/tbbExample-Prefix.pch"; + HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../include\""; + INFOPLIST_FILE = "../../../common/gui/xcode/tbbExample/tbbExample-Info.plist"; + LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/../../../../lib\""; + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_NAME = tachyon.tbb1d; + RUN_CLANG_STATIC_ANALYZER = YES; + USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../include\""; + VERSION_INFO_BUILDER = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 84011799152D6F8400B07E4D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "../../../common/gui/xcode/tbbExample/tbbExample-Prefix.pch"; + HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../include\""; + INFOPLIST_FILE = "../../../common/gui/xcode/tbbExample/tbbExample-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "\"$(SRCROOT)/../../../../lib\"", + "\"$(SRCROOT)\"", + ); + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_NAME = tachyon.tbb1d; + RUN_CLANG_STATIC_ANALYZER = YES; + USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../include\""; + VERSION_INFO_BUILDER = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; + 84D01770152743200008A4E0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 84D01771152743200008A4E0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + SDKROOT = macosx; + }; + name = Release; + }; + 84D01773152743200008A4E0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "../../../common/gui/xcode/tbbExample/tbbExample-Prefix.pch"; + HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../include\""; + INFOPLIST_FILE = "../../../common/gui/xcode/tbbExample/tbbExample-Info.plist"; + LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/../../../../lib\""; + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_NAME = "$(TARGET_NAME)"; + RUN_CLANG_STATIC_ANALYZER = YES; + USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../include\""; + VERSION_INFO_BUILDER = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 84D01774152743200008A4E0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "../../../common/gui/xcode/tbbExample/tbbExample-Prefix.pch"; + HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../include\""; + INFOPLIST_FILE = "../../../common/gui/xcode/tbbExample/tbbExample-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "\"$(SRCROOT)/../../../../lib\"", + "\"$(SRCROOT)\"", + ); + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_NAME = "$(TARGET_NAME)"; + RUN_CLANG_STATIC_ANALYZER = YES; + USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../include\""; + VERSION_INFO_BUILDER = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 8401175E152D6F6C00B07E4D /* Build configuration list for PBXNativeTarget "tachyon.serial" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8401175F152D6F6C00B07E4D /* Debug */, + 84011760152D6F6C00B07E4D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 84011797152D6F8400B07E4D /* Build configuration list for PBXNativeTarget "tachyon.tbb1d" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 84011798152D6F8400B07E4D /* Debug */, + 84011799152D6F8400B07E4D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 84D0174B1527431F0008A4E0 /* Build configuration list for PBXProject "tachyon" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 84D01770152743200008A4E0 /* Debug */, + 84D01771152743200008A4E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 84D01772152743200008A4E0 /* Build configuration list for PBXNativeTarget "tachyon.tbb" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 84D01773152743200008A4E0 /* Debug */, + 84D01774152743200008A4E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 84D017481527431F0008A4E0 /* Project object */; +} diff --git a/src/tbb/examples/parallel_for/tachyon/xcode/tachyon.xcodeproj/xcshareddata/xcschemes/tachyon.serial.xcscheme b/src/tbb/examples/parallel_for/tachyon/xcode/tachyon.xcodeproj/xcshareddata/xcschemes/tachyon.serial.xcscheme new file mode 100644 index 0000000..b1c8534 --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/xcode/tachyon.xcodeproj/xcshareddata/xcschemes/tachyon.serial.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/parallel_for/tachyon/xcode/tachyon.xcodeproj/xcshareddata/xcschemes/tachyon.tbb.xcscheme b/src/tbb/examples/parallel_for/tachyon/xcode/tachyon.xcodeproj/xcshareddata/xcschemes/tachyon.tbb.xcscheme new file mode 100644 index 0000000..ccd129c --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/xcode/tachyon.xcodeproj/xcshareddata/xcschemes/tachyon.tbb.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/parallel_for/tachyon/xcode/tachyon.xcodeproj/xcshareddata/xcschemes/tachyon.tbb1d.xcscheme b/src/tbb/examples/parallel_for/tachyon/xcode/tachyon.xcodeproj/xcshareddata/xcschemes/tachyon.tbb1d.xcscheme new file mode 100644 index 0000000..4cb4aad --- /dev/null +++ b/src/tbb/examples/parallel_for/tachyon/xcode/tachyon.xcodeproj/xcshareddata/xcschemes/tachyon.tbb1d.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/parallel_reduce/convex_hull/Makefile b/src/tbb/examples/parallel_reduce/convex_hull/Makefile new file mode 100644 index 0000000..5b1cd76 --- /dev/null +++ b/src/tbb/examples/parallel_reduce/convex_hull/Makefile @@ -0,0 +1,64 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# GNU Makefile that builds and runs example. +PROG=convex_hull_bench +ARGS= +PERF_RUN_ARGS = silent auto 40000000 +LIGHT_ARGS = 4 400 + +# The C++ compiler +ifneq (,$(shell which icc 2>/dev/null)) +CXX=icc +endif # icc + +ifeq ($(shell uname), Linux) +LIBS+= -lrt +endif + +all: release test + +release: *.cpp + $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o convex_hull_sample convex_hull_sample.cpp -ltbb $(LIBS) + $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o convex_hull_bench convex_hull_bench.cpp -ltbb $(LIBS) + +debug: *.cpp + $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o convex_hull_sample convex_hull_sample.cpp -ltbb_debug $(LIBS) + $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o convex_hull_bench convex_hull_bench.cpp -ltbb_debug $(LIBS) + +clean: + $(RM) convex_hull_bench convex_hull_sample *.o *.d + +perf_build: release + +perf_run: + ./convex_hull_sample $(PERF_RUN_ARGS) + +test: + ./$(PROG) $(ARGS) + +light_test: + ./$(PROG) $(LIGHT_ARGS) diff --git a/src/tbb/examples/parallel_reduce/convex_hull/Makefile.windows b/src/tbb/examples/parallel_reduce/convex_hull/Makefile.windows new file mode 100644 index 0000000..f354d02 --- /dev/null +++ b/src/tbb/examples/parallel_reduce/convex_hull/Makefile.windows @@ -0,0 +1,63 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Common Makefile that builds and runs example. +PROG=convex_hull_bench +ARGS= +PERF_RUN_ARGS = silent auto 40000000 +LIGHT_ARGS = 4 400 + +# Trying to find if icl.exe is set +CXX1 = $(TBB_CXX)- +CXX2 = $(CXX1:icl.exe-=icl.exe) +CXX = $(CXX2:-=cl.exe) + +# The C++ compiler options +MYCXXFLAGS = /TP /EHsc /W3 /nologo $(TBB_SECURITY_SWITCH) /D _CONSOLE /D _MBCS /D WIN32 /D _SCL_SECURE_NO_DEPRECATE /D _SECURE_SCL=0 $(CXXFLAGS) +MYLDFLAGS =/INCREMENTAL:NO /NOLOGO /DEBUG /FIXED:NO $(LDFLAGS) + +all: release test +release: compiler_check + $(CXX) convex_hull_sample.cpp /MD /O2 /D NDEBUG $(MYCXXFLAGS) /link tbb.lib $(LIBS) $(MYLDFLAGS) /OUT:convex_hull_sample.exe + $(CXX) convex_hull_bench.cpp /MD /O2 /D NDEBUG $(MYCXXFLAGS) /link tbb.lib $(LIBS) $(MYLDFLAGS) /OUT:convex_hull_bench.exe +debug: compiler_check + $(CXX) convex_hull_sample.cpp /MDd /Od /Zi /D TBB_USE_DEBUG /D _DEBUG $(MYCXXFLAGS) /link tbb_debug.lib $(LIBS) $(MYLDFLAGS) /OUT:convex_hull_sample.exe + $(CXX) convex_hull_bench.cpp /MDd /Od /Zi /D TBB_USE_DEBUG /D _DEBUG $(MYCXXFLAGS) /link tbb_debug.lib $(LIBS) $(MYLDFLAGS) /OUT:convex_hull_bench.exe +clean: + @cmd.exe /C del convex_hull*.exe *.obj *.?db *.manifest +test: + $(PROG) $(ARGS) +perf_build: release + +perf_run: + ./convex_hull_sample $(PERF_RUN_ARGS) + +light_test: + ./$(PROG) $(LIGHT_ARGS) + +compiler_check: + @echo compiler_test>compiler_test && @$(CXX) /E compiler_test >nul 2>&1 || echo "$(CXX) command not found. Check if CXX=$(CXX) is set properly" + @cmd.exe /C del compiler_test diff --git a/src/tbb/examples/parallel_reduce/convex_hull/convex_hull.h b/src/tbb/examples/parallel_reduce/convex_hull/convex_hull.h new file mode 100644 index 0000000..babd81f --- /dev/null +++ b/src/tbb/examples/parallel_reduce/convex_hull/convex_hull.h @@ -0,0 +1,197 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __CONVEX_HULL_H__ +#define __CONVEX_HULL_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tbb/tick_count.h" +#include "tbb/task_scheduler_init.h" +#include "../../common/utility/utility.h" +#include "../../common/utility/fast_random.h" +#include "tbb/blocked_range.h" + +using namespace std; + +namespace cfg { + // convex hull problem user set parameters + long numberOfPoints = 5000000; // problem size + utility::thread_number_range threads(tbb::task_scheduler_init::default_num_threads); + + // convex hull grain sizes for 3 subproblems. Be sure 16*GS < 512Kb + const size_t generateGrainSize = 25000; + const size_t findExtremumGrainSize = 25000; + const size_t divideGrainSize = 25000; +}; + +namespace util { + bool silent = false; + bool verbose = false; + vector OUTPUT; + + // utility functionality + void ParseInputArgs(int argc, char* argv[]) { + utility::parse_cli_arguments( + argc,argv, + utility::cli_argument_pack() + //"-h" option for for displaying help is present implicitly + .positional_arg(cfg::threads,"n-of-threads","number of threads to run on; a non-negative integer, or 'auto' to use HW number of threads, or range of the form low:high") + .positional_arg(cfg::numberOfPoints,"n-of-points","number of points") + .arg(silent,"silent","no output except elapsed time") + .arg(verbose,"verbose","turns verbose ON") + ); + //disabling verbose if silent is specified + if (silent) verbose = false;; + } + + template + struct point { + T x; + T y; + //According to subparagraph 4 of paragraph 12.6.2 "Initializing bases and members" [class.base.init] + //of ANSI-ISO-IEC C++ 2003 standard, POD members will _not_ be initialized if they are not mentioned + //in the base-member initializer list. + + //For more details why this needed please see comment in FillRNDPointsVector_buf + point() {} + point(T _x, T _y) : x(_x), y(_y) {} + }; + + std::ostream& operator<< (std::ostream& o, point const& p) { + return o << "(" << p.x << "," << p.y << ")"; + } + + struct rng { + static const size_t max_rand = USHRT_MAX; + utility::FastRandom my_fast_random; + rng (size_t seed):my_fast_random(seed) {} + unsigned short operator()(){return my_fast_random.get();} + unsigned short operator()(size_t& seed){return my_fast_random.get(seed);} + }; + + + template < typename T ,typename rng_functor_type> + point GenerateRNDPoint(size_t& count, rng_functor_type random, size_t rand_max) { + /* generates random points on 2D plane so that the cluster + is somewhat circle shaped */ + const size_t maxsize=500; + T x = random()*2.0/(double)rand_max - 1; + T y = random()*2.0/(double)rand_max - 1; + T r = (x*x + y*y); + if(r>1) { + count++; + if(count>10) { + if (random()/(double)rand_max > 0.5) + x /= r; + if (random()/(double)rand_max > 0.5) + y /= r; + count = 0; + } + else { + x /= r; + y /= r; + } + } + + x = (x+1)*0.5*maxsize; + y = (y+1)*0.5*maxsize; + + return point(x,y); + } + + template + struct edge { + Index start; + Index end; + edge(Index _p1, Index _p2) : start(_p1), end(_p2) {}; + }; + + template + ostream& operator <<(ostream& _ostr, point _p) { + return _ostr << '(' << _p.x << ',' << _p.y << ')'; + } + + template + istream& operator >>(istream& _istr, point _p) { + return _istr >> _p.x >> _p.y; + } + + template + bool operator ==(point p1, point p2) { + return (p1.x == p2.x && p1.y == p2.y); + } + + template + bool operator !=(point p1, point p2) { + return !(p1 == p2); + } + + template + double cross_product(const point& start, const point& end1, const point& end2) { + return ((end1.x-start.x)*(end2.y-start.y)-(end2.x-start.x)*(end1.y-start.y)); + } + + // Timing functions are based on TBB to always obtain wall-clock time + typedef tbb::tick_count my_time_t; + + my_time_t gettime() { + return tbb::tick_count::now(); + } + + double time_diff(my_time_t start, my_time_t end) { + return (end-start).seconds(); + } + + void WriteResults(int nthreads, double initTime, double calcTime) { + if(verbose) { + cout << " Step by step hull construction:" << endl; + for(size_t i = 0; i < OUTPUT.size(); ++i) + cout << OUTPUT[i] << endl; + } + if (!silent){ + cout + << " Number of nodes:" << cfg::numberOfPoints + << " Number of threads:" << nthreads + << " Initialization time:" << setw(10) << setprecision(3) << initTime + << " Calculation time:" << setw(10) << setprecision(3) << calcTime + << endl; + } + } +}; + +#endif // __CONVEX_HULL_H__ diff --git a/src/tbb/examples/parallel_reduce/convex_hull/convex_hull_bench.cpp b/src/tbb/examples/parallel_reduce/convex_hull/convex_hull_bench.cpp new file mode 100644 index 0000000..b83f34d --- /dev/null +++ b/src/tbb/examples/parallel_reduce/convex_hull/convex_hull_bench.cpp @@ -0,0 +1,646 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + This file contains a few implementations, so it may look overly complicated. + The most efficient implementation is also separated into convex_hull_sample.cpp +*/ +#include +#include "convex_hull.h" + +typedef util::point point_t; + +#ifndef USETBB + #define USETBB 1 +#endif +#ifndef USECONCVEC + #define USECONCVEC 1 +#endif + +#if !USETBB // Serial implementation of Quick Hull algorithm + +typedef std::vector< point_t > pointVec_t; + +void serial_initialize(pointVec_t &points); + +// C++ style serial code + +class FindXExtremum : public std::unary_function { +public: + typedef enum { + minX, maxX + } extremumType; + + FindXExtremum(const point_t& frstPoint, extremumType exType_) + : extrXPoint(frstPoint), exType(exType_) {} + + void operator()(const point_t& p) { + if(closerToExtremum(p)) + extrXPoint = p; + } + + operator point_t () { + return extrXPoint; + } + +private: + const extremumType exType; + point_t extrXPoint; + + bool closerToExtremum(const point_t &p) const { + switch(exType) { + case minX: + return p.xextrXPoint.x; break; + } + return false; // avoid warning + } +}; + +template +point_t extremum(const pointVec_t &points) { + assert(!points.empty()); + return std::for_each(points.begin(), points.end(), FindXExtremum(points[0], type)); +} + +class SplitByCP : public std::unary_function { + pointVec_t &reducedSet; + point_t p1, p2; + point_t farPoint; + double howFar; +public: + + SplitByCP( point_t _p1, point_t _p2, pointVec_t &_reducedSet) + : p1(_p1), p2(_p2), reducedSet(_reducedSet), howFar(0), farPoint(p1) {} + + void operator()(const point_t& p) { + double cp; + if( (p != p1) && (p != p2) ) { + cp = util::cross_product(p1, p2, p); + if(cp>0) { + reducedSet.push_back(p); + if(cp>howFar) { + farPoint = p; + howFar = cp; + } + } + } + } + + operator point_t (){ + return farPoint; + } +}; + +point_t divide(const pointVec_t &P, pointVec_t &P_reduced, const point_t &p1, const point_t &p2) { + SplitByCP splitByCP(p1, p2, P_reduced); + point_t farPoint = std::for_each(P.begin(), P.end(), splitByCP); + + if(util::verbose) { + std::stringstream ss; + ss << P.size() << " nodes in bucket"<< ", " + << "dividing by: [ " << p1 << ", " << p2 << " ], " + << "farthest node: " << farPoint; + util::OUTPUT.push_back(ss.str()); + } + + return farPoint; +} + +void divide_and_conquer(const pointVec_t &P, pointVec_t &H, point_t p1, point_t p2) { + assert(P.size() >= 2); + pointVec_t P_reduced; + pointVec_t H1, H2; + point_t p_far = divide(P, P_reduced, p1, p2); + if (P_reduced.size()<2) { + H.push_back(p1); + H.insert(H.end(), P_reduced.begin(), P_reduced.end()); + } + else { + divide_and_conquer(P_reduced, H1, p1, p_far); + divide_and_conquer(P_reduced, H2, p_far, p2); + + H.insert(H.end(), H1.begin(), H1.end()); + H.insert(H.end(), H2.begin(), H2.end()); + } +} + +void quickhull(const pointVec_t &points, pointVec_t &hull) { + if (points.size() < 2) { + hull.insert(hull.end(), points.begin(), points.end()); + return; + } + point_t p_maxx = extremum(points); + point_t p_minx = extremum(points); + + pointVec_t H; + + divide_and_conquer(points, hull, p_maxx, p_minx); + divide_and_conquer(points, H, p_minx, p_maxx); + hull.insert(hull.end(), H.begin(), H.end()); +} + + +int main(int argc, char* argv[]) { + util::ParseInputArgs(argc, argv); + + pointVec_t points; + pointVec_t hull; + util::my_time_t tm_init, tm_start, tm_end; + + std::cout << "Starting serial version of QUICK HULL algorithm" << std::endl; + + tm_init = util::gettime(); + serial_initialize(points); + tm_start = util::gettime(); + std::cout << "Init time: " << util::time_diff(tm_init, tm_start) << " Points in input: " << points.size() << "\n"; + tm_start = util::gettime(); + quickhull(points, hull); + tm_end = util::gettime(); + std::cout << "Serial time: " << util::time_diff(tm_start, tm_end) << " Points in hull: " << hull.size() << "\n"; +} + +#else // USETBB - parallel version of Quick Hull algorithm + +#include "tbb/task_scheduler_init.h" +#include "tbb/parallel_for.h" +#include "tbb/parallel_reduce.h" +#include "tbb/blocked_range.h" + +typedef tbb::blocked_range range_t; + +#if USECONCVEC +#include "tbb/concurrent_vector.h" + +typedef tbb::concurrent_vector pointVec_t; + +void appendVector(const point_t* src, size_t srcSize, pointVec_t& dest) { + std::copy(src, src + srcSize, dest.grow_by(srcSize)); +} + +void appendVector(const pointVec_t& src, pointVec_t& dest) { + std::copy(src.begin(), src.end(), dest.grow_by(src.size())); +} + +void grow_vector_to_at_least(pointVec_t& vect, size_t size) { + vect.grow_to_at_least(size); +} +#else // USE STD::VECTOR - include spin_mutex.h and lock vector operations +#include "tbb/spin_mutex.h" + +typedef tbb::spin_mutex mutex_t; +typedef std::vector pointVec_t; + +void appendVector(mutex_t& insertMutex, const pointVec_t& src, pointVec_t& dest) { + mutex_t::scoped_lock lock(insertMutex); + dest.insert(dest.end(), src.begin(), src.end()); +} + +void appendVector(mutex_t& insertMutex, const point_t* src, size_t srcSize, + pointVec_t& dest) { + mutex_t::scoped_lock lock(insertMutex); + dest.insert(dest.end(), src, src + srcSize); +} + +void grow_vector_to_at_least(mutex_t& mutex, pointVec_t& vect, size_t size) { + mutex_t::scoped_lock lock(mutex); + if (vect.size()< size){ + vect.resize(size); + } +} +#endif // USECONCVEC + +class FillRNDPointsVector { + pointVec_t &points; +public: + static const size_t grainSize = cfg::generateGrainSize; +#if !USECONCVEC + static mutex_t pushBackMutex; +#endif // USECONCVEC + + explicit FillRNDPointsVector(pointVec_t& _points) + : points(_points){} + + void operator()(const range_t& range) const { + util::rng the_rng(range.begin()); + const size_t i_end = range.end(); + size_t count = 0; +#if USECONCVEC + points.grow_to_at_least(i_end); +#else // Locked enlarge to a not thread-safe STD::VECTOR + grow_vector_to_at_least(pushBackMutex,points,i_end); +#endif // USECONCVEC + + for(size_t i = range.begin(); i != i_end; ++i) { + points[i]=util::GenerateRNDPoint(count,the_rng,util::rng::max_rand); + } + } +}; + +class FillRNDPointsVector_buf { + pointVec_t &points; +public: + static const size_t grainSize = cfg::generateGrainSize; +#if !USECONCVEC + static mutex_t insertMutex; +#endif // USECONCVEC + + explicit FillRNDPointsVector_buf(pointVec_t& _points) + : points(_points){} + + void operator()(const range_t& range) const { + util::rng the_rng(range.begin()); + const size_t i_end = range.end(); + size_t count = 0, j = 0; + point_t tmp_vec[grainSize]; + + for(size_t i=range.begin(); i!=i_end; ++i) { + tmp_vec[j++] = util::GenerateRNDPoint(count,the_rng,util::rng::max_rand); + } +#if USECONCVEC + grow_vector_to_at_least(points,range.end()); +#else // USE STD::VECTOR + grow_vector_to_at_least(insertMutex,points,range.end()); +#endif // USECONCVEC + std::copy(tmp_vec, tmp_vec+j,points.begin()+range.begin()); + } +}; + +#if !USECONCVEC +mutex_t FillRNDPointsVector::pushBackMutex = mutex_t(); +mutex_t FillRNDPointsVector_buf::insertMutex = mutex_t(); +#endif + +template +void initialize(pointVec_t &points) { + //This function generate the same series of point on every call. + //Reproducibility is needed for benchmarking to produce reliable results. + //It is achieved through the following points: + // - FillRNDPointsVector_buf instance has its own local instance + // of random number generator, which in turn does not use any global data + // - tbb::simple_partitioner produce the same set of ranges on every call to + // tbb::parallel_for + // - local RNG instances are seeded by the starting indexes of corresponding ranges + // - grow_to_at_least() enables putting points into the resulting vector in deterministic order + // (unlike concurrent push_back or grow_by). + + // In the buffered version, a temporary storage for as much as grainSize elements + // is allocated inside the body. Since auto_partitioner may increase effective + // range size which would cause a crash, simple partitioner has to be used. + + tbb::parallel_for(range_t(0, cfg::numberOfPoints, BodyType::grainSize), + BodyType(points), tbb::simple_partitioner()); +} + +class FindXExtremum { +public: + typedef enum { + minX, maxX + } extremumType; + + static const size_t grainSize = cfg::findExtremumGrainSize; + + FindXExtremum(const pointVec_t& points_, extremumType exType_) + : points(points_), exType(exType_), extrXPoint(points[0]) {} + + FindXExtremum(const FindXExtremum& fxex, tbb::split) + : points(fxex.points), exType(fxex.exType), extrXPoint(fxex.extrXPoint) {} + + void operator()(const range_t& range) { + const size_t i_end = range.end(); + if(!range.empty()) { + for(size_t i = range.begin(); i != i_end; ++i) { + if(closerToExtremum(points[i])) { + extrXPoint = points[i]; + } + } + } + } + + void join(const FindXExtremum &rhs) { + if(closerToExtremum(rhs.extrXPoint)) { + extrXPoint = rhs.extrXPoint; + } + } + + point_t extremeXPoint() { + return extrXPoint; + } + +private: + const pointVec_t &points; + const extremumType exType; + point_t extrXPoint; + bool closerToExtremum(const point_t &p) const { + switch(exType) { + case minX: + return p.xextrXPoint.x; break; + } + return false; // avoid warning + } +}; + +template +point_t extremum(const pointVec_t &P) { + FindXExtremum fxBody(P, type); + tbb::parallel_reduce(range_t(0, P.size(), FindXExtremum::grainSize), fxBody); + return fxBody.extremeXPoint(); +} + +class SplitByCP { + const pointVec_t &initialSet; + pointVec_t &reducedSet; + point_t p1, p2; + point_t farPoint; + double howFar; +public: + static const size_t grainSize = cfg::divideGrainSize; +#if !USECONCVEC + static mutex_t pushBackMutex; +#endif // USECONCVEC + + SplitByCP( point_t _p1, point_t _p2, + const pointVec_t &_initialSet, pointVec_t &_reducedSet) + : p1(_p1), p2(_p2), + initialSet(_initialSet), reducedSet(_reducedSet), + howFar(0), farPoint(p1) { + } + + SplitByCP( SplitByCP& sbcp, tbb::split ) + : p1(sbcp.p1), p2(sbcp.p2), + initialSet(sbcp.initialSet), reducedSet(sbcp.reducedSet), + howFar(0), farPoint(p1) {} + + void operator()( const range_t& range ) { + const size_t i_end = range.end(); + double cp; + for(size_t i=range.begin(); i!=i_end; ++i) { + if( (initialSet[i] != p1) && (initialSet[i] != p2) ) { + cp = util::cross_product(p1, p2, initialSet[i]); + if(cp>0) { +#if USECONCVEC + reducedSet.push_back(initialSet[i]); +#else // Locked push_back to a not thread-safe STD::VECTOR + { + mutex_t::scoped_lock lock(pushBackMutex); + reducedSet.push_back(initialSet[i]); + } +#endif // USECONCVEC + if(cp>howFar) { + farPoint = initialSet[i]; + howFar = cp; + } + } + } + } + } + + void join(const SplitByCP& rhs) { + if(rhs.howFar>howFar) { + howFar = rhs.howFar; + farPoint = rhs.farPoint; + } + } + + point_t farthestPoint() const { + return farPoint; + } +}; + +class SplitByCP_buf { + const pointVec_t &initialSet; + pointVec_t &reducedSet; + point_t p1, p2; + point_t farPoint; + double howFar; +public: + static const size_t grainSize = cfg::divideGrainSize; +#if !USECONCVEC + static mutex_t insertMutex; +#endif // USECONCVEC + + SplitByCP_buf( point_t _p1, point_t _p2, + const pointVec_t &_initialSet, pointVec_t &_reducedSet) + : p1(_p1), p2(_p2), + initialSet(_initialSet), reducedSet(_reducedSet), + howFar(0), farPoint(p1) {} + + SplitByCP_buf(SplitByCP_buf& sbcp, tbb::split) + : p1(sbcp.p1), p2(sbcp.p2), + initialSet(sbcp.initialSet), reducedSet(sbcp.reducedSet), + howFar(0), farPoint(p1) {} + + void operator()(const range_t& range) { + const size_t i_end = range.end(); + size_t j = 0; + double cp; + point_t tmp_vec[grainSize]; + for(size_t i = range.begin(); i != i_end; ++i) { + if( (initialSet[i] != p1) && (initialSet[i] != p2) ) { + cp = util::cross_product(p1, p2, initialSet[i]); + if(cp>0) { + tmp_vec[j++] = initialSet[i]; + if(cp>howFar) { + farPoint = initialSet[i]; + howFar = cp; + } + } + } + } + +#if USECONCVEC + appendVector(tmp_vec, j, reducedSet); +#else // USE STD::VECTOR + appendVector(insertMutex, tmp_vec, j, reducedSet); +#endif // USECONCVEC + } + + void join(const SplitByCP_buf& rhs) { + if(rhs.howFar>howFar) { + howFar = rhs.howFar; + farPoint = rhs.farPoint; + } + } + + point_t farthestPoint() const { + return farPoint; + } +}; + +#if !USECONCVEC +mutex_t SplitByCP::pushBackMutex = mutex_t(); +mutex_t SplitByCP_buf::insertMutex = mutex_t(); +#endif + +template +point_t divide(const pointVec_t &P, pointVec_t &P_reduced, + const point_t &p1, const point_t &p2) { + BodyType body(p1, p2, P, P_reduced); + // Must use simple_partitioner (see the comment in initialize() above) + tbb::parallel_reduce(range_t(0, P.size(), BodyType::grainSize), + body, tbb::simple_partitioner() ); + + if(util::verbose) { + std::stringstream ss; + ss << P.size() << " nodes in bucket"<< ", " + << "dividing by: [ " << p1 << ", " << p2 << " ], " + << "farthest node: " << body.farthestPoint(); + util::OUTPUT.push_back(ss.str()); + } + + return body.farthestPoint(); +} + +void divide_and_conquer(const pointVec_t &P, pointVec_t &H, + point_t p1, point_t p2, bool buffered) { + assert(P.size() >= 2); + pointVec_t P_reduced; + pointVec_t H1, H2; + point_t p_far; + + if(buffered) { + p_far = divide(P, P_reduced, p1, p2); + } else { + p_far = divide(P, P_reduced, p1, p2); + } + + if (P_reduced.size()<2) { + H.push_back(p1); +#if USECONCVEC + appendVector(P_reduced, H); +#else // insert into STD::VECTOR + H.insert(H.end(), P_reduced.begin(), P_reduced.end()); +#endif + } + else { + divide_and_conquer(P_reduced, H1, p1, p_far, buffered); + divide_and_conquer(P_reduced, H2, p_far, p2, buffered); + +#if USECONCVEC + appendVector(H1, H); + appendVector(H2, H); +#else // insert into STD::VECTOR + H.insert(H.end(), H1.begin(), H1.end()); + H.insert(H.end(), H2.begin(), H2.end()); +#endif + } +} + +void quickhull(const pointVec_t &points, pointVec_t &hull, bool buffered) { + if (points.size() < 2) { +#if USECONCVEC + appendVector(points, hull); +#else // STD::VECTOR + hull.insert(hull.end(), points.begin(), points.end()); +#endif // USECONCVEC + return; + } + + point_t p_maxx = extremum(points); + point_t p_minx = extremum(points); + + pointVec_t H; + + divide_and_conquer(points, hull, p_maxx, p_minx, buffered); + divide_and_conquer(points, H, p_minx, p_maxx, buffered); +#if USECONCVEC + appendVector(H, hull); +#else // STD::VECTOR + hull.insert(hull.end(), H.begin(), H.end()); +#endif // USECONCVEC +} + +int main(int argc, char* argv[]) { + util::ParseInputArgs(argc, argv); + + int nthreads; + util::my_time_t tm_init, tm_start, tm_end; + +#if USECONCVEC + std::cout << "Starting TBB unbuffered push_back version of QUICK HULL algorithm" << std::endl; +#else + std::cout << "Starting STL locked unbuffered push_back version of QUICK HULL algorithm" << std::endl; +#endif // USECONCVEC + + for(nthreads=cfg::threads.first; nthreads<=cfg::threads.last; + ++nthreads) { + pointVec_t points; + pointVec_t hull; + + tbb::task_scheduler_init init(nthreads); + tm_init = util::gettime(); + initialize(points); + tm_start = util::gettime(); + std::cout << "Parallel init time on " << nthreads << " threads: " << util::time_diff(tm_init, tm_start) << " Points in input: " << points.size() << "\n"; + + tm_start = util::gettime(); + quickhull(points, hull, false); + tm_end = util::gettime(); + std::cout << "Time on " << nthreads << " threads: " << util::time_diff(tm_start, tm_end) << " Points in hull: " << hull.size() << "\n"; + } + +#if USECONCVEC + std::cout << "Starting TBB buffered version of QUICK HULL algorithm" << std::endl; +#else + std::cout << "Starting STL locked buffered version of QUICK HULL algorithm" << std::endl; +#endif + + for(nthreads=cfg::threads.first; nthreads<=cfg::threads.last; + ++nthreads) { + pointVec_t points; + pointVec_t hull; + + tbb::task_scheduler_init init(nthreads); + + tm_init = util::gettime(); + initialize(points); + tm_start = util::gettime(); + std::cout << "Init time on " << nthreads << " threads: " << util::time_diff(tm_init, tm_start) << " Points in input: " << points.size() << "\n"; + + tm_start = util::gettime(); + quickhull(points, hull, true); + tm_end = util::gettime(); + std::cout << "Time on " << nthreads << " threads: " << util::time_diff(tm_start, tm_end) << " Points in hull: " << hull.size() << "\n"; + } + + return 0; +} + +#endif // USETBB + +void serial_initialize(pointVec_t &points) { + points.reserve(cfg::numberOfPoints); + + unsigned int rseed=1; + for(size_t i=0, count=0; long(i)(count,&std::rand,RAND_MAX )); + } +} diff --git a/src/tbb/examples/parallel_reduce/convex_hull/convex_hull_sample.cpp b/src/tbb/examples/parallel_reduce/convex_hull/convex_hull_sample.cpp new file mode 100644 index 0000000..810f2aa --- /dev/null +++ b/src/tbb/examples/parallel_reduce/convex_hull/convex_hull_sample.cpp @@ -0,0 +1,309 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* + This file contains the TBB-based implementation of convex hull algortihm. + It corresponds to the following settings in convex_hull_bench.cpp: + - USETBB defined to 1 + - USECONCVEC defined to 1 + - INIT_ONCE defined to 0 + - only buffered version is used +*/ +#include +#include +#include "convex_hull.h" + +#include "tbb/task_scheduler_init.h" +#include "tbb/parallel_for.h" +#include "tbb/parallel_reduce.h" +#include "tbb/blocked_range.h" +#include "tbb/tick_count.h" +#include "tbb/concurrent_vector.h" + +typedef util::point point_t; +typedef tbb::concurrent_vector< point_t > pointVec_t; +typedef tbb::blocked_range range_t; + +void appendVector(const point_t* src, size_t srcSize, pointVec_t& dest) { + std::copy(src, src + srcSize, dest.grow_by(srcSize)); +} + +void appendVector(const pointVec_t& src, pointVec_t& dest) { + std::copy(src.begin(), src.end(), dest.grow_by(src.size())); +} +class FillRNDPointsVector_buf { + pointVec_t &points; +public: + static const size_t grainSize = cfg::generateGrainSize; + + explicit FillRNDPointsVector_buf(pointVec_t& _points) + : points(_points) {} + + void operator()(const range_t& range) const { + util::rng the_rng(range.begin()); + const size_t i_end = range.end(); + size_t count = 0, j = 0; + point_t tmp_vec[grainSize]; + + for(size_t i=range.begin(); i!=i_end; ++i) { + tmp_vec[j++] = util::GenerateRNDPoint(count, the_rng, util::rng::max_rand); + } + //Here we have race condition. Elements being written to may be still under construction. + //For C++ 2003 it is workarounded by vector element type which default constructor does not touch memory, + //it being constructed on. See comments near default ctor of point class for more details. + //Strictly speaking it is UB. + //TODO: need to find more reliable/correct way + points.grow_to_at_least(range.end()); + std::copy(tmp_vec, tmp_vec+j,points.begin()+range.begin()); + } +}; + +void initialize(pointVec_t &points) { + //This function generate the same series of point on every call. + //Reproducibility is needed for benchmarking to produce reliable results. + //It is achieved through the following points: + // - FillRNDPointsVector_buf instance has its own local instance + // of random number generator, which in turn does not use any global data + // - tbb::simple_partitioner produce the same set of ranges on every call to + // tbb::parallel_for + // - local RNG instances are seeded by the starting indexes of corresponding ranges + // - grow_to_at_least() enables putting points into the resulting vector in deterministic order + // (unlike concurrent push_back or grow_by). + + // In the buffered version, a temporary storage for as much as grainSize elements + // is allocated inside the body. Since auto_partitioner may increase effective + // range size which would cause a crash, simple partitioner has to be used. + tbb::parallel_for(range_t(0, cfg::numberOfPoints, FillRNDPointsVector_buf::grainSize), + FillRNDPointsVector_buf(points), tbb::simple_partitioner()); +} + +class FindXExtremum { +public: + typedef enum { + minX, maxX + } extremumType; + + static const size_t grainSize = cfg::findExtremumGrainSize; + + FindXExtremum(const pointVec_t& points_, extremumType exType_) + : points(points_), exType(exType_), extrXPoint(points[0]) {} + + FindXExtremum(const FindXExtremum& fxex, tbb::split) + // Can run in parallel with fxex.operator()() or fxex.join(). + // The data race reported by tools is harmless. + : points(fxex.points), exType(fxex.exType), extrXPoint(fxex.extrXPoint) {} + + void operator()(const range_t& range) { + const size_t i_end = range.end(); + if(!range.empty()) { + for(size_t i = range.begin(); i != i_end; ++i) { + if(closerToExtremum(points[i])) { + extrXPoint = points[i]; + } + } + } + } + + void join(const FindXExtremum &rhs) { + if(closerToExtremum(rhs.extrXPoint)) { + extrXPoint = rhs.extrXPoint; + } + } + + point_t extremeXPoint() { + return extrXPoint; + } + +private: + const pointVec_t &points; + const extremumType exType; + point_t extrXPoint; + bool closerToExtremum(const point_t &p) const { + switch(exType) { + case minX: + return p.xextrXPoint.x; break; + } + return false; // avoid warning + } +}; + +template +point_t extremum(const pointVec_t &P) { + FindXExtremum fxBody(P, type); + tbb::parallel_reduce(range_t(0, P.size(), FindXExtremum::grainSize), fxBody); + return fxBody.extremeXPoint(); +} + +class SplitByCP_buf { + const pointVec_t &initialSet; + pointVec_t &reducedSet; + point_t p1, p2; + point_t farPoint; + double howFar; +public: + static const size_t grainSize = cfg::divideGrainSize; + + SplitByCP_buf( point_t _p1, point_t _p2, + const pointVec_t &_initialSet, pointVec_t &_reducedSet) + : p1(_p1), p2(_p2), + initialSet(_initialSet), reducedSet(_reducedSet), + howFar(0), farPoint(p1) {} + + SplitByCP_buf(SplitByCP_buf& sbcp, tbb::split) + : p1(sbcp.p1), p2(sbcp.p2), + initialSet(sbcp.initialSet), reducedSet(sbcp.reducedSet), + howFar(0), farPoint(p1) {} + + void operator()(const range_t& range) { + const size_t i_end = range.end(); + size_t j = 0; + double cp; + point_t tmp_vec[grainSize]; + for(size_t i = range.begin(); i != i_end; ++i) { + if( (initialSet[i] != p1) && (initialSet[i] != p2) ) { + cp = util::cross_product(p1, p2, initialSet[i]); + if(cp>0) { + tmp_vec[j++] = initialSet[i]; + if(cp>howFar) { + farPoint = initialSet[i]; + howFar = cp; + } + } + } + } + + appendVector(tmp_vec, j, reducedSet); + } + + void join(const SplitByCP_buf& rhs) { + if(rhs.howFar>howFar) { + howFar = rhs.howFar; + farPoint = rhs.farPoint; + } + } + + point_t farthestPoint() const { + return farPoint; + } +}; + +point_t divide(const pointVec_t &P, pointVec_t &P_reduced, + const point_t &p1, const point_t &p2) { + SplitByCP_buf sbcpb(p1, p2, P, P_reduced); + // Must use simple_partitioner (see the comment in initialize() above) + tbb::parallel_reduce(range_t(0, P.size(), SplitByCP_buf::grainSize), + sbcpb, tbb::simple_partitioner()); + + if(util::verbose) { + std::stringstream ss; + ss << P.size() << " nodes in bucket"<< ", " + << "dividing by: [ " << p1 << ", " << p2 << " ], " + << "farthest node: " << sbcpb.farthestPoint(); + util::OUTPUT.push_back(ss.str()); + } + + return sbcpb.farthestPoint(); +} + +void divide_and_conquer(const pointVec_t &P, pointVec_t &H, + point_t p1, point_t p2) { + assert(P.size() >= 2); + pointVec_t P_reduced; + pointVec_t H1, H2; + point_t p_far = divide(P, P_reduced, p1, p2); + if (P_reduced.size()<2) { + H.push_back(p1); + appendVector(P_reduced, H); + } + else { + divide_and_conquer(P_reduced, H1, p1, p_far); + divide_and_conquer(P_reduced, H2, p_far, p2); + + appendVector(H1, H); + appendVector(H2, H); + } +} + +void quickhull(const pointVec_t &points, pointVec_t &hull) { + if (points.size() < 2) { + appendVector(points, hull); + return; + } + + point_t p_maxx = extremum(points); + point_t p_minx = extremum(points); + + pointVec_t H; + + divide_and_conquer(points, hull, p_maxx, p_minx); + divide_and_conquer(points, H, p_minx, p_maxx); + + appendVector(H, hull); +} + +int main(int argc, char* argv[]) { + util::my_time_t tm_main_begin = util::gettime(); + + util::ParseInputArgs(argc, argv); + + pointVec_t points; + pointVec_t hull; + int nthreads; + + points.reserve(cfg::numberOfPoints); + + if(!util::silent) { + std::cout << "Starting TBB-buffered version of QUICK HULL algorithm" << std::endl; + } + + + for(nthreads=cfg::threads.first; nthreads<=cfg::threads.last; + ++nthreads) { + tbb::task_scheduler_init init(nthreads); + + points.clear(); + util::my_time_t tm_init = util::gettime(); + initialize(points); + util::my_time_t tm_start = util::gettime(); + if(!util::silent) { + std::cout <<"Init time on "< + + +

    Overview

    +Parallel version of convex hull algorithm (quick hull). + +

    Files

    +
    +
    convex_hull_sample.cpp +
    Source code for TBB version of example. +
    convex_hull_bench.cpp +
    Source code for version of example that compares serial and TBB buffered and unbuffered implementations. +
    convex_hull.h +
    Include file for example. +
    Makefile +
    Makefile for building example. +
    + +

    Directories

    +
    +
    msvs +
    Contains Microsoft* Visual Studio* 2005 workspace for building and running the + example (Windows* systems only).
    xcode +
    Contains Xcode* IDE workspace for building and running the example (Mac OS* X + systems only).
    + +

    To Build

    +General build directions can be found here. + +

    Usage

    +
    +
    convex_hull_sample [S] [M[:N]] [-v] +
    S is the number of points (problem size). + M:N are a range of numbers of threads to be used. + Use the -v option to turn on verbose output. +
    To run a short version of this example, e.g., for use with Intel® Threading Tools: +
    Build a debug version of the example + (see the build directions). +
    Run it with a small problem size and the desired number of threads, e.g., convex_hull_sample 500000 4. +
    + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + diff --git a/src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_benchmark.icproj b/src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_benchmark.icproj new file mode 100644 index 0000000..6667cee --- /dev/null +++ b/src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_benchmark.icproj @@ -0,0 +1,11 @@ + + + + + diff --git a/src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_benchmark.vcproj b/src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_benchmark.vcproj new file mode 100644 index 0000000..f6b9c06 --- /dev/null +++ b/src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_benchmark.vcproj @@ -0,0 +1,366 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_cl.sln b/src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_cl.sln new file mode 100644 index 0000000..8dbd651 --- /dev/null +++ b/src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_cl.sln @@ -0,0 +1,35 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "convex_hull_benchmark", "convex_hull_benchmark.vcproj", "{3AA40693-F93D-4D4B-B32E-068F511A252A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "convex_hull_sample", "convex_hull_sample.vcproj", "{5F897A77-EBD9-4462-94D4-06E2ADE47F3B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|Win32.ActiveCfg = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|Win32.Build.0 = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|x64.ActiveCfg = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|x64.Build.0 = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|Win32.ActiveCfg = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|Win32.Build.0 = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|x64.ActiveCfg = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|x64.Build.0 = Release|x64 + {5F897A77-EBD9-4462-94D4-06E2ADE47F3B}.Debug|Win32.ActiveCfg = Debug|Win32 + {5F897A77-EBD9-4462-94D4-06E2ADE47F3B}.Debug|Win32.Build.0 = Debug|Win32 + {5F897A77-EBD9-4462-94D4-06E2ADE47F3B}.Debug|x64.ActiveCfg = Debug|x64 + {5F897A77-EBD9-4462-94D4-06E2ADE47F3B}.Debug|x64.Build.0 = Debug|x64 + {5F897A77-EBD9-4462-94D4-06E2ADE47F3B}.Release|Win32.ActiveCfg = Release|Win32 + {5F897A77-EBD9-4462-94D4-06E2ADE47F3B}.Release|Win32.Build.0 = Release|Win32 + {5F897A77-EBD9-4462-94D4-06E2ADE47F3B}.Release|x64.ActiveCfg = Release|x64 + {5F897A77-EBD9-4462-94D4-06E2ADE47F3B}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_icl.sln b/src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_icl.sln new file mode 100644 index 0000000..7d1545f --- /dev/null +++ b/src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_icl.sln @@ -0,0 +1,51 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "convex_hull_benchmark", "convex_hull_benchmark.icproj", "{347CD752-84DD-4E7C-9DB3-90B740C03E8E}" +EndProject +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "convex_hull_sample", "convex_hull_sample.icproj", "{B83E81E3-9EB0-4C22-B6CF-F2329A496EDA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {347CD752-84DD-4E7C-9DB3-90B740C03E8E}.Debug|Win32.ActiveCfg = Debug|Win32 + {347CD752-84DD-4E7C-9DB3-90B740C03E8E}.Debug|Win32.Build.0 = Debug|Win32 + {347CD752-84DD-4E7C-9DB3-90B740C03E8E}.Debug|x64.ActiveCfg = Debug|x64 + {347CD752-84DD-4E7C-9DB3-90B740C03E8E}.Debug|x64.Build.0 = Debug|x64 + {347CD752-84DD-4E7C-9DB3-90B740C03E8E}.Release|Win32.ActiveCfg = Release|Win32 + {347CD752-84DD-4E7C-9DB3-90B740C03E8E}.Release|Win32.Build.0 = Release|Win32 + {347CD752-84DD-4E7C-9DB3-90B740C03E8E}.Release|x64.ActiveCfg = Release|x64 + {347CD752-84DD-4E7C-9DB3-90B740C03E8E}.Release|x64.Build.0 = Release|x64 + {B83E81E3-9EB0-4C22-B6CF-F2329A496EDA}.Debug|Win32.ActiveCfg = Debug|Win32 + {B83E81E3-9EB0-4C22-B6CF-F2329A496EDA}.Debug|Win32.Build.0 = Debug|Win32 + {B83E81E3-9EB0-4C22-B6CF-F2329A496EDA}.Debug|x64.ActiveCfg = Debug|x64 + {B83E81E3-9EB0-4C22-B6CF-F2329A496EDA}.Debug|x64.Build.0 = Debug|x64 + {B83E81E3-9EB0-4C22-B6CF-F2329A496EDA}.Release|Win32.ActiveCfg = Release|Win32 + {B83E81E3-9EB0-4C22-B6CF-F2329A496EDA}.Release|Win32.Build.0 = Release|Win32 + {B83E81E3-9EB0-4C22-B6CF-F2329A496EDA}.Release|x64.ActiveCfg = Release|x64 + {B83E81E3-9EB0-4C22-B6CF-F2329A496EDA}.Release|x64.Build.0 = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|x64.Build.0 = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|x64.ActiveCfg = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|Win32.Build.0 = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|Win32.ActiveCfg = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|x64.Build.0 = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|x64.ActiveCfg = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|Win32.Build.0 = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|Win32.ActiveCfg = Debug|Win32 + {5F897A77-EBD9-4462-94D4-06E2ADE47F3B}.Release|x64.Build.0 = Release|x64 + {5F897A77-EBD9-4462-94D4-06E2ADE47F3B}.Release|x64.ActiveCfg = Release|x64 + {5F897A77-EBD9-4462-94D4-06E2ADE47F3B}.Release|Win32.Build.0 = Release|Win32 + {5F897A77-EBD9-4462-94D4-06E2ADE47F3B}.Release|Win32.ActiveCfg = Release|Win32 + {5F897A77-EBD9-4462-94D4-06E2ADE47F3B}.Debug|x64.Build.0 = Debug|x64 + {5F897A77-EBD9-4462-94D4-06E2ADE47F3B}.Debug|x64.ActiveCfg = Debug|x64 + {5F897A77-EBD9-4462-94D4-06E2ADE47F3B}.Debug|Win32.Build.0 = Debug|Win32 + {5F897A77-EBD9-4462-94D4-06E2ADE47F3B}.Debug|Win32.ActiveCfg = Debug|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_sample.icproj b/src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_sample.icproj new file mode 100644 index 0000000..b6926c0 --- /dev/null +++ b/src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_sample.icproj @@ -0,0 +1,11 @@ + + + + + diff --git a/src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_sample.vcproj b/src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_sample.vcproj new file mode 100644 index 0000000..10f0eae --- /dev/null +++ b/src/tbb/examples/parallel_reduce/convex_hull/msvs/convex_hull_sample.vcproj @@ -0,0 +1,364 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/parallel_reduce/convex_hull/xcode/convex_hull.xcodeproj/project.pbxproj b/src/tbb/examples/parallel_reduce/convex_hull/xcode/convex_hull.xcodeproj/project.pbxproj new file mode 100644 index 0000000..6b35ba1 --- /dev/null +++ b/src/tbb/examples/parallel_reduce/convex_hull/xcode/convex_hull.xcodeproj/project.pbxproj @@ -0,0 +1,441 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + A146114A0B94631F000C6B18 /* convex_hull_bench.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A14611490B94631F000C6B18 /* convex_hull_bench.cpp */; }; + A1F593A60B8F042A00073279 /* convex_hull_sample.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1F593A50B8F042A00073279 /* convex_hull_sample.cpp */; }; + A1F593B70B8F06F900073279 /* libtbb.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; + A1F593BB0B8F072500073279 /* libtbb.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; + A1F594FC0B8F4F1000073279 /* libtbb.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; + A1F594FD0B8F4F1800073279 /* libtbb.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8DD76F690486A84900D96B5E /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = ""; + dstSubfolderSpec = 16; + files = ( + A1F593BB0B8F072500073279 /* libtbb.dylib in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1F594F40B8F4E7700073279 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 16; + files = ( + A1F594FD0B8F4F1800073279 /* libtbb.dylib in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + A14611490B94631F000C6B18 /* convex_hull_bench.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = convex_hull_bench.cpp; path = ../convex_hull_bench.cpp; sourceTree = SOURCE_ROOT; }; + A146114C0B9463CB000C6B18 /* convex_hull.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = convex_hull.h; path = ../convex_hull.h; sourceTree = SOURCE_ROOT; }; + A1F593A50B8F042A00073279 /* convex_hull_sample.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = convex_hull_sample.cpp; path = ../convex_hull_sample.cpp; sourceTree = SOURCE_ROOT; }; + A1F593B30B8F06F900073279 /* libtbb.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtbb.dylib; path = ../../../../lib/libtbb.dylib; sourceTree = SOURCE_ROOT; }; + A1F594EB0B8F4B5600073279 /* convex_hull_bench */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = convex_hull_bench; sourceTree = BUILT_PRODUCTS_DIR; }; + A1F594FA0B8F4EE000073279 /* convex_hull_sample */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = convex_hull_sample; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8DD76F660486A84900D96B5E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A1F593B70B8F06F900073279 /* libtbb.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1F594E90B8F4B5600073279 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A1F594FC0B8F4F1000073279 /* libtbb.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* convex_hull */ = { + isa = PBXGroup; + children = ( + 08FB7795FE84155DC02AAC07 /* Source */, + A1F593B20B8F06F900073279 /* External Frameworks and Libraries */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + ); + name = convex_hull; + sourceTree = ""; + }; + 08FB7795FE84155DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + A146114C0B9463CB000C6B18 /* convex_hull.h */, + A14611490B94631F000C6B18 /* convex_hull_bench.cpp */, + A1F593A50B8F042A00073279 /* convex_hull_sample.cpp */, + ); + name = Source; + sourceTree = ""; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + A1F594EB0B8F4B5600073279 /* convex_hull_bench */, + A1F594FA0B8F4EE000073279 /* convex_hull_sample */, + ); + name = Products; + sourceTree = ""; + }; + A1F593B20B8F06F900073279 /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + A1F593B30B8F06F900073279 /* libtbb.dylib */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8DD76F620486A84900D96B5E /* convex_hull_sample */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "convex_hull_sample" */; + buildPhases = ( + 8DD76F640486A84900D96B5E /* Sources */, + 8DD76F660486A84900D96B5E /* Frameworks */, + 8DD76F690486A84900D96B5E /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = convex_hull_sample; + productInstallPath = "$(HOME)/bin"; + productName = convex_hull; + productReference = A1F594FA0B8F4EE000073279 /* convex_hull_sample */; + productType = "com.apple.product-type.tool"; + }; + A1F594EA0B8F4B5600073279 /* convex_hull_bench */ = { + isa = PBXNativeTarget; + buildConfigurationList = A1F594EE0B8F4B8200073279 /* Build configuration list for PBXNativeTarget "convex_hull_bench" */; + buildPhases = ( + A1F594E80B8F4B5600073279 /* Sources */, + A1F594E90B8F4B5600073279 /* Frameworks */, + A1F594F40B8F4E7700073279 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = convex_hull_bench; + productName = convex_hull_bench; + productReference = A1F594EB0B8F4B5600073279 /* convex_hull_bench */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0410; + }; + buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "convex_hull" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 08FB7794FE84155DC02AAC07 /* convex_hull */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DD76F620486A84900D96B5E /* convex_hull_sample */, + A1F594EA0B8F4B5600073279 /* convex_hull_bench */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 8DD76F640486A84900D96B5E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1F593A60B8F042A00073279 /* convex_hull_sample.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A1F594E80B8F4B5600073279 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A146114A0B94631F000C6B18 /* convex_hull_bench.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1DEB923208733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = convex_hull_sample; + ZERO_LINK = NO; + }; + name = Debug; + }; + 1DEB923308733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = convex_hull_sample; + ZERO_LINK = NO; + }; + name = Release; + }; + 1DEB923608733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Debug; + }; + 1DEB923708733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Release; + }; + A1F593C60B8F0E6E00073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = convex_hull_sample; + ZERO_LINK = NO; + }; + name = Debug64; + }; + A1F593C70B8F0E6E00073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = convex_hull_sample; + ZERO_LINK = NO; + }; + name = Release64; + }; + A1F593C80B8F0E6E00073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-m64", + ); + OTHER_LDFLAGS = "-m64"; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Debug64; + }; + A1F593C90B8F0E6E00073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-m64", + ); + OTHER_LDFLAGS = "-m64"; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Release64; + }; + A1F594EF0B8F4B8200073279 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = convex_hull_bench; + ZERO_LINK = NO; + }; + name = Debug; + }; + A1F594F00B8F4B8200073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = convex_hull_bench; + ZERO_LINK = NO; + }; + name = Debug64; + }; + A1F594F10B8F4B8200073279 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = convex_hull_bench; + ZERO_LINK = NO; + }; + name = Release; + }; + A1F594F20B8F4B8200073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = convex_hull_bench; + ZERO_LINK = NO; + }; + name = Release64; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "convex_hull_sample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923208733DC60010E9CD /* Debug */, + A1F593C60B8F0E6E00073279 /* Debug64 */, + 1DEB923308733DC60010E9CD /* Release */, + A1F593C70B8F0E6E00073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "convex_hull" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923608733DC60010E9CD /* Debug */, + A1F593C80B8F0E6E00073279 /* Debug64 */, + 1DEB923708733DC60010E9CD /* Release */, + A1F593C90B8F0E6E00073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A1F594EE0B8F4B8200073279 /* Build configuration list for PBXNativeTarget "convex_hull_bench" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A1F594EF0B8F4B8200073279 /* Debug */, + A1F594F00B8F4B8200073279 /* Debug64 */, + A1F594F10B8F4B8200073279 /* Release */, + A1F594F20B8F4B8200073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/src/tbb/examples/parallel_reduce/index.html b/src/tbb/examples/parallel_reduce/index.html new file mode 100644 index 0000000..c25a0bb --- /dev/null +++ b/src/tbb/examples/parallel_reduce/index.html @@ -0,0 +1,26 @@ + + + +

    Overview

    +This directory has examples of the template parallel_reduce. + +

    Directories

    +
    +
    convex_hull +
    Parallel version of convex hull algorithm (quick hull). +
    primes +
    Parallel version of the Sieve of Eratosthenes. +
    + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + + diff --git a/src/tbb/examples/parallel_reduce/primes/Makefile b/src/tbb/examples/parallel_reduce/primes/Makefile new file mode 100644 index 0000000..9b6f06e --- /dev/null +++ b/src/tbb/examples/parallel_reduce/primes/Makefile @@ -0,0 +1,69 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# GNU Makefile that builds and runs example. +PROG=primes +ARGS= +PERF_RUN_ARGS=silent auto 1000000000 1000 20 + +# The C++ compiler +ifneq (,$(shell which icc 2>/dev/null)) +CXX=icc +endif # icc + +ifeq ($(offload), mic) +override CXXFLAGS += -D__TBB_MIC=1 +endif + +ifeq ($(CXX), icc) +TBBLIB = -tbb +TBBLIB_DEBUG = -tbb +else +TBBLIB = -ltbb +TBBLIB_DEBUG = -ltbb_debug +endif + +ifeq ($(shell uname), Linux) +LIBS+= -lrt +endif + +all: release test + +release: main.cpp primes.cpp + $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ $(TBBLIB) $(LIBS) + +debug: main.cpp primes.cpp + $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ $(TBBLIB_DEBUG) $(LIBS) + +clean: + $(RM) $(PROG) *.o *.d + +test: + ./$(PROG) $(ARGS) + +perf_build: release + +perf_run: diff --git a/src/tbb/examples/parallel_reduce/primes/Makefile.windows b/src/tbb/examples/parallel_reduce/primes/Makefile.windows new file mode 100644 index 0000000..a5c813b --- /dev/null +++ b/src/tbb/examples/parallel_reduce/primes/Makefile.windows @@ -0,0 +1,60 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Common Makefile that builds and runs example. + +# Just specify your program basename +PROG=Primes +ARGS=0:auto +PERF_RUN_ARGS=silent auto 1000000000 1000 20 + +# Trying to find if icl.exe is set +CXX1 = $(TBB_CXX)- +CXX2 = $(CXX1:icl.exe-=icl.exe) +CXX = $(CXX2:-=cl.exe) + +# The C++ compiler options +MYCXXFLAGS = /TP /EHsc /W3 /nologo /D _CONSOLE /D _MBCS /D WIN32 $(CXXFLAGS) +MYLDFLAGS =/INCREMENTAL:NO /NOLOGO /DEBUG /FIXED:NO $(LDFLAGS) + +all: release test +release: compiler_check + $(CXX) main.cpp primes.cpp /MD /O2 /D NDEBUG $(MYCXXFLAGS) /link tbb.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +debug: compiler_check + $(CXX) main.cpp primes.cpp /MDd /Od /Zi /D TBB_USE_DEBUG /D _DEBUG $(MYCXXFLAGS) /link tbb_debug.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +clean: + @cmd.exe /C del $(PROG).exe *.obj *.?db *.manifest +test: + $(PROG) $(ARGS) + +perf_build: release + +perf_run: + ./$(PROG) $(PERF_RUN_ARGS) + +compiler_check: + @echo compiler_test>compiler_test && @$(CXX) /E compiler_test >nul 2>&1 || echo "$(CXX) command not found. Check if CXX=$(CXX) is set properly" + @cmd.exe /C del compiler_test diff --git a/src/tbb/examples/parallel_reduce/primes/index.html b/src/tbb/examples/parallel_reduce/primes/index.html new file mode 100644 index 0000000..39c1d36 --- /dev/null +++ b/src/tbb/examples/parallel_reduce/primes/index.html @@ -0,0 +1,63 @@ + + + +

    Overview

    +
    +
    Parallel version of the Sieve of Eratosthenes. +
    The example can be built in the offload version to run on Intel® Many Integrated Core (Intel® MIC) Architecture based coprocessor (see build instructions). +
    + +

    Files

    +
    +
    main.cpp +
    Main program which parses command line options and runs the algorithm with different numbers of threads. +
    primes.h +
    The Sieve of Eratosthenes interface. +
    primes.cpp +
    The Sieve of Eratosthenes implementation. +
    Makefile +
    Makefile for building example. +
    + +

    Directories

    +
    +
    msvs +
    Contains Microsoft* Visual Studio* 2005 workspace for building and running the + example (Windows* systems only).
    xcode +
    Contains Xcode* IDE workspace for building and running the example (Mac OS* X + systems only).
    + +

    To Build

    +General build directions can be found here. +here + +

    Usage

    +
    +
    primes -h +
    Prints the help for command line options +
    primes [n-of-threads=value] [number=value] [grain-size=value] [n-of-repeats=value] [silent] +
    primes [n-of-threads [number [grain-size [n-of-repeats]]]][silent] +
    n-of-threads is the number of threads to use; a range of the form low[:high], where low and optional high are non-negative integers or 'auto' for the TBB default.
    + number is an upper bound of range to search primes in, must be a positive integer.
    + grain-size is an optional grain size, must be a positive integer.
    + n-of-repeats is a number of the calculation repeats, must be a positive integer.
    + silent - no output except elapsed time.
    + +
    To run a short version of this example, e.g., for use with Intel® Parallel Inspector: +
    Build a debug version of the example + (see the build directions). +
    Run it with a small problem size and the desired number of threads, e.g., primes 4 100000. +
    + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + + diff --git a/src/tbb/examples/parallel_reduce/primes/main.cpp b/src/tbb/examples/parallel_reduce/primes/main.cpp new file mode 100644 index 0000000..510ec97 --- /dev/null +++ b/src/tbb/examples/parallel_reduce/primes/main.cpp @@ -0,0 +1,132 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "primes.h" +#include +#include +#include +#include +#include +#include +#include +#include "tbb/tick_count.h" + +#include "../../common/utility/utility.h" + +struct RunOptions{ + //! NumberType of threads to use. + utility::thread_number_range threads; + //whether to suppress additional output + bool silentFlag; + // + NumberType n; + //! Grain size parameter + NumberType grainSize; + // number of time to repeat calculation + NumberType repeatNumber; + + RunOptions(utility::thread_number_range threads, NumberType grainSize, NumberType n, bool silentFlag, NumberType repeatNumber) + : threads(threads), grainSize(grainSize), n(n), silentFlag(silentFlag), repeatNumber(repeatNumber) + {} +}; + +int do_get_default_num_threads() { + int threads; + #if __TBB_MIC + #pragma offload target(mic) out(threads) + #endif // __TBB_MIC + threads = tbb::task_scheduler_init::default_num_threads(); + return threads; +} + +int get_default_num_threads() { + static int threads = do_get_default_num_threads(); + return threads; +} + +//! Parse the command line. +static RunOptions ParseCommandLine( int argc, const char* argv[] ) { + utility::thread_number_range threads( get_default_num_threads, 0, get_default_num_threads() ); + NumberType grainSize = 1000; + bool silent = false; + NumberType number = 100000000; + NumberType repeatNumber = 1; + + utility::parse_cli_arguments(argc,argv, + utility::cli_argument_pack() + //"-h" option for for displaying help is present implicitly + .positional_arg(threads,"n-of-threads","number of threads to use; a range of the form low[:high], where low and optional high are non-negative integers or 'auto' for the TBB default.") + .positional_arg(number,"number","upper bound of range to search primes in, must be a positive integer") + .positional_arg(grainSize,"grain-size","must be a positive integer") + .positional_arg(repeatNumber,"n-of-repeats","repeat the calculation this number of times, must be a positive integer") + .arg(silent,"silent","no output except elapsed time") + ); + + RunOptions options(threads,grainSize, number, silent, repeatNumber); + return options; +} + +int main( int argc, const char* argv[] ) { + tbb::tick_count mainBeginMark = tbb::tick_count::now(); + RunOptions options =ParseCommandLine(argc,argv); + + // Try different numbers of threads + for( int p=options.threads.first; p<=options.threads.last; ++p ) { + for (NumberType i=0; i + + + + diff --git a/src/tbb/examples/parallel_reduce/primes/msvs/primes.vcproj b/src/tbb/examples/parallel_reduce/primes/msvs/primes.vcproj new file mode 100644 index 0000000..74d2ef2 --- /dev/null +++ b/src/tbb/examples/parallel_reduce/primes/msvs/primes.vcproj @@ -0,0 +1,364 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/parallel_reduce/primes/msvs/primes_cl.sln b/src/tbb/examples/parallel_reduce/primes/msvs/primes_cl.sln new file mode 100644 index 0000000..9e30985 --- /dev/null +++ b/src/tbb/examples/parallel_reduce/primes/msvs/primes_cl.sln @@ -0,0 +1,25 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "primes", "primes.vcproj", "{3AA40693-F93D-4D4B-B32E-068F511A252A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|Win32.ActiveCfg = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|Win32.Build.0 = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|x64.ActiveCfg = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|x64.Build.0 = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|Win32.ActiveCfg = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|Win32.Build.0 = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|x64.ActiveCfg = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/parallel_reduce/primes/msvs/primes_icl.sln b/src/tbb/examples/parallel_reduce/primes/msvs/primes_icl.sln new file mode 100644 index 0000000..cde13dc --- /dev/null +++ b/src/tbb/examples/parallel_reduce/primes/msvs/primes_icl.sln @@ -0,0 +1,33 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "primes", "primes.icproj", "{D731702C-B704-468D-9497-A75EE0521C89}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D731702C-B704-468D-9497-A75EE0521C89}.Debug|Win32.ActiveCfg = Debug|Win32 + {D731702C-B704-468D-9497-A75EE0521C89}.Debug|Win32.Build.0 = Debug|Win32 + {D731702C-B704-468D-9497-A75EE0521C89}.Debug|x64.ActiveCfg = Debug|x64 + {D731702C-B704-468D-9497-A75EE0521C89}.Debug|x64.Build.0 = Debug|x64 + {D731702C-B704-468D-9497-A75EE0521C89}.Release|Win32.ActiveCfg = Release|Win32 + {D731702C-B704-468D-9497-A75EE0521C89}.Release|Win32.Build.0 = Release|Win32 + {D731702C-B704-468D-9497-A75EE0521C89}.Release|x64.ActiveCfg = Release|x64 + {D731702C-B704-468D-9497-A75EE0521C89}.Release|x64.Build.0 = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|x64.Build.0 = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|x64.ActiveCfg = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|Win32.Build.0 = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Release|Win32.ActiveCfg = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|x64.Build.0 = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|x64.ActiveCfg = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|Win32.Build.0 = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252A}.Debug|Win32.ActiveCfg = Debug|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/parallel_reduce/primes/primes.cpp b/src/tbb/examples/parallel_reduce/primes/primes.cpp new file mode 100644 index 0000000..414eff5 --- /dev/null +++ b/src/tbb/examples/parallel_reduce/primes/primes.cpp @@ -0,0 +1,317 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Example program that computes number of prime numbers up to n, +// where n is a command line argument. The algorithm here is a +// fairly efficient version of the sieve of Eratosthenes. +// The parallel version demonstrates how to use parallel_reduce, +// and in particular how to exploit lazy splitting. + +#include "primes.h" + +#if __TBB_MIC +#pragma offload_attribute (target(mic)) +#endif // __TBB_MIC +#include +#include +#include +#include +#include +#include +#include +#include "tbb/parallel_reduce.h" +#include "tbb/task_scheduler_init.h" + +using namespace std; + +//! If true, then print primes on stdout. +static bool printPrimes = false; + + +class Multiples { + inline NumberType strike( NumberType start, NumberType limit, NumberType stride ) { + // Hoist "my_is_composite" into register for sake of speed. + bool* is_composite = my_is_composite; + assert( stride>=2 ); + for( ;start=1 ); + my_is_composite = new bool[m/2]; + my_striker = new NumberType[m/2]; + for( size_t k=0; k=2; + if( n>=3 ) { + Multiples multiples(n); + count += multiples.n_factor; + if( printPrimes ) + printf("---\n"); + NumberType window_size = multiples.m; + for( NumberType j=multiples.m; j<=n; j+=window_size ) { + if( j+window_size>n+1 ) + window_size = n+1-j; + count += multiples.find_primes_in_window( j, window_size ); + } + } + return count; +} + +//! Range of a sieve window. +class SieveRange { + //! Width of full-size window into sieve. + const NumberType my_stride; + + //! Always multiple of my_stride + NumberType my_begin; + + //! One past last number in window. + NumberType my_end; + + //! Width above which it is worth forking. + const NumberType my_grainsize; + + bool assert_okay() const { + assert( my_begin%my_stride==0 ); + assert( my_begin<=my_end ); + assert( my_stride<=my_grainsize ); + return true; + } +public: + //------------------------------------------------------------------------ + // Begin signatures required by parallel_reduce + //------------------------------------------------------------------------ + bool is_divisible() const {return my_end-my_begin>my_grainsize;} + bool empty() const {return my_end<=my_begin;} + SieveRange( SieveRange& r, tbb::split ) : + my_stride(r.my_stride), + my_grainsize(r.my_grainsize), + my_end(r.my_end) + { + assert( r.is_divisible() ); + assert( r.assert_okay() ); + NumberType middle = r.my_begin + (r.my_end-r.my_begin+r.my_stride-1)/2; + middle = middle/my_stride*my_stride; + my_begin = middle; + r.my_end = middle; + assert( assert_okay() ); + assert( r.assert_okay() ); + } + //------------------------------------------------------------------------ + // End of signatures required by parallel_reduce + //------------------------------------------------------------------------ + NumberType begin() const {return my_begin;} + NumberType end() const {return my_end;} + SieveRange( NumberType begin, NumberType end, NumberType stride, NumberType grainsize ) : + my_begin(begin), + my_end(end), + my_stride(stride), + my_grainsize(grainsizer.end() ) + window_size = r.end()-j; + count += multiples.find_primes_in_window( j, window_size ); + } + } + void join( Sieve& other ) { + count += other.count; + // Final value of multiples needs to final value of other.mulitiples, + // so that *this can correcty process next window to right. + multiples.move( other.multiples ); + } + Sieve( Sieve& other, tbb::split ) : + multiples(other.multiples,tbb::split()), + count(0) + {} + //------------------------------------------------------------------------ + // End of signatures required by parallel_reduce + //------------------------------------------------------------------------ +}; + +//! Count number of primes between 0 and n +/** This is the parallel version. */ +NumberType ParallelCountPrimes( NumberType n , int number_of_threads, NumberType grain_size ) { + tbb::task_scheduler_init init(number_of_threads); + + // Two is special case + NumberType count = n>=2; + if( n>=3 ) { + Sieve s(n); + count += s.multiples.n_factor; + if( printPrimes ) + printf("---\n"); + using namespace tbb; + // Explicit grain size and simple_partitioner() used here instead of automatic grainsize + // determination becase we want SieveRange to be decomposed down to grainSize or smaller. + // Doing so improves odds that the working set fits in cache when evaluating Sieve::operator(). + parallel_reduce( SieveRange( s.multiples.m, n, s.multiples.m, grain_size ), s, simple_partitioner() ); + count += s.count; + } + return count; +} diff --git a/src/tbb/examples/parallel_reduce/primes/primes.h b/src/tbb/examples/parallel_reduce/primes/primes.h new file mode 100644 index 0000000..b763a14 --- /dev/null +++ b/src/tbb/examples/parallel_reduce/primes/primes.h @@ -0,0 +1,52 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef PRIMES_H_ +#define PRIMES_H_ + +#if __TBB_MIC +#pragma offload_attribute (push,target(mic)) +#endif // __TBB_MIC + +#include "tbb/task_scheduler_init.h" +#include +typedef std::size_t NumberType; + +//! Count number of primes between 0 and n +/** This is the serial version. */ +NumberType SerialCountPrimes( NumberType n); + +//! Count number of primes between 0 and n +/** This is the parallel version. */ +NumberType ParallelCountPrimes( NumberType n, int numberOfThreads= tbb::task_scheduler_init::automatic, NumberType grainSize = 1000); + +#if __TBB_MIC +#pragma offload_attribute (pop) +#endif // __TBB_MIC + +#endif /* PRIMES_H_ */ diff --git a/src/tbb/examples/parallel_reduce/primes/xcode/primes.xcodeproj/project.pbxproj b/src/tbb/examples/parallel_reduce/primes/xcode/primes.xcodeproj/project.pbxproj new file mode 100644 index 0000000..2202d31 --- /dev/null +++ b/src/tbb/examples/parallel_reduce/primes/xcode/primes.xcodeproj/project.pbxproj @@ -0,0 +1,311 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + A1F593A60B8F042A00073279 /* primes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1F593A50B8F042A00073279 /* primes.cpp */; }; + A1F593B70B8F06F900073279 /* libtbb.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; + A1F593BB0B8F072500073279 /* libtbb.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; + EA8D882D1301731B00385DE1 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA8D882C1301731B00385DE1 /* main.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8DD76F690486A84900D96B5E /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = ""; + dstSubfolderSpec = 16; + files = ( + A1F593BB0B8F072500073279 /* libtbb.dylib in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 8DD76F6C0486A84900D96B5E /* primes */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = primes; sourceTree = BUILT_PRODUCTS_DIR; }; + A1F593A50B8F042A00073279 /* primes.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = primes.cpp; path = ../primes.cpp; sourceTree = SOURCE_ROOT; }; + A1F593B30B8F06F900073279 /* libtbb.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtbb.dylib; path = ../../../../lib/libtbb.dylib; sourceTree = SOURCE_ROOT; }; + EA8D882B130172E400385DE1 /* primes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = primes.h; path = ../primes.h; sourceTree = SOURCE_ROOT; }; + EA8D882C1301731B00385DE1 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = ../main.cpp; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8DD76F660486A84900D96B5E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A1F593B70B8F06F900073279 /* libtbb.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* primes */ = { + isa = PBXGroup; + children = ( + 08FB7795FE84155DC02AAC07 /* Source */, + A1F593B20B8F06F900073279 /* External Frameworks and Libraries */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + ); + name = primes; + sourceTree = ""; + }; + 08FB7795FE84155DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + EA8D882C1301731B00385DE1 /* main.cpp */, + EA8D882B130172E400385DE1 /* primes.h */, + A1F593A50B8F042A00073279 /* primes.cpp */, + ); + name = Source; + sourceTree = ""; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8DD76F6C0486A84900D96B5E /* primes */, + ); + name = Products; + sourceTree = ""; + }; + A1F593B20B8F06F900073279 /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + A1F593B30B8F06F900073279 /* libtbb.dylib */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8DD76F620486A84900D96B5E /* primes */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "primes" */; + buildPhases = ( + 8DD76F640486A84900D96B5E /* Sources */, + 8DD76F660486A84900D96B5E /* Frameworks */, + 8DD76F690486A84900D96B5E /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = primes; + productInstallPath = "$(HOME)/bin"; + productName = primes; + productReference = 8DD76F6C0486A84900D96B5E /* primes */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0410; + }; + buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "primes" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 08FB7794FE84155DC02AAC07 /* primes */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DD76F620486A84900D96B5E /* primes */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 8DD76F640486A84900D96B5E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1F593A60B8F042A00073279 /* primes.cpp in Sources */, + EA8D882D1301731B00385DE1 /* main.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1DEB923208733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = primes; + ZERO_LINK = NO; + }; + name = Debug; + }; + 1DEB923308733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = primes; + ZERO_LINK = NO; + }; + name = Release; + }; + 1DEB923608733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Debug; + }; + 1DEB923708733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Release; + }; + A1F593C60B8F0E6E00073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = primes; + ZERO_LINK = NO; + }; + name = Debug64; + }; + A1F593C70B8F0E6E00073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = primes; + ZERO_LINK = NO; + }; + name = Release64; + }; + A1F593C80B8F0E6E00073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-m64", + ); + OTHER_LDFLAGS = "-m64"; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Debug64; + }; + A1F593C90B8F0E6E00073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-m64", + ); + OTHER_LDFLAGS = "-m64"; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Release64; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "primes" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923208733DC60010E9CD /* Debug */, + A1F593C60B8F0E6E00073279 /* Debug64 */, + 1DEB923308733DC60010E9CD /* Release */, + A1F593C70B8F0E6E00073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "primes" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923608733DC60010E9CD /* Debug */, + A1F593C80B8F0E6E00073279 /* Debug64 */, + 1DEB923708733DC60010E9CD /* Release */, + A1F593C90B8F0E6E00073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/src/tbb/examples/pipeline/index.html b/src/tbb/examples/pipeline/index.html new file mode 100644 index 0000000..20c213c --- /dev/null +++ b/src/tbb/examples/pipeline/index.html @@ -0,0 +1,24 @@ + + + +

    Overview

    +This directory has examples of the template pipeline. + +

    Directories

    +
    +
    square +
    Another simple string transformation example that squares numbers read from a file. +
    + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + + diff --git a/src/tbb/examples/pipeline/square/Makefile b/src/tbb/examples/pipeline/square/Makefile new file mode 100644 index 0000000..44e2850 --- /dev/null +++ b/src/tbb/examples/pipeline/square/Makefile @@ -0,0 +1,68 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# GNU Makefile that builds and runs example. +PROG=square +ARGS=0 input.txt output.txt +PERF_RUN_ARGS=auto input.txt output.txt silent +GEN=gen_input + +# The C++ compiler +ifneq (,$(shell which icc 2>/dev/null)) +CXX=icc +endif # icc + +SQUARE = square.cpp + +ifeq ($(shell uname), Linux) +LIBS+= -lrt +endif + +all: release test + +release: $(SQUARE) input.txt + $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $(SQUARE) -ltbb $(LIBS) + +debug: $(SQUARE) input.txt + $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $(SQUARE) -ltbb_debug $(LIBS) + +clean: + $(RM) $(PROG) $(GEN) *.o *.d input.txt output.txt + +$(GEN): gen_input.cpp + $(CXX) -O2 $(CXXFLAGS) -o $(GEN) $^ $(LIBS) + +input.txt: $(GEN) + ./$(GEN) >input.txt + +test: input.txt + ./$(PROG) $(ARGS) + +perf_build: $(SQUARE) input.txt + $(CXX) -O2 -msse2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $(SQUARE) -ltbb $(LIBS) + +perf_run: input.txt + ./$(PROG) $(PERF_RUN_ARGS) diff --git a/src/tbb/examples/pipeline/square/Makefile.windows b/src/tbb/examples/pipeline/square/Makefile.windows new file mode 100644 index 0000000..747e143 --- /dev/null +++ b/src/tbb/examples/pipeline/square/Makefile.windows @@ -0,0 +1,62 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Common Makefile that builds and runs example. + +# Just specify your program basename +PROG=square +ARGS=0 input.txt output.txt +PERF_RUN_ARGS=auto input.txt output.txt silent + +# Trying to find if icl.exe is set +CXX1 = $(TBB_CXX)- +CXX2 = $(CXX1:icl.exe-=icl.exe) +CXX = $(CXX2:-=cl.exe) + +# The C++ compiler options +MYCXXFLAGS = /TP /EHsc /W3 /nologo /D _CONSOLE /D _MBCS /D WIN32 $(CXXFLAGS) /D _CRT_SECURE_NO_DEPRECATE /D _SECURE_SCL=0 /arch:sse2 +MYLDFLAGS =/INCREMENTAL:NO /NOLOGO /DEBUG /FIXED:NO $(LDFLAGS) +SQUARE = square.cpp + +all: release test +release: compiler_check + $(CXX) $(SQUARE) /MD /O2 /D NDEBUG $(MYCXXFLAGS) /link tbb.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +debug: compiler_check + $(CXX) $(SQUARE) /MDd /Od /Zi /D TBB_USE_DEBUG /D _DEBUG $(MYCXXFLAGS) /link tbb_debug.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +clean: + @cmd.exe /C del $(PROG).exe input.txt output.txt *.obj *.?db *.manifest gen_input.exe +gen_input.exe: gen_input.cpp + $(CXX) gen_input.cpp +input.txt: gen_input.exe + gen_input.exe > input.txt +test: input.txt + $(PROG) $(ARGS) +compiler_check: + @echo compiler_test>compiler_test && @$(CXX) /E compiler_test >nul 2>&1 || echo "$(CXX) command not found. Check if CXX=$(CXX) is set properly" + @cmd.exe /C del compiler_test +perf_build: release +perf_run: input.txt + $(PROG) $(PERF_RUN_ARGS) diff --git a/src/tbb/examples/pipeline/square/gen_input.cpp b/src/tbb/examples/pipeline/square/gen_input.cpp new file mode 100644 index 0000000..b870952 --- /dev/null +++ b/src/tbb/examples/pipeline/square/gen_input.cpp @@ -0,0 +1,44 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include +#include + +//! Generates sample input for square.cpp +int main( int argc, char* argv[] ) { + long num = argc>1 ? atol(argv[1]) : 1000000; + int a=0; + int b=1; + for( long j=0; j + + +

    Overview

    +Text filter that demonstrates class pipeline. Example program reads a file +containing decimal integers in text format, and changes each to its square. + +

    Files

    +
    +
    square.cpp +
    Source code for example. +
    gen_input.cpp +
    Source code for sample input generation. +
    Makefile +
    Makefile for building example. +
    + +

    Directories

    +
    +
    msvs +
    Contains Microsoft* Visual Studio* 2005 workspace for building and running the + example (Windows* systems only).
    xcode +
    Contains Xcode* IDE workspace for building and running the example (Mac OS* X + systems only).
    + +

    To Build

    +General build directions can be found here. +

    +Two additional targets for this example: +
    +
    make gen_input +
    Create an input generator program that prints out a sequence of integers. +
    make input.txt +
    Create an input file for the example (with help of gen_input). +
    +

    + +

    Usage

    +
    +
    square -h +
    Prints the help for command line options +
    square [n-of-threads=value] [input-file=value] [output-file=value] [max-slice-size=value] [silent] +
    square [n-of-threads [input-file [output-file [max-slice-size]]]] [silent] +
    n-of-threads is the number of threads to use; a range of the form low[:high], where low and optional high are non-negative integers or 'auto' for the TBB default.
    + input-file is an input file name.
    + output-file is an output file name.
    + max-slice-size is the maximum number of characters in one slice.
    + silent - no output except elapsed time.
    +
    gen_input [LN] > inputfile +
    Generate a file named inputfile consisting of LN lines each containing one integer. + If not specified, LN is assumed to be 1000000. + +
    To run a short version of this example, e.g., for use with Intel® Parallel Inspector: +
    Build a debug version of the example + (see the build directions). +
    Prepare an inputfile with about 5,000 lines of text (see the instruction above). +
    Run it with this inputfile and the desired number of threads, + e.g., square 4 inputfile outputfile. +
    + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + diff --git a/src/tbb/examples/pipeline/square/msvs/gen_input.icproj b/src/tbb/examples/pipeline/square/msvs/gen_input.icproj new file mode 100644 index 0000000..50048b7 --- /dev/null +++ b/src/tbb/examples/pipeline/square/msvs/gen_input.icproj @@ -0,0 +1,11 @@ + + + + + diff --git a/src/tbb/examples/pipeline/square/msvs/gen_input.vcproj b/src/tbb/examples/pipeline/square/msvs/gen_input.vcproj new file mode 100644 index 0000000..9a0af57 --- /dev/null +++ b/src/tbb/examples/pipeline/square/msvs/gen_input.vcproj @@ -0,0 +1,354 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/pipeline/square/msvs/square.icproj b/src/tbb/examples/pipeline/square/msvs/square.icproj new file mode 100644 index 0000000..a957bf5 --- /dev/null +++ b/src/tbb/examples/pipeline/square/msvs/square.icproj @@ -0,0 +1,11 @@ + + + + + diff --git a/src/tbb/examples/pipeline/square/msvs/square.vcproj b/src/tbb/examples/pipeline/square/msvs/square.vcproj new file mode 100644 index 0000000..3632731 --- /dev/null +++ b/src/tbb/examples/pipeline/square/msvs/square.vcproj @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/pipeline/square/msvs/square.vcproj.user b/src/tbb/examples/pipeline/square/msvs/square.vcproj.user new file mode 100644 index 0000000..22c54af --- /dev/null +++ b/src/tbb/examples/pipeline/square/msvs/square.vcproj.user @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/pipeline/square/msvs/square_cl.sln b/src/tbb/examples/pipeline/square/msvs/square_cl.sln new file mode 100644 index 0000000..056f4f2 --- /dev/null +++ b/src/tbb/examples/pipeline/square/msvs/square_cl.sln @@ -0,0 +1,38 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "square", "square.vcproj", "{A21C0AEE-ADDC-45F0-A668-58FF10351D23}" + ProjectSection(ProjectDependencies) = postProject + {25A46A49-406F-4681-8AC9-5FE46F38E5A7} = {25A46A49-406F-4681-8AC9-5FE46F38E5A7} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_input", "gen_input.vcproj", "{25A46A49-406F-4681-8AC9-5FE46F38E5A7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A21C0AEE-ADDC-45F0-A668-58FF10351D23}.Debug|Win32.ActiveCfg = Debug|Win32 + {A21C0AEE-ADDC-45F0-A668-58FF10351D23}.Debug|Win32.Build.0 = Debug|Win32 + {A21C0AEE-ADDC-45F0-A668-58FF10351D23}.Debug|x64.ActiveCfg = Debug|x64 + {A21C0AEE-ADDC-45F0-A668-58FF10351D23}.Debug|x64.Build.0 = Debug|x64 + {A21C0AEE-ADDC-45F0-A668-58FF10351D23}.Release|Win32.ActiveCfg = Release|Win32 + {A21C0AEE-ADDC-45F0-A668-58FF10351D23}.Release|Win32.Build.0 = Release|Win32 + {A21C0AEE-ADDC-45F0-A668-58FF10351D23}.Release|x64.ActiveCfg = Release|x64 + {A21C0AEE-ADDC-45F0-A668-58FF10351D23}.Release|x64.Build.0 = Release|x64 + {25A46A49-406F-4681-8AC9-5FE46F38E5A7}.Debug|Win32.ActiveCfg = Debug|Win32 + {25A46A49-406F-4681-8AC9-5FE46F38E5A7}.Debug|Win32.Build.0 = Debug|Win32 + {25A46A49-406F-4681-8AC9-5FE46F38E5A7}.Debug|x64.ActiveCfg = Debug|x64 + {25A46A49-406F-4681-8AC9-5FE46F38E5A7}.Debug|x64.Build.0 = Debug|x64 + {25A46A49-406F-4681-8AC9-5FE46F38E5A7}.Release|Win32.ActiveCfg = Release|Win32 + {25A46A49-406F-4681-8AC9-5FE46F38E5A7}.Release|Win32.Build.0 = Release|Win32 + {25A46A49-406F-4681-8AC9-5FE46F38E5A7}.Release|x64.ActiveCfg = Release|x64 + {25A46A49-406F-4681-8AC9-5FE46F38E5A7}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/pipeline/square/msvs/square_icl.sln b/src/tbb/examples/pipeline/square/msvs/square_icl.sln new file mode 100644 index 0000000..f122357 --- /dev/null +++ b/src/tbb/examples/pipeline/square/msvs/square_icl.sln @@ -0,0 +1,54 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "square", "square.icproj", "{7462FB4A-C9BE-40D4-A568-5D08F507EEB1}" + ProjectSection(ProjectDependencies) = postProject + {18ECAB6C-2630-4F8F-BEF2-3DBDEF7355AA} = {18ECAB6C-2630-4F8F-BEF2-3DBDEF7355AA} + EndProjectSection +EndProject +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "gen_input", "gen_input.icproj", "{18ECAB6C-2630-4F8F-BEF2-3DBDEF7355AA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7462FB4A-C9BE-40D4-A568-5D08F507EEB1}.Debug|Win32.ActiveCfg = Debug|Win32 + {7462FB4A-C9BE-40D4-A568-5D08F507EEB1}.Debug|Win32.Build.0 = Debug|Win32 + {7462FB4A-C9BE-40D4-A568-5D08F507EEB1}.Debug|x64.ActiveCfg = Debug|x64 + {7462FB4A-C9BE-40D4-A568-5D08F507EEB1}.Debug|x64.Build.0 = Debug|x64 + {7462FB4A-C9BE-40D4-A568-5D08F507EEB1}.Release|Win32.ActiveCfg = Release|Win32 + {7462FB4A-C9BE-40D4-A568-5D08F507EEB1}.Release|Win32.Build.0 = Release|Win32 + {7462FB4A-C9BE-40D4-A568-5D08F507EEB1}.Release|x64.ActiveCfg = Release|x64 + {7462FB4A-C9BE-40D4-A568-5D08F507EEB1}.Release|x64.Build.0 = Release|x64 + {18ECAB6C-2630-4F8F-BEF2-3DBDEF7355AA}.Debug|Win32.ActiveCfg = Debug|Win32 + {18ECAB6C-2630-4F8F-BEF2-3DBDEF7355AA}.Debug|Win32.Build.0 = Debug|Win32 + {18ECAB6C-2630-4F8F-BEF2-3DBDEF7355AA}.Debug|x64.ActiveCfg = Debug|x64 + {18ECAB6C-2630-4F8F-BEF2-3DBDEF7355AA}.Debug|x64.Build.0 = Debug|x64 + {18ECAB6C-2630-4F8F-BEF2-3DBDEF7355AA}.Release|Win32.ActiveCfg = Release|Win32 + {18ECAB6C-2630-4F8F-BEF2-3DBDEF7355AA}.Release|Win32.Build.0 = Release|Win32 + {18ECAB6C-2630-4F8F-BEF2-3DBDEF7355AA}.Release|x64.ActiveCfg = Release|x64 + {18ECAB6C-2630-4F8F-BEF2-3DBDEF7355AA}.Release|x64.Build.0 = Release|x64 + {A21C0AEE-ADDC-45F0-A668-58FF10351D23}.Release|x64.Build.0 = Release|x64 + {A21C0AEE-ADDC-45F0-A668-58FF10351D23}.Release|x64.ActiveCfg = Release|x64 + {A21C0AEE-ADDC-45F0-A668-58FF10351D23}.Release|Win32.Build.0 = Release|Win32 + {A21C0AEE-ADDC-45F0-A668-58FF10351D23}.Release|Win32.ActiveCfg = Release|Win32 + {A21C0AEE-ADDC-45F0-A668-58FF10351D23}.Debug|x64.Build.0 = Debug|x64 + {A21C0AEE-ADDC-45F0-A668-58FF10351D23}.Debug|x64.ActiveCfg = Debug|x64 + {A21C0AEE-ADDC-45F0-A668-58FF10351D23}.Debug|Win32.Build.0 = Debug|Win32 + {A21C0AEE-ADDC-45F0-A668-58FF10351D23}.Debug|Win32.ActiveCfg = Debug|Win32 + {25A46A49-406F-4681-8AC9-5FE46F38E5A7}.Release|x64.Build.0 = Release|x64 + {25A46A49-406F-4681-8AC9-5FE46F38E5A7}.Release|x64.ActiveCfg = Release|x64 + {25A46A49-406F-4681-8AC9-5FE46F38E5A7}.Release|Win32.Build.0 = Release|Win32 + {25A46A49-406F-4681-8AC9-5FE46F38E5A7}.Release|Win32.ActiveCfg = Release|Win32 + {25A46A49-406F-4681-8AC9-5FE46F38E5A7}.Debug|x64.Build.0 = Debug|x64 + {25A46A49-406F-4681-8AC9-5FE46F38E5A7}.Debug|x64.ActiveCfg = Debug|x64 + {25A46A49-406F-4681-8AC9-5FE46F38E5A7}.Debug|Win32.Build.0 = Debug|Win32 + {25A46A49-406F-4681-8AC9-5FE46F38E5A7}.Debug|Win32.ActiveCfg = Debug|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/pipeline/square/square.cpp b/src/tbb/examples/pipeline/square/square.cpp new file mode 100644 index 0000000..96c39eb --- /dev/null +++ b/src/tbb/examples/pipeline/square/square.cpp @@ -0,0 +1,284 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// +// Example program that reads a file of decimal integers in text format +// and changes each to its square. +// +#include "tbb/pipeline.h" +#include "tbb/tick_count.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/tbb_allocator.h" +#include +#include +#include +#include +#include "../../common/utility/utility.h" + +using namespace std; + +//! Holds a slice of text. +/** Instances *must* be allocated/freed using methods herein, because the C++ declaration + represents only the header of a much larger object in memory. */ +class TextSlice { + //! Pointer to one past last character in sequence + char* logical_end; + //! Pointer to one past last available byte in sequence. + char* physical_end; +public: + //! Allocate a TextSlice object that can hold up to max_size characters. + static TextSlice* allocate( size_t max_size ) { + // +1 leaves room for a terminating null character. + TextSlice* t = (TextSlice*)tbb::tbb_allocator().allocate( sizeof(TextSlice)+max_size+1 ); + t->logical_end = t->begin(); + t->physical_end = t->begin()+max_size; + return t; + } + //! Free a TextSlice object + void free() { + tbb::tbb_allocator().deallocate((char*)this,sizeof(TextSlice)+(physical_end-begin())+1); + } + //! Pointer to beginning of sequence + char* begin() {return (char*)(this+1);} + //! Pointer to one past last character in sequence + char* end() {return logical_end;} + //! Length of sequence + size_t size() const {return logical_end-(char*)(this+1);} + //! Maximum number of characters that can be appended to sequence + size_t avail() const {return physical_end-logical_end;} + //! Append sequence [first,last) to this sequence. + void append( char* first, char* last ) { + memcpy( logical_end, first, last-first ); + logical_end += last-first; + } + //! Set end() to given value. + void set_end( char* p ) {logical_end=p;} +}; + +size_t MAX_CHAR_PER_INPUT_SLICE = 4000; +string InputFileName = "input.txt"; +string OutputFileName = "output.txt"; + +class MyInputFilter: public tbb::filter { +public: + MyInputFilter( FILE* input_file_ ); + ~MyInputFilter(); +private: + FILE* input_file; + TextSlice* next_slice; + /*override*/ void* operator()(void*); +}; + +MyInputFilter::MyInputFilter( FILE* input_file_ ) : + filter(serial_in_order), + input_file(input_file_), + next_slice( TextSlice::allocate( MAX_CHAR_PER_INPUT_SLICE ) ) +{ +} + +MyInputFilter::~MyInputFilter() { + next_slice->free(); +} + +void* MyInputFilter::operator()(void*) { + // Read characters into space that is available in the next slice. + size_t m = next_slice->avail(); + size_t n = fread( next_slice->end(), 1, m, input_file ); + if( !n && next_slice->size()==0 ) { + // No more characters to process + return NULL; + } else { + // Have more characters to process. + TextSlice& t = *next_slice; + next_slice = TextSlice::allocate( MAX_CHAR_PER_INPUT_SLICE ); + char* p = t.end()+n; + if( n==m ) { + // Might have read partial number. If so, transfer characters of partial number to next slice. + while( p>t.begin() && isdigit(p[-1]) ) + --p; + next_slice->append( p, t.end()+n ); + } + t.set_end(p); + return &t; + } +} + +//! Filter that changes each decimal number to its square. +class MyTransformFilter: public tbb::filter { +public: + MyTransformFilter(); + /*override*/void* operator()( void* item ); +}; + +MyTransformFilter::MyTransformFilter() : + tbb::filter(parallel) +{} + +/*override*/void* MyTransformFilter::operator()( void* item ) { + TextSlice& input = *static_cast(item); + // Add terminating null so that strtol works right even if number is at end of the input. + *input.end() = '\0'; + char* p = input.begin(); + TextSlice& out = *TextSlice::allocate( 2*MAX_CHAR_PER_INPUT_SLICE ); + char* q = out.begin(); + for(;;) { + while( p(item); + size_t n = fwrite( out.begin(), 1, out.size(), my_output_file ); + if( n!=out.size() ) { + fprintf(stderr,"Can't write into file '%s'\n", OutputFileName.c_str()); + exit(1); + } + out.free(); + return NULL; +} + +bool silent = false; + +int run_pipeline( int nthreads ) +{ + FILE* input_file = fopen( InputFileName.c_str(), "r" ); + if( !input_file ) { + throw std::invalid_argument( ("Invalid input file name: "+InputFileName).c_str() ); + return 0; + } + FILE* output_file = fopen( OutputFileName.c_str(), "w" ); + if( !output_file ) { + throw std::invalid_argument( ("Invalid output file name: "+OutputFileName).c_str() ); + return 0; + } + + // Create the pipeline + tbb::pipeline pipeline; + + // Create file-reading writing stage and add it to the pipeline + MyInputFilter input_filter( input_file ); + pipeline.add_filter( input_filter ); + + // Create squaring stage and add it to the pipeline + MyTransformFilter transform_filter; + pipeline.add_filter( transform_filter ); + + // Create file-writing stage and add it to the pipeline + MyOutputFilter output_filter( output_file ); + pipeline.add_filter( output_filter ); + + // Run the pipeline + tbb::tick_count t0 = tbb::tick_count::now(); + // Need more than one token in flight per thread to keep all threads + // busy; 2-4 works + pipeline.run( nthreads*4 ); + tbb::tick_count t1 = tbb::tick_count::now(); + + fclose( output_file ); + fclose( input_file ); + + if ( !silent ) printf("time = %g\n", (t1-t0).seconds()); + + return 1; +} + +int main( int argc, char* argv[] ) { + try { + tbb::tick_count mainStartTime = tbb::tick_count::now(); + + // The 1st argument is the function to obtain 'auto' value; the 2nd is the default value + // The example interprets 0 threads as "run serially, then fully subscribed" + utility::thread_number_range threads( tbb::task_scheduler_init::default_num_threads, 0 ); + + utility::parse_cli_arguments(argc,argv, + utility::cli_argument_pack() + //"-h" option for for displaying help is present implicitly + .positional_arg(threads,"n-of-threads","number of threads to use; a range of the form low[:high], where low and optional high are non-negative integers or 'auto' for the TBB default.") + .positional_arg(InputFileName,"input-file","input file name") + .positional_arg(OutputFileName,"output-file","output file name") + .positional_arg(MAX_CHAR_PER_INPUT_SLICE, "max-slice-size","the maximum number of characters in one slice") + .arg(silent,"silent","no output except elapsed time") + ); + + if ( threads.first ) { + for(int p = threads.first; p <= threads.last; ++p ) { + if ( !silent ) printf("threads = %d ", p); + tbb::task_scheduler_init init(p); + if(!run_pipeline (p)) + return 1; + } + } else { // Number of threads wasn't set explicitly. Run serial and parallel version + { // serial run + if ( !silent ) printf("serial run "); + tbb::task_scheduler_init init_serial(1); + if(!run_pipeline (1)) + return 1; + } + { // parallel run (number of threads is selected automatically) + if ( !silent ) printf("parallel run "); + tbb::task_scheduler_init init_parallel; + if(!run_pipeline (init_parallel.default_num_threads())) + return 1; + } + } + + utility::report_elapsed_time((tbb::tick_count::now() - mainStartTime).seconds()); + + return 0; + } catch(std::exception& e) { + std::cerr<<"error occurred. error text is :\"" < + + +

    Overview

    +This directory has examples of how to use the raw task scheduler. + +

    Directories

    +
    +
    tree_sum +
    Sum values in a tree. +
    + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + + diff --git a/src/tbb/examples/task/tree_sum/Makefile b/src/tbb/examples/task/tree_sum/Makefile new file mode 100644 index 0000000..a9681e1 --- /dev/null +++ b/src/tbb/examples/task/tree_sum/Makefile @@ -0,0 +1,59 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# GNU Makefile that builds and runs example. +PROG=tree_sum +ARGS= +PERF_RUN_ARGS=auto 100000000 silent + +# The C++ compiler +ifneq (,$(shell which icc 2>/dev/null)) +CXX=icc +endif # icc + +ifeq ($(shell uname), Linux) +LIBS+= -lrt +endif + +all: release test + +release: *.cpp + $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbbmalloc -ltbb $(LIBS) + +debug: *.cpp + $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbbmalloc_debug -ltbb_debug $(LIBS) + +clean: + $(RM) $(PROG) *.o *.d + +test: + ./$(PROG) $(ARGS) + ./$(PROG) stdmalloc $(ARGS) + +perf_build: release + +perf_run: + ./$(PROG) $(PERF_RUN_ARGS) diff --git a/src/tbb/examples/task/tree_sum/Makefile.windows b/src/tbb/examples/task/tree_sum/Makefile.windows new file mode 100644 index 0000000..08ecf03 --- /dev/null +++ b/src/tbb/examples/task/tree_sum/Makefile.windows @@ -0,0 +1,60 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Common Makefile that builds and runs example. + +# Just specify your program basename +PROG=Tree_sum +ARGS= +PERF_RUN_ARGS=auto 100000000 silent + +# Trying to find if icl.exe is set +CXX1 = $(TBB_CXX)- +CXX2 = $(CXX1:icl.exe-=icl.exe) +CXX = $(CXX2:-=cl.exe) + +# The C++ compiler options +MYCXXFLAGS = /TP /EHsc /W3 /nologo /D _CONSOLE /D _MBCS /D WIN32 $(CXXFLAGS) +MYLDFLAGS =/INCREMENTAL:NO /NOLOGO /DEBUG /FIXED:NO $(LDFLAGS) + +all: release test +release: compiler_check + $(CXX) *.cpp /MD /O2 /D NDEBUG $(MYCXXFLAGS) /link tbbmalloc.lib tbb.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +debug: compiler_check + $(CXX) *.cpp /MDd /Od /Zi /D TBB_USE_DEBUG /D _DEBUG $(MYCXXFLAGS) /link tbbmalloc_debug.lib tbb_debug.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +clean: + @cmd.exe /C del $(PROG).exe *.obj *.?db *.manifest +test: + $(PROG) $(ARGS) + $(PROG) stdmalloc $(ARGS) +perf_build: release + +perf_run: + $(PROG) $(PERF_RUN_ARGS) + +compiler_check: + @echo compiler_test>compiler_test && @$(CXX) /E compiler_test >nul 2>&1 || echo "$(CXX) command not found. Check if CXX=$(CXX) is set properly" + @cmd.exe /C del compiler_test diff --git a/src/tbb/examples/task/tree_sum/OptimizedParallelSumTree.cpp b/src/tbb/examples/task/tree_sum/OptimizedParallelSumTree.cpp new file mode 100644 index 0000000..7e81e8d --- /dev/null +++ b/src/tbb/examples/task/tree_sum/OptimizedParallelSumTree.cpp @@ -0,0 +1,77 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "common.h" +#include "tbb/task.h" + +class OptimizedSumTask: public tbb::task { + Value* const sum; + TreeNode* root; + bool is_continuation; + Value x, y; +public: + OptimizedSumTask( TreeNode* root_, Value* sum_ ) : root(root_), sum(sum_), is_continuation(false) { + } + tbb::task* execute() { + tbb::task* next = NULL; + if( !is_continuation ) { + if( root->node_count<1000 ) { + *sum = SerialSumTree(root); + } else { + // Create tasks before spawning any of them. + tbb::task* a = NULL; + tbb::task* b = NULL; + if( root->left ) + a = new( allocate_child() ) OptimizedSumTask(root->left,&x); + if( root->right ) + b = new( allocate_child() ) OptimizedSumTask(root->right,&y); + recycle_as_continuation(); + is_continuation = true; + set_ref_count( (a!=NULL)+(b!=NULL) ); + if( a ) { + if( b ) spawn(*b); + } else + a = b; + next = a; + } + } else { + *sum = root->value; + if( root->left ) *sum += x; + if( root->right ) *sum += y; + } + return next; + } +}; + +Value OptimizedParallelSumTree( TreeNode* root ) { + Value sum; + OptimizedSumTask& a = *new(tbb::task::allocate_root()) OptimizedSumTask(root,&sum); + tbb::task::spawn_root_and_wait(a); + return sum; +} + diff --git a/src/tbb/examples/task/tree_sum/SerialSumTree.cpp b/src/tbb/examples/task/tree_sum/SerialSumTree.cpp new file mode 100644 index 0000000..da6c2b5 --- /dev/null +++ b/src/tbb/examples/task/tree_sum/SerialSumTree.cpp @@ -0,0 +1,38 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "common.h" + +Value SerialSumTree( TreeNode* root ) { + Value result = root->value; + if( root->left ) + result += SerialSumTree(root->left); + if( root->right ) + result += SerialSumTree(root->right); + return result; +} diff --git a/src/tbb/examples/task/tree_sum/SimpleParallelSumTree.cpp b/src/tbb/examples/task/tree_sum/SimpleParallelSumTree.cpp new file mode 100644 index 0000000..a7d68ee --- /dev/null +++ b/src/tbb/examples/task/tree_sum/SimpleParallelSumTree.cpp @@ -0,0 +1,70 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "common.h" +#include "tbb/task.h" + +class SimpleSumTask: public tbb::task { + Value* const sum; + TreeNode* root; +public: + SimpleSumTask( TreeNode* root_, Value* sum_ ) : root(root_), sum(sum_) {} + task* execute() { + if( root->node_count<1000 ) { + *sum = SerialSumTree(root); + } else { + Value x, y; + int count = 1; + tbb::task_list list; + if( root->left ) { + ++count; + list.push_back( *new( allocate_child() ) SimpleSumTask(root->left,&x) ); + } + if( root->right ) { + ++count; + list.push_back( *new( allocate_child() ) SimpleSumTask(root->right,&y) ); + } + // Argument to set_ref_count is one more than size of the list, + // because spawn_and_wait_for_all expects an augmented ref_count. + set_ref_count(count); + spawn_and_wait_for_all(list); + *sum = root->value; + if( root->left ) *sum += x; + if( root->right ) *sum += y; + } + return NULL; + } +}; + +Value SimpleParallelSumTree( TreeNode* root ) { + Value sum; + SimpleSumTask& a = *new(tbb::task::allocate_root()) SimpleSumTask(root,&sum); + tbb::task::spawn_root_and_wait(a); + return sum; +} + diff --git a/src/tbb/examples/task/tree_sum/TreeMaker.h b/src/tbb/examples/task/tree_sum/TreeMaker.h new file mode 100644 index 0000000..90a1cd3 --- /dev/null +++ b/src/tbb/examples/task/tree_sum/TreeMaker.h @@ -0,0 +1,124 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef TREE_MAKER_H_ +#define TREE_MAKER_H_ + +#include "tbb/tick_count.h" +#include "tbb/task.h" + +static double Pi = 3.14159265358979; + +const bool tbbmalloc = true; +const bool stdmalloc = false; + +template +class TreeMaker { + + class SubTreeCreationTask: public tbb::task { + TreeNode*& my_root; + bool is_continuation; + typedef TreeMaker MyTreeMaker; + + public: + SubTreeCreationTask( TreeNode*& root, long number_of_nodes ) : my_root(root), is_continuation(false) { + my_root = MyTreeMaker::allocate_node(); + my_root->node_count = number_of_nodes; + my_root->value = Value(Pi*number_of_nodes); + } + + tbb::task* execute() { + tbb::task* next = NULL; + if( !is_continuation ) { + long subtree_size = my_root->node_count - 1; + if( subtree_size<1000 ) { /* grainsize */ + my_root->left = MyTreeMaker::do_in_one_thread(subtree_size/2); + my_root->right = MyTreeMaker::do_in_one_thread(subtree_size - subtree_size/2); + } else { + // Create tasks before spawning any of them. + tbb::task* a = new( allocate_child() ) SubTreeCreationTask(my_root->left,subtree_size/2); + tbb::task* b = new( allocate_child() ) SubTreeCreationTask(my_root->right,subtree_size - subtree_size/2); + recycle_as_continuation(); + is_continuation = true; + set_ref_count(2); + spawn(*b); + next = a; + } + } + return next; + } + }; + +public: + static TreeNode* allocate_node() { + return use_tbbmalloc? tbb::scalable_allocator().allocate(1) : new TreeNode; + } + + static TreeNode* do_in_one_thread( long number_of_nodes ) { + if( number_of_nodes==0 ) { + return NULL; + } else { + TreeNode* n = allocate_node(); + n->node_count = number_of_nodes; + n->value = Value(Pi*number_of_nodes); + --number_of_nodes; + n->left = do_in_one_thread( number_of_nodes/2 ); + n->right = do_in_one_thread( number_of_nodes - number_of_nodes/2 ); + return n; + } + } + + static TreeNode* do_in_parallel( long number_of_nodes ) { + TreeNode* root_node; + SubTreeCreationTask& a = *new(tbb::task::allocate_root()) SubTreeCreationTask(root_node, number_of_nodes); + tbb::task::spawn_root_and_wait(a); + return root_node; + } + + static TreeNode* create_and_time( long number_of_nodes, bool silent=false ) { + tbb::tick_count t0, t1; + TreeNode* root = allocate_node(); + root->node_count = number_of_nodes; + root->value = Value(Pi*number_of_nodes); + --number_of_nodes; + + t0 = tbb::tick_count::now(); + root->left = do_in_one_thread( number_of_nodes/2 ); + t1 = tbb::tick_count::now(); + if ( !silent ) printf ("%24s: time = %.1f msec\n", "half created serially", (t1-t0).seconds()*1000); + + t0 = tbb::tick_count::now(); + root->right = do_in_parallel( number_of_nodes - number_of_nodes/2 ); + t1 = tbb::tick_count::now(); + if ( !silent ) printf ("%24s: time = %.1f msec\n", "half done in parallel", (t1-t0).seconds()*1000); + + return root; + } +}; + +#endif // TREE_MAKER_H_ diff --git a/src/tbb/examples/task/tree_sum/common.h b/src/tbb/examples/task/tree_sum/common.h new file mode 100644 index 0000000..7191c3b --- /dev/null +++ b/src/tbb/examples/task/tree_sum/common.h @@ -0,0 +1,44 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +typedef float Value; + +struct TreeNode { + //! Pointer to left subtree + TreeNode* left; + //! Pointer to right subtree + TreeNode* right; + //! Number of nodes in this subtree, including this node. + long node_count; + //! Value associated with the node. + Value value; +}; + +Value SerialSumTree( TreeNode* root ); +Value SimpleParallelSumTree( TreeNode* root ); +Value OptimizedParallelSumTree( TreeNode* root ); diff --git a/src/tbb/examples/task/tree_sum/index.html b/src/tbb/examples/task/tree_sum/index.html new file mode 100644 index 0000000..c0c8f15 --- /dev/null +++ b/src/tbb/examples/task/tree_sum/index.html @@ -0,0 +1,76 @@ + + + +

    Overview

    +This directory contains a simple example that sums values in a tree. +The example exhibits some speedup, but not a lot, because it quickly saturates +the system bus on a multiprocessor. For good speedup, there needs to be +more computation cycles per memory reference. The point of the example +is to teach how to use the raw task interface, so the computation is +deliberately trivial. +

    +The performance of this example is better when objects are allocated +by the scalable_allocator instead of +the default "operator new". The reason is that the scalable_allocator typically +packs small objects more tightly than the default "operator new", resulting in +a smaller memory footprint, and thus more efficient use of cache and virtual memory. +In addition, the scalable_allocator performs better for multi-threaded allocations. +

    +

    Files

    +
    +
    SerialSumTree.cpp +
    Sums sequentially. +
    SimpleParallelSumTree.cpp
    +
    Sums in parallel without any fancy tricks. +
    OptimizedParallelSumTree.cpp
    +
    Sums in parallel, using "recycling" and "continuation-passing" tricks. + In this case, it is only slightly faster than the simple version. +
    common.h +
    Shared declarations. +
    main.cpp +
    Main program which parses command line options and runs the algorithm. +
    Makefile +
    Makefile for building example. +
    + +

    Directories

    +
    +
    msvs +
    Contains Microsoft* Visual Studio* 2005 workspace for building and running the + example (Windows* systems only).
    xcode +
    Contains Xcode* IDE workspace for building and running the example (Mac OS* X + systems only).
    + +

    To Build

    +General build directions can be found here. +

    + +

    Usage

    +
    +
    tree_sum -h +
    Prints the help for command line options +
    tree_sum [n-of-threads=value] [number-of-nodes=value] [silent] [stdmalloc] +
    tree_sum [n-of-threads [number-of-nodes]] [silent] [stdmalloc] +
    n-of-threads is the number of threads to use; a range of the form low[:high], where low and optional high are non-negative integers or 'auto' for the default.
    + number-of-nodes is the number of nodes in the tree.
    + silent - no output except elapsed time.
    + stdmalloc - causes the default "operator new" to be used for memory allocations instead of the scalable_allocator.
    + +
    To run a short version of this example, e.g., for use with Intel® Parallel Inspector: +
    Build a debug version of the example + (see the build directions). +
    Run it with a small problem size and the desired number of threads, e.g., tree_sum 4 100000. +
    + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + + diff --git a/src/tbb/examples/task/tree_sum/main.cpp b/src/tbb/examples/task/tree_sum/main.cpp new file mode 100644 index 0000000..92c8fc0 --- /dev/null +++ b/src/tbb/examples/task/tree_sum/main.cpp @@ -0,0 +1,116 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "common.h" + +#include +#include +#include + +// The performance of this example can be significantly better when +// the objects are allocated by the scalable_allocator instead of the +// default "operator new". The reason is that the scalable_allocator +// typically packs small objects more tightly than the default "operator new", +// resulting in a smaller memory footprint, and thus more efficient use of +// cache and virtual memory. Also the scalable_allocator works faster for +// multi-threaded allocations. +// +// Pass stdmalloc as the 1st command line parameter to use the default "operator new" +// and see the performance difference. +#include "tbb/scalable_allocator.h" +#include "TreeMaker.h" +#include "tbb/tick_count.h" +#include "tbb/task_scheduler_init.h" + +#include "../../common/utility/utility.h" + +using namespace std; + +void Run( const char* which, Value(*SumTree)(TreeNode*), TreeNode* root, bool silent) { + tbb::tick_count t0; + if ( !silent ) t0 = tbb::tick_count::now(); + Value result = SumTree(root); + if ( !silent ) printf ("%24s: time = %.1f msec, sum=%g\n", which, (tbb::tick_count::now()-t0).seconds()*1000, result); +} + +int main( int argc, const char *argv[] ) { + try{ + tbb::tick_count mainStartTime = tbb::tick_count::now(); + + // The 1st argument is the function to obtain 'auto' value; the 2nd is the default value + // The example interprets 0 threads as "run serially, then fully subscribed" + utility::thread_number_range threads( tbb::task_scheduler_init::default_num_threads, 0 ); + long number_of_nodes = 10000000; + bool silent = false; + bool use_stdmalloc = false; + + utility::parse_cli_arguments(argc,argv, + utility::cli_argument_pack() + //"-h" option for for displaying help is present implicitly + .positional_arg(threads,"n-of-threads","number of threads to use; a range of the form low[:high], where low and optional high are non-negative integers or 'auto' for the TBB default") + .positional_arg(number_of_nodes,"number-of-nodes","the number of nodes") + .arg(silent,"silent","no output except elapsed time") + .arg(use_stdmalloc,"stdmalloc","use standard allocator") + ); + + TreeNode* root; + { // In this scope, TBB will use default number of threads for tree creation + tbb::task_scheduler_init init; + + if( use_stdmalloc ) { + if ( !silent ) printf("Tree creation using standard operator new\n"); + root = TreeMaker::create_and_time( number_of_nodes, silent ); + } else { + if ( !silent ) printf("Tree creation using TBB scalable allocator\n"); + root = TreeMaker::create_and_time( number_of_nodes, silent ); + } + } + + // Warm up caches + SerialSumTree(root); + if ( !silent ) printf("Calculations:\n"); + if ( threads.first ) { + for(int p = threads.first; p <= threads.last; ++p ) { + if ( !silent ) printf("threads = %d\n", p ); + tbb::task_scheduler_init init( p ); + Run ( "SimpleParallelSumTree", SimpleParallelSumTree, root, silent ); + Run ( "OptimizedParallelSumTree", OptimizedParallelSumTree, root, silent ); + } + } else { // Number of threads wasn't set explicitly. Run serial and two parallel versions + Run ( "SerialSumTree", SerialSumTree, root, silent ); + tbb::task_scheduler_init init; + Run ( "SimpleParallelSumTree", SimpleParallelSumTree, root, silent ); + Run ( "OptimizedParallelSumTree", OptimizedParallelSumTree, root, silent ); + } + utility::report_elapsed_time((tbb::tick_count::now() - mainStartTime).seconds()); + return 0; + }catch(std::exception& e){ + std::cerr<<"error occurred. error text is :\"" < + + + + diff --git a/src/tbb/examples/task/tree_sum/msvs/tree_sum.vcproj b/src/tbb/examples/task/tree_sum/msvs/tree_sum.vcproj new file mode 100644 index 0000000..ffe61c6 --- /dev/null +++ b/src/tbb/examples/task/tree_sum/msvs/tree_sum.vcproj @@ -0,0 +1,376 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/task/tree_sum/msvs/tree_sum_cl.sln b/src/tbb/examples/task/tree_sum/msvs/tree_sum_cl.sln new file mode 100644 index 0000000..66c92d9 --- /dev/null +++ b/src/tbb/examples/task/tree_sum/msvs/tree_sum_cl.sln @@ -0,0 +1,25 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tree_sum", "tree_sum.vcproj", "{C931C7A2-074E-4150-9E7A-39A03250411E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|Win32.ActiveCfg = Debug|Win32 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|Win32.Build.0 = Debug|Win32 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|x64.ActiveCfg = Debug|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|x64.Build.0 = Debug|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|Win32.ActiveCfg = Release|Win32 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|Win32.Build.0 = Release|Win32 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|x64.ActiveCfg = Release|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/task/tree_sum/msvs/tree_sum_icl.sln b/src/tbb/examples/task/tree_sum/msvs/tree_sum_icl.sln new file mode 100644 index 0000000..7d25cdc --- /dev/null +++ b/src/tbb/examples/task/tree_sum/msvs/tree_sum_icl.sln @@ -0,0 +1,33 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "tree_sum", "tree_sum.icproj", "{CB292CD9-903E-464C-AAFE-E7A49003565C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Debug|Win32.Build.0 = Debug|Win32 + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Debug|x64.ActiveCfg = Debug|x64 + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Debug|x64.Build.0 = Debug|x64 + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Release|Win32.ActiveCfg = Release|Win32 + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Release|Win32.Build.0 = Release|Win32 + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Release|x64.ActiveCfg = Release|x64 + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Release|x64.Build.0 = Release|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|x64.Build.0 = Release|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|x64.ActiveCfg = Release|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|Win32.Build.0 = Release|Win32 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|Win32.ActiveCfg = Release|Win32 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|x64.Build.0 = Debug|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|x64.ActiveCfg = Debug|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|Win32.Build.0 = Debug|Win32 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|Win32.ActiveCfg = Debug|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/task/tree_sum/xcode/tree_sum.xcodeproj/project.pbxproj b/src/tbb/examples/task/tree_sum/xcode/tree_sum.xcodeproj/project.pbxproj new file mode 100644 index 0000000..02843a4 --- /dev/null +++ b/src/tbb/examples/task/tree_sum/xcode/tree_sum.xcodeproj/project.pbxproj @@ -0,0 +1,325 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 05593A110B8F4F4500DE73AB /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05593A0C0B8F4F4500DE73AB /* main.cpp */; }; + 05593A120B8F4F4500DE73AB /* OptimizedParallelSumTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05593A0D0B8F4F4500DE73AB /* OptimizedParallelSumTree.cpp */; }; + 05593A130B8F4F4500DE73AB /* SerialSumTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05593A0E0B8F4F4500DE73AB /* SerialSumTree.cpp */; }; + 05593A140B8F4F4500DE73AB /* SimpleParallelSumTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05593A0F0B8F4F4500DE73AB /* SimpleParallelSumTree.cpp */; }; + 05593A160B8F4F5D00DE73AB /* libtbbmalloc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 05593A150B8F4F5D00DE73AB /* libtbbmalloc.dylib */; }; + 05593A170B8F4F6E00DE73AB /* libtbbmalloc.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 05593A150B8F4F5D00DE73AB /* libtbbmalloc.dylib */; }; + A1F593B70B8F06F900073279 /* libtbb.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; + A1F593BB0B8F072500073279 /* libtbb.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8DD76F690486A84900D96B5E /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = ""; + dstSubfolderSpec = 16; + files = ( + A1F593BB0B8F072500073279 /* libtbb.dylib in CopyFiles */, + 05593A170B8F4F6E00DE73AB /* libtbbmalloc.dylib in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 05593A0B0B8F4F4500DE73AB /* common.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = common.h; path = ../common.h; sourceTree = SOURCE_ROOT; }; + 05593A0C0B8F4F4500DE73AB /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = ../main.cpp; sourceTree = SOURCE_ROOT; }; + 05593A0D0B8F4F4500DE73AB /* OptimizedParallelSumTree.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = OptimizedParallelSumTree.cpp; path = ../OptimizedParallelSumTree.cpp; sourceTree = SOURCE_ROOT; }; + 05593A0E0B8F4F4500DE73AB /* SerialSumTree.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SerialSumTree.cpp; path = ../SerialSumTree.cpp; sourceTree = SOURCE_ROOT; }; + 05593A0F0B8F4F4500DE73AB /* SimpleParallelSumTree.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SimpleParallelSumTree.cpp; path = ../SimpleParallelSumTree.cpp; sourceTree = SOURCE_ROOT; }; + 05593A150B8F4F5D00DE73AB /* libtbbmalloc.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtbbmalloc.dylib; path = ../../../../lib/libtbbmalloc.dylib; sourceTree = SOURCE_ROOT; }; + 05593A4A0B8F51E000DE73AB /* tree_sum */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tree_sum; sourceTree = BUILT_PRODUCTS_DIR; }; + A1F593B30B8F06F900073279 /* libtbb.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtbb.dylib; path = ../../../../lib/libtbb.dylib; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8DD76F660486A84900D96B5E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A1F593B70B8F06F900073279 /* libtbb.dylib in Frameworks */, + 05593A160B8F4F5D00DE73AB /* libtbbmalloc.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* tree_sum */ = { + isa = PBXGroup; + children = ( + 08FB7795FE84155DC02AAC07 /* Source */, + A1F593B20B8F06F900073279 /* External Frameworks and Libraries */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + ); + name = tree_sum; + sourceTree = ""; + }; + 08FB7795FE84155DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + 05593A0B0B8F4F4500DE73AB /* common.h */, + 05593A0C0B8F4F4500DE73AB /* main.cpp */, + 05593A0D0B8F4F4500DE73AB /* OptimizedParallelSumTree.cpp */, + 05593A0E0B8F4F4500DE73AB /* SerialSumTree.cpp */, + 05593A0F0B8F4F4500DE73AB /* SimpleParallelSumTree.cpp */, + ); + name = Source; + sourceTree = ""; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 05593A4A0B8F51E000DE73AB /* tree_sum */, + ); + name = Products; + sourceTree = ""; + }; + A1F593B20B8F06F900073279 /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + 05593A150B8F4F5D00DE73AB /* libtbbmalloc.dylib */, + A1F593B30B8F06F900073279 /* libtbb.dylib */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8DD76F620486A84900D96B5E /* tree_sum */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "tree_sum" */; + buildPhases = ( + 8DD76F640486A84900D96B5E /* Sources */, + 8DD76F660486A84900D96B5E /* Frameworks */, + 8DD76F690486A84900D96B5E /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = tree_sum; + productInstallPath = "$(HOME)/bin"; + productName = tree_sum; + productReference = 05593A4A0B8F51E000DE73AB /* tree_sum */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0410; + }; + buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "tree_sum" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 08FB7794FE84155DC02AAC07 /* tree_sum */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DD76F620486A84900D96B5E /* tree_sum */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 8DD76F640486A84900D96B5E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 05593A110B8F4F4500DE73AB /* main.cpp in Sources */, + 05593A120B8F4F4500DE73AB /* OptimizedParallelSumTree.cpp in Sources */, + 05593A130B8F4F4500DE73AB /* SerialSumTree.cpp in Sources */, + 05593A140B8F4F4500DE73AB /* SimpleParallelSumTree.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1DEB923208733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = tree_sum; + ZERO_LINK = NO; + }; + name = Debug; + }; + 1DEB923308733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = tree_sum; + ZERO_LINK = NO; + }; + name = Release; + }; + 1DEB923608733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Debug; + }; + 1DEB923708733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Release; + }; + A1F593C60B8F0E6E00073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = tree_sum; + ZERO_LINK = NO; + }; + name = Debug64; + }; + A1F593C70B8F0E6E00073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = tree_sum; + ZERO_LINK = NO; + }; + name = Release64; + }; + A1F593C80B8F0E6E00073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-m64", + ); + OTHER_LDFLAGS = "-m64"; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Debug64; + }; + A1F593C90B8F0E6E00073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-m64", + ); + OTHER_LDFLAGS = "-m64"; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Release64; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "tree_sum" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923208733DC60010E9CD /* Debug */, + A1F593C60B8F0E6E00073279 /* Debug64 */, + 1DEB923308733DC60010E9CD /* Release */, + A1F593C70B8F0E6E00073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "tree_sum" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923608733DC60010E9CD /* Debug */, + A1F593C80B8F0E6E00073279 /* Debug64 */, + 1DEB923708733DC60010E9CD /* Release */, + A1F593C90B8F0E6E00073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/src/tbb/examples/task_group/index.html b/src/tbb/examples/task_group/index.html new file mode 100644 index 0000000..9a93ddb --- /dev/null +++ b/src/tbb/examples/task_group/index.html @@ -0,0 +1,23 @@ + + + +

    Overview

    +This directory has examples of how to use task_groups. + +

    Directories

    +
    +
    Sudoku +
    Compute all solutions for a Sudoku board. +
    + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + diff --git a/src/tbb/examples/task_group/sudoku/Makefile b/src/tbb/examples/task_group/sudoku/Makefile new file mode 100644 index 0000000..12702a7 --- /dev/null +++ b/src/tbb/examples/task_group/sudoku/Makefile @@ -0,0 +1,72 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# GNU Makefile that builds and runs example. +PROG=sudoku +ARGS=4 input1 verbose +PERF_RUN_ARGS=auto input1 silent + +# The C++ compiler +ifneq (,$(shell which icc 2>/dev/null)) +CXX=icc +endif # which icc + +ifeq ($(offload), mic) +override CXXFLAGS += -D__TBB_MIC=1 +endif + +ifeq ($(CXX), icc) +TBBLIB = -tbb +TBBLIB_DEBUG = -tbb +CXX0XFLAGS?=-std=c++0x -D_TBB_CPP0X +else +TBBLIB = -ltbb +TBBLIB_DEBUG = -ltbb_debug +endif + +ifeq ($(shell uname), Linux) +LIBS+= -lrt +endif + +all: release test + +release: *.cpp + $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ $(TBBLIB) $(LIBS) $(CXX0XFLAGS) + +debug: *.cpp + $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ $(TBBLIB_DEBUG) $(LIBS) $(CXX0XFLAGS) + +clean: + $(RM) $(PROG) *.o *.d + +test: + ./$(PROG) $(ARGS) + +perf_build: release + +perf_run: + ./$(PROG) $(PERF_RUN_ARGS) + diff --git a/src/tbb/examples/task_group/sudoku/Makefile.windows b/src/tbb/examples/task_group/sudoku/Makefile.windows new file mode 100644 index 0000000..b525cdc --- /dev/null +++ b/src/tbb/examples/task_group/sudoku/Makefile.windows @@ -0,0 +1,58 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Common Makefile that builds and runs example. + +# Just specify your program basename +PROG=sudoku +ARGS= 4 input1 verbose +PERF_RUN_ARGS=auto input1 silent + +# Trying to find if icl.exe is set +CXX1 = $(TBB_CXX)- +CXX2 = $(CXX1:icl.exe-=icl.exe) +CXX = $(CXX2:-=cl.exe) + +# The C++ compiler options +MYCXXFLAGS = /TP /EHsc /W3 /nologo /D _CONSOLE /D _MBCS /D WIN32 /D _CRT_SECURE_NO_DEPRECATE $(CXXFLAGS) +MYLDFLAGS =/INCREMENTAL:NO /NOLOGO /DEBUG /FIXED:NO $(LDFLAGS) + +all: release test +release: + $(CXX) *.cpp /MD /O2 /D NDEBUG $(MYCXXFLAGS) /link tbb.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +debug: + $(CXX) *.cpp /MDd /Od /Zi /D TBB_USE_DEBUG /D _DEBUG $(MYCXXFLAGS) /link tbb_debug.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +clean: + @cmd.exe /C del $(PROG).exe *.obj *.?db *.manifest +test: + $(PROG) $(ARGS) +compiler_check: + @$(CXX) >nul 2>&1 || echo "$(CXX) command not found. Check if CXX=$(CXX) is set properly" + +perf_build: release + +perf_run: + $(PROG) $(PERF_RUN_ARGS) diff --git a/src/tbb/examples/task_group/sudoku/index.html b/src/tbb/examples/task_group/sudoku/index.html new file mode 100644 index 0000000..dca0111 --- /dev/null +++ b/src/tbb/examples/task_group/sudoku/index.html @@ -0,0 +1,76 @@ + + + +

    Overview

    +
    +
    This directory contains a simple example that finds all solutions to a +Sudoku board. It uses a straightforward state-space search algorithm +that exhibits OR-parallelism. It can be optionally run until it +obtains just the first solution. The point of the example is to teach +how to use the task_group interface. +
    The example can be built in the offload version to run on Intel® Many Integrated Core (Intel® MIC) Architecture based coprocessor (see build instructions). +
    + +

    Files

    +
    +
    sudoku.cpp +
    Driver. +
    input1 +
    Sample input file with modest number of solutions. + +
    input2 +
    Sample input file with small number of solutions. + +
    input3 +
    Sample input file with larger number of solutions. + +
    input4 +
    Sample input file with very large number of solutions. + +
    Makefile +
    Makefile for building example. + +
    + +

    Directories

    +
    +
    msvs +
    Contains Microsoft* Visual Studio* 2008 workspace for building and running the example with the Intel® C++ compiler (Windows* systems only). +
    xcode +
    Contains Xcode* IDE workspace for building and running the example (Mac OS* X systems only). +
    + +

    To Build

    +General build directions can be found here. +

    + +

    Usage

    +
    + +
    sudoku -h +
    Prints the help for command line options +
    sudoku [n-of-threads=value] [filename=value] [verbose] [silent] [find-one] +
    sudoku [n-of-threads [filename]] [verbose] [silent] [find-one] +
    n-of-threads is the number of threads to use; a range of the form low[:high], where low and optional high are non-negative integers or 'auto' for the TBB default.
    + filename is an input filename.
    + verbose - prints the first solution.
    + silent - no output except elapsed time.
    + find-one - stops after finding first solution.
    + +
    To run a short version of this example, e.g., for use with Intel® Parallel Inspector: +
    Build a debug version of the example + (see the build directions). +
    Run it with a small problem size and the desired number of threads, e.g., sudoku 4 input2. +
    + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + diff --git a/src/tbb/examples/task_group/sudoku/input1 b/src/tbb/examples/task_group/sudoku/input1 new file mode 100644 index 0000000..6591752 --- /dev/null +++ b/src/tbb/examples/task_group/sudoku/input1 @@ -0,0 +1,19 @@ +1 0 0 9 0 0 0 8 0 0 8 0 2 0 0 0 0 0 0 0 5 0 0 0 7 0 0 0 5 2 1 0 0 4 0 0 0 0 0 0 0 5 0 0 7 4 0 0 7 0 0 0 3 0 0 3 0 0 0 2 0 0 5 0 0 0 0 0 0 1 0 0 5 0 0 0 1 0 0 0 0 + + + + + + + +1 0 0 9 0 0 0 8 0 +0 8 0 2 0 0 0 0 0 +0 0 5 0 0 0 7 0 0 + +0 5 2 1 0 0 4 0 0 +0 0 0 0 0 5 0 0 7 +4 0 0 7 0 0 0 3 0 + +0 3 0 0 0 2 0 0 5 +0 0 0 0 0 0 1 0 0 +5 0 0 0 1 0 0 0 0 diff --git a/src/tbb/examples/task_group/sudoku/input2 b/src/tbb/examples/task_group/sudoku/input2 new file mode 100644 index 0000000..4951425 --- /dev/null +++ b/src/tbb/examples/task_group/sudoku/input2 @@ -0,0 +1,18 @@ +2 0 1 0 0 0 0 8 0 0 8 0 2 1 9 6 0 0 0 0 5 0 0 0 7 0 0 0 5 2 1 0 0 4 0 0 0 0 0 0 0 5 0 0 7 4 0 0 7 0 0 0 3 0 0 3 0 0 0 2 0 0 5 0 0 0 0 3 0 1 0 0 5 0 0 0 8 0 0 0 6 + + + + + + +2 0 1 0 0 0 0 8 0 +0 8 0 2 1 9 6 0 0 +0 0 5 0 0 0 7 0 0 + +0 5 2 1 0 0 4 0 0 +0 0 0 0 0 5 0 0 7 +4 0 0 7 0 0 0 3 0 + +0 3 0 0 0 2 0 0 5 +0 0 0 0 3 0 1 0 0 +5 0 0 0 8 0 0 0 6 diff --git a/src/tbb/examples/task_group/sudoku/input3 b/src/tbb/examples/task_group/sudoku/input3 new file mode 100644 index 0000000..e6cbb09 --- /dev/null +++ b/src/tbb/examples/task_group/sudoku/input3 @@ -0,0 +1,19 @@ +1 0 0 9 0 0 0 8 0 0 0 0 2 0 0 0 0 0 0 0 5 0 0 0 7 0 0 0 5 2 6 0 0 4 0 0 0 0 0 0 0 5 0 0 7 4 0 0 7 0 0 0 3 0 0 3 0 0 0 2 0 0 5 0 0 0 0 0 0 1 0 0 5 0 0 0 1 0 0 0 0 + + + + + + + +1 0 0 9 0 0 0 8 0 +0 0 0 2 0 0 0 0 0 +0 0 5 0 0 0 7 0 0 + +0 5 2 6 0 0 4 0 0 +0 0 0 0 0 5 0 0 7 +4 0 0 7 0 0 0 3 0 + +0 3 0 0 0 2 0 0 5 +0 0 0 0 0 0 1 0 0 +5 0 0 0 1 0 0 0 0 diff --git a/src/tbb/examples/task_group/sudoku/input4 b/src/tbb/examples/task_group/sudoku/input4 new file mode 100644 index 0000000..9436cd7 --- /dev/null +++ b/src/tbb/examples/task_group/sudoku/input4 @@ -0,0 +1,19 @@ +1 0 0 9 0 0 0 8 0 0 0 0 2 0 0 0 0 0 0 0 5 0 0 0 7 0 0 0 0 2 6 0 0 0 0 0 0 0 0 0 0 5 0 0 7 4 0 0 0 0 0 0 3 0 0 3 0 0 0 2 0 0 5 0 0 0 0 0 0 1 0 0 5 0 0 0 1 0 0 0 0 + + + + + + + +1 0 0 9 0 0 0 8 0 +0 0 0 2 0 0 0 0 0 +0 0 5 0 0 0 7 0 0 + +0 0 2 6 0 0 0 0 0 +0 0 0 0 0 5 0 0 7 +4 0 0 0 0 0 0 3 0 + +0 3 0 0 0 2 0 0 5 +0 0 0 0 0 0 1 0 0 +5 0 0 0 1 0 0 0 0 diff --git a/src/tbb/examples/task_group/sudoku/msvs/sudoku.icproj b/src/tbb/examples/task_group/sudoku/msvs/sudoku.icproj new file mode 100644 index 0000000..d95f8b2 --- /dev/null +++ b/src/tbb/examples/task_group/sudoku/msvs/sudoku.icproj @@ -0,0 +1,11 @@ + + + + + diff --git a/src/tbb/examples/task_group/sudoku/msvs/sudoku.vcproj b/src/tbb/examples/task_group/sudoku/msvs/sudoku.vcproj new file mode 100644 index 0000000..a84ca15 --- /dev/null +++ b/src/tbb/examples/task_group/sudoku/msvs/sudoku.vcproj @@ -0,0 +1,356 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/task_group/sudoku/msvs/sudoku_cl.sln b/src/tbb/examples/task_group/sudoku/msvs/sudoku_cl.sln new file mode 100644 index 0000000..176854b --- /dev/null +++ b/src/tbb/examples/task_group/sudoku/msvs/sudoku_cl.sln @@ -0,0 +1,25 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sudoku", "sudoku.vcproj", "{C931C7A2-074E-4150-9E7A-39A03250411E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|Win32.ActiveCfg = Debug|Win32 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|Win32.Build.0 = Debug|Win32 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|x64.ActiveCfg = Debug|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|x64.Build.0 = Debug|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|Win32.ActiveCfg = Release|Win32 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|Win32.Build.0 = Release|Win32 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|x64.ActiveCfg = Release|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/task_group/sudoku/msvs/sudoku_icl.sln b/src/tbb/examples/task_group/sudoku/msvs/sudoku_icl.sln new file mode 100644 index 0000000..70d124d --- /dev/null +++ b/src/tbb/examples/task_group/sudoku/msvs/sudoku_icl.sln @@ -0,0 +1,33 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "sudoku", "sudoku.icproj", "{CB292CD9-903E-464C-AAFE-E7A49003565C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Debug|Win32.ActiveCfg = Debug|Win32 + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Debug|Win32.Build.0 = Debug|Win32 + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Debug|x64.ActiveCfg = Debug|x64 + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Debug|x64.Build.0 = Debug|x64 + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Release|Win32.ActiveCfg = Release|Win32 + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Release|Win32.Build.0 = Release|Win32 + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Release|x64.ActiveCfg = Release|x64 + {CB292CD9-903E-464C-AAFE-E7A49003565C}.Release|x64.Build.0 = Release|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|x64.Build.0 = Release|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|x64.ActiveCfg = Release|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|Win32.Build.0 = Release|Win32 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Release|Win32.ActiveCfg = Release|Win32 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|x64.Build.0 = Debug|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|x64.ActiveCfg = Debug|x64 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|Win32.Build.0 = Debug|Win32 + {C931C7A2-074E-4150-9E7A-39A03250411E}.Debug|Win32.ActiveCfg = Debug|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/task_group/sudoku/sudoku.cpp b/src/tbb/examples/task_group/sudoku/sudoku.cpp new file mode 100644 index 0000000..d241b80 --- /dev/null +++ b/src/tbb/examples/task_group/sudoku/sudoku.cpp @@ -0,0 +1,353 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if __TBB_MIC +#pragma offload_attribute (push,target(mic)) +#endif // __TBB_MIC + +#include +#include +#include +#include "tbb/atomic.h" +#include "tbb/tick_count.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/task_group.h" + +#if __INTEL_COMPILER +// Suppress "std::auto_prt<> is deprecated" warning +// TODO: replace auto_ptr with unique_ptr for compilers supporting C++11 +#pragma warning(disable: 1478) +#endif +#include "../../common/utility/utility.h" + +#pragma warning(disable: 4996) + +#if __INTEL_COMPILER +#define __TBB_LAMBDAS_PRESENT ( _TBB_CPP0X && __INTEL_COMPILER > 1100 ) +#elif __GNUC__ +#define __TBB_LAMBDAS_PRESENT ( _TBB_CPP0X && __TBB_GCC_VERSION >= 40500 ) +#elif _MSC_VER +#define __TBB_LAMBDAS_PRESENT ( _MSC_VER>=1600 ) +#endif + +const unsigned BOARD_SIZE=81; +const unsigned BOARD_DIM=9; + +using namespace tbb; +using namespace std; + +atomic nSols; +bool find_one = false; +bool verbose = false; +unsigned short init_values[BOARD_SIZE] = {1,0,0,9,0,0,0,8,0,0,8,0,2,0,0,0,0,0,0,0,5,0,0,0,7,0,0,0,5,2,1,0,0,4,0,0,0,0,0,0,0,5,0,0,7,4,0,0,7,0,0,0,3,0,0,3,0,0,0,2,0,0,5,0,0,0,0,0,0,1,0,0,5,0,0,0,1,0,0,0,0}; +task_group *g; +double solve_time; + +typedef struct { + unsigned short solved_element; + unsigned potential_set; +} board_element; + +void read_board(const char *filename) { + FILE *fp; + int input; + fp = fopen(filename, "r"); + if (!fp) { + fprintf(stderr, "sudoku: Could not open input file '%s'.\n", filename); + exit(1); + } + for (unsigned i=0; i=0; --i) + if (b[i].solved_element==0) return false; + return true; +} + +bool in_row(board_element *b, unsigned row, unsigned col, unsigned short p) { + for (unsigned c=0; ccancel(); + if (++nSols==1 && verbose) { + print_board(b); + } + free(b); + return; + } + calculate_potentials(b); + bool progress=true; + bool success = examine_potentials(b, &progress); + if (success && progress) { + partial_solve(b, first_potential_set); + } else if (success && !progress) { + board_element *new_board; + while (b[first_potential_set].solved_element!=0) ++first_potential_set; + for (unsigned short potential=1; potential<=BOARD_DIM; ++potential) { + if (1<<(potential-1) & b[first_potential_set].potential_set) { + new_board = (board_element *)malloc(BOARD_SIZE*sizeof(board_element)); + copy_board(b, new_board); + new_board[first_potential_set].solved_element = potential; +#if __TBB_LAMBDAS_PRESENT + g->run( [=]{ partial_solve(new_board, first_potential_set); } ); +#else + g->run(PartialSolveBoard(new_board, first_potential_set)); +#endif + } + } + free(b); + } + else { + free(b); + } +} + +unsigned solve(int p) { + task_scheduler_init init(p); + nSols = 0; + board_element *start_board = (board_element *)malloc(BOARD_SIZE*sizeof(board_element)); + init_board(start_board, init_values); + g = new task_group; + tick_count t0 = tick_count::now(); + partial_solve(start_board, 0); + g->wait(); + solve_time = (tick_count::now() - t0).seconds(); + delete g; + return nSols; +} + +#if __TBB_MIC +#pragma offload_attribute (pop) +#endif // __TBB_MIC + +int do_get_default_num_threads() { + int threads; + #if __TBB_MIC + #pragma offload target(mic) out(threads) + #endif // __TBB_MIC + threads = tbb::task_scheduler_init::default_num_threads(); + return threads; +} + +int get_default_num_threads() { + static int threads = do_get_default_num_threads(); + return threads; +} + +int main(int argc, char *argv[]) { + try { + tbb::tick_count mainStartTime = tbb::tick_count::now(); + + utility::thread_number_range threads(get_default_num_threads); + string filename = ""; + bool silent = false; + + utility::parse_cli_arguments(argc,argv, + utility::cli_argument_pack() + //"-h" option for for displaying help is present implicitly + .positional_arg(threads,"n-of-threads","number of threads to use; a range of the form low[:high], where low and optional high are non-negative integers or 'auto' for the TBB default.") + .positional_arg(filename,"filename","input filename") + + .arg(verbose,"verbose","prints the first solution") + .arg(silent,"silent","no output except elapsed time") + .arg(find_one,"find-one","stops after finding first solution\n") + ); + + if ( silent ) verbose = false; + + if ( !filename.empty() ) + read_board( filename.c_str() ); + // otherwise (if file name not specified), the default statically initialized board will be used. + for(int p = threads.first; p <= threads.last; ++p ) { + unsigned number; + #if __TBB_MIC + #pragma offload target(mic) in(init_values, p, verbose, find_one) out(number, solve_time) + { + #endif // __TBB_MIC + number = solve(p); + #if __TBB_MIC + } + #endif // __TBB_MIC + + if ( !silent ) { + if ( find_one ) { + printf("Sudoku: Time to find first solution on %d threads: %6.6f seconds.\n", p, solve_time); + } + else { + printf("Sudoku: Time to find all %u solutions on %d threads: %6.6f seconds.\n", number, p, solve_time); + } + } + } + + utility::report_elapsed_time((tbb::tick_count::now() - mainStartTime).seconds()); + + return 0; + } catch(std::exception& e) { + std::cerr<<"error occurred. error text is :\"" </dev/null)) +CXX=icc +endif # icc + +ifeq ($(shell uname), Linux) +LIBS+= -lrt +endif + +include ../../common/gui/Makefile.gmake + +SOURCES= ../../common/gui/$(UI)video.cpp fractal.cpp main.cpp + +override CXXFLAGS += $(UI_CXXFLAGS) + +all: release test + +resources: +ifeq ($(UI),mac) + mkdir -p $(APPRES)/en.lproj $(NAME).app/Contents/MacOS + cp ../../common/gui/xcode/tbbExample/Info.plist $(NAME).app/Contents + cp ../../common/gui/xcode/tbbExample/PkgInfo $(NAME).app/Contents + cp ../../common/gui/xcode/tbbExample/en.lproj/* $(APPRES)/en.lproj +endif # Mac + +release: $(SOURCES) resources +ifeq ($(UI),mac) + $(CXX_UI) -O2 -DNDEBUG $(CXXFLAGS) -c $(MACUISOURCES) +endif # Mac + $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(EXE) $(SOURCES) $(MACUIOBJS) -ltbb $(LIBS) + +debug: resources +ifeq ($(UI),mac) + $(CXX_UI) -g -O0 -DTBB_USE_DEBUG $(CXXFLAGS) -c $(MACUISOURCES) +endif # Mac + $(CXX) -g -O0 -DTBB_USE_DEBUG $(CXXFLAGS) -o $(EXE) $(SOURCES) $(MACUIOBJS) -ltbb_debug $(LIBS) + +clean: + $(RM) $(EXE) *.o *.d +ifeq ($(UI),mac) + rm -rf $(NAME).app +endif + +test: +ifeq ($(UI),mac) + export DYLD_LIBRARY_PATH="$(DYLD_LIBRARY_PATH):$(TBBLIBSPATH)"; ./$(EXE) $(ARGS) +else + ./$(EXE) $(ARGS) +endif + +light_test: +ifeq ($(UI),mac) + export DYLD_LIBRARY_PATH="$(DYLD_LIBRARY_PATH):$(TBBLIBSPATH)"; ./$(EXE) $(LIGHT_ARGS) +else + ./$(EXE) $(LIGHT_ARGS) +endif + +perf_build: release + +perf_run: + ./$(EXE) $(PERF_RUN_ARGS) diff --git a/src/tbb/examples/task_priority/fractal/Makefile.windows b/src/tbb/examples/task_priority/fractal/Makefile.windows new file mode 100644 index 0000000..7d9a00b --- /dev/null +++ b/src/tbb/examples/task_priority/fractal/Makefile.windows @@ -0,0 +1,74 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Common Makefile that builds and runs example. + +# Just specify your program basename +PROG=Fractal +ARGS=auto +PERF_RUN_ARGS=auto 1 1000000 silent +LIGHT_ARGS=auto 1 1000 + +# Trying to find if icl.exe is set +CXX1 = $(TBB_CXX)- +CXX2 = $(CXX1:icl.exe-=icl.exe) +CXX = $(CXX2:-=cl.exe) +# Uncomment one of next lines to choose user interface type (console, gdiplus, direct draw) +#UI = con +UI = gdi +#UI = dd + +# Machine architecture, auto-detected from TBB_TARGET_ARCH by default +# Use XARCH variable to change it. See index.html for more information +ARCH0 = $(TBB_TARGET_ARCH)- +ARCH1 = $(ARCH0:ia32-=x86) +ARCH2 = $(ARCH1:intel64-=AMD64) +XARCH = $(ARCH2:-=x86) + +MAKEINC = ../../common/gui/Makefile.win +SOURCES = fractal.cpp main.cpp + +all: release test +release: compiler_check + @$(MAKE) -f $(MAKEINC) UI=$(UI) CXX="$(CXX)" CXXFLAGS="$(CXXFLAGS)" LFLAGS="$(LDFLAGS) tbb.lib $(LIBS)" XARCH=$(XARCH) RCNAME=gui SOURCE="$(SOURCES)" EXE=$(PROG).exe build_one +debug: compiler_check + @$(MAKE) -f $(MAKEINC) UI=$(UI) DEBUG=_debug CXX="$(CXX)" CXXFLAGS="$(CXXFLAGS) /D TBB_USE_DEBUG" LFLAGS="$(LDFLAGS) tbb_debug.lib $(LIBS)" XARCH=$(XARCH) RCNAME=gui SOURCE="$(SOURCES)" EXE=$(PROG).exe build_one +clean: + @cmd.exe /C del $(PROG).exe *.obj *.?db *.manifest msvs\gui.res +test: + $(PROG) $(ARGS) +light_test: + $(PROG) $(LIGHT_ARGS) + +perf_build: compiler_check + @$(MAKE) -f $(MAKEINC) UI=con CXX="$(CXX)" CXXFLAGS="$(CXXFLAGS)" LFLAGS="$(LDFLAGS) tbb.lib $(LIBS)" XARCH=$(XARCH) RCNAME=gui SOURCE="$(SOURCES) " EXE=$(PROG).exe build_one +perf_run: + $(PROG) $(PERF_RUN_ARGS) + +compiler_check: + @echo compiler_test>compiler_test && @$(CXX) /E compiler_test >nul 2>&1 || echo "$(CXX) command not found. Check if CXX=$(CXX) is set properly" + @cmd.exe /C del compiler_test + diff --git a/src/tbb/examples/task_priority/fractal/fractal.cpp b/src/tbb/examples/task_priority/fractal/fractal.cpp new file mode 100644 index 0000000..518ce56 --- /dev/null +++ b/src/tbb/examples/task_priority/fractal/fractal.cpp @@ -0,0 +1,277 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "fractal.h" + +#include "tbb/compat/thread" +#include "tbb/parallel_for.h" +#include "tbb/blocked_range2d.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/tick_count.h" + +#include +#include + +video *v; +extern bool silent; +extern bool schedule_auto; +extern int grain_size; + +color_t fractal::calc_one_pixel(int x0, int y0) { + int iter; + double fx0, fy0, xtemp, x, y, mu; + + color_t color; + + fx0 = (double)x0 - (double) size_x / 2.0; + fy0 = (double)y0 - (double) size_y / 2.0; + fx0 = fx0 / magn + cx; + fy0 = fy0 / magn + cy; + + iter = 0; x = 0; y = 0; + + while (((x*x + y*y) <= 4) && (iter < max_iterations)) { + xtemp = x*x - y*y + fx0; + y = 2*x*y + fy0; + x = xtemp; + iter++; + } + + if (iter == max_iterations) { + // point corresponds to the mandelbrot set + color = v->get_color(255, 255, 255); + return color; + } + + // compute again but with exponent calculation at each iteration + // it's all for coloring point outside the mandelbrot set + iter = 0; x = 0; y = 0; + mu = 0; + while (((x*x + y*y) <= 4) && (iter < max_iterations)) { + xtemp = x*x - y*y + fx0; + y = 2*x*y + fy0; + x = xtemp; + mu += exp(-sqrt(x*x+y*y)); + iter++; + } + + int b = (int)(256*mu); + int g = (b/8); + int r = (g/16); + + b = b>255 ? 255 : b; + g = g>255 ? 255 : g; + r = r>255 ? 255 : r; + + color = v->get_color(r, g, b); + return color; +} + +void fractal::clear() { + drawing_area area( off_x, off_y, size_x, size_y, dm) ; + + // fill the rendering area with black color + for (int y=0; yget_color(0, 0, 0) ); + } + } +} + +void fractal::draw_border( bool is_active ) { + color_t color = is_active ? v->get_color(0, 255, 0) // green color + : v->get_color(96, 128, 96); // green-gray color + + // top border + drawing_area area0( off_x-1, off_y-1, size_x+2, 1, dm ); + for (int i=-1; i &r ) const { + if ( v->next_frame() ) + f.render_rect( r.cols().begin(), r.rows().begin(), r.cols().end(), r.rows().end() ); + } + + fractal_body( fractal &f ) : f(f) { + } +}; + +void fractal::render( tbb::task_group_context &context ) { + // run parallel_for that process the fractal area + if( schedule_auto ) + tbb::parallel_for( tbb::blocked_range2d(0, size_y, grain_size, 0, size_x, grain_size ), + fractal_body(*this), tbb::auto_partitioner(), context); + else + tbb::parallel_for( tbb::blocked_range2d(0, size_y, grain_size, 0, size_x, grain_size ), + fractal_body(*this), tbb::simple_partitioner(), context); +} + +void fractal::run( tbb::task_group_context &context ) { + clear(); + render( context ); +} + +bool fractal::check_point( int x, int y ) { + return x >= off_x && x <= off_x+size_x && + y >= off_y && y <= off_y+size_y; +} + +void fractal_group::calc_fractal( int num ) { + // calculate the fractal + fractal &f = num ? f1 : f0; + + tbb::tick_count t0 = tbb::tick_count::now(); + while ( v->next_frame() && num_frames[num] != 0 ) { + f.run( context[num] ); + if ( num_frames[num]>0 ) num_frames[num] -= 1; + } + tbb::tick_count t1 = tbb::tick_count::now(); + + if ( !silent ) { + printf(" %s fractal finished. Time: %g\n", num ? "Second" : "First", (t1-t0).seconds()); + } +} + +void fg_thread_func(fractal_group *fg) { + // initialize the task scheduler for the second thread + tbb::task_scheduler_init init( fg->get_num_threads() ); + // calculate the second fractal + fg->calc_fractal( 1 ); +} + +void fractal_group::set_priorities() { + // set the high priority for the active area and the normal priority for another area + context[active].set_priority( tbb::priority_high ); + context[active^1].set_priority( tbb::priority_normal ); +} + +void fractal_group::switch_priorities( int new_active ) { + if( new_active!=-1 ) active = new_active; + else active = 1-active; // assumes 'active' is only 0 or 1 + set_priorities(); + draw_borders(); +} + +void fractal_group::set_num_frames_at_least(int n) { + if ( num_frames[0]join(); + delete fg_thread; + } + + delete[] context; +} + +void fractal_group::draw_borders() { + f0.draw_border( active==0 ); + f1.draw_border( active==1 ); +} + +fractal_group::fractal_group( const drawing_memory &_dm, int _num_threads, int _max_iterations, int _num_frames ) : f0(_dm), f1(_dm), num_threads(_num_threads) { + // set rendering areas + f0.size_x = f1.size_x = _dm.sizex/2-4; + f0.size_y = f1.size_y = _dm.sizey-4; + f0.off_x = f0.off_y = f1.off_y = 2; + f1.off_x = f0.size_x+4+2; + + // set fractals parameters + f0.cx = -0.6f; f0.cy = 0.0f; f0.magn = 200.0f; + f1.cx = -0.6f; f1.cy = 0.0f; f1.magn = 200.0f; + f0.max_iterations = f1.max_iterations = _max_iterations; + + // initially the first fractal is active + active = 0; + + num_frames[0] = num_frames[1] = _num_frames; +} + +void fractal_group::mouse_click(int x, int y) { + // assumption that the point is not inside any fractal area + int new_active = -1; + + if ( f0.check_point( x, y ) ) { + // the point is inside the first fractal area + new_active = 0; + } else if ( f1.check_point( x, y ) ) { + // the point is inside the second fractal area + new_active = 1; + } + + if ( new_active != -1 && new_active != active ) { + switch_priorities( new_active ); + } +} diff --git a/src/tbb/examples/task_priority/fractal/fractal.h b/src/tbb/examples/task_priority/fractal/fractal.h new file mode 100644 index 0000000..f060553 --- /dev/null +++ b/src/tbb/examples/task_priority/fractal/fractal.h @@ -0,0 +1,122 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef FRACTAL_H_ +#define FRACTAL_H_ + +#include "../../common/gui/video.h" + +#include "tbb/task.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/atomic.h" + +//! Fractal class +class fractal { + //! Left corner of the fractal area + int off_x, off_y; + //! Size of the fractal area + int size_x, size_y; + + //! Fractal properties + float cx, cy; + float magn; + int max_iterations; + + //! Drawing memory object for rendering + const drawing_memory &dm; + + //! One pixel calculation routine + color_t calc_one_pixel(int x, int y); + //! Clears the fractal area + void clear(); + //! Draws the border around the fractal area + void draw_border( bool is_active ); + //! Renders the fractal + void render( tbb::task_group_context &context ); + //! Check if the point is inside the fractal area + bool check_point( int x, int y); + +public: + //! Constructor + fractal( const drawing_memory &dm ) : dm(dm) { +#if _MSC_VER && _WIN64 && !__INTEL_COMPILER + // Workaround for MSVC x64 compiler issue + volatile int i=0; +#endif + } + //! Runs the fractal calculation + void run( tbb::task_group_context &context ); + //! Renders the fractal rectangular area + void render_rect(int x0, int y0, int x1, int y1); + + friend class fractal_group; +}; + +//! The group of fractals +class fractal_group { + //! Fractals defenition + fractal f0, f1; + //! Number of frames to calculate + tbb::atomic num_frames[2]; + //! Task group contexts to manage prioroties + tbb::task_group_context *context; + + //! Border type enumeration + enum BORDER_TYPE { + BORDER_INACTIVE = 0, + BORDER_ACTIVE + }; + + //! The number of the threads + int num_threads; + //! The active (high priority) fractal number + int active; + + //! Draws the borders around the fractals + void draw_borders(); + //! Sets priorities for fractals calculations + void set_priorities(); + +public: + //! Constructor + fractal_group( const drawing_memory &_dm, int num_threads = tbb::task_scheduler_init::automatic, int max_iterations = 100000, int num_frames = 1); + //! Run calculation + void run( bool create_second_fractal=true ); + //! Mouse event handler + void mouse_click(int x, int y); + //! Fractal calculation routine + void calc_fractal( int num ); + //! Get number of threads + int get_num_threads() const { return num_threads; } + //! Reset the number of frames to be not less than the given value + void set_num_frames_at_least(int n); + //! Switches the priorities of two fractals + void switch_priorities( int new_active=-1 ); +}; + +#endif /* FRACTAL_H_ */ diff --git a/src/tbb/examples/task_priority/fractal/fractal_video.h b/src/tbb/examples/task_priority/fractal/fractal_video.h new file mode 100644 index 0000000..c3b8f49 --- /dev/null +++ b/src/tbb/examples/task_priority/fractal/fractal_video.h @@ -0,0 +1,80 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef FRACTAL_VIDEO_H_ +#define FRACTAL_VIDEO_H_ + +#include "../../common/gui/video.h" +#include "fractal.h" + +extern video *v; +extern bool single; + +class fractal_video : public video +{ + fractal_group *fg; + +private: + void on_mouse( int x, int y, int key ) { + if( key == 1 ) { + if ( fg ) { + fg->set_num_frames_at_least(20); + fg->mouse_click( x, y ); + } + } + } + + void on_key( int key ) { + switch ( key&0xff ) { + case 27: + running = false; break; + case ' ': // space + if( fg ) fg->switch_priorities(); + default: + if( fg ) fg->set_num_frames_at_least(20); + } + } + + void on_process() { + if ( fg ) { + fg->run( !single ); + } + } + +public: + fractal_video() :fg(0) { + title = "Dynamic Priorities in TBB: Fractal Example"; + v = this; + } + + void set_fractal_group( fractal_group &_fg ) { + fg = &_fg; + } +}; + +#endif /* FRACTAL_VIDEO_H_ */ diff --git a/src/tbb/examples/task_priority/fractal/index.html b/src/tbb/examples/task_priority/fractal/index.html new file mode 100644 index 0000000..7caed5e --- /dev/null +++ b/src/tbb/examples/task_priority/fractal/index.html @@ -0,0 +1,66 @@ + + + +

    Overview

    +The example calculates two classical Mandelbrot fractals with different priorities. +The application window is divided into two areas where fractals are rendered. With mouse click on an area the user can change the priority of the calculating fractal. In the clicked area the fractal priority is changed to be "high" and the priority of the other fractal is changed to "normal". +The example also has the console mode but in this mode the priorities could not be changed during execution. + + +

    Files

    +
    +
    main.cpp +
    Main program which parses command line options and runs the fractals calculation in GUI or Console mode. +
    fractal.h +
    Interfaces of fractal and fractal_group classes. +
    fractal.cpp +
    Implementations of fractal and fractal_group classes. +
    fractal_video.h +
    GUI mode support interface. +
    Makefile +
    Makefile for building example. +
    + +

    Directories

    +
    +
    msvs +
    Contains Microsoft* Visual Studio* 2005 workspace for building and running the example (Windows* systems only). +
    xcode +
    Contains Xcode* IDE workspace for building and running the example (Mac OS* X systems only). +
    + +

    To Build

    +General build directions can be found here. + +

    Usage

    +
    +
    fractal -h +
    Prints the help for command line options +
    fractal [n-of-threads=value] [n-of-frames=value] [max-of-iterations=value] [grain-size=value] [silent] [single] +
    fractal [n-of-threads [n-of-frames [max-of-iterations [grain-size]]]] [silent] [single] +
    n-of-threads is the number of threads to use; a range of the form low[:high], where low and optional high are non-negative integers or 'auto' for the TBB default.
    + n-of-frames is a number of frames the example processes internally.
    + max-of-iterations is a maximum number of the fractal iterations.
    + grain-size is an optional grain size, must be a positive integer.
    + use-auto-partitioner - use tbb::auto_partitioner.
    + silent - no output except elapsed time.
    + single - process only one fractal.
    + +
    To run a short version of this example, e.g., for use with Intel® Parallel Inspector: +
    Build a debug version of the example + (see the build directions). +
    Run it with a small fractal iterations number and the desired number of threads, e.g., fractal 4 1 10000. +
    + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + + diff --git a/src/tbb/examples/task_priority/fractal/main.cpp b/src/tbb/examples/task_priority/fractal/main.cpp new file mode 100644 index 0000000..f364474 --- /dev/null +++ b/src/tbb/examples/task_priority/fractal/main.cpp @@ -0,0 +1,100 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#define VIDEO_WINMAIN_ARGS + +#include +#include + +#include "fractal.h" +#include "fractal_video.h" + +#include "tbb/tick_count.h" +#include "tbb/task_scheduler_init.h" + +#include "../../common/utility/utility.h" + +bool silent = false; +bool single = false; +bool schedule_auto = false; +int grain_size = 8; + +int main(int argc, char *argv[]) +{ + try{ + tbb::tick_count mainStartTime = tbb::tick_count::now(); + + // It is used for console mode for test with different number of threads and also has + // meaning for GUI: threads.first - use separate event/updating loop thread (>0) or not (0). + // threads.second - initialization value for scheduler + utility::thread_number_range threads( tbb::task_scheduler_init::default_num_threads ); + int num_frames = -1; + int max_iterations = 1000000; + + // command line parsing + utility::parse_cli_arguments(argc,argv, + utility::cli_argument_pack() + //"-h" option for for displaying help is present implicitly + .positional_arg(threads,"n-of-threads","number of threads to use; a range of the form low[:high], where low and optional high are non-negative integers or 'auto' for the TBB default.") + .positional_arg(num_frames,"n-of-frames","number of frames the example processes internally") + .positional_arg(max_iterations,"max-of-iterations","maximum number of the fractal iterations") + .positional_arg(grain_size,"grain-size","the grain size value") + .arg(schedule_auto, "use-auto-partitioner", "use tbb::auto_partitioner") + .arg(silent, "silent", "no output except elapsed time") + .arg(single, "single", "process only one fractal") + ); + + fractal_video video; + + // video layer init + if ( video.init_window(1024, 512) ) { + video.calc_fps = false; + video.threaded = threads.first > 0; + // initialize fractal group + fractal_group fg( video.get_drawing_memory(), threads.last, max_iterations, num_frames ); + video.set_fractal_group( fg ); + // main loop + video.main_loop(); + } + else if ( video.init_console() ) { + // in console mode we always have limited number of frames + num_frames = num_frames<0 ? 1 : num_frames; + for(int p = threads.first; p <= threads.last; ++p ) { + if ( !silent ) printf("Threads = %d\n", p); + fractal_group fg( video.get_drawing_memory(), p, max_iterations, num_frames ); + fg.run( !single ); + } + } + video.terminate(); + utility::report_elapsed_time((tbb::tick_count::now() - mainStartTime).seconds()); + return 0; + } catch ( std::exception& e ) { + std::cerr<<"error occurred. error text is :\"" < + + + + diff --git a/src/tbb/examples/task_priority/fractal/msvs/fractal.vcproj b/src/tbb/examples/task_priority/fractal/msvs/fractal.vcproj new file mode 100644 index 0000000..2c10b70 --- /dev/null +++ b/src/tbb/examples/task_priority/fractal/msvs/fractal.vcproj @@ -0,0 +1,853 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/task_priority/fractal/msvs/fractal_cl.sln b/src/tbb/examples/task_priority/fractal/msvs/fractal_cl.sln new file mode 100644 index 0000000..7ded9c9 --- /dev/null +++ b/src/tbb/examples/task_priority/fractal/msvs/fractal_cl.sln @@ -0,0 +1,35 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fractal", "fractal.vcproj", "{3AA40693-F93D-4D4B-B32E-068F511A2527}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + DD Debug|Win32 = DD Debug|Win32 + DD Debug|x64 = DD Debug|x64 + DD Release|Win32 = DD Release|Win32 + DD Release|x64 = DD Release|x64 + GDI Debug|Win32 = GDI Debug|Win32 + GDI Debug|x64 = GDI Debug|x64 + _GDI Release|Win32 = _GDI Release|Win32 + _GDI Release|x64 = _GDI Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Debug|Win32.Build.0 = DDDebug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Debug|x64.Build.0 = DDDebug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Release|Win32.Build.0 = DDRelease|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Release|x64.ActiveCfg = DDRelease|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Release|x64.Build.0 = DDRelease|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.GDI Debug|Win32.ActiveCfg = GDIDebug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.GDI Debug|x64.ActiveCfg = GDIRelease|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.GDI Debug|x64.Build.0 = GDIRelease|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}._GDI Release|Win32.ActiveCfg = GDIRelease|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}._GDI Release|x64.ActiveCfg = GDIRelease|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}._GDI Release|x64.Build.0 = GDIRelease|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/task_priority/fractal/msvs/fractal_icl.sln b/src/tbb/examples/task_priority/fractal/msvs/fractal_icl.sln new file mode 100644 index 0000000..600a1da --- /dev/null +++ b/src/tbb/examples/task_priority/fractal/msvs/fractal_icl.sln @@ -0,0 +1,49 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "fractal", "fractal.icproj", "{BF088DF5-BAEA-4EB2-8EA5-1E8DFBC75E5C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + DD Debug|Win32 = DD Debug|Win32 + DD Debug|x64 = DD Debug|x64 + DD Release|Win32 = DD Release|Win32 + DD Release|x64 = DD Release|x64 + GDI Debug|Win32 = GDI Debug|Win32 + GDI Debug|x64 = GDI Debug|x64 + _GDI Release|Win32 = _GDI Release|Win32 + _GDI Release|x64 = _GDI Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BF088DF5-BAEA-4EB2-8EA5-1E8DFBC75E5C}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + {BF088DF5-BAEA-4EB2-8EA5-1E8DFBC75E5C}.DD Debug|Win32.Build.0 = DDDebug|Win32 + {BF088DF5-BAEA-4EB2-8EA5-1E8DFBC75E5C}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {BF088DF5-BAEA-4EB2-8EA5-1E8DFBC75E5C}.DD Debug|x64.Build.0 = DDDebug|x64 + {BF088DF5-BAEA-4EB2-8EA5-1E8DFBC75E5C}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {BF088DF5-BAEA-4EB2-8EA5-1E8DFBC75E5C}.DD Release|Win32.Build.0 = DDRelease|Win32 + {BF088DF5-BAEA-4EB2-8EA5-1E8DFBC75E5C}.DD Release|x64.ActiveCfg = DDRelease|x64 + {BF088DF5-BAEA-4EB2-8EA5-1E8DFBC75E5C}.DD Release|x64.Build.0 = DDRelease|x64 + {BF088DF5-BAEA-4EB2-8EA5-1E8DFBC75E5C}.GDI Debug|Win32.ActiveCfg = GDIDebug|x64 + {BF088DF5-BAEA-4EB2-8EA5-1E8DFBC75E5C}.GDI Debug|x64.ActiveCfg = GDIRelease|x64 + {BF088DF5-BAEA-4EB2-8EA5-1E8DFBC75E5C}.GDI Debug|x64.Build.0 = GDIRelease|x64 + {BF088DF5-BAEA-4EB2-8EA5-1E8DFBC75E5C}._GDI Release|Win32.ActiveCfg = GDIRelease|x64 + {BF088DF5-BAEA-4EB2-8EA5-1E8DFBC75E5C}._GDI Release|x64.ActiveCfg = GDIRelease|x64 + {BF088DF5-BAEA-4EB2-8EA5-1E8DFBC75E5C}._GDI Release|x64.Build.0 = GDIRelease|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}._GDI Release|x64.Build.0 = GDIRelease|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}._GDI Release|x64.ActiveCfg = GDIRelease|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}._GDI Release|Win32.ActiveCfg = GDIRelease|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.GDI Debug|x64.Build.0 = GDIRelease|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.GDI Debug|x64.ActiveCfg = GDIRelease|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.GDI Debug|Win32.ActiveCfg = GDIDebug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Release|x64.Build.0 = DDRelease|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Release|x64.ActiveCfg = DDRelease|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Release|Win32.Build.0 = DDRelease|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Release|Win32.ActiveCfg = DDRelease|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Debug|x64.Build.0 = DDDebug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Debug|x64.ActiveCfg = DDDebug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Debug|Win32.Build.0 = DDDebug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A2527}.DD Debug|Win32.ActiveCfg = DDDebug|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/task_priority/fractal/msvs/gui.ico b/src/tbb/examples/task_priority/fractal/msvs/gui.ico new file mode 100644 index 0000000000000000000000000000000000000000..d551aa3aaf80adf9b7760e2eb8de95a5c3e53df6 GIT binary patch literal 23558 zcmeI430zgx+QuJHKtxbe5gbu*030B5$VyGcDGSFOalkY&2LuvC5pp(7&2XNl96=@z zNXGH2`|DO#nx)3nwUq43A>_N=+wHsYe$U#6ePmShD&p^B>2uySylbs@uYIPy&-w#c zpc-6UYC)x+ErDgUwQ8BlZ7hIURRB*7exZ#T}AXG2* z=^weGTI5~Inq#r?3QZRh5>Vvy7AqDy*^i;1p6BY7;LQSXZ{;g>M z?fm5AM!1uJ~14CP5-;mbWJGeF0 z_iurN!(6GBI54yo4h(CB{j~e(6Em$hj*V=Fqpvo{5$e#07L+U2`wvFkn8s8S#Efo= z^|!}o{tozLT1|Z7UlaSMxZ(5FgK^Rilm(Khv|vko7i5X}36?lI))Ggklas69 zVxSe$=33+10BfA^v%)uXY;b;dHGCaV4e6oPadwt1PEE7L#SjO4G`kKy33kG#^P1yK zcx(J^Ra<Ti+?95-JJvGIWK0JnTs;vs^DcXy)=jK$w z=lme~e0CM~SM61i7E+Zy6!Vv8(?YCpX|5H%3$bS21{dbq;8I96Tne>C8jm-9o*mM| z?2r~#1K&~U^BwT@ygK+I#1UDG8sIO%&iE*}A+E1$jbGNa!S(fRas9ovxba>)TBY{5 zxxo`Rq9|oIDtY0?rjE#1t!!u9+}s5>w|2#i&D55z%y+}h?JrQ>af9~O4zA^n9=Nr$ z7jEt9gPXg&@$23JxV49(y|Q~4emOiI-)H_6dH=qKoBYhlq5e+&PW_AegZf|U-_)N} z9@RJC3MS7vp?yXL1qC4>AOQaU{+Kjr5++WZhzS!Wz}MFoW5Wxo&I+1!G$zZHn#$;`!98-<yjHIyy#~ zd!^|5sm6LSF)_!K%8;V#rWzZU(N_%@(#Q5Ewg{KRHI95 zY?=LIo2D9@#Ky*zb^O>SmHu~IE44l?Dgh-;K81z)WLJ`;4wqn z_ZrZ%LmzL?wy3kD_lL%jZ@l`n*YIJJ=8o?=KVm^dc=tK8XTNSrUK1xwofb5!|4WPJ z4;&O=5uecStt8`&$o&U)@7lX>*XEsj-g|fBj_upFZrx%^n^vq{{r0M5OP8-%`Odni z4ek1_pUw~WS3(xf3w~KkBmDdVRSL~dfr0)bOf7sI@n%@?lm1=c0pd4Z&T02Hm@RH2 z)we;5{I7(S*0d0%twR;wLsA|##n-X4buN70s`TsBg@MbpxknH6!QPjfV-K~P+VA6v z_lLE?{$Xwi?eB?&gE}IlpC>|?5A<%2&;edpIl33d4IhkA?7Qcs#@NdnYWsbf({dao zjuAS*69M!eGt37G)4CyX#*2ub-V>ij1>vuo!mzs+z)KgL@b7{zHqOE48v-$!zJ3#Y zv6uJbc6$T6dQ*KU=65px!K_Y5n$a2Cr*_9zn`Ys&O+gqt+y{pT0q+l>1_JwOKM87w zj|1D|zXCjwI@=4Ewok|DRTFSw+Z#B)bq3CDnTav%mol33yacQq;D9qB?)YqOTV(8< zhO{02IO`82u>Hs|UYpK$#ksIn_%f8&v3sW=YtK}ip9y^Z1~r3H`B~I#;2iDQ=@jeE zsP;Kl_%^%|E=9QF`(^IPTIr6TH*`S`ui5^ww+}9?dJfr}dg8{OA;>xEhiiu?LYUzwb+T)8Ci=PAZtkjWKvm68X{|HBivlm3|Y&X;^sP6+GhB5eJk92w>5I2 z+$j(Ix}hC1827D>9dK(?2jp()h@8zG@!QT$$l2N%x3+e|?QJ|JOre?J8PhnJ%Ni~CLrzWB&44|iS%zyB8@if zn`DaR3m@|O^QyPhwX#dzrgIKY+OQIBHLeiIw|EP z&VT0+jvL~&)rdRJe}-vnAIJ6*Q-ZDH1N-*w-gRv2&ZLw99b3D3xO=#{xw*T!wQ+Oz@bGBcd0?|n&$#sN_2S8-lrFX#RqEa{~iIg60Iwp0)kazxeJo zgX#N&>G3k(9Zpk`k46?8yGp_NR9<~gx%0b2>EBc6h6N*s;*a0{2Wy6O#7ZA8q(u55 zXmAg#9`ZC+QBk9x#nSQpa4CKpR!sCp#>stnXRBl-)qQFW^fsryy=(Z?FI2AS<5;lV$HB*W zpm$$$hhFu3THa~z+qYL;AE$u>2QZl)2G;Ru)3f^vUAny3rOUHDp6~jct50i}CXE|6 zZPK7&qvp+?vT*b1+^M5y`wmZgdAPT0`%H^xiXL6DvWOu*60xx;u6V#Q2{0r8adCy( zEn;IuV&g28p4jI>W#CW53OF&!CsAr~RottogHM>&s@S>DKq|7h|3SD9 zqF9XiYwfgmNUJRFhY%(1o6xLY)@?;QKJMM%9Zv1};>0~2!r#}0zp0zW`xNH9UeDj( zg}=XRQtjm}{_d~Eq+;bB6m$ICmr^L!lH$^jp`^CQQOEr>=J>f^rrg)^KRssd^D)QI zeLuo|80KTp^Sb>{=X%)v)pLRSmCW&T|B@EJinpT1Tyzb%m&zPJ_g4w`z?hFg`Rd1_ z>Wj7&9jm;{DmLy1Gsn+8Vp@!PtSTNouWWh8cdz+W{M_4Sj-PwjDs;R>k4LR3_uiS~ z=YBll{weJklr8FC(aI`*?jJPA&pn00ytW2@1pNNmFr)z)}MRaMZIsT^P*Jr zd{v~ficiI=V%Fb3xlf-prc}}2|5bcSDrP-?@&@_Qn~c8Rs-)*Df-M*%`H0H+%lZ72 zvi{EGQOr#h;dxS84CWx2AwMJBn{b$~fyU%&3N}@!=X}9qDHtRuG5tUm68j-~fkG1sqOUyGmYlwPgb z2OYaS`ssnHnDzL{f$7y1HvU2ZvOsRl96y=1qRkb)O#V)fzZuy)A>;K#iJYK%{YIx)`7mahDM1B1t%cm9kaZNYkD4X_DC9qd+$8->B5TQhB} zPLpFP(T5^y$$V8IA1dTRh5V#84>?gGBg(O=3b|S#mnh^Cg)FI%vsB;THmdl^aSGW> zA@3;U9fcgEkcSj)tKX)y|CMyJ9 zWMGAisgNZVGNwZIRLI7bES?uKuA0cIN->306SAtME58p}SdPK5N}H!(y?QQ$SPR)# zEw=cH;9p8myVEOE~ZJrY}3iIg?0rP&%LTBp=}8h@I%TXv<9-xUO`%}-uWt5a*E=2Z6^)Nip$4?6}mrb=W3r9pMm{N(?%I<=0f{ZX!iK0oKQ1d^EdG#^%`N>O4Lp#&)lc_BC`N?cbBh&ou z$Ha>#mE4>Z3XbJ2L!+Nt++W%XmzCnEDKwe#1XEVN#&9kX7z*Ba>aDt~p(O7d58 ztNMbLMIj4qo}V1Gs?t)?V|bWl{j*<9L>}8bKN)V*HyMT)&Xn7jpKpqbGz6zmVk@{(S%;moMb= zg`B=PIy$QPUCF}>xq2agFXZoq+`W*w*DN`FAuBIr%G&-D!IW`F9}` zFJ#_@jJ%MQmz-@~sV+i3UdYL7B1xFE+kg*rC_sn}}eaYVo*?J*YFZ>$;!oOJ{ z{QCgB-)1FF4i?imzkPZz{4Rvr{h7I>sgUu{%LsSK%b0JUml0-1RnN;GSP!(-+jpO%JopO`B((dnpK-(&yRaUJ6F; zchnE_k$Wv1f4{oG;*T$8Vx5|ss!Wf01@yO_$nuNBLZ4Gvb)Vu6x9f7RD3t3{RPFna z@~=**zWfUs8kYPPZCSL4e)B1xT|TXnSM+U>y|{O?8%m4vtzIr_BVKg5vCP}`*3dR} z&a!{N#n>%>kU18z!$Q_q$meQ#RW3=oZ=knFmg=8&V&`qOUg~p1N&lWwnpHmPb9YW3 zw+z)kIP(xwOMAJX5{|A*v__uZdtvV;w2rOkgeCCc1i z#a5Q%Amc3IgIa3+fBIm(x&OWTs_~Un|HxNN{coH$#m{POUDev^Dy>e{FMhe1Y5iiu zZ_N=+wHsYe$U#6ePmShD&p^B>2uySylbs@uYIPy&-w#c zpc-6UYC)x+ErDgUwQ8BlZ7hIURRB*7exZ#T}AXG2* z=^weGTI5~Inq#r?3QZRh5>Vvy7AqDy*^i;1p6BY7;LQSXZ{;g>M z?fm5AM!1uJ~14CP5-;mbWJGeF0 z_iurN!(6GBI54yo4h(CB{j~e(6Em$hj*V=Fqpvo{5$e#07L+U2`wvFkn8s8S#Efo= z^|!}o{tozLT1|Z7UlaSMxZ(5FgK^Rilm(Khv|vko7i5X}36?lI))Ggklas69 zVxSe$=33+10BfA^v%)uXY;b;dHGCaV4e6oPadwt1PEE7L#SjO4G`kKy33kG#^P1yK zcx(J^Ra<Ti+?95-JJvGIWK0JnTs;vs^DcXy)=jK$w z=lme~e0CM~SM61i7E+Zy6!Vv8(?YCpX|5H%3$bS21{dbq;8I96Tne>C8jm-9o*mM| z?2r~#1K&~U^BwT@ygK+I#1UDG8sIO%&iE*}A+E1$jbGNa!S(fRas9ovxba>)TBY{5 zxxo`Rq9|oIDtY0?rjE#1t!!u9+}s5>w|2#i&D55z%y+}h?JrQ>af9~O4zA^n9=Nr$ z7jEt9gPXg&@$23JxV49(y|Q~4emOiI-)H_6dH=qKoBYhlq5e+&PW_AegZf|U-_)N} z9@RJC3MS7vp?yXL1qC4>AOQaU{+Kjr5++WZhzS!Wz}MFoW5Wxo&I+1!G$zZHn#$;`!98-<yjHIyy#~ zd!^|5sm6LSF)_!K%8;V#rWzZU(N_%@(#Q5Ewg{KRHI95 zY?=LIo2D9@#Ky*zb^O>SmHu~IE44l?Dgh-;K81z)WLJ`;4wqn z_ZrZ%LmzL?wy3kD_lL%jZ@l`n*YIJJ=8o?=KVm^dc=tK8XTNSrUK1xwofb5!|4WPJ z4;&O=5uecStt8`&$o&U)@7lX>*XEsj-g|fBj_upFZrx%^n^vq{{r0M5OP8-%`Odni z4ek1_pUw~WS3(xf3w~KkBmDdVRSL~dfr0)bOf7sI@n%@?lm1=c0pd4Z&T02Hm@RH2 z)we;5{I7(S*0d0%twR;wLsA|##n-X4buN70s`TsBg@MbpxknH6!QPjfV-K~P+VA6v z_lLE?{$Xwi?eB?&gE}IlpC>|?5A<%2&;edpIl33d4IhkA?7Qcs#@NdnYWsbf({dao zjuAS*69M!eGt37G)4CyX#*2ub-V>ij1>vuo!mzs+z)KgL@b7{zHqOE48v-$!zJ3#Y zv6uJbc6$T6dQ*KU=65px!K_Y5n$a2Cr*_9zn`Ys&O+gqt+y{pT0q+l>1_JwOKM87w zj|1D|zXCjwI@=4Ewok|DRTFSw+Z#B)bq3CDnTav%mol33yacQq;D9qB?)YqOTV(8< zhO{02IO`82u>Hs|UYpK$#ksIn_%f8&v3sW=YtK}ip9y^Z1~r3H`B~I#;2iDQ=@jeE zsP;Kl_%^%|E=9QF`(^IPTIr6TH*`S`ui5^ww+}9?dJfr}dg8{OA;>xEhiiu?LYUzwb+T)8Ci=PAZtkjWKvm68X{|HBivlm3|Y&X;^sP6+GhB5eJk92w>5I2 z+$j(Ix}hC1827D>9dK(?2jp()h@8zG@!QT$$l2N%x3+e|?QJ|JOre?J8PhnJ%Ni~CLrzWB&44|iS%zyB8@if zn`DaR3m@|O^QyPhwX#dzrgIKY+OQIBHLeiIw|EP z&VT0+jvL~&)rdRJe}-vnAIJ6*Q-ZDH1N-*w-gRv2&ZLw99b3D3xO=#{xw*T!wQ+Oz@bGBcd0?|n&$#sN_2S8-lrFX#RqEa{~iIg60Iwp0)kazxeJo zgX#N&>G3k(9Zpk`k46?8yGp_NR9<~gx%0b2>EBc6h6N*s;*a0{2Wy6O#7ZA8q(u55 zXmAg#9`ZC+QBk9x#nSQpa4CKpR!sCp#>stnXRBl-)qQFW^fsryy=(Z?FI2AS<5;lV$HB*W zpm$$$hhFu3THa~z+qYL;AE$u>2QZl)2G;Ru)3f^vUAny3rOUHDp6~jct50i}CXE|6 zZPK7&qvp+?vT*b1+^M5y`wmZgdAPT0`%H^xiXL6DvWOu*60xx;u6V#Q2{0r8adCy( zEn;IuV&g28p4jI>W#CW53OF&!CsAr~RottogHM>&s@S>DKq|7h|3SD9 zqF9XiYwfgmNUJRFhY%(1o6xLY)@?;QKJMM%9Zv1};>0~2!r#}0zp0zW`xNH9UeDj( zg}=XRQtjm}{_d~Eq+;bB6m$ICmr^L!lH$^jp`^CQQOEr>=J>f^rrg)^KRssd^D)QI zeLuo|80KTp^Sb>{=X%)v)pLRSmCW&T|B@EJinpT1Tyzb%m&zPJ_g4w`z?hFg`Rd1_ z>Wj7&9jm;{DmLy1Gsn+8Vp@!PtSTNouWWh8cdz+W{M_4Sj-PwjDs;R>k4LR3_uiS~ z=YBll{weJklr8FC(aI`*?jJPA&pn00ytW2@1pNNmFr)z)}MRaMZIsT^P*Jr zd{v~ficiI=V%Fb3xlf-prc}}2|5bcSDrP-?@&@_Qn~c8Rs-)*Df-M*%`H0H+%lZ72 zvi{EGQOr#h;dxS84CWx2AwMJBn{b$~fyU%&3N}@!=X}9qDHtRuG5tUm68j-~fkG1sqOUyGmYlwPgb z2OYaS`ssnHnDzL{f$7y1HvU2ZvOsRl96y=1qRkb)O#V)fzZuy)A>;K#iJYK%{YIx)`7mahDM1B1t%cm9kaZNYkD4X_DC9qd+$8->B5TQhB} zPLpFP(T5^y$$V8IA1dTRh5V#84>?gGBg(O=3b|S#mnh^Cg)FI%vsB;THmdl^aSGW> zA@3;U9fcgEkcSj)tKX)y|CMyJ9 zWMGAisgNZVGNwZIRLI7bES?uKuA0cIN->306SAtME58p}SdPK5N}H!(y?QQ$SPR)# zEw=cH;9p8myVEOE~ZJrY}3iIg?0rP&%LTBp=}8h@I%TXv<9-xUO`%}-uWt5a*E=2Z6^)Nip$4?6}mrb=W3r9pMm{N(?%I<=0f{ZX!iK0oKQ1d^EdG#^%`N>O4Lp#&)lc_BC`N?cbBh&ou z$Ha>#mE4>Z3XbJ2L!+Nt++W%XmzCnEDKwe#1XEVN#&9kX7z*Ba>aDt~p(O7d58 ztNMbLMIj4qo}V1Gs?t)?V|bWl{j*<9L>}8bKN)V*HyMT)&Xn7jpKpqbGz6zmVk@{(S%;moMb= zg`B=PIy$QPUCF}>xq2agFXZoq+`W*w*DN`FAuBIr%G&-D!IW`F9}` zFJ#_@jJ%MQmz-@~sV+i3UdYL7B1xFE+kg*rC_sn}}eaYVo*?J*YFZ>$;!oOJ{ z{QCgB-)1FF4i?imzkPZz{4Rvr{h7I>sgUu{%LsSK%b0JUml0-1RnN;GSP!(-+jpO%JopO`B((dnpK-(&yRaUJ6F; zchnE_k$Wv1f4{oG;*T$8Vx5|ss!Wf01@yO_$nuNBLZ4Gvb)Vu6x9f7RD3t3{RPFna z@~=**zWfUs8kYPPZCSL4e)B1xT|TXnSM+U>y|{O?8%m4vtzIr_BVKg5vCP}`*3dR} z&a!{N#n>%>kU18z!$Q_q$meQ#RW3=oZ=knFmg=8&V&`qOUg~p1N&lWwnpHmPb9YW3 zw+z)kIP(xwOMAJX5{|A*v__uZdtvV;w2rOkgeCCc1i z#a5Q%Amc3IgIa3+fBIm(x&OWTs_~Un|HxNN{coH$#m{POUDev^Dy>e{FMhe1Y5iiu zZ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/task_priority/index.html b/src/tbb/examples/task_priority/index.html new file mode 100644 index 0000000..cf2ff56 --- /dev/null +++ b/src/tbb/examples/task_priority/index.html @@ -0,0 +1,23 @@ + + + +

    Overview

    +This directory has examples of how to use the task priority feature. + +

    Directories

    +
    +
    fractal +
    The example calculates two classical Mandelbrot fractals with different priorities. +
    + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + diff --git a/src/tbb/examples/test_all/fibonacci/Fibonacci.cpp b/src/tbb/examples/test_all/fibonacci/Fibonacci.cpp new file mode 100644 index 0000000..bcd9ac4 --- /dev/null +++ b/src/tbb/examples/test_all/fibonacci/Fibonacci.cpp @@ -0,0 +1,601 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* Example program that computes Fibonacci numbers in different ways. + Arguments are: [ Number [Threads [Repeats]]] + The defaults are Number=500 Threads=1:4 Repeats=1. + + The point of this program is to check that the library is working properly. + Most of the computations are deliberately silly and not expected to + show any speedup on multiprocessors. +*/ + +// enable assertions +#ifdef NDEBUG +#undef NDEBUG +#endif + +#include +#include +#include +#include +#include "tbb/task.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/tick_count.h" +#include "tbb/blocked_range.h" +#include "tbb/concurrent_vector.h" +#include "tbb/concurrent_queue.h" +#include "tbb/concurrent_hash_map.h" +#include "tbb/parallel_while.h" +#include "tbb/parallel_for.h" +#include "tbb/parallel_reduce.h" +#include "tbb/parallel_scan.h" +#include "tbb/pipeline.h" +#include "tbb/atomic.h" +#include "tbb/mutex.h" +#include "tbb/spin_mutex.h" +#include "tbb/queuing_mutex.h" +#include "tbb/tbb_thread.h" + +using namespace std; +using namespace tbb; + +//! type used for Fibonacci number computations +typedef long long value; + +//! Matrix 2x2 class +struct Matrix2x2 +{ + //! Array of values + value v[2][2]; + Matrix2x2() {} + Matrix2x2(value v00, value v01, value v10, value v11) { + v[0][0] = v00; v[0][1] = v01; v[1][0] = v10; v[1][1] = v11; + } + Matrix2x2 operator * (const Matrix2x2 &to) const; //< Multiply two Matrices +}; +//! Default matrix to multiply +static const Matrix2x2 Matrix1110(1, 1, 1, 0); +//! Raw arrays matrices multiply +void Matrix2x2Multiply(const value a[2][2], const value b[2][2], value c[2][2]); + +/////////////////////// Serial methods //////////////////////// + +//! Plain serial sum +value SerialFib(int n) +{ + if(n < 2) + return n; + value a = 0, b = 1, sum; int i; + for( i = 2; i <= n; i++ ) + { // n is really index of Fibonacci number + sum = a + b; a = b; b = sum; + } + return sum; +} +//! Serial n-1 matrices multiplication +value SerialMatrixFib(int n) +{ + value c[2][2], a[2][2] = {{1, 1}, {1, 0}}, b[2][2] = {{1, 1}, {1, 0}}; int i; + for(i = 2; i < n; i++) + { // Using condition to prevent copying of values + if(i & 1) Matrix2x2Multiply(a, c, b); + else Matrix2x2Multiply(a, b, c); + } + return (i & 1) ? c[0][0] : b[0][0]; // get result from upper left cell +} +//! Recursive summing. Just for complete list of serial algorithms, not used +value SerialRecursiveFib(int n) +{ + value result; + if(n < 2) + result = n; + else + result = SerialRecursiveFib(n - 1) + SerialRecursiveFib(n - 2); + return result; +} +//! Introducing of queue method in serial +value SerialQueueFib(int n) +{ + concurrent_queue Q; + for(int i = 1; i < n; i++) + Q.push(Matrix1110); + Matrix2x2 A, B; + while(true) { + while( !Q.try_pop(A) ) this_tbb_thread::yield(); + if(Q.empty()) break; + while( !Q.try_pop(B) ) this_tbb_thread::yield(); + Q.push(A * B); + } + return A.v[0][0]; +} +//! Trying to use concurrent_vector +value SerialVectorFib(int n) +{ + concurrent_vector A; + A.grow_by(2); + A[0] = 0; A[1] = 1; + for( int i = 2; i <= n; i++) + { + A.grow_to_at_least(i+1); + A[i] = A[i-1] + A[i-2]; + } + return A[n]; +} + +///////////////////// Parallel methods //////////////////////// + +// *** Serial shared by mutexes *** // + +//! Shared glabals +value SharedA = 0, SharedB = 1; int SharedI = 1, SharedN; + +//! Template task class which computes Fibonacci numbers with shared globals +template +class SharedSerialFibBody { + M &mutex; +public: + SharedSerialFibBody( M &m ) : mutex( m ) {} + //! main loop + void operator()( const blocked_range& range ) const { + for(;;) { + typename M::scoped_lock lock( mutex ); + if(SharedI >= SharedN) break; + value sum = SharedA + SharedB; + SharedA = SharedB; SharedB = sum; + ++SharedI; + } + } +}; + +//! Root function +template +value SharedSerialFib(int n) +{ + SharedA = 0; SharedB = 1; SharedI = 1; SharedN = n; M mutex; + parallel_for( blocked_range(0,4,1), SharedSerialFibBody( mutex ) ); + return SharedB; +} + +// *** Serial shared by concurrent hash map *** // + +//! Hash comparer +struct IntHashCompare { + bool equal( const int j, const int k ) const { return j == k; } + unsigned long hash( const int k ) const { return (unsigned long)k; } +}; +//! NumbersTable type based on concurrent_hash_map +typedef concurrent_hash_map NumbersTable; +//! task for serial method using shared concurrent_hash_map +class ConcurrentHashSerialFibTask: public task { + NumbersTable &Fib; + int my_n; +public: + //! constructor + ConcurrentHashSerialFibTask( NumbersTable &cht, int n ) : Fib(cht), my_n(n) { } + //! executing task + /*override*/ task* execute() + { + for( int i = 2; i <= my_n; ++i ) { // there is no difference in to recycle or to make loop + NumbersTable::const_accessor f1, f2; // same as iterators + if( !Fib.find(f1, i-1) || !Fib.find(f2, i-2) ) { + // Something is seriously wrong, because i-1 and i-2 must have been inserted + // earlier by this thread or another thread. + assert(0); + } + value sum = f1->second + f2->second; + NumbersTable::const_accessor fsum; + Fib.insert(fsum, make_pair(i, sum)); // inserting + assert( fsum->second == sum ); // check value + } + return 0; + } +}; + +//! Root function +value ConcurrentHashSerialFib(int n) +{ + NumbersTable Fib; + bool okay; + okay = Fib.insert( make_pair(0, 0) ); assert(okay); // assign initial values + okay = Fib.insert( make_pair(1, 1) ); assert(okay); + + task_list list; + // allocate tasks + list.push_back(*new(task::allocate_root()) ConcurrentHashSerialFibTask(Fib, n)); + list.push_back(*new(task::allocate_root()) ConcurrentHashSerialFibTask(Fib, n)); + task::spawn_root_and_wait(list); + NumbersTable::const_accessor fresult; + okay = Fib.find( fresult, n ); + assert(okay); + return fresult->second; +} + +// *** Queue with parallel_for and parallel_while *** // + +//! Stream of matrices +struct QueueStream { + volatile bool producer_is_done; + concurrent_queue Queue; + //! Get pair of matricies if present + bool pop_if_present( pair &mm ) { + // get first matrix if present + if(!Queue.try_pop(mm.first)) return false; + // get second matrix if present + if(!Queue.try_pop(mm.second)) { + // if not, then push back first matrix + Queue.push(mm.first); return false; + } + return true; + } +}; + +//! Functor for parallel_for which fills the queue +struct parallel_forFibBody { + QueueStream &my_stream; + //! fill functor arguments + parallel_forFibBody(QueueStream &s) : my_stream(s) { } + //! iterate thorough range + void operator()( const blocked_range &range ) const { + int i_end = range.end(); + for( int i = range.begin(); i != i_end; ++i ) { + my_stream.Queue.push( Matrix1110 ); // push initial matrix + } + } +}; +//! Functor for parallel_while which process the queue +class parallel_whileFibBody +{ + QueueStream &my_stream; + parallel_while &my_while; +public: + typedef pair argument_type; + //! fill functor arguments + parallel_whileFibBody(parallel_while &w, QueueStream &s) + : my_while(w), my_stream(s) { } + //! process pair of matrices + void operator() (argument_type mm) const { + mm.first = mm.first * mm.second; + // note: it can run concurrently with QueueStream::pop_if_present() + if(my_stream.Queue.try_pop(mm.second)) + my_while.add( mm ); // now, two matrices available. Add next iteration. + else my_stream.Queue.push( mm.first ); // or push back calculated value if queue is empty + } +}; + +//! Parallel queue's filling task +struct QueueInsertTask: public task { + QueueStream &my_stream; + int my_n; + //! fill task arguments + QueueInsertTask( int n, QueueStream &s ) : my_n(n), my_stream(s) { } + //! executing task + /*override*/ task* execute() { + // Execute of parallel pushing of n-1 initial matrices + parallel_for( blocked_range( 1, my_n, 10 ), parallel_forFibBody(my_stream) ); + my_stream.producer_is_done = true; + return 0; + } +}; +//! Parallel queue's processing task +struct QueueProcessTask: public task { + QueueStream &my_stream; + //! fill task argument + QueueProcessTask( QueueStream &s ) : my_stream(s) { } + //! executing task + /*override*/ task* execute() { + while( !my_stream.producer_is_done || my_stream.Queue.unsafe_size()>1 ) { + parallel_while w; // run while loop in parallel + w.run( my_stream, parallel_whileFibBody( w, my_stream ) ); + } + return 0; + } +}; +//! Root function +value ParallelQueueFib(int n) +{ + QueueStream stream; + stream.producer_is_done = false; + task_list list; + list.push_back(*new(task::allocate_root()) QueueInsertTask( n, stream )); + list.push_back(*new(task::allocate_root()) QueueProcessTask( stream )); + // If there is only a single thread, the first task in the list runs to completion + // before the second task in the list starts. + task::spawn_root_and_wait(list); + assert(stream.Queue.unsafe_size() == 1); // it is easy to lose some work + Matrix2x2 M; + bool result = stream.Queue.try_pop( M ); // get last matrix + assert( result ); + return M.v[0][0]; // and result number +} + +// *** Queue with pipeline *** // + +//! filter to fills queue +class InputFilter: public filter { + atomic N; //< index of Fibonacci number minus 1 +public: + concurrent_queue Queue; + //! fill filter arguments + InputFilter( int n ) : filter(false /*is not serial*/) { N = n; } + //! executing filter + /*override*/ void* operator()(void*) + { + int n = --N; + if(n <= 0) return 0; + Queue.push( Matrix1110 ); + return &Queue; + } +}; +//! filter to process queue +class MultiplyFilter: public filter { +public: + MultiplyFilter( ) : filter(false /*is not serial*/) { } + //! executing filter + /*override*/ void* operator()(void*p) + { + concurrent_queue &Queue = *static_cast *>(p); + Matrix2x2 m1, m2; + // get two elements + while( !Queue.try_pop( m1 ) ) this_tbb_thread::yield(); + while( !Queue.try_pop( m2 ) ) this_tbb_thread::yield(); + m1 = m1 * m2; // process them + Queue.push( m1 ); // and push back + return this; // just nothing + } +}; +//! Root function +value ParallelPipeFib(int n) +{ + InputFilter input( n-1 ); + MultiplyFilter process; + // Create the pipeline + pipeline pipeline; + // add filters + pipeline.add_filter( input ); // first + pipeline.add_filter( process ); // second + + input.Queue.push( Matrix1110 ); + // Run the pipeline + pipeline.run( n ); // must be larger then max threads number + pipeline.clear(); // do not forget clear the pipeline + + assert( input.Queue.unsafe_size()==1 ); + Matrix2x2 M; + bool result = input.Queue.try_pop( M ); // get last element + assert( result ); + return M.v[0][0]; // get value +} + +// *** parallel_reduce *** // + +//! Functor for parallel_reduce +struct parallel_reduceFibBody { + Matrix2x2 sum; + int splitted; //< flag to make one less operation for splitted bodies + //! Constructor fills sum with initial matrix + parallel_reduceFibBody() : sum( Matrix1110 ), splitted(0) { } + //! Splitting constructor + parallel_reduceFibBody( parallel_reduceFibBody& other, split ) : sum( Matrix1110 ), splitted(1/*note that it is splitted*/) {} + //! Join point + void join( parallel_reduceFibBody &s ) { + sum = sum * s.sum; + } + //! Process multiplications + void operator()( const blocked_range &r ) { + for( int k = r.begin() + splitted; k < r.end(); ++k ) + sum = sum * Matrix1110; + splitted = 0; // reset flag, because this method can be reused for next range + } +}; +//! Root function +value parallel_reduceFib(int n) +{ + parallel_reduceFibBody b; + parallel_reduce(blocked_range(2, n, 3), b); // do parallel reduce on range [2, n) for b + return b.sum.v[0][0]; +} + +// *** parallel_scan *** // + +//! Functor for parallel_scan +struct parallel_scanFibBody { + Matrix2x2 sum; + int first; // flag to make one less operation for first range + //! Constructor fills sum with initial matrix + parallel_scanFibBody() : sum( Matrix1110 ), first(1) {} + //! Splitting constructor + parallel_scanFibBody( parallel_scanFibBody &b, split) : sum( Matrix1110 ), first(1) {} + //! Join point + void reverse_join( parallel_scanFibBody &a ) { + sum = sum * a.sum; + } + //! Assign point + void assign( parallel_scanFibBody &b ) { + sum = b.sum; + } + //! Process multiplications. For two tags + template + void operator()( const blocked_range &r, T) { + // see tag.is_final_scan() for what tag is used + for( int k = r.begin() + first; k < r.end(); ++k ) + sum = sum * Matrix1110; + first = 0; // reset flag, because this method can be reused for next range + } +}; +//! Root function +value parallel_scanFib(int n) +{ + parallel_scanFibBody b; + parallel_scan(blocked_range(1/*one less, because body skip first*/, n, 3), b); + return b.sum.v[0][0]; +} + +// *** Raw tasks *** // + +//! task class which computes Fibonacci numbers by Lucas formula +struct FibTask: public task { + const int n; + value& sum; + value x, y; + bool second_phase; //< flag of continuation + // task arguments + FibTask( int n_, value& sum_ ) : + n(n_), sum(sum_), second_phase(false) + {} + //! Execute task + /*override*/ task* execute() { + // Using Lucas' formula here + if( second_phase ) { // children finished + sum = n&1 ? x*x + y*y : x*x - y*y; + return NULL; + } + if( n <= 2 ) { + sum = n!=0; + return NULL; + } else { + recycle_as_continuation(); // repeat this task when children finish + second_phase = true; // mark second phase + FibTask& a = *new( allocate_child() ) FibTask( n/2 + 1, x ); + FibTask& b = *new( allocate_child() ) FibTask( n/2 - 1 + (n&1), y ); + set_ref_count(2); + spawn( a ); + return &b; + } + } +}; +//! Root function +value ParallelTaskFib(int n) { + value sum; + FibTask& a = *new(task::allocate_root()) FibTask(n, sum); + task::spawn_root_and_wait(a); + return sum; +} + +/////////////////////////// Main //////////////////////////////////////////////////// + +//! A closed range of int. +struct IntRange { + int low; + int high; + void set_from_string( const char* s ); + IntRange( int low_, int high_ ) : low(low_), high(high_) {} +}; + +void IntRange::set_from_string( const char* s ) { + char* end; + high = low = strtol(s,&end,0); + switch( *end ) { + case ':': + high = strtol(end+1,0,0); + break; + case '\0': + break; + default: + printf("unexpected character = %c\n",*end); + } +} + +//! Tick count for start +static tick_count t0; + +//! Verbose output flag +static bool Verbose = false; + +typedef value (*MeasureFunc)(int); +//! Measure ticks count in loop [2..n] +value Measure(const char *name, MeasureFunc func, int n) +{ + value result; + if(Verbose) printf("%s",name); + t0 = tick_count::now(); + for(int number = 2; number <= n; number++) + result = func(number); + if(Verbose) printf("\t- in %f msec\n", (tick_count::now() - t0).seconds()*1000); + return result; +} + +//! program entry +int main(int argc, char* argv[]) +{ + if(argc>1) Verbose = true; + int NumbersCount = argc>1 ? strtol(argv[1],0,0) : 500; + IntRange NThread(1,4);// Number of threads to use. + if(argc>2) NThread.set_from_string(argv[2]); + unsigned long ntrial = argc>3? (unsigned long)strtoul(argv[3],0,0) : 1; + value result, sum; + + if(Verbose) printf("Fibonacci numbers example. Generating %d numbers..\n", NumbersCount); + + result = Measure("Serial loop", SerialFib, NumbersCount); + sum = Measure("Serial matrix", SerialMatrixFib, NumbersCount); assert(result == sum); + sum = Measure("Serial vector", SerialVectorFib, NumbersCount); assert(result == sum); + sum = Measure("Serial queue", SerialQueueFib, NumbersCount); assert(result == sum); + // now in parallel + for( unsigned long i=0; i, NumbersCount); assert(result == sum); + sum = Measure("Shared serial (spin_mutex)", SharedSerialFib, NumbersCount); assert(result == sum); + sum = Measure("Shared serial (queuing_mutex)", SharedSerialFib, NumbersCount); assert(result == sum); + sum = Measure("Shared serial (Conc.HashTable)", ConcurrentHashSerialFib, NumbersCount); assert(result == sum); + sum = Measure("Parallel while+for/queue", ParallelQueueFib, NumbersCount); assert(result == sum); + sum = Measure("Parallel pipe/queue\t", ParallelPipeFib, NumbersCount); assert(result == sum); + sum = Measure("Parallel reduce\t\t", parallel_reduceFib, NumbersCount); assert(result == sum); + sum = Measure("Parallel scan\t\t", parallel_scanFib, NumbersCount); assert(result == sum); + sum = Measure("Parallel tasks\t\t", ParallelTaskFib, NumbersCount); assert(result == sum); + } + + #ifdef __GNUC__ + if(Verbose) printf("Fibonacci number #%d modulo 2^64 is %lld\n\n", NumbersCount, result); + #else + if(Verbose) printf("Fibonacci number #%d modulo 2^64 is %I64d\n\n", NumbersCount, result); + #endif + } + if(!Verbose) printf("TEST PASSED\n"); + return 0; +} + +// Utils + +void Matrix2x2Multiply(const value a[2][2], const value b[2][2], value c[2][2]) +{ + for( int i = 0; i <= 1; i++) + for( int j = 0; j <= 1; j++) + c[i][j] = a[i][0]*b[0][j] + a[i][1]*b[1][j]; +} + +Matrix2x2 Matrix2x2::operator *(const Matrix2x2 &to) const +{ + Matrix2x2 result; + Matrix2x2Multiply(v, to.v, result.v); + return result; +} diff --git a/src/tbb/examples/test_all/fibonacci/Makefile b/src/tbb/examples/test_all/fibonacci/Makefile new file mode 100644 index 0000000..5144576 --- /dev/null +++ b/src/tbb/examples/test_all/fibonacci/Makefile @@ -0,0 +1,52 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# GNU Makefile that builds and runs example. +PROG=fibonacci +ARGS= + +# The C++ compiler +ifneq (,$(shell which icc 2>/dev/null)) +CXX=icc +endif # icc + +ifeq ($(shell uname), Linux) +LIBS+= -lrt +endif + +all: release test + +release: *.cpp + $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb $(LIBS) + +debug: *.cpp + $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(LIBS) + +clean: + $(RM) $(PROG) *.o *.d + +test: + ./$(PROG) $(ARGS) diff --git a/src/tbb/examples/test_all/fibonacci/Makefile.windows b/src/tbb/examples/test_all/fibonacci/Makefile.windows new file mode 100644 index 0000000..79a20e4 --- /dev/null +++ b/src/tbb/examples/test_all/fibonacci/Makefile.windows @@ -0,0 +1,53 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +# Common Makefile that builds and runs example. + +# Just specify your program basename +PROG=Fibonacci +ARGS= + +# Trying to find if icl.exe is set +CXX1 = $(TBB_CXX)- +CXX2 = $(CXX1:icl.exe-=icl.exe) +CXX = $(CXX2:-=cl.exe) + +# The C++ compiler options +MYCXXFLAGS = /TP /EHsc /W3 /nologo /D _CONSOLE /D _MBCS /D WIN32 $(CXXFLAGS) +MYLDFLAGS =/INCREMENTAL:NO /NOLOGO /DEBUG /FIXED:NO $(LDFLAGS) + +all: release test +release: compiler_check + $(CXX) *.cpp /MD /O2 /D NDEBUG $(MYCXXFLAGS) /link tbb.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +debug: compiler_check + $(CXX) *.cpp /MDd /Od /Zi /D TBB_USE_DEBUG /D _DEBUG $(MYCXXFLAGS) /link tbb_debug.lib $(LIBS) $(MYLDFLAGS) /OUT:$(PROG).exe +clean: + @cmd.exe /C del $(PROG).exe *.obj *.?db *.manifest +test: + $(PROG) $(ARGS) +compiler_check: + @echo compiler_test>compiler_test && @$(CXX) /E compiler_test >nul 2>&1 || echo "$(CXX) command not found. Check if CXX=$(CXX) is set properly" + @cmd.exe /C del compiler_test diff --git a/src/tbb/examples/test_all/fibonacci/index.html b/src/tbb/examples/test_all/fibonacci/index.html new file mode 100644 index 0000000..684c02b --- /dev/null +++ b/src/tbb/examples/test_all/fibonacci/index.html @@ -0,0 +1,51 @@ + + + +

    Overview

    +This directory contains an example that computes Fibonacci numbers in several +different ways. The purpose of the example is to exercise every include file +and class in Intel® Threading Building Blocks. +Most of the computations are deliberately silly and not expected to +show any speedup on multiprocessors. +

    Files

    +
    +
    Fibonacci.cpp +
    Source code for example. +
    Makefile +
    Makefile for building example. +
    + +

    Directories

    +
    +
    msvs +
    Contains Microsoft* Visual Studio* 2005 workspace for building and running the + example (Windows* systems only).
    xcode +
    Contains Xcode* IDE workspace for building and running the example (Mac OS* X + systems only).
    + +

    To Build

    +General build directions can be found here. + +

    Usage

    +
    +
    fibonacci K [M[:N]] [R] +
    Calculates the K-th fibonacci number. + M and N are a range of numbers of threads to be used. + R is the number of times to repeat the calculation. +
    To run a short version of this example, e.g., for use with Intel® Threading Tools: +
    Build a debug version of the example + (see the build directions). +
    Run it with a small fibonacci number and the desired number of threads, e.g., fibonacci 100 4. +
    + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + diff --git a/src/tbb/examples/test_all/fibonacci/msvs/fibonacci.icproj b/src/tbb/examples/test_all/fibonacci/msvs/fibonacci.icproj new file mode 100644 index 0000000..1f5e5b4 --- /dev/null +++ b/src/tbb/examples/test_all/fibonacci/msvs/fibonacci.icproj @@ -0,0 +1,11 @@ + + + + + diff --git a/src/tbb/examples/test_all/fibonacci/msvs/fibonacci.vcproj b/src/tbb/examples/test_all/fibonacci/msvs/fibonacci.vcproj new file mode 100644 index 0000000..7d38fd0 --- /dev/null +++ b/src/tbb/examples/test_all/fibonacci/msvs/fibonacci.vcproj @@ -0,0 +1,356 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tbb/examples/test_all/fibonacci/msvs/fibonacci_cl.sln b/src/tbb/examples/test_all/fibonacci/msvs/fibonacci_cl.sln new file mode 100644 index 0000000..60dafea --- /dev/null +++ b/src/tbb/examples/test_all/fibonacci/msvs/fibonacci_cl.sln @@ -0,0 +1,25 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fibonacci", "fibonacci.vcproj", "{3AA40693-F93D-4D4B-B32E-068F511A252E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3AA40693-F93D-4D4B-B32E-068F511A252E}.Debug|Win32.ActiveCfg = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252E}.Debug|Win32.Build.0 = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252E}.Debug|x64.ActiveCfg = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252E}.Debug|x64.Build.0 = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252E}.Release|Win32.ActiveCfg = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252E}.Release|Win32.Build.0 = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252E}.Release|x64.ActiveCfg = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252E}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/test_all/fibonacci/msvs/fibonacci_icl.sln b/src/tbb/examples/test_all/fibonacci/msvs/fibonacci_icl.sln new file mode 100644 index 0000000..70c5369 --- /dev/null +++ b/src/tbb/examples/test_all/fibonacci/msvs/fibonacci_icl.sln @@ -0,0 +1,33 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "fibonacci", "fibonacci.icproj", "{123FDABA-4A55-4E79-AE28-58E90AA8256E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {123FDABA-4A55-4E79-AE28-58E90AA8256E}.Debug|Win32.ActiveCfg = Debug|Win32 + {123FDABA-4A55-4E79-AE28-58E90AA8256E}.Debug|Win32.Build.0 = Debug|Win32 + {123FDABA-4A55-4E79-AE28-58E90AA8256E}.Debug|x64.ActiveCfg = Debug|x64 + {123FDABA-4A55-4E79-AE28-58E90AA8256E}.Debug|x64.Build.0 = Debug|x64 + {123FDABA-4A55-4E79-AE28-58E90AA8256E}.Release|Win32.ActiveCfg = Release|Win32 + {123FDABA-4A55-4E79-AE28-58E90AA8256E}.Release|Win32.Build.0 = Release|Win32 + {123FDABA-4A55-4E79-AE28-58E90AA8256E}.Release|x64.ActiveCfg = Release|x64 + {123FDABA-4A55-4E79-AE28-58E90AA8256E}.Release|x64.Build.0 = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252E}.Release|x64.Build.0 = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252E}.Release|x64.ActiveCfg = Release|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252E}.Release|Win32.Build.0 = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252E}.Release|Win32.ActiveCfg = Release|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252E}.Debug|x64.Build.0 = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252E}.Debug|x64.ActiveCfg = Debug|x64 + {3AA40693-F93D-4D4B-B32E-068F511A252E}.Debug|Win32.Build.0 = Debug|Win32 + {3AA40693-F93D-4D4B-B32E-068F511A252E}.Debug|Win32.ActiveCfg = Debug|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/tbb/examples/test_all/fibonacci/xcode/fibonacci.xcodeproj/project.pbxproj b/src/tbb/examples/test_all/fibonacci/xcode/fibonacci.xcodeproj/project.pbxproj new file mode 100644 index 0000000..0a08617 --- /dev/null +++ b/src/tbb/examples/test_all/fibonacci/xcode/fibonacci.xcodeproj/project.pbxproj @@ -0,0 +1,305 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + A1F593A60B8F042A00073279 /* Fibonacci.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1F593A50B8F042A00073279 /* Fibonacci.cpp */; }; + A1F593B70B8F06F900073279 /* libtbb.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; + A1F593BB0B8F072500073279 /* libtbb.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = A1F593B30B8F06F900073279 /* libtbb.dylib */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8DD76F690486A84900D96B5E /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = ""; + dstSubfolderSpec = 16; + files = ( + A1F593BB0B8F072500073279 /* libtbb.dylib in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 8DD76F6C0486A84900D96B5E /* Fibonacci */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Fibonacci; sourceTree = BUILT_PRODUCTS_DIR; }; + A1F593A50B8F042A00073279 /* Fibonacci.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Fibonacci.cpp; path = ../Fibonacci.cpp; sourceTree = SOURCE_ROOT; }; + A1F593B30B8F06F900073279 /* libtbb.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtbb.dylib; path = ../../../../lib/libtbb.dylib; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8DD76F660486A84900D96B5E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A1F593B70B8F06F900073279 /* libtbb.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* Fibonacci */ = { + isa = PBXGroup; + children = ( + 08FB7795FE84155DC02AAC07 /* Source */, + A1F593B20B8F06F900073279 /* External Frameworks and Libraries */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + ); + name = Fibonacci; + sourceTree = ""; + }; + 08FB7795FE84155DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + A1F593A50B8F042A00073279 /* Fibonacci.cpp */, + ); + name = Source; + sourceTree = ""; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8DD76F6C0486A84900D96B5E /* Fibonacci */, + ); + name = Products; + sourceTree = ""; + }; + A1F593B20B8F06F900073279 /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + A1F593B30B8F06F900073279 /* libtbb.dylib */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8DD76F620486A84900D96B5E /* Fibonacci */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "Fibonacci" */; + buildPhases = ( + 8DD76F640486A84900D96B5E /* Sources */, + 8DD76F660486A84900D96B5E /* Frameworks */, + 8DD76F690486A84900D96B5E /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Fibonacci; + productInstallPath = "$(HOME)/bin"; + productName = Fibonacci; + productReference = 8DD76F6C0486A84900D96B5E /* Fibonacci */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0410; + }; + buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "fibonacci" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + en, + ); + mainGroup = 08FB7794FE84155DC02AAC07 /* Fibonacci */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DD76F620486A84900D96B5E /* Fibonacci */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 8DD76F640486A84900D96B5E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A1F593A60B8F042A00073279 /* Fibonacci.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1DEB923208733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = ""; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = Fibonacci; + ZERO_LINK = NO; + }; + name = Debug; + }; + 1DEB923308733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = ""; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = Fibonacci; + ZERO_LINK = NO; + }; + name = Release; + }; + 1DEB923608733DC60010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Debug; + }; + 1DEB923708733DC60010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Release; + }; + A1F593C60B8F0E6E00073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = ""; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = Fibonacci; + ZERO_LINK = NO; + }; + name = Debug64; + }; + A1F593C70B8F0E6E00073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_VERSION = ""; + HEADER_SEARCH_PATHS = ../../../../include; + INSTALL_PATH = "$(HOME)/bin"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../../../lib, + ); + PRODUCT_NAME = Fibonacci; + ZERO_LINK = NO; + }; + name = Release64; + }; + A1F593C80B8F0E6E00073279 /* Debug64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-m64", + ); + OTHER_LDFLAGS = "-m64"; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Debug64; + }; + A1F593C90B8F0E6E00073279 /* Release64 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = i386; + GCC_ENABLE_CPP_RTTI = YES; + GCC_MODEL_TUNING = ""; + GCC_VERSION = 4.0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-m64", + ); + OTHER_LDFLAGS = "-m64"; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; + SYMROOT = "/tmp/tbb-$(USER)"; + }; + name = Release64; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "Fibonacci" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923208733DC60010E9CD /* Debug */, + A1F593C60B8F0E6E00073279 /* Debug64 */, + 1DEB923308733DC60010E9CD /* Release */, + A1F593C70B8F0E6E00073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "fibonacci" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB923608733DC60010E9CD /* Debug */, + A1F593C80B8F0E6E00073279 /* Debug64 */, + 1DEB923708733DC60010E9CD /* Release */, + A1F593C90B8F0E6E00073279 /* Release64 */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/src/tbb/examples/test_all/index.html b/src/tbb/examples/test_all/index.html new file mode 100644 index 0000000..277d315 --- /dev/null +++ b/src/tbb/examples/test_all/index.html @@ -0,0 +1,24 @@ + + + +

    Overview

    +This directory contains programs that exercise all the components of Intel® Threading Building Blocks. + +

    Directories

    +
    +
    fibonacci +
    Compute Fibonacci numbers in different ways. +
    + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + + diff --git a/src/tbb/include/index.html b/src/tbb/include/index.html new file mode 100644 index 0000000..26cd33a --- /dev/null +++ b/src/tbb/include/index.html @@ -0,0 +1,23 @@ + + + +

    Overview

    +Include files for Intel® Threading Building Blocks (Intel® TBB). + +

    Directories

    +
    +
    tbb +
    Include files for Intel TBB classes and functions. +
    + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + diff --git a/src/tbb/include/serial/tbb/parallel_for.h b/src/tbb/include/serial/tbb/parallel_for.h new file mode 100644 index 0000000..7f10403 --- /dev/null +++ b/src/tbb/include/serial/tbb/parallel_for.h @@ -0,0 +1,173 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_SERIAL_parallel_for_H +#define __TBB_SERIAL_parallel_for_H + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include +#include // required to construct std exception classes + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +#include "tbb_annotate.h" + +#ifndef __TBB_NORMAL_EXECUTION +#include "tbb/blocked_range.h" +#include "tbb/partitioner.h" +#endif + +namespace tbb { +namespace serial { +namespace interface6 { + +// parallel_for serial annotated implementation + +template< typename Range, typename Body, typename Partitioner > +class start_for : tbb::internal::no_copy { + Range my_range; + const Body my_body; + typename Partitioner::task_partition_type my_partition; + void execute(); + + //! Constructor for root task. + start_for( const Range& range, const Body& body, Partitioner& partitioner ) : + my_range( range ), + my_body( body ), + my_partition( partitioner ) + { + } + + //! Splitting constructor used to generate children. + /** this becomes left child. Newly constructed object is right child. */ + start_for( start_for& parent_, split ) : + my_range( parent_.my_range, split() ), + my_body( parent_.my_body ), + my_partition( parent_.my_partition, split() ) + { + } + +public: + static void run( const Range& range, const Body& body, const Partitioner& partitioner ) { + if( !range.empty() ) { + ANNOTATE_SITE_BEGIN( tbb_parallel_for ); + { + start_for a( range, body, const_cast< Partitioner& >( partitioner ) ); + a.execute(); + } + ANNOTATE_SITE_END( tbb_parallel_for ); + } + } +}; + +template< typename Range, typename Body, typename Partitioner > +void start_for< Range, Body, Partitioner >::execute() { + if( !my_range.is_divisible() || !my_partition.divisions_left() ) { + ANNOTATE_TASK_BEGIN( tbb_parallel_for_range ); + { + my_body( my_range ); + } + ANNOTATE_TASK_END( tbb_parallel_for_range ); + } else { + start_for b( *this, split() ); + this->execute(); // Execute the left interval first to keep the serial order. + b.execute(); // Execute the right interval then. + } +} + +//! Parallel iteration over range with default partitioner.. +/** @ingroup algorithms **/ +template +void parallel_for( const Range& range, const Body& body ) { + serial::interface6::start_for::run(range,body,auto_partitioner()); +} + +//! Parallel iteration over range with simple partitioner. +/** @ingroup algorithms **/ +template +void parallel_for( const Range& range, const Body& body, const simple_partitioner& partitioner ) { + serial::interface6::start_for::run(range,body,partitioner); +} + +//! Parallel iteration over range with auto_partitioner. +/** @ingroup algorithms **/ +template +void parallel_for( const Range& range, const Body& body, const auto_partitioner& partitioner ) { + serial::interface6::start_for::run(range,body,partitioner); +} + +//! Parallel iteration over range with affinity_partitioner. +/** @ingroup algorithms **/ +template +void parallel_for( const Range& range, const Body& body, affinity_partitioner& partitioner ) { + serial::interface6::start_for::run(range,body,partitioner); +} + +//! Parallel iteration over a range of integers with a step value +template +void parallel_for(Index first, Index last, Index step, const Function& f) { + if (step <= 0 ) + throw std::invalid_argument( "nonpositive_step" ); + else if (last > first) { + // Above "else" avoids "potential divide by zero" warning on some platforms + ANNOTATE_SITE_BEGIN( tbb_parallel_for ); + for( Index i = first; i < last; i = i + step ) { + ANNOTATE_TASK_BEGIN( tbb_parallel_for_iteration ); + { f( i ); } + ANNOTATE_TASK_END( tbb_parallel_for_iteration ); + } + ANNOTATE_SITE_END( tbb_parallel_for ); + } +} + +//! Parallel iteration over a range of integers with a default step value +template +void parallel_for(Index first, Index last, const Function& f) { + parallel_for(first, last, static_cast(1), f); +} + +} // namespace interface6 + +using interface6::parallel_for; + +} // namespace serial + +#ifndef __TBB_NORMAL_EXECUTION +using serial::interface6::parallel_for; +#endif + +} // namespace tbb + +#endif /* __TBB_SERIAL_parallel_for_H */ diff --git a/src/tbb/include/serial/tbb/tbb_annotate.h b/src/tbb/include/serial/tbb/tbb_annotate.h new file mode 100644 index 0000000..58385f6 --- /dev/null +++ b/src/tbb/include/serial/tbb/tbb_annotate.h @@ -0,0 +1,44 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_annotate_H +#define __TBB_annotate_H + +// Macros used by the Intel(R) Parallel Advisor. +#ifdef __TBB_NORMAL_EXECUTION + #define ANNOTATE_SITE_BEGIN( site ) + #define ANNOTATE_SITE_END( site ) + #define ANNOTATE_TASK_BEGIN( task ) + #define ANNOTATE_TASK_END( task ) + #define ANNOTATE_LOCK_ACQUIRE( lock ) + #define ANNOTATE_LOCK_RELEASE( lock ) +#else + #include +#endif + +#endif /* __TBB_annotate_H */ diff --git a/src/tbb/include/tbb/aggregator.h b/src/tbb/include/tbb/aggregator.h new file mode 100644 index 0000000..5415528 --- /dev/null +++ b/src/tbb/include/tbb/aggregator.h @@ -0,0 +1,210 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB__aggregator_H +#define __TBB__aggregator_H + +#if !TBB_PREVIEW_AGGREGATOR +#error Set TBB_PREVIEW_AGGREGATOR before including aggregator.h +#endif + +#include "atomic.h" +#include "tbb_profiling.h" + +namespace tbb { +namespace interface6 { + +using namespace tbb::internal; + +class aggregator_operation { + template friend class aggregator_ext; + uintptr_t status; + aggregator_operation* my_next; +public: + enum aggregator_operation_status { agg_waiting=0, agg_finished }; + aggregator_operation() : status(agg_waiting), my_next(NULL) {} + /// Call start before handling this operation + void start() { call_itt_notify(acquired, &status); } + /// Call finish when done handling this operation + /** The operation will be released to its originating thread, and possibly deleted. */ + void finish() { itt_store_word_with_release(status, uintptr_t(agg_finished)); } + aggregator_operation* next() { return itt_hide_load_word(my_next);} + void set_next(aggregator_operation* n) { itt_hide_store_word(my_next, n); } +}; + +namespace internal { + +class basic_operation_base : public aggregator_operation { + friend class basic_handler; + virtual void apply_body() = 0; +public: + basic_operation_base() : aggregator_operation() {} + virtual ~basic_operation_base() {} +}; + +template +class basic_operation : public basic_operation_base, no_assign { + const Body& my_body; + /*override*/ void apply_body() { my_body(); } +public: + basic_operation(const Body& b) : basic_operation_base(), my_body(b) {} +}; + +class basic_handler { +public: + basic_handler() {} + void operator()(aggregator_operation* op_list) const { + while (op_list) { + // ITT note: &(op_list->status) tag is used to cover accesses to the operation data. + // The executing thread "acquires" the tag (see start()) and then performs + // the associated operation w/o triggering a race condition diagnostics. + // A thread that created the operation is waiting for its status (see execute_impl()), + // so when this thread is done with the operation, it will "release" the tag + // and update the status (see finish()) to give control back to the waiting thread. + basic_operation_base& request = static_cast(*op_list); + // IMPORTANT: need to advance op_list to op_list->next() before calling request.finish() + op_list = op_list->next(); + request.start(); + request.apply_body(); + request.finish(); + } + } +}; + +} // namespace internal + +//! Aggregator base class and expert interface +/** An aggregator for collecting operations coming from multiple sources and executing + them serially on a single thread. */ +template +class aggregator_ext : tbb::internal::no_copy { +public: + aggregator_ext(const handler_type& h) : handler_busy(0), handle_operations(h) { mailbox = NULL; } + + //! EXPERT INTERFACE: Enter a user-made operation into the aggregator's mailbox. + /** Details of user-made operations must be handled by user-provided handler */ + void process(aggregator_operation *op) { execute_impl(*op); } + + protected: + /** Place operation in mailbox, then either handle mailbox or wait for the operation + to be completed by a different thread. */ + void execute_impl(aggregator_operation& op) { + aggregator_operation* res; + + // ITT note: &(op.status) tag is used to cover accesses to this operation. This + // thread has created the operation, and now releases it so that the handler + // thread may handle the associated operation w/o triggering a race condition; + // thus this tag will be acquired just before the operation is handled in the + // handle_operations functor. + call_itt_notify(releasing, &(op.status)); + // insert the operation in the queue + do { + // ITT may flag the following line as a race; it is a false positive: + // This is an atomic read; we don't provide itt_hide_load_word for atomics + op.my_next = res = mailbox; // NOT A RACE + } while (mailbox.compare_and_swap(&op, res) != res); + if (!res) { // first in the list; handle the operations + // ITT note: &mailbox tag covers access to the handler_busy flag, which this + // waiting handler thread will try to set before entering handle_operations. + call_itt_notify(acquired, &mailbox); + start_handle_operations(); + __TBB_ASSERT(op.status, NULL); + } + else { // not first; wait for op to be ready + call_itt_notify(prepare, &(op.status)); + spin_wait_while_eq(op.status, uintptr_t(aggregator_operation::agg_waiting)); + itt_load_word_with_acquire(op.status); + } + } + + + private: + //! An atomically updated list (aka mailbox) of aggregator_operations + atomic mailbox; + + //! Controls thread access to handle_operations + /** Behaves as boolean flag where 0=false, 1=true */ + uintptr_t handler_busy; + + handler_type handle_operations; + + //! Trigger the handling of operations when the handler is free + void start_handle_operations() { + aggregator_operation *pending_operations; + + // ITT note: &handler_busy tag covers access to mailbox as it is passed + // between active and waiting handlers. Below, the waiting handler waits until + // the active handler releases, and the waiting handler acquires &handler_busy as + // it becomes the active_handler. The release point is at the end of this + // function, when all operations in mailbox have been handled by the + // owner of this aggregator. + call_itt_notify(prepare, &handler_busy); + // get handler_busy: only one thread can possibly spin here at a time + spin_wait_until_eq(handler_busy, uintptr_t(0)); + call_itt_notify(acquired, &handler_busy); + // acquire fence not necessary here due to causality rule and surrounding atomics + __TBB_store_with_release(handler_busy, uintptr_t(1)); + + // ITT note: &mailbox tag covers access to the handler_busy flag itself. + // Capturing the state of the mailbox signifies that handler_busy has been + // set and a new active handler will now process that list's operations. + call_itt_notify(releasing, &mailbox); + // grab pending_operations + pending_operations = mailbox.fetch_and_store(NULL); + + // handle all the operations + handle_operations(pending_operations); + + // release the handler + itt_store_word_with_release(handler_busy, uintptr_t(0)); + } +}; + +//! Basic aggregator interface +class aggregator : private aggregator_ext { +public: + aggregator() : aggregator_ext(internal::basic_handler()) {} + //! BASIC INTERFACE: Enter a function for exclusvie execution by the aggregator. + /** The calling thread stores the function object in a basic_operation and + places the operation in the aggregator's mailbox */ + template + void execute(const Body& b) { + internal::basic_operation op(b); + this->execute_impl(op); + } +}; + +} // namespace interface6 + +using interface6::aggregator; +using interface6::aggregator_ext; +using interface6::aggregator_operation; + +} // namespace tbb + +#endif // __TBB__aggregator_H diff --git a/src/tbb/include/tbb/aligned_space.h b/src/tbb/include/tbb/aligned_space.h new file mode 100644 index 0000000..d23baed --- /dev/null +++ b/src/tbb/include/tbb/aligned_space.h @@ -0,0 +1,55 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_aligned_space_H +#define __TBB_aligned_space_H + +#include "tbb_stddef.h" +#include "tbb_machine.h" + +namespace tbb { + +//! Block of space aligned sufficiently to construct an array T with N elements. +/** The elements are not constructed or destroyed by this class. + @ingroup memory_allocation */ +template +class aligned_space { +private: + typedef __TBB_TypeWithAlignmentAtLeastAsStrict(T) element_type; + element_type array[(sizeof(T)*N+sizeof(element_type)-1)/sizeof(element_type)]; +public: + //! Pointer to beginning of array + T* begin() {return internal::punned_cast(this);} + + //! Pointer to one past last element in array. + T* end() {return begin()+N;} +}; + +} // namespace tbb + +#endif /* __TBB_aligned_space_H */ diff --git a/src/tbb/include/tbb/atomic.h b/src/tbb/include/tbb/atomic.h new file mode 100644 index 0000000..8715a1e --- /dev/null +++ b/src/tbb/include/tbb/atomic.h @@ -0,0 +1,450 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_atomic_H +#define __TBB_atomic_H + +#include +#include "tbb_stddef.h" + +#if _MSC_VER +#define __TBB_LONG_LONG __int64 +#else +#define __TBB_LONG_LONG long long +#endif /* _MSC_VER */ + +#include "tbb_machine.h" + +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) + // Workaround for overzealous compiler warnings + #pragma warning (push) + #pragma warning (disable: 4244 4267) +#endif + +namespace tbb { + +//! Specifies memory semantics. +enum memory_semantics { + //! Sequential consistency + full_fence, + //! Acquire + acquire, + //! Release + release, + //! No ordering + relaxed +}; + +//! @cond INTERNAL +namespace internal { + +#if __TBB_ATTRIBUTE_ALIGNED_PRESENT + #define __TBB_DECL_ATOMIC_FIELD(t,f,a) t f __attribute__ ((aligned(a))); +#elif __TBB_DECLSPEC_ALIGN_PRESENT + #define __TBB_DECL_ATOMIC_FIELD(t,f,a) __declspec(align(a)) t f; +#else + #error Do not know syntax for forcing alignment. +#endif + +template +struct atomic_rep; // Primary template declared, but never defined. + +template<> +struct atomic_rep<1> { // Specialization + typedef int8_t word; + int8_t value; +}; +template<> +struct atomic_rep<2> { // Specialization + typedef int16_t word; + __TBB_DECL_ATOMIC_FIELD(int16_t,value,2) +}; +template<> +struct atomic_rep<4> { // Specialization +#if _MSC_VER && !_WIN64 + // Work-around that avoids spurious /Wp64 warnings + typedef intptr_t word; +#else + typedef int32_t word; +#endif + __TBB_DECL_ATOMIC_FIELD(int32_t,value,4) +}; +#if __TBB_64BIT_ATOMICS +template<> +struct atomic_rep<8> { // Specialization + typedef int64_t word; + __TBB_DECL_ATOMIC_FIELD(int64_t,value,8) +}; +#endif + +template +struct atomic_traits; // Primary template declared, but not defined. + +#define __TBB_DECL_FENCED_ATOMIC_PRIMITIVES(S,M) \ + template<> struct atomic_traits { \ + typedef atomic_rep::word word; \ + inline static word compare_and_swap( volatile void* location, word new_value, word comparand ) { \ + return __TBB_machine_cmpswp##S##M(location,new_value,comparand); \ + } \ + inline static word fetch_and_add( volatile void* location, word addend ) { \ + return __TBB_machine_fetchadd##S##M(location,addend); \ + } \ + inline static word fetch_and_store( volatile void* location, word value ) { \ + return __TBB_machine_fetchstore##S##M(location,value); \ + } \ + }; + +#define __TBB_DECL_ATOMIC_PRIMITIVES(S) \ + template \ + struct atomic_traits { \ + typedef atomic_rep::word word; \ + inline static word compare_and_swap( volatile void* location, word new_value, word comparand ) { \ + return __TBB_machine_cmpswp##S(location,new_value,comparand); \ + } \ + inline static word fetch_and_add( volatile void* location, word addend ) { \ + return __TBB_machine_fetchadd##S(location,addend); \ + } \ + inline static word fetch_and_store( volatile void* location, word value ) { \ + return __TBB_machine_fetchstore##S(location,value); \ + } \ + }; + +template +struct atomic_load_store_traits; // Primary template declaration + +#define __TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(M) \ + template<> struct atomic_load_store_traits { \ + template \ + inline static T load( const volatile T& location ) { \ + return __TBB_load_##M( location ); \ + } \ + template \ + inline static void store( volatile T& location, T value ) { \ + __TBB_store_##M( location, value ); \ + } \ + } + +#if __TBB_USE_FENCED_ATOMICS +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,full_fence) +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,full_fence) +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,full_fence) +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,acquire) +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,acquire) +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,acquire) +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,release) +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,release) +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,release) +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(1,relaxed) +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(2,relaxed) +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(4,relaxed) +#if __TBB_64BIT_ATOMICS +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,full_fence) +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,acquire) +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,release) +__TBB_DECL_FENCED_ATOMIC_PRIMITIVES(8,relaxed) +#endif +#else /* !__TBB_USE_FENCED_ATOMICS */ +__TBB_DECL_ATOMIC_PRIMITIVES(1) +__TBB_DECL_ATOMIC_PRIMITIVES(2) +__TBB_DECL_ATOMIC_PRIMITIVES(4) +#if __TBB_64BIT_ATOMICS +__TBB_DECL_ATOMIC_PRIMITIVES(8) +#endif +#endif /* !__TBB_USE_FENCED_ATOMICS */ + +__TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(full_fence); +__TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(acquire); +__TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(release); +__TBB_DECL_ATOMIC_LOAD_STORE_PRIMITIVES(relaxed); + +//! Additive inverse of 1 for type T. +/** Various compilers issue various warnings if -1 is used with various integer types. + The baroque expression below avoids all the warnings (we hope). */ +#define __TBB_MINUS_ONE(T) (T(T(0)-T(1))) + +//! Base class that provides basic functionality for atomic without fetch_and_add. +/** Works for any type T that has the same size as an integral type, has a trivial constructor/destructor, + and can be copied/compared by memcpy/memcmp. */ +template +struct atomic_impl { +protected: + atomic_rep rep; +private: + //! Union type used to convert type T to underlying integral type. + union converter { + T value; + typename atomic_rep::word bits; + }; +public: + typedef T value_type; + + template + value_type fetch_and_store( value_type value ) { + converter u, w; + u.value = value; + w.bits = internal::atomic_traits::fetch_and_store(&rep.value,u.bits); + return w.value; + } + + value_type fetch_and_store( value_type value ) { + return fetch_and_store(value); + } + + template + value_type compare_and_swap( value_type value, value_type comparand ) { + converter u, v, w; + u.value = value; + v.value = comparand; + w.bits = internal::atomic_traits::compare_and_swap(&rep.value,u.bits,v.bits); + return w.value; + } + + value_type compare_and_swap( value_type value, value_type comparand ) { + return compare_and_swap(value,comparand); + } + + operator value_type() const volatile { // volatile qualifier here for backwards compatibility + converter w; + w.bits = __TBB_load_with_acquire( rep.value ); + return w.value; + } + + template + value_type load () const { + converter u; + u.bits = internal::atomic_load_store_traits::load( rep.value ); + return u.value; + } + + value_type load () const { + return load(); + } + + template + void store ( value_type value ) { + converter u; + u.value = value; + internal::atomic_load_store_traits::store( rep.value, u.bits ); + } + + void store ( value_type value ) { + store( value ); + } + +protected: + value_type store_with_release( value_type rhs ) { + converter u; + u.value = rhs; + __TBB_store_with_release(rep.value,u.bits); + return rhs; + } +}; + +//! Base class that provides basic functionality for atomic with fetch_and_add. +/** I is the underlying type. + D is the difference type. + StepType should be char if I is an integral type, and T if I is a T*. */ +template +struct atomic_impl_with_arithmetic: atomic_impl { +public: + typedef I value_type; + + template + value_type fetch_and_add( D addend ) { + return value_type(internal::atomic_traits::fetch_and_add( &this->rep.value, addend*sizeof(StepType) )); + } + + value_type fetch_and_add( D addend ) { + return fetch_and_add(addend); + } + + template + value_type fetch_and_increment() { + return fetch_and_add(1); + } + + value_type fetch_and_increment() { + return fetch_and_add(1); + } + + template + value_type fetch_and_decrement() { + return fetch_and_add(__TBB_MINUS_ONE(D)); + } + + value_type fetch_and_decrement() { + return fetch_and_add(__TBB_MINUS_ONE(D)); + } + +public: + value_type operator+=( D value ) { + return fetch_and_add(value)+value; + } + + value_type operator-=( D value ) { + // Additive inverse of value computed using binary minus, + // instead of unary minus, for sake of avoiding compiler warnings. + return operator+=(D(0)-value); + } + + value_type operator++() { + return fetch_and_add(1)+1; + } + + value_type operator--() { + return fetch_and_add(__TBB_MINUS_ONE(D))-1; + } + + value_type operator++(int) { + return fetch_and_add(1); + } + + value_type operator--(int) { + return fetch_and_add(__TBB_MINUS_ONE(D)); + } +}; + +} /* Internal */ +//! @endcond + +//! Primary template for atomic. +/** See the Reference for details. + @ingroup synchronization */ +template +struct atomic: internal::atomic_impl { + T operator=( T rhs ) { + // "this" required here in strict ISO C++ because store_with_release is a dependent name + return this->store_with_release(rhs); + } + atomic& operator=( const atomic& rhs ) {this->store_with_release(rhs); return *this;} +}; + +#define __TBB_DECL_ATOMIC(T) \ + template<> struct atomic: internal::atomic_impl_with_arithmetic { \ + T operator=( T rhs ) {return store_with_release(rhs);} \ + atomic& operator=( const atomic& rhs ) {store_with_release(rhs); return *this;} \ + }; + +#if __TBB_64BIT_ATOMICS +__TBB_DECL_ATOMIC(__TBB_LONG_LONG) +__TBB_DECL_ATOMIC(unsigned __TBB_LONG_LONG) +#else +// test_atomic will verify that sizeof(long long)==8 +#endif +__TBB_DECL_ATOMIC(long) +__TBB_DECL_ATOMIC(unsigned long) + +#if _MSC_VER && !_WIN64 +/* Special version of __TBB_DECL_ATOMIC that avoids gratuitous warnings from cl /Wp64 option. + It is identical to __TBB_DECL_ATOMIC(unsigned) except that it replaces operator=(T) + with an operator=(U) that explicitly converts the U to a T. Types T and U should be + type synonyms on the platform. Type U should be the wider variant of T from the + perspective of /Wp64. */ +#define __TBB_DECL_ATOMIC_ALT(T,U) \ + template<> struct atomic: internal::atomic_impl_with_arithmetic { \ + T operator=( U rhs ) {return store_with_release(T(rhs));} \ + atomic& operator=( const atomic& rhs ) {store_with_release(rhs); return *this;} \ + }; +__TBB_DECL_ATOMIC_ALT(unsigned,size_t) +__TBB_DECL_ATOMIC_ALT(int,ptrdiff_t) +#else +__TBB_DECL_ATOMIC(unsigned) +__TBB_DECL_ATOMIC(int) +#endif /* _MSC_VER && !_WIN64 */ + +__TBB_DECL_ATOMIC(unsigned short) +__TBB_DECL_ATOMIC(short) +__TBB_DECL_ATOMIC(char) +__TBB_DECL_ATOMIC(signed char) +__TBB_DECL_ATOMIC(unsigned char) + +#if !_MSC_VER || defined(_NATIVE_WCHAR_T_DEFINED) +__TBB_DECL_ATOMIC(wchar_t) +#endif /* _MSC_VER||!defined(_NATIVE_WCHAR_T_DEFINED) */ + +//! Specialization for atomic with arithmetic and operator->. +template struct atomic: internal::atomic_impl_with_arithmetic { + T* operator=( T* rhs ) { + // "this" required here in strict ISO C++ because store_with_release is a dependent name + return this->store_with_release(rhs); + } + atomic& operator=( const atomic& rhs ) { + this->store_with_release(rhs); return *this; + } + T* operator->() const { + return (*this); + } +}; + +//! Specialization for atomic, for sake of not allowing arithmetic or operator->. +template<> struct atomic: internal::atomic_impl { + void* operator=( void* rhs ) { + // "this" required here in strict ISO C++ because store_with_release is a dependent name + return this->store_with_release(rhs); + } + atomic& operator=( const atomic& rhs ) { + this->store_with_release(rhs); return *this; + } +}; + +// Helpers to workaround ugly syntax of calling template member function of a +// template class with template argument dependent on template parameters. + +template +T load ( const atomic& a ) { return a.template load(); } + +template +void store ( atomic& a, T value ) { return a.template store(value); } + +namespace interface6{ +//! Make an atomic for use in an initialization (list), as an alternative to zero-initializaton or normal assignment. +template +atomic make_atomic(T t) { + atomic a; + store(a,t); + return a; +} +} +using interface6::make_atomic; + +namespace internal { + +// only to aid in the gradual conversion of ordinary variables to proper atomics +template +inline atomic& as_atomic( T& t ) { + return (atomic&)t; +} +} // namespace tbb::internal + +} // namespace tbb + +#if _MSC_VER && !__INTEL_COMPILER + #pragma warning (pop) +#endif // warnings 4244, 4267 are back + +#endif /* __TBB_atomic_H */ diff --git a/src/tbb/include/tbb/blocked_range.h b/src/tbb/include/tbb/blocked_range.h new file mode 100644 index 0000000..670e43a --- /dev/null +++ b/src/tbb/include/tbb/blocked_range.h @@ -0,0 +1,129 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_blocked_range_H +#define __TBB_blocked_range_H + +#include "tbb_stddef.h" + +namespace tbb { + +/** \page range_req Requirements on range concept + Class \c R implementing the concept of range must define: + - \code R::R( const R& ); \endcode Copy constructor + - \code R::~R(); \endcode Destructor + - \code bool R::is_divisible() const; \endcode True if range can be partitioned into two subranges + - \code bool R::empty() const; \endcode True if range is empty + - \code R::R( R& r, split ); \endcode Split range \c r into two subranges. +**/ + +//! A range over which to iterate. +/** @ingroup algorithms */ +template +class blocked_range { +public: + //! Type of a value + /** Called a const_iterator for sake of algorithms that need to treat a blocked_range + as an STL container. */ + typedef Value const_iterator; + + //! Type for size of a range + typedef std::size_t size_type; + + //! Construct range with default-constructed values for begin and end. + /** Requires that Value have a default constructor. */ + blocked_range() : my_end(), my_begin() {} + + //! Construct range over half-open interval [begin,end), with the given grainsize. + blocked_range( Value begin_, Value end_, size_type grainsize_=1 ) : + my_end(end_), my_begin(begin_), my_grainsize(grainsize_) + { + __TBB_ASSERT( my_grainsize>0, "grainsize must be positive" ); + } + + //! Beginning of range. + const_iterator begin() const {return my_begin;} + + //! One past last value in range. + const_iterator end() const {return my_end;} + + //! Size of the range + /** Unspecified if end() + friend class blocked_range2d; + + template + friend class blocked_range3d; +}; + +} // namespace tbb + +#endif /* __TBB_blocked_range_H */ diff --git a/src/tbb/include/tbb/blocked_range2d.h b/src/tbb/include/tbb/blocked_range2d.h new file mode 100644 index 0000000..08a8efe --- /dev/null +++ b/src/tbb/include/tbb/blocked_range2d.h @@ -0,0 +1,97 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_blocked_range2d_H +#define __TBB_blocked_range2d_H + +#include "tbb_stddef.h" +#include "blocked_range.h" + +namespace tbb { + +//! A 2-dimensional range that models the Range concept. +/** @ingroup algorithms */ +template +class blocked_range2d { +public: + //! Type for size of an iteration range + typedef blocked_range row_range_type; + typedef blocked_range col_range_type; + +private: + row_range_type my_rows; + col_range_type my_cols; + +public: + + blocked_range2d( RowValue row_begin, RowValue row_end, typename row_range_type::size_type row_grainsize, + ColValue col_begin, ColValue col_end, typename col_range_type::size_type col_grainsize ) : + my_rows(row_begin,row_end,row_grainsize), + my_cols(col_begin,col_end,col_grainsize) + { + } + + blocked_range2d( RowValue row_begin, RowValue row_end, + ColValue col_begin, ColValue col_end ) : + my_rows(row_begin,row_end), + my_cols(col_begin,col_end) + { + } + + //! True if range is empty + bool empty() const { + // Yes, it is a logical OR here, not AND. + return my_rows.empty() || my_cols.empty(); + } + + //! True if range is divisible into two pieces. + bool is_divisible() const { + return my_rows.is_divisible() || my_cols.is_divisible(); + } + + blocked_range2d( blocked_range2d& r, split ) : + my_rows(r.my_rows), + my_cols(r.my_cols) + { + if( my_rows.size()*double(my_cols.grainsize()) < my_cols.size()*double(my_rows.grainsize()) ) { + my_cols.my_begin = col_range_type::do_split(r.my_cols); + } else { + my_rows.my_begin = row_range_type::do_split(r.my_rows); + } + } + + //! The rows of the iteration space + const row_range_type& rows() const {return my_rows;} + + //! The columns of the iteration space + const col_range_type& cols() const {return my_cols;} +}; + +} // namespace tbb + +#endif /* __TBB_blocked_range2d_H */ diff --git a/src/tbb/include/tbb/blocked_range3d.h b/src/tbb/include/tbb/blocked_range3d.h new file mode 100644 index 0000000..e741a12 --- /dev/null +++ b/src/tbb/include/tbb/blocked_range3d.h @@ -0,0 +1,116 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_blocked_range3d_H +#define __TBB_blocked_range3d_H + +#include "tbb_stddef.h" +#include "blocked_range.h" + +namespace tbb { + +//! A 3-dimensional range that models the Range concept. +/** @ingroup algorithms */ +template +class blocked_range3d { +public: + //! Type for size of an iteration range + typedef blocked_range page_range_type; + typedef blocked_range row_range_type; + typedef blocked_range col_range_type; + +private: + page_range_type my_pages; + row_range_type my_rows; + col_range_type my_cols; + +public: + + blocked_range3d( PageValue page_begin, PageValue page_end, + RowValue row_begin, RowValue row_end, + ColValue col_begin, ColValue col_end ) : + my_pages(page_begin,page_end), + my_rows(row_begin,row_end), + my_cols(col_begin,col_end) + { + } + + blocked_range3d( PageValue page_begin, PageValue page_end, typename page_range_type::size_type page_grainsize, + RowValue row_begin, RowValue row_end, typename row_range_type::size_type row_grainsize, + ColValue col_begin, ColValue col_end, typename col_range_type::size_type col_grainsize ) : + my_pages(page_begin,page_end,page_grainsize), + my_rows(row_begin,row_end,row_grainsize), + my_cols(col_begin,col_end,col_grainsize) + { + } + + //! True if range is empty + bool empty() const { + // Yes, it is a logical OR here, not AND. + return my_pages.empty() || my_rows.empty() || my_cols.empty(); + } + + //! True if range is divisible into two pieces. + bool is_divisible() const { + return my_pages.is_divisible() || my_rows.is_divisible() || my_cols.is_divisible(); + } + + blocked_range3d( blocked_range3d& r, split ) : + my_pages(r.my_pages), + my_rows(r.my_rows), + my_cols(r.my_cols) + { + if( my_pages.size()*double(my_rows.grainsize()) < my_rows.size()*double(my_pages.grainsize()) ) { + if ( my_rows.size()*double(my_cols.grainsize()) < my_cols.size()*double(my_rows.grainsize()) ) { + my_cols.my_begin = col_range_type::do_split(r.my_cols); + } else { + my_rows.my_begin = row_range_type::do_split(r.my_rows); + } + } else { + if ( my_pages.size()*double(my_cols.grainsize()) < my_cols.size()*double(my_pages.grainsize()) ) { + my_cols.my_begin = col_range_type::do_split(r.my_cols); + } else { + my_pages.my_begin = page_range_type::do_split(r.my_pages); + } + } + } + + //! The pages of the iteration space + const page_range_type& pages() const {return my_pages;} + + //! The rows of the iteration space + const row_range_type& rows() const {return my_rows;} + + //! The columns of the iteration space + const col_range_type& cols() const {return my_cols;} + +}; + +} // namespace tbb + +#endif /* __TBB_blocked_range3d_H */ diff --git a/src/tbb/include/tbb/cache_aligned_allocator.h b/src/tbb/include/tbb/cache_aligned_allocator.h new file mode 100644 index 0000000..f6782bf --- /dev/null +++ b/src/tbb/include/tbb/cache_aligned_allocator.h @@ -0,0 +1,146 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_cache_aligned_allocator_H +#define __TBB_cache_aligned_allocator_H + +#include +#include "tbb_stddef.h" +#if __TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_CPP11_STD_FORWARD_BROKEN + #include // std::forward +#endif + +namespace tbb { + +//! @cond INTERNAL +namespace internal { + //! Cache/sector line size. + /** @ingroup memory_allocation */ + size_t __TBB_EXPORTED_FUNC NFS_GetLineSize(); + + //! Allocate memory on cache/sector line boundary. + /** @ingroup memory_allocation */ + void* __TBB_EXPORTED_FUNC NFS_Allocate( size_t n_element, size_t element_size, void* hint ); + + //! Free memory allocated by NFS_Allocate. + /** Freeing a NULL pointer is allowed, but has no effect. + @ingroup memory_allocation */ + void __TBB_EXPORTED_FUNC NFS_Free( void* ); +} +//! @endcond + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // Workaround for erroneous "unreferenced parameter" warning in method destroy. + #pragma warning (push) + #pragma warning (disable: 4100) +#endif + +//! Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5 +/** The members are ordered the same way they are in section 20.4.1 + of the ISO C++ standard. + @ingroup memory_allocation */ +template +class cache_aligned_allocator { +public: + typedef typename internal::allocator_type::value_type value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + template struct rebind { + typedef cache_aligned_allocator other; + }; + + cache_aligned_allocator() throw() {} + cache_aligned_allocator( const cache_aligned_allocator& ) throw() {} + template cache_aligned_allocator(const cache_aligned_allocator&) throw() {} + + pointer address(reference x) const {return &x;} + const_pointer address(const_reference x) const {return &x;} + + //! Allocate space for n objects, starting on a cache/sector line. + pointer allocate( size_type n, const void* hint=0 ) { + // The "hint" argument is always ignored in NFS_Allocate thus const_cast shouldn't hurt + return pointer(internal::NFS_Allocate( n, sizeof(value_type), const_cast(hint) )); + } + + //! Free block of memory that starts on a cache line + void deallocate( pointer p, size_type ) { + internal::NFS_Free(p); + } + + //! Largest value for which method allocate might succeed. + size_type max_size() const throw() { + return (~size_t(0)-internal::NFS_MaxLineSize)/sizeof(value_type); + } + + //! Copy-construct value at location pointed to by p. +#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT + template + void construct(pointer p, Args&&... args) + #if __TBB_CPP11_STD_FORWARD_BROKEN + { ::new((void *)p) T((args)...); } + #else + { ::new((void *)p) T(std::forward(args)...); } + #endif +#else // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT + void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);} +#endif // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT + + //! Destroy value at location pointed to by p. + void destroy( pointer p ) {p->~value_type();} +}; + +#if _MSC_VER && !defined(__INTEL_COMPILER) + #pragma warning (pop) +#endif // warning 4100 is back + +//! Analogous to std::allocator, as defined in ISO C++ Standard, Section 20.4.1 +/** @ingroup memory_allocation */ +template<> +class cache_aligned_allocator { +public: + typedef void* pointer; + typedef const void* const_pointer; + typedef void value_type; + template struct rebind { + typedef cache_aligned_allocator other; + }; +}; + +template +inline bool operator==( const cache_aligned_allocator&, const cache_aligned_allocator& ) {return true;} + +template +inline bool operator!=( const cache_aligned_allocator&, const cache_aligned_allocator& ) {return false;} + +} // namespace tbb + +#endif /* __TBB_cache_aligned_allocator_H */ diff --git a/src/tbb/include/tbb/combinable.h b/src/tbb/include/tbb/combinable.h new file mode 100644 index 0000000..d9a3bb5 --- /dev/null +++ b/src/tbb/include/tbb/combinable.h @@ -0,0 +1,80 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_combinable_H +#define __TBB_combinable_H + +#include "enumerable_thread_specific.h" +#include "cache_aligned_allocator.h" + +namespace tbb { +/** \name combinable + **/ +//@{ +//! Thread-local storage with optional reduction +/** @ingroup containers */ + template + class combinable { + private: + typedef typename tbb::cache_aligned_allocator my_alloc; + + typedef typename tbb::enumerable_thread_specific my_ets_type; + my_ets_type my_ets; + + public: + + combinable() { } + + template + combinable( finit _finit) : my_ets(_finit) { } + + //! destructor + ~combinable() { + } + + combinable(const combinable& other) : my_ets(other.my_ets) { } + + combinable & operator=( const combinable & other) { my_ets = other.my_ets; return *this; } + + void clear() { my_ets.clear(); } + + T& local() { return my_ets.local(); } + + T& local(bool & exists) { return my_ets.local(exists); } + + // combine_func_t has signature T(T,T) or T(const T&, const T&) + template + T combine(combine_func_t f_combine) { return my_ets.combine(f_combine); } + + // combine_func_t has signature void(T) or void(const T&) + template + void combine_each(combine_func_t f_combine) { my_ets.combine_each(f_combine); } + + }; +} // namespace tbb +#endif /* __TBB_combinable_H */ diff --git a/src/tbb/include/tbb/compat/condition_variable b/src/tbb/include/tbb/compat/condition_variable new file mode 100644 index 0000000..16caf12 --- /dev/null +++ b/src/tbb/include/tbb/compat/condition_variable @@ -0,0 +1,465 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_condition_variable_H +#define __TBB_condition_variable_H + +#if _WIN32||_WIN64 +#include "../machine/windows_api.h" + +namespace tbb { +namespace interface5 { +namespace internal { +struct condition_variable_using_event +{ + //! Event for blocking waiting threads. + HANDLE event; + //! Protects invariants involving n_waiters, release_count, and epoch. + CRITICAL_SECTION mutex; + //! Number of threads waiting on this condition variable + int n_waiters; + //! Number of threads remaining that should no longer wait on this condition variable. + int release_count; + //! To keep threads from waking up prematurely with earlier signals. + unsigned epoch; +}; +}}} // namespace tbb::interface5::internal + +#ifndef CONDITION_VARIABLE_INIT +typedef void* CONDITION_VARIABLE; +typedef CONDITION_VARIABLE* PCONDITION_VARIABLE; +#endif + +#else /* if not _WIN32||_WIN64 */ +#include // some systems need it for ETIMEDOUT +#include +#if __linux__ +#include +#else /* generic Unix */ +#include +#endif +#endif /* _WIN32||_WIN64 */ + +#include "../tbb_stddef.h" +#include "../mutex.h" +#include "../tbb_thread.h" +#include "../tbb_exception.h" +#include "../tbb_profiling.h" + +namespace tbb { + +namespace interface5 { + +// C++0x standard working draft 30.4.3 +// Lock tag types +struct defer_lock_t { }; //! do not acquire ownership of the mutex +struct try_to_lock_t { }; //! try to acquire ownership of the mutex without blocking +struct adopt_lock_t { }; //! assume the calling thread has already +const defer_lock_t defer_lock = {}; +const try_to_lock_t try_to_lock = {}; +const adopt_lock_t adopt_lock = {}; + +// C++0x standard working draft 30.4.3.1 +//! lock_guard +template +class lock_guard : tbb::internal::no_copy { +public: + //! mutex type + typedef M mutex_type; + + //! Constructor + /** precondition: If mutex_type is not a recursive mutex, the calling thread + does not own the mutex m. */ + explicit lock_guard(mutex_type& m) : pm(m) {m.lock();} + + //! Adopt_lock constructor + /** precondition: the calling thread owns the mutex m. */ + lock_guard(mutex_type& m, adopt_lock_t) : pm(m) {} + + //! Destructor + ~lock_guard() { pm.unlock(); } +private: + mutex_type& pm; +}; + +// C++0x standard working draft 30.4.3.2 +//! unique_lock +template +class unique_lock : tbb::internal::no_copy { + friend class condition_variable; +public: + typedef M mutex_type; + + // 30.4.3.2.1 construct/copy/destroy + // NB: Without constructors that take an r-value reference to a unique_lock, the following constructor is of little use. + //! Constructor + /** postcondition: pm==0 && owns==false */ + unique_lock() : pm(NULL), owns(false) {} + + //! Constructor + /** precondition: if mutex_type is not a recursive mutex, the calling thread + does not own the mutex m. If the precondition is not met, a deadlock occurs. + postcondition: pm==&m and owns==true */ + explicit unique_lock(mutex_type& m) : pm(&m) {m.lock(); owns=true;} + + //! Defer_lock constructor + /** postcondition: pm==&m and owns==false */ + unique_lock(mutex_type& m, defer_lock_t) : pm(&m), owns(false) {} + + //! Try_to_lock constructor + /** precondition: if mutex_type is not a recursive mutex, the calling thread + does not own the mutex m. If the precondition is not met, a deadlock occurs. + postcondition: pm==&m and owns==res where res is the value returned by + the call to m.try_lock(). */ + unique_lock(mutex_type& m, try_to_lock_t) : pm(&m) {owns = m.try_lock();} + + //! Adopt_lock constructor + /** precondition: the calling thread owns the mutex. If it does not, mutex->unlock() would fail. + postcondition: pm==&m and owns==true */ + unique_lock(mutex_type& m, adopt_lock_t) : pm(&m), owns(true) {} + + //! Timed unique_lock acquisition. + /** To avoid requiring support for namespace chrono, this method deviates from the working draft in that + it uses tbb::tick_count::interval_t to specify the time duration. */ + unique_lock(mutex_type& m, const tick_count::interval_t &i) : pm(&m) {owns = try_lock_for( i );} + + //! Destructor + ~unique_lock() { if( owns ) pm->unlock(); } + + // 30.4.3.2.2 locking + //! Lock the mutex and own it. + void lock() { + if( pm ) { + if( !owns ) { + pm->lock(); + owns = true; + } else + throw_exception_v4( tbb::internal::eid_possible_deadlock ); + } else + throw_exception_v4( tbb::internal::eid_operation_not_permitted ); + __TBB_ASSERT( owns, NULL ); + } + + //! Try to lock the mutex. + /** If successful, note that this lock owns it. Otherwise, set it false. */ + bool try_lock() { + if( pm ) { + if( !owns ) + owns = pm->try_lock(); + else + throw_exception_v4( tbb::internal::eid_possible_deadlock ); + } else + throw_exception_v4( tbb::internal::eid_operation_not_permitted ); + return owns; + } + + //! Try to lock the mutex. + bool try_lock_for( const tick_count::interval_t &i ); + + //! Unlock the mutex + /** And note that this lock no longer owns it. */ + void unlock() { + if( owns ) { + pm->unlock(); + owns = false; + } else + throw_exception_v4( tbb::internal::eid_operation_not_permitted ); + __TBB_ASSERT( !owns, NULL ); + } + + // 30.4.3.2.3 modifiers + //! Swap the two unique locks + void swap(unique_lock& u) { + mutex_type* t_pm = u.pm; u.pm = pm; pm = t_pm; + bool t_owns = u.owns; u.owns = owns; owns = t_owns; + } + + //! Release control over the mutex. + mutex_type* release() { + mutex_type* o_pm = pm; + pm = NULL; + owns = false; + return o_pm; + } + + // 30.4.3.2.4 observers + //! Does this lock own the mutex? + bool owns_lock() const { return owns; } + + // TODO: Un-comment 'explicit' when the last non-C++0x compiler support is dropped + //! Does this lock own the mutex? + /*explicit*/ operator bool() const { return owns; } + + //! Return the mutex that this lock currently has. + mutex_type* mutex() const { return pm; } + +private: + mutex_type* pm; + bool owns; +}; + +template +bool unique_lock::try_lock_for( const tick_count::interval_t &i) +{ + const int unique_lock_tick = 100; /* microseconds; 0.1 milliseconds */ + // the smallest wait-time is 0.1 milliseconds. + bool res = pm->try_lock(); + int duration_in_micro; + if( !res && (duration_in_micro=int(i.seconds()*1e6))>unique_lock_tick ) { + tick_count::interval_t i_100( double(unique_lock_tick)/1e6 /* seconds */); // 100 microseconds = 0.1*10E-3 + do { + this_tbb_thread::sleep(i_100); // sleep for 100 micro seconds + duration_in_micro -= unique_lock_tick; + res = pm->try_lock(); + } while( !res && duration_in_micro>unique_lock_tick ); + } + return (owns=res); +} + +//! Swap the two unique locks that have the mutexes of same type +template +void swap(unique_lock& x, unique_lock& y) { x.swap( y ); } + +namespace internal { + +#if _WIN32||_WIN64 +union condvar_impl_t { + condition_variable_using_event cv_event; + CONDITION_VARIABLE cv_native; +}; +void __TBB_EXPORTED_FUNC internal_initialize_condition_variable( condvar_impl_t& cv ); +void __TBB_EXPORTED_FUNC internal_destroy_condition_variable( condvar_impl_t& cv ); +void __TBB_EXPORTED_FUNC internal_condition_variable_notify_one( condvar_impl_t& cv ); +void __TBB_EXPORTED_FUNC internal_condition_variable_notify_all( condvar_impl_t& cv ); +bool __TBB_EXPORTED_FUNC internal_condition_variable_wait( condvar_impl_t& cv, mutex* mtx, const tick_count::interval_t* i = NULL ); + +#else /* if !(_WIN32||_WIN64), i.e., POSIX threads */ +typedef pthread_cond_t condvar_impl_t; +#endif + +} // namespace internal + +//! cv_status +/** C++0x standard working draft 30.5 */ +enum cv_status { no_timeout, timeout }; + +//! condition variable +/** C++0x standard working draft 30.5.1 + @ingroup synchronization */ +class condition_variable : tbb::internal::no_copy { +public: + //! Constructor + condition_variable() { +#if _WIN32||_WIN64 + internal_initialize_condition_variable( my_cv ); +#else + pthread_cond_init( &my_cv, NULL ); +#endif + } + + //! Destructor + ~condition_variable() { + //precondition: There shall be no thread blocked on *this. +#if _WIN32||_WIN64 + internal_destroy_condition_variable( my_cv ); +#else + pthread_cond_destroy( &my_cv ); +#endif + } + + //! Notify one thread and wake it up + void notify_one() { +#if _WIN32||_WIN64 + internal_condition_variable_notify_one( my_cv ); +#else + pthread_cond_signal( &my_cv ); +#endif + } + + //! Notify all threads + void notify_all() { +#if _WIN32||_WIN64 + internal_condition_variable_notify_all( my_cv ); +#else + pthread_cond_broadcast( &my_cv ); +#endif + } + + //! Release the mutex associated with the lock and wait on this condition variable + void wait(unique_lock& lock); + + //! Wait on this condition variable while pred is false + template + void wait(unique_lock& lock, Predicate pred) { + while( !pred() ) + wait( lock ); + } + + //! Timed version of wait() + cv_status wait_for(unique_lock& lock, const tick_count::interval_t &i ); + + //! Timed version of the predicated wait + /** The loop terminates when pred() returns true or when the time duration specified by rel_time (i) has elapsed. */ + template + bool wait_for(unique_lock& lock, const tick_count::interval_t &i, Predicate pred) + { + while( !pred() ) { + cv_status st = wait_for( lock, i ); + if( st==timeout ) + return pred(); + } + return true; + } + + // C++0x standard working draft. 30.2.3 + typedef internal::condvar_impl_t* native_handle_type; + + native_handle_type native_handle() { return (native_handle_type) &my_cv; } + +private: + internal::condvar_impl_t my_cv; +}; + + +#if _WIN32||_WIN64 +inline void condition_variable::wait( unique_lock& lock ) +{ + __TBB_ASSERT( lock.owns, NULL ); + lock.owns = false; + if( !internal_condition_variable_wait( my_cv, lock.mutex() ) ) { + int ec = GetLastError(); + // on Windows 7, SleepConditionVariableCS() may return ERROR_TIMEOUT while the doc says it returns WAIT_TIMEOUT + __TBB_ASSERT_EX( ec!=WAIT_TIMEOUT&&ec!=ERROR_TIMEOUT, NULL ); + lock.owns = true; + throw_exception_v4( tbb::internal::eid_condvar_wait_failed ); + } + lock.owns = true; +} + +inline cv_status condition_variable::wait_for( unique_lock& lock, const tick_count::interval_t& i ) +{ + cv_status rc = no_timeout; + __TBB_ASSERT( lock.owns, NULL ); + lock.owns = false; + // condvar_wait could be SleepConditionVariableCS (or SleepConditionVariableSRW) or our own pre-vista cond_var_wait() + if( !internal_condition_variable_wait( my_cv, lock.mutex(), &i ) ) { + int ec = GetLastError(); + if( ec==WAIT_TIMEOUT || ec==ERROR_TIMEOUT ) + rc = timeout; + else { + lock.owns = true; + throw_exception_v4( tbb::internal::eid_condvar_wait_failed ); + } + } + lock.owns = true; + return rc; +} + +#else /* !(_WIN32||_WIN64) */ +inline void condition_variable::wait( unique_lock& lock ) +{ + __TBB_ASSERT( lock.owns, NULL ); + lock.owns = false; + if( pthread_cond_wait( &my_cv, lock.mutex()->native_handle() ) ) { + lock.owns = true; + throw_exception_v4( tbb::internal::eid_condvar_wait_failed ); + } + // upon successful return, the mutex has been locked and is owned by the calling thread. + lock.owns = true; +} + +inline cv_status condition_variable::wait_for( unique_lock& lock, const tick_count::interval_t& i ) +{ +#if __linux__ + struct timespec req; + double sec = i.seconds(); + clock_gettime( CLOCK_REALTIME, &req ); + req.tv_sec += static_cast(sec); + req.tv_nsec += static_cast( (sec - static_cast(sec))*1e9 ); +#else /* generic Unix */ + struct timeval tv; + struct timespec req; + double sec = i.seconds(); + int status = gettimeofday(&tv, NULL); + __TBB_ASSERT_EX( status==0, "gettimeofday failed" ); + req.tv_sec = tv.tv_sec + static_cast(sec); + req.tv_nsec = tv.tv_usec*1000 + static_cast( (sec - static_cast(sec))*1e9 ); +#endif /*(choice of OS) */ + if( req.tv_nsec>=1e9 ) { + req.tv_sec += 1; + req.tv_nsec -= static_cast(1e9); + } + __TBB_ASSERT( 0<=req.tv_nsec && req.tv_nsec<1e9, NULL ); + + int ec; + cv_status rc = no_timeout; + __TBB_ASSERT( lock.owns, NULL ); + lock.owns = false; + if( ( ec=pthread_cond_timedwait( &my_cv, lock.mutex()->native_handle(), &req ) ) ) { + if( ec==ETIMEDOUT ) + rc = timeout; + else { + __TBB_ASSERT( lock.try_lock()==false, NULL ); + lock.owns = true; + throw_exception_v4( tbb::internal::eid_condvar_wait_failed ); + } + } + lock.owns = true; + return rc; +} +#endif /* !(_WIN32||_WIN64) */ + +} // namespace interface5 + +__TBB_DEFINE_PROFILING_SET_NAME(interface5::condition_variable) + +} // namespace tbb + +#if TBB_IMPLEMENT_CPP0X + +namespace std { + +using tbb::interface5::defer_lock_t; +using tbb::interface5::try_to_lock_t; +using tbb::interface5::adopt_lock_t; +using tbb::interface5::defer_lock; +using tbb::interface5::try_to_lock; +using tbb::interface5::adopt_lock; +using tbb::interface5::lock_guard; +using tbb::interface5::unique_lock; +using tbb::interface5::swap; /* this is for void std::swap(unique_lock&,unique_lock&) */ +using tbb::interface5::condition_variable; +using tbb::interface5::cv_status; +using tbb::interface5::timeout; +using tbb::interface5::no_timeout; + +} // namespace std + +#endif /* TBB_IMPLEMENT_CPP0X */ + +#endif /* __TBB_condition_variable_H */ diff --git a/src/tbb/include/tbb/compat/ppl.h b/src/tbb/include/tbb/compat/ppl.h new file mode 100644 index 0000000..514a7b4 --- /dev/null +++ b/src/tbb/include/tbb/compat/ppl.h @@ -0,0 +1,70 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_compat_ppl_H +#define __TBB_compat_ppl_H + +#include "../task_group.h" +#include "../parallel_invoke.h" +#include "../parallel_for_each.h" +#include "../parallel_for.h" +#include "../tbb_exception.h" +#include "../critical_section.h" +#include "../reader_writer_lock.h" +#include "../combinable.h" + +namespace Concurrency { + +#if __TBB_TASK_GROUP_CONTEXT + using tbb::task_handle; + using tbb::task_group_status; + using tbb::task_group; + using tbb::structured_task_group; + using tbb::invalid_multiple_scheduling; + using tbb::missing_wait; + using tbb::make_task; + + using tbb::not_complete; + using tbb::complete; + using tbb::canceled; + + using tbb::is_current_task_group_canceling; +#endif /* __TBB_TASK_GROUP_CONTEXT */ + + using tbb::parallel_invoke; + using tbb::strict_ppl::parallel_for; + using tbb::parallel_for_each; + using tbb::critical_section; + using tbb::reader_writer_lock; + using tbb::combinable; + + using tbb::improper_lock; + +} // namespace Concurrency + +#endif /* __TBB_compat_ppl_H */ diff --git a/src/tbb/include/tbb/compat/thread b/src/tbb/include/tbb/compat/thread new file mode 100644 index 0000000..54483ea --- /dev/null +++ b/src/tbb/include/tbb/compat/thread @@ -0,0 +1,54 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_thread_H +#define __TBB_thread_H + +#include "../tbb_thread.h" + +#if TBB_IMPLEMENT_CPP0X + +namespace std { + +typedef tbb::tbb_thread thread; + +namespace this_thread { + using tbb::this_tbb_thread::get_id; + using tbb::this_tbb_thread::yield; + + inline void sleep_for(const tbb::tick_count::interval_t& rel_time) { + tbb::internal::thread_sleep_v3( rel_time ); + } + +} + +} + +#endif /* TBB_IMPLEMENT_CPP0X */ + +#endif /* __TBB_thread_H */ diff --git a/src/tbb/include/tbb/compat/tuple b/src/tbb/include/tbb/compat/tuple new file mode 100644 index 0000000..0c8721c --- /dev/null +++ b/src/tbb/include/tbb/compat/tuple @@ -0,0 +1,524 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_tuple_H +#define __TBB_tuple_H + +#if !TBB_PREVIEW_TUPLE +#error Set TBB_PREVIEW_TUPLE to include compat/tuple +#endif + +#include +#include "../tbb_stddef.h" + +// build preprocessor variables for varying number of arguments +// Need the leading comma so the empty __TBB_T_PACK will not cause a syntax error. +#if __TBB_VARIADIC_MAX <= 5 +#define __TBB_T_PACK +#define __TBB_U_PACK +#define __TBB_CLASS_T_PACK +#define __TBB_CLASS_U_PACK +#define __TBB_NULL_TYPE_PACK +#define __TBB_REF_T_PARAM_PACK +#define __TBB_CONST_REF_T_PARAM_PACK +#define __TBB_T_PARAM_LIST_PACK +#define __TBB_CONST_NULL_REF_PACK +// +#elif __TBB_VARIADIC_MAX == 6 +#define __TBB_T_PACK ,T5 +#define __TBB_U_PACK ,U5 +#define __TBB_CLASS_T_PACK , class T5 +#define __TBB_CLASS_U_PACK , class U5 +#define __TBB_NULL_TYPE_PACK , null_type +#define __TBB_REF_T_PARAM_PACK ,T5& t5 +#define __TBB_CONST_REF_T_PARAM_PACK ,const T5& t5 +#define __TBB_T_PARAM_LIST_PACK ,t5 +#define __TBB_CONST_NULL_REF_PACK , const null_type& +// +#elif __TBB_VARIADIC_MAX == 7 +#define __TBB_T_PACK ,T5, T6 +#define __TBB_U_PACK ,U5, U6 +#define __TBB_CLASS_T_PACK , class T5 , class T6 +#define __TBB_CLASS_U_PACK , class U5 , class U6 +#define __TBB_NULL_TYPE_PACK , null_type, null_type +#define __TBB_REF_T_PARAM_PACK ,T5& t5, T6& t6 +#define __TBB_CONST_REF_T_PARAM_PACK ,const T5& t5, const T6& t6 +#define __TBB_T_PARAM_LIST_PACK ,t5 ,t6 +#define __TBB_CONST_NULL_REF_PACK , const null_type&, const null_type& +// +#elif __TBB_VARIADIC_MAX == 8 +#define __TBB_T_PACK ,T5, T6, T7 +#define __TBB_U_PACK ,U5, U6, U7 +#define __TBB_CLASS_T_PACK , class T5 , class T6, class T7 +#define __TBB_CLASS_U_PACK , class U5 , class U6, class U7 +#define __TBB_NULL_TYPE_PACK , null_type, null_type, null_type +#define __TBB_REF_T_PARAM_PACK ,T5& t5, T6& t6, T7& t7 +#define __TBB_CONST_REF_T_PARAM_PACK , const T5& t5, const T6& t6, const T7& t7 +#define __TBB_T_PARAM_LIST_PACK ,t5 ,t6 ,t7 +#define __TBB_CONST_NULL_REF_PACK , const null_type&, const null_type&, const null_type& +// +#elif __TBB_VARIADIC_MAX == 9 +#define __TBB_T_PACK ,T5, T6, T7, T8 +#define __TBB_U_PACK ,U5, U6, U7, U8 +#define __TBB_CLASS_T_PACK , class T5, class T6, class T7, class T8 +#define __TBB_CLASS_U_PACK , class U5, class U6, class U7, class U8 +#define __TBB_NULL_TYPE_PACK , null_type, null_type, null_type, null_type +#define __TBB_REF_T_PARAM_PACK ,T5& t5, T6& t6, T7& t7, T8& t8 +#define __TBB_CONST_REF_T_PARAM_PACK , const T5& t5, const T6& t6, const T7& t7, const T8& t8 +#define __TBB_T_PARAM_LIST_PACK ,t5 ,t6 ,t7 ,t8 +#define __TBB_CONST_NULL_REF_PACK , const null_type&, const null_type&, const null_type&, const null_type& +// +#elif __TBB_VARIADIC_MAX >= 10 +#define __TBB_T_PACK ,T5, T6, T7, T8, T9 +#define __TBB_U_PACK ,U5, U6, U7, U8, U9 +#define __TBB_CLASS_T_PACK , class T5, class T6, class T7, class T8, class T9 +#define __TBB_CLASS_U_PACK , class U5, class U6, class U7, class U8, class U9 +#define __TBB_NULL_TYPE_PACK , null_type, null_type, null_type, null_type, null_type +#define __TBB_REF_T_PARAM_PACK ,T5& t5, T6& t6, T7& t7, T8& t8, T9& t9 +#define __TBB_CONST_REF_T_PARAM_PACK , const T5& t5, const T6& t6, const T7& t7, const T8& t8, const T9& t9 +#define __TBB_T_PARAM_LIST_PACK ,t5 ,t6 ,t7 ,t8 ,t9 +#define __TBB_CONST_NULL_REF_PACK , const null_type&, const null_type&, const null_type&, const null_type&, const null_type& +#endif + + + +namespace tbb { +namespace interface5 { +namespace internal { +struct null_type { }; +} +using internal::null_type; + +// tuple forward declaration +template = 6 +, class T5=null_type +#if __TBB_VARIADIC_MAX >= 7 +, class T6=null_type +#if __TBB_VARIADIC_MAX >= 8 +, class T7=null_type +#if __TBB_VARIADIC_MAX >= 9 +, class T8=null_type +#if __TBB_VARIADIC_MAX >= 10 +, class T9=null_type +#endif +#endif +#endif +#endif +#endif +> +class tuple; + +namespace internal { + +// const null_type temp +inline const null_type cnull() { return null_type(); } + +// cons forward declaration +template struct cons; + +// type of a component of the cons +template +struct component { + typedef typename T::tail_type next; + typedef typename component::type type; +}; + +template +struct component<0,T> { + typedef typename T::head_type type; +}; + +template<> +struct component<0,null_type> { + typedef null_type type; +}; + +// const version of component + +template +struct component +{ + typedef typename T::tail_type next; + typedef const typename component::type type; +}; + +template +struct component<0, const T> +{ + typedef const typename T::head_type type; +}; + + +// helper class for getting components of cons +template< int N> +struct get_helper { +template +inline static typename component >::type& get(cons& ti) { + return get_helper::get(ti.tail); +} +template +inline static typename component >::type const& get(const cons& ti) { + return get_helper::get(ti.tail); +} +}; + +template<> +struct get_helper<0> { +template +inline static typename component<0, cons >::type& get(cons& ti) { + return ti.head; +} +template +inline static typename component<0, cons >::type const& get(const cons& ti) { + return ti.head; +} +}; + +// traits adaptor +template +struct tuple_traits { + typedef cons ::U > U; +}; + +template <> +struct tuple_traits { + typedef cons U; +}; + +template<> +struct tuple_traits { + typedef null_type U; +}; + + +// core cons defs +template +struct cons{ + + typedef HT head_type; + typedef TT tail_type; + + HT head; + TT tail; + + static const int length = 1 + tail_type::length; + + // default constructors + explicit cons() : head(), tail() { } + + // non-default constructors + cons(head_type& h, const tail_type& t) : head(h), tail(t) { } + + template + cons(const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4 __TBB_CONST_REF_T_PARAM_PACK) : + head(t0), tail(t1, t2, t3, t4 __TBB_T_PARAM_LIST_PACK, cnull()) { } + + template + cons(T0& t0, T1& t1, T2& t2, T3& t3, T4& t4 __TBB_REF_T_PARAM_PACK) : + head(t0), tail(t1, t2, t3, t4 __TBB_T_PARAM_LIST_PACK , cnull()) { } + + template + cons(const cons& other) : head(other.head), tail(other.tail) { } + + cons& operator=(const cons& other) { head = other.head; tail = other.tail; return *this; } + + friend bool operator==(const cons& me, const cons& other) { + return me.head == other.head && me.tail == other.tail; + } + friend bool operator<(const cons& me, const cons& other) { + return me.head < other.head || (!(other.head < me.head) && me.tail < other.tail); + } + friend bool operator>(const cons& me, const cons& other) { return other=(const cons& me, const cons& other) { return !(meother); } + + template + friend bool operator==(const cons& me, const cons& other) { + return me.head == other.head && me.tail == other.tail; + } + + template + friend bool operator<(const cons& me, const cons& other) { + return me.head < other.head || (!(other.head < me.head) && me.tail < other.tail); + } + + template + friend bool operator>(const cons& me, const cons& other) { return other + friend bool operator!=(const cons& me, const cons& other) { return !(me==other); } + + template + friend bool operator>=(const cons& me, const cons& other) { return !(me + friend bool operator<=(const cons& me, const cons& other) { return !(me>other); } + + +}; // cons + + +template +struct cons { + + typedef HT head_type; + typedef null_type tail_type; + static const int length = 1; + head_type head; + + // default constructor + cons() : head() { /*std::cout << "default constructor 1\n";*/ } + + cons(const null_type&, const null_type&, const null_type&, const null_type&, const null_type& __TBB_CONST_NULL_REF_PACK) : head() { /*std::cout << "default constructor 2\n";*/ } + + // non-default constructor + template + cons(T1& t1, const null_type&, const null_type&, const null_type&, const null_type& __TBB_CONST_NULL_REF_PACK) : head(t1) { /*std::cout << "non-default a1, t1== " << t1 << "\n";*/} + + cons(head_type& h, const null_type& = null_type() ) : head(h) { } + cons(const head_type& t0, const null_type&, const null_type&, const null_type&, const null_type& __TBB_CONST_NULL_REF_PACK) : head(t0) { } + + // converting constructor + template + cons(HT1 h1, const null_type&, const null_type&, const null_type&, const null_type& __TBB_CONST_NULL_REF_PACK) : head(h1) { } + + // copy constructor + template + cons( const cons& other) : head(other.head) { } + + // assignment operator + cons& operator=(const cons& other) { head = other.head; return *this; } + + friend bool operator==(const cons& me, const cons& other) { return me.head == other.head; } + friend bool operator<(const cons& me, const cons& other) { return me.head < other.head; } + friend bool operator>(const cons& me, const cons& other) { return otherother); } + friend bool operator>=(const cons& me, const cons& other) {return !(me + friend bool operator==(const cons& me, const cons& other) { + return me.head == other.head; + } + + template + friend bool operator<(const cons& me, const cons& other) { + return me.head < other.head; + } + + template + friend bool operator>(const cons& me, const cons& other) { return other + friend bool operator!=(const cons& me, const cons& other) { return !(me==other); } + + template + friend bool operator<=(const cons& me, const cons& other) { return !(me>other); } + + template + friend bool operator>=(const cons& me, const cons& other) { return !(me +struct cons { typedef null_type tail_type; static const int length = 0; }; + +// wrapper for default constructor +template +inline const T wrap_dcons(T*) { return T(); } +} // namespace internal + +// tuple definition +template +class tuple : public internal::tuple_traits::U { + // friends + template friend class tuple_size; + template friend struct tuple_element; + + // stl components + typedef tuple value_type; + typedef value_type *pointer; + typedef const value_type *const_pointer; + typedef value_type &reference; + typedef const value_type &const_reference; + typedef size_t size_type; + + typedef typename internal::tuple_traits::U my_cons; +public: + + tuple(const T0& t0=internal::wrap_dcons((T0*)NULL) + ,const T1& t1=internal::wrap_dcons((T1*)NULL) + ,const T2& t2=internal::wrap_dcons((T2*)NULL) + ,const T3& t3=internal::wrap_dcons((T3*)NULL) + ,const T4& t4=internal::wrap_dcons((T4*)NULL) +#if __TBB_VARIADIC_MAX >= 6 + ,const T5& t5=internal::wrap_dcons((T5*)NULL) +#if __TBB_VARIADIC_MAX >= 7 + ,const T6& t6=internal::wrap_dcons((T6*)NULL) +#if __TBB_VARIADIC_MAX >= 8 + ,const T7& t7=internal::wrap_dcons((T7*)NULL) +#if __TBB_VARIADIC_MAX >= 9 + ,const T8& t8=internal::wrap_dcons((T8*)NULL) +#if __TBB_VARIADIC_MAX >= 10 + ,const T9& t9=internal::wrap_dcons((T9*)NULL) +#endif +#endif +#endif +#endif +#endif + ) : + internal::tuple_traits::U(t0,t1,t2,t3,t4 __TBB_T_PARAM_LIST_PACK) { } + + template + struct internal_tuple_element { + typedef typename internal::component::type type; + }; + + template + typename internal_tuple_element::type& get() { return internal::get_helper::get(*this); } + + template + typename internal_tuple_element::type const& get() const { return internal::get_helper::get(*this); } + + template + tuple& operator=(const internal::cons& other) { + my_cons::operator=(other); + return *this; + } + + template + tuple& operator=(const std::pair& other) { + // __TBB_ASSERT(tuple_size::value == 2, "Invalid size for pair to tuple assignment"); + this->head = other.first; + this->tail.head = other.second; + return *this; + } + + friend bool operator==(const tuple& me, const tuple& other) {return static_cast(me)==(other);} + friend bool operator<(const tuple& me, const tuple& other) {return static_cast(me)<(other);} + friend bool operator>(const tuple& me, const tuple& other) {return static_cast(me)>(other);} + friend bool operator!=(const tuple& me, const tuple& other) {return static_cast(me)!=(other);} + friend bool operator>=(const tuple& me, const tuple& other) {return static_cast(me)>=(other);} + friend bool operator<=(const tuple& me, const tuple& other) {return static_cast(me)<=(other);} + + template + friend bool operator==(const tuple& me, const tuple& other) { + return static_cast(me)==(other); + } + + template + friend bool operator<(const tuple& me, const tuple& other) { + return static_cast(me)<(other); + } + + template + friend bool operator>(const tuple& me, const tuple& other) { + return static_cast(me)>(other); + } + + template + friend bool operator!=(const tuple& me, const tuple& other) { + return static_cast(me)!=(other); + } + + template + friend bool operator>=(const tuple& me, const tuple& other) { + return static_cast(me)>=(other); + } + + template + friend bool operator<=(const tuple& me, const tuple& other) { + return static_cast(me)<=(other); + } + +}; // tuple + +// empty tuple +template<> +class tuple : public null_type { + typedef null_type inherited; +}; + +// helper classes + +template < class T> +class tuple_size { +public: + static const size_t value = 1 + tuple_size::value; +}; + +template <> +class tuple_size > { +public: + static const size_t value = 0; +}; + +template <> +class tuple_size { +public: + static const size_t value = 0; +}; + +template +struct tuple_element { + typedef typename internal::component::type type; +}; + +template +inline static typename tuple_element >::type& + get(tuple& t) { return t.get(); } + +template +inline static typename tuple_element >::type const& + get(const tuple& t) { return t.get(); } + +} // interface5 +} // tbb + +#if TBB_IMPLEMENT_CPP0X +namespace std { +using tbb::interface5::tuple; +using tbb::interface5::tuple_size; +using tbb::interface5::tuple_element; +using tbb::interface5::get; +} +#endif + +#undef __TBB_T_PACK +#undef __TBB_U_PACK +#undef __TBB_CLASS_T_PACK +#undef __TBB_CLASS_U_PACK +#undef __TBB_NULL_TYPE_PACK +#undef __TBB_REF_T_PARAM_PACK +#undef __TBB_CONST_REF_T_PARAM_PACK +#undef __TBB_T_PARAM_LIST_PACK +#undef __TBB_CONST_NULL_REF_PACK + +#endif /* __TBB_tuple_H */ diff --git a/src/tbb/include/tbb/concurrent_hash_map.h b/src/tbb/include/tbb/concurrent_hash_map.h new file mode 100644 index 0000000..d12ceb3 --- /dev/null +++ b/src/tbb/include/tbb/concurrent_hash_map.h @@ -0,0 +1,1336 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_concurrent_hash_map_H +#define __TBB_concurrent_hash_map_H + +#include "tbb_stddef.h" + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include +#include // Need std::pair +#include // Need std::memset + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +#include "cache_aligned_allocator.h" +#include "tbb_allocator.h" +#include "spin_rw_mutex.h" +#include "atomic.h" +#include "aligned_space.h" +#include "tbb_exception.h" +#include "tbb_profiling.h" +#include "internal/_concurrent_unordered_impl.h" // Need tbb_hasher +#if TBB_USE_PERFORMANCE_WARNINGS || __TBB_STATISTICS +#include +#endif +#if __TBB_STATISTICS +#include +#endif + +namespace tbb { + +//! hash_compare that is default argument for concurrent_hash_map +template +struct tbb_hash_compare { + static size_t hash( const Key& a ) { return tbb_hasher(a); } + static bool equal( const Key& a, const Key& b ) { return a == b; } +}; + +namespace interface5 { + + template, typename A = tbb_allocator > > + class concurrent_hash_map; + + //! @cond INTERNAL + namespace internal { + + + //! Type of a hash code. + typedef size_t hashcode_t; + //! Node base type + struct hash_map_node_base : tbb::internal::no_copy { + //! Mutex type + typedef spin_rw_mutex mutex_t; + //! Scoped lock type for mutex + typedef mutex_t::scoped_lock scoped_t; + //! Next node in chain + hash_map_node_base *next; + mutex_t mutex; + }; + //! Incompleteness flag value + static hash_map_node_base *const rehash_req = reinterpret_cast(size_t(3)); + //! Rehashed empty bucket flag + static hash_map_node_base *const empty_rehashed = reinterpret_cast(size_t(0)); + //! base class of concurrent_hash_map + class hash_map_base { + public: + //! Size type + typedef size_t size_type; + //! Type of a hash code. + typedef size_t hashcode_t; + //! Segment index type + typedef size_t segment_index_t; + //! Node base type + typedef hash_map_node_base node_base; + //! Bucket type + struct bucket : tbb::internal::no_copy { + //! Mutex type for buckets + typedef spin_rw_mutex mutex_t; + //! Scoped lock type for mutex + typedef mutex_t::scoped_lock scoped_t; + mutex_t mutex; + node_base *node_list; + }; + //! Count of segments in the first block + static size_type const embedded_block = 1; + //! Count of segments in the first block + static size_type const embedded_buckets = 1< my_mask; + //! Segment pointers table. Also prevents false sharing between my_mask and my_size + segments_table_t my_table; + //! Size of container in stored items + atomic my_size; // It must be in separate cache line from my_mask due to performance effects + //! Zero segment + bucket my_embedded_segment[embedded_buckets]; +#if __TBB_STATISTICS + atomic my_info_resizes; // concurrent ones + mutable atomic my_info_restarts; // race collisions + atomic my_info_rehashes; // invocations of rehash_bucket +#endif + //! Constructor + hash_map_base() { + std::memset( this, 0, pointers_per_table*sizeof(segment_ptr_t) // 32*4=128 or 64*8=512 + + sizeof(my_size) + sizeof(my_mask) // 4+4 or 8+8 + + embedded_buckets*sizeof(bucket) ); // n*8 or n*16 + for( size_type i = 0; i < embedded_block; i++ ) // fill the table + my_table[i] = my_embedded_segment + segment_base(i); + my_mask = embedded_buckets - 1; + __TBB_ASSERT( embedded_block <= first_block, "The first block number must include embedded blocks"); +#if __TBB_STATISTICS + my_info_resizes = 0; // concurrent ones + my_info_restarts = 0; // race collisions + my_info_rehashes = 0; // invocations of rehash_bucket +#endif + } + + //! @return segment index of given index in the array + static segment_index_t segment_index_of( size_type index ) { + return segment_index_t( __TBB_Log2( index|1 ) ); + } + + //! @return the first array index of given segment + static segment_index_t segment_base( segment_index_t k ) { + return (segment_index_t(1)<(ptr) > uintptr_t(63); + } + + //! Initialize buckets + static void init_buckets( segment_ptr_t ptr, size_type sz, bool is_initial ) { + if( is_initial ) std::memset(ptr, 0, sz*sizeof(bucket) ); + else for(size_type i = 0; i < sz; i++, ptr++) { + *reinterpret_cast(&ptr->mutex) = 0; + ptr->node_list = rehash_req; + } + } + + //! Add node @arg n to bucket @arg b + static void add_to_bucket( bucket *b, node_base *n ) { + __TBB_ASSERT(b->node_list != rehash_req, NULL); + n->next = b->node_list; + b->node_list = n; // its under lock and flag is set + } + + //! Exception safety helper + struct enable_segment_failsafe : tbb::internal::no_copy { + segment_ptr_t *my_segment_ptr; + enable_segment_failsafe(segments_table_t &table, segment_index_t k) : my_segment_ptr(&table[k]) {} + ~enable_segment_failsafe() { + if( my_segment_ptr ) *my_segment_ptr = 0; // indicate no allocation in progress + } + }; + + //! Enable segment + void enable_segment( segment_index_t k, bool is_initial = false ) { + __TBB_ASSERT( k, "Zero segment must be embedded" ); + enable_segment_failsafe watchdog( my_table, k ); + cache_aligned_allocator alloc; + size_type sz; + __TBB_ASSERT( !is_valid(my_table[k]), "Wrong concurrent assignment"); + if( k >= first_block ) { + sz = segment_size( k ); + segment_ptr_t ptr = alloc.allocate( sz ); + init_buckets( ptr, sz, is_initial ); + itt_hide_store_word( my_table[k], ptr ); + sz <<= 1;// double it to get entire capacity of the container + } else { // the first block + __TBB_ASSERT( k == embedded_block, "Wrong segment index" ); + sz = segment_size( first_block ); + segment_ptr_t ptr = alloc.allocate( sz - embedded_buckets ); + init_buckets( ptr, sz - embedded_buckets, is_initial ); + ptr -= segment_base(embedded_block); + for(segment_index_t i = embedded_block; i < first_block; i++) // calc the offsets + itt_hide_store_word( my_table[i], ptr + segment_base(i) ); + } + itt_store_word_with_release( my_mask, sz-1 ); + watchdog.my_segment_ptr = 0; + } + + //! Get bucket by (masked) hashcode + bucket *get_bucket( hashcode_t h ) const throw() { // TODO: add throw() everywhere? + segment_index_t s = segment_index_of( h ); + h -= segment_base(s); + segment_ptr_t seg = my_table[s]; + __TBB_ASSERT( is_valid(seg), "hashcode must be cut by valid mask for allocated segments" ); + return &seg[h]; + } + + // internal serial rehashing helper + void mark_rehashed_levels( hashcode_t h ) throw () { + segment_index_t s = segment_index_of( h ); + while( segment_ptr_t seg = my_table[++s] ) + if( seg[h].node_list == rehash_req ) { + seg[h].node_list = empty_rehashed; + mark_rehashed_levels( h + ((hashcode_t)1<node_list) != rehash_req ) + { +#if __TBB_STATISTICS + my_info_restarts++; // race collisions +#endif + return true; + } + } + return false; + } + + //! Insert a node and check for load factor. @return segment index to enable. + segment_index_t insert_new_node( bucket *b, node_base *n, hashcode_t mask ) { + size_type sz = ++my_size; // prefix form is to enforce allocation after the first item inserted + add_to_bucket( b, n ); + // check load factor + if( sz >= mask ) { // TODO: add custom load_factor + segment_index_t new_seg = __TBB_Log2( mask+1 ); //optimized segment_index_of + __TBB_ASSERT( is_valid(my_table[new_seg-1]), "new allocations must not publish new mask until segment has allocated"); + if( !itt_hide_load_word(my_table[new_seg]) + && __TBB_CompareAndSwapW(&my_table[new_seg], 2, 0) == 0 ) + return new_seg; // The value must be processed + } + return 0; + } + + //! Prepare enough segments for number of buckets + void reserve(size_type buckets) { + if( !buckets-- ) return; + bool is_initial = !my_size; + for( size_type m = my_mask; buckets > m; m = my_mask ) + enable_segment( segment_index_of( m+1 ), is_initial ); + } + //! Swap hash_map_bases + void internal_swap(hash_map_base &table) { + std::swap(this->my_mask, table.my_mask); + std::swap(this->my_size, table.my_size); + for(size_type i = 0; i < embedded_buckets; i++) + std::swap(this->my_embedded_segment[i].node_list, table.my_embedded_segment[i].node_list); + for(size_type i = embedded_block; i < pointers_per_table; i++) + std::swap(this->my_table[i], table.my_table[i]); + } + }; + + template + class hash_map_range; + + //! Meets requirements of a forward iterator for STL */ + /** Value is either the T or const T type of the container. + @ingroup containers */ + template + class hash_map_iterator + : public std::iterator + { + typedef Container map_type; + typedef typename Container::node node; + typedef hash_map_base::node_base node_base; + typedef hash_map_base::bucket bucket; + + template + friend bool operator==( const hash_map_iterator& i, const hash_map_iterator& j ); + + template + friend bool operator!=( const hash_map_iterator& i, const hash_map_iterator& j ); + + template + friend ptrdiff_t operator-( const hash_map_iterator& i, const hash_map_iterator& j ); + + template + friend class hash_map_iterator; + + template + friend class hash_map_range; + + void advance_to_next_bucket() { // TODO?: refactor to iterator_base class + size_t k = my_index+1; + while( my_bucket && k <= my_map->my_mask ) { + // Following test uses 2's-complement wizardry + if( k& (k-2) ) // not the beginning of a segment + ++my_bucket; + else my_bucket = my_map->get_bucket( k ); + my_node = static_cast( my_bucket->node_list ); + if( hash_map_base::is_valid(my_node) ) { + my_index = k; return; + } + ++k; + } + my_bucket = 0; my_node = 0; my_index = k; // the end + } +#if !defined(_MSC_VER) || defined(__INTEL_COMPILER) + template + friend class interface5::concurrent_hash_map; +#else + public: // workaround +#endif + //! concurrent_hash_map over which we are iterating. + const Container *my_map; + + //! Index in hash table for current item + size_t my_index; + + //! Pointer to bucket + const bucket *my_bucket; + + //! Pointer to node that has current item + node *my_node; + + hash_map_iterator( const Container &map, size_t index, const bucket *b, node_base *n ); + + public: + //! Construct undefined iterator + hash_map_iterator() {} + hash_map_iterator( const hash_map_iterator &other ) : + my_map(other.my_map), + my_index(other.my_index), + my_bucket(other.my_bucket), + my_node(other.my_node) + {} + Value& operator*() const { + __TBB_ASSERT( hash_map_base::is_valid(my_node), "iterator uninitialized or at end of container?" ); + return my_node->item; + } + Value* operator->() const {return &operator*();} + hash_map_iterator& operator++(); + + //! Post increment + hash_map_iterator operator++(int) { + hash_map_iterator old(*this); + operator++(); + return old; + } + }; + + template + hash_map_iterator::hash_map_iterator( const Container &map, size_t index, const bucket *b, node_base *n ) : + my_map(&map), + my_index(index), + my_bucket(b), + my_node( static_cast(n) ) + { + if( b && !hash_map_base::is_valid(n) ) + advance_to_next_bucket(); + } + + template + hash_map_iterator& hash_map_iterator::operator++() { + my_node = static_cast( my_node->next ); + if( !my_node ) advance_to_next_bucket(); + return *this; + } + + template + bool operator==( const hash_map_iterator& i, const hash_map_iterator& j ) { + return i.my_node == j.my_node && i.my_map == j.my_map; + } + + template + bool operator!=( const hash_map_iterator& i, const hash_map_iterator& j ) { + return i.my_node != j.my_node || i.my_map != j.my_map; + } + + //! Range class used with concurrent_hash_map + /** @ingroup containers */ + template + class hash_map_range { + typedef typename Iterator::map_type map_type; + Iterator my_begin; + Iterator my_end; + mutable Iterator my_midpoint; + size_t my_grainsize; + //! Set my_midpoint to point approximately half way between my_begin and my_end. + void set_midpoint() const; + template friend class hash_map_range; + public: + //! Type for size of a range + typedef std::size_t size_type; + typedef typename Iterator::value_type value_type; + typedef typename Iterator::reference reference; + typedef typename Iterator::difference_type difference_type; + typedef Iterator iterator; + + //! True if range is empty. + bool empty() const {return my_begin==my_end;} + + //! True if range can be partitioned into two subranges. + bool is_divisible() const { + return my_midpoint!=my_end; + } + //! Split range. + hash_map_range( hash_map_range& r, split ) : + my_end(r.my_end), + my_grainsize(r.my_grainsize) + { + r.my_end = my_begin = r.my_midpoint; + __TBB_ASSERT( !empty(), "Splitting despite the range is not divisible" ); + __TBB_ASSERT( !r.empty(), "Splitting despite the range is not divisible" ); + set_midpoint(); + r.set_midpoint(); + } + //! type conversion + template + hash_map_range( hash_map_range& r) : + my_begin(r.my_begin), + my_end(r.my_end), + my_midpoint(r.my_midpoint), + my_grainsize(r.my_grainsize) + {} +#if TBB_DEPRECATED + //! Init range with iterators and grainsize specified + hash_map_range( const Iterator& begin_, const Iterator& end_, size_type grainsize_ = 1 ) : + my_begin(begin_), + my_end(end_), + my_grainsize(grainsize_) + { + if(!my_end.my_index && !my_end.my_bucket) // end + my_end.my_index = my_end.my_map->my_mask + 1; + set_midpoint(); + __TBB_ASSERT( grainsize_>0, "grainsize must be positive" ); + } +#endif + //! Init range with container and grainsize specified + hash_map_range( const map_type &map, size_type grainsize_ = 1 ) : + my_begin( Iterator( map, 0, map.my_embedded_segment, map.my_embedded_segment->node_list ) ), + my_end( Iterator( map, map.my_mask + 1, 0, 0 ) ), + my_grainsize( grainsize_ ) + { + __TBB_ASSERT( grainsize_>0, "grainsize must be positive" ); + set_midpoint(); + } + const Iterator& begin() const {return my_begin;} + const Iterator& end() const {return my_end;} + //! The grain size for this range. + size_type grainsize() const {return my_grainsize;} + }; + + template + void hash_map_range::set_midpoint() const { + // Split by groups of nodes + size_t m = my_end.my_index-my_begin.my_index; + if( m > my_grainsize ) { + m = my_begin.my_index + m/2u; + hash_map_base::bucket *b = my_begin.my_map->get_bucket(m); + my_midpoint = Iterator(*my_begin.my_map,m,b,b->node_list); + } else { + my_midpoint = my_end; + } + __TBB_ASSERT( my_begin.my_index <= my_midpoint.my_index, + "my_begin is after my_midpoint" ); + __TBB_ASSERT( my_midpoint.my_index <= my_end.my_index, + "my_midpoint is after my_end" ); + __TBB_ASSERT( my_begin != my_midpoint || my_begin == my_end, + "[my_begin, my_midpoint) range should not be empty" ); + } + + } // internal +//! @endcond + +//! Unordered map from Key to T. +/** concurrent_hash_map is associative container with concurrent access. + +@par Compatibility + The class meets all Container Requirements from C++ Standard (See ISO/IEC 14882:2003(E), clause 23.1). + +@par Exception Safety + - Hash function is not permitted to throw an exception. User-defined types Key and T are forbidden from throwing an exception in destructors. + - If exception happens during insert() operations, it has no effect (unless exception raised by HashCompare::hash() function during grow_segment). + - If exception happens during operator=() operation, the container can have a part of source items, and methods size() and empty() can return wrong results. + +@par Changes since TBB 2.1 + - Replaced internal algorithm and data structure. Patent is pending. + - Added buckets number argument for constructor + +@par Changes since TBB 2.0 + - Fixed exception-safety + - Added template argument for allocator + - Added allocator argument in constructors + - Added constructor from a range of iterators + - Added several new overloaded insert() methods + - Added get_allocator() + - Added swap() + - Added count() + - Added overloaded erase(accessor &) and erase(const_accessor&) + - Added equal_range() [const] + - Added [const_]pointer, [const_]reference, and allocator_type types + - Added global functions: operator==(), operator!=(), and swap() + + @ingroup containers */ +template +class concurrent_hash_map : protected internal::hash_map_base { + template + friend class internal::hash_map_iterator; + + template + friend class internal::hash_map_range; + +public: + typedef Key key_type; + typedef T mapped_type; + typedef std::pair value_type; + typedef hash_map_base::size_type size_type; + typedef ptrdiff_t difference_type; + typedef value_type *pointer; + typedef const value_type *const_pointer; + typedef value_type &reference; + typedef const value_type &const_reference; + typedef internal::hash_map_iterator iterator; + typedef internal::hash_map_iterator const_iterator; + typedef internal::hash_map_range range_type; + typedef internal::hash_map_range const_range_type; + typedef Allocator allocator_type; + +protected: + friend class const_accessor; + struct node; + typedef typename Allocator::template rebind::other node_allocator_type; + node_allocator_type my_allocator; + HashCompare my_hash_compare; + + struct node : public node_base { + value_type item; + node( const Key &key ) : item(key, T()) {} + node( const Key &key, const T &t ) : item(key, t) {} + // exception-safe allocation, see C++ Standard 2003, clause 5.3.4p17 + void *operator new( size_t /*size*/, node_allocator_type &a ) { + void *ptr = a.allocate(1); + if(!ptr) + tbb::internal::throw_exception(tbb::internal::eid_bad_alloc); + return ptr; + } + // match placement-new form above to be called if exception thrown in constructor + void operator delete( void *ptr, node_allocator_type &a ) {return a.deallocate(static_cast(ptr),1); } + }; + + void delete_node( node_base *n ) { + my_allocator.destroy( static_cast(n) ); + my_allocator.deallocate( static_cast(n), 1); + } + + node *search_bucket( const key_type &key, bucket *b ) const { + node *n = static_cast( b->node_list ); + while( is_valid(n) && !my_hash_compare.equal(key, n->item.first) ) + n = static_cast( n->next ); + __TBB_ASSERT(n != internal::rehash_req, "Search can be executed only for rehashed bucket"); + return n; + } + + //! bucket accessor is to find, rehash, acquire a lock, and access a bucket + class bucket_accessor : public bucket::scoped_t { + bucket *my_b; + public: + bucket_accessor( concurrent_hash_map *base, const hashcode_t h, bool writer = false ) { acquire( base, h, writer ); } + //! find a bucket by masked hashcode, optionally rehash, and acquire the lock + inline void acquire( concurrent_hash_map *base, const hashcode_t h, bool writer = false ) { + my_b = base->get_bucket( h ); + // TODO: actually, notification is unnecessary here, just hiding double-check + if( itt_load_word_with_acquire(my_b->node_list) == internal::rehash_req + && try_acquire( my_b->mutex, /*write=*/true ) ) + { + if( my_b->node_list == internal::rehash_req ) base->rehash_bucket( my_b, h ); //recursive rehashing + } + else bucket::scoped_t::acquire( my_b->mutex, writer ); + __TBB_ASSERT( my_b->node_list != internal::rehash_req, NULL); + } + //! check whether bucket is locked for write + bool is_writer() { return bucket::scoped_t::is_writer; } + //! get bucket pointer + bucket *operator() () { return my_b; } + }; + + // TODO refactor to hash_base + void rehash_bucket( bucket *b_new, const hashcode_t h ) { + __TBB_ASSERT( *(intptr_t*)(&b_new->mutex), "b_new must be locked (for write)"); + __TBB_ASSERT( h > 1, "The lowermost buckets can't be rehashed" ); + __TBB_store_with_release(b_new->node_list, internal::empty_rehashed); // mark rehashed + hashcode_t mask = ( 1u<<__TBB_Log2( h ) ) - 1; // get parent mask from the topmost bit +#if __TBB_STATISTICS + my_info_rehashes++; // invocations of rehash_bucket +#endif + + bucket_accessor b_old( this, h & mask ); + + mask = (mask<<1) | 1; // get full mask for new bucket + __TBB_ASSERT( (mask&(mask+1))==0 && (h & mask) == h, NULL ); + restart: + for( node_base **p = &b_old()->node_list, *n = __TBB_load_with_acquire(*p); is_valid(n); n = *p ) { + hashcode_t c = my_hash_compare.hash( static_cast(n)->item.first ); +#if TBB_USE_ASSERT + hashcode_t bmask = h & (mask>>1); + bmask = bmask==0? 1 : ( 1u<<(__TBB_Log2( bmask )+1 ) ) - 1; // minimal mask of parent bucket + __TBB_ASSERT( (c & bmask) == (h & bmask), "hash() function changed for key in table" ); +#endif + if( (c & mask) == h ) { + if( !b_old.is_writer() ) + if( !b_old.upgrade_to_writer() ) { + goto restart; // node ptr can be invalid due to concurrent erase + } + *p = n->next; // exclude from b_old + add_to_bucket( b_new, n ); + } else p = &n->next; // iterate to next item + } + } + +public: + + class accessor; + //! Combines data access, locking, and garbage collection. + class const_accessor : private node::scoped_t /*which derived from no_copy*/ { + friend class concurrent_hash_map; + friend class accessor; + public: + //! Type of value + typedef const typename concurrent_hash_map::value_type value_type; + + //! True if result is empty. + bool empty() const {return !my_node;} + + //! Set to null + void release() { + if( my_node ) { + node::scoped_t::release(); + my_node = 0; + } + } + + //! Return reference to associated value in hash table. + const_reference operator*() const { + __TBB_ASSERT( my_node, "attempt to dereference empty accessor" ); + return my_node->item; + } + + //! Return pointer to associated value in hash table. + const_pointer operator->() const { + return &operator*(); + } + + //! Create empty result + const_accessor() : my_node(NULL) {} + + //! Destroy result after releasing the underlying reference. + ~const_accessor() { + my_node = NULL; // scoped lock's release() is called in its destructor + } + protected: + bool is_writer() { return node::scoped_t::is_writer; } + node *my_node; + hashcode_t my_hash; + }; + + //! Allows write access to elements and combines data access, locking, and garbage collection. + class accessor: public const_accessor { + public: + //! Type of value + typedef typename concurrent_hash_map::value_type value_type; + + //! Return reference to associated value in hash table. + reference operator*() const { + __TBB_ASSERT( this->my_node, "attempt to dereference empty accessor" ); + return this->my_node->item; + } + + //! Return pointer to associated value in hash table. + pointer operator->() const { + return &operator*(); + } + }; + + //! Construct empty table. + concurrent_hash_map(const allocator_type &a = allocator_type()) + : internal::hash_map_base(), my_allocator(a) + {} + + //! Construct empty table with n preallocated buckets. This number serves also as initial concurrency level. + concurrent_hash_map(size_type n, const allocator_type &a = allocator_type()) + : my_allocator(a) + { + reserve( n ); + } + + //! Copy constructor + concurrent_hash_map( const concurrent_hash_map& table, const allocator_type &a = allocator_type()) + : internal::hash_map_base(), my_allocator(a) + { + internal_copy(table); + } + + //! Construction with copying iteration range and given allocator instance + template + concurrent_hash_map(I first, I last, const allocator_type &a = allocator_type()) + : my_allocator(a) + { + reserve( std::distance(first, last) ); // TODO: load_factor? + internal_copy(first, last); + } + + //! Assignment + concurrent_hash_map& operator=( const concurrent_hash_map& table ) { + if( this!=&table ) { + clear(); + internal_copy(table); + } + return *this; + } + + + //! Rehashes and optionally resizes the whole table. + /** Useful to optimize performance before or after concurrent operations. + Also enables using of find() and count() concurrent methods in serial context. */ + void rehash(size_type n = 0); + + //! Clear table + void clear(); + + //! Clear table and destroy it. + ~concurrent_hash_map() { clear(); } + + //------------------------------------------------------------------------ + // Parallel algorithm support + //------------------------------------------------------------------------ + range_type range( size_type grainsize=1 ) { + return range_type( *this, grainsize ); + } + const_range_type range( size_type grainsize=1 ) const { + return const_range_type( *this, grainsize ); + } + + //------------------------------------------------------------------------ + // STL support - not thread-safe methods + //------------------------------------------------------------------------ + iterator begin() {return iterator(*this,0,my_embedded_segment,my_embedded_segment->node_list);} + iterator end() {return iterator(*this,0,0,0);} + const_iterator begin() const {return const_iterator(*this,0,my_embedded_segment,my_embedded_segment->node_list);} + const_iterator end() const {return const_iterator(*this,0,0,0);} + std::pair equal_range( const Key& key ) { return internal_equal_range(key, end()); } + std::pair equal_range( const Key& key ) const { return internal_equal_range(key, end()); } + + //! Number of items in table. + size_type size() const { return my_size; } + + //! True if size()==0. + bool empty() const { return my_size == 0; } + + //! Upper bound on size. + size_type max_size() const {return (~size_type(0))/sizeof(node);} + + //! Returns the current number of buckets + size_type bucket_count() const { return my_mask+1; } + + //! return allocator object + allocator_type get_allocator() const { return this->my_allocator; } + + //! swap two instances. Iterators are invalidated + void swap(concurrent_hash_map &table); + + //------------------------------------------------------------------------ + // concurrent map operations + //------------------------------------------------------------------------ + + //! Return count of items (0 or 1) + size_type count( const Key &key ) const { + return const_cast(this)->lookup(/*insert*/false, key, NULL, NULL, /*write=*/false ); + } + + //! Find item and acquire a read lock on the item. + /** Return true if item is found, false otherwise. */ + bool find( const_accessor &result, const Key &key ) const { + result.release(); + return const_cast(this)->lookup(/*insert*/false, key, NULL, &result, /*write=*/false ); + } + + //! Find item and acquire a write lock on the item. + /** Return true if item is found, false otherwise. */ + bool find( accessor &result, const Key &key ) { + result.release(); + return lookup(/*insert*/false, key, NULL, &result, /*write=*/true ); + } + + //! Insert item (if not already present) and acquire a read lock on the item. + /** Returns true if item is new. */ + bool insert( const_accessor &result, const Key &key ) { + result.release(); + return lookup(/*insert*/true, key, NULL, &result, /*write=*/false ); + } + + //! Insert item (if not already present) and acquire a write lock on the item. + /** Returns true if item is new. */ + bool insert( accessor &result, const Key &key ) { + result.release(); + return lookup(/*insert*/true, key, NULL, &result, /*write=*/true ); + } + + //! Insert item by copying if there is no such key present already and acquire a read lock on the item. + /** Returns true if item is new. */ + bool insert( const_accessor &result, const value_type &value ) { + result.release(); + return lookup(/*insert*/true, value.first, &value.second, &result, /*write=*/false ); + } + + //! Insert item by copying if there is no such key present already and acquire a write lock on the item. + /** Returns true if item is new. */ + bool insert( accessor &result, const value_type &value ) { + result.release(); + return lookup(/*insert*/true, value.first, &value.second, &result, /*write=*/true ); + } + + //! Insert item by copying if there is no such key present already + /** Returns true if item is inserted. */ + bool insert( const value_type &value ) { + return lookup(/*insert*/true, value.first, &value.second, NULL, /*write=*/false ); + } + + //! Insert range [first, last) + template + void insert(I first, I last) { + for(; first != last; ++first) + insert( *first ); + } + + //! Erase item. + /** Return true if item was erased by particularly this call. */ + bool erase( const Key& key ); + + //! Erase item by const_accessor. + /** Return true if item was erased by particularly this call. */ + bool erase( const_accessor& item_accessor ) { + return exclude( item_accessor ); + } + + //! Erase item by accessor. + /** Return true if item was erased by particularly this call. */ + bool erase( accessor& item_accessor ) { + return exclude( item_accessor ); + } + +protected: + //! Insert or find item and optionally acquire a lock on the item. + bool lookup( bool op_insert, const Key &key, const T *t, const_accessor *result, bool write ); + + //! delete item by accessor + bool exclude( const_accessor &item_accessor ); + + //! Returns an iterator for an item defined by the key, or for the next item after it (if upper==true) + template + std::pair internal_equal_range( const Key& key, I end ) const; + + //! Copy "source" to *this, where *this must start out empty. + void internal_copy( const concurrent_hash_map& source ); + + template + void internal_copy(I first, I last); + + //! Fast find when no concurrent erasure is used. For internal use inside TBB only! + /** Return pointer to item with given key, or NULL if no such item exists. + Must not be called concurrently with erasure operations. */ + const_pointer internal_fast_find( const Key& key ) const { + hashcode_t h = my_hash_compare.hash( key ); + hashcode_t m = (hashcode_t) itt_load_word_with_acquire( my_mask ); + node *n; + restart: + __TBB_ASSERT((m&(m+1))==0, NULL); + bucket *b = get_bucket( h & m ); + // TODO: actually, notification is unnecessary here, just hiding double-check + if( itt_load_word_with_acquire(b->node_list) == internal::rehash_req ) + { + bucket::scoped_t lock; + if( lock.try_acquire( b->mutex, /*write=*/true ) ) { + if( b->node_list == internal::rehash_req) + const_cast(this)->rehash_bucket( b, h & m ); //recursive rehashing + } + else lock.acquire( b->mutex, /*write=*/false ); + __TBB_ASSERT(b->node_list!=internal::rehash_req,NULL); + } + n = search_bucket( key, b ); + if( n ) + return &n->item; + else if( check_mask_race( h, m ) ) + goto restart; + return 0; + } +}; + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // Suppress "conditional expression is constant" warning. + #pragma warning( push ) + #pragma warning( disable: 4127 ) +#endif + +template +bool concurrent_hash_map::lookup( bool op_insert, const Key &key, const T *t, const_accessor *result, bool write ) { + __TBB_ASSERT( !result || !result->my_node, NULL ); + bool return_value; + hashcode_t const h = my_hash_compare.hash( key ); + hashcode_t m = (hashcode_t) itt_load_word_with_acquire( my_mask ); + segment_index_t grow_segment = 0; + node *n, *tmp_n = 0; + restart: + {//lock scope + __TBB_ASSERT((m&(m+1))==0, NULL); + return_value = false; + // get bucket + bucket_accessor b( this, h & m ); + + // find a node + n = search_bucket( key, b() ); + if( op_insert ) { + // [opt] insert a key + if( !n ) { + if( !tmp_n ) { + if(t) tmp_n = new( my_allocator ) node(key, *t); + else tmp_n = new( my_allocator ) node(key); + } + if( !b.is_writer() && !b.upgrade_to_writer() ) { // TODO: improved insertion + // Rerun search_list, in case another thread inserted the item during the upgrade. + n = search_bucket( key, b() ); + if( is_valid(n) ) { // unfortunately, it did + b.downgrade_to_reader(); + goto exists; + } + } + if( check_mask_race(h, m) ) + goto restart; // b.release() is done in ~b(). + // insert and set flag to grow the container + grow_segment = insert_new_node( b(), n = tmp_n, m ); + tmp_n = 0; + return_value = true; + } + } else { // find or count + if( !n ) { + if( check_mask_race( h, m ) ) + goto restart; // b.release() is done in ~b(). TODO: replace by continue + return false; + } + return_value = true; + } + exists: + if( !result ) goto check_growth; + // TODO: the following seems as generic/regular operation + // acquire the item + if( !result->try_acquire( n->mutex, write ) ) { + // we are unlucky, prepare for longer wait + tbb::internal::atomic_backoff trials; + do { + if( !trials.bounded_pause() ) { + // the wait takes really long, restart the operation + b.release(); + __TBB_ASSERT( !op_insert || !return_value, "Can't acquire new item in locked bucket?" ); + __TBB_Yield(); + m = (hashcode_t) itt_load_word_with_acquire( my_mask ); + goto restart; + } + } while( !result->try_acquire( n->mutex, write ) ); + } + }//lock scope + result->my_node = n; + result->my_hash = h; +check_growth: + // [opt] grow the container + if( grow_segment ) { +#if __TBB_STATISTICS + my_info_resizes++; // concurrent ones +#endif + enable_segment( grow_segment ); + } + if( tmp_n ) // if op_insert only + delete_node( tmp_n ); + return return_value; +} + +template +template +std::pair concurrent_hash_map::internal_equal_range( const Key& key, I end_ ) const { + hashcode_t h = my_hash_compare.hash( key ); + hashcode_t m = my_mask; + __TBB_ASSERT((m&(m+1))==0, NULL); + h &= m; + bucket *b = get_bucket( h ); + while( b->node_list == internal::rehash_req ) { + m = ( 1u<<__TBB_Log2( h ) ) - 1; // get parent mask from the topmost bit + b = get_bucket( h &= m ); + } + node *n = search_bucket( key, b ); + if( !n ) + return std::make_pair(end_, end_); + iterator lower(*this, h, b, n), upper(lower); + return std::make_pair(lower, ++upper); +} + +template +bool concurrent_hash_map::exclude( const_accessor &item_accessor ) { + __TBB_ASSERT( item_accessor.my_node, NULL ); + node_base *const n = item_accessor.my_node; + hashcode_t const h = item_accessor.my_hash; + hashcode_t m = (hashcode_t) itt_load_word_with_acquire( my_mask ); + do { + // get bucket + bucket_accessor b( this, h & m, /*writer=*/true ); + node_base **p = &b()->node_list; + while( *p && *p != n ) + p = &(*p)->next; + if( !*p ) { // someone else was first + if( check_mask_race( h, m ) ) + continue; + item_accessor.release(); + return false; + } + __TBB_ASSERT( *p == n, NULL ); + *p = n->next; // remove from container + my_size--; + break; + } while(true); + if( !item_accessor.is_writer() ) // need to get exclusive lock + item_accessor.upgrade_to_writer(); // return value means nothing here + item_accessor.release(); + delete_node( n ); // Only one thread can delete it + return true; +} + +template +bool concurrent_hash_map::erase( const Key &key ) { + node_base *n; + hashcode_t const h = my_hash_compare.hash( key ); + hashcode_t m = (hashcode_t) itt_load_word_with_acquire( my_mask ); +restart: + {//lock scope + // get bucket + bucket_accessor b( this, h & m ); + search: + node_base **p = &b()->node_list; + n = *p; + while( is_valid(n) && !my_hash_compare.equal(key, static_cast(n)->item.first ) ) { + p = &n->next; + n = *p; + } + if( !n ) { // not found, but mask could be changed + if( check_mask_race( h, m ) ) + goto restart; + return false; + } + else if( !b.is_writer() && !b.upgrade_to_writer() ) { + if( check_mask_race( h, m ) ) // contended upgrade, check mask + goto restart; + goto search; + } + *p = n->next; + my_size--; + } + { + typename node::scoped_t item_locker( n->mutex, /*write=*/true ); + } + // note: there should be no threads pretending to acquire this mutex again, do not try to upgrade const_accessor! + delete_node( n ); // Only one thread can delete it due to write lock on the bucket + return true; +} + +template +void concurrent_hash_map::swap(concurrent_hash_map &table) { + std::swap(this->my_allocator, table.my_allocator); + std::swap(this->my_hash_compare, table.my_hash_compare); + internal_swap(table); +} + +template +void concurrent_hash_map::rehash(size_type sz) { + reserve( sz ); // TODO: add reduction of number of buckets as well + hashcode_t mask = my_mask; + hashcode_t b = (mask+1)>>1; // size or first index of the last segment + __TBB_ASSERT((b&(b-1))==0, NULL); // zero or power of 2 + bucket *bp = get_bucket( b ); // only the last segment should be scanned for rehashing + for(; b <= mask; b++, bp++ ) { + node_base *n = bp->node_list; + __TBB_ASSERT( is_valid(n) || n == internal::empty_rehashed || n == internal::rehash_req, "Broken internal structure" ); + __TBB_ASSERT( *reinterpret_cast(&bp->mutex) == 0, "concurrent or unexpectedly terminated operation during rehash() execution" ); + if( n == internal::rehash_req ) { // rehash bucket, conditional because rehashing of a previous bucket may affect this one + hashcode_t h = b; bucket *b_old = bp; + do { + __TBB_ASSERT( h > 1, "The lowermost buckets can't be rehashed" ); + hashcode_t m = ( 1u<<__TBB_Log2( h ) ) - 1; // get parent mask from the topmost bit + b_old = get_bucket( h &= m ); + } while( b_old->node_list == internal::rehash_req ); + // now h - is index of the root rehashed bucket b_old + mark_rehashed_levels( h ); // mark all non-rehashed children recursively across all segments + for( node_base **p = &b_old->node_list, *q = *p; is_valid(q); q = *p ) { + hashcode_t c = my_hash_compare.hash( static_cast(q)->item.first ); + if( (c & mask) != h ) { // should be rehashed + *p = q->next; // exclude from b_old + bucket *b_new = get_bucket( c & mask ); + __TBB_ASSERT( b_new->node_list != internal::rehash_req, "hash() function changed for key in table or internal error" ); + add_to_bucket( b_new, q ); + } else p = &q->next; // iterate to next item + } + } + } +#if TBB_USE_PERFORMANCE_WARNINGS + int current_size = int(my_size), buckets = int(mask)+1, empty_buckets = 0, overpopulated_buckets = 0; // usage statistics + static bool reported = false; +#endif +#if TBB_USE_ASSERT || TBB_USE_PERFORMANCE_WARNINGS + for( b = 0; b <= mask; b++ ) {// only last segment should be scanned for rehashing + if( b & (b-2) ) ++bp; // not the beginning of a segment + else bp = get_bucket( b ); + node_base *n = bp->node_list; + __TBB_ASSERT( *reinterpret_cast(&bp->mutex) == 0, "concurrent or unexpectedly terminated operation during rehash() execution" ); + __TBB_ASSERT( is_valid(n) || n == internal::empty_rehashed, "Broken internal structure" ); +#if TBB_USE_PERFORMANCE_WARNINGS + if( n == internal::empty_rehashed ) empty_buckets++; + else if( n->next ) overpopulated_buckets++; +#endif +#if TBB_USE_ASSERT + for( ; is_valid(n); n = n->next ) { + hashcode_t h = my_hash_compare.hash( static_cast(n)->item.first ) & mask; + __TBB_ASSERT( h == b, "hash() function changed for key in table or internal error" ); + } +#endif + } +#endif // TBB_USE_ASSERT || TBB_USE_PERFORMANCE_WARNINGS +#if TBB_USE_PERFORMANCE_WARNINGS + if( buckets > current_size) empty_buckets -= buckets - current_size; + else overpopulated_buckets -= current_size - buckets; // TODO: load_factor? + if( !reported && buckets >= 512 && ( 2*empty_buckets > current_size || 2*overpopulated_buckets > current_size ) ) { + tbb::internal::runtime_warning( + "Performance is not optimal because the hash function produces bad randomness in lower bits in %s.\nSize: %d Empties: %d Overlaps: %d", + typeid(*this).name(), current_size, empty_buckets, overpopulated_buckets ); + reported = true; + } +#endif +} + +template +void concurrent_hash_map::clear() { + hashcode_t m = my_mask; + __TBB_ASSERT((m&(m+1))==0, NULL); +#if TBB_USE_ASSERT || TBB_USE_PERFORMANCE_WARNINGS || __TBB_STATISTICS +#if TBB_USE_PERFORMANCE_WARNINGS || __TBB_STATISTICS + int current_size = int(my_size), buckets = int(m)+1, empty_buckets = 0, overpopulated_buckets = 0; // usage statistics + static bool reported = false; +#endif + bucket *bp = 0; + // check consistency + for( segment_index_t b = 0; b <= m; b++ ) { + if( b & (b-2) ) ++bp; // not the beginning of a segment + else bp = get_bucket( b ); + node_base *n = bp->node_list; + __TBB_ASSERT( is_valid(n) || n == internal::empty_rehashed || n == internal::rehash_req, "Broken internal structure" ); + __TBB_ASSERT( *reinterpret_cast(&bp->mutex) == 0, "concurrent or unexpectedly terminated operation during clear() execution" ); +#if TBB_USE_PERFORMANCE_WARNINGS || __TBB_STATISTICS + if( n == internal::empty_rehashed ) empty_buckets++; + else if( n == internal::rehash_req ) buckets--; + else if( n->next ) overpopulated_buckets++; +#endif +#if __TBB_EXTRA_DEBUG + for(; is_valid(n); n = n->next ) { + hashcode_t h = my_hash_compare.hash( static_cast(n)->item.first ); + h &= m; + __TBB_ASSERT( h == b || get_bucket(h)->node_list == internal::rehash_req, "hash() function changed for key in table or internal error" ); + } +#endif + } +#if TBB_USE_PERFORMANCE_WARNINGS || __TBB_STATISTICS +#if __TBB_STATISTICS + printf( "items=%d buckets: capacity=%d rehashed=%d empty=%d overpopulated=%d" + " concurrent: resizes=%u rehashes=%u restarts=%u\n", + current_size, int(m+1), buckets, empty_buckets, overpopulated_buckets, + unsigned(my_info_resizes), unsigned(my_info_rehashes), unsigned(my_info_restarts) ); + my_info_resizes = 0; // concurrent ones + my_info_restarts = 0; // race collisions + my_info_rehashes = 0; // invocations of rehash_bucket +#endif + if( buckets > current_size) empty_buckets -= buckets - current_size; + else overpopulated_buckets -= current_size - buckets; // TODO: load_factor? + if( !reported && buckets >= 512 && ( 2*empty_buckets > current_size || 2*overpopulated_buckets > current_size ) ) { + tbb::internal::runtime_warning( + "Performance is not optimal because the hash function produces bad randomness in lower bits in %s.\nSize: %d Empties: %d Overlaps: %d", + typeid(*this).name(), current_size, empty_buckets, overpopulated_buckets ); + reported = true; + } +#endif +#endif//TBB_USE_ASSERT || TBB_USE_PERFORMANCE_WARNINGS || __TBB_STATISTICS + my_size = 0; + segment_index_t s = segment_index_of( m ); + __TBB_ASSERT( s+1 == pointers_per_table || !my_table[s+1], "wrong mask or concurrent grow" ); + cache_aligned_allocator alloc; + do { + __TBB_ASSERT( is_valid( my_table[s] ), "wrong mask or concurrent grow" ); + segment_ptr_t buckets_ptr = my_table[s]; + size_type sz = segment_size( s ? s : 1 ); + for( segment_index_t i = 0; i < sz; i++ ) + for( node_base *n = buckets_ptr[i].node_list; is_valid(n); n = buckets_ptr[i].node_list ) { + buckets_ptr[i].node_list = n->next; + delete_node( n ); + } + if( s >= first_block) // the first segment or the next + alloc.deallocate( buckets_ptr, sz ); + else if( s == embedded_block && embedded_block != first_block ) + alloc.deallocate( buckets_ptr, segment_size(first_block)-embedded_buckets ); + if( s >= embedded_block ) my_table[s] = 0; + } while(s-- > 0); + my_mask = embedded_buckets - 1; +} + +template +void concurrent_hash_map::internal_copy( const concurrent_hash_map& source ) { + reserve( source.my_size ); // TODO: load_factor? + hashcode_t mask = source.my_mask; + if( my_mask == mask ) { // optimized version + bucket *dst = 0, *src = 0; + bool rehash_required = false; + for( hashcode_t k = 0; k <= mask; k++ ) { + if( k & (k-2) ) ++dst,src++; // not the beginning of a segment + else { dst = get_bucket( k ); src = source.get_bucket( k ); } + __TBB_ASSERT( dst->node_list != internal::rehash_req, "Invalid bucket in destination table"); + node *n = static_cast( src->node_list ); + if( n == internal::rehash_req ) { // source is not rehashed, items are in previous buckets + rehash_required = true; + dst->node_list = internal::rehash_req; + } else for(; n; n = static_cast( n->next ) ) { + add_to_bucket( dst, new( my_allocator ) node(n->item.first, n->item.second) ); + ++my_size; // TODO: replace by non-atomic op + } + } + if( rehash_required ) rehash(); + } else internal_copy( source.begin(), source.end() ); +} + +template +template +void concurrent_hash_map::internal_copy(I first, I last) { + hashcode_t m = my_mask; + for(; first != last; ++first) { + hashcode_t h = my_hash_compare.hash( first->first ); + bucket *b = get_bucket( h & m ); + __TBB_ASSERT( b->node_list != internal::rehash_req, "Invalid bucket in destination table"); + node *n = new( my_allocator ) node(first->first, first->second); + add_to_bucket( b, n ); + ++my_size; // TODO: replace by non-atomic op + } +} + +} // namespace interface5 + +using interface5::concurrent_hash_map; + + +template +inline bool operator==(const concurrent_hash_map &a, const concurrent_hash_map &b) { + if(a.size() != b.size()) return false; + typename concurrent_hash_map::const_iterator i(a.begin()), i_end(a.end()); + typename concurrent_hash_map::const_iterator j, j_end(b.end()); + for(; i != i_end; ++i) { + j = b.equal_range(i->first).first; + if( j == j_end || !(i->second == j->second) ) return false; + } + return true; +} + +template +inline bool operator!=(const concurrent_hash_map &a, const concurrent_hash_map &b) +{ return !(a == b); } + +template +inline void swap(concurrent_hash_map &a, concurrent_hash_map &b) +{ a.swap( b ); } + +#if _MSC_VER && !defined(__INTEL_COMPILER) + #pragma warning( pop ) +#endif // warning 4127 is back + +} // namespace tbb + +#endif /* __TBB_concurrent_hash_map_H */ diff --git a/src/tbb/include/tbb/concurrent_lru_cache.h b/src/tbb/include/tbb/concurrent_lru_cache.h new file mode 100644 index 0000000..a251163 --- /dev/null +++ b/src/tbb/include/tbb/concurrent_lru_cache.h @@ -0,0 +1,238 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_concurrent_lru_cache_H +#define __TBB_concurrent_lru_cache_H + +#if ! TBB_PREVIEW_CONCURRENT_LRU_CACHE + #error Set TBB_PREVIEW_CONCURRENT_LRU_CACHE to include concurrent_lru_cache.h +#endif + +#include +#include + +#include "tbb_stddef.h" +#include "atomic.h" +#include "internal/_aggregator_impl.h" + +namespace tbb{ +namespace interface6 { + + +template +class concurrent_lru_cache : internal::no_assign{ +private: + typedef concurrent_lru_cache self_type; + typedef value_functor_type value_function_type; + typedef std::size_t ref_counter_type; + struct map_value_type; + typedef std::map map_storage_type; + typedef std::list lru_list_type; + struct map_value_type { + value_type my_value; + ref_counter_type my_ref_counter; + typename lru_list_type::iterator my_lru_list_iterator; + bool my_is_ready; + + map_value_type (value_type const& a_value, ref_counter_type a_ref_counter, typename lru_list_type::iterator a_lru_list_iterator, bool a_is_ready) + : my_value(a_value), my_ref_counter(a_ref_counter), my_lru_list_iterator (a_lru_list_iterator), my_is_ready(a_is_ready) + {} + }; + + class handle_object; + + struct aggregator_operation; + typedef aggregator_operation aggregated_operation_type; + typedef tbb::internal::aggregating_functor aggregator_function_type; + friend class tbb::internal::aggregating_functor; + typedef tbb::internal::aggregator aggregator_type; + +private: + value_function_type my_value_function; + std::size_t const my_number_of_lru_history_items; + map_storage_type my_map_storage; + lru_list_type my_lru_list; + aggregator_type my_aggregator; + +public: + typedef handle_object handle; + +public: + concurrent_lru_cache(value_function_type f, std::size_t number_of_lru_history_items) + : my_value_function(f),my_number_of_lru_history_items(number_of_lru_history_items) + { + my_aggregator.initialize_handler(aggregator_function_type(this)); + } + + handle_object operator[](key_type k){ + retrieve_aggregator_operation op(k); + my_aggregator.execute(&op); + if (op.is_new_value_needed()){ + op.result().second.my_value = my_value_function(k); + __TBB_store_with_release(op.result().second.my_is_ready, true); + }else{ + tbb::internal::spin_wait_while_eq(op.result().second.my_is_ready,false); + } + return handle_object(*this,op.result()); + } +private: + void signal_end_of_usage(typename map_storage_type::reference value_ref){ + signal_end_of_usage_aggregator_operation op(value_ref); + my_aggregator.execute(&op); + } + +private: + struct handle_move_t:no_assign{ + concurrent_lru_cache & my_cache_ref; + typename map_storage_type::reference my_map_record_ref; + handle_move_t(concurrent_lru_cache & cache_ref, typename map_storage_type::reference value_ref):my_cache_ref(cache_ref),my_map_record_ref(value_ref) {}; + }; + class handle_object { + concurrent_lru_cache * my_cache_pointer; + typename map_storage_type::reference my_map_record_ref; + public: + handle_object(concurrent_lru_cache & cache_ref, typename map_storage_type::reference value_ref):my_cache_pointer(&cache_ref), my_map_record_ref(value_ref) {} + handle_object(handle_move_t m):my_cache_pointer(&m.my_cache_ref), my_map_record_ref(m.my_map_record_ref){} + operator handle_move_t(){ return move(*this);} + value_type& value(){ + __TBB_ASSERT(my_cache_pointer,"get value from moved from object?"); + return my_map_record_ref.second.my_value; + } + ~handle_object(){ + if (my_cache_pointer){ + my_cache_pointer->signal_end_of_usage(my_map_record_ref); + } + } + private: + friend handle_move_t move(handle_object& h){ + return handle_object::move(h); + } + static handle_move_t move(handle_object& h){ + __TBB_ASSERT(h.my_cache_pointer,"move from the same object twice ?"); + concurrent_lru_cache * cache_pointer = NULL; + std::swap(cache_pointer,h.my_cache_pointer); + return handle_move_t(*cache_pointer,h.my_map_record_ref); + } + private: + void operator=(handle_object&); + handle_object(handle_object &); + }; +private: + //TODO: looks like aggregator_operation is a perfect match for statically typed variant type + struct aggregator_operation : tbb::internal::aggregated_operation{ + enum e_op_type {op_retive, op_signal_end_of_usage}; + //TODO: try to use pointer to function apply_visitor here + //TODO: try virtual functions and measure the difference + e_op_type my_operation_type; + aggregator_operation(e_op_type operation_type): my_operation_type(operation_type) {} + void cast_and_handle(self_type& container ){ + if (my_operation_type==op_retive){ + static_cast(this)->handle(container); + }else{ + static_cast(this)->handle(container); + } + } + }; + struct retrieve_aggregator_operation : aggregator_operation, private internal::no_assign { + key_type my_key; + typename map_storage_type::pointer my_result_map_record_pointer; + bool my_is_new_value_needed; + retrieve_aggregator_operation(key_type key):aggregator_operation(aggregator_operation::op_retive),my_key(key),my_is_new_value_needed(false){} + void handle(self_type& container ){ + my_result_map_record_pointer = & container.retrieve_serial(my_key,my_is_new_value_needed); + } + typename map_storage_type::reference result(){ return * my_result_map_record_pointer; } + bool is_new_value_needed(){return my_is_new_value_needed;} + }; + struct signal_end_of_usage_aggregator_operation : aggregator_operation, private internal::no_assign { + typename map_storage_type::reference my_map_record_ref; + signal_end_of_usage_aggregator_operation(typename map_storage_type::reference map_record_ref):aggregator_operation(aggregator_operation::op_signal_end_of_usage),my_map_record_ref(map_record_ref){} + void handle(self_type& container ){ + container.signal_end_of_usage_serial(my_map_record_ref); + } + }; + +private: + void handle_operations(aggregator_operation* op_list){ + while(op_list){ + op_list->cast_and_handle(*this); + aggregator_operation* tmp = op_list; + op_list=op_list->next; + tbb::internal::itt_store_word_with_release(tmp->status, uintptr_t(1)); + } + } + +private: + typename map_storage_type::reference retrieve_serial(key_type k, bool& is_new_value_needed){ + typename map_storage_type::iterator it = my_map_storage.find(k); + if (it == my_map_storage.end()){ + it = my_map_storage.insert(it,std::make_pair(k,map_value_type(value_type(),0,my_lru_list.end(),false))); + is_new_value_needed = true; + }else { + typename lru_list_type::iterator list_it = it->second.my_lru_list_iterator; + if (list_it!=my_lru_list.end()) { + __TBB_ASSERT(!it->second.my_ref_counter,"item to be evicted should not have a live references"); + //item is going to be used. Therefore it is not a subject for eviction + //so - remove it from LRU history. + my_lru_list.erase(list_it); + it->second.my_lru_list_iterator= my_lru_list.end(); + } + } + ++(it->second.my_ref_counter); + return *it; + } + + void signal_end_of_usage_serial(typename map_storage_type::reference map_record_ref){ + typename map_storage_type::iterator it = my_map_storage.find(map_record_ref.first); + __TBB_ASSERT(it!=my_map_storage.end(),"cache should not return past-end iterators to outer world"); + __TBB_ASSERT(&(*it) == &map_record_ref,"dangling reference has been returned to outside world? data race ?"); + __TBB_ASSERT( my_lru_list.end()== std::find(my_lru_list.begin(),my_lru_list.end(),it), + "object in use should not be in list of unused objects "); + if (! --(it->second.my_ref_counter)){ + //it was the last reference so put it to the LRU history + if (my_lru_list.size()>=my_number_of_lru_history_items){ + //evict items in order to get a space + size_t number_of_elements_to_evict = 1 + my_lru_list.size() - my_number_of_lru_history_items; + for (size_t i=0; isecond.my_ref_counter,"item to be evicted should not have a live references"); + my_lru_list.pop_back(); + my_map_storage.erase(it_to_evict); + } + } + my_lru_list.push_front(it); + it->second.my_lru_list_iterator = my_lru_list.begin(); + } + } +}; +} // namespace interface6 + +using interface6::concurrent_lru_cache; + +} // namespace tbb +#endif //__TBB_concurrent_lru_cache_H diff --git a/src/tbb/include/tbb/concurrent_priority_queue.h b/src/tbb/include/tbb/concurrent_priority_queue.h new file mode 100644 index 0000000..47f40cd --- /dev/null +++ b/src/tbb/include/tbb/concurrent_priority_queue.h @@ -0,0 +1,353 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_concurrent_priority_queue_H +#define __TBB_concurrent_priority_queue_H + +#include "atomic.h" +#include "cache_aligned_allocator.h" +#include "tbb_exception.h" +#include "tbb_stddef.h" +#include "tbb_profiling.h" +#include "internal/_aggregator_impl.h" +#include +#include +#include + +namespace tbb { +namespace interface5 { + +using namespace tbb::internal; + +//! Concurrent priority queue +template , typename A=cache_aligned_allocator > +class concurrent_priority_queue { + public: + //! Element type in the queue. + typedef T value_type; + + //! Reference type + typedef T& reference; + + //! Const reference type + typedef const T& const_reference; + + //! Integral type for representing size of the queue. + typedef size_t size_type; + + //! Difference type for iterator + typedef ptrdiff_t difference_type; + + //! Allocator type + typedef A allocator_type; + + //! Constructs a new concurrent_priority_queue with default capacity + explicit concurrent_priority_queue(const allocator_type& a = allocator_type()) : mark(0), my_size(0), data(a) + { + my_aggregator.initialize_handler(my_functor_t(this)); + } + + //! Constructs a new concurrent_priority_queue with init_sz capacity + explicit concurrent_priority_queue(size_type init_capacity, const allocator_type& a = allocator_type()) : + mark(0), my_size(0), data(a) + { + data.reserve(init_capacity); + my_aggregator.initialize_handler(my_functor_t(this)); + } + + //! [begin,end) constructor + template + concurrent_priority_queue(InputIterator begin, InputIterator end, const allocator_type& a = allocator_type()) : + data(begin, end, a) + { + mark = 0; + my_aggregator.initialize_handler(my_functor_t(this)); + heapify(); + my_size = data.size(); + } + + //! Copy constructor + /** This operation is unsafe if there are pending concurrent operations on the src queue. */ + explicit concurrent_priority_queue(const concurrent_priority_queue& src) : mark(src.mark), + my_size(src.my_size), data(src.data.begin(), src.data.end(), src.data.get_allocator()) + { + my_aggregator.initialize_handler(my_functor_t(this)); + heapify(); + } + + //! Copy constructor with specific allocator + /** This operation is unsafe if there are pending concurrent operations on the src queue. */ + concurrent_priority_queue(const concurrent_priority_queue& src, const allocator_type& a) : mark(src.mark), + my_size(src.my_size), data(src.data.begin(), src.data.end(), a) + { + my_aggregator.initialize_handler(my_functor_t(this)); + heapify(); + } + + //! Assignment operator + /** This operation is unsafe if there are pending concurrent operations on the src queue. */ + concurrent_priority_queue& operator=(const concurrent_priority_queue& src) { + if (this != &src) { + std::vector(src.data.begin(), src.data.end(), src.data.get_allocator()).swap(data); + mark = src.mark; + my_size = src.my_size; + } + return *this; + } + + //! Returns true if empty, false otherwise + /** Returned value may not reflect results of pending operations. + This operation reads shared data and will trigger a race condition. */ + bool empty() const { return size()==0; } + + //! Returns the current number of elements contained in the queue + /** Returned value may not reflect results of pending operations. + This operation reads shared data and will trigger a race condition. */ + size_type size() const { return __TBB_load_with_acquire(my_size); } + + //! Pushes elem onto the queue, increasing capacity of queue if necessary + /** This operation can be safely used concurrently with other push, try_pop or reserve operations. */ + void push(const_reference elem) { + cpq_operation op_data(elem, PUSH_OP); + my_aggregator.execute(&op_data); + if (op_data.status == FAILED) // exception thrown + throw_exception(eid_bad_alloc); + } + + //! Gets a reference to and removes highest priority element + /** If a highest priority element was found, sets elem and returns true, + otherwise returns false. + This operation can be safely used concurrently with other push, try_pop or reserve operations. */ + bool try_pop(reference elem) { + cpq_operation op_data(POP_OP); + op_data.elem = &elem; + my_aggregator.execute(&op_data); + return op_data.status==SUCCEEDED; + } + + //! Clear the queue; not thread-safe + /** This operation is unsafe if there are pending concurrent operations on the queue. + Resets size, effectively emptying queue; does not free space. + May not clear elements added in pending operations. */ + void clear() { + data.clear(); + mark = 0; + my_size = 0; + } + + //! Swap this queue with another; not thread-safe + /** This operation is unsafe if there are pending concurrent operations on the queue. */ + void swap(concurrent_priority_queue& q) { + data.swap(q.data); + std::swap(mark, q.mark); + std::swap(my_size, q.my_size); + } + + //! Return allocator object + allocator_type get_allocator() const { return data.get_allocator(); } + + private: + enum operation_type {INVALID_OP, PUSH_OP, POP_OP}; + enum operation_status { WAIT=0, SUCCEEDED, FAILED }; + + class cpq_operation : public aggregated_operation { + public: + operation_type type; + union { + value_type *elem; + size_type sz; + }; + cpq_operation(const_reference e, operation_type t) : + type(t), elem(const_cast(&e)) {} + cpq_operation(operation_type t) : type(t) {} + }; + + class my_functor_t { + concurrent_priority_queue *cpq; + public: + my_functor_t() {} + my_functor_t(concurrent_priority_queue *cpq_) : cpq(cpq_) {} + void operator()(cpq_operation* op_list) { + cpq->handle_operations(op_list); + } + }; + + aggregator< my_functor_t, cpq_operation> my_aggregator; + //! Padding added to avoid false sharing + char padding1[NFS_MaxLineSize - sizeof(aggregator< my_functor_t, cpq_operation >)]; + //! The point at which unsorted elements begin + size_type mark; + __TBB_atomic size_type my_size; + Compare compare; + //! Padding added to avoid false sharing + char padding2[NFS_MaxLineSize - (2*sizeof(size_type)) - sizeof(Compare)]; + //! Storage for the heap of elements in queue, plus unheapified elements + /** data has the following structure: + + binary unheapified + heap elements + ____|_______|____ + | | | + v v v + [_|...|_|_|...|_| |...| ] + 0 ^ ^ ^ + | | |__capacity + | |__my_size + |__mark + + Thus, data stores the binary heap starting at position 0 through + mark-1 (it may be empty). Then there are 0 or more elements + that have not yet been inserted into the heap, in positions + mark through my_size-1. */ + std::vector data; + + void handle_operations(cpq_operation *op_list) { + cpq_operation *tmp, *pop_list=NULL; + + __TBB_ASSERT(mark == data.size(), NULL); + + // First pass processes all constant (amortized; reallocation may happen) time pushes and pops. + while (op_list) { + // ITT note: &(op_list->status) tag is used to cover accesses to op_list + // node. This thread is going to handle the operation, and so will acquire it + // and perform the associated operation w/o triggering a race condition; the + // thread that created the operation is waiting on the status field, so when + // this thread is done with the operation, it will perform a + // store_with_release to give control back to the waiting thread in + // aggregator::insert_operation. + call_itt_notify(acquired, &(op_list->status)); + __TBB_ASSERT(op_list->type != INVALID_OP, NULL); + tmp = op_list; + op_list = itt_hide_load_word(op_list->next); + if (tmp->type == PUSH_OP) { + __TBB_TRY { + data.push_back(*(tmp->elem)); + __TBB_store_with_release(my_size, my_size+1); + itt_store_word_with_release(tmp->status, uintptr_t(SUCCEEDED)); + } __TBB_CATCH(...) { + itt_store_word_with_release(tmp->status, uintptr_t(FAILED)); + } + } + else { // tmp->type == POP_OP + __TBB_ASSERT(tmp->type == POP_OP, NULL); + if (mark < data.size() && + compare(data[0], data[data.size()-1])) { + // there are newly pushed elems and the last one + // is higher than top + *(tmp->elem) = data[data.size()-1]; // copy the data + __TBB_store_with_release(my_size, my_size-1); + itt_store_word_with_release(tmp->status, uintptr_t(SUCCEEDED)); + data.pop_back(); + __TBB_ASSERT(mark<=data.size(), NULL); + } + else { // no convenient item to pop; postpone + itt_hide_store_word(tmp->next, pop_list); + pop_list = tmp; + } + } + } + + // second pass processes pop operations + while (pop_list) { + tmp = pop_list; + pop_list = itt_hide_load_word(pop_list->next); + __TBB_ASSERT(tmp->type == POP_OP, NULL); + if (data.empty()) { + itt_store_word_with_release(tmp->status, uintptr_t(FAILED)); + } + else { + __TBB_ASSERT(mark<=data.size(), NULL); + if (mark < data.size() && + compare(data[0], data[data.size()-1])) { + // there are newly pushed elems and the last one is + // higher than top + *(tmp->elem) = data[data.size()-1]; // copy the data + __TBB_store_with_release(my_size, my_size-1); + itt_store_word_with_release(tmp->status, uintptr_t(SUCCEEDED)); + data.pop_back(); + } + else { // extract top and push last element down heap + *(tmp->elem) = data[0]; // copy the data + __TBB_store_with_release(my_size, my_size-1); + itt_store_word_with_release(tmp->status, uintptr_t(SUCCEEDED)); + reheap(); + } + } + } + + // heapify any leftover pushed elements before doing the next + // batch of operations + if (mark0) mark = 1; + for (; mark>1; + if (!compare(data[parent], to_place)) break; + data[cur_pos] = data[parent]; + cur_pos = parent; + } while( cur_pos ); + data[cur_pos] = to_place; + } + } + + //! Re-heapify after an extraction + /** Re-heapify by pushing last element down the heap from the root. */ + void reheap() { + size_type cur_pos=0, child=1; + + while (child < mark) { + size_type target = child; + if (child+1 < mark && compare(data[child], data[child+1])) + ++target; + // target now has the higher priority child + if (compare(data[target], data[data.size()-1])) break; + data[cur_pos] = data[target]; + cur_pos = target; + child = (cur_pos<<1)+1; + } + data[cur_pos] = data[data.size()-1]; + data.pop_back(); + if (mark > data.size()) mark = data.size(); + } +}; + +} // namespace interface5 + +using interface5::concurrent_priority_queue; + +} // namespace tbb + +#endif /* __TBB_concurrent_priority_queue_H */ diff --git a/src/tbb/include/tbb/concurrent_queue.h b/src/tbb/include/tbb/concurrent_queue.h new file mode 100644 index 0000000..b2d495b --- /dev/null +++ b/src/tbb/include/tbb/concurrent_queue.h @@ -0,0 +1,420 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_concurrent_queue_H +#define __TBB_concurrent_queue_H + +#include "internal/_concurrent_queue_impl.h" + +namespace tbb { + +namespace strict_ppl { + +//! A high-performance thread-safe non-blocking concurrent queue. +/** Multiple threads may each push and pop concurrently. + Assignment construction is not allowed. + @ingroup containers */ +template > +class concurrent_queue: public internal::concurrent_queue_base_v3 { + template friend class internal::concurrent_queue_iterator; + + //! Allocator type + typedef typename A::template rebind::other page_allocator_type; + page_allocator_type my_allocator; + + //! Allocates a block of size n (bytes) + /*override*/ virtual void *allocate_block( size_t n ) { + void *b = reinterpret_cast(my_allocator.allocate( n )); + if( !b ) + internal::throw_exception(internal::eid_bad_alloc); + return b; + } + + //! Deallocates block created by allocate_block. + /*override*/ virtual void deallocate_block( void *b, size_t n ) { + my_allocator.deallocate( reinterpret_cast(b), n ); + } + +public: + //! Element type in the queue. + typedef T value_type; + + //! Reference type + typedef T& reference; + + //! Const reference type + typedef const T& const_reference; + + //! Integral type for representing size of the queue. + typedef size_t size_type; + + //! Difference type for iterator + typedef ptrdiff_t difference_type; + + //! Allocator type + typedef A allocator_type; + + //! Construct empty queue + explicit concurrent_queue(const allocator_type& a = allocator_type()) : + my_allocator( a ) + { + } + + //! [begin,end) constructor + template + concurrent_queue( InputIterator begin, InputIterator end, const allocator_type& a = allocator_type()) : + my_allocator( a ) + { + for( ; begin != end; ++begin ) + this->internal_push(&*begin); + } + + //! Copy constructor + concurrent_queue( const concurrent_queue& src, const allocator_type& a = allocator_type()) : + internal::concurrent_queue_base_v3(), my_allocator( a ) + { + this->assign( src ); + } + + //! Destroy queue + ~concurrent_queue(); + + //! Enqueue an item at tail of queue. + void push( const T& source ) { + this->internal_push( &source ); + } + + //! Attempt to dequeue an item from head of queue. + /** Does not wait for item to become available. + Returns true if successful; false otherwise. */ + bool try_pop( T& result ) { + return this->internal_try_pop( &result ); + } + + //! Return the number of items in the queue; thread unsafe + size_type unsafe_size() const {return this->internal_size();} + + //! Equivalent to size()==0. + bool empty() const {return this->internal_empty();} + + //! Clear the queue. not thread-safe. + void clear() ; + + //! Return allocator object + allocator_type get_allocator() const { return this->my_allocator; } + + typedef internal::concurrent_queue_iterator iterator; + typedef internal::concurrent_queue_iterator const_iterator; + + //------------------------------------------------------------------------ + // The iterators are intended only for debugging. They are slow and not thread safe. + //------------------------------------------------------------------------ + iterator unsafe_begin() {return iterator(*this);} + iterator unsafe_end() {return iterator();} + const_iterator unsafe_begin() const {return const_iterator(*this);} + const_iterator unsafe_end() const {return const_iterator();} +} ; + +template +concurrent_queue::~concurrent_queue() { + clear(); + this->internal_finish_clear(); +} + +template +void concurrent_queue::clear() { + while( !empty() ) { + T value; + this->internal_try_pop(&value); + } +} + +} // namespace strict_ppl + +//! A high-performance thread-safe blocking concurrent bounded queue. +/** This is the pre-PPL TBB concurrent queue which supports boundedness and blocking semantics. + Note that method names agree with the PPL-style concurrent queue. + Multiple threads may each push and pop concurrently. + Assignment construction is not allowed. + @ingroup containers */ +template > +class concurrent_bounded_queue: public internal::concurrent_queue_base_v3 { + template friend class internal::concurrent_queue_iterator; + + //! Allocator type + typedef typename A::template rebind::other page_allocator_type; + page_allocator_type my_allocator; + + typedef typename concurrent_queue_base_v3::padded_page padded_page; + + //! Class used to ensure exception-safety of method "pop" + class destroyer: internal::no_copy { + T& my_value; + public: + destroyer( T& value ) : my_value(value) {} + ~destroyer() {my_value.~T();} + }; + + T& get_ref( page& p, size_t index ) { + __TBB_ASSERT( index(static_cast(&p))->last)[index]; + } + + /*override*/ virtual void copy_item( page& dst, size_t index, const void* src ) { + new( &get_ref(dst,index) ) T(*static_cast(src)); + } + + /*override*/ virtual void copy_page_item( page& dst, size_t dindex, const page& src, size_t sindex ) { + new( &get_ref(dst,dindex) ) T( get_ref( const_cast(src), sindex ) ); + } + + /*override*/ virtual void assign_and_destroy_item( void* dst, page& src, size_t index ) { + T& from = get_ref(src,index); + destroyer d(from); + *static_cast(dst) = from; + } + + /*override*/ virtual page *allocate_page() { + size_t n = sizeof(padded_page) + (items_per_page-1)*sizeof(T); + page *p = reinterpret_cast(my_allocator.allocate( n )); + if( !p ) + internal::throw_exception(internal::eid_bad_alloc); + return p; + } + + /*override*/ virtual void deallocate_page( page *p ) { + size_t n = sizeof(padded_page) + (items_per_page-1)*sizeof(T); + my_allocator.deallocate( reinterpret_cast(p), n ); + } + +public: + //! Element type in the queue. + typedef T value_type; + + //! Allocator type + typedef A allocator_type; + + //! Reference type + typedef T& reference; + + //! Const reference type + typedef const T& const_reference; + + //! Integral type for representing size of the queue. + /** Note that the size_type is a signed integral type. + This is because the size can be negative if there are pending pops without corresponding pushes. */ + typedef std::ptrdiff_t size_type; + + //! Difference type for iterator + typedef std::ptrdiff_t difference_type; + + //! Construct empty queue + explicit concurrent_bounded_queue(const allocator_type& a = allocator_type()) : + concurrent_queue_base_v3( sizeof(T) ), my_allocator( a ) + { + } + + //! Copy constructor + concurrent_bounded_queue( const concurrent_bounded_queue& src, const allocator_type& a = allocator_type()) : + concurrent_queue_base_v3( sizeof(T) ), my_allocator( a ) + { + assign( src ); + } + + //! [begin,end) constructor + template + concurrent_bounded_queue( InputIterator begin, InputIterator end, const allocator_type& a = allocator_type()) : + concurrent_queue_base_v3( sizeof(T) ), my_allocator( a ) + { + for( ; begin != end; ++begin ) + internal_push_if_not_full(&*begin); + } + + //! Destroy queue + ~concurrent_bounded_queue(); + + //! Enqueue an item at tail of queue. + void push( const T& source ) { + internal_push( &source ); + } + + //! Dequeue item from head of queue. + /** Block until an item becomes available, and then dequeue it. */ + void pop( T& destination ) { + internal_pop( &destination ); + } + +#if TBB_USE_EXCEPTIONS + //! Abort all pending queue operations + void abort() { + internal_abort(); + } +#endif + + //! Enqueue an item at tail of queue if queue is not already full. + /** Does not wait for queue to become not full. + Returns true if item is pushed; false if queue was already full. */ + bool try_push( const T& source ) { + return internal_push_if_not_full( &source ); + } + + //! Attempt to dequeue an item from head of queue. + /** Does not wait for item to become available. + Returns true if successful; false otherwise. */ + bool try_pop( T& destination ) { + return internal_pop_if_present( &destination ); + } + + //! Return number of pushes minus number of pops. + /** Note that the result can be negative if there are pops waiting for the + corresponding pushes. The result can also exceed capacity() if there + are push operations in flight. */ + size_type size() const {return internal_size();} + + //! Equivalent to size()<=0. + bool empty() const {return internal_empty();} + + //! Maximum number of allowed elements + size_type capacity() const { + return my_capacity; + } + + //! Set the capacity + /** Setting the capacity to 0 causes subsequent try_push operations to always fail, + and subsequent push operations to block forever. */ + void set_capacity( size_type new_capacity ) { + internal_set_capacity( new_capacity, sizeof(T) ); + } + + //! return allocator object + allocator_type get_allocator() const { return this->my_allocator; } + + //! clear the queue. not thread-safe. + void clear() ; + + typedef internal::concurrent_queue_iterator iterator; + typedef internal::concurrent_queue_iterator const_iterator; + + //------------------------------------------------------------------------ + // The iterators are intended only for debugging. They are slow and not thread safe. + //------------------------------------------------------------------------ + iterator unsafe_begin() {return iterator(*this);} + iterator unsafe_end() {return iterator();} + const_iterator unsafe_begin() const {return const_iterator(*this);} + const_iterator unsafe_end() const {return const_iterator();} + +}; + +template +concurrent_bounded_queue::~concurrent_bounded_queue() { + clear(); + internal_finish_clear(); +} + +template +void concurrent_bounded_queue::clear() { + while( !empty() ) { + T value; + internal_pop_if_present(&value); + } +} + +namespace deprecated { + +//! A high-performance thread-safe blocking concurrent bounded queue. +/** This is the pre-PPL TBB concurrent queue which support boundedness and blocking semantics. + Note that method names agree with the PPL-style concurrent queue. + Multiple threads may each push and pop concurrently. + Assignment construction is not allowed. + @ingroup containers */ +template > +class concurrent_queue: public concurrent_bounded_queue { +#if !__TBB_TEMPLATE_FRIENDS_BROKEN + template friend class internal::concurrent_queue_iterator; +#endif + +public: + //! Construct empty queue + explicit concurrent_queue(const A& a = A()) : + concurrent_bounded_queue( a ) + { + } + + //! Copy constructor + concurrent_queue( const concurrent_queue& src, const A& a = A()) : + concurrent_bounded_queue( src, a ) + { + } + + //! [begin,end) constructor + template + concurrent_queue( InputIterator b /*begin*/, InputIterator e /*end*/, const A& a = A()) : + concurrent_bounded_queue( b, e, a ) + { + } + + //! Enqueue an item at tail of queue if queue is not already full. + /** Does not wait for queue to become not full. + Returns true if item is pushed; false if queue was already full. */ + bool push_if_not_full( const T& source ) { + return this->try_push( source ); + } + + //! Attempt to dequeue an item from head of queue. + /** Does not wait for item to become available. + Returns true if successful; false otherwise. + @deprecated Use try_pop() + */ + bool pop_if_present( T& destination ) { + return this->try_pop( destination ); + } + + typedef typename concurrent_bounded_queue::iterator iterator; + typedef typename concurrent_bounded_queue::const_iterator const_iterator; + // + //------------------------------------------------------------------------ + // The iterators are intended only for debugging. They are slow and not thread safe. + //------------------------------------------------------------------------ + iterator begin() {return this->unsafe_begin();} + iterator end() {return this->unsafe_end();} + const_iterator begin() const {return this->unsafe_begin();} + const_iterator end() const {return this->unsafe_end();} +}; + +} + + +#if TBB_DEPRECATED +using deprecated::concurrent_queue; +#else +using strict_ppl::concurrent_queue; +#endif + +} // namespace tbb + +#endif /* __TBB_concurrent_queue_H */ diff --git a/src/tbb/include/tbb/concurrent_unordered_map.h b/src/tbb/include/tbb/concurrent_unordered_map.h new file mode 100644 index 0000000..1f5272a --- /dev/null +++ b/src/tbb/include/tbb/concurrent_unordered_map.h @@ -0,0 +1,228 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* Container implementations in this header are based on PPL implementations + provided by Microsoft. */ + +#ifndef __TBB_concurrent_unordered_map_H +#define __TBB_concurrent_unordered_map_H + +#include "internal/_concurrent_unordered_impl.h" + +namespace tbb +{ + +namespace interface5 { + +// Template class for hash map traits +template +class concurrent_unordered_map_traits +{ +protected: + typedef std::pair value_type; + typedef Key key_type; + typedef Hash_compare hash_compare; + typedef typename Allocator::template rebind::other allocator_type; + enum { allow_multimapping = Allow_multimapping }; + + concurrent_unordered_map_traits() : my_hash_compare() {} + concurrent_unordered_map_traits(const hash_compare& hc) : my_hash_compare(hc) {} + + class value_compare : public std::binary_function + { + friend class concurrent_unordered_map_traits; + + public: + bool operator()(const value_type& left, const value_type& right) const + { + return (my_hash_compare(left.first, right.first)); + } + + value_compare(const hash_compare& comparator) : my_hash_compare(comparator) {} + + protected: + hash_compare my_hash_compare; // the comparator predicate for keys + }; + + template + static const Key& get_key(const std::pair& value) { + return (value.first); + } + + hash_compare my_hash_compare; // the comparator predicate for keys +}; + +template , typename Key_equality = std::equal_to, typename Allocator = tbb::tbb_allocator > > +class concurrent_unordered_map : public internal::concurrent_unordered_base< concurrent_unordered_map_traits, Allocator, false> > +{ + // Base type definitions + typedef internal::hash_compare hash_compare; + typedef internal::concurrent_unordered_base< concurrent_unordered_map_traits > base_type; + typedef concurrent_unordered_map_traits, Allocator, false> traits_type; + using traits_type::my_hash_compare; +#if __TBB_EXTRA_DEBUG +public: +#endif + using traits_type::allow_multimapping; +public: + using base_type::end; + using base_type::find; + using base_type::insert; + + // Type definitions + typedef Key key_type; + typedef typename base_type::value_type value_type; + typedef T mapped_type; + typedef Hasher hasher; + typedef Key_equality key_equal; + typedef hash_compare key_compare; + + typedef typename base_type::allocator_type allocator_type; + typedef typename base_type::pointer pointer; + typedef typename base_type::const_pointer const_pointer; + typedef typename base_type::reference reference; + typedef typename base_type::const_reference const_reference; + + typedef typename base_type::size_type size_type; + typedef typename base_type::difference_type difference_type; + + typedef typename base_type::iterator iterator; + typedef typename base_type::const_iterator const_iterator; + typedef typename base_type::iterator local_iterator; + typedef typename base_type::const_iterator const_local_iterator; + + // Construction/destruction/copying + explicit concurrent_unordered_map(size_type n_of_buckets = 8, const hasher& a_hasher = hasher(), + const key_equal& a_keyeq = key_equal(), const allocator_type& a = allocator_type()) + : base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a) + { + } + + concurrent_unordered_map(const Allocator& a) : base_type(8, key_compare(), a) + { + } + + template + concurrent_unordered_map(Iterator first, Iterator last, size_type n_of_buckets = 8, const hasher& a_hasher = hasher(), + const key_equal& a_keyeq = key_equal(), const allocator_type& a = allocator_type()) + : base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a) + { + for (; first != last; ++first) + base_type::insert(*first); + } + + concurrent_unordered_map(const concurrent_unordered_map& table) : base_type(table) + { + } + + concurrent_unordered_map(const concurrent_unordered_map& table, const Allocator& a) + : base_type(table, a) + { + } + + concurrent_unordered_map& operator=(const concurrent_unordered_map& table) + { + base_type::operator=(table); + return (*this); + } + + iterator unsafe_erase(const_iterator where) + { + return base_type::unsafe_erase(where); + } + + size_type unsafe_erase(const key_type& key) + { + return base_type::unsafe_erase(key); + } + + iterator unsafe_erase(const_iterator first, const_iterator last) + { + return base_type::unsafe_erase(first, last); + } + + void swap(concurrent_unordered_map& table) + { + base_type::swap(table); + } + + // Observers + hasher hash_function() const + { + return my_hash_compare.my_hash_object; + } + + key_equal key_eq() const + { + return my_hash_compare.my_key_compare_object; + } + + mapped_type& operator[](const key_type& key) + { + iterator where = find(key); + + if (where == end()) + { + where = insert(std::pair(key, mapped_type())).first; + } + + return ((*where).second); + } + + mapped_type& at(const key_type& key) + { + iterator where = find(key); + + if (where == end()) + { + tbb::internal::throw_exception(tbb::internal::eid_invalid_key); + } + + return ((*where).second); + } + + const mapped_type& at(const key_type& key) const + { + const_iterator where = find(key); + + if (where == end()) + { + tbb::internal::throw_exception(tbb::internal::eid_invalid_key); + } + + return ((*where).second); + } +}; + +} // namespace interface5 + +using interface5::concurrent_unordered_map; + +} // namespace tbb + +#endif// __TBB_concurrent_unordered_map_H diff --git a/src/tbb/include/tbb/concurrent_unordered_set.h b/src/tbb/include/tbb/concurrent_unordered_set.h new file mode 100644 index 0000000..acf550b --- /dev/null +++ b/src/tbb/include/tbb/concurrent_unordered_set.h @@ -0,0 +1,177 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* Container implementations in this header are based on PPL implementations + provided by Microsoft. */ + +#ifndef __TBB_concurrent_unordered_set_H +#define __TBB_concurrent_unordered_set_H + +#include "internal/_concurrent_unordered_impl.h" + +namespace tbb +{ + +namespace interface5 { + +// Template class for hash set traits +template +class concurrent_unordered_set_traits +{ +protected: + typedef Key value_type; + typedef Key key_type; + typedef Hash_compare hash_compare; + typedef typename Allocator::template rebind::other allocator_type; + enum { allow_multimapping = Allow_multimapping }; + + concurrent_unordered_set_traits() : my_hash_compare() {} + concurrent_unordered_set_traits(const hash_compare& hc) : my_hash_compare(hc) {} + + typedef hash_compare value_compare; + + static const Key& get_key(const value_type& value) { + return value; + } + + hash_compare my_hash_compare; // the comparator predicate for keys +}; + +template , typename Key_equality = std::equal_to, typename Allocator = tbb::tbb_allocator > +class concurrent_unordered_set : public internal::concurrent_unordered_base< concurrent_unordered_set_traits, Allocator, false> > +{ + // Base type definitions + typedef internal::hash_compare hash_compare; + typedef internal::concurrent_unordered_base< concurrent_unordered_set_traits > base_type; + typedef concurrent_unordered_set_traits, Allocator, false> traits_type; + using traits_type::my_hash_compare; +#if __TBB_EXTRA_DEBUG +public: +#endif + using traits_type::allow_multimapping; +public: + using base_type::end; + using base_type::find; + using base_type::insert; + + // Type definitions + typedef Key key_type; + typedef typename base_type::value_type value_type; + typedef Key mapped_type; + typedef Hasher hasher; + typedef Key_equality key_equal; + typedef hash_compare key_compare; + + typedef typename base_type::allocator_type allocator_type; + typedef typename base_type::pointer pointer; + typedef typename base_type::const_pointer const_pointer; + typedef typename base_type::reference reference; + typedef typename base_type::const_reference const_reference; + + typedef typename base_type::size_type size_type; + typedef typename base_type::difference_type difference_type; + + typedef typename base_type::iterator iterator; + typedef typename base_type::const_iterator const_iterator; + typedef typename base_type::iterator local_iterator; + typedef typename base_type::const_iterator const_local_iterator; + + // Construction/destruction/copying + explicit concurrent_unordered_set(size_type n_of_buckets = 8, const hasher& a_hasher = hasher(), + const key_equal& a_keyeq = key_equal(), const allocator_type& a = allocator_type()) + : base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a) + { + } + + concurrent_unordered_set(const Allocator& a) : base_type(8, key_compare(), a) + { + } + + template + concurrent_unordered_set(Iterator first, Iterator last, size_type n_of_buckets = 8, const hasher& a_hasher = hasher(), + const key_equal& a_keyeq = key_equal(), const allocator_type& a = allocator_type()) + : base_type(n_of_buckets, key_compare(a_hasher, a_keyeq), a) + { + for (; first != last; ++first) + base_type::insert(*first); + } + + concurrent_unordered_set(const concurrent_unordered_set& table) : base_type(table) + { + } + + concurrent_unordered_set(const concurrent_unordered_set& table, const Allocator& a) + : base_type(table, a) + { + } + + concurrent_unordered_set& operator=(const concurrent_unordered_set& table) + { + base_type::operator=(table); + return (*this); + } + + iterator unsafe_erase(const_iterator where) + { + return base_type::unsafe_erase(where); + } + + size_type unsafe_erase(const key_type& key) + { + return base_type::unsafe_erase(key); + } + + iterator unsafe_erase(const_iterator first, const_iterator last) + { + return base_type::unsafe_erase(first, last); + } + + void swap(concurrent_unordered_set& table) + { + base_type::swap(table); + } + + // Observers + hasher hash_function() const + { + return my_hash_compare.my_hash_object; + } + + key_equal key_eq() const + { + return my_hash_compare.my_key_compare_object; + } +}; + +} // namespace interface5 + +using interface5::concurrent_unordered_set; + +} // namespace tbb + +#endif// __TBB_concurrent_unordered_set_H diff --git a/src/tbb/include/tbb/concurrent_vector.h b/src/tbb/include/tbb/concurrent_vector.h new file mode 100644 index 0000000..3692cf0 --- /dev/null +++ b/src/tbb/include/tbb/concurrent_vector.h @@ -0,0 +1,1063 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_concurrent_vector_H +#define __TBB_concurrent_vector_H + +#include "tbb_stddef.h" +#include "tbb_exception.h" +#include "atomic.h" +#include "cache_aligned_allocator.h" +#include "blocked_range.h" +#include "tbb_machine.h" +#include "tbb_profiling.h" +#include +#include // for memset() + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include +#include + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +#if _MSC_VER==1500 && !__INTEL_COMPILER + // VS2008/VC9 seems to have an issue; limits pull in math.h + #pragma warning( push ) + #pragma warning( disable: 4985 ) +#endif +#include /* std::numeric_limits */ +#if _MSC_VER==1500 && !__INTEL_COMPILER + #pragma warning( pop ) +#endif + +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_Wp64) + // Workaround for overzealous compiler warnings in /Wp64 mode + #pragma warning (push) + #pragma warning (disable: 4267) +#endif + +namespace tbb { + +template > +class concurrent_vector; + +//! @cond INTERNAL +namespace internal { + + //! Bad allocation marker + static void *const vector_allocation_error_flag = reinterpret_cast(size_t(63)); + + //! Base class of concurrent vector implementation. + /** @ingroup containers */ + class concurrent_vector_base_v3 { + protected: + + // Basic types declarations + typedef size_t segment_index_t; + typedef size_t size_type; + + // Using enumerations due to Mac linking problems of static const variables + enum { + // Size constants + default_initial_segments = 1, // 2 initial items + //! Number of slots for segment's pointers inside the class + pointers_per_short_table = 3, // to fit into 8 words of entire structure + pointers_per_long_table = sizeof(segment_index_t) * 8 // one segment per bit + }; + + // Segment pointer. Can be zero-initialized + struct segment_t { + void* array; +#if TBB_USE_ASSERT + ~segment_t() { + __TBB_ASSERT( array <= internal::vector_allocation_error_flag, "should have been freed by clear" ); + } +#endif /* TBB_USE_ASSERT */ + }; + + // Data fields + + //! allocator function pointer + void* (*vector_allocator_ptr)(concurrent_vector_base_v3 &, size_t); + + //! count of segments in the first block + atomic my_first_block; + + //! Requested size of vector + atomic my_early_size; + + //! Pointer to the segments table + atomic my_segment; + + //! embedded storage of segment pointers + segment_t my_storage[pointers_per_short_table]; + + // Methods + + concurrent_vector_base_v3() { + my_early_size = 0; + my_first_block = 0; // here is not default_initial_segments + for( segment_index_t i = 0; i < pointers_per_short_table; i++) + my_storage[i].array = NULL; + my_segment = my_storage; + } + __TBB_EXPORTED_METHOD ~concurrent_vector_base_v3(); + + static segment_index_t segment_index_of( size_type index ) { + return segment_index_t( __TBB_Log2( index|1 ) ); + } + + static segment_index_t segment_base( segment_index_t k ) { + return (segment_index_t(1)< + class vector_iterator + { + //! concurrent_vector over which we are iterating. + Container* my_vector; + + //! Index into the vector + size_t my_index; + + //! Caches my_vector->internal_subscript(my_index) + /** NULL if cached value is not available */ + mutable Value* my_item; + + template + friend vector_iterator operator+( ptrdiff_t offset, const vector_iterator& v ); + + template + friend bool operator==( const vector_iterator& i, const vector_iterator& j ); + + template + friend bool operator<( const vector_iterator& i, const vector_iterator& j ); + + template + friend ptrdiff_t operator-( const vector_iterator& i, const vector_iterator& j ); + + template + friend class internal::vector_iterator; + +#if !defined(_MSC_VER) || defined(__INTEL_COMPILER) + template + friend class tbb::concurrent_vector; +#else +public: // workaround for MSVC +#endif + + vector_iterator( const Container& vector, size_t index, void *ptr = 0 ) : + my_vector(const_cast(&vector)), + my_index(index), + my_item(static_cast(ptr)) + {} + + public: + //! Default constructor + vector_iterator() : my_vector(NULL), my_index(~size_t(0)), my_item(NULL) {} + + vector_iterator( const vector_iterator& other ) : + my_vector(other.my_vector), + my_index(other.my_index), + my_item(other.my_item) + {} + + vector_iterator operator+( ptrdiff_t offset ) const { + return vector_iterator( *my_vector, my_index+offset ); + } + vector_iterator &operator+=( ptrdiff_t offset ) { + my_index+=offset; + my_item = NULL; + return *this; + } + vector_iterator operator-( ptrdiff_t offset ) const { + return vector_iterator( *my_vector, my_index-offset ); + } + vector_iterator &operator-=( ptrdiff_t offset ) { + my_index-=offset; + my_item = NULL; + return *this; + } + Value& operator*() const { + Value* item = my_item; + if( !item ) { + item = my_item = &my_vector->internal_subscript(my_index); + } + __TBB_ASSERT( item==&my_vector->internal_subscript(my_index), "corrupt cache" ); + return *item; + } + Value& operator[]( ptrdiff_t k ) const { + return my_vector->internal_subscript(my_index+k); + } + Value* operator->() const {return &operator*();} + + //! Pre increment + vector_iterator& operator++() { + size_t k = ++my_index; + if( my_item ) { + // Following test uses 2's-complement wizardry + if( (k& (k-2))==0 ) { + // k is a power of two that is at least k-2 + my_item= NULL; + } else { + ++my_item; + } + } + return *this; + } + + //! Pre decrement + vector_iterator& operator--() { + __TBB_ASSERT( my_index>0, "operator--() applied to iterator already at beginning of concurrent_vector" ); + size_t k = my_index--; + if( my_item ) { + // Following test uses 2's-complement wizardry + if( (k& (k-2))==0 ) { + // k is a power of two that is at least k-2 + my_item= NULL; + } else { + --my_item; + } + } + return *this; + } + + //! Post increment + vector_iterator operator++(int) { + vector_iterator result = *this; + operator++(); + return result; + } + + //! Post decrement + vector_iterator operator--(int) { + vector_iterator result = *this; + operator--(); + return result; + } + + // STL support + + typedef ptrdiff_t difference_type; + typedef Value value_type; + typedef Value* pointer; + typedef Value& reference; + typedef std::random_access_iterator_tag iterator_category; + }; + + template + vector_iterator operator+( ptrdiff_t offset, const vector_iterator& v ) { + return vector_iterator( *v.my_vector, v.my_index+offset ); + } + + template + bool operator==( const vector_iterator& i, const vector_iterator& j ) { + return i.my_index==j.my_index && i.my_vector == j.my_vector; + } + + template + bool operator!=( const vector_iterator& i, const vector_iterator& j ) { + return !(i==j); + } + + template + bool operator<( const vector_iterator& i, const vector_iterator& j ) { + return i.my_index + bool operator>( const vector_iterator& i, const vector_iterator& j ) { + return j + bool operator>=( const vector_iterator& i, const vector_iterator& j ) { + return !(i + bool operator<=( const vector_iterator& i, const vector_iterator& j ) { + return !(j + ptrdiff_t operator-( const vector_iterator& i, const vector_iterator& j ) { + return ptrdiff_t(i.my_index)-ptrdiff_t(j.my_index); + } + + template + class allocator_base { + public: + typedef typename A::template + rebind::other allocator_type; + allocator_type my_allocator; + + allocator_base(const allocator_type &a = allocator_type() ) : my_allocator(a) {} + }; + +} // namespace internal +//! @endcond + +//! Concurrent vector container +/** concurrent_vector is a container having the following main properties: + - It provides random indexed access to its elements. The index of the first element is 0. + - It ensures safe concurrent growing its size (different threads can safely append new elements). + - Adding new elements does not invalidate existing iterators and does not change indices of existing items. + +@par Compatibility + The class meets all Container Requirements and Reversible Container Requirements from + C++ Standard (See ISO/IEC 14882:2003(E), clause 23.1). But it doesn't meet + Sequence Requirements due to absence of insert() and erase() methods. + +@par Exception Safety + Methods working with memory allocation and/or new elements construction can throw an + exception if allocator fails to allocate memory or element's default constructor throws one. + Concurrent vector's element of type T must conform to the following requirements: + - Throwing an exception is forbidden for destructor of T. + - Default constructor of T must not throw an exception OR its non-virtual destructor must safely work when its object memory is zero-initialized. + . + Otherwise, the program's behavior is undefined. +@par + If an exception happens inside growth or assignment operation, an instance of the vector becomes invalid unless it is stated otherwise in the method documentation. + Invalid state means: + - There are no guarantees that all items were initialized by a constructor. The rest of items is zero-filled, including item where exception happens. + - An invalid vector instance cannot be repaired; it is unable to grow anymore. + - Size and capacity reported by the vector are incorrect, and calculated as if the failed operation were successful. + - Attempt to access not allocated elements using operator[] or iterators results in access violation or segmentation fault exception, and in case of using at() method a C++ exception is thrown. + . + If a concurrent grow operation successfully completes, all the elements it has added to the vector will remain valid and accessible even if one of subsequent grow operations fails. + +@par Fragmentation + Unlike an STL vector, a concurrent_vector does not move existing elements if it needs + to allocate more memory. The container is divided into a series of contiguous arrays of + elements. The first reservation, growth, or assignment operation determines the size of + the first array. Using small number of elements as initial size incurs fragmentation that + may increase element access time. Internal layout can be optimized by method compact() that + merges several smaller arrays into one solid. + +@par Changes since TBB 2.1 + - Fixed guarantees of concurrent_vector::size() and grow_to_at_least() methods to assure elements are allocated. + - Methods end()/rbegin()/back() are partly thread-safe since they use size() to get the end of vector + - Added resize() methods (not thread-safe) + - Added cbegin/cend/crbegin/crend methods + - Changed return type of methods grow* and push_back to iterator + +@par Changes since TBB 2.0 + - Implemented exception-safety guarantees + - Added template argument for allocator + - Added allocator argument in constructors + - Faster index calculation + - First growth call specifies a number of segments to be merged in the first allocation. + - Fixed memory blow up for swarm of vector's instances of small size + - Added grow_by(size_type n, const_reference t) growth using copying constructor to init new items. + - Added STL-like constructors. + - Added operators ==, < and derivatives + - Added at() method, approved for using after an exception was thrown inside the vector + - Added get_allocator() method. + - Added assign() methods + - Added compact() method to defragment first segments + - Added swap() method + - range() defaults on grainsize = 1 supporting auto grainsize algorithms. + + @ingroup containers */ +template +class concurrent_vector: protected internal::allocator_base, + private internal::concurrent_vector_base { +private: + template + class generic_range_type: public blocked_range { + public: + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; + typedef I iterator; + typedef ptrdiff_t difference_type; + generic_range_type( I begin_, I end_, size_t grainsize_ = 1) : blocked_range(begin_,end_,grainsize_) {} + template + generic_range_type( const generic_range_type& r) : blocked_range(r.begin(),r.end(),r.grainsize()) {} + generic_range_type( generic_range_type& r, split ) : blocked_range(r,split()) {} + }; + + template + friend class internal::vector_iterator; +public: + //------------------------------------------------------------------------ + // STL compatible types + //------------------------------------------------------------------------ + typedef internal::concurrent_vector_base_v3::size_type size_type; + typedef typename internal::allocator_base::allocator_type allocator_type; + + typedef T value_type; + typedef ptrdiff_t difference_type; + typedef T& reference; + typedef const T& const_reference; + typedef T *pointer; + typedef const T *const_pointer; + + typedef internal::vector_iterator iterator; + typedef internal::vector_iterator const_iterator; + +#if !defined(_MSC_VER) || _CPPLIB_VER>=300 + // Assume ISO standard definition of std::reverse_iterator + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; +#else + // Use non-standard std::reverse_iterator + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; +#endif /* defined(_MSC_VER) && (_MSC_VER<1300) */ + + //------------------------------------------------------------------------ + // Parallel algorithm support + //------------------------------------------------------------------------ + typedef generic_range_type range_type; + typedef generic_range_type const_range_type; + + //------------------------------------------------------------------------ + // STL compatible constructors & destructors + //------------------------------------------------------------------------ + + //! Construct empty vector. + explicit concurrent_vector(const allocator_type &a = allocator_type()) + : internal::allocator_base(a), internal::concurrent_vector_base() + { + vector_allocator_ptr = &internal_allocator; + } + + //! Copying constructor + concurrent_vector( const concurrent_vector& vector, const allocator_type& a = allocator_type() ) + : internal::allocator_base(a), internal::concurrent_vector_base() + { + vector_allocator_ptr = &internal_allocator; + __TBB_TRY { + internal_copy(vector, sizeof(T), ©_array); + } __TBB_CATCH(...) { + segment_t *table = my_segment; + internal_free_segments( reinterpret_cast(table), internal_clear(&destroy_array), my_first_block ); + __TBB_RETHROW(); + } + } + + //! Copying constructor for vector with different allocator type + template + concurrent_vector( const concurrent_vector& vector, const allocator_type& a = allocator_type() ) + : internal::allocator_base(a), internal::concurrent_vector_base() + { + vector_allocator_ptr = &internal_allocator; + __TBB_TRY { + internal_copy(vector.internal_vector_base(), sizeof(T), ©_array); + } __TBB_CATCH(...) { + segment_t *table = my_segment; + internal_free_segments( reinterpret_cast(table), internal_clear(&destroy_array), my_first_block ); + __TBB_RETHROW(); + } + } + + //! Construction with initial size specified by argument n + explicit concurrent_vector(size_type n) + { + vector_allocator_ptr = &internal_allocator; + __TBB_TRY { + internal_resize( n, sizeof(T), max_size(), NULL, &destroy_array, &initialize_array ); + } __TBB_CATCH(...) { + segment_t *table = my_segment; + internal_free_segments( reinterpret_cast(table), internal_clear(&destroy_array), my_first_block ); + __TBB_RETHROW(); + } + } + + //! Construction with initial size specified by argument n, initialization by copying of t, and given allocator instance + concurrent_vector(size_type n, const_reference t, const allocator_type& a = allocator_type()) + : internal::allocator_base(a) + { + vector_allocator_ptr = &internal_allocator; + __TBB_TRY { + internal_resize( n, sizeof(T), max_size(), static_cast(&t), &destroy_array, &initialize_array_by ); + } __TBB_CATCH(...) { + segment_t *table = my_segment; + internal_free_segments( reinterpret_cast(table), internal_clear(&destroy_array), my_first_block ); + __TBB_RETHROW(); + } + } + + //! Construction with copying iteration range and given allocator instance + template + concurrent_vector(I first, I last, const allocator_type &a = allocator_type()) + : internal::allocator_base(a) + { + vector_allocator_ptr = &internal_allocator; + __TBB_TRY { + internal_assign_range(first, last, static_cast::is_integer> *>(0) ); + } __TBB_CATCH(...) { + segment_t *table = my_segment; + internal_free_segments( reinterpret_cast(table), internal_clear(&destroy_array), my_first_block ); + __TBB_RETHROW(); + } + } + + //! Assignment + concurrent_vector& operator=( const concurrent_vector& vector ) { + if( this != &vector ) + internal_assign(vector, sizeof(T), &destroy_array, &assign_array, ©_array); + return *this; + } + + //! Assignment for vector with different allocator type + template + concurrent_vector& operator=( const concurrent_vector& vector ) { + if( static_cast( this ) != static_cast( &vector ) ) + internal_assign(vector.internal_vector_base(), + sizeof(T), &destroy_array, &assign_array, ©_array); + return *this; + } + + //------------------------------------------------------------------------ + // Concurrent operations + //------------------------------------------------------------------------ + //! Grow by "delta" elements. +#if TBB_DEPRECATED + /** Returns old size. */ + size_type grow_by( size_type delta ) { + return delta ? internal_grow_by( delta, sizeof(T), &initialize_array, NULL ) : my_early_size; + } +#else + /** Returns iterator pointing to the first new element. */ + iterator grow_by( size_type delta ) { + return iterator(*this, delta ? internal_grow_by( delta, sizeof(T), &initialize_array, NULL ) : my_early_size); + } +#endif + + //! Grow by "delta" elements using copying constructor. +#if TBB_DEPRECATED + /** Returns old size. */ + size_type grow_by( size_type delta, const_reference t ) { + return delta ? internal_grow_by( delta, sizeof(T), &initialize_array_by, static_cast(&t) ) : my_early_size; + } +#else + /** Returns iterator pointing to the first new element. */ + iterator grow_by( size_type delta, const_reference t ) { + return iterator(*this, delta ? internal_grow_by( delta, sizeof(T), &initialize_array_by, static_cast(&t) ) : my_early_size); + } +#endif + + //! Append minimal sequence of elements such that size()>=n. +#if TBB_DEPRECATED + /** The new elements are default constructed. Blocks until all elements in range [0..n) are allocated. + May return while other elements are being constructed by other threads. */ + void grow_to_at_least( size_type n ) { + if( n ) internal_grow_to_at_least_with_result( n, sizeof(T), &initialize_array, NULL ); + }; +#else + /** The new elements are default constructed. Blocks until all elements in range [0..n) are allocated. + May return while other elements are being constructed by other threads. + Returns iterator that points to beginning of appended sequence. + If no elements were appended, returns iterator pointing to nth element. */ + iterator grow_to_at_least( size_type n ) { + size_type m=0; + if( n ) { + m = internal_grow_to_at_least_with_result( n, sizeof(T), &initialize_array, NULL ); + if( m>n ) m=n; + } + return iterator(*this, m); + }; +#endif + + //! Push item +#if TBB_DEPRECATED + size_type push_back( const_reference item ) +#else + /** Returns iterator pointing to the new element. */ + iterator push_back( const_reference item ) +#endif + { + size_type k; + void *ptr = internal_push_back(sizeof(T),k); + internal_loop_guide loop(1, ptr); + loop.init(&item); +#if TBB_DEPRECATED + return k; +#else + return iterator(*this, k, ptr); +#endif + } + + //! Get reference to element at given index. + /** This method is thread-safe for concurrent reads, and also while growing the vector, + as long as the calling thread has checked that index<size(). */ + reference operator[]( size_type index ) { + return internal_subscript(index); + } + + //! Get const reference to element at given index. + const_reference operator[]( size_type index ) const { + return internal_subscript(index); + } + + //! Get reference to element at given index. Throws exceptions on errors. + reference at( size_type index ) { + return internal_subscript_with_exceptions(index); + } + + //! Get const reference to element at given index. Throws exceptions on errors. + const_reference at( size_type index ) const { + return internal_subscript_with_exceptions(index); + } + + //! Get range for iterating with parallel algorithms + range_type range( size_t grainsize = 1 ) { + return range_type( begin(), end(), grainsize ); + } + + //! Get const range for iterating with parallel algorithms + const_range_type range( size_t grainsize = 1 ) const { + return const_range_type( begin(), end(), grainsize ); + } + + //------------------------------------------------------------------------ + // Capacity + //------------------------------------------------------------------------ + //! Return size of vector. It may include elements under construction + size_type size() const { + size_type sz = my_early_size, cp = internal_capacity(); + return cp < sz ? cp : sz; + } + + //! Return false if vector is not empty or has elements under construction at least. + bool empty() const {return !my_early_size;} + + //! Maximum size to which array can grow without allocating more memory. Concurrent allocations are not included in the value. + size_type capacity() const {return internal_capacity();} + + //! Allocate enough space to grow to size n without having to allocate more memory later. + /** Like most of the methods provided for STL compatibility, this method is *not* thread safe. + The capacity afterwards may be bigger than the requested reservation. */ + void reserve( size_type n ) { + if( n ) + internal_reserve(n, sizeof(T), max_size()); + } + + //! Resize the vector. Not thread-safe. + void resize( size_type n ) { + internal_resize( n, sizeof(T), max_size(), NULL, &destroy_array, &initialize_array ); + } + + //! Resize the vector, copy t for new elements. Not thread-safe. + void resize( size_type n, const_reference t ) { + internal_resize( n, sizeof(T), max_size(), static_cast(&t), &destroy_array, &initialize_array_by ); + } + +#if TBB_DEPRECATED + //! An alias for shrink_to_fit() + void compact() {shrink_to_fit();} +#endif /* TBB_DEPRECATED */ + + //! Optimize memory usage and fragmentation. + void shrink_to_fit(); + + //! Upper bound on argument to reserve. + size_type max_size() const {return (~size_type(0))/sizeof(T);} + + //------------------------------------------------------------------------ + // STL support + //------------------------------------------------------------------------ + + //! start iterator + iterator begin() {return iterator(*this,0);} + //! end iterator + iterator end() {return iterator(*this,size());} + //! start const iterator + const_iterator begin() const {return const_iterator(*this,0);} + //! end const iterator + const_iterator end() const {return const_iterator(*this,size());} + //! start const iterator + const_iterator cbegin() const {return const_iterator(*this,0);} + //! end const iterator + const_iterator cend() const {return const_iterator(*this,size());} + //! reverse start iterator + reverse_iterator rbegin() {return reverse_iterator(end());} + //! reverse end iterator + reverse_iterator rend() {return reverse_iterator(begin());} + //! reverse start const iterator + const_reverse_iterator rbegin() const {return const_reverse_iterator(end());} + //! reverse end const iterator + const_reverse_iterator rend() const {return const_reverse_iterator(begin());} + //! reverse start const iterator + const_reverse_iterator crbegin() const {return const_reverse_iterator(end());} + //! reverse end const iterator + const_reverse_iterator crend() const {return const_reverse_iterator(begin());} + //! the first item + reference front() { + __TBB_ASSERT( size()>0, NULL); + return static_cast(my_segment[0].array)[0]; + } + //! the first item const + const_reference front() const { + __TBB_ASSERT( size()>0, NULL); + return static_cast(my_segment[0].array)[0]; + } + //! the last item + reference back() { + __TBB_ASSERT( size()>0, NULL); + return internal_subscript( size()-1 ); + } + //! the last item const + const_reference back() const { + __TBB_ASSERT( size()>0, NULL); + return internal_subscript( size()-1 ); + } + //! return allocator object + allocator_type get_allocator() const { return this->my_allocator; } + + //! assign n items by copying t item + void assign(size_type n, const_reference t) { + clear(); + internal_resize( n, sizeof(T), max_size(), static_cast(&t), &destroy_array, &initialize_array_by ); + } + + //! assign range [first, last) + template + void assign(I first, I last) { + clear(); internal_assign_range( first, last, static_cast::is_integer> *>(0) ); + } + + //! swap two instances + void swap(concurrent_vector &vector) { + if( this != &vector ) { + concurrent_vector_base_v3::internal_swap(static_cast(vector)); + std::swap(this->my_allocator, vector.my_allocator); + } + } + + //! Clear container while keeping memory allocated. + /** To free up the memory, use in conjunction with method compact(). Not thread safe **/ + void clear() { + internal_clear(&destroy_array); + } + + //! Clear and destroy vector. + ~concurrent_vector() { + segment_t *table = my_segment; + internal_free_segments( reinterpret_cast(table), internal_clear(&destroy_array), my_first_block ); + // base class destructor call should be then + } + + const internal::concurrent_vector_base_v3 &internal_vector_base() const { return *this; } +private: + //! Allocate k items + static void *internal_allocator(internal::concurrent_vector_base_v3 &vb, size_t k) { + return static_cast&>(vb).my_allocator.allocate(k); + } + //! Free k segments from table + void internal_free_segments(void *table[], segment_index_t k, segment_index_t first_block); + + //! Get reference to element at given index. + T& internal_subscript( size_type index ) const; + + //! Get reference to element at given index with errors checks + T& internal_subscript_with_exceptions( size_type index ) const; + + //! assign n items by copying t + void internal_assign_n(size_type n, const_pointer p) { + internal_resize( n, sizeof(T), max_size(), static_cast(p), &destroy_array, p? &initialize_array_by : &initialize_array ); + } + + //! helper class + template class is_integer_tag; + + //! assign integer items by copying when arguments are treated as iterators. See C++ Standard 2003 23.1.1p9 + template + void internal_assign_range(I first, I last, is_integer_tag *) { + internal_assign_n(static_cast(first), &static_cast(last)); + } + //! inline proxy assign by iterators + template + void internal_assign_range(I first, I last, is_integer_tag *) { + internal_assign_iterators(first, last); + } + //! assign by iterators + template + void internal_assign_iterators(I first, I last); + + //! Construct n instances of T, starting at "begin". + static void __TBB_EXPORTED_FUNC initialize_array( void* begin, const void*, size_type n ); + + //! Construct n instances of T, starting at "begin". + static void __TBB_EXPORTED_FUNC initialize_array_by( void* begin, const void* src, size_type n ); + + //! Construct n instances of T, starting at "begin". + static void __TBB_EXPORTED_FUNC copy_array( void* dst, const void* src, size_type n ); + + //! Assign n instances of T, starting at "begin". + static void __TBB_EXPORTED_FUNC assign_array( void* dst, const void* src, size_type n ); + + //! Destroy n instances of T, starting at "begin". + static void __TBB_EXPORTED_FUNC destroy_array( void* begin, size_type n ); + + //! Exception-aware helper class for filling a segment by exception-danger operators of user class + class internal_loop_guide : internal::no_copy { + public: + const pointer array; + const size_type n; + size_type i; + internal_loop_guide(size_type ntrials, void *ptr) + : array(static_cast(ptr)), n(ntrials), i(0) {} + void init() { for(; i < n; ++i) new( &array[i] ) T(); } + void init(const void *src) { for(; i < n; ++i) new( &array[i] ) T(*static_cast(src)); } + void copy(const void *src) { for(; i < n; ++i) new( &array[i] ) T(static_cast(src)[i]); } + void assign(const void *src) { for(; i < n; ++i) array[i] = static_cast(src)[i]; } + template void iterate(I &src) { for(; i < n; ++i, ++src) new( &array[i] ) T( *src ); } + ~internal_loop_guide() { + if(i < n) // if exception raised, do zeroing on the rest of items + std::memset(array+i, 0, (n-i)*sizeof(value_type)); + } + }; +}; + +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) +#pragma warning (push) +#pragma warning (disable: 4701) // potentially uninitialized local variable "old" +#endif +template +void concurrent_vector::shrink_to_fit() { + internal_segments_table old; + __TBB_TRY { + if( internal_compact( sizeof(T), &old, &destroy_array, ©_array ) ) + internal_free_segments( old.table, pointers_per_long_table, old.first_block ); // free joined and unnecessary segments + } __TBB_CATCH(...) { + if( old.first_block ) // free segment allocated for compacting. Only for support of exceptions in ctor of user T[ype] + internal_free_segments( old.table, 1, old.first_block ); + __TBB_RETHROW(); + } +} +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) +#pragma warning (pop) +#endif // warning 4701 is back + +template +void concurrent_vector::internal_free_segments(void *table[], segment_index_t k, segment_index_t first_block) { + // Free the arrays + while( k > first_block ) { + --k; + T* array = static_cast(table[k]); + table[k] = NULL; + if( array > internal::vector_allocation_error_flag ) // check for correct segment pointer + this->my_allocator.deallocate( array, segment_size(k) ); + } + T* array = static_cast(table[0]); + if( array > internal::vector_allocation_error_flag ) { + __TBB_ASSERT( first_block > 0, NULL ); + while(k > 0) table[--k] = NULL; + this->my_allocator.deallocate( array, segment_size(first_block) ); + } +} + +template +T& concurrent_vector::internal_subscript( size_type index ) const { + __TBB_ASSERT( index < my_early_size, "index out of bounds" ); + size_type j = index; + segment_index_t k = segment_base_index_of( j ); + __TBB_ASSERT( (segment_t*)my_segment != my_storage || k < pointers_per_short_table, "index is being allocated" ); + // no need in __TBB_load_with_acquire since thread works in own space or gets + T* array = static_cast( tbb::internal::itt_hide_load_word(my_segment[k].array)); + __TBB_ASSERT( array != internal::vector_allocation_error_flag, "the instance is broken by bad allocation. Use at() instead" ); + __TBB_ASSERT( array, "index is being allocated" ); + return array[j]; +} + +template +T& concurrent_vector::internal_subscript_with_exceptions( size_type index ) const { + if( index >= my_early_size ) + internal::throw_exception(internal::eid_out_of_range); // throw std::out_of_range + size_type j = index; + segment_index_t k = segment_base_index_of( j ); + if( (segment_t*)my_segment == my_storage && k >= pointers_per_short_table ) + internal::throw_exception(internal::eid_segment_range_error); // throw std::range_error + void *array = my_segment[k].array; // no need in __TBB_load_with_acquire + if( array <= internal::vector_allocation_error_flag ) // check for correct segment pointer + internal::throw_exception(internal::eid_index_range_error); // throw std::range_error + return static_cast(array)[j]; +} + +template template +void concurrent_vector::internal_assign_iterators(I first, I last) { + __TBB_ASSERT(my_early_size == 0, NULL); + size_type n = std::distance(first, last); + if( !n ) return; + internal_reserve(n, sizeof(T), max_size()); + my_early_size = n; + segment_index_t k = 0; + size_type sz = segment_size( my_first_block ); + while( sz < n ) { + internal_loop_guide loop(sz, my_segment[k].array); + loop.iterate(first); + n -= sz; + if( !k ) k = my_first_block; + else { ++k; sz <<= 1; } + } + internal_loop_guide loop(n, my_segment[k].array); + loop.iterate(first); +} + +template +void concurrent_vector::initialize_array( void* begin, const void *, size_type n ) { + internal_loop_guide loop(n, begin); loop.init(); +} + +template +void concurrent_vector::initialize_array_by( void* begin, const void *src, size_type n ) { + internal_loop_guide loop(n, begin); loop.init(src); +} + +template +void concurrent_vector::copy_array( void* dst, const void* src, size_type n ) { + internal_loop_guide loop(n, dst); loop.copy(src); +} + +template +void concurrent_vector::assign_array( void* dst, const void* src, size_type n ) { + internal_loop_guide loop(n, dst); loop.assign(src); +} + +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) + // Workaround for overzealous compiler warning + #pragma warning (push) + #pragma warning (disable: 4189) +#endif +template +void concurrent_vector::destroy_array( void* begin, size_type n ) { + T* array = static_cast(begin); + for( size_type j=n; j>0; --j ) + array[j-1].~T(); // destructors are supposed to not throw any exceptions +} +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) + #pragma warning (pop) +#endif // warning 4189 is back + +// concurrent_vector's template functions +template +inline bool operator==(const concurrent_vector &a, const concurrent_vector &b) { + // Simply: return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin()); + if(a.size() != b.size()) return false; + typename concurrent_vector::const_iterator i(a.begin()); + typename concurrent_vector::const_iterator j(b.begin()); + for(; i != a.end(); ++i, ++j) + if( !(*i == *j) ) return false; + return true; +} + +template +inline bool operator!=(const concurrent_vector &a, const concurrent_vector &b) +{ return !(a == b); } + +template +inline bool operator<(const concurrent_vector &a, const concurrent_vector &b) +{ return (std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end())); } + +template +inline bool operator>(const concurrent_vector &a, const concurrent_vector &b) +{ return b < a; } + +template +inline bool operator<=(const concurrent_vector &a, const concurrent_vector &b) +{ return !(b < a); } + +template +inline bool operator>=(const concurrent_vector &a, const concurrent_vector &b) +{ return !(a < b); } + +template +inline void swap(concurrent_vector &a, concurrent_vector &b) +{ a.swap( b ); } + +} // namespace tbb + +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_Wp64) + #pragma warning (pop) +#endif // warning 4267 is back + +#endif /* __TBB_concurrent_vector_H */ diff --git a/src/tbb/include/tbb/critical_section.h b/src/tbb/include/tbb/critical_section.h new file mode 100644 index 0000000..f48db40 --- /dev/null +++ b/src/tbb/include/tbb/critical_section.h @@ -0,0 +1,141 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _TBB_CRITICAL_SECTION_H_ +#define _TBB_CRITICAL_SECTION_H_ + +#if _WIN32||_WIN64 +#include "machine/windows_api.h" +#else +#include +#include +#endif // _WIN32||WIN64 + +#include "tbb_stddef.h" +#include "tbb_thread.h" +#include "tbb_exception.h" + +#include "tbb_profiling.h" + +namespace tbb { + + namespace internal { +class critical_section_v4 : internal::no_copy { +#if _WIN32||_WIN64 + CRITICAL_SECTION my_impl; +#else + pthread_mutex_t my_impl; +#endif + tbb_thread::id my_tid; +public: + + void __TBB_EXPORTED_METHOD internal_construct(); + + critical_section_v4() { +#if _WIN32||_WIN64 + InitializeCriticalSection(&my_impl); +#else + pthread_mutex_init(&my_impl, NULL); +#endif + internal_construct(); + } + + ~critical_section_v4() { + __TBB_ASSERT(my_tid == tbb_thread::id(), "Destroying a still-held critical section"); +#if _WIN32||_WIN64 + DeleteCriticalSection(&my_impl); +#else + pthread_mutex_destroy(&my_impl); +#endif + } + + class scoped_lock : internal::no_copy { + private: + critical_section_v4 &my_crit; + public: + scoped_lock( critical_section_v4& lock_me) :my_crit(lock_me) { + my_crit.lock(); + } + + ~scoped_lock() { + my_crit.unlock(); + } + }; + + void lock() { + tbb_thread::id local_tid = this_tbb_thread::get_id(); + if(local_tid == my_tid) throw_exception( eid_improper_lock ); +#if _WIN32||_WIN64 + EnterCriticalSection( &my_impl ); +#else + int rval = pthread_mutex_lock(&my_impl); + __TBB_ASSERT_EX(!rval, "critical_section::lock: pthread_mutex_lock failed"); +#endif + __TBB_ASSERT(my_tid == tbb_thread::id(), NULL); + my_tid = local_tid; + } + + bool try_lock() { + bool gotlock; + tbb_thread::id local_tid = this_tbb_thread::get_id(); + if(local_tid == my_tid) return false; +#if _WIN32||_WIN64 + gotlock = TryEnterCriticalSection( &my_impl ) != 0; +#else + int rval = pthread_mutex_trylock(&my_impl); + // valid returns are 0 (locked) and [EBUSY] + __TBB_ASSERT(rval == 0 || rval == EBUSY, "critical_section::trylock: pthread_mutex_trylock failed"); + gotlock = rval == 0; +#endif + if(gotlock) { + my_tid = local_tid; + } + return gotlock; + } + + void unlock() { + __TBB_ASSERT(this_tbb_thread::get_id() == my_tid, "thread unlocking critical_section is not thread that locked it"); + my_tid = tbb_thread::id(); +#if _WIN32||_WIN64 + LeaveCriticalSection( &my_impl ); +#else + int rval = pthread_mutex_unlock(&my_impl); + __TBB_ASSERT_EX(!rval, "critical_section::unlock: pthread_mutex_unlock failed"); +#endif + } + + static const bool is_rw_mutex = false; + static const bool is_recursive_mutex = false; + static const bool is_fair_mutex = true; +}; // critical_section_v4 +} // namespace internal +typedef internal::critical_section_v4 critical_section; + +__TBB_DEFINE_PROFILING_SET_NAME(critical_section) +} // namespace tbb +#endif // _TBB_CRITICAL_SECTION_H_ diff --git a/src/tbb/include/tbb/enumerable_thread_specific.h b/src/tbb/include/tbb/enumerable_thread_specific.h new file mode 100644 index 0000000..eb989b5 --- /dev/null +++ b/src/tbb/include/tbb/enumerable_thread_specific.h @@ -0,0 +1,995 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_enumerable_thread_specific_H +#define __TBB_enumerable_thread_specific_H + +#include "concurrent_vector.h" +#include "tbb_thread.h" +#include "tbb_allocator.h" +#include "cache_aligned_allocator.h" +#include "aligned_space.h" +#include // for memcpy + +#if _WIN32||_WIN64 +#include "machine/windows_api.h" +#else +#include +#endif + +namespace tbb { + +//! enum for selecting between single key and key-per-instance versions +enum ets_key_usage_type { ets_key_per_instance, ets_no_key }; + +namespace interface6 { + + //! @cond + namespace internal { + + template + class ets_base: tbb::internal::no_copy { + protected: +#if _WIN32||_WIN64 + typedef DWORD key_type; +#else + typedef pthread_t key_type; +#endif +#if __TBB_PROTECTED_NESTED_CLASS_BROKEN + public: +#endif + struct slot; + + struct array { + array* next; + size_t lg_size; + slot& at( size_t k ) { + return ((slot*)(void*)(this+1))[k]; + } + size_t size() const {return (size_t)1<>(8*sizeof(size_t)-lg_size); + } + }; + struct slot { + key_type key; + void* ptr; + bool empty() const {return !key;} + bool match( key_type k ) const {return key==k;} + bool claim( key_type k ) { + __TBB_ASSERT(sizeof(tbb::atomic)==sizeof(key_type), NULL); + return tbb::internal::punned_cast*>(&key)->compare_and_swap(k,0)==0; + } + }; +#if __TBB_PROTECTED_NESTED_CLASS_BROKEN + protected: +#endif + + static key_type key_of_current_thread() { + tbb::tbb_thread::id id = tbb::this_tbb_thread::get_id(); + key_type k; + memcpy( &k, &id, sizeof(k) ); + return k; + } + + //! Root of linked list of arrays of decreasing size. + /** NULL if and only if my_count==0. + Each array in the list is half the size of its predecessor. */ + atomic my_root; + atomic my_count; + virtual void* create_local() = 0; + virtual void* create_array(size_t _size) = 0; // _size in bytes + virtual void free_array(void* ptr, size_t _size) = 0; // _size in bytes + array* allocate( size_t lg_size ) { + size_t n = 1<(create_array( sizeof(array)+n*sizeof(slot) )); + a->lg_size = lg_size; + std::memset( a+1, 0, n*sizeof(slot) ); + return a; + } + void free(array* a) { + size_t n = 1<<(a->lg_size); + free_array( (void *)a, size_t(sizeof(array)+n*sizeof(slot)) ); + } + static size_t hash( key_type k ) { + // Multiplicative hashing. Client should use *upper* bits. + // casts required for Mac gcc4.* compiler + return uintptr_t(k)*tbb::internal::size_t_select(0x9E3779B9,0x9E3779B97F4A7C15ULL); + } + + ets_base() {my_root=NULL; my_count=0;} + virtual ~ets_base(); // g++ complains if this is not virtual... + void* table_lookup( bool& exists ); + void table_clear(); + slot& table_find( key_type k ) { + size_t h = hash(k); + array* r = my_root; + size_t mask = r->mask(); + for(size_t i = r->start(h);;i=(i+1)&mask) { + slot& s = r->at(i); + if( s.empty() || s.match(k) ) + return s; + } + } + void table_reserve_for_copy( const ets_base& other ) { + __TBB_ASSERT(!my_root,NULL); + __TBB_ASSERT(!my_count,NULL); + if( other.my_root ) { + array* a = allocate(other.my_root->lg_size); + a->next = NULL; + my_root = a; + my_count = other.my_count; + } + } + }; + + template + ets_base::~ets_base() { + __TBB_ASSERT(!my_root, NULL); + } + + template + void ets_base::table_clear() { + while( array* r = my_root ) { + my_root = r->next; + free(r); + } + my_count = 0; + } + + template + void* ets_base::table_lookup( bool& exists ) { + const key_type k = key_of_current_thread(); + + __TBB_ASSERT(k!=0,NULL); + void* found; + size_t h = hash(k); + for( array* r=my_root; r; r=r->next ) { + size_t mask=r->mask(); + for(size_t i = r->start(h); ;i=(i+1)&mask) { + slot& s = r->at(i); + if( s.empty() ) break; + if( s.match(k) ) { + if( r==my_root ) { + // Success at top level + exists = true; + return s.ptr; + } else { + // Success at some other level. Need to insert at top level. + exists = true; + found = s.ptr; + goto insert; + } + } + } + } + // Key does not yet exist + exists = false; + found = create_local(); + { + size_t c = ++my_count; + array* r = my_root; + if( !r || c>r->size()/2 ) { + size_t s = r ? r->lg_size : 2; + while( c>size_t(1)<<(s-1) ) ++s; + array* a = allocate(s); + for(;;) { + a->next = my_root; + array* new_r = my_root.compare_and_swap(a,r); + if( new_r==r ) break; + if( new_r->lg_size>=s ) { + // Another thread inserted an equal or bigger array, so our array is superfluous. + free(a); + break; + } + r = new_r; + } + } + } + insert: + // Guaranteed to be room for it, and it is not present, so search for empty slot and grab it. + array* ir = my_root; + size_t mask = ir->mask(); + for(size_t i = ir->start(h);;i=(i+1)&mask) { + slot& s = ir->at(i); + if( s.empty() ) { + if( s.claim(k) ) { + s.ptr = found; + return found; + } + } + } + } + + //! Specialization that exploits native TLS + template <> + class ets_base: protected ets_base { + typedef ets_base super; +#if _WIN32||_WIN64 + typedef DWORD tls_key_t; + void create_key() { my_key = TlsAlloc(); } + void destroy_key() { TlsFree(my_key); } + void set_tls(void * value) { TlsSetValue(my_key, (LPVOID)value); } + void* get_tls() { return (void *)TlsGetValue(my_key); } +#else + typedef pthread_key_t tls_key_t; + void create_key() { pthread_key_create(&my_key, NULL); } + void destroy_key() { pthread_key_delete(my_key); } + void set_tls( void * value ) const { pthread_setspecific(my_key, value); } + void* get_tls() const { return pthread_getspecific(my_key); } +#endif + tls_key_t my_key; + virtual void* create_local() = 0; + virtual void* create_array(size_t _size) = 0; // _size in bytes + virtual void free_array(void* ptr, size_t _size) = 0; // size in bytes + public: + ets_base() {create_key();} + ~ets_base() {destroy_key();} + void* table_lookup( bool& exists ) { + void* found = get_tls(); + if( found ) { + exists=true; + } else { + found = super::table_lookup(exists); + set_tls(found); + } + return found; + } + void table_clear() { + destroy_key(); + create_key(); + super::table_clear(); + } + }; + + //! Random access iterator for traversing the thread local copies. + template< typename Container, typename Value > + class enumerable_thread_specific_iterator +#if defined(_WIN64) && defined(_MSC_VER) + // Ensure that Microsoft's internal template function _Val_type works correctly. + : public std::iterator +#endif /* defined(_WIN64) && defined(_MSC_VER) */ + { + //! current position in the concurrent_vector + + Container *my_container; + typename Container::size_type my_index; + mutable Value *my_value; + + template + friend enumerable_thread_specific_iterator operator+( ptrdiff_t offset, + const enumerable_thread_specific_iterator& v ); + + template + friend bool operator==( const enumerable_thread_specific_iterator& i, + const enumerable_thread_specific_iterator& j ); + + template + friend bool operator<( const enumerable_thread_specific_iterator& i, + const enumerable_thread_specific_iterator& j ); + + template + friend ptrdiff_t operator-( const enumerable_thread_specific_iterator& i, const enumerable_thread_specific_iterator& j ); + + template + friend class enumerable_thread_specific_iterator; + + public: + + enumerable_thread_specific_iterator( const Container &container, typename Container::size_type index ) : + my_container(&const_cast(container)), my_index(index), my_value(NULL) {} + + //! Default constructor + enumerable_thread_specific_iterator() : my_container(NULL), my_index(0), my_value(NULL) {} + + template + enumerable_thread_specific_iterator( const enumerable_thread_specific_iterator& other ) : + my_container( other.my_container ), my_index( other.my_index), my_value( const_cast(other.my_value) ) {} + + enumerable_thread_specific_iterator operator+( ptrdiff_t offset ) const { + return enumerable_thread_specific_iterator(*my_container, my_index + offset); + } + + enumerable_thread_specific_iterator &operator+=( ptrdiff_t offset ) { + my_index += offset; + my_value = NULL; + return *this; + } + + enumerable_thread_specific_iterator operator-( ptrdiff_t offset ) const { + return enumerable_thread_specific_iterator( *my_container, my_index-offset ); + } + + enumerable_thread_specific_iterator &operator-=( ptrdiff_t offset ) { + my_index -= offset; + my_value = NULL; + return *this; + } + + Value& operator*() const { + Value* value = my_value; + if( !value ) { + value = my_value = reinterpret_cast(&(*my_container)[my_index].value); + } + __TBB_ASSERT( value==reinterpret_cast(&(*my_container)[my_index].value), "corrupt cache" ); + return *value; + } + + Value& operator[]( ptrdiff_t k ) const { + return (*my_container)[my_index + k].value; + } + + Value* operator->() const {return &operator*();} + + enumerable_thread_specific_iterator& operator++() { + ++my_index; + my_value = NULL; + return *this; + } + + enumerable_thread_specific_iterator& operator--() { + --my_index; + my_value = NULL; + return *this; + } + + //! Post increment + enumerable_thread_specific_iterator operator++(int) { + enumerable_thread_specific_iterator result = *this; + ++my_index; + my_value = NULL; + return result; + } + + //! Post decrement + enumerable_thread_specific_iterator operator--(int) { + enumerable_thread_specific_iterator result = *this; + --my_index; + my_value = NULL; + return result; + } + + // STL support + typedef ptrdiff_t difference_type; + typedef Value value_type; + typedef Value* pointer; + typedef Value& reference; + typedef std::random_access_iterator_tag iterator_category; + }; + + template + enumerable_thread_specific_iterator operator+( ptrdiff_t offset, + const enumerable_thread_specific_iterator& v ) { + return enumerable_thread_specific_iterator( v.my_container, v.my_index + offset ); + } + + template + bool operator==( const enumerable_thread_specific_iterator& i, + const enumerable_thread_specific_iterator& j ) { + return i.my_index==j.my_index && i.my_container == j.my_container; + } + + template + bool operator!=( const enumerable_thread_specific_iterator& i, + const enumerable_thread_specific_iterator& j ) { + return !(i==j); + } + + template + bool operator<( const enumerable_thread_specific_iterator& i, + const enumerable_thread_specific_iterator& j ) { + return i.my_index + bool operator>( const enumerable_thread_specific_iterator& i, + const enumerable_thread_specific_iterator& j ) { + return j + bool operator>=( const enumerable_thread_specific_iterator& i, + const enumerable_thread_specific_iterator& j ) { + return !(i + bool operator<=( const enumerable_thread_specific_iterator& i, + const enumerable_thread_specific_iterator& j ) { + return !(j + ptrdiff_t operator-( const enumerable_thread_specific_iterator& i, + const enumerable_thread_specific_iterator& j ) { + return i.my_index-j.my_index; + } + + template + class segmented_iterator +#if defined(_WIN64) && defined(_MSC_VER) + : public std::iterator +#endif + { + template + friend bool operator==(const segmented_iterator& i, const segmented_iterator& j); + + template + friend bool operator!=(const segmented_iterator& i, const segmented_iterator& j); + + template + friend class segmented_iterator; + + public: + + segmented_iterator() {my_segcont = NULL;} + + segmented_iterator( const SegmentedContainer& _segmented_container ) : + my_segcont(const_cast(&_segmented_container)), + outer_iter(my_segcont->end()) { } + + ~segmented_iterator() {} + + typedef typename SegmentedContainer::iterator outer_iterator; + typedef typename SegmentedContainer::value_type InnerContainer; + typedef typename InnerContainer::iterator inner_iterator; + + // STL support + typedef ptrdiff_t difference_type; + typedef Value value_type; + typedef typename SegmentedContainer::size_type size_type; + typedef Value* pointer; + typedef Value& reference; + typedef std::input_iterator_tag iterator_category; + + // Copy Constructor + template + segmented_iterator(const segmented_iterator& other) : + my_segcont(other.my_segcont), + outer_iter(other.outer_iter), + // can we assign a default-constructed iterator to inner if we're at the end? + inner_iter(other.inner_iter) + {} + + // assignment + template + segmented_iterator& operator=( const segmented_iterator& other) { + if(this != &other) { + my_segcont = other.my_segcont; + outer_iter = other.outer_iter; + if(outer_iter != my_segcont->end()) inner_iter = other.inner_iter; + } + return *this; + } + + // allow assignment of outer iterator to segmented iterator. Once it is + // assigned, move forward until a non-empty inner container is found or + // the end of the outer container is reached. + segmented_iterator& operator=(const outer_iterator& new_outer_iter) { + __TBB_ASSERT(my_segcont != NULL, NULL); + // check that this iterator points to something inside the segmented container + for(outer_iter = new_outer_iter ;outer_iter!=my_segcont->end(); ++outer_iter) { + if( !outer_iter->empty() ) { + inner_iter = outer_iter->begin(); + break; + } + } + return *this; + } + + // pre-increment + segmented_iterator& operator++() { + advance_me(); + return *this; + } + + // post-increment + segmented_iterator operator++(int) { + segmented_iterator tmp = *this; + operator++(); + return tmp; + } + + bool operator==(const outer_iterator& other_outer) const { + __TBB_ASSERT(my_segcont != NULL, NULL); + return (outer_iter == other_outer && + (outer_iter == my_segcont->end() || inner_iter == outer_iter->begin())); + } + + bool operator!=(const outer_iterator& other_outer) const { + return !operator==(other_outer); + + } + + // (i)* RHS + reference operator*() const { + __TBB_ASSERT(my_segcont != NULL, NULL); + __TBB_ASSERT(outer_iter != my_segcont->end(), "Dereferencing a pointer at end of container"); + __TBB_ASSERT(inner_iter != outer_iter->end(), NULL); // should never happen + return *inner_iter; + } + + // i-> + pointer operator->() const { return &operator*();} + + private: + SegmentedContainer* my_segcont; + outer_iterator outer_iter; + inner_iterator inner_iter; + + void advance_me() { + __TBB_ASSERT(my_segcont != NULL, NULL); + __TBB_ASSERT(outer_iter != my_segcont->end(), NULL); // not true if there are no inner containers + __TBB_ASSERT(inner_iter != outer_iter->end(), NULL); // not true if the inner containers are all empty. + ++inner_iter; + while(inner_iter == outer_iter->end() && ++outer_iter != my_segcont->end()) { + inner_iter = outer_iter->begin(); + } + } + }; // segmented_iterator + + template + bool operator==( const segmented_iterator& i, + const segmented_iterator& j ) { + if(i.my_segcont != j.my_segcont) return false; + if(i.my_segcont == NULL) return true; + if(i.outer_iter != j.outer_iter) return false; + if(i.outer_iter == i.my_segcont->end()) return true; + return i.inner_iter == j.inner_iter; + } + + // != + template + bool operator!=( const segmented_iterator& i, + const segmented_iterator& j ) { + return !(i==j); + } + + template + struct destruct_only: tbb::internal::no_copy { + tbb::aligned_space value; + ~destruct_only() {value.begin()[0].~T();} + }; + + template + struct construct_by_default: tbb::internal::no_assign { + void construct(void*where) {new(where) T();} // C++ note: the () in T() ensure zero initialization. + construct_by_default( int ) {} + }; + + template + struct construct_by_exemplar: tbb::internal::no_assign { + const T exemplar; + void construct(void*where) {new(where) T(exemplar);} + construct_by_exemplar( const T& t ) : exemplar(t) {} + }; + + template + struct construct_by_finit: tbb::internal::no_assign { + Finit f; + void construct(void* where) {new(where) T(f());} + construct_by_finit( const Finit& f_ ) : f(f_) {} + }; + + // storage for initialization function pointer + template + class callback_base { + public: + // Clone *this + virtual callback_base* clone() = 0; + // Destruct and free *this + virtual void destroy() = 0; + // Need virtual destructor to satisfy GCC compiler warning + virtual ~callback_base() { } + // Construct T at where + virtual void construct(void* where) = 0; + }; + + template + class callback_leaf: public callback_base, Constructor { + template callback_leaf( const X& x ) : Constructor(x) {} + + typedef typename tbb::tbb_allocator my_allocator_type; + + /*override*/ callback_base* clone() { + void* where = my_allocator_type().allocate(1); + return new(where) callback_leaf(*this); + } + + /*override*/ void destroy() { + my_allocator_type().destroy(this); + my_allocator_type().deallocate(this,1); + } + + /*override*/ void construct(void* where) { + Constructor::construct(where); + } + public: + template + static callback_base* make( const X& x ) { + void* where = my_allocator_type().allocate(1); + return new(where) callback_leaf(x); + } + }; + + //! Template for adding padding in order to avoid false sharing + /** ModularSize should be sizeof(U) modulo the cache line size. + All maintenance of the space will be done explicitly on push_back, + and all thread local copies must be destroyed before the concurrent + vector is deleted. + */ + template + struct ets_element { + char value[ModularSize==0 ? sizeof(U) : sizeof(U)+(tbb::internal::NFS_MaxLineSize-ModularSize)]; + void unconstruct() { + tbb::internal::punned_cast(&value)->~U(); + } + }; + + } // namespace internal + //! @endcond + + //! The enumerable_thread_specific container + /** enumerable_thread_specific has the following properties: + - thread-local copies are lazily created, with default, exemplar or function initialization. + - thread-local copies do not move (during lifetime, and excepting clear()) so the address of a copy is invariant. + - the contained objects need not have operator=() defined if combine is not used. + - enumerable_thread_specific containers may be copy-constructed or assigned. + - thread-local copies can be managed by hash-table, or can be accessed via TLS storage for speed. + - outside of parallel contexts, the contents of all thread-local copies are accessible by iterator or using combine or combine_each methods + + @par Segmented iterator + When the thread-local objects are containers with input_iterators defined, a segmented iterator may + be used to iterate over all the elements of all thread-local copies. + + @par combine and combine_each + - Both methods are defined for enumerable_thread_specific. + - combine() requires the the type T have operator=() defined. + - neither method modifies the contents of the object (though there is no guarantee that the applied methods do not modify the object.) + - Both are evaluated in serial context (the methods are assumed to be non-benign.) + + @ingroup containers */ + template , + ets_key_usage_type ETS_key_type=ets_no_key > + class enumerable_thread_specific: internal::ets_base { + + template friend class enumerable_thread_specific; + + typedef internal::ets_element padded_element; + + //! A generic range, used to create range objects from the iterators + template + class generic_range_type: public blocked_range { + public: + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; + typedef I iterator; + typedef ptrdiff_t difference_type; + generic_range_type( I begin_, I end_, size_t grainsize_ = 1) : blocked_range(begin_,end_,grainsize_) {} + template + generic_range_type( const generic_range_type& r) : blocked_range(r.begin(),r.end(),r.grainsize()) {} + generic_range_type( generic_range_type& r, split ) : blocked_range(r,split()) {} + }; + + typedef typename Allocator::template rebind< padded_element >::other padded_allocator_type; + typedef tbb::concurrent_vector< padded_element, padded_allocator_type > internal_collection_type; + + internal::callback_base *my_construct_callback; + + internal_collection_type my_locals; + + /*override*/ void* create_local() { +#if TBB_DEPRECATED + void* lref = &my_locals[my_locals.push_back(padded_element())]; +#else + void* lref = &*my_locals.push_back(padded_element()); +#endif + my_construct_callback->construct(lref); + return lref; + } + + void unconstruct_locals() { + for(typename internal_collection_type::iterator cvi = my_locals.begin(); cvi != my_locals.end(); ++cvi) { + cvi->unconstruct(); + } + } + + typedef typename Allocator::template rebind< uintptr_t >::other array_allocator_type; + + // _size is in bytes + /*override*/ void* create_array(size_t _size) { + size_t nelements = (_size + sizeof(uintptr_t) -1) / sizeof(uintptr_t); + return array_allocator_type().allocate(nelements); + } + + /*override*/ void free_array( void* _ptr, size_t _size) { + size_t nelements = (_size + sizeof(uintptr_t) -1) / sizeof(uintptr_t); + array_allocator_type().deallocate( reinterpret_cast(_ptr),nelements); + } + + public: + + //! Basic types + typedef Allocator allocator_type; + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + typedef typename internal_collection_type::size_type size_type; + typedef typename internal_collection_type::difference_type difference_type; + + // Iterator types + typedef typename internal::enumerable_thread_specific_iterator< internal_collection_type, value_type > iterator; + typedef typename internal::enumerable_thread_specific_iterator< internal_collection_type, const value_type > const_iterator; + + // Parallel range types + typedef generic_range_type< iterator > range_type; + typedef generic_range_type< const_iterator > const_range_type; + + //! Default constructor. Each local instance of T is default constructed. + enumerable_thread_specific() : + my_construct_callback( internal::callback_leaf >::make(/*dummy argument*/0) ) + {} + + //! Constructor with initializer functor. Each local instance of T is constructed by T(finit()). + template + enumerable_thread_specific( Finit finit ) : + my_construct_callback( internal::callback_leaf >::make( finit ) ) + {} + + //! Constuctor with exemplar. Each local instance of T is copied-constructed from the exemplar. + enumerable_thread_specific(const T& exemplar) : + my_construct_callback( internal::callback_leaf >::make( exemplar ) ) + {} + + //! Destructor + ~enumerable_thread_specific() { + my_construct_callback->destroy(); + this->clear(); // deallocation before the derived class is finished destructing + // So free(array *) is still accessible + } + + //! returns reference to local, discarding exists + reference local() { + bool exists; + return local(exists); + } + + //! Returns reference to calling thread's local copy, creating one if necessary + reference local(bool& exists) { + void* ptr = this->table_lookup(exists); + return *(T*)ptr; + } + + //! Get the number of local copies + size_type size() const { return my_locals.size(); } + + //! true if there have been no local copies created + bool empty() const { return my_locals.empty(); } + + //! begin iterator + iterator begin() { return iterator( my_locals, 0 ); } + //! end iterator + iterator end() { return iterator(my_locals, my_locals.size() ); } + + //! begin const iterator + const_iterator begin() const { return const_iterator(my_locals, 0); } + + //! end const iterator + const_iterator end() const { return const_iterator(my_locals, my_locals.size()); } + + //! Get range for parallel algorithms + range_type range( size_t grainsize=1 ) { return range_type( begin(), end(), grainsize ); } + + //! Get const range for parallel algorithms + const_range_type range( size_t grainsize=1 ) const { return const_range_type( begin(), end(), grainsize ); } + + //! Destroys local copies + void clear() { + unconstruct_locals(); + my_locals.clear(); + this->table_clear(); + // callback is not destroyed + // exemplar is not destroyed + } + + private: + + template + void internal_copy( const enumerable_thread_specific& other); + + public: + + template + enumerable_thread_specific( const enumerable_thread_specific& other ) : internal::ets_base () + { + internal_copy(other); + } + + enumerable_thread_specific( const enumerable_thread_specific& other ) : internal::ets_base () + { + internal_copy(other); + } + + private: + + template + enumerable_thread_specific & + internal_assign(const enumerable_thread_specific& other) { + if(static_cast( this ) != static_cast( &other )) { + this->clear(); + my_construct_callback->destroy(); + my_construct_callback = 0; + internal_copy( other ); + } + return *this; + } + + public: + + // assignment + enumerable_thread_specific& operator=(const enumerable_thread_specific& other) { + return internal_assign(other); + } + + template + enumerable_thread_specific& operator=(const enumerable_thread_specific& other) + { + return internal_assign(other); + } + + // combine_func_t has signature T(T,T) or T(const T&, const T&) + template + T combine(combine_func_t f_combine) { + if(begin() == end()) { + internal::destruct_only location; + my_construct_callback->construct(location.value.begin()); + return *location.value.begin(); + } + const_iterator ci = begin(); + T my_result = *ci; + while(++ci != end()) + my_result = f_combine( my_result, *ci ); + return my_result; + } + + // combine_func_t has signature void(T) or void(const T&) + template + void combine_each(combine_func_t f_combine) { + for(const_iterator ci = begin(); ci != end(); ++ci) { + f_combine( *ci ); + } + } + + }; // enumerable_thread_specific + + template + template + void enumerable_thread_specific::internal_copy( const enumerable_thread_specific& other) { + // Initialize my_construct_callback first, so that it is valid even if rest of this routine throws an exception. + my_construct_callback = other.my_construct_callback->clone(); + + typedef internal::ets_base base; + __TBB_ASSERT(my_locals.size()==0,NULL); + this->table_reserve_for_copy( other ); + for( base::array* r=other.my_root; r; r=r->next ) { + for( size_t i=0; isize(); ++i ) { + base::slot& s1 = r->at(i); + if( !s1.empty() ) { + base::slot& s2 = this->table_find(s1.key); + if( s2.empty() ) { +#if TBB_DEPRECATED + void* lref = &my_locals[my_locals.push_back(padded_element())]; +#else + void* lref = &*my_locals.push_back(padded_element()); +#endif + s2.ptr = new(lref) T(*(U*)s1.ptr); + s2.key = s1.key; + } else { + // Skip the duplicate + } + } + } + } + } + + template< typename Container > + class flattened2d { + + // This intermediate typedef is to address issues with VC7.1 compilers + typedef typename Container::value_type conval_type; + + public: + + //! Basic types + typedef typename conval_type::size_type size_type; + typedef typename conval_type::difference_type difference_type; + typedef typename conval_type::allocator_type allocator_type; + typedef typename conval_type::value_type value_type; + typedef typename conval_type::reference reference; + typedef typename conval_type::const_reference const_reference; + typedef typename conval_type::pointer pointer; + typedef typename conval_type::const_pointer const_pointer; + + typedef typename internal::segmented_iterator iterator; + typedef typename internal::segmented_iterator const_iterator; + + flattened2d( const Container &c, typename Container::const_iterator b, typename Container::const_iterator e ) : + my_container(const_cast(&c)), my_begin(b), my_end(e) { } + + flattened2d( const Container &c ) : + my_container(const_cast(&c)), my_begin(c.begin()), my_end(c.end()) { } + + iterator begin() { return iterator(*my_container) = my_begin; } + iterator end() { return iterator(*my_container) = my_end; } + const_iterator begin() const { return const_iterator(*my_container) = my_begin; } + const_iterator end() const { return const_iterator(*my_container) = my_end; } + + size_type size() const { + size_type tot_size = 0; + for(typename Container::const_iterator i = my_begin; i != my_end; ++i) { + tot_size += i->size(); + } + return tot_size; + } + + private: + + Container *my_container; + typename Container::const_iterator my_begin; + typename Container::const_iterator my_end; + + }; + + template + flattened2d flatten2d(const Container &c, const typename Container::const_iterator b, const typename Container::const_iterator e) { + return flattened2d(c, b, e); + } + + template + flattened2d flatten2d(const Container &c) { + return flattened2d(c); + } + +} // interface6 + +namespace internal { +using interface6::internal::segmented_iterator; +} + +using interface6::enumerable_thread_specific; +using interface6::flattened2d; +using interface6::flatten2d; + +} // namespace tbb + +#endif diff --git a/src/tbb/include/tbb/flow_graph.h b/src/tbb/include/tbb/flow_graph.h new file mode 100644 index 0000000..0b725a3 --- /dev/null +++ b/src/tbb/include/tbb/flow_graph.h @@ -0,0 +1,1782 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_flow_graph_H +#define __TBB_flow_graph_H + +#include "tbb_stddef.h" +#include "atomic.h" +#include "spin_mutex.h" +#include "null_mutex.h" +#include "spin_rw_mutex.h" +#include "null_rw_mutex.h" +#include "task.h" +#include "concurrent_vector.h" +#include "internal/_aggregator_impl.h" + +// use the VC10 or gcc version of tuple if it is available. +#if TBB_IMPLEMENT_CPP0X && (!defined(_MSC_VER) || _MSC_VER < 1600) +#define TBB_PREVIEW_TUPLE 1 +#include "compat/tuple" +#else +#include +#endif + +#include +#include + +/** @file + \brief The graph related classes and functions + + There are some applications that best express dependencies as messages + passed between nodes in a graph. These messages may contain data or + simply act as signals that a predecessors has completed. The graph + class and its associated node classes can be used to express such + applcations. +*/ + +namespace tbb { +namespace flow { + +//! An enumeration the provides the two most common concurrency levels: unlimited and serial +enum concurrency { unlimited = 0, serial = 1 }; + +namespace interface6 { + +//! An empty class used for messages that mean "I'm done" +class continue_msg {}; + +template< typename T > class sender; +template< typename T > class receiver; +class continue_receiver; + +//! Pure virtual template class that defines a sender of messages of type T +template< typename T > +class sender { +public: + //! The output type of this sender + typedef T output_type; + + //! The successor type for this node + typedef receiver successor_type; + + virtual ~sender() {} + + //! Add a new successor to this node + virtual bool register_successor( successor_type &r ) = 0; + + //! Removes a successor from this node + virtual bool remove_successor( successor_type &r ) = 0; + + //! Request an item from the sender + virtual bool try_get( T & ) { return false; } + + //! Reserves an item in the sender + virtual bool try_reserve( T & ) { return false; } + + //! Releases the reserved item + virtual bool try_release( ) { return false; } + + //! Consumes the reserved item + virtual bool try_consume( ) { return false; } +}; + +//! Pure virtual template class that defines a receiver of messages of type T +template< typename T > +class receiver { +public: + //! The input type of this receiver + typedef T input_type; + + //! The predecessor type for this node + typedef sender predecessor_type; + + //! Destructor + virtual ~receiver() {} + + //! Put an item to the receiver + virtual bool try_put( const T& t ) = 0; + + //! Add a predecessor to the node + virtual bool register_predecessor( predecessor_type & ) { return false; } + + //! Remove a predecessor from the node + virtual bool remove_predecessor( predecessor_type & ) { return false; } +}; + +//! Base class for receivers of completion messages +/** These receivers automatically reset, but cannot be explicitly waited on */ +class continue_receiver : public receiver< continue_msg > { +public: + + //! The input type + typedef continue_msg input_type; + + //! The predecessor type for this node + typedef sender< continue_msg > predecessor_type; + + //! Constructor + continue_receiver( int number_of_predecessors = 0 ) { + my_predecessor_count = my_initial_predecessor_count = number_of_predecessors; + my_current_count = 0; + } + + //! Copy constructor + continue_receiver( const continue_receiver& src ) : receiver() { + my_predecessor_count = my_initial_predecessor_count = src.my_initial_predecessor_count; + my_current_count = 0; + } + + //! Destructor + virtual ~continue_receiver() { } + + //! Increments the trigger threshold + /* override */ bool register_predecessor( predecessor_type & ) { + spin_mutex::scoped_lock l(my_mutex); + ++my_predecessor_count; + return true; + } + + //! Decrements the trigger threshold + /** Does not check to see if the removal of the predecessor now makes the current count + exceed the new threshold. So removing a predecessor while the graph is active can cause + unexpected results. */ + /* override */ bool remove_predecessor( predecessor_type & ) { + spin_mutex::scoped_lock l(my_mutex); + --my_predecessor_count; + return true; + } + + //! Puts a continue_msg to the receiver + /** If the message causes the message count to reach the predecessor count, execute() is called and + the message count is reset to 0. Otherwise the message count is incremented. */ + /* override */ bool try_put( const input_type & ) { + { + spin_mutex::scoped_lock l(my_mutex); + if ( ++my_current_count < my_predecessor_count ) + return true; + else + my_current_count = 0; + } + execute(); + return true; + } + +protected: + spin_mutex my_mutex; + int my_predecessor_count; + int my_current_count; + int my_initial_predecessor_count; + + //! Does whatever should happen when the threshold is reached + /** This should be very fast or else spawn a task. This is + called while the sender is blocked in the try_put(). */ + virtual void execute() = 0; +}; + +#include "internal/_flow_graph_impl.h" +using namespace internal::graph_policy_namespace; + +class graph; +class graph_node; + +template +class graph_iterator { + friend class graph; + friend class graph_node; +public: + typedef size_t size_type; + typedef GraphNodeType value_type; + typedef GraphNodeType* pointer; + typedef GraphNodeType& reference; + typedef const GraphNodeType& const_reference; + typedef std::forward_iterator_tag iterator_category; + + //! Default constructor + graph_iterator() : my_graph(NULL), current_node(NULL) {} + + //! Copy constructor + graph_iterator(const graph_iterator& other) : + my_graph(other.my_graph), current_node(other.current_node) + {} + + //! Assignment + graph_iterator& operator=(const graph_iterator& other) { + if (this != &other) { + my_graph = other.my_graph; + current_node = other.current_node; + } + return *this; + } + + //! Dereference + reference operator*() const; + + //! Dereference + pointer operator->() const; + + //! Equality + bool operator==(const graph_iterator& other) const { + return ((my_graph == other.my_graph) && (current_node == other.current_node)); + } + + //! Inequality + bool operator!=(const graph_iterator& other) const { return !(operator==(other)); } + + //! Pre-increment + graph_iterator& operator++() { + internal_forward(); + return *this; + } + + //! Post-increment + graph_iterator operator++(int) { + graph_iterator result = *this; + operator++(); + return result; + } + +private: + // the graph over which we are iterating + GraphContainerType *my_graph; + // pointer into my_graph's my_nodes list + pointer current_node; + + //! Private initializing constructor for begin() and end() iterators + graph_iterator(GraphContainerType *g, bool begin); + void internal_forward(); +}; + +//! The graph class +/** This class serves as a handle to the graph */ +class graph : tbb::internal::no_copy { + friend class graph_node; + + template< typename Body > + class run_task : public task { + public: + run_task( Body& body ) : my_body(body) {} + task *execute() { + my_body(); + return NULL; + } + private: + Body my_body; + }; + + template< typename Receiver, typename Body > + class run_and_put_task : public task { + public: + run_and_put_task( Receiver &r, Body& body ) : my_receiver(r), my_body(body) {} + task *execute() { + my_receiver.try_put( my_body() ); + return NULL; + } + private: + Receiver &my_receiver; + Body my_body; + }; + +public: + //! Constructs a graph with isolated task_group_context + explicit graph() : my_nodes(NULL), my_nodes_last(NULL) + { + own_context = true; + cancelled = false; + caught_exception = false; + my_context = new task_group_context(); + my_root_task = ( new ( task::allocate_root(*my_context) ) empty_task ); + my_root_task->set_ref_count(1); + } + + //! Constructs a graph with use_this_context as context + explicit graph(task_group_context& use_this_context) : + my_context(&use_this_context), my_nodes(NULL), my_nodes_last(NULL) + { + own_context = false; + my_root_task = ( new ( task::allocate_root(*my_context) ) empty_task ); + my_root_task->set_ref_count(1); + } + + //! Destroys the graph. + /** Calls wait_for_all, then destroys the root task and context. */ + ~graph() { + wait_for_all(); + my_root_task->set_ref_count(0); + task::destroy( *my_root_task ); + if (own_context) delete my_context; + } + + //! Used to register that an external entity may still interact with the graph. + /** The graph will not return from wait_for_all until a matching number of decrement_wait_count calls + is made. */ + void increment_wait_count() { + if (my_root_task) + my_root_task->increment_ref_count(); + } + + //! Deregisters an external entity that may have interacted with the graph. + /** The graph will not return from wait_for_all until all the number of decrement_wait_count calls + matches the number of increment_wait_count calls. */ + void decrement_wait_count() { + if (my_root_task) + my_root_task->decrement_ref_count(); + } + + //! Spawns a task that runs a body and puts its output to a specific receiver + /** The task is spawned as a child of the graph. This is useful for running tasks + that need to block a wait_for_all() on the graph. For example a one-off source. */ + template< typename Receiver, typename Body > + void run( Receiver &r, Body body ) { + task::enqueue( * new ( task::allocate_additional_child_of( *my_root_task ) ) + run_and_put_task< Receiver, Body >( r, body ) ); + } + + //! Spawns a task that runs a function object + /** The task is spawned as a child of the graph. This is useful for running tasks + that need to block a wait_for_all() on the graph. For example a one-off source. */ + template< typename Body > + void run( Body body ) { + task::enqueue( * new ( task::allocate_additional_child_of( *my_root_task ) ) + run_task< Body >( body ) ); + } + + //! Wait until graph is idle and decrement_wait_count calls equals increment_wait_count calls. + /** The waiting thread will go off and steal work while it is block in the wait_for_all. */ + void wait_for_all() { + cancelled = false; + caught_exception = false; + if (my_root_task) { +#if TBB_USE_EXCEPTIONS + try { +#endif + my_root_task->wait_for_all(); + cancelled = my_context->is_group_execution_cancelled(); +#if TBB_USE_EXCEPTIONS + } + catch(...) { + my_root_task->set_ref_count(1); + my_context->reset(); + caught_exception = true; + cancelled = true; + throw; + } +#endif + my_root_task->set_ref_count(1); + } + } + + //! Returns the root task of the graph + task * root_task() { + return my_root_task; + } + + // ITERATORS + template + friend class graph_iterator; + + // Graph iterator typedefs + typedef graph_iterator iterator; + typedef graph_iterator const_iterator; + + // Graph iterator constructors + //! start iterator + iterator begin() { return iterator(this, true); } + //! end iterator + iterator end() { return iterator(this, false); } + //! start const iterator + const_iterator begin() const { return const_iterator(this, true); } + //! end const iterator + const_iterator end() const { return const_iterator(this, false); } + //! start const iterator + const_iterator cbegin() const { return const_iterator(this, true); } + //! end const iterator + const_iterator cend() const { return const_iterator(this, false); } + + //! return status of graph execution + bool is_cancelled() { return cancelled; } + bool exception_thrown() { return caught_exception; } + +private: + task *my_root_task; + task_group_context *my_context; + bool own_context; + bool cancelled; + bool caught_exception; + + graph_node *my_nodes, *my_nodes_last; + + spin_mutex nodelist_mutex; + void register_node(graph_node *n); + void remove_node(graph_node *n); + +}; + +template +graph_iterator::graph_iterator(C *g, bool begin) : my_graph(g), current_node(NULL) +{ + if (begin) current_node = my_graph->my_nodes; + //else it is an end iterator by default +} + +template +typename graph_iterator::reference graph_iterator::operator*() const { + __TBB_ASSERT(current_node, "graph_iterator at end"); + return *operator->(); +} + +template +typename graph_iterator::pointer graph_iterator::operator->() const { + return current_node; +} + + +template +void graph_iterator::internal_forward() { + if (current_node) current_node = current_node->next; +} + +//! The base of all graph nodes. +class graph_node : tbb::internal::no_assign { + friend class graph; + template + friend class graph_iterator; +protected: + graph& my_graph; + graph_node *next, *prev; +public: + graph_node(graph& g) : my_graph(g) { + my_graph.register_node(this); + } + virtual ~graph_node() { + my_graph.remove_node(this); + } +}; + +inline void graph::register_node(graph_node *n) { + n->next = NULL; + { + spin_mutex::scoped_lock lock(nodelist_mutex); + n->prev = my_nodes_last; + if (my_nodes_last) my_nodes_last->next = n; + my_nodes_last = n; + if (!my_nodes) my_nodes = n; + } +} + +inline void graph::remove_node(graph_node *n) { + { + spin_mutex::scoped_lock lock(nodelist_mutex); + __TBB_ASSERT(my_nodes && my_nodes_last, "graph::remove_node: Error: no registered nodes"); + if (n->prev) n->prev->next = n->next; + if (n->next) n->next->prev = n->prev; + if (my_nodes_last == n) my_nodes_last = n->prev; + if (my_nodes == n) my_nodes = n->next; + } + n->prev = n->next = NULL; +} + +#include "internal/_flow_graph_node_impl.h" + +//! An executable node that acts as a source, i.e. it has no predecessors +template < typename Output > +class source_node : public graph_node, public sender< Output > { + using graph_node::my_graph; +public: + //! The type of the output message, which is complete + typedef Output output_type; + + //! The type of successors of this node + typedef receiver< Output > successor_type; + + //! Constructor for a node with a successor + template< typename Body > + source_node( graph &g, Body body, bool is_active = true ) + : graph_node(g), my_root_task(g.root_task()), my_active(is_active), init_my_active(is_active), + my_body( new internal::source_body_leaf< output_type, Body>(body) ), + my_reserved(false), my_has_cached_item(false) + { + my_successors.set_owner(this); + } + + //! Copy constructor + source_node( const source_node& src ) : + graph_node(src.my_graph), sender(), + my_root_task( src.my_root_task), my_active(src.init_my_active), + init_my_active(src.init_my_active), my_body( src.my_body->clone() ), + my_reserved(false), my_has_cached_item(false) + { + my_successors.set_owner(this); + } + + //! The destructor + ~source_node() { delete my_body; } + + //! Add a new successor to this node + /* override */ bool register_successor( receiver &r ) { + spin_mutex::scoped_lock lock(my_mutex); + my_successors.register_successor(r); + if ( my_active ) + spawn_put(); + return true; + } + + //! Removes a successor from this node + /* override */ bool remove_successor( receiver &r ) { + spin_mutex::scoped_lock lock(my_mutex); + my_successors.remove_successor(r); + return true; + } + + //! Request an item from the node + /*override */ bool try_get( output_type &v ) { + spin_mutex::scoped_lock lock(my_mutex); + if ( my_reserved ) + return false; + + if ( my_has_cached_item ) { + v = my_cached_item; + my_has_cached_item = false; + } else if ( (*my_body)(v) == false ) { + return false; + } + return true; + } + + //! Reserves an item. + /* override */ bool try_reserve( output_type &v ) { + spin_mutex::scoped_lock lock(my_mutex); + if ( my_reserved ) { + return false; + } + + if ( !my_has_cached_item && (*my_body)(my_cached_item) ) + my_has_cached_item = true; + + if ( my_has_cached_item ) { + v = my_cached_item; + my_reserved = true; + return true; + } else { + return false; + } + } + + //! Release a reserved item. + /** true = item has been released and so remains in sender, dest must request or reserve future items */ + /* override */ bool try_release( ) { + spin_mutex::scoped_lock lock(my_mutex); + __TBB_ASSERT( my_reserved && my_has_cached_item, "releasing non-existent reservation" ); + my_reserved = false; + if(!my_successors.empty()) + spawn_put(); + return true; + } + + //! Consumes a reserved item + /* override */ bool try_consume( ) { + spin_mutex::scoped_lock lock(my_mutex); + __TBB_ASSERT( my_reserved && my_has_cached_item, "consuming non-existent reservation" ); + my_reserved = false; + my_has_cached_item = false; + if ( !my_successors.empty() ) { + spawn_put(); + } + return true; + } + + //! Activates a node that was created in the inactive state + void activate() { + spin_mutex::scoped_lock lock(my_mutex); + my_active = true; + if ( !my_successors.empty() ) + spawn_put(); + } + +private: + task *my_root_task; + spin_mutex my_mutex; + bool my_active; + bool init_my_active; + internal::source_body *my_body; + internal::broadcast_cache< output_type > my_successors; + bool my_reserved; + bool my_has_cached_item; + output_type my_cached_item; + + friend class internal::source_task< source_node< output_type > >; + + //! Applies the body + /* override */ void apply_body( ) { + output_type v; + if ( try_reserve(v) == false ) + return; + + if ( my_successors.try_put( v ) ) + try_consume(); + else + try_release(); + } + + //! Spawns a task that applies the body + /* override */ void spawn_put( ) { + task::enqueue( * new ( task::allocate_additional_child_of( *my_root_task ) ) + internal::source_task< source_node< output_type > >( *this ) ); + } +}; + +//! Implements a function node that supports Input -> Output +template < typename Input, typename Output = continue_msg, graph_buffer_policy = queueing, typename Allocator=cache_aligned_allocator > +class function_node : public graph_node, public internal::function_input, public internal::function_output { + using graph_node::my_graph; +public: + typedef Input input_type; + typedef Output output_type; + typedef sender< input_type > predecessor_type; + typedef receiver< output_type > successor_type; + typedef internal::function_input fInput_type; + typedef internal::function_output fOutput_type; + + //! Constructor + template< typename Body > + function_node( graph &g, size_t concurrency, Body body ) : + graph_node(g), internal::function_input(g, concurrency, body) + {} + + //! Copy constructor + function_node( const function_node& src ) : + graph_node(src.my_graph), internal::function_input( src ), + fOutput_type() + {} + + bool try_put(const input_type &i) { return fInput_type::try_put(i); } + +protected: + /* override */ internal::broadcast_cache &successors () { return fOutput_type::my_successors; } +}; + +//! Implements a function node that supports Input -> Output +template < typename Input, typename Output, typename Allocator > +class function_node : public graph_node, public internal::function_input, public internal::function_output { + using graph_node::my_graph; +public: + typedef Input input_type; + typedef Output output_type; + typedef sender< input_type > predecessor_type; + typedef receiver< output_type > successor_type; + typedef internal::function_input fInput_type; + typedef internal::function_input_queue queue_type; + typedef internal::function_output fOutput_type; + + //! Constructor + template< typename Body > + function_node( graph &g, size_t concurrency, Body body ) : + graph_node(g), fInput_type( g, concurrency, body, new queue_type() ) + {} + + //! Copy constructor + function_node( const function_node& src ) : + graph_node(src.my_graph), fInput_type( src, new queue_type() ), fOutput_type() + {} + + bool try_put(const input_type &i) { return fInput_type::try_put(i); } + +protected: + /* override */ internal::broadcast_cache &successors () { return fOutput_type::my_successors; } +}; + +#include "tbb/internal/_flow_graph_types_impl.h" + +//! implements a function node that supports Input -> (set of outputs) +// Output is a tuple of output types. +template < typename Input, typename Output, graph_buffer_policy = queueing, typename Allocator=cache_aligned_allocator > +class multifunction_node : + public graph_node, + public internal::multifunction_input + < + Input, + typename internal::wrap_tuple_elements< + std::tuple_size::value, // #elements in tuple + internal::function_output, // wrap this around each element + Output // the tuple providing the types + >::type, + Allocator + > { + using graph_node::my_graph; +private: + static const int N = std::tuple_size::value; +public: + typedef Input input_type; + typedef typename internal::wrap_tuple_elements::type output_ports_type; +private: + typedef typename internal::multifunction_input base_type; + typedef typename internal::function_input_queue queue_type; +public: + template + multifunction_node( graph &g, size_t concurrency, Body body ) : + graph_node(g), base_type(g,concurrency, body) + {} + multifunction_node( const multifunction_node &other) : + graph_node(other.my_graph), base_type(other) + {} + // all the guts are in multifunction_input... +}; // multifunction_node + +template < typename Input, typename Output, typename Allocator > +class multifunction_node : public graph_node, public internal::multifunction_input::value, internal::function_output, Output>::type, Allocator> { + using graph_node::my_graph; + static const int N = std::tuple_size::value; +public: + typedef Input input_type; + typedef typename internal::wrap_tuple_elements::type output_ports_type; +private: + typedef typename internal::multifunction_input base_type; + typedef typename internal::function_input_queue queue_type; +public: + template + multifunction_node( graph &g, size_t concurrency, Body body) : + graph_node(g), base_type(g,concurrency, body, new queue_type()) + {} + multifunction_node( const multifunction_node &other) : + graph_node(other.my_graph), base_type(other, new queue_type()) + {} +}; // multifunction_node + +//! split_node: accepts a tuple as input, forwards each element of the tuple to its +// successors. The node has unlimited concurrency, so though it is marked as +// "rejecting" it does not reject inputs. +template > +class split_node : public multifunction_node { + static const int N = std::tuple_size::value; + typedef multifunction_node base_type; +public: + typedef typename base_type::output_ports_type output_ports_type; +private: + struct splitting_body { + void operator()(const TupleType& t, output_ports_type &p) { + internal::emit_element::emit_this(t, p); + } + }; +public: + typedef TupleType input_type; + typedef Allocator allocator_type; + split_node(graph &g) : base_type(g, unlimited, splitting_body()) {} + split_node( const split_node & other) : base_type(other) {} +}; + +//! Implements an executable node that supports continue_msg -> Output +template +class continue_node : public graph_node, public internal::continue_input, public internal::function_output { + using graph_node::my_graph; +public: + typedef continue_msg input_type; + typedef Output output_type; + typedef sender< input_type > predecessor_type; + typedef receiver< output_type > successor_type; + typedef internal::function_output fOutput_type; + + //! Constructor for executable node with continue_msg -> Output + template + continue_node( graph &g, Body body ) : + graph_node(g), internal::continue_input( g, body ) + {} + + //! Constructor for executable node with continue_msg -> Output + template + continue_node( graph &g, int number_of_predecessors, Body body ) : + graph_node(g), internal::continue_input( g, number_of_predecessors, body ) + {} + + //! Copy constructor + continue_node( const continue_node& src ) : + graph_node(src.my_graph), internal::continue_input(src), + internal::function_output() + {} + + bool try_put(const input_type &i) { return internal::continue_input::try_put(i); } + +protected: + /* override */ internal::broadcast_cache &successors () { return fOutput_type::my_successors; } +}; + +template< typename T > +class overwrite_node : public graph_node, public receiver, public sender { + using graph_node::my_graph; +public: + typedef T input_type; + typedef T output_type; + typedef sender< input_type > predecessor_type; + typedef receiver< output_type > successor_type; + + overwrite_node(graph &g) : graph_node(g), my_buffer_is_valid(false) { + my_successors.set_owner( this ); + } + + // Copy constructor; doesn't take anything from src; default won't work + overwrite_node( const overwrite_node& src ) : + graph_node(src.my_graph), receiver(), sender(), my_buffer_is_valid(false) + { + my_successors.set_owner( this ); + } + + ~overwrite_node() {} + + /* override */ bool register_successor( successor_type &s ) { + spin_mutex::scoped_lock l( my_mutex ); + if ( my_buffer_is_valid ) { + // We have a valid value that must be forwarded immediately. + if ( s.try_put( my_buffer ) || !s.register_predecessor( *this ) ) { + // We add the successor: it accepted our put or it rejected it but won't let use become a predecessor + my_successors.register_successor( s ); + return true; + } else { + // We don't add the successor: it rejected our put and we became its predecessor instead + return false; + } + } else { + // No valid value yet, just add as successor + my_successors.register_successor( s ); + return true; + } + } + + /* override */ bool remove_successor( successor_type &s ) { + spin_mutex::scoped_lock l( my_mutex ); + my_successors.remove_successor(s); + return true; + } + + /* override */ bool try_put( const T &v ) { + spin_mutex::scoped_lock l( my_mutex ); + my_buffer = v; + my_buffer_is_valid = true; + my_successors.try_put(v); + return true; + } + + /* override */ bool try_get( T &v ) { + spin_mutex::scoped_lock l( my_mutex ); + if ( my_buffer_is_valid ) { + v = my_buffer; + return true; + } else { + return false; + } + } + + bool is_valid() { + spin_mutex::scoped_lock l( my_mutex ); + return my_buffer_is_valid; + } + + void clear() { + spin_mutex::scoped_lock l( my_mutex ); + my_buffer_is_valid = false; + } + +protected: + spin_mutex my_mutex; + internal::broadcast_cache< T, null_rw_mutex > my_successors; + T my_buffer; + bool my_buffer_is_valid; +}; + +template< typename T > +class write_once_node : public overwrite_node { +public: + typedef T input_type; + typedef T output_type; + typedef sender< input_type > predecessor_type; + typedef receiver< output_type > successor_type; + + //! Constructor + write_once_node(graph& g) : overwrite_node(g) {} + + //! Copy constructor: call base class copy constructor + write_once_node( const write_once_node& src ) : overwrite_node(src) {} + + /* override */ bool try_put( const T &v ) { + spin_mutex::scoped_lock l( this->my_mutex ); + if ( this->my_buffer_is_valid ) { + return false; + } else { + this->my_buffer = v; + this->my_buffer_is_valid = true; + this->my_successors.try_put(v); + return true; + } + } +}; + +//! Forwards messages of type T to all successors +template +class broadcast_node : public graph_node, public receiver, public sender { + using graph_node::my_graph; + internal::broadcast_cache my_successors; +public: + typedef T input_type; + typedef T output_type; + typedef sender< input_type > predecessor_type; + typedef receiver< output_type > successor_type; + + broadcast_node(graph& g) : graph_node(g) { + my_successors.set_owner( this ); + } + + // Copy constructor + broadcast_node( const broadcast_node& src ) : + graph_node(src.my_graph), receiver(), sender() + { + my_successors.set_owner( this ); + } + + //! Adds a successor + virtual bool register_successor( receiver &r ) { + my_successors.register_successor( r ); + return true; + } + + //! Removes s as a successor + virtual bool remove_successor( receiver &r ) { + my_successors.remove_successor( r ); + return true; + } + + /* override */ bool try_put( const T &t ) { + my_successors.try_put(t); + return true; + } +}; + +#include "internal/_flow_graph_item_buffer_impl.h" + +//! Forwards messages in arbitrary order +template > +class buffer_node : public graph_node, public reservable_item_buffer, public receiver, public sender { + using graph_node::my_graph; +public: + typedef T input_type; + typedef T output_type; + typedef sender< input_type > predecessor_type; + typedef receiver< output_type > successor_type; + typedef buffer_node my_class; +protected: + typedef size_t size_type; + internal::round_robin_cache< T, null_rw_mutex > my_successors; + + task *my_parent; + + friend class internal::forward_task< buffer_node< T, A > >; + + enum op_type {reg_succ, rem_succ, req_item, res_item, rel_res, con_res, put_item, try_fwd}; + enum op_stat {WAIT=0, SUCCEEDED, FAILED}; + + // implements the aggregator_operation concept + class buffer_operation : public internal::aggregated_operation< buffer_operation > { + public: + char type; + T *elem; + successor_type *r; + buffer_operation(const T& e, op_type t) : + type(char(t)), elem(const_cast(&e)), r(NULL) {} + buffer_operation(op_type t) : type(char(t)), r(NULL) {} + }; + + bool forwarder_busy; + typedef internal::aggregating_functor my_handler; + friend class internal::aggregating_functor; + internal::aggregator< my_handler, buffer_operation> my_aggregator; + + virtual void handle_operations(buffer_operation *op_list) { + buffer_operation *tmp; + bool try_forwarding=false; + while (op_list) { + tmp = op_list; + op_list = op_list->next; + switch (tmp->type) { + case reg_succ: internal_reg_succ(tmp); try_forwarding = true; break; + case rem_succ: internal_rem_succ(tmp); break; + case req_item: internal_pop(tmp); break; + case res_item: internal_reserve(tmp); break; + case rel_res: internal_release(tmp); try_forwarding = true; break; + case con_res: internal_consume(tmp); try_forwarding = true; break; + case put_item: internal_push(tmp); try_forwarding = true; break; + case try_fwd: internal_forward(tmp); break; + } + } + if (try_forwarding && !forwarder_busy) { + forwarder_busy = true; + task::enqueue(*new(task::allocate_additional_child_of(*my_parent)) internal::forward_task< buffer_node >(*this)); + } + } + + //! This is executed by an enqueued task, the "forwarder" + virtual void forward() { + buffer_operation op_data(try_fwd); + do { + op_data.status = WAIT; + my_aggregator.execute(&op_data); + } while (op_data.status == SUCCEEDED); + } + + //! Register successor + virtual void internal_reg_succ(buffer_operation *op) { + my_successors.register_successor(*(op->r)); + __TBB_store_with_release(op->status, SUCCEEDED); + } + + //! Remove successor + virtual void internal_rem_succ(buffer_operation *op) { + my_successors.remove_successor(*(op->r)); + __TBB_store_with_release(op->status, SUCCEEDED); + } + + //! Tries to forward valid items to successors + virtual void internal_forward(buffer_operation *op) { + T i_copy; + bool success = false; // flagged when a successor accepts + size_type counter = my_successors.size(); + // Try forwarding, giving each successor a chance + while (counter>0 && !this->buffer_empty() && this->item_valid(this->my_tail-1)) { + this->fetch_back(i_copy); + if( my_successors.try_put(i_copy) ) { + this->invalidate_back(); + --(this->my_tail); + success = true; // found an accepting successor + } + --counter; + } + if (success && !counter) + __TBB_store_with_release(op->status, SUCCEEDED); + else { + __TBB_store_with_release(op->status, FAILED); + forwarder_busy = false; + } + } + + virtual void internal_push(buffer_operation *op) { + this->push_back(*(op->elem)); + __TBB_store_with_release(op->status, SUCCEEDED); + } + + virtual void internal_pop(buffer_operation *op) { + if(this->pop_back(*(op->elem))) { + __TBB_store_with_release(op->status, SUCCEEDED); + } + else { + __TBB_store_with_release(op->status, FAILED); + } + } + + virtual void internal_reserve(buffer_operation *op) { + if(this->reserve_front(*(op->elem))) { + __TBB_store_with_release(op->status, SUCCEEDED); + } + else { + __TBB_store_with_release(op->status, FAILED); + } + } + + virtual void internal_consume(buffer_operation *op) { + this->consume_front(); + __TBB_store_with_release(op->status, SUCCEEDED); + } + + virtual void internal_release(buffer_operation *op) { + this->release_front(); + __TBB_store_with_release(op->status, SUCCEEDED); + } + +public: + //! Constructor + buffer_node( graph &g ) : graph_node(g), reservable_item_buffer(), + my_parent( g.root_task() ), forwarder_busy(false) { + my_successors.set_owner(this); + my_aggregator.initialize_handler(my_handler(this)); + } + + //! Copy constructor + buffer_node( const buffer_node& src ) : graph_node(src.my_graph), + reservable_item_buffer(), receiver(), sender(), + my_parent( src.my_parent ) { + forwarder_busy = false; + my_successors.set_owner(this); + my_aggregator.initialize_handler(my_handler(this)); + } + + virtual ~buffer_node() {} + + // + // message sender implementation + // + + //! Adds a new successor. + /** Adds successor r to the list of successors; may forward tasks. */ + /* override */ bool register_successor( receiver &r ) { + buffer_operation op_data(reg_succ); + op_data.r = &r; + my_aggregator.execute(&op_data); + return true; + } + + //! Removes a successor. + /** Removes successor r from the list of successors. + It also calls r.remove_predecessor(*this) to remove this node as a predecessor. */ + /* override */ bool remove_successor( receiver &r ) { + r.remove_predecessor(*this); + buffer_operation op_data(rem_succ); + op_data.r = &r; + my_aggregator.execute(&op_data); + return true; + } + + //! Request an item from the buffer_node + /** true = v contains the returned item
    + false = no item has been returned */ + /* override */ bool try_get( T &v ) { + buffer_operation op_data(req_item); + op_data.elem = &v; + my_aggregator.execute(&op_data); + return (op_data.status==SUCCEEDED); + } + + //! Reserves an item. + /** false = no item can be reserved
    + true = an item is reserved */ + /* override */ bool try_reserve( T &v ) { + buffer_operation op_data(res_item); + op_data.elem = &v; + my_aggregator.execute(&op_data); + return (op_data.status==SUCCEEDED); + } + + //! Release a reserved item. + /** true = item has been released and so remains in sender */ + /* override */ bool try_release() { + buffer_operation op_data(rel_res); + my_aggregator.execute(&op_data); + return true; + } + + //! Consumes a reserved item. + /** true = item is removed from sender and reservation removed */ + /* override */ bool try_consume() { + buffer_operation op_data(con_res); + my_aggregator.execute(&op_data); + return true; + } + + //! Receive an item + /** true is always returned */ + /* override */ bool try_put(const T &t) { + buffer_operation op_data(t, put_item); + my_aggregator.execute(&op_data); + return true; + } +}; + +//! Forwards messages in FIFO order +template > +class queue_node : public buffer_node { +protected: + typedef typename buffer_node::size_type size_type; + typedef typename buffer_node::buffer_operation queue_operation; + + enum op_stat {WAIT=0, SUCCEEDED, FAILED}; + + //! Tries to forward valid items to successors + /* override */ void internal_forward(queue_operation *op) { + T i_copy; + bool success = false; // flagged when a successor accepts + size_type counter = this->my_successors.size(); + if (this->my_reserved || !this->item_valid(this->my_head)) { + __TBB_store_with_release(op->status, FAILED); + this->forwarder_busy = false; + return; + } + // Keep trying to send items while there is at least one accepting successor + while (counter>0 && this->item_valid(this->my_head)) { + this->fetch_front(i_copy); + if(this->my_successors.try_put(i_copy)) { + this->invalidate_front(); + ++(this->my_head); + success = true; // found an accepting successor + } + --counter; + } + if (success && !counter) + __TBB_store_with_release(op->status, SUCCEEDED); + else { + __TBB_store_with_release(op->status, FAILED); + this->forwarder_busy = false; + } + } + + /* override */ void internal_pop(queue_operation *op) { + if ( this->my_reserved || !this->item_valid(this->my_head)){ + __TBB_store_with_release(op->status, FAILED); + } + else { + this->pop_front(*(op->elem)); + __TBB_store_with_release(op->status, SUCCEEDED); + } + } + /* override */ void internal_reserve(queue_operation *op) { + if (this->my_reserved || !this->item_valid(this->my_head)) { + __TBB_store_with_release(op->status, FAILED); + } + else { + this->my_reserved = true; + this->fetch_front(*(op->elem)); + this->invalidate_front(); + __TBB_store_with_release(op->status, SUCCEEDED); + } + } + /* override */ void internal_consume(queue_operation *op) { + this->consume_front(); + __TBB_store_with_release(op->status, SUCCEEDED); + } + +public: + typedef T input_type; + typedef T output_type; + typedef sender< input_type > predecessor_type; + typedef receiver< output_type > successor_type; + + //! Constructor + queue_node( graph &g ) : buffer_node(g) {} + + //! Copy constructor + queue_node( const queue_node& src) : buffer_node(src) {} +}; + +//! Forwards messages in sequence order +template< typename T, typename A=cache_aligned_allocator > +class sequencer_node : public queue_node { + internal::function_body< T, size_t > *my_sequencer; +public: + typedef T input_type; + typedef T output_type; + typedef sender< input_type > predecessor_type; + typedef receiver< output_type > successor_type; + + //! Constructor + template< typename Sequencer > + sequencer_node( graph &g, const Sequencer& s ) : queue_node(g), + my_sequencer(new internal::function_body_leaf< T, size_t, Sequencer>(s) ) {} + + //! Copy constructor + sequencer_node( const sequencer_node& src ) : queue_node(src), + my_sequencer( src.my_sequencer->clone() ) {} + + //! Destructor + ~sequencer_node() { delete my_sequencer; } +protected: + typedef typename buffer_node::size_type size_type; + typedef typename buffer_node::buffer_operation sequencer_operation; + + enum op_stat {WAIT=0, SUCCEEDED, FAILED}; + +private: + /* override */ void internal_push(sequencer_operation *op) { + size_type tag = (*my_sequencer)(*(op->elem)); + + this->my_tail = (tag+1 > this->my_tail) ? tag+1 : this->my_tail; + + if(this->size() > this->capacity()) + this->grow_my_array(this->size()); // tail already has 1 added to it + this->item(tag) = std::make_pair( *(op->elem), true ); + __TBB_store_with_release(op->status, SUCCEEDED); + } +}; + +//! Forwards messages in priority order +template< typename T, typename Compare = std::less, typename A=cache_aligned_allocator > +class priority_queue_node : public buffer_node { +public: + typedef T input_type; + typedef T output_type; + typedef sender< input_type > predecessor_type; + typedef receiver< output_type > successor_type; + + //! Constructor + priority_queue_node( graph &g ) : buffer_node(g), mark(0) {} + + //! Copy constructor + priority_queue_node( const priority_queue_node &src ) : buffer_node(src), mark(0) {} + +protected: + typedef typename buffer_node::size_type size_type; + typedef typename buffer_node::item_type item_type; + typedef typename buffer_node::buffer_operation prio_operation; + + enum op_stat {WAIT=0, SUCCEEDED, FAILED}; + + /* override */ void handle_operations(prio_operation *op_list) { + prio_operation *tmp /*, *pop_list*/ ; + bool try_forwarding=false; + while (op_list) { + tmp = op_list; + op_list = op_list->next; + switch (tmp->type) { + case buffer_node::reg_succ: this->internal_reg_succ(tmp); try_forwarding = true; break; + case buffer_node::rem_succ: this->internal_rem_succ(tmp); break; + case buffer_node::put_item: internal_push(tmp); try_forwarding = true; break; + case buffer_node::try_fwd: internal_forward(tmp); break; + case buffer_node::rel_res: internal_release(tmp); try_forwarding = true; break; + case buffer_node::con_res: internal_consume(tmp); try_forwarding = true; break; + case buffer_node::req_item: internal_pop(tmp); break; + case buffer_node::res_item: internal_reserve(tmp); break; + } + } + // process pops! for now, no special pop processing + if (markmy_tail) heapify(); + if (try_forwarding && !this->forwarder_busy) { + this->forwarder_busy = true; + task::enqueue(*new(task::allocate_additional_child_of(*(this->my_parent))) internal::forward_task< buffer_node >(*this)); + } + } + + //! Tries to forward valid items to successors + /* override */ void internal_forward(prio_operation *op) { + T i_copy; + bool success = false; // flagged when a successor accepts + size_type counter = this->my_successors.size(); + + if (this->my_reserved || this->my_tail == 0) { + __TBB_store_with_release(op->status, FAILED); + this->forwarder_busy = false; + return; + } + // Keep trying to send while there exists an accepting successor + while (counter>0 && this->my_tail > 0) { + i_copy = this->my_array[0].first; + bool msg = this->my_successors.try_put(i_copy); + if ( msg == true ) { + if (mark == this->my_tail) --mark; + --(this->my_tail); + this->my_array[0].first=this->my_array[this->my_tail].first; + if (this->my_tail > 1) // don't reheap for heap of size 1 + reheap(); + success = true; // found an accepting successor + } + --counter; + } + if (success && !counter) + __TBB_store_with_release(op->status, SUCCEEDED); + else { + __TBB_store_with_release(op->status, FAILED); + this->forwarder_busy = false; + } + } + + /* override */ void internal_push(prio_operation *op) { + if ( this->my_tail >= this->my_array_size ) + this->grow_my_array( this->my_tail + 1 ); + this->my_array[this->my_tail] = std::make_pair( *(op->elem), true ); + ++(this->my_tail); + __TBB_store_with_release(op->status, SUCCEEDED); + } + /* override */ void internal_pop(prio_operation *op) { + if ( this->my_reserved == true || this->my_tail == 0 ) { + __TBB_store_with_release(op->status, FAILED); + } + else { + if (markmy_tail && + compare(this->my_array[0].first, + this->my_array[this->my_tail-1].first)) { + // there are newly pushed elems; last one higher than top + // copy the data + *(op->elem) = this->my_array[this->my_tail-1].first; + --(this->my_tail); + __TBB_store_with_release(op->status, SUCCEEDED); + } + else { // extract and push the last element down heap + *(op->elem) = this->my_array[0].first; // copy the data + if (mark == this->my_tail) --mark; + --(this->my_tail); + __TBB_store_with_release(op->status, SUCCEEDED); + this->my_array[0].first=this->my_array[this->my_tail].first; + if (this->my_tail > 1) // don't reheap for heap of size 1 + reheap(); + } + } + } + /* override */ void internal_reserve(prio_operation *op) { + if (this->my_reserved == true || this->my_tail == 0) { + __TBB_store_with_release(op->status, FAILED); + } + else { + this->my_reserved = true; + *(op->elem) = reserved_item = this->my_array[0].first; + if (mark == this->my_tail) --mark; + --(this->my_tail); + __TBB_store_with_release(op->status, SUCCEEDED); + this->my_array[0].first = this->my_array[this->my_tail].first; + if (this->my_tail > 1) // don't reheap for heap of size 1 + reheap(); + } + } + /* override */ void internal_consume(prio_operation *op) { + this->my_reserved = false; + __TBB_store_with_release(op->status, SUCCEEDED); + } + /* override */ void internal_release(prio_operation *op) { + if (this->my_tail >= this->my_array_size) + this->grow_my_array( this->my_tail + 1 ); + this->my_array[this->my_tail] = std::make_pair(reserved_item, true); + ++(this->my_tail); + this->my_reserved = false; + __TBB_store_with_release(op->status, SUCCEEDED); + heapify(); + } +private: + Compare compare; + size_type mark; + input_type reserved_item; + + void heapify() { + if (!mark) mark = 1; + for (; markmy_tail; ++mark) { // for each unheaped element + size_type cur_pos = mark; + input_type to_place = this->my_array[mark].first; + do { // push to_place up the heap + size_type parent = (cur_pos-1)>>1; + if (!compare(this->my_array[parent].first, to_place)) + break; + this->my_array[cur_pos].first = this->my_array[parent].first; + cur_pos = parent; + } while( cur_pos ); + this->my_array[cur_pos].first = to_place; + } + } + + void reheap() { + size_type cur_pos=0, child=1; + while (child < mark) { + size_type target = child; + if (child+1my_array[child].first, + this->my_array[child+1].first)) + ++target; + // target now has the higher priority child + if (compare(this->my_array[target].first, + this->my_array[this->my_tail].first)) + break; + this->my_array[cur_pos].first = this->my_array[target].first; + cur_pos = target; + child = (cur_pos<<1)+1; + } + this->my_array[cur_pos].first = this->my_array[this->my_tail].first; + } +}; + +//! Forwards messages only if the threshold has not been reached +/** This node forwards items until its threshold is reached. + It contains no buffering. If the downstream node rejects, the + message is dropped. */ +template< typename T > +class limiter_node : public graph_node, public receiver< T >, public sender< T > { + using graph_node::my_graph; +public: + typedef T input_type; + typedef T output_type; + typedef sender< input_type > predecessor_type; + typedef receiver< output_type > successor_type; + +private: + task *my_root_task; + size_t my_threshold; + size_t my_count; + internal::predecessor_cache< T > my_predecessors; + spin_mutex my_mutex; + internal::broadcast_cache< T > my_successors; + int init_decrement_predecessors; + + friend class internal::forward_task< limiter_node >; + + // Let decrementer call decrement_counter() + friend class internal::decrementer< limiter_node >; + + void decrement_counter() { + input_type v; + + // If we can't get / put an item immediately then drop the count + if ( my_predecessors.get_item( v ) == false + || my_successors.try_put(v) == false ) { + spin_mutex::scoped_lock lock(my_mutex); + --my_count; + if ( !my_predecessors.empty() ) + task::enqueue( * new ( task::allocate_additional_child_of( *my_root_task ) ) + internal::forward_task< limiter_node >( *this ) ); + } + } + + void forward() { + { + spin_mutex::scoped_lock lock(my_mutex); + if ( my_count < my_threshold ) + ++my_count; + else + return; + } + decrement_counter(); + } + +public: + //! The internal receiver< continue_msg > that decrements the count + internal::decrementer< limiter_node > decrement; + + //! Constructor + limiter_node(graph &g, size_t threshold, int num_decrement_predecessors=0) : + graph_node(g), my_root_task(g.root_task()), my_threshold(threshold), my_count(0), + init_decrement_predecessors(num_decrement_predecessors), + decrement(num_decrement_predecessors) + { + my_predecessors.set_owner(this); + my_successors.set_owner(this); + decrement.set_owner(this); + } + + //! Copy constructor + limiter_node( const limiter_node& src ) : + graph_node(src.my_graph), receiver(), sender(), + my_root_task(src.my_root_task), my_threshold(src.my_threshold), my_count(0), + init_decrement_predecessors(src.init_decrement_predecessors), + decrement(src.init_decrement_predecessors) + { + my_predecessors.set_owner(this); + my_successors.set_owner(this); + decrement.set_owner(this); + } + + //! Replace the current successor with this new successor + /* override */ bool register_successor( receiver &r ) { + my_successors.register_successor(r); + return true; + } + + //! Removes a successor from this node + /** r.remove_predecessor(*this) is also called. */ + /* override */ bool remove_successor( receiver &r ) { + r.remove_predecessor(*this); + my_successors.remove_successor(r); + return true; + } + + //! Puts an item to this receiver + /* override */ bool try_put( const T &t ) { + { + spin_mutex::scoped_lock lock(my_mutex); + if ( my_count >= my_threshold ) + return false; + else + ++my_count; + } + + bool msg = my_successors.try_put(t); + + if ( msg != true ) { + spin_mutex::scoped_lock lock(my_mutex); + --my_count; + if ( !my_predecessors.empty() ) + task::enqueue( * new ( task::allocate_additional_child_of( *my_root_task ) ) + internal::forward_task< limiter_node >( *this ) ); + } + + return msg; + } + + //! Removes src from the list of cached predecessors. + /* override */ bool register_predecessor( predecessor_type &src ) { + spin_mutex::scoped_lock lock(my_mutex); + my_predecessors.add( src ); + if ( my_count < my_threshold && !my_successors.empty() ) + task::enqueue( * new ( task::allocate_additional_child_of( *my_root_task ) ) + internal::forward_task< limiter_node >( *this ) ); + return true; + } + + //! Removes src from the list of cached predecessors. + /* override */ bool remove_predecessor( predecessor_type &src ) { + my_predecessors.remove( src ); + return true; + } +}; + +#include "internal/_flow_graph_join_impl.h" + +using internal::reserving_port; +using internal::queueing_port; +using internal::tag_matching_port; +using internal::input_port; +using internal::tag_value; +using internal::NO_TAG; + +template class join_node; + +template +class join_node: public internal::unfolded_join_node::value, reserving_port, OutputTuple, reserving> { +private: + static const int N = std::tuple_size::value; + typedef typename internal::unfolded_join_node unfolded_type; +public: + typedef OutputTuple output_type; + typedef typename unfolded_type::input_ports_type input_ports_type; + join_node(graph &g) : unfolded_type(g) { } + join_node(const join_node &other) : unfolded_type(other) {} +}; + +template +class join_node: public internal::unfolded_join_node::value, queueing_port, OutputTuple, queueing> { +private: + static const int N = std::tuple_size::value; + typedef typename internal::unfolded_join_node unfolded_type; +public: + typedef OutputTuple output_type; + typedef typename unfolded_type::input_ports_type input_ports_type; + join_node(graph &g) : unfolded_type(g) { } + join_node(const join_node &other) : unfolded_type(other) {} +}; + +// template for tag_matching join_node +template +class join_node : public internal::unfolded_join_node::value, + tag_matching_port, OutputTuple, tag_matching> { +private: + static const int N = std::tuple_size::value; + typedef typename internal::unfolded_join_node unfolded_type; +public: + typedef OutputTuple output_type; + typedef typename unfolded_type::input_ports_type input_ports_type; + template + join_node(graph &g, B0 b0, B1 b1) : unfolded_type(g, b0, b1) { } + template + join_node(graph &g, B0 b0, B1 b1, B2 b2) : unfolded_type(g, b0, b1, b2) { } + template + join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3) : unfolded_type(g, b0, b1, b2, b3) { } + template + join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4) : unfolded_type(g, b0, b1, b2, b3, b4) { } +#if __TBB_VARIADIC_MAX >= 6 + template + join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5) : unfolded_type(g, b0, b1, b2, b3, b4, b5) { } +#endif +#if __TBB_VARIADIC_MAX >= 7 + template + join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5, B6 b6) : unfolded_type(g, b0, b1, b2, b3, b4, b5, b6) { } +#endif +#if __TBB_VARIADIC_MAX >= 8 + template + join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5, B6 b6, B7 b7) : unfolded_type(g, b0, b1, b2, b3, b4, b5, b6, b7) { } +#endif +#if __TBB_VARIADIC_MAX >= 9 + template + join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5, B6 b6, B7 b7, B8 b8) : unfolded_type(g, b0, b1, b2, b3, b4, b5, b6, b7, b8) { } +#endif +#if __TBB_VARIADIC_MAX >= 10 + template + join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5, B6 b6, B7 b7, B8 b8, B9 b9) : unfolded_type(g, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9) { } +#endif + join_node(const join_node &other) : unfolded_type(other) {} +}; + +#if TBB_PREVIEW_GRAPH_NODES +// or node +#include "internal/_flow_graph_or_impl.h" + +template +class or_node : public internal::unfolded_or_node { +private: + static const int N = std::tuple_size::value; +public: + typedef typename internal::or_output_type::type output_type; + typedef typename internal::unfolded_or_node unfolded_type; + or_node(graph& g) : unfolded_type(g) { } + // Copy constructor + or_node( const or_node& other ) : unfolded_type(other) { } +}; +#endif // TBB_PREVIEW_GRAPH_NODES + +//! Makes an edge between a single predecessor and a single successor +template< typename T > +inline void make_edge( sender &p, receiver &s ) { + p.register_successor( s ); +} + +//! Makes an edge between a single predecessor and a single successor +template< typename T > +inline void remove_edge( sender &p, receiver &s ) { + p.remove_successor( s ); +} + +//! Returns a copy of the body from a function or continue node +template< typename Body, typename Node > +Body copy_body( Node &n ) { + return n.template copy_function_object(); +} + +} // interface6 + + using interface6::graph; + using interface6::graph_node; + using interface6::continue_msg; + using interface6::sender; + using interface6::receiver; + using interface6::continue_receiver; + + using interface6::source_node; + using interface6::function_node; + using interface6::multifunction_node; + using interface6::split_node; + using interface6::internal::output_port; +#if TBB_PREVIEW_GRAPH_NODES + using interface6::or_node; +#endif + using interface6::continue_node; + using interface6::overwrite_node; + using interface6::write_once_node; + using interface6::broadcast_node; + using interface6::buffer_node; + using interface6::queue_node; + using interface6::sequencer_node; + using interface6::priority_queue_node; + using interface6::limiter_node; + using namespace interface6::internal::graph_policy_namespace; + using interface6::join_node; + using interface6::input_port; + using interface6::copy_body; + using interface6::make_edge; + using interface6::remove_edge; + using interface6::internal::NO_TAG; + using interface6::internal::tag_value; + +} // flow +} // tbb + +#endif // __TBB_flow_graph_H diff --git a/src/tbb/include/tbb/index.html b/src/tbb/include/tbb/index.html new file mode 100644 index 0000000..b8af0cc --- /dev/null +++ b/src/tbb/include/tbb/index.html @@ -0,0 +1,29 @@ + + + +

    Overview

    +Include files for Intel® Threading Building Blocks classes and functions. + +
    Click here to see all files in the directory. + +

    Directories

    +
    +
    compat +
    Include files for source level compatibility with other frameworks. +
    internal +
    Include files with implementation details; not for direct use. +
    machine +
    Include files for low-level architecture specific functionality; not for direct use. +
    + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + diff --git a/src/tbb/include/tbb/internal/_aggregator_impl.h b/src/tbb/include/tbb/internal/_aggregator_impl.h new file mode 100644 index 0000000..1c4a8b2 --- /dev/null +++ b/src/tbb/include/tbb/internal/_aggregator_impl.h @@ -0,0 +1,162 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB__aggregator_impl_H +#define __TBB__aggregator_impl_H + +#include "../atomic.h" +#include "../tbb_profiling.h" + +namespace tbb { +namespace interface6 { +namespace internal { + +using namespace tbb::internal; + +//! aggregated_operation base class +template +class aggregated_operation { + public: + uintptr_t status; + Derived *next; + aggregated_operation() : status(0), next(NULL) {} +}; + +//! Aggregator base class +/** An aggregator for collecting operations coming from multiple sources and executing + them serially on a single thread. operation_type must be derived from + aggregated_operation. The parameter handler_type is a functor that will be passed the + list of operations and is expected to handle each operation appropriately, setting the + status of each operation to non-zero.*/ +template < typename handler_type, typename operation_type > +class aggregator { + public: + aggregator() : handler_busy(false) { pending_operations = NULL; } + explicit aggregator(handler_type h) : handler_busy(false), handle_operations(h) { + pending_operations = NULL; + } + + void initialize_handler(handler_type h) { handle_operations = h; } + + //! Place operation in list + /** Place operation in list and either handle list or wait for operation to + complete. */ + void execute(operation_type *op) { + operation_type *res; + + // ITT note: &(op->status) tag is used to cover accesses to this op node. This + // thread has created the operation, and now releases it so that the handler + // thread may handle the associated operation w/o triggering a race condition; + // thus this tag will be acquired just before the operation is handled in the + // handle_operations functor. + call_itt_notify(releasing, &(op->status)); + // insert the operation in the queue + do { + // ITT may flag the following line as a race; it is a false positive: + // This is an atomic read; we don't provide itt_hide_load_word for atomics + op->next = res = pending_operations; // NOT A RACE + } while (pending_operations.compare_and_swap(op, res) != res); + if (!res) { // first in the list; handle the operations + // ITT note: &pending_operations tag covers access to the handler_busy flag, + // which this waiting handler thread will try to set before entering + // handle_operations. + call_itt_notify(acquired, &pending_operations); + start_handle_operations(); + __TBB_ASSERT(op->status, NULL); + } + else { // not first; wait for op to be ready + call_itt_notify(prepare, &(op->status)); + spin_wait_while_eq(op->status, uintptr_t(0)); + itt_load_word_with_acquire(op->status); + } + } + + private: + //! An atomically updated list (aka mailbox) of pending operations + atomic pending_operations; + //! Controls thread access to handle_operations + uintptr_t handler_busy; + handler_type handle_operations; + + //! Trigger the handling of operations when the handler is free + void start_handle_operations() { + operation_type *op_list; + + // ITT note: &handler_busy tag covers access to pending_operations as it is passed + // between active and waiting handlers. Below, the waiting handler waits until + // the active handler releases, and the waiting handler acquires &handler_busy as + // it becomes the active_handler. The release point is at the end of this + // function, when all operations in pending_operations have been handled by the + // owner of this aggregator. + call_itt_notify(prepare, &handler_busy); + // get the handler_busy: + // only one thread can possibly spin here at a time + spin_wait_until_eq(handler_busy, uintptr_t(0)); + call_itt_notify(acquired, &handler_busy); + // acquire fence not necessary here due to causality rule and surrounding atomics + __TBB_store_with_release(handler_busy, uintptr_t(1)); + + // ITT note: &pending_operations tag covers access to the handler_busy flag + // itself. Capturing the state of the pending_operations signifies that + // handler_busy has been set and a new active handler will now process that list's + // operations. + call_itt_notify(releasing, &pending_operations); + // grab pending_operations + op_list = pending_operations.fetch_and_store(NULL); + + // handle all the operations + handle_operations(op_list); + + // release the handler + itt_store_word_with_release(handler_busy, uintptr_t(0)); + } +}; + +// the most-compatible friend declaration (vs, gcc, icc) is +// template friend class aggregating_functor; +template +class aggregating_functor { + aggregating_class *fi; +public: + aggregating_functor() {} + aggregating_functor(aggregating_class *fi_) : fi(fi_) {} + void operator()(operation_list* op_list) { fi->handle_operations(op_list); } +}; + +} // namespace internal +} // namespace interface6 + +namespace internal { + using interface6::internal::aggregated_operation; + using interface6::internal::aggregator; + using interface6::internal::aggregating_functor; +} // namespace internal + +} // namespace tbb + +#endif // __TBB__aggregator_impl_H diff --git a/src/tbb/include/tbb/internal/_concurrent_queue_impl.h b/src/tbb/include/tbb/internal/_concurrent_queue_impl.h new file mode 100644 index 0000000..b9d56e6 --- /dev/null +++ b/src/tbb/include/tbb/internal/_concurrent_queue_impl.h @@ -0,0 +1,1026 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB__concurrent_queue_impl_H +#define __TBB__concurrent_queue_impl_H + +#ifndef __TBB_concurrent_queue_H +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + +#include "../tbb_stddef.h" +#include "../tbb_machine.h" +#include "../atomic.h" +#include "../spin_mutex.h" +#include "../cache_aligned_allocator.h" +#include "../tbb_exception.h" +#include "../tbb_profiling.h" +#include + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +namespace tbb { + +#if !__TBB_TEMPLATE_FRIENDS_BROKEN + +// forward declaration +namespace strict_ppl { +template class concurrent_queue; +} + +template class concurrent_bounded_queue; + +namespace deprecated { +template class concurrent_queue; +} +#endif + +//! For internal use only. +namespace strict_ppl { + +//! @cond INTERNAL +namespace internal { + +using namespace tbb::internal; + +typedef size_t ticket; + +template class micro_queue ; +template class micro_queue_pop_finalizer ; +template class concurrent_queue_base_v3; + +//! parts of concurrent_queue_rep that do not have references to micro_queue +/** + * For internal use only. + */ +struct concurrent_queue_rep_base : no_copy { + template friend class micro_queue; + template friend class concurrent_queue_base_v3; + +protected: + //! Approximately n_queue/golden ratio + static const size_t phi = 3; + +public: + // must be power of 2 + static const size_t n_queue = 8; + + //! Prefix on a page + struct page { + page* next; + uintptr_t mask; + }; + + atomic head_counter; + char pad1[NFS_MaxLineSize-sizeof(atomic)]; + atomic tail_counter; + char pad2[NFS_MaxLineSize-sizeof(atomic)]; + + //! Always a power of 2 + size_t items_per_page; + + //! Size of an item + size_t item_size; + + //! number of invalid entries in the queue + atomic n_invalid_entries; + + char pad3[NFS_MaxLineSize-sizeof(size_t)-sizeof(size_t)-sizeof(atomic)]; +} ; + +inline bool is_valid_page(const concurrent_queue_rep_base::page* p) { + return uintptr_t(p)>1; +} + +//! Abstract class to define interface for page allocation/deallocation +/** + * For internal use only. + */ +class concurrent_queue_page_allocator +{ + template friend class micro_queue ; + template friend class micro_queue_pop_finalizer ; +protected: + virtual ~concurrent_queue_page_allocator() {} +private: + virtual concurrent_queue_rep_base::page* allocate_page() = 0; + virtual void deallocate_page( concurrent_queue_rep_base::page* p ) = 0; +} ; + +#if _MSC_VER && !defined(__INTEL_COMPILER) +// unary minus operator applied to unsigned type, result still unsigned +#pragma warning( push ) +#pragma warning( disable: 4146 ) +#endif + +//! A queue using simple locking. +/** For efficiency, this class has no constructor. + The caller is expected to zero-initialize it. */ +template +class micro_queue : no_copy { + typedef concurrent_queue_rep_base::page page; + + //! Class used to ensure exception-safety of method "pop" + class destroyer: no_copy { + T& my_value; + public: + destroyer( T& value ) : my_value(value) {} + ~destroyer() {my_value.~T();} + }; + + void copy_item( page& dst, size_t index, const void* src ) { + new( &get_ref(dst,index) ) T(*static_cast(src)); + } + + void copy_item( page& dst, size_t dindex, const page& src, size_t sindex ) { + new( &get_ref(dst,dindex) ) T( get_ref(const_cast(src),sindex) ); + } + + void assign_and_destroy_item( void* dst, page& src, size_t index ) { + T& from = get_ref(src,index); + destroyer d(from); + *static_cast(dst) = from; + } + + void spin_wait_until_my_turn( atomic& counter, ticket k, concurrent_queue_rep_base& rb ) const ; + +public: + friend class micro_queue_pop_finalizer; + + struct padded_page: page { + //! Not defined anywhere - exists to quiet warnings. + padded_page(); + //! Not defined anywhere - exists to quiet warnings. + void operator=( const padded_page& ); + //! Must be last field. + T last; + }; + + static T& get_ref( page& p, size_t index ) { + return (&static_cast(static_cast(&p))->last)[index]; + } + + atomic head_page; + atomic head_counter; + + atomic tail_page; + atomic tail_counter; + + spin_mutex page_mutex; + + void push( const void* item, ticket k, concurrent_queue_base_v3& base ) ; + + bool pop( void* dst, ticket k, concurrent_queue_base_v3& base ) ; + + micro_queue& assign( const micro_queue& src, concurrent_queue_base_v3& base ) ; + + page* make_copy( concurrent_queue_base_v3& base, const page* src_page, size_t begin_in_page, size_t end_in_page, ticket& g_index ) ; + + void invalidate_page_and_rethrow( ticket k ) ; +}; + +template +void micro_queue::spin_wait_until_my_turn( atomic& counter, ticket k, concurrent_queue_rep_base& rb ) const { + atomic_backoff backoff; + do { + backoff.pause(); + if( counter&1 ) { + ++rb.n_invalid_entries; + throw_exception( eid_bad_last_alloc ); + } + } while( counter!=k ) ; +} + +template +void micro_queue::push( const void* item, ticket k, concurrent_queue_base_v3& base ) { + k &= -concurrent_queue_rep_base::n_queue; + page* p = NULL; + size_t index = k/concurrent_queue_rep_base::n_queue & (base.my_rep->items_per_page-1); + if( !index ) { + __TBB_TRY { + concurrent_queue_page_allocator& pa = base; + p = pa.allocate_page(); + } __TBB_CATCH (...) { + ++base.my_rep->n_invalid_entries; + invalidate_page_and_rethrow( k ); + } + p->mask = 0; + p->next = NULL; + } + + if( tail_counter!=k ) spin_wait_until_my_turn( tail_counter, k, *base.my_rep ); + call_itt_notify(acquired, &tail_counter); + + if( p ) { + spin_mutex::scoped_lock lock( page_mutex ); + page* q = tail_page; + if( is_valid_page(q) ) + q->next = p; + else + head_page = p; + tail_page = p; + } else { + p = tail_page; + } + __TBB_TRY { + copy_item( *p, index, item ); + // If no exception was thrown, mark item as present. + itt_hide_store_word(p->mask, p->mask | uintptr_t(1)<n_invalid_entries; + call_itt_notify(releasing, &tail_counter); + tail_counter += concurrent_queue_rep_base::n_queue; + __TBB_RETHROW(); + } +} + +template +bool micro_queue::pop( void* dst, ticket k, concurrent_queue_base_v3& base ) { + k &= -concurrent_queue_rep_base::n_queue; + if( head_counter!=k ) spin_wait_until_eq( head_counter, k ); + call_itt_notify(acquired, &head_counter); + if( tail_counter==k ) spin_wait_while_eq( tail_counter, k ); + call_itt_notify(acquired, &tail_counter); + page& p = *head_page; + __TBB_ASSERT( &p, NULL ); + size_t index = k/concurrent_queue_rep_base::n_queue & (base.my_rep->items_per_page-1); + bool success = false; + { + micro_queue_pop_finalizer finalizer( *this, base, k+concurrent_queue_rep_base::n_queue, index==base.my_rep->items_per_page-1 ? &p : NULL ); + if( p.mask & uintptr_t(1)<n_invalid_entries; + } + } + return success; +} + +template +micro_queue& micro_queue::assign( const micro_queue& src, concurrent_queue_base_v3& base ) { + head_counter = src.head_counter; + tail_counter = src.tail_counter; + page_mutex = src.page_mutex; + + const page* srcp = src.head_page; + if( is_valid_page(srcp) ) { + ticket g_index = head_counter; + __TBB_TRY { + size_t n_items = (tail_counter-head_counter)/concurrent_queue_rep_base::n_queue; + size_t index = head_counter/concurrent_queue_rep_base::n_queue & (base.my_rep->items_per_page-1); + size_t end_in_first_page = (index+n_itemsitems_per_page)?(index+n_items):base.my_rep->items_per_page; + + head_page = make_copy( base, srcp, index, end_in_first_page, g_index ); + page* cur_page = head_page; + + if( srcp != src.tail_page ) { + for( srcp = srcp->next; srcp!=src.tail_page; srcp=srcp->next ) { + cur_page->next = make_copy( base, srcp, 0, base.my_rep->items_per_page, g_index ); + cur_page = cur_page->next; + } + + __TBB_ASSERT( srcp==src.tail_page, NULL ); + size_t last_index = tail_counter/concurrent_queue_rep_base::n_queue & (base.my_rep->items_per_page-1); + if( last_index==0 ) last_index = base.my_rep->items_per_page; + + cur_page->next = make_copy( base, srcp, 0, last_index, g_index ); + cur_page = cur_page->next; + } + tail_page = cur_page; + } __TBB_CATCH (...) { + invalidate_page_and_rethrow( g_index ); + } + } else { + head_page = tail_page = NULL; + } + return *this; +} + +template +void micro_queue::invalidate_page_and_rethrow( ticket k ) { + // Append an invalid page at address 1 so that no more pushes are allowed. + page* invalid_page = (page*)uintptr_t(1); + { + spin_mutex::scoped_lock lock( page_mutex ); + itt_store_word_with_release(tail_counter, k+concurrent_queue_rep_base::n_queue+1); + page* q = tail_page; + if( is_valid_page(q) ) + q->next = invalid_page; + else + head_page = invalid_page; + tail_page = invalid_page; + } + __TBB_RETHROW(); +} + +template +concurrent_queue_rep_base::page* micro_queue::make_copy( concurrent_queue_base_v3& base, const concurrent_queue_rep_base::page* src_page, size_t begin_in_page, size_t end_in_page, ticket& g_index ) { + concurrent_queue_page_allocator& pa = base; + page* new_page = pa.allocate_page(); + new_page->next = NULL; + new_page->mask = src_page->mask; + for( ; begin_in_page!=end_in_page; ++begin_in_page, ++g_index ) + if( new_page->mask & uintptr_t(1)< +class micro_queue_pop_finalizer: no_copy { + typedef concurrent_queue_rep_base::page page; + ticket my_ticket; + micro_queue& my_queue; + page* my_page; + concurrent_queue_page_allocator& allocator; +public: + micro_queue_pop_finalizer( micro_queue& queue, concurrent_queue_base_v3& b, ticket k, page* p ) : + my_ticket(k), my_queue(queue), my_page(p), allocator(b) + {} + ~micro_queue_pop_finalizer() ; +}; + +template +micro_queue_pop_finalizer::~micro_queue_pop_finalizer() { + page* p = my_page; + if( is_valid_page(p) ) { + spin_mutex::scoped_lock lock( my_queue.page_mutex ); + page* q = p->next; + my_queue.head_page = q; + if( !is_valid_page(q) ) { + my_queue.tail_page = NULL; + } + } + itt_store_word_with_release(my_queue.head_counter, my_ticket); + if( is_valid_page(p) ) { + allocator.deallocate_page( p ); + } +} + +#if _MSC_VER && !defined(__INTEL_COMPILER) +#pragma warning( pop ) +#endif // warning 4146 is back + +template class concurrent_queue_iterator_rep ; +template class concurrent_queue_iterator_base_v3; + +//! representation of concurrent_queue_base +/** + * the class inherits from concurrent_queue_rep_base and defines an array of micro_queue's + */ +template +struct concurrent_queue_rep : public concurrent_queue_rep_base { + micro_queue array[n_queue]; + + //! Map ticket to an array index + static size_t index( ticket k ) { + return k*phi%n_queue; + } + + micro_queue& choose( ticket k ) { + // The formula here approximates LRU in a cache-oblivious way. + return array[index(k)]; + } +}; + +//! base class of concurrent_queue +/** + * The class implements the interface defined by concurrent_queue_page_allocator + * and has a pointer to an instance of concurrent_queue_rep. + */ +template +class concurrent_queue_base_v3: public concurrent_queue_page_allocator { + //! Internal representation + concurrent_queue_rep* my_rep; + + friend struct concurrent_queue_rep; + friend class micro_queue; + friend class concurrent_queue_iterator_rep; + friend class concurrent_queue_iterator_base_v3; + +protected: + typedef typename concurrent_queue_rep::page page; + +private: + typedef typename micro_queue::padded_page padded_page; + + /* override */ virtual page *allocate_page() { + concurrent_queue_rep& r = *my_rep; + size_t n = sizeof(padded_page) + (r.items_per_page-1)*sizeof(T); + return reinterpret_cast(allocate_block ( n )); + } + + /* override */ virtual void deallocate_page( concurrent_queue_rep_base::page *p ) { + concurrent_queue_rep& r = *my_rep; + size_t n = sizeof(padded_page) + (r.items_per_page-1)*sizeof(T); + deallocate_block( reinterpret_cast(p), n ); + } + + //! custom allocator + virtual void *allocate_block( size_t n ) = 0; + + //! custom de-allocator + virtual void deallocate_block( void *p, size_t n ) = 0; + +protected: + concurrent_queue_base_v3(); + + /* override */ virtual ~concurrent_queue_base_v3() { +#if TBB_USE_ASSERT + size_t nq = my_rep->n_queue; + for( size_t i=0; iarray[i].tail_page==NULL, "pages were not freed properly" ); +#endif /* TBB_USE_ASSERT */ + cache_aligned_allocator >().deallocate(my_rep,1); + } + + //! Enqueue item at tail of queue + void internal_push( const void* src ) { + concurrent_queue_rep& r = *my_rep; + ticket k = r.tail_counter++; + r.choose(k).push( src, k, *this ); + } + + //! Attempt to dequeue item from queue. + /** NULL if there was no item to dequeue. */ + bool internal_try_pop( void* dst ) ; + + //! Get size of queue; result may be invalid if queue is modified concurrently + size_t internal_size() const ; + + //! check if the queue is empty; thread safe + bool internal_empty() const ; + + //! free any remaining pages + /* note that the name may be misleading, but it remains so due to a historical accident. */ + void internal_finish_clear() ; + + //! Obsolete + void internal_throw_exception() const { + throw_exception( eid_bad_alloc ); + } + + //! copy internal representation + void assign( const concurrent_queue_base_v3& src ) ; +}; + +template +concurrent_queue_base_v3::concurrent_queue_base_v3() { + const size_t item_size = sizeof(T); + my_rep = cache_aligned_allocator >().allocate(1); + __TBB_ASSERT( (size_t)my_rep % NFS_GetLineSize()==0, "alignment error" ); + __TBB_ASSERT( (size_t)&my_rep->head_counter % NFS_GetLineSize()==0, "alignment error" ); + __TBB_ASSERT( (size_t)&my_rep->tail_counter % NFS_GetLineSize()==0, "alignment error" ); + __TBB_ASSERT( (size_t)&my_rep->array % NFS_GetLineSize()==0, "alignment error" ); + memset(my_rep,0,sizeof(concurrent_queue_rep)); + my_rep->item_size = item_size; + my_rep->items_per_page = item_size<= 8 ? 32 : + item_size<= 16 ? 16 : + item_size<= 32 ? 8 : + item_size<= 64 ? 4 : + item_size<=128 ? 2 : + 1; +} + +template +bool concurrent_queue_base_v3::internal_try_pop( void* dst ) { + concurrent_queue_rep& r = *my_rep; + ticket k; + do { + k = r.head_counter; + for(;;) { + if( (ptrdiff_t)(r.tail_counter-k)<=0 ) { + // Queue is empty + return false; + } + // Queue had item with ticket k when we looked. Attempt to get that item. + ticket tk=k; +#if defined(_MSC_VER) && defined(_Wp64) + #pragma warning (push) + #pragma warning (disable: 4267) +#endif + k = r.head_counter.compare_and_swap( tk+1, tk ); +#if defined(_MSC_VER) && defined(_Wp64) + #pragma warning (pop) +#endif + if( k==tk ) + break; + // Another thread snatched the item, retry. + } + } while( !r.choose( k ).pop( dst, k, *this ) ); + return true; +} + +template +size_t concurrent_queue_base_v3::internal_size() const { + concurrent_queue_rep& r = *my_rep; + __TBB_ASSERT( sizeof(ptrdiff_t)<=sizeof(size_t), NULL ); + ticket hc = r.head_counter; + size_t nie = r.n_invalid_entries; + ticket tc = r.tail_counter; + __TBB_ASSERT( hc!=tc || !nie, NULL ); + ptrdiff_t sz = tc-hc-nie; + return sz<0 ? 0 : size_t(sz); +} + +template +bool concurrent_queue_base_v3::internal_empty() const { + concurrent_queue_rep& r = *my_rep; + ticket tc = r.tail_counter; + ticket hc = r.head_counter; + // if tc!=r.tail_counter, the queue was not empty at some point between the two reads. + return tc==r.tail_counter && tc==hc+r.n_invalid_entries ; +} + +template +void concurrent_queue_base_v3::internal_finish_clear() { + concurrent_queue_rep& r = *my_rep; + size_t nq = r.n_queue; + for( size_t i=0; i +void concurrent_queue_base_v3::assign( const concurrent_queue_base_v3& src ) { + concurrent_queue_rep& r = *my_rep; + r.items_per_page = src.my_rep->items_per_page; + + // copy concurrent_queue_rep. + r.head_counter = src.my_rep->head_counter; + r.tail_counter = src.my_rep->tail_counter; + r.n_invalid_entries = src.my_rep->n_invalid_entries; + + // copy micro_queues + for( size_t i = 0; iarray[i], *this); + + __TBB_ASSERT( r.head_counter==src.my_rep->head_counter && r.tail_counter==src.my_rep->tail_counter, + "the source concurrent queue should not be concurrently modified." ); +} + +template class concurrent_queue_iterator; + +template +class concurrent_queue_iterator_rep: no_assign { + typedef typename micro_queue::padded_page padded_page; +public: + ticket head_counter; + const concurrent_queue_base_v3& my_queue; + typename concurrent_queue_base_v3::page* array[concurrent_queue_rep::n_queue]; + concurrent_queue_iterator_rep( const concurrent_queue_base_v3& queue ) : + head_counter(queue.my_rep->head_counter), + my_queue(queue) + { + for( size_t k=0; k::n_queue; ++k ) + array[k] = queue.my_rep->array[k].head_page; + } + + //! Set item to point to kth element. Return true if at end of queue or item is marked valid; false otherwise. + bool get_item( T*& item, size_t k ) ; +}; + +template +bool concurrent_queue_iterator_rep::get_item( T*& item, size_t k ) { + if( k==my_queue.my_rep->tail_counter ) { + item = NULL; + return true; + } else { + typename concurrent_queue_base_v3::page* p = array[concurrent_queue_rep::index(k)]; + __TBB_ASSERT(p,NULL); + size_t i = k/concurrent_queue_rep::n_queue & (my_queue.my_rep->items_per_page-1); + item = µ_queue::get_ref(*p,i); + return (p->mask & uintptr_t(1)< +class concurrent_queue_iterator_base_v3 : no_assign { + //! Represents concurrent_queue over which we are iterating. + /** NULL if one past last element in queue. */ + concurrent_queue_iterator_rep* my_rep; + + template + friend bool operator==( const concurrent_queue_iterator& i, const concurrent_queue_iterator& j ); + + template + friend bool operator!=( const concurrent_queue_iterator& i, const concurrent_queue_iterator& j ); +protected: + //! Pointer to current item + Value* my_item; + + //! Default constructor + concurrent_queue_iterator_base_v3() : my_rep(NULL), my_item(NULL) { +#if __TBB_GCC_OPTIMIZER_ORDERING_BROKEN + __TBB_compiler_fence(); +#endif + } + + //! Copy constructor + concurrent_queue_iterator_base_v3( const concurrent_queue_iterator_base_v3& i ) + : no_assign(), my_rep(NULL), my_item(NULL) { + assign(i); + } + + //! Construct iterator pointing to head of queue. + concurrent_queue_iterator_base_v3( const concurrent_queue_base_v3& queue ) ; + + //! Assignment + void assign( const concurrent_queue_iterator_base_v3& other ) ; + + //! Advance iterator one step towards tail of queue. + void advance() ; + + //! Destructor + ~concurrent_queue_iterator_base_v3() { + cache_aligned_allocator >().deallocate(my_rep, 1); + my_rep = NULL; + } +}; + +template +concurrent_queue_iterator_base_v3::concurrent_queue_iterator_base_v3( const concurrent_queue_base_v3& queue ) { + my_rep = cache_aligned_allocator >().allocate(1); + new( my_rep ) concurrent_queue_iterator_rep(queue); + size_t k = my_rep->head_counter; + if( !my_rep->get_item(my_item, k) ) advance(); +} + +template +void concurrent_queue_iterator_base_v3::assign( const concurrent_queue_iterator_base_v3& other ) { + if( my_rep!=other.my_rep ) { + if( my_rep ) { + cache_aligned_allocator >().deallocate(my_rep, 1); + my_rep = NULL; + } + if( other.my_rep ) { + my_rep = cache_aligned_allocator >().allocate(1); + new( my_rep ) concurrent_queue_iterator_rep( *other.my_rep ); + } + } + my_item = other.my_item; +} + +template +void concurrent_queue_iterator_base_v3::advance() { + __TBB_ASSERT( my_item, "attempt to increment iterator past end of queue" ); + size_t k = my_rep->head_counter; + const concurrent_queue_base_v3& queue = my_rep->my_queue; +#if TBB_USE_ASSERT + Value* tmp; + my_rep->get_item(tmp,k); + __TBB_ASSERT( my_item==tmp, NULL ); +#endif /* TBB_USE_ASSERT */ + size_t i = k/concurrent_queue_rep::n_queue & (queue.my_rep->items_per_page-1); + if( i==queue.my_rep->items_per_page-1 ) { + typename concurrent_queue_base_v3::page*& root = my_rep->array[concurrent_queue_rep::index(k)]; + root = root->next; + } + // advance k + my_rep->head_counter = ++k; + if( !my_rep->get_item(my_item, k) ) advance(); +} + +//! Similar to C++0x std::remove_cv +/** "tbb_" prefix added to avoid overload confusion with C++0x implementations. */ +template struct tbb_remove_cv {typedef T type;}; +template struct tbb_remove_cv {typedef T type;}; +template struct tbb_remove_cv {typedef T type;}; +template struct tbb_remove_cv {typedef T type;}; + +//! Meets requirements of a forward iterator for STL. +/** Value is either the T or const T type of the container. + @ingroup containers */ +template +class concurrent_queue_iterator: public concurrent_queue_iterator_base_v3::type>, + public std::iterator { +#if !__TBB_TEMPLATE_FRIENDS_BROKEN + template + friend class ::tbb::strict_ppl::concurrent_queue; +#else +public: // workaround for MSVC +#endif + //! Construct iterator pointing to head of queue. + concurrent_queue_iterator( const concurrent_queue_base_v3& queue ) : + concurrent_queue_iterator_base_v3::type>(queue) + { + } + +public: + concurrent_queue_iterator() {} + + concurrent_queue_iterator( const concurrent_queue_iterator& other ) : + concurrent_queue_iterator_base_v3::type>(other) + {} + + //! Iterator assignment + concurrent_queue_iterator& operator=( const concurrent_queue_iterator& other ) { + this->assign(other); + return *this; + } + + //! Reference to current item + Value& operator*() const { + return *static_cast(this->my_item); + } + + Value* operator->() const {return &operator*();} + + //! Advance to next item in queue + concurrent_queue_iterator& operator++() { + this->advance(); + return *this; + } + + //! Post increment + Value* operator++(int) { + Value* result = &operator*(); + operator++(); + return result; + } +}; // concurrent_queue_iterator + + +template +bool operator==( const concurrent_queue_iterator& i, const concurrent_queue_iterator& j ) { + return i.my_item==j.my_item; +} + +template +bool operator!=( const concurrent_queue_iterator& i, const concurrent_queue_iterator& j ) { + return i.my_item!=j.my_item; +} + +} // namespace internal + +//! @endcond + +} // namespace strict_ppl + +//! @cond INTERNAL +namespace internal { + +class concurrent_queue_rep; +class concurrent_queue_iterator_rep; +class concurrent_queue_iterator_base_v3; +template class concurrent_queue_iterator; + +//! For internal use only. +/** Type-independent portion of concurrent_queue. + @ingroup containers */ +class concurrent_queue_base_v3: no_copy { + //! Internal representation + concurrent_queue_rep* my_rep; + + friend class concurrent_queue_rep; + friend struct micro_queue; + friend class micro_queue_pop_finalizer; + friend class concurrent_queue_iterator_rep; + friend class concurrent_queue_iterator_base_v3; +protected: + //! Prefix on a page + struct page { + page* next; + uintptr_t mask; + }; + + //! Capacity of the queue + ptrdiff_t my_capacity; + + //! Always a power of 2 + size_t items_per_page; + + //! Size of an item + size_t item_size; + +#if __TBB_PROTECTED_NESTED_CLASS_BROKEN +public: +#endif + template + struct padded_page: page { + //! Not defined anywhere - exists to quiet warnings. + padded_page(); + //! Not defined anywhere - exists to quiet warnings. + void operator=( const padded_page& ); + //! Must be last field. + T last; + }; + +private: + virtual void copy_item( page& dst, size_t index, const void* src ) = 0; + virtual void assign_and_destroy_item( void* dst, page& src, size_t index ) = 0; +protected: + __TBB_EXPORTED_METHOD concurrent_queue_base_v3( size_t item_size ); + virtual __TBB_EXPORTED_METHOD ~concurrent_queue_base_v3(); + + //! Enqueue item at tail of queue + void __TBB_EXPORTED_METHOD internal_push( const void* src ); + + //! Dequeue item from head of queue + void __TBB_EXPORTED_METHOD internal_pop( void* dst ); + + //! Abort all pending queue operations + void __TBB_EXPORTED_METHOD internal_abort(); + + //! Attempt to enqueue item onto queue. + bool __TBB_EXPORTED_METHOD internal_push_if_not_full( const void* src ); + + //! Attempt to dequeue item from queue. + /** NULL if there was no item to dequeue. */ + bool __TBB_EXPORTED_METHOD internal_pop_if_present( void* dst ); + + //! Get size of queue + ptrdiff_t __TBB_EXPORTED_METHOD internal_size() const; + + //! Check if the queue is emtpy + bool __TBB_EXPORTED_METHOD internal_empty() const; + + //! Set the queue capacity + void __TBB_EXPORTED_METHOD internal_set_capacity( ptrdiff_t capacity, size_t element_size ); + + //! custom allocator + virtual page *allocate_page() = 0; + + //! custom de-allocator + virtual void deallocate_page( page *p ) = 0; + + //! free any remaining pages + /* note that the name may be misleading, but it remains so due to a historical accident. */ + void __TBB_EXPORTED_METHOD internal_finish_clear() ; + + //! throw an exception + void __TBB_EXPORTED_METHOD internal_throw_exception() const; + + //! copy internal representation + void __TBB_EXPORTED_METHOD assign( const concurrent_queue_base_v3& src ) ; + +private: + virtual void copy_page_item( page& dst, size_t dindex, const page& src, size_t sindex ) = 0; +}; + +//! Type-independent portion of concurrent_queue_iterator. +/** @ingroup containers */ +class concurrent_queue_iterator_base_v3 { + //! concurrent_queue over which we are iterating. + /** NULL if one past last element in queue. */ + concurrent_queue_iterator_rep* my_rep; + + template + friend bool operator==( const concurrent_queue_iterator& i, const concurrent_queue_iterator& j ); + + template + friend bool operator!=( const concurrent_queue_iterator& i, const concurrent_queue_iterator& j ); + + void initialize( const concurrent_queue_base_v3& queue, size_t offset_of_data ); +protected: + //! Pointer to current item + void* my_item; + + //! Default constructor + concurrent_queue_iterator_base_v3() : my_rep(NULL), my_item(NULL) {} + + //! Copy constructor + concurrent_queue_iterator_base_v3( const concurrent_queue_iterator_base_v3& i ) : my_rep(NULL), my_item(NULL) { + assign(i); + } + + //! Obsolete entry point for constructing iterator pointing to head of queue. + /** Does not work correctly for SSE types. */ + __TBB_EXPORTED_METHOD concurrent_queue_iterator_base_v3( const concurrent_queue_base_v3& queue ); + + //! Construct iterator pointing to head of queue. + __TBB_EXPORTED_METHOD concurrent_queue_iterator_base_v3( const concurrent_queue_base_v3& queue, size_t offset_of_data ); + + //! Assignment + void __TBB_EXPORTED_METHOD assign( const concurrent_queue_iterator_base_v3& i ); + + //! Advance iterator one step towards tail of queue. + void __TBB_EXPORTED_METHOD advance(); + + //! Destructor + __TBB_EXPORTED_METHOD ~concurrent_queue_iterator_base_v3(); +}; + +typedef concurrent_queue_iterator_base_v3 concurrent_queue_iterator_base; + +//! Meets requirements of a forward iterator for STL. +/** Value is either the T or const T type of the container. + @ingroup containers */ +template +class concurrent_queue_iterator: public concurrent_queue_iterator_base, + public std::iterator { + +#if !defined(_MSC_VER) || defined(__INTEL_COMPILER) + template + friend class ::tbb::concurrent_bounded_queue; + + template + friend class ::tbb::deprecated::concurrent_queue; +#else +public: // workaround for MSVC +#endif + //! Construct iterator pointing to head of queue. + concurrent_queue_iterator( const concurrent_queue_base_v3& queue ) : + concurrent_queue_iterator_base_v3(queue,__TBB_offsetof(concurrent_queue_base_v3::padded_page,last)) + { + } + +public: + concurrent_queue_iterator() {} + + /** If Value==Container::value_type, then this routine is the copy constructor. + If Value==const Container::value_type, then this routine is a conversion constructor. */ + concurrent_queue_iterator( const concurrent_queue_iterator& other ) : + concurrent_queue_iterator_base_v3(other) + {} + + //! Iterator assignment + concurrent_queue_iterator& operator=( const concurrent_queue_iterator& other ) { + assign(other); + return *this; + } + + //! Reference to current item + Value& operator*() const { + return *static_cast(my_item); + } + + Value* operator->() const {return &operator*();} + + //! Advance to next item in queue + concurrent_queue_iterator& operator++() { + advance(); + return *this; + } + + //! Post increment + Value* operator++(int) { + Value* result = &operator*(); + operator++(); + return result; + } +}; // concurrent_queue_iterator + + +template +bool operator==( const concurrent_queue_iterator& i, const concurrent_queue_iterator& j ) { + return i.my_item==j.my_item; +} + +template +bool operator!=( const concurrent_queue_iterator& i, const concurrent_queue_iterator& j ) { + return i.my_item!=j.my_item; +} + +} // namespace internal; + +//! @endcond + +} // namespace tbb + +#endif /* __TBB__concurrent_queue_impl_H */ diff --git a/src/tbb/include/tbb/internal/_concurrent_unordered_impl.h b/src/tbb/include/tbb/internal/_concurrent_unordered_impl.h new file mode 100644 index 0000000..460d5f6 --- /dev/null +++ b/src/tbb/include/tbb/internal/_concurrent_unordered_impl.h @@ -0,0 +1,1429 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* Container implementations in this header are based on PPL implementations + provided by Microsoft. */ + +#ifndef __TBB__concurrent_unordered_impl_H +#define __TBB__concurrent_unordered_impl_H +#if !defined(__TBB_concurrent_unordered_map_H) && !defined(__TBB_concurrent_unordered_set_H) && !defined(__TBB_concurrent_hash_map_H) +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + +#include "../tbb_stddef.h" + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include +#include // Need std::pair +#include +#include // For tbb_hasher +#include // Need std::memset + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +#include "../atomic.h" +#include "../tbb_exception.h" +#include "../tbb_allocator.h" + +namespace tbb { +namespace interface5 { +//! @cond INTERNAL +namespace internal { + +template +class split_ordered_list; +template +class concurrent_unordered_base; + +// Forward list iterators (without skipping dummy elements) +template +class flist_iterator : public std::iterator +{ + template + friend class split_ordered_list; + template + friend class concurrent_unordered_base; + template + friend class flist_iterator; + + typedef typename Solist::nodeptr_t nodeptr_t; +public: + typedef typename Solist::value_type value_type; + typedef typename Solist::difference_type difference_type; + typedef typename Solist::pointer pointer; + typedef typename Solist::reference reference; + + flist_iterator() : my_node_ptr(0) {} + flist_iterator( const flist_iterator &other ) + : my_node_ptr(other.my_node_ptr) {} + + reference operator*() const { return my_node_ptr->my_element; } + pointer operator->() const { return &**this; } + + flist_iterator& operator++() { + my_node_ptr = my_node_ptr->my_next; + return *this; + } + + flist_iterator operator++(int) { + flist_iterator tmp = *this; + ++*this; + return tmp; + } + +protected: + flist_iterator(nodeptr_t pnode) : my_node_ptr(pnode) {} + nodeptr_t get_node_ptr() const { return my_node_ptr; } + + nodeptr_t my_node_ptr; + + template + friend bool operator==( const flist_iterator &i, const flist_iterator &j ); + template + friend bool operator!=( const flist_iterator& i, const flist_iterator& j ); +}; + +template +bool operator==( const flist_iterator &i, const flist_iterator &j ) { + return i.my_node_ptr == j.my_node_ptr; +} +template +bool operator!=( const flist_iterator& i, const flist_iterator& j ) { + return i.my_node_ptr != j.my_node_ptr; +} + +// Split-order list iterators, needed to skip dummy elements +template +class solist_iterator : public flist_iterator +{ + typedef flist_iterator base_type; + typedef typename Solist::nodeptr_t nodeptr_t; + using base_type::get_node_ptr; + template + friend class split_ordered_list; + template + friend class solist_iterator; + template + friend bool operator==( const solist_iterator &i, const solist_iterator &j ); + template + friend bool operator!=( const solist_iterator& i, const solist_iterator& j ); + + const Solist *my_list_ptr; + solist_iterator(nodeptr_t pnode, const Solist *plist) : base_type(pnode), my_list_ptr(plist) {} + +public: + typedef typename Solist::value_type value_type; + typedef typename Solist::difference_type difference_type; + typedef typename Solist::pointer pointer; + typedef typename Solist::reference reference; + + solist_iterator() {} + solist_iterator(const solist_iterator &other ) + : base_type(other), my_list_ptr(other.my_list_ptr) {} + + reference operator*() const { + return this->base_type::operator*(); + } + + pointer operator->() const { + return (&**this); + } + + solist_iterator& operator++() { + do ++(*(base_type *)this); + while (get_node_ptr() != NULL && get_node_ptr()->is_dummy()); + + return (*this); + } + + solist_iterator operator++(int) { + solist_iterator tmp = *this; + do ++*this; + while (get_node_ptr() != NULL && get_node_ptr()->is_dummy()); + + return (tmp); + } +}; + +template +bool operator==( const solist_iterator &i, const solist_iterator &j ) { + return i.my_node_ptr == j.my_node_ptr && i.my_list_ptr == j.my_list_ptr; +} +template +bool operator!=( const solist_iterator& i, const solist_iterator& j ) { + return i.my_node_ptr != j.my_node_ptr || i.my_list_ptr != j.my_list_ptr; +} + +// Forward type and class definitions +typedef size_t sokey_t; + +// Forward list in which elements are sorted in a split-order +template +class split_ordered_list +{ +public: + typedef split_ordered_list self_type; + typedef typename Allocator::template rebind::other allocator_type; + struct node; + typedef node *nodeptr_t; + + typedef typename allocator_type::size_type size_type; + typedef typename allocator_type::difference_type difference_type; + typedef typename allocator_type::pointer pointer; + typedef typename allocator_type::const_pointer const_pointer; + typedef typename allocator_type::reference reference; + typedef typename allocator_type::const_reference const_reference; + typedef typename allocator_type::value_type value_type; + + typedef solist_iterator const_iterator; + typedef solist_iterator iterator; + typedef flist_iterator raw_const_iterator; + typedef flist_iterator raw_iterator; + + // Node that holds the element in a split-ordered list + struct node : tbb::internal::no_assign + { + // Initialize the node with the given order key + void init(sokey_t order_key) { + my_order_key = order_key; + my_next = NULL; + } + + // Return the order key (needed for hashing) + sokey_t get_order_key() const { // TODO: remove + return my_order_key; + } + + // Inserts the new element in the list in an atomic fashion + nodeptr_t atomic_set_next(nodeptr_t new_node, nodeptr_t current_node) + { + // Try to change the next pointer on the current element to a new element, only if it still points to the cached next + nodeptr_t exchange_node = (nodeptr_t) __TBB_CompareAndSwapW((void *) &my_next, (uintptr_t)new_node, (uintptr_t)current_node); + + if (exchange_node == current_node) // TODO: why this branch? + { + // Operation succeeded, return the new node + return new_node; + } + else + { + // Operation failed, return the "interfering" node + return exchange_node; + } + } + + // Checks if this element in the list is a dummy, order enforcing node. Dummy nodes are used by buckets + // in the hash table to quickly index into the right subsection of the split-ordered list. + bool is_dummy() const { + return (my_order_key & 0x1) == 0; + } + + + nodeptr_t my_next; // Next element in the list + value_type my_element; // Element storage + sokey_t my_order_key; // Order key for this element + }; + + // Allocate a new node with the given order key and value + nodeptr_t create_node(sokey_t order_key, const T &value) { + nodeptr_t pnode = my_node_allocator.allocate(1); + + __TBB_TRY { + new(static_cast(&pnode->my_element)) T(value); + pnode->init(order_key); + } __TBB_CATCH(...) { + my_node_allocator.deallocate(pnode, 1); + __TBB_RETHROW(); + } + + return (pnode); + } + + // Allocate a new node with the given order key; used to allocate dummy nodes + nodeptr_t create_node(sokey_t order_key) { + nodeptr_t pnode = my_node_allocator.allocate(1); + + __TBB_TRY { + new(static_cast(&pnode->my_element)) T(); + pnode->init(order_key); + } __TBB_CATCH(...) { + my_node_allocator.deallocate(pnode, 1); + __TBB_RETHROW(); + } + + return (pnode); + } + + split_ordered_list(allocator_type a = allocator_type()) + : my_node_allocator(a), my_element_count(0) + { + // Immediately allocate a dummy node with order key of 0. This node + // will always be the head of the list. + my_head = create_node(0); + } + + ~split_ordered_list() + { + // Clear the list + clear(); + + // Remove the head element which is not cleared by clear() + nodeptr_t pnode = my_head; + my_head = NULL; + + __TBB_ASSERT(pnode != NULL && pnode->my_next == NULL, "Invalid head list node"); + + destroy_node(pnode); + } + + // Common forward list functions + + allocator_type get_allocator() const { + return (my_node_allocator); + } + + void clear() { + nodeptr_t pnext; + nodeptr_t pnode = my_head; + + __TBB_ASSERT(my_head != NULL, "Invalid head list node"); + pnext = pnode->my_next; + pnode->my_next = NULL; + pnode = pnext; + + while (pnode != NULL) + { + pnext = pnode->my_next; + destroy_node(pnode); + pnode = pnext; + } + + my_element_count = 0; + } + + // Returns a first non-dummy element in the SOL + iterator begin() { + return first_real_iterator(raw_begin()); + } + + // Returns a first non-dummy element in the SOL + const_iterator begin() const { + return first_real_iterator(raw_begin()); + } + + iterator end() { + return (iterator(0, this)); + } + + const_iterator end() const { + return (const_iterator(0, this)); + } + + const_iterator cbegin() const { + return (((const self_type *)this)->begin()); + } + + const_iterator cend() const { + return (((const self_type *)this)->end()); + } + + // Checks if the number of elements (non-dummy) is 0 + bool empty() const { + return (my_element_count == 0); + } + + // Returns the number of non-dummy elements in the list + size_type size() const { + return my_element_count; + } + + // Returns the maximum size of the list, determined by the allocator + size_type max_size() const { + return my_node_allocator.max_size(); + } + + // Swaps 'this' list with the passed in one + void swap(self_type& other) + { + if (this == &other) + { + // Nothing to do + return; + } + + std::swap(my_element_count, other.my_element_count); + std::swap(my_head, other.my_head); + } + + // Split-order list functions + + // Returns a first element in the SOL, which is always a dummy + raw_iterator raw_begin() { + return raw_iterator(my_head); + } + + // Returns a first element in the SOL, which is always a dummy + raw_const_iterator raw_begin() const { + return raw_const_iterator(my_head); + } + + raw_iterator raw_end() { + return raw_iterator(0); + } + + raw_const_iterator raw_end() const { + return raw_const_iterator(0); + } + + static sokey_t get_order_key(const raw_const_iterator& it) { + return it.get_node_ptr()->get_order_key(); + } + + static sokey_t get_safe_order_key(const raw_const_iterator& it) { + if( !it.get_node_ptr() ) return sokey_t(~0U); + return it.get_node_ptr()->get_order_key(); + } + + // Returns a public iterator version of the internal iterator. Public iterator must not + // be a dummy private iterator. + iterator get_iterator(raw_iterator it) { + __TBB_ASSERT(it.get_node_ptr() == NULL || !it.get_node_ptr()->is_dummy(), "Invalid user node (dummy)"); + return iterator(it.get_node_ptr(), this); + } + + // Returns a public iterator version of the internal iterator. Public iterator must not + // be a dummy private iterator. + const_iterator get_iterator(raw_const_iterator it) const { + __TBB_ASSERT(it.get_node_ptr() == NULL || !it.get_node_ptr()->is_dummy(), "Invalid user node (dummy)"); + return const_iterator(it.get_node_ptr(), this); + } + + // Returns a non-const version of the raw_iterator + raw_iterator get_iterator(raw_const_iterator it) { + return raw_iterator(it.get_node_ptr()); + } + + // Returns a non-const version of the iterator + static iterator get_iterator(const_iterator it) { + return iterator(it.my_node_ptr, it.my_list_ptr); + } + + // Returns a public iterator version of a first non-dummy internal iterator at or after + // the passed in internal iterator. + iterator first_real_iterator(raw_iterator it) + { + // Skip all dummy, internal only iterators + while (it != raw_end() && it.get_node_ptr()->is_dummy()) + ++it; + + return iterator(it.get_node_ptr(), this); + } + + // Returns a public iterator version of a first non-dummy internal iterator at or after + // the passed in internal iterator. + const_iterator first_real_iterator(raw_const_iterator it) const + { + // Skip all dummy, internal only iterators + while (it != raw_end() && it.get_node_ptr()->is_dummy()) + ++it; + + return const_iterator(it.get_node_ptr(), this); + } + + // Erase an element using the allocator + void destroy_node(nodeptr_t pnode) { + my_node_allocator.destroy(pnode); + my_node_allocator.deallocate(pnode, 1); + } + + // Try to insert a new element in the list. If insert fails, return the node that + // was inserted instead. + nodeptr_t try_insert(nodeptr_t previous, nodeptr_t new_node, nodeptr_t current_node) { + new_node->my_next = current_node; + return previous->atomic_set_next(new_node, current_node); + } + + // Insert a new element between passed in iterators + std::pair try_insert(raw_iterator it, raw_iterator next, const value_type &value, sokey_t order_key, size_type *new_count) + { + nodeptr_t pnode = create_node(order_key, value); + nodeptr_t inserted_node = try_insert(it.get_node_ptr(), pnode, next.get_node_ptr()); + + if (inserted_node == pnode) + { + // If the insert succeeded, check that the order is correct and increment the element count + check_range(); + *new_count = __TBB_FetchAndAddW((uintptr_t*)&my_element_count, uintptr_t(1)); + return std::pair(iterator(pnode, this), true); + } + else + { + // If the insert failed (element already there), then delete the new one + destroy_node(pnode); + return std::pair(end(), false); + } + } + + // Insert a new dummy element, starting search at a parent dummy element + raw_iterator insert_dummy(raw_iterator it, sokey_t order_key) + { + raw_iterator last = raw_end(); + raw_iterator where = it; + + __TBB_ASSERT(where != last, "Invalid head node"); + + ++where; + + // Create a dummy element up front, even though it may be discarded (due to concurrent insertion) + nodeptr_t dummy_node = create_node(order_key); + + for (;;) + { + __TBB_ASSERT(it != last, "Invalid head list node"); + + // If the head iterator is at the end of the list, or past the point where this dummy + // node needs to be inserted, then try to insert it. + if (where == last || get_order_key(where) > order_key) + { + __TBB_ASSERT(get_order_key(it) < order_key, "Invalid node order in the list"); + + // Try to insert it in the right place + nodeptr_t inserted_node = try_insert(it.get_node_ptr(), dummy_node, where.get_node_ptr()); + + if (inserted_node == dummy_node) + { + // Insertion succeeded, check the list for order violations + check_range(); + return raw_iterator(dummy_node); + } + else + { + // Insertion failed: either dummy node was inserted by another thread, or + // a real element was inserted at exactly the same place as dummy node. + // Proceed with the search from the previous location where order key was + // known to be larger (note: this is legal only because there is no safe + // concurrent erase operation supported). + where = it; + ++where; + continue; + } + } + else if (get_order_key(where) == order_key) + { + // Another dummy node with the same value found, discard the new one. + destroy_node(dummy_node); + return where; + } + + // Move the iterator forward + it = where; + ++where; + } + + } + + // This erase function can handle both real and dummy nodes + void erase_node(raw_iterator previous, raw_const_iterator& where) + { + nodeptr_t pnode = (where++).get_node_ptr(); + nodeptr_t prevnode = previous.get_node_ptr(); + __TBB_ASSERT(prevnode->my_next == pnode, "Erase must take consecutive iterators"); + prevnode->my_next = pnode->my_next; + + destroy_node(pnode); + } + + // Erase the element (previous node needs to be passed because this is a forward only list) + iterator erase_node(raw_iterator previous, const_iterator where) + { + raw_const_iterator it = where; + erase_node(previous, it); + my_element_count--; + + return get_iterator(first_real_iterator(it)); + } + + // Move all elements from the passed in split-ordered list to this one + void move_all(self_type& source) + { + raw_const_iterator first = source.raw_begin(); + raw_const_iterator last = source.raw_end(); + + if (first == last) + return; + + nodeptr_t previous_node = my_head; + raw_const_iterator begin_iterator = first++; + + // Move all elements one by one, including dummy ones + for (raw_const_iterator it = first; it != last;) + { + nodeptr_t pnode = it.get_node_ptr(); + + nodeptr_t dummy_node = pnode->is_dummy() ? create_node(pnode->get_order_key()) : create_node(pnode->get_order_key(), pnode->my_element); + previous_node = try_insert(previous_node, dummy_node, NULL); + __TBB_ASSERT(previous_node != NULL, "Insertion must succeed"); + raw_const_iterator where = it++; + source.erase_node(get_iterator(begin_iterator), where); + } + check_range(); + } + + +private: + + // Check the list for order violations + void check_range() + { +#if TBB_USE_ASSERT + for (raw_iterator it = raw_begin(); it != raw_end(); ++it) + { + raw_iterator next_iterator = it; + ++next_iterator; + + __TBB_ASSERT(next_iterator == end() || next_iterator.get_node_ptr()->get_order_key() >= it.get_node_ptr()->get_order_key(), "!!! List order inconsistency !!!"); + } +#endif + } + + typename allocator_type::template rebind::other my_node_allocator; // allocator object for nodes + size_type my_element_count; // Total item count, not counting dummy nodes + nodeptr_t my_head; // pointer to head node +}; + +// Template class for hash compare +template +class hash_compare +{ +public: + hash_compare() {} + + hash_compare(Hasher a_hasher) : my_hash_object(a_hasher) {} + + hash_compare(Hasher a_hasher, Key_equality a_keyeq) : my_hash_object(a_hasher), my_key_compare_object(a_keyeq) {} + + size_t operator()(const Key& key) const { + return ((size_t)my_hash_object(key)); + } + + bool operator()(const Key& key1, const Key& key2) const { + return (!my_key_compare_object(key1, key2)); + } + + Hasher my_hash_object; // The hash object + Key_equality my_key_compare_object; // The equality comparator object +}; + +#if _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) // warning 4127 -- while (true) has a constant expression in it (for allow_multimapping) +#endif + +template +class concurrent_unordered_base : public Traits +{ +protected: + // Type definitions + typedef concurrent_unordered_base self_type; + typedef typename Traits::value_type value_type; + typedef typename Traits::key_type key_type; + typedef typename Traits::hash_compare hash_compare; + typedef typename Traits::value_compare value_compare; + typedef typename Traits::allocator_type allocator_type; + typedef typename allocator_type::pointer pointer; + typedef typename allocator_type::const_pointer const_pointer; + typedef typename allocator_type::reference reference; + typedef typename allocator_type::const_reference const_reference; + typedef typename allocator_type::size_type size_type; + typedef typename allocator_type::difference_type difference_type; + typedef split_ordered_list solist_t; + typedef typename solist_t::nodeptr_t nodeptr_t; + // Iterators that walk the entire split-order list, including dummy nodes + typedef typename solist_t::raw_iterator raw_iterator; + typedef typename solist_t::raw_const_iterator raw_const_iterator; + typedef typename solist_t::iterator iterator; // TODO: restore const iterator for unordered_sets + typedef typename solist_t::const_iterator const_iterator; + typedef iterator local_iterator; + typedef const_iterator const_local_iterator; + using Traits::my_hash_compare; + using Traits::get_key; + using Traits::allow_multimapping; + +private: + typedef std::pair pairii_t; + typedef std::pair paircc_t; + + static size_type const pointers_per_table = sizeof(size_type) * 8; // One bucket segment per bit + static const size_type initial_bucket_number = 8; // Initial number of buckets + static const size_type initial_bucket_load = 4; // Initial maximum number of elements per bucket + +protected: + // Constructors/Destructors + concurrent_unordered_base(size_type n_of_buckets = initial_bucket_number, + const hash_compare& hc = hash_compare(), const allocator_type& a = allocator_type()) + : Traits(hc), my_solist(a), + my_allocator(a), my_maximum_bucket_size((float) initial_bucket_load) + { + if( n_of_buckets == 0) ++n_of_buckets; + my_number_of_buckets = 1<<__TBB_Log2((uintptr_t)n_of_buckets*2-1); // round up to power of 2 + internal_init(); + } + + concurrent_unordered_base(const concurrent_unordered_base& right, const allocator_type& a) + : Traits(right.my_hash_compare), my_solist(a), my_allocator(a) + { + internal_init(); + internal_copy(right); + } + + concurrent_unordered_base(const concurrent_unordered_base& right) + : Traits(right.my_hash_compare), my_solist(right.get_allocator()), my_allocator(right.get_allocator()) + { + internal_init(); + internal_copy(right); + } + + concurrent_unordered_base& operator=(const concurrent_unordered_base& right) { + if (this != &right) + internal_copy(right); + return (*this); + } + + ~concurrent_unordered_base() { + // Delete all node segments + internal_clear(); + } + +public: + allocator_type get_allocator() const { + return my_solist.get_allocator(); + } + + // Size and capacity function + bool empty() const { + return my_solist.empty(); + } + + size_type size() const { + return my_solist.size(); + } + + size_type max_size() const { + return my_solist.max_size(); + } + + // Iterators + iterator begin() { + return my_solist.begin(); + } + + const_iterator begin() const { + return my_solist.begin(); + } + + iterator end() { + return my_solist.end(); + } + + const_iterator end() const { + return my_solist.end(); + } + + const_iterator cbegin() const { + return my_solist.cbegin(); + } + + const_iterator cend() const { + return my_solist.cend(); + } + + // Parallel traversal support + class const_range_type : tbb::internal::no_assign { + const concurrent_unordered_base &my_table; + raw_const_iterator my_begin_node; + raw_const_iterator my_end_node; + mutable raw_const_iterator my_midpoint_node; + public: + //! Type for size of a range + typedef typename concurrent_unordered_base::size_type size_type; + typedef typename concurrent_unordered_base::value_type value_type; + typedef typename concurrent_unordered_base::reference reference; + typedef typename concurrent_unordered_base::difference_type difference_type; + typedef typename concurrent_unordered_base::const_iterator iterator; + + //! True if range is empty. + bool empty() const {return my_begin_node == my_end_node;} + + //! True if range can be partitioned into two subranges. + bool is_divisible() const { + return my_midpoint_node != my_end_node; + } + //! Split range. + const_range_type( const_range_type &r, split ) : + my_table(r.my_table), my_end_node(r.my_end_node) + { + r.my_end_node = my_begin_node = r.my_midpoint_node; + __TBB_ASSERT( !empty(), "Splitting despite the range is not divisible" ); + __TBB_ASSERT( !r.empty(), "Splitting despite the range is not divisible" ); + set_midpoint(); + r.set_midpoint(); + } + //! Init range with container and grainsize specified + const_range_type( const concurrent_unordered_base &a_table ) : + my_table(a_table), my_begin_node(a_table.my_solist.begin()), + my_end_node(a_table.my_solist.end()) + { + set_midpoint(); + } + iterator begin() const { return my_table.my_solist.get_iterator(my_begin_node); } + iterator end() const { return my_table.my_solist.get_iterator(my_end_node); } + //! The grain size for this range. + size_type grainsize() const { return 1; } + + //! Set my_midpoint_node to point approximately half way between my_begin_node and my_end_node. + void set_midpoint() const { + if( my_begin_node == my_end_node ) // not divisible + my_midpoint_node = my_end_node; + else { + sokey_t begin_key = solist_t::get_safe_order_key(my_begin_node); + sokey_t end_key = solist_t::get_safe_order_key(my_end_node); + size_t mid_bucket = __TBB_ReverseBits( begin_key + (end_key-begin_key)/2 ) % my_table.my_number_of_buckets; + while ( !my_table.is_initialized(mid_bucket) ) mid_bucket = my_table.get_parent(mid_bucket); + my_midpoint_node = my_table.my_solist.first_real_iterator(my_table.get_bucket( mid_bucket )); + if( my_midpoint_node == my_begin_node ) + my_midpoint_node = my_end_node; +#if TBB_USE_ASSERT + else { + sokey_t mid_key = solist_t::get_safe_order_key(my_midpoint_node); + __TBB_ASSERT( begin_key < mid_key, "my_begin_node is after my_midpoint_node" ); + __TBB_ASSERT( mid_key <= end_key, "my_midpoint_node is after my_end_node" ); + } +#endif // TBB_USE_ASSERT + } + } + }; + + class range_type : public const_range_type { + public: + typedef typename concurrent_unordered_base::iterator iterator; + //! Split range. + range_type( range_type &r, split ) : const_range_type( r, split() ) {} + //! Init range with container and grainsize specified + range_type( const concurrent_unordered_base &a_table ) : const_range_type(a_table) {} + + iterator begin() const { return solist_t::get_iterator( const_range_type::begin() ); } + iterator end() const { return solist_t::get_iterator( const_range_type::end() ); } + }; + + range_type range() { + return range_type( *this ); + } + + const_range_type range() const { + return const_range_type( *this ); + } + + // Modifiers + std::pair insert(const value_type& value) { + return internal_insert(value); + } + + iterator insert(const_iterator, const value_type& value) { + // Ignore hint + return insert(value).first; + } + + template + void insert(Iterator first, Iterator last) { + for (Iterator it = first; it != last; ++it) + insert(*it); + } + + iterator unsafe_erase(const_iterator where) { + return internal_erase(where); + } + + iterator unsafe_erase(const_iterator first, const_iterator last) { + while (first != last) + unsafe_erase(first++); + return my_solist.get_iterator(first); + } + + size_type unsafe_erase(const key_type& key) { + pairii_t where = equal_range(key); + size_type item_count = internal_distance(where.first, where.second); + unsafe_erase(where.first, where.second); + return item_count; + } + + void swap(concurrent_unordered_base& right) { + if (this != &right) { + std::swap(my_hash_compare, right.my_hash_compare); // TODO: check what ADL meant here + my_solist.swap(right.my_solist); + internal_swap_buckets(right); + std::swap(my_number_of_buckets, right.my_number_of_buckets); + std::swap(my_maximum_bucket_size, right.my_maximum_bucket_size); + } + } + + // Observers + void clear() { + // Clear list + my_solist.clear(); + + // Clear buckets + internal_clear(); + + // Initialize bucket 0 + __TBB_ASSERT(my_buckets[0] == NULL, NULL); + raw_iterator dummy_node = my_solist.raw_begin(); + set_bucket(0, dummy_node); + } + + // Lookup + iterator find(const key_type& key) { + return internal_find(key); + } + + const_iterator find(const key_type& key) const { + return const_cast(this)->internal_find(key); + } + + size_type count(const key_type& key) const { + if(allow_multimapping) { + paircc_t answer = equal_range(key); + size_type item_count = internal_distance(answer.first, answer.second); + return item_count; + } else { + return const_cast(this)->internal_find(key) == end()?0:1; + } + } + + std::pair equal_range(const key_type& key) { + return internal_equal_range(key); + } + + std::pair equal_range(const key_type& key) const { + return const_cast(this)->internal_equal_range(key); + } + + // Bucket interface - for debugging + size_type unsafe_bucket_count() const { + return my_number_of_buckets; + } + + size_type unsafe_max_bucket_count() const { + return segment_size(pointers_per_table-1); + } + + size_type unsafe_bucket_size(size_type bucket) { + size_type item_count = 0; + if (is_initialized(bucket)) { + raw_iterator it = get_bucket(bucket); + ++it; + for (; it != my_solist.raw_end() && !it.get_node_ptr()->is_dummy(); ++it) + ++item_count; + } + return item_count; + } + + size_type unsafe_bucket(const key_type& key) const { + sokey_t order_key = (sokey_t) my_hash_compare(key); + size_type bucket = order_key % my_number_of_buckets; + return bucket; + } + + // If the bucket is initialized, return a first non-dummy element in it + local_iterator unsafe_begin(size_type bucket) { + if (!is_initialized(bucket)) + return end(); + + raw_iterator it = get_bucket(bucket); + return my_solist.first_real_iterator(it); + } + + // If the bucket is initialized, return a first non-dummy element in it + const_local_iterator unsafe_begin(size_type bucket) const + { + if (!is_initialized(bucket)) + return end(); + + raw_const_iterator it = get_bucket(bucket); + return my_solist.first_real_iterator(it); + } + + // @REVIEW: Takes O(n) + // Returns the iterator after the last non-dummy element in the bucket + local_iterator unsafe_end(size_type bucket) + { + if (!is_initialized(bucket)) + return end(); + + raw_iterator it = get_bucket(bucket); + + // Find the end of the bucket, denoted by the dummy element + do ++it; + while(it != my_solist.raw_end() && !it.get_node_ptr()->is_dummy()); + + // Return the first real element past the end of the bucket + return my_solist.first_real_iterator(it); + } + + // @REVIEW: Takes O(n) + // Returns the iterator after the last non-dummy element in the bucket + const_local_iterator unsafe_end(size_type bucket) const + { + if (!is_initialized(bucket)) + return end(); + + raw_const_iterator it = get_bucket(bucket); + + // Find the end of the bucket, denoted by the dummy element + do ++it; + while(it != my_solist.raw_end() && !it.get_node_ptr()->is_dummy()); + + // Return the first real element past the end of the bucket + return my_solist.first_real_iterator(it); + } + + const_local_iterator unsafe_cbegin(size_type /*bucket*/) const { + return ((const self_type *) this)->begin(); + } + + const_local_iterator unsafe_cend(size_type /*bucket*/) const { + return ((const self_type *) this)->end(); + } + + // Hash policy + float load_factor() const { + return (float) size() / (float) unsafe_bucket_count(); + } + + float max_load_factor() const { + return my_maximum_bucket_size; + } + + void max_load_factor(float newmax) { + if (newmax != newmax || newmax < 0) + tbb::internal::throw_exception(tbb::internal::eid_invalid_load_factor); + my_maximum_bucket_size = newmax; + } + + // This function is a noop, because the underlying split-ordered list + // is already sorted, so an increase in the bucket number will be + // reflected next time this bucket is touched. + void rehash(size_type buckets) { + size_type current_buckets = my_number_of_buckets; + if (current_buckets >= buckets) + return; + my_number_of_buckets = 1<<__TBB_Log2((uintptr_t)buckets*2-1); // round up to power of 2 + } + +private: + + // Initialize the hash and keep the first bucket open + void internal_init() { + // Allocate an array of segment pointers + memset(my_buckets, 0, pointers_per_table * sizeof(void *)); + + // Initialize bucket 0 + raw_iterator dummy_node = my_solist.raw_begin(); + set_bucket(0, dummy_node); + } + + void internal_clear() { + for (size_type index = 0; index < pointers_per_table; ++index) { + if (my_buckets[index] != NULL) { + size_type sz = segment_size(index); + for (size_type index2 = 0; index2 < sz; ++index2) + my_allocator.destroy(&my_buckets[index][index2]); + my_allocator.deallocate(my_buckets[index], sz); + my_buckets[index] = 0; + } + } + } + + void internal_copy(const self_type& right) { + clear(); + + my_maximum_bucket_size = right.my_maximum_bucket_size; + my_number_of_buckets = right.my_number_of_buckets; + + __TBB_TRY { + insert(right.begin(), right.end()); + my_hash_compare = right.my_hash_compare; + } __TBB_CATCH(...) { + my_solist.clear(); + __TBB_RETHROW(); + } + } + + void internal_swap_buckets(concurrent_unordered_base& right) + { + // Swap all node segments + for (size_type index = 0; index < pointers_per_table; ++index) + { + raw_iterator * iterator_pointer = my_buckets[index]; + my_buckets[index] = right.my_buckets[index]; + right.my_buckets[index] = iterator_pointer; + } + } + + // Hash APIs + size_type internal_distance(const_iterator first, const_iterator last) const + { + size_type num = 0; + + for (const_iterator it = first; it != last; ++it) + ++num; + + return num; + } + + // Insert an element in the hash given its value + std::pair internal_insert(const value_type& value) + { + sokey_t order_key = (sokey_t) my_hash_compare(get_key(value)); + size_type bucket = order_key % my_number_of_buckets; + + // If bucket is empty, initialize it first + if (!is_initialized(bucket)) + init_bucket(bucket); + + size_type new_count; + order_key = split_order_key_regular(order_key); + raw_iterator it = get_bucket(bucket); + raw_iterator last = my_solist.raw_end(); + raw_iterator where = it; + + __TBB_ASSERT(where != last, "Invalid head node"); + + // First node is a dummy node + ++where; + + for (;;) + { + if (where == last || solist_t::get_order_key(where) > order_key) + { + // Try to insert it in the right place + std::pair result = my_solist.try_insert(it, where, value, order_key, &new_count); + + if (result.second) + { + // Insertion succeeded, adjust the table size, if needed + adjust_table_size(new_count, my_number_of_buckets); + return result; + } + else + { + // Insertion failed: either the same node was inserted by another thread, or + // another element was inserted at exactly the same place as this node. + // Proceed with the search from the previous location where order key was + // known to be larger (note: this is legal only because there is no safe + // concurrent erase operation supported). + where = it; + ++where; + continue; + } + } + else if (!allow_multimapping && solist_t::get_order_key(where) == order_key && my_hash_compare(get_key(*where), get_key(value)) == 0) + { + // Element already in the list, return it + return std::pair(my_solist.get_iterator(where), false); + } + + // Move the iterator forward + it = where; + ++where; + } + } + + // Find the element in the split-ordered list + iterator internal_find(const key_type& key) + { + sokey_t order_key = (sokey_t) my_hash_compare(key); + size_type bucket = order_key % my_number_of_buckets; + + // If bucket is empty, initialize it first + if (!is_initialized(bucket)) + init_bucket(bucket); + + order_key = split_order_key_regular(order_key); + raw_iterator last = my_solist.raw_end(); + + for (raw_iterator it = get_bucket(bucket); it != last; ++it) + { + if (solist_t::get_order_key(it) > order_key) + { + // If the order key is smaller than the current order key, the element + // is not in the hash. + return end(); + } + else if (solist_t::get_order_key(it) == order_key) + { + // The fact that order keys match does not mean that the element is found. + // Key function comparison has to be performed to check whether this is the + // right element. If not, keep searching while order key is the same. + if (!my_hash_compare(get_key(*it), key)) + return my_solist.get_iterator(it); + } + } + + return end(); + } + + // Erase an element from the list. This is not a concurrency safe function. + iterator internal_erase(const_iterator it) + { + key_type key = get_key(*it); + sokey_t order_key = (sokey_t) my_hash_compare(key); + size_type bucket = order_key % my_number_of_buckets; + + // If bucket is empty, initialize it first + if (!is_initialized(bucket)) + init_bucket(bucket); + + order_key = split_order_key_regular(order_key); + + raw_iterator previous = get_bucket(bucket); + raw_iterator last = my_solist.raw_end(); + raw_iterator where = previous; + + __TBB_ASSERT(where != last, "Invalid head node"); + + // First node is a dummy node + ++where; + + for (;;) { + if (where == last) + return end(); + else if (my_solist.get_iterator(where) == it) + return my_solist.erase_node(previous, it); + + // Move the iterator forward + previous = where; + ++where; + } + } + + // Return the [begin, end) pair of iterators with the same key values. + // This operation makes sense only if mapping is many-to-one. + pairii_t internal_equal_range(const key_type& key) + { + sokey_t order_key = (sokey_t) my_hash_compare(key); + size_type bucket = order_key % my_number_of_buckets; + + // If bucket is empty, initialize it first + if (!is_initialized(bucket)) + init_bucket(bucket); + + order_key = split_order_key_regular(order_key); + raw_iterator end_it = my_solist.raw_end(); + + for (raw_iterator it = get_bucket(bucket); it != end_it; ++it) + { + if (solist_t::get_order_key(it) > order_key) + { + // There is no element with the given key + return pairii_t(end(), end()); + } + else if (solist_t::get_order_key(it) == order_key && !my_hash_compare(get_key(*it), key)) + { + iterator first = my_solist.get_iterator(it); + iterator last = first; + do ++last; while( allow_multimapping && last != end() && !my_hash_compare(get_key(*last), key) ); + return pairii_t(first, last); + } + } + + return pairii_t(end(), end()); + } + + // Bucket APIs + void init_bucket(size_type bucket) + { + // Bucket 0 has no parent. + __TBB_ASSERT( bucket != 0, "The first bucket must always be initialized"); + + size_type parent_bucket = get_parent(bucket); + + // All parent_bucket buckets have to be initialized before this bucket is + if (!is_initialized(parent_bucket)) + init_bucket(parent_bucket); + + raw_iterator parent = get_bucket(parent_bucket); + + // Create a dummy first node in this bucket + raw_iterator dummy_node = my_solist.insert_dummy(parent, split_order_key_dummy(bucket)); + set_bucket(bucket, dummy_node); + } + + void adjust_table_size(size_type total_elements, size_type current_size) + { + // Grow the table by a factor of 2 if possible and needed + if ( ((float) total_elements / (float) current_size) > my_maximum_bucket_size ) + { + // Double the size of the hash only if size has not changed inbetween loads + __TBB_CompareAndSwapW((uintptr_t*)&my_number_of_buckets, uintptr_t(2u*current_size), uintptr_t(current_size) ); + //Simple "my_number_of_buckets.compare_and_swap( current_size<<1, current_size );" does not work for VC8 + //due to overzealous compiler warnings in /Wp64 mode + } + } + + size_type get_parent(size_type bucket) const + { + // Unsets bucket's most significant turned-on bit + size_type msb = __TBB_Log2((uintptr_t)bucket); + return bucket & ~(size_type(1) << msb); + } + + + // Dynamic sized array (segments) + //! @return segment index of given index in the array + static size_type segment_index_of( size_type index ) { + return size_type( __TBB_Log2( uintptr_t(index|1) ) ); + } + + //! @return the first array index of given segment + static size_type segment_base( size_type k ) { + return (size_type(1)< my_number_of_buckets; // Current table size + solist_t my_solist; // List where all the elements are kept + typename allocator_type::template rebind::other my_allocator; // Allocator object for segments + float my_maximum_bucket_size; // Maximum size of the bucket + atomic my_buckets[pointers_per_table]; // The segment table +}; +#if _MSC_VER +#pragma warning(pop) // warning 4127 -- while (true) has a constant expression in it +#endif + +//! Hash multiplier +static const size_t hash_multiplier = tbb::internal::size_t_select(2654435769U, 11400714819323198485ULL); +} // namespace internal +//! @endcond +//! Hasher functions +template +inline size_t tbb_hasher( const T& t ) { + return static_cast( t ) * internal::hash_multiplier; +} +template +inline size_t tbb_hasher( P* ptr ) { + size_t const h = reinterpret_cast( ptr ); + return (h >> 3) ^ h; +} +template +inline size_t tbb_hasher( const std::basic_string& s ) { + size_t h = 0; + for( const E* c = s.c_str(); *c; ++c ) + h = static_cast(*c) ^ (h * internal::hash_multiplier); + return h; +} +template +inline size_t tbb_hasher( const std::pair& p ) { + return tbb_hasher(p.first) ^ tbb_hasher(p.second); +} +} // namespace interface5 +using interface5::tbb_hasher; + + +// Template class for hash compare +template +class tbb_hash +{ +public: + tbb_hash() {} + + size_t operator()(const Key& key) const + { + return tbb_hasher(key); + } +}; + +} // namespace tbb +#endif// __TBB__concurrent_unordered_impl_H diff --git a/src/tbb/include/tbb/internal/_flow_graph_impl.h b/src/tbb/include/tbb/internal/_flow_graph_impl.h new file mode 100644 index 0000000..fe932a6 --- /dev/null +++ b/src/tbb/include/tbb/internal/_flow_graph_impl.h @@ -0,0 +1,580 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB__flow_graph_impl_H +#define __TBB__flow_graph_impl_H + +#ifndef __TBB_flow_graph_H +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + +namespace internal { + + namespace graph_policy_namespace { + enum graph_buffer_policy { rejecting, reserving, queueing, tag_matching }; + } + + //! A functor that takes no input and generates a value of type Output + template< typename Output > + class source_body : tbb::internal::no_assign { + public: + virtual ~source_body() {} + virtual bool operator()(Output &output) = 0; + virtual source_body* clone() = 0; + }; + + //! The leaf for source_body + template< typename Output, typename Body> + class source_body_leaf : public source_body { + public: + source_body_leaf( const Body &_body ) : body(_body), init_body(_body) { } + /*override*/ bool operator()(Output &output) { return body( output ); } + /*override*/ source_body_leaf* clone() { + return new source_body_leaf< Output, Body >(init_body); + } + private: + Body body; + Body init_body; + }; + + //! A functor that takes an Input and generates an Output + template< typename Input, typename Output > + class function_body : tbb::internal::no_assign { + public: + virtual ~function_body() {} + virtual Output operator()(const Input &input) = 0; + virtual function_body* clone() = 0; + }; + + //! the leaf for function_body + template + class function_body_leaf : public function_body< Input, Output > { + public: + function_body_leaf( const B &_body ) : body(_body), init_body(_body) { } + Output operator()(const Input &i) { return body(i); } + B get_body() { return body; } + /*override*/ function_body_leaf* clone() { + return new function_body_leaf< Input, Output, B >(init_body); + } + private: + B body; + B init_body; + }; + + //! the leaf for function_body specialized for Input and output of continue_msg + template + class function_body_leaf< continue_msg, continue_msg, B> : public function_body< continue_msg, continue_msg > { + public: + function_body_leaf( const B &_body ) : body(_body), init_body(_body) { } + continue_msg operator()( const continue_msg &i ) { + body(i); + return i; + } + B get_body() { return body; } + /*override*/ function_body_leaf* clone() { + return new function_body_leaf< continue_msg, continue_msg, B >(init_body); + } + private: + B body; + B init_body; + }; + + //! the leaf for function_body specialized for Output of continue_msg + template + class function_body_leaf< Input, continue_msg, B> : public function_body< Input, continue_msg > { + public: + function_body_leaf( const B &_body ) : body(_body), init_body(_body) { } + continue_msg operator()(const Input &i) { + body(i); + return continue_msg(); + } + B get_body() { return body; } + /*override*/ function_body_leaf* clone() { + return new function_body_leaf< Input, continue_msg, B >(init_body); + } + private: + B body; + B init_body; + }; + + //! the leaf for function_body specialized for Input of continue_msg + template + class function_body_leaf< continue_msg, Output, B > : public function_body< continue_msg, Output > { + public: + function_body_leaf( const B &_body ) : body(_body), init_body(_body) { } + Output operator()(const continue_msg &i) { + return body(i); + } + B get_body() { return body; } + /*override*/ function_body_leaf* clone() { + return new function_body_leaf< continue_msg, Output, B >(init_body); + } + private: + B body; + B init_body; + }; + + //! function_body that takes an Input and a set of output ports + template + class multifunction_body { + public: + virtual ~multifunction_body () {} + virtual void operator()(const Input &/* input*/, OutputSet &/*oset*/) = 0; + virtual multifunction_body* clone() = 0; + }; + + //! leaf for multifunction. OutputSet can be a std::tuple or a vector. + template + class multifunction_body_leaf : public multifunction_body { + public: + multifunction_body_leaf(const B &_body) : body(_body), init_body(_body) { } + void operator()(const Input &input, OutputSet &oset) { + body(input, oset); // body should explicitly put() to one or more of oset. + } + B get_body() { return body; } + /*override*/ multifunction_body_leaf* clone() { + return new multifunction_body_leaf(init_body); + } + private: + B body; + B init_body; + }; + + //! A task that calls a node's forward function + template< typename NodeType > + class forward_task : public task { + + NodeType &my_node; + + public: + + forward_task( NodeType &n ) : my_node(n) {} + + task *execute() { + my_node.forward(); + return NULL; + } + }; + + //! A task that calls a node's apply_body function, passing in an input of type Input + template< typename NodeType, typename Input > + class apply_body_task : public task { + + NodeType &my_node; + Input my_input; + + public: + + apply_body_task( NodeType &n, const Input &i ) : my_node(n), my_input(i) {} + + task *execute() { + my_node.apply_body( my_input ); + return NULL; + } + }; + + //! A task that calls a node's apply_body function with no input + template< typename NodeType > + class source_task : public task { + + NodeType &my_node; + + public: + + source_task( NodeType &n ) : my_node(n) {} + + task *execute() { + my_node.apply_body( ); + return NULL; + } + }; + + //! An empty functor that takes an Input and returns a default constructed Output + template< typename Input, typename Output > + struct empty_body { + Output operator()( const Input & ) const { return Output(); } + }; + + //! A node_cache maintains a std::queue of elements of type T. Each operation is protected by a lock. + template< typename T, typename M=spin_mutex > + class node_cache { + public: + + typedef size_t size_type; + + bool empty() { + typename my_mutex_type::scoped_lock lock( my_mutex ); + return internal_empty(); + } + + void add( T &n ) { + typename my_mutex_type::scoped_lock lock( my_mutex ); + internal_push(n); + } + + void remove( T &n ) { + typename my_mutex_type::scoped_lock lock( my_mutex ); + for ( size_t i = internal_size(); i != 0; --i ) { + T &s = internal_pop(); + if ( &s != &n ) { + internal_push(s); + } + } + } + + protected: + + typedef M my_mutex_type; + my_mutex_type my_mutex; + std::queue< T * > my_q; + + // Assumes lock is held + inline bool internal_empty( ) { + return my_q.empty(); + } + + // Assumes lock is held + inline size_type internal_size( ) { + return my_q.size(); + } + + // Assumes lock is held + inline void internal_push( T &n ) { + my_q.push(&n); + } + + // Assumes lock is held + inline T &internal_pop() { + T *v = my_q.front(); + my_q.pop(); + return *v; + } + + }; + + //! A cache of predecessors that only supports try_get + template< typename T, typename M=spin_mutex > + class predecessor_cache : public node_cache< sender, M > { + public: + typedef M my_mutex_type; + typedef T output_type; + typedef sender predecessor_type; + typedef receiver successor_type; + + predecessor_cache( ) : my_owner( NULL ) { } + + void set_owner( successor_type *owner ) { my_owner = owner; } + + bool get_item( output_type &v ) { + + bool msg = false; + + do { + predecessor_type *src; + { + typename my_mutex_type::scoped_lock lock(this->my_mutex); + if ( this->internal_empty() ) { + break; + } + src = &this->internal_pop(); + } + + // Try to get from this sender + msg = src->try_get( v ); + + if (msg == false) { + // Relinquish ownership of the edge + if ( my_owner) + src->register_successor( *my_owner ); + } else { + // Retain ownership of the edge + this->add(*src); + } + } while ( msg == false ); + return msg; + } + + protected: + successor_type *my_owner; + }; + + //! An cache of predecessors that supports requests and reservations + template< typename T, typename M=spin_mutex > + class reservable_predecessor_cache : public predecessor_cache< T, M > { + public: + typedef M my_mutex_type; + typedef T output_type; + typedef sender predecessor_type; + typedef receiver successor_type; + + reservable_predecessor_cache( ) : reserved_src(NULL) { } + + bool + try_reserve( output_type &v ) { + bool msg = false; + + do { + { + typename my_mutex_type::scoped_lock lock(this->my_mutex); + if ( reserved_src || this->internal_empty() ) + return false; + + reserved_src = &this->internal_pop(); + } + + // Try to get from this sender + msg = reserved_src->try_reserve( v ); + + if (msg == false) { + typename my_mutex_type::scoped_lock lock(this->my_mutex); + // Relinquish ownership of the edge + reserved_src->register_successor( *this->my_owner ); + reserved_src = NULL; + } else { + // Retain ownership of the edge + this->add( *reserved_src ); + } + } while ( msg == false ); + + return msg; + } + + bool + try_release( ) { + reserved_src->try_release( ); + reserved_src = NULL; + return true; + } + + bool + try_consume( ) { + reserved_src->try_consume( ); + reserved_src = NULL; + return true; + } + + private: + predecessor_type *reserved_src; + }; + + + //! An abstract cache of succesors + template + class successor_cache : tbb::internal::no_copy { + protected: + + typedef M my_mutex_type; + my_mutex_type my_mutex; + + typedef std::list< receiver * > my_successors_type; + my_successors_type my_successors; + + sender *my_owner; + + public: + + successor_cache( ) : my_owner(NULL) {} + + void set_owner( sender *owner ) { my_owner = owner; } + + virtual ~successor_cache() {} + + void register_successor( receiver &r ) { + typename my_mutex_type::scoped_lock l(my_mutex, true); + my_successors.push_back( &r ); + } + + void remove_successor( receiver &r ) { + typename my_mutex_type::scoped_lock l(my_mutex, true); + for ( typename my_successors_type::iterator i = my_successors.begin(); + i != my_successors.end(); ++i ) { + if ( *i == & r ) { + my_successors.erase(i); + break; + } + } + } + + bool empty() { + typename my_mutex_type::scoped_lock l(my_mutex, false); + return my_successors.empty(); + } + + virtual bool try_put( const T &t ) = 0; + }; + + //! An abstract cache of succesors, specialized to continue_msg + template<> + class successor_cache< continue_msg > : tbb::internal::no_copy { + protected: + + typedef spin_rw_mutex my_mutex_type; + my_mutex_type my_mutex; + + typedef std::list< receiver * > my_successors_type; + my_successors_type my_successors; + + sender *my_owner; + + public: + + successor_cache( ) : my_owner(NULL) {} + + void set_owner( sender *owner ) { my_owner = owner; } + + virtual ~successor_cache() {} + + void register_successor( receiver &r ) { + my_mutex_type::scoped_lock l(my_mutex, true); + my_successors.push_back( &r ); + if ( my_owner ) { + continue_receiver *cr = dynamic_cast< continue_receiver * >(&r); + if ( cr ) + cr->register_predecessor( *my_owner ); + } + } + + void remove_successor( receiver &r ) { + my_mutex_type::scoped_lock l(my_mutex, true); + for ( my_successors_type::iterator i = my_successors.begin(); + i != my_successors.end(); ++i ) { + if ( *i == & r ) { + if ( my_owner ) + r.remove_predecessor( *my_owner ); + my_successors.erase(i); + break; + } + } + } + + bool empty() { + my_mutex_type::scoped_lock l(my_mutex, false); + return my_successors.empty(); + } + + virtual bool try_put( const continue_msg &t ) = 0; + + }; + + //! A cache of successors that are broadcast to + template + class broadcast_cache : public successor_cache { + typedef M my_mutex_type; + typedef std::list< receiver * > my_successors_type; + + public: + + broadcast_cache( ) {} + + bool try_put( const T &t ) { + bool msg = false; + bool upgraded = false; + typename my_mutex_type::scoped_lock l(this->my_mutex, false); + typename my_successors_type::iterator i = this->my_successors.begin(); + while ( i != this->my_successors.end() ) { + if ( (*i)->try_put( t ) == true ) { + ++i; + msg = true; + } else { + if ( (*i)->register_predecessor(*this->my_owner) ) { + if (!upgraded) { + l.upgrade_to_writer(); + upgraded = true; + } + i = this->my_successors.erase(i); + } + else { + ++i; + } + } + } + return msg; + } + }; + + //! A cache of successors that are put in a round-robin fashion + template + class round_robin_cache : public successor_cache { + typedef size_t size_type; + typedef M my_mutex_type; + typedef std::list< receiver * > my_successors_type; + + public: + + round_robin_cache( ) {} + + size_type size() { + typename my_mutex_type::scoped_lock l(this->my_mutex, false); + return this->my_successors.size(); + } + + bool try_put( const T &t ) { + bool upgraded = false; + typename my_mutex_type::scoped_lock l(this->my_mutex, false); + typename my_successors_type::iterator i = this->my_successors.begin(); + while ( i != this->my_successors.end() ) { + if ( (*i)->try_put( t ) ) { + return true; + } else { + if ( (*i)->register_predecessor(*this->my_owner) ) { + if (!upgraded) { + l.upgrade_to_writer(); + upgraded = true; + } + i = this->my_successors.erase(i); + } + else { + ++i; + } + } + } + return false; + } + }; + + template + class decrementer : public continue_receiver, tbb::internal::no_copy { + + T *my_node; + + void execute() { + my_node->decrement_counter(); + } + + public: + + typedef continue_msg input_type; + typedef continue_msg output_type; + decrementer( int number_of_predecessors = 0 ) : continue_receiver( number_of_predecessors ) { } + void set_owner( T *node ) { my_node = node; } + }; + +} + +#endif // __TBB__flow_graph_impl_H + diff --git a/src/tbb/include/tbb/internal/_flow_graph_item_buffer_impl.h b/src/tbb/include/tbb/internal/_flow_graph_item_buffer_impl.h new file mode 100644 index 0000000..d217005 --- /dev/null +++ b/src/tbb/include/tbb/internal/_flow_graph_item_buffer_impl.h @@ -0,0 +1,190 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB__flow_graph_item_buffer_impl_H +#define __TBB__flow_graph_item_buffer_impl_H + +#ifndef __TBB_flow_graph_H +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + + //! Expandable buffer of items. The possible operations are push, pop, + //* tests for empty and so forth. No mutual exclusion is built in. + template > + class item_buffer { + public: + typedef T input_type; + typedef T output_type; + protected: + typedef size_t size_type; + typedef std::pair< T, bool > item_type; + typedef typename A::template rebind::other allocator_type; + + item_type *my_array; + size_type my_array_size; + static const size_type initial_buffer_size = 4; + size_type my_head; + size_type my_tail; + + bool buffer_empty() { return my_head == my_tail; } + + item_type &item(size_type i) { return my_array[i & (my_array_size - 1) ]; } // may not be marked valid + + bool item_valid(size_type i) { return item(i).second; } + + void fetch_front(T &v) { __TBB_ASSERT(item_valid(my_head), "front not valid"); v = item(my_head).first; } + void fetch_back(T &v) { __TBB_ASSERT(item_valid(my_tail-1), "back not valid"); v = item(my_tail-1).first; } + + void invalidate(size_type i) { __TBB_ASSERT(item_valid(i), "Item not valid"); item(i).second = false; } + void validate(size_type i) { __TBB_ASSERT(!item_valid(i), "Item already valid"); item(i).second = true; } + + void invalidate_front() { invalidate(my_head); } + void validate_front() { validate(my_head); } + void invalidate_back() { invalidate(my_tail-1); } + + size_type size() { return my_tail - my_head; } + size_type capacity() { return my_array_size; } + bool buffer_full() { return size() == capacity(); } + + //! Grows the internal array. + void grow_my_array( size_t minimum_size ) { + size_type old_size = my_array_size; + size_type new_size = old_size ? 2*old_size : initial_buffer_size; + while( new_size > + class reservable_item_buffer : public item_buffer { + protected: + using item_buffer::buffer_empty; + using item_buffer::fetch_front; + using item_buffer::invalidate_front; + using item_buffer::validate_front; + using item_buffer::item_valid; + using item_buffer::my_head; + + public: + reservable_item_buffer() : item_buffer(), my_reserved(false) {} + protected: + + bool reserve_front(T &v) { + if(my_reserved || !item_valid(my_head)) return false; + my_reserved = true; + // reserving the head + fetch_front(v); + // invalidate the head, but don't commit until consume is called + invalidate_front(); + return true; + } + + void consume_front() { + __TBB_ASSERT(my_reserved, "Attempt to consume a non-reserved item"); + ++my_head; + my_reserved = false; + } + + void release_front() { + __TBB_ASSERT(my_reserved, "Attempt to release a non-reserved item"); + validate_front(); + my_reserved = false; + } + + bool my_reserved; + }; + +#endif // __TBB__flow_graph_item_buffer_impl_H diff --git a/src/tbb/include/tbb/internal/_flow_graph_join_impl.h b/src/tbb/include/tbb/internal/_flow_graph_join_impl.h new file mode 100644 index 0000000..0555411 --- /dev/null +++ b/src/tbb/include/tbb/internal/_flow_graph_join_impl.h @@ -0,0 +1,1399 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB__flow_graph_join_impl_H +#define __TBB__flow_graph_join_impl_H + +#ifndef __TBB_flow_graph_H +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + +#include "tbb/internal/_flow_graph_types_impl.h" + +namespace internal { + + typedef size_t tag_value; + static const tag_value NO_TAG = tag_value(-1); + + struct forwarding_base { + forwarding_base(task *rt) : my_root_task(rt), current_tag(NO_TAG) {} + virtual ~forwarding_base() {} + virtual void decrement_port_count() = 0; + virtual void increment_port_count() = 0; + virtual void increment_tag_count(tag_value /*t*/) {} + // moved here so input ports can queue tasks + task* my_root_task; + tag_value current_tag; // so ports can refer to FE's desired items + }; + + template< int N > + struct join_helper { + + template< typename TupleType, typename PortType > + static inline void set_join_node_pointer(TupleType &my_input, PortType *port) { + std::get( my_input ).set_join_node_pointer(port); + join_helper::set_join_node_pointer( my_input, port ); + } + template< typename TupleType > + static inline void consume_reservations( TupleType &my_input ) { + std::get( my_input ).consume(); + join_helper::consume_reservations( my_input ); + } + + template< typename TupleType > + static inline void release_my_reservation( TupleType &my_input ) { + std::get( my_input ).release(); + } + + template + static inline void release_reservations( TupleType &my_input) { + join_helper::release_reservations(my_input); + release_my_reservation(my_input); + } + + template< typename InputTuple, typename OutputTuple > + static inline bool reserve( InputTuple &my_input, OutputTuple &out) { + if ( !std::get( my_input ).reserve( std::get( out ) ) ) return false; + if ( !join_helper::reserve( my_input, out ) ) { + release_my_reservation( my_input ); + return false; + } + return true; + } + + template + static inline bool get_my_item( InputTuple &my_input, OutputTuple &out) { + bool res = std::get(my_input).get_item(std::get(out) ); // may fail + return join_helper::get_my_item(my_input, out) && res; // do get on other inputs before returning + } + + template + static inline bool get_items(InputTuple &my_input, OutputTuple &out) { + return get_my_item(my_input, out); + } + + template + static inline void reset_my_port(InputTuple &my_input) { + join_helper::reset_my_port(my_input); + std::get(my_input).reset_port(); + } + + template + static inline void reset_ports(InputTuple& my_input) { + reset_my_port(my_input); + } + + template + static inline void set_tag_func(InputTuple &my_input, TagFuncTuple &my_tag_funcs) { + std::get(my_input).set_my_original_tag_func(std::get(my_tag_funcs)); + std::get(my_input).set_my_tag_func(std::get(my_input).my_original_func()->clone()); + std::get(my_tag_funcs) = NULL; + join_helper::set_tag_func(my_input, my_tag_funcs); + } + + template< typename TagFuncTuple1, typename TagFuncTuple2> + static inline void copy_tag_functors(TagFuncTuple1 &my_inputs, TagFuncTuple2 &other_inputs) { + if(std::get(other_inputs).my_original_func()) { + std::get(my_inputs).set_my_tag_func(std::get(other_inputs).my_original_func()->clone()); + std::get(my_inputs).set_my_original_tag_func(std::get(other_inputs).my_original_func()->clone()); + } + join_helper::copy_tag_functors(my_inputs, other_inputs); + } + }; + + template< > + struct join_helper<1> { + + template< typename TupleType, typename PortType > + static inline void set_join_node_pointer(TupleType &my_input, PortType *port) { + std::get<0>( my_input ).set_join_node_pointer(port); + } + + template< typename TupleType > + static inline void consume_reservations( TupleType &my_input ) { + std::get<0>( my_input ).consume(); + } + + template< typename TupleType > + static inline void release_my_reservation( TupleType &my_input ) { + std::get<0>( my_input ).release(); + } + + template + static inline void release_reservations( TupleType &my_input) { + release_my_reservation(my_input); + } + + template< typename InputTuple, typename OutputTuple > + static inline bool reserve( InputTuple &my_input, OutputTuple &out) { + return std::get<0>( my_input ).reserve( std::get<0>( out ) ); + } + + template + static inline bool get_my_item( InputTuple &my_input, OutputTuple &out) { + return std::get<0>(my_input).get_item(std::get<0>(out)); + } + + template + static inline bool get_items(InputTuple &my_input, OutputTuple &out) { + return get_my_item(my_input, out); + } + + template + static inline void reset_my_port(InputTuple &my_input) { + std::get<0>(my_input).reset_port(); + } + + template + static inline void reset_ports(InputTuple& my_input) { + reset_my_port(my_input); + } + + template + static inline void set_tag_func(InputTuple &my_input, TagFuncTuple &my_tag_funcs) { + std::get<0>(my_input).set_my_original_tag_func(std::get<0>(my_tag_funcs)); + std::get<0>(my_input).set_my_tag_func(std::get<0>(my_input).my_original_func()->clone()); + std::get<0>(my_tag_funcs) = NULL; + } + + template< typename TagFuncTuple1, typename TagFuncTuple2> + static inline void copy_tag_functors(TagFuncTuple1 &my_inputs, TagFuncTuple2 &other_inputs) { + if(std::get<0>(other_inputs).my_original_func()) { + std::get<0>(my_inputs).set_my_tag_func(std::get<0>(other_inputs).my_original_func()->clone()); + std::get<0>(my_inputs).set_my_original_tag_func(std::get<0>(other_inputs).my_original_func()->clone()); + } + } + }; + + //! The two-phase join port + template< typename T > + class reserving_port : public receiver { + public: + typedef T input_type; + typedef sender predecessor_type; + private: + // ----------- Aggregator ------------ + enum op_type { reg_pred, rem_pred, res_item, rel_res, con_res }; + enum op_stat {WAIT=0, SUCCEEDED, FAILED}; + typedef reserving_port my_class; + + class reserving_port_operation : public aggregated_operation { + public: + char type; + union { + T *my_arg; + predecessor_type *my_pred; + }; + reserving_port_operation(const T& e, op_type t) : + type(char(t)), my_arg(const_cast(&e)) {} + reserving_port_operation(const predecessor_type &s, op_type t) : type(char(t)), + my_pred(const_cast(&s)) {} + reserving_port_operation(op_type t) : type(char(t)) {} + }; + + typedef internal::aggregating_functor my_handler; + friend class internal::aggregating_functor; + aggregator my_aggregator; + + void handle_operations(reserving_port_operation* op_list) { + reserving_port_operation *current; + bool no_predecessors; + while(op_list) { + current = op_list; + op_list = op_list->next; + switch(current->type) { + case reg_pred: + no_predecessors = my_predecessors.empty(); + my_predecessors.add(*(current->my_pred)); + if ( no_predecessors ) { + my_join->decrement_port_count( ); // may try to forward + } + __TBB_store_with_release(current->status, SUCCEEDED); + break; + case rem_pred: + my_predecessors.remove(*(current->my_pred)); + if(my_predecessors.empty()) my_join->increment_port_count(); + __TBB_store_with_release(current->status, SUCCEEDED); + break; + case res_item: + if ( reserved ) { + __TBB_store_with_release(current->status, FAILED); + } + else if ( my_predecessors.try_reserve( *(current->my_arg) ) ) { + reserved = true; + __TBB_store_with_release(current->status, SUCCEEDED); + } else { + if ( my_predecessors.empty() ) { + my_join->increment_port_count(); + } + __TBB_store_with_release(current->status, FAILED); + } + break; + case rel_res: + reserved = false; + my_predecessors.try_release( ); + __TBB_store_with_release(current->status, SUCCEEDED); + break; + case con_res: + reserved = false; + my_predecessors.try_consume( ); + __TBB_store_with_release(current->status, SUCCEEDED); + break; + } + } + } + + public: + + //! Constructor + reserving_port() : reserved(false) { + my_join = NULL; + my_predecessors.set_owner( this ); + my_aggregator.initialize_handler(my_handler(this)); + } + + // copy constructor + reserving_port(const reserving_port& /* other */) : receiver() { + reserved = false; + my_join = NULL; + my_predecessors.set_owner( this ); + my_aggregator.initialize_handler(my_handler(this)); + } + + void set_join_node_pointer(forwarding_base *join) { + my_join = join; + } + + // always rejects, so arc is reversed (and reserves can be done.) + bool try_put( const T & ) { + return false; + } + + //! Add a predecessor + bool register_predecessor( sender &src ) { + reserving_port_operation op_data(src, reg_pred); + my_aggregator.execute(&op_data); + return op_data.status == SUCCEEDED; + } + + //! Remove a predecessor + bool remove_predecessor( sender &src ) { + reserving_port_operation op_data(src, rem_pred); + my_aggregator.execute(&op_data); + return op_data.status == SUCCEEDED; + } + + //! Reserve an item from the port + bool reserve( T &v ) { + reserving_port_operation op_data(v, res_item); + my_aggregator.execute(&op_data); + return op_data.status == SUCCEEDED; + } + + //! Release the port + void release( ) { + reserving_port_operation op_data(rel_res); + my_aggregator.execute(&op_data); + } + + //! Complete use of the port + void consume( ) { + reserving_port_operation op_data(con_res); + my_aggregator.execute(&op_data); + } + + private: + forwarding_base *my_join; + reservable_predecessor_cache< T, null_mutex > my_predecessors; + bool reserved; + }; + + //! queueing join_port + template + class queueing_port : public receiver, public item_buffer { + public: + typedef T input_type; + typedef sender predecessor_type; + typedef queueing_port my_node_type; + + // ----------- Aggregator ------------ + private: + enum op_type { try__put, get__item, res_port }; + enum op_stat {WAIT=0, SUCCEEDED, FAILED}; + typedef queueing_port my_class; + + class queueing_port_operation : public aggregated_operation { + public: + char type; + T my_val; + T *my_arg; + // constructor for value parameter + queueing_port_operation(const T& e, op_type t) : + // type(char(t)), my_val(const_cast(e)) {} + type(char(t)), my_val(e) {} + // constructor for pointer parameter + queueing_port_operation(const T* p, op_type t) : + type(char(t)), my_arg(const_cast(p)) {} + // constructor with no parameter + queueing_port_operation(op_type t) : type(char(t)) {} + }; + + typedef internal::aggregating_functor my_handler; + friend class internal::aggregating_functor; + aggregator my_aggregator; + + void handle_operations(queueing_port_operation* op_list) { + queueing_port_operation *current; + bool was_empty; + while(op_list) { + current = op_list; + op_list = op_list->next; + switch(current->type) { + case try__put: + was_empty = this->buffer_empty(); + this->push_back(current->my_val); + if (was_empty) my_join->decrement_port_count(); + __TBB_store_with_release(current->status, SUCCEEDED); + break; + case get__item: + if(!this->buffer_empty()) { + this->fetch_front(*(current->my_arg)); + __TBB_store_with_release(current->status, SUCCEEDED); + } + else { + __TBB_store_with_release(current->status, FAILED); + } + break; + case res_port: + __TBB_ASSERT(this->item_valid(this->my_head), "No item to reset"); + this->invalidate_front(); ++(this->my_head); + if(this->item_valid(this->my_head)) { + my_join->decrement_port_count(); + } + __TBB_store_with_release(current->status, SUCCEEDED); + break; + } + } + } + // ------------ End Aggregator --------------- + public: + + //! Constructor + queueing_port() : item_buffer() { + my_join = NULL; + my_aggregator.initialize_handler(my_handler(this)); + } + + //! copy constructor + queueing_port(const queueing_port& /* other */) : receiver(), item_buffer() { + my_join = NULL; + my_aggregator.initialize_handler(my_handler(this)); + } + + //! record parent for tallying available items + void set_join_node_pointer(forwarding_base *join) { + my_join = join; + } + + /*override*/bool try_put(const T &v) { + queueing_port_operation op_data(v, try__put); + my_aggregator.execute(&op_data); + return op_data.status == SUCCEEDED; + } + + + bool get_item( T &v ) { + queueing_port_operation op_data(&v, get__item); + my_aggregator.execute(&op_data); + return op_data.status == SUCCEEDED; + } + + // reset_port is called when item is accepted by successor, but + // is initiated by join_node. + void reset_port() { + queueing_port_operation op_data(res_port); + my_aggregator.execute(&op_data); + return; + } + + private: + forwarding_base *my_join; + }; + +#include "_flow_graph_tagged_buffer_impl.h" + + template< typename T > + class tag_matching_port : public receiver, public tagged_buffer< tag_value, T, NO_TAG > { + public: + typedef T input_type; + typedef sender predecessor_type; + typedef tag_matching_port my_node_type; // for forwarding, if needed + typedef function_body my_tag_func_type; + private: +// ----------- Aggregator ------------ + private: + enum op_type { try__put, get__item, res_port }; + enum op_stat {WAIT=0, SUCCEEDED, FAILED}; + typedef tag_matching_port my_class; + + class tag_matching_port_operation : public aggregated_operation { + public: + char type; + T my_val; + T *my_arg; + tag_value my_tag_value; + // constructor for value parameter + tag_matching_port_operation(const T& e, op_type t) : + // type(char(t)), my_val(const_cast(e)) {} + type(char(t)), my_val(e) {} + // constructor for pointer parameter + tag_matching_port_operation(const T* p, op_type t) : + type(char(t)), my_arg(const_cast(p)) {} + // constructor with no parameter + tag_matching_port_operation(op_type t) : type(char(t)) {} + }; + + typedef internal::aggregating_functor my_handler; + friend class internal::aggregating_functor; + aggregator my_aggregator; + + void handle_operations(tag_matching_port_operation* op_list) { + tag_matching_port_operation *current; + while(op_list) { + current = op_list; + op_list = op_list->next; + switch(current->type) { + case try__put: { + bool was_inserted = this->tagged_insert(current->my_tag_value, current->my_val); + // return failure if a duplicate insertion occurs + __TBB_store_with_release(current->status, was_inserted ? SUCCEEDED : FAILED); + } + break; + case get__item: + // use current_tag from FE for item + if(!this->tagged_find(my_join->current_tag, *(current->my_arg))) { + __TBB_ASSERT(false, "Failed to find item corresponding to current_tag."); + } + __TBB_store_with_release(current->status, SUCCEEDED); + break; + case res_port: + // use current_tag from FE for item + this->tagged_delete(my_join->current_tag); + __TBB_store_with_release(current->status, SUCCEEDED); + break; + } + } + } +// ------------ End Aggregator --------------- + public: + + tag_matching_port() : receiver(), tagged_buffer() { + my_join = NULL; + my_tag_func = NULL; + my_original_tag_func = NULL; + my_aggregator.initialize_handler(my_handler(this)); + } + + // copy constructor + tag_matching_port(const tag_matching_port& /*other*/) : receiver(), tagged_buffer() { + my_join = NULL; + // setting the tag methods is done in the copy-constructor for the front-end. + my_tag_func = NULL; + my_original_tag_func = NULL; + my_aggregator.initialize_handler(my_handler(this)); + } + + ~tag_matching_port() { + if (my_tag_func) delete my_tag_func; + if (my_original_tag_func) delete my_original_tag_func; + } + + void set_join_node_pointer(forwarding_base *join) { + my_join = join; + } + + void set_my_original_tag_func(my_tag_func_type *f) { + my_original_tag_func = f; + } + + void set_my_tag_func(my_tag_func_type *f) { + my_tag_func = f; + } + + /*override*/bool try_put(const T& v) { + tag_matching_port_operation op_data(v, try__put); + op_data.my_tag_value = (*my_tag_func)(v); + my_aggregator.execute(&op_data); + if(op_data.status == SUCCEEDED) { + // the assertion in the aggregator above will ensure we do not call with the same + // tag twice. We have to exit the aggregator to keep lock-ups from happening; + // the increment of the tag hash table in the FE is under a separate aggregator, + // so that is serialized. + // is a race possible? I do not believe so; the increment may cause a build of + // an output tuple, but its component is already in the hash table for the port. + my_join->increment_tag_count(op_data.my_tag_value); // may spawn + + } + return op_data.status == SUCCEEDED; + } + + + bool get_item( T &v ) { + tag_matching_port_operation op_data(&v, get__item); + my_aggregator.execute(&op_data); + return op_data.status == SUCCEEDED; + } + + // reset_port is called when item is accepted by successor, but + // is initiated by join_node. + void reset_port() { + tag_matching_port_operation op_data(res_port); + my_aggregator.execute(&op_data); + return; + } + + my_tag_func_type *my_func() { return my_tag_func; } + my_tag_func_type *my_original_func() { return my_original_tag_func; } + + private: + // need map of tags to values + forwarding_base *my_join; + my_tag_func_type *my_tag_func; + my_tag_func_type *my_original_tag_func; + }; // tag_matching_port + + using namespace graph_policy_namespace; + + template + class join_node_base; + + //! join_node_FE : implements input port policy + template + class join_node_FE; + + template + class join_node_FE : public forwarding_base { + public: + static const int N = std::tuple_size::value; + typedef OutputTuple output_type; + typedef InputTuple input_type; + typedef join_node_base my_node_type; // for forwarding + + join_node_FE(graph &g) : forwarding_base(g.root_task()), my_node(NULL) { + ports_with_no_inputs = N; + join_helper::set_join_node_pointer(my_inputs, this); + } + + join_node_FE(const join_node_FE& other) : forwarding_base(other.my_root_task), my_node(NULL) { + ports_with_no_inputs = N; + join_helper::set_join_node_pointer(my_inputs, this); + } + + void set_my_node(my_node_type *new_my_node) { my_node = new_my_node; } + + void increment_port_count() { + ++ports_with_no_inputs; + } + + // if all input_ports have predecessors, spawn forward to try and consume tuples + void decrement_port_count() { + if(ports_with_no_inputs.fetch_and_decrement() == 1) { + task::enqueue( * new ( task::allocate_additional_child_of( *(this->my_root_task) ) ) + forward_task(*my_node) ); + } + } + + input_type &input_ports() { return my_inputs; } + protected: + // all methods on input ports should be called under mutual exclusion from join_node_base. + + bool tuple_build_may_succeed() { + return !ports_with_no_inputs; + } + + bool try_to_make_tuple(output_type &out) { + if(ports_with_no_inputs) return false; + return join_helper::reserve(my_inputs, out); + } + + void tuple_accepted() { + join_helper::consume_reservations(my_inputs); + } + void tuple_rejected() { + join_helper::release_reservations(my_inputs); + } + + input_type my_inputs; + my_node_type *my_node; + atomic ports_with_no_inputs; + }; + + template + class join_node_FE : public forwarding_base { + public: + static const int N = std::tuple_size::value; + typedef OutputTuple output_type; + typedef InputTuple input_type; + typedef join_node_base my_node_type; // for forwarding + + join_node_FE(graph &g) : forwarding_base(g.root_task()), my_node(NULL) { + ports_with_no_items = N; + join_helper::set_join_node_pointer(my_inputs, this); + } + + join_node_FE(const join_node_FE& other) : forwarding_base(other.my_root_task), my_node(NULL) { + ports_with_no_items = N; + join_helper::set_join_node_pointer(my_inputs, this); + } + + // needed for forwarding + void set_my_node(my_node_type *new_my_node) { my_node = new_my_node; } + + void reset_port_count() { + ports_with_no_items = N; + } + + // if all input_ports have items, spawn forward to try and consume tuples + void decrement_port_count() { + if(ports_with_no_items.fetch_and_decrement() == 1) { + task::enqueue( * new ( task::allocate_additional_child_of( *(this->my_root_task) ) ) + forward_task(*my_node) ); + } + } + + void increment_port_count() { __TBB_ASSERT(false, NULL); } // should never be called + + input_type &input_ports() { return my_inputs; } + protected: + // all methods on input ports should be called under mutual exclusion from join_node_base. + + bool tuple_build_may_succeed() { + return !ports_with_no_items; + } + + bool try_to_make_tuple(output_type &out) { + if(ports_with_no_items) return false; + return join_helper::get_items(my_inputs, out); + } + + void tuple_accepted() { + reset_port_count(); + join_helper::reset_ports(my_inputs); + } + void tuple_rejected() { + // nothing to do. + } + + input_type my_inputs; + my_node_type *my_node; + atomic ports_with_no_items; + }; + + // tag_matching join input port. + template + class join_node_FE : public forwarding_base, + public tagged_buffer, public item_buffer { + public: + static const int N = std::tuple_size::value; + typedef OutputTuple output_type; + typedef InputTuple input_type; + typedef tagged_buffer my_tag_buffer; + typedef item_buffer output_buffer_type; + typedef join_node_base my_node_type; // for forwarding + +// ----------- Aggregator ------------ + // the aggregator is only needed to serialize the access to the hash table. + // and the output_buffer_type base class + private: + enum op_type { res_count, inc_count, may_succeed, try_make }; + enum op_stat {WAIT=0, SUCCEEDED, FAILED}; + typedef join_node_FE my_class; + + class tag_matching_FE_operation : public aggregated_operation { + public: + char type; + union { + tag_value my_val; + output_type* my_output; + }; + // constructor for value parameter + tag_matching_FE_operation(const tag_value& e, op_type t) : + // type(char(t)), my_val(const_cast(e)) {} + type(char(t)), my_val(e) {} + tag_matching_FE_operation(output_type *p, op_type t) : + type(char(t)), my_output(p) {} + // constructor with no parameter + tag_matching_FE_operation(op_type t) : type(char(t)) {} + }; + + typedef internal::aggregating_functor my_handler; + friend class internal::aggregating_functor; + aggregator my_aggregator; + + // called from aggregator, so serialized + void fill_output_buffer(bool should_enqueue) { + output_type l_out; + bool do_fwd = should_enqueue && this->buffer_empty(); + while(find_value_tag(this->current_tag,N)) { + this->tagged_delete(this->current_tag); + if(join_helper::get_items(my_inputs, l_out)) { // <== call back + this->push_back(l_out); + if(do_fwd) { + task::enqueue( * new ( task::allocate_additional_child_of( *(this->my_root_task) ) ) + forward_task(*my_node) ); + do_fwd = false; + } + // retire the input values + join_helper::reset_ports(my_inputs); // <== call back + this->current_tag = NO_TAG; + } + else { + __TBB_ASSERT(false, "should have had something to push"); + } + } + } + + void handle_operations(tag_matching_FE_operation* op_list) { + tag_matching_FE_operation *current; + while(op_list) { + current = op_list; + op_list = op_list->next; + switch(current->type) { + case res_count: // called from BE + { + output_type l_out; + this->pop_front(l_out); // don't care about returned value. + // buffer as many tuples as we can make + fill_output_buffer(true); + __TBB_store_with_release(current->status, SUCCEEDED); + } + break; + case inc_count: { // called from input ports + size_t *p = 0; + tag_value t = current->my_val; + if(!(this->tagged_find_ref(t,p))) { + this->tagged_insert(t, 0); + if(!(this->tagged_find_ref(t,p))) { + __TBB_ASSERT(false, NULL); + } + } + if(++(*p) == size_t(N)) { + task::enqueue( * new ( task::allocate_additional_child_of( *(this->my_root_task) ) ) + forward_task(*my_node) ); + } + } + __TBB_store_with_release(current->status, SUCCEEDED); + break; + case may_succeed: // called from BE + fill_output_buffer(false); + __TBB_store_with_release(current->status, this->buffer_empty() ? FAILED : SUCCEEDED); + break; + case try_make: // called from BE + if(this->buffer_empty()) { + __TBB_store_with_release(current->status, FAILED); + } + else { + this->fetch_front(*(current->my_output)); + __TBB_store_with_release(current->status, SUCCEEDED); + } + break; + } + } + } +// ------------ End Aggregator --------------- + + public: + template + join_node_FE(graph &g, FunctionTuple tag_funcs) : forwarding_base(g.root_task()), my_node(NULL) { + join_helper::set_join_node_pointer(my_inputs, this); + join_helper::set_tag_func(my_inputs, tag_funcs); + my_aggregator.initialize_handler(my_handler(this)); + } + + join_node_FE(const join_node_FE& other) : forwarding_base(other.my_root_task), my_tag_buffer(), + output_buffer_type() { + my_node = NULL; + join_helper::set_join_node_pointer(my_inputs, this); + join_helper::copy_tag_functors(my_inputs, const_cast(other.my_inputs)); + my_aggregator.initialize_handler(my_handler(this)); + } + + // needed for forwarding + void set_my_node(my_node_type *new_my_node) { my_node = new_my_node; } + + void reset_port_count() { // called from BE + tag_matching_FE_operation op_data(res_count); + my_aggregator.execute(&op_data); + return; + } + + // if all input_ports have items, spawn forward to try and consume tuples + void increment_tag_count(tag_value t) { // called from input_ports + tag_matching_FE_operation op_data(t, inc_count); + my_aggregator.execute(&op_data); + return; + } + + void decrement_port_count() { __TBB_ASSERT(false, NULL); } + + void increment_port_count() { __TBB_ASSERT(false, NULL); } // should never be called + + input_type &input_ports() { return my_inputs; } + protected: + // all methods on input ports should be called under mutual exclusion from join_node_base. + + bool tuple_build_may_succeed() { // called from back-end + tag_matching_FE_operation op_data(may_succeed); + my_aggregator.execute(&op_data); + return op_data.status == SUCCEEDED; + } + + // cannot lock while calling back to input_ports. current_tag will only be set + // and reset under the aggregator, so it will remain consistent. + bool try_to_make_tuple(output_type &out) { + tag_matching_FE_operation op_data(&out,try_make); + my_aggregator.execute(&op_data); + return op_data.status == SUCCEEDED; + } + + void tuple_accepted() { + reset_port_count(); // reset current_tag after ports reset. + } + + void tuple_rejected() { + // nothing to do. + } + + input_type my_inputs; // input ports + my_node_type *my_node; + }; // join_node_FE + + //! join_node_base + template + class join_node_base : public graph_node, public join_node_FE, + public sender { + using graph_node::my_graph; + public: + typedef OutputTuple output_type; + + typedef receiver successor_type; + typedef join_node_FE input_ports_type; + using input_ports_type::tuple_build_may_succeed; + using input_ports_type::try_to_make_tuple; + using input_ports_type::tuple_accepted; + using input_ports_type::tuple_rejected; + + private: + // ----------- Aggregator ------------ + enum op_type { reg_succ, rem_succ, try__get, do_fwrd }; + enum op_stat {WAIT=0, SUCCEEDED, FAILED}; + typedef join_node_base my_class; + + class join_node_base_operation : public aggregated_operation { + public: + char type; + union { + output_type *my_arg; + successor_type *my_succ; + }; + join_node_base_operation(const output_type& e, op_type t) : + type(char(t)), my_arg(const_cast(&e)) {} + join_node_base_operation(const successor_type &s, op_type t) : type(char(t)), + my_succ(const_cast(&s)) {} + join_node_base_operation(op_type t) : type(char(t)) {} + }; + + typedef internal::aggregating_functor my_handler; + friend class internal::aggregating_functor; + bool forwarder_busy; + aggregator my_aggregator; + + void handle_operations(join_node_base_operation* op_list) { + join_node_base_operation *current; + while(op_list) { + current = op_list; + op_list = op_list->next; + switch(current->type) { + case reg_succ: + my_successors.register_successor(*(current->my_succ)); + if(tuple_build_may_succeed() && !forwarder_busy) { + task::enqueue( * new ( task::allocate_additional_child_of(*(this->my_root_task)) ) + forward_task >(*this)); + forwarder_busy = true; + } + __TBB_store_with_release(current->status, SUCCEEDED); + break; + case rem_succ: + my_successors.remove_successor(*(current->my_succ)); + __TBB_store_with_release(current->status, SUCCEEDED); + break; + case try__get: + if(tuple_build_may_succeed()) { + if(try_to_make_tuple(*(current->my_arg))) { + tuple_accepted(); + __TBB_store_with_release(current->status, SUCCEEDED); + } + else __TBB_store_with_release(current->status, FAILED); + } + else __TBB_store_with_release(current->status, FAILED); + break; + case do_fwrd: { + bool build_succeeded; + output_type out; + if(tuple_build_may_succeed()) { + do { + build_succeeded = try_to_make_tuple(out); + if(build_succeeded) { + if(my_successors.try_put(out)) { + tuple_accepted(); + } + else { + tuple_rejected(); + build_succeeded = false; + } + } + } while(build_succeeded); + } + __TBB_store_with_release(current->status, SUCCEEDED); + forwarder_busy = false; + } + break; + } + } + } + // ---------- end aggregator ----------- + public: + join_node_base(graph &g) : graph_node(g), input_ports_type(g), forwarder_busy(false) { + my_successors.set_owner(this); + input_ports_type::set_my_node(this); + my_aggregator.initialize_handler(my_handler(this)); + } + + join_node_base(const join_node_base& other) : + graph_node(other.my_graph), input_ports_type(other), + sender(), forwarder_busy(false), my_successors() { + my_successors.set_owner(this); + input_ports_type::set_my_node(this); + my_aggregator.initialize_handler(my_handler(this)); + } + + template + join_node_base(graph &g, FunctionTuple f) : graph_node(g), input_ports_type(g, f), forwarder_busy(false) { + my_successors.set_owner(this); + input_ports_type::set_my_node(this); + my_aggregator.initialize_handler(my_handler(this)); + } + + bool register_successor(successor_type &r) { + join_node_base_operation op_data(r, reg_succ); + my_aggregator.execute(&op_data); + return op_data.status == SUCCEEDED; + } + + bool remove_successor( successor_type &r) { + join_node_base_operation op_data(r, rem_succ); + my_aggregator.execute(&op_data); + return op_data.status == SUCCEEDED; + } + + bool try_get( output_type &v) { + join_node_base_operation op_data(v, try__get); + my_aggregator.execute(&op_data); + return op_data.status == SUCCEEDED; + } + + private: + broadcast_cache my_successors; + + friend class forward_task< join_node_base >; + + void forward() { + join_node_base_operation op_data(do_fwrd); + my_aggregator.execute(&op_data); + } + }; + + // join base class type generator + template class PT, typename OutputTuple, graph_buffer_policy JP> + struct join_base { + typedef typename internal::join_node_base::type, OutputTuple> type; + }; + + //! unfolded_join_node : passes input_ports_type to join_node_base. We build the input port type + // using tuple_element. The class PT is the port type (reserving_port, queueing_port, tag_matching_port) + // and should match the graph_buffer_policy. + + template class PT, typename OutputTuple, graph_buffer_policy JP> + class unfolded_join_node : public join_base::type { + public: + typedef typename wrap_tuple_elements::type input_ports_type; + typedef OutputTuple output_type; + private: + typedef join_node_base base_type; + public: + unfolded_join_node(graph &g) : base_type(g) {} + unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} + }; + + // tag_matching unfolded_join_node. This must be a separate specialization because the constructors + // differ. + + template + class unfolded_join_node<2,tag_matching_port,OutputTuple,tag_matching> : public + join_base<2,tag_matching_port,OutputTuple,tag_matching>::type { + typedef typename std::tuple_element<0, OutputTuple>::type T0; + typedef typename std::tuple_element<1, OutputTuple>::type T1; + public: + typedef typename wrap_tuple_elements<2,tag_matching_port,OutputTuple>::type input_ports_type; + typedef OutputTuple output_type; + private: + typedef join_node_base base_type; + typedef typename internal::function_body *f0_p; + typedef typename internal::function_body *f1_p; + typedef typename std::tuple< f0_p, f1_p > func_initializer_type; + public: + template + unfolded_join_node(graph &g, B0 b0, B1 b1) : base_type(g, + func_initializer_type( + new internal::function_body_leaf(b0), + new internal::function_body_leaf(b1) + ) ) {} + unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} + }; + + template + class unfolded_join_node<3,tag_matching_port,OutputTuple,tag_matching> : public + join_base<3,tag_matching_port,OutputTuple,tag_matching>::type { + typedef typename std::tuple_element<0, OutputTuple>::type T0; + typedef typename std::tuple_element<1, OutputTuple>::type T1; + typedef typename std::tuple_element<2, OutputTuple>::type T2; + public: + typedef typename wrap_tuple_elements<3, tag_matching_port, OutputTuple>::type input_ports_type; + typedef OutputTuple output_type; + private: + typedef join_node_base base_type; + typedef typename internal::function_body *f0_p; + typedef typename internal::function_body *f1_p; + typedef typename internal::function_body *f2_p; + typedef typename std::tuple< f0_p, f1_p, f2_p > func_initializer_type; + public: + template + unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2) : base_type(g, + func_initializer_type( + new internal::function_body_leaf(b0), + new internal::function_body_leaf(b1), + new internal::function_body_leaf(b2) + ) ) {} + unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} + }; + + template + class unfolded_join_node<4,tag_matching_port,OutputTuple,tag_matching> : public + join_base<4,tag_matching_port,OutputTuple,tag_matching>::type { + typedef typename std::tuple_element<0, OutputTuple>::type T0; + typedef typename std::tuple_element<1, OutputTuple>::type T1; + typedef typename std::tuple_element<2, OutputTuple>::type T2; + typedef typename std::tuple_element<3, OutputTuple>::type T3; + public: + typedef typename wrap_tuple_elements<4, tag_matching_port, OutputTuple>::type input_ports_type; + typedef OutputTuple output_type; + private: + typedef join_node_base base_type; + typedef typename internal::function_body *f0_p; + typedef typename internal::function_body *f1_p; + typedef typename internal::function_body *f2_p; + typedef typename internal::function_body *f3_p; + typedef typename std::tuple< f0_p, f1_p, f2_p, f3_p > func_initializer_type; + public: + template + unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3) : base_type(g, + func_initializer_type( + new internal::function_body_leaf(b0), + new internal::function_body_leaf(b1), + new internal::function_body_leaf(b2), + new internal::function_body_leaf(b3) + ) ) {} + unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} + }; + + template + class unfolded_join_node<5,tag_matching_port,OutputTuple,tag_matching> : public + join_base<5,tag_matching_port,OutputTuple,tag_matching>::type { + typedef typename std::tuple_element<0, OutputTuple>::type T0; + typedef typename std::tuple_element<1, OutputTuple>::type T1; + typedef typename std::tuple_element<2, OutputTuple>::type T2; + typedef typename std::tuple_element<3, OutputTuple>::type T3; + typedef typename std::tuple_element<4, OutputTuple>::type T4; + public: + typedef typename wrap_tuple_elements<5, tag_matching_port, OutputTuple>::type input_ports_type; + typedef OutputTuple output_type; + private: + typedef join_node_base base_type; + typedef typename internal::function_body *f0_p; + typedef typename internal::function_body *f1_p; + typedef typename internal::function_body *f2_p; + typedef typename internal::function_body *f3_p; + typedef typename internal::function_body *f4_p; + typedef typename std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p > func_initializer_type; + public: + template + unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4) : base_type(g, + func_initializer_type( + new internal::function_body_leaf(b0), + new internal::function_body_leaf(b1), + new internal::function_body_leaf(b2), + new internal::function_body_leaf(b3), + new internal::function_body_leaf(b4) + ) ) {} + unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} + }; + +#if __TBB_VARIADIC_MAX >= 6 + template + class unfolded_join_node<6,tag_matching_port,OutputTuple,tag_matching> : public + join_base<6,tag_matching_port,OutputTuple,tag_matching>::type { + typedef typename std::tuple_element<0, OutputTuple>::type T0; + typedef typename std::tuple_element<1, OutputTuple>::type T1; + typedef typename std::tuple_element<2, OutputTuple>::type T2; + typedef typename std::tuple_element<3, OutputTuple>::type T3; + typedef typename std::tuple_element<4, OutputTuple>::type T4; + typedef typename std::tuple_element<5, OutputTuple>::type T5; + public: + typedef typename wrap_tuple_elements<6, tag_matching_port, OutputTuple>::type input_ports_type; + typedef OutputTuple output_type; + private: + typedef join_node_base base_type; + typedef typename internal::function_body *f0_p; + typedef typename internal::function_body *f1_p; + typedef typename internal::function_body *f2_p; + typedef typename internal::function_body *f3_p; + typedef typename internal::function_body *f4_p; + typedef typename internal::function_body *f5_p; + typedef typename std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p > func_initializer_type; + public: + template + unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5) : base_type(g, + func_initializer_type( + new internal::function_body_leaf(b0), + new internal::function_body_leaf(b1), + new internal::function_body_leaf(b2), + new internal::function_body_leaf(b3), + new internal::function_body_leaf(b4), + new internal::function_body_leaf(b5) + ) ) {} + unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} + }; +#endif + +#if __TBB_VARIADIC_MAX >= 7 + template + class unfolded_join_node<7,tag_matching_port,OutputTuple,tag_matching> : public + join_base<7,tag_matching_port,OutputTuple,tag_matching>::type { + typedef typename std::tuple_element<0, OutputTuple>::type T0; + typedef typename std::tuple_element<1, OutputTuple>::type T1; + typedef typename std::tuple_element<2, OutputTuple>::type T2; + typedef typename std::tuple_element<3, OutputTuple>::type T3; + typedef typename std::tuple_element<4, OutputTuple>::type T4; + typedef typename std::tuple_element<5, OutputTuple>::type T5; + typedef typename std::tuple_element<6, OutputTuple>::type T6; + public: + typedef typename wrap_tuple_elements<7, tag_matching_port, OutputTuple>::type input_ports_type; + typedef OutputTuple output_type; + private: + typedef join_node_base base_type; + typedef typename internal::function_body *f0_p; + typedef typename internal::function_body *f1_p; + typedef typename internal::function_body *f2_p; + typedef typename internal::function_body *f3_p; + typedef typename internal::function_body *f4_p; + typedef typename internal::function_body *f5_p; + typedef typename internal::function_body *f6_p; + typedef typename std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p, f6_p > func_initializer_type; + public: + template + unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5, B6 b6) : base_type(g, + func_initializer_type( + new internal::function_body_leaf(b0), + new internal::function_body_leaf(b1), + new internal::function_body_leaf(b2), + new internal::function_body_leaf(b3), + new internal::function_body_leaf(b4), + new internal::function_body_leaf(b5), + new internal::function_body_leaf(b6) + ) ) {} + unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} + }; +#endif + +#if __TBB_VARIADIC_MAX >= 8 + template + class unfolded_join_node<8,tag_matching_port,OutputTuple,tag_matching> : public + join_base<8,tag_matching_port,OutputTuple,tag_matching>::type { + typedef typename std::tuple_element<0, OutputTuple>::type T0; + typedef typename std::tuple_element<1, OutputTuple>::type T1; + typedef typename std::tuple_element<2, OutputTuple>::type T2; + typedef typename std::tuple_element<3, OutputTuple>::type T3; + typedef typename std::tuple_element<4, OutputTuple>::type T4; + typedef typename std::tuple_element<5, OutputTuple>::type T5; + typedef typename std::tuple_element<6, OutputTuple>::type T6; + typedef typename std::tuple_element<7, OutputTuple>::type T7; + public: + typedef typename wrap_tuple_elements<8, tag_matching_port, OutputTuple>::type input_ports_type; + typedef OutputTuple output_type; + private: + typedef join_node_base base_type; + typedef typename internal::function_body *f0_p; + typedef typename internal::function_body *f1_p; + typedef typename internal::function_body *f2_p; + typedef typename internal::function_body *f3_p; + typedef typename internal::function_body *f4_p; + typedef typename internal::function_body *f5_p; + typedef typename internal::function_body *f6_p; + typedef typename internal::function_body *f7_p; + typedef typename std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p, f6_p, f7_p > func_initializer_type; + public: + template + unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5, B6 b6, B7 b7) : base_type(g, + func_initializer_type( + new internal::function_body_leaf(b0), + new internal::function_body_leaf(b1), + new internal::function_body_leaf(b2), + new internal::function_body_leaf(b3), + new internal::function_body_leaf(b4), + new internal::function_body_leaf(b5), + new internal::function_body_leaf(b6), + new internal::function_body_leaf(b7) + ) ) {} + unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} + }; +#endif + +#if __TBB_VARIADIC_MAX >= 9 + template + class unfolded_join_node<9,tag_matching_port,OutputTuple,tag_matching> : public + join_base<9,tag_matching_port,OutputTuple,tag_matching>::type { + typedef typename std::tuple_element<0, OutputTuple>::type T0; + typedef typename std::tuple_element<1, OutputTuple>::type T1; + typedef typename std::tuple_element<2, OutputTuple>::type T2; + typedef typename std::tuple_element<3, OutputTuple>::type T3; + typedef typename std::tuple_element<4, OutputTuple>::type T4; + typedef typename std::tuple_element<5, OutputTuple>::type T5; + typedef typename std::tuple_element<6, OutputTuple>::type T6; + typedef typename std::tuple_element<7, OutputTuple>::type T7; + typedef typename std::tuple_element<8, OutputTuple>::type T8; + public: + typedef typename wrap_tuple_elements<9, tag_matching_port, OutputTuple>::type input_ports_type; + typedef OutputTuple output_type; + private: + typedef join_node_base base_type; + typedef typename internal::function_body *f0_p; + typedef typename internal::function_body *f1_p; + typedef typename internal::function_body *f2_p; + typedef typename internal::function_body *f3_p; + typedef typename internal::function_body *f4_p; + typedef typename internal::function_body *f5_p; + typedef typename internal::function_body *f6_p; + typedef typename internal::function_body *f7_p; + typedef typename internal::function_body *f8_p; + typedef typename std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p, f6_p, f7_p, f8_p > func_initializer_type; + public: + template + unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5, B6 b6, B7 b7, B8 b8) : base_type(g, + func_initializer_type( + new internal::function_body_leaf(b0), + new internal::function_body_leaf(b1), + new internal::function_body_leaf(b2), + new internal::function_body_leaf(b3), + new internal::function_body_leaf(b4), + new internal::function_body_leaf(b5), + new internal::function_body_leaf(b6), + new internal::function_body_leaf(b7), + new internal::function_body_leaf(b8) + ) ) {} + unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} + }; +#endif + +#if __TBB_VARIADIC_MAX >= 10 + template + class unfolded_join_node<10,tag_matching_port,OutputTuple,tag_matching> : public + join_base<10,tag_matching_port,OutputTuple,tag_matching>::type { + typedef typename std::tuple_element<0, OutputTuple>::type T0; + typedef typename std::tuple_element<1, OutputTuple>::type T1; + typedef typename std::tuple_element<2, OutputTuple>::type T2; + typedef typename std::tuple_element<3, OutputTuple>::type T3; + typedef typename std::tuple_element<4, OutputTuple>::type T4; + typedef typename std::tuple_element<5, OutputTuple>::type T5; + typedef typename std::tuple_element<6, OutputTuple>::type T6; + typedef typename std::tuple_element<7, OutputTuple>::type T7; + typedef typename std::tuple_element<8, OutputTuple>::type T8; + typedef typename std::tuple_element<9, OutputTuple>::type T9; + public: + typedef typename wrap_tuple_elements<10, tag_matching_port, OutputTuple>::type input_ports_type; + typedef OutputTuple output_type; + private: + typedef join_node_base base_type; + typedef typename internal::function_body *f0_p; + typedef typename internal::function_body *f1_p; + typedef typename internal::function_body *f2_p; + typedef typename internal::function_body *f3_p; + typedef typename internal::function_body *f4_p; + typedef typename internal::function_body *f5_p; + typedef typename internal::function_body *f6_p; + typedef typename internal::function_body *f7_p; + typedef typename internal::function_body *f8_p; + typedef typename internal::function_body *f9_p; + typedef typename std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p, f6_p, f7_p, f8_p, f9_p > func_initializer_type; + public: + template + unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5, B6 b6, B7 b7, B8 b8, B9 b9) : base_type(g, + func_initializer_type( + new internal::function_body_leaf(b0), + new internal::function_body_leaf(b1), + new internal::function_body_leaf(b2), + new internal::function_body_leaf(b3), + new internal::function_body_leaf(b4), + new internal::function_body_leaf(b5), + new internal::function_body_leaf(b6), + new internal::function_body_leaf(b7), + new internal::function_body_leaf(b8), + new internal::function_body_leaf(b9) + ) ) {} + unfolded_join_node(const unfolded_join_node &other) : base_type(other) {} + }; +#endif + + //! templated function to refer to input ports of the join node + template + typename std::tuple_element::type &input_port(JNT &jn) { + return std::get(jn.input_ports()); + } + +} +#endif // __TBB__flow_graph_join_impl_H + diff --git a/src/tbb/include/tbb/internal/_flow_graph_node_impl.h b/src/tbb/include/tbb/internal/_flow_graph_node_impl.h new file mode 100644 index 0000000..781454f --- /dev/null +++ b/src/tbb/include/tbb/internal/_flow_graph_node_impl.h @@ -0,0 +1,470 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB__flow_graph_node_impl_H +#define __TBB__flow_graph_node_impl_H + +#ifndef __TBB_flow_graph_H +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + +#include "_flow_graph_item_buffer_impl.h" + +//! @cond INTERNAL +namespace internal { + + using tbb::internal::aggregated_operation; + using tbb::internal::aggregating_functor; + using tbb::internal::aggregator; + + template< typename T, typename A > + class function_input_queue : public item_buffer { + public: + bool pop( T& t ) { + return this->pop_front( t ); + } + + bool push( T& t ) { + return this->push_back( t ); + } + }; + + //! Input and scheduling for a function node that takes a type Input as input + // The only up-ref is apply_body_impl, which should implement the function + // call and any handling of the result. + template< typename Input, typename A, typename ImplType > + class function_input_base : public receiver, tbb::internal::no_assign { + typedef sender predecessor_type; + enum op_stat {WAIT=0, SUCCEEDED, FAILED}; + enum op_type {reg_pred, rem_pred, app_body, tryput, try_fwd}; + typedef function_input_base my_class; + + public: + + //! The input type of this receiver + typedef Input input_type; + + //! Constructor for function_input_base + function_input_base( graph &g, size_t max_concurrency, function_input_queue *q = NULL ) + : my_root_task(g.root_task()), my_max_concurrency(max_concurrency), my_concurrency(0), + my_queue(q), forwarder_busy(false) { + my_predecessors.set_owner(this); + my_aggregator.initialize_handler(my_handler(this)); + } + + //! Copy constructor + function_input_base( const function_input_base& src, function_input_queue *q = NULL ) : + receiver(), tbb::internal::no_assign(), + my_root_task( src.my_root_task), my_max_concurrency(src.my_max_concurrency), + my_concurrency(0), my_queue(q), forwarder_busy(false) + { + my_predecessors.set_owner(this); + my_aggregator.initialize_handler(my_handler(this)); + } + + //! Destructor + virtual ~function_input_base() { + if ( my_queue ) delete my_queue; + } + + //! Put to the node + virtual bool try_put( const input_type &t ) { + if ( my_max_concurrency == 0 ) { + spawn_body_task( t ); + return true; + } else { + my_operation op_data(t, tryput); + my_aggregator.execute(&op_data); + return op_data.status == SUCCEEDED; + } + } + + //! Adds src to the list of cached predecessors. + /* override */ bool register_predecessor( predecessor_type &src ) { + my_operation op_data(reg_pred); + op_data.r = &src; + my_aggregator.execute(&op_data); + return true; + } + + //! Removes src from the list of cached predecessors. + /* override */ bool remove_predecessor( predecessor_type &src ) { + my_operation op_data(rem_pred); + op_data.r = &src; + my_aggregator.execute(&op_data); + return true; + } + + protected: + + task *my_root_task; + const size_t my_max_concurrency; + size_t my_concurrency; + function_input_queue *my_queue; + predecessor_cache my_predecessors; + + private: + + friend class apply_body_task< my_class, input_type >; + friend class forward_task< my_class >; + + class my_operation : public aggregated_operation< my_operation > { + public: + char type; + union { + input_type *elem; + predecessor_type *r; + }; + my_operation(const input_type& e, op_type t) : + type(char(t)), elem(const_cast(&e)) {} + my_operation(op_type t) : type(char(t)), r(NULL) {} + }; + + bool forwarder_busy; + typedef internal::aggregating_functor my_handler; + friend class internal::aggregating_functor; + aggregator< my_handler, my_operation > my_aggregator; + + void handle_operations(my_operation *op_list) { + my_operation *tmp; + while (op_list) { + tmp = op_list; + op_list = op_list->next; + switch (tmp->type) { + case reg_pred: + my_predecessors.add(*(tmp->r)); + __TBB_store_with_release(tmp->status, SUCCEEDED); + if (!forwarder_busy) { + forwarder_busy = true; + spawn_forward_task(); + } + break; + case rem_pred: + my_predecessors.remove(*(tmp->r)); + __TBB_store_with_release(tmp->status, SUCCEEDED); + break; + case app_body: + __TBB_ASSERT(my_max_concurrency != 0, NULL); + --my_concurrency; + __TBB_store_with_release(tmp->status, SUCCEEDED); + if (my_concurrencypop(i); + else + item_was_retrieved = my_predecessors.get_item(i); + if (item_was_retrieved) { + ++my_concurrency; + spawn_body_task(i); + } + } + break; + case tryput: internal_try_put(tmp); break; + case try_fwd: internal_forward(tmp); break; + } + } + } + + //! Put to the node + void internal_try_put(my_operation *op) { + __TBB_ASSERT(my_max_concurrency != 0, NULL); + if (my_concurrency < my_max_concurrency) { + ++my_concurrency; + spawn_body_task(*(op->elem)); + __TBB_store_with_release(op->status, SUCCEEDED); + } else if ( my_queue && my_queue->push(*(op->elem)) ) { + __TBB_store_with_release(op->status, SUCCEEDED); + } else { + __TBB_store_with_release(op->status, FAILED); + } + } + + //! Tries to spawn bodies if available and if concurrency allows + void internal_forward(my_operation *op) { + if (my_concurrencypop(i); + else + item_was_retrieved = my_predecessors.get_item(i); + if (item_was_retrieved) { + ++my_concurrency; + __TBB_store_with_release(op->status, SUCCEEDED); + spawn_body_task(i); + return; + } + } + __TBB_store_with_release(op->status, FAILED); + forwarder_busy = false; + } + + //! Applies the body to the provided input + void apply_body( input_type &i ) { + static_cast(this)->apply_body_impl(i); + if ( my_max_concurrency != 0 ) { + my_operation op_data(app_body); + my_aggregator.execute(&op_data); + } + } + + //! Spawns a task that calls apply_body( input ) + inline void spawn_body_task( const input_type &input ) { + task::enqueue(*new(task::allocate_additional_child_of(*my_root_task)) apply_body_task< my_class, input_type >(*this, input)); + } + + //! This is executed by an enqueued task, the "forwarder" + void forward() { + my_operation op_data(try_fwd); + do { + op_data.status = WAIT; + my_aggregator.execute(&op_data); + } while (op_data.status == SUCCEEDED); + } + + //! Spawns a task that calls forward() + inline void spawn_forward_task() { + task::enqueue(*new(task::allocate_additional_child_of(*my_root_task)) forward_task< my_class >(*this)); + } + }; // function_input_base + + //! Implements methods for a function node that takes a type Input as input and sends + // a type Output to its successors. + template< typename Input, typename Output, typename A> + class function_input : public function_input_base > { + public: + typedef Input input_type; + typedef Output output_type; + typedef function_input my_class; + typedef function_input_base base_type; + typedef function_input_queue input_queue_type; + + + // constructor + template + function_input( graph &g, size_t max_concurrency, Body& body, function_input_queue *q = NULL ) : + base_type(g, max_concurrency, q), + my_body( new internal::function_body_leaf< input_type, output_type, Body>(body) ) { + } + + //! Copy constructor + function_input( const function_input& src, input_queue_type *q = NULL ) : + base_type(src, q), + my_body( src.my_body->clone() ) { + } + + ~function_input() { + delete my_body; + } + + template< typename Body > + Body copy_function_object() { + internal::function_body &body_ref = *this->my_body; + return dynamic_cast< internal::function_body_leaf & >(body_ref).get_body(); + } + + void apply_body_impl( const input_type &i) { + successors().try_put( (*my_body)(i) ); + } + + protected: + function_body *my_body; + virtual broadcast_cache &successors() = 0; + + }; + + //! Implements methods for a function node that takes a type Input as input + // and has a tuple of output ports specified. + template< typename Input, typename OutputPortSet, typename A> + class multifunction_input : public function_input_base > { + public: + typedef Input input_type; + typedef OutputPortSet output_ports_type; + typedef multifunction_input my_class; + typedef function_input_base base_type; + typedef function_input_queue input_queue_type; + + + // constructor + template + multifunction_input( + graph &g, + size_t max_concurrency, + Body& body, + function_input_queue *q = NULL ) : + base_type(g, max_concurrency, q), + my_body( new internal::multifunction_body_leaf(body) ) { + } + + //! Copy constructor + multifunction_input( const multifunction_input& src, input_queue_type *q = NULL ) : + base_type(src, q), + my_body( src.my_body->clone() ) { + } + + ~multifunction_input() { + delete my_body; + } + + template< typename Body > + Body copy_function_object() { + internal::multifunction_body &body_ref = *this->my_body; + return dynamic_cast< internal::multifunction_body_leaf & >(body_ref).get_body(); + } + + void apply_body_impl( const input_type &i) { + (*my_body)(i, my_output_ports); + } + + output_ports_type &output_ports(){ return my_output_ports; } + + protected: + multifunction_body *my_body; + output_ports_type my_output_ports; + + }; + + // template to refer to an output port of a multifunction_node + template + typename std::tuple_element::type &output_port(MOP &op) { + return std::get(op.output_ports()); + } + +// helper structs for split_node + template + struct emit_element { + template + static void emit_this(const T &t, P &p) { + (void)std::get(p).try_put(std::get(t)); + emit_element::emit_this(t,p); + } + }; + + template<> + struct emit_element<1> { + template + static void emit_this(const T &t, P &p) { + (void)std::get<0>(p).try_put(std::get<0>(t)); + } + }; + + //! Implements methods for an executable node that takes continue_msg as input + template< typename Output > + class continue_input : public continue_receiver { + public: + + //! The input type of this receiver + typedef continue_msg input_type; + + //! The output type of this receiver + typedef Output output_type; + + template< typename Body > + continue_input( graph &g, Body& body ) + : my_root_task(g.root_task()), + my_body( new internal::function_body_leaf< input_type, output_type, Body>(body) ) { } + + template< typename Body > + continue_input( graph &g, int number_of_predecessors, Body& body ) + : continue_receiver( number_of_predecessors ), my_root_task(g.root_task()), + my_body( new internal::function_body_leaf< input_type, output_type, Body>(body) ) { } + + continue_input( const continue_input& src ) : continue_receiver(src), + my_root_task(src.my_root_task), my_body( src.my_body->clone() ) {} + + template< typename Body > + Body copy_function_object() { + internal::function_body &body_ref = *my_body; + return dynamic_cast< internal::function_body_leaf & >(body_ref).get_body(); + } + + protected: + + task *my_root_task; + function_body *my_body; + + virtual broadcast_cache &successors() = 0; + + friend class apply_body_task< continue_input< Output >, continue_msg >; + + //! Applies the body to the provided input + /* override */ void apply_body( input_type ) { + successors().try_put( (*my_body)( continue_msg() ) ); + } + + //! Spawns a task that applies the body + /* override */ void execute( ) { + task::enqueue( * new ( task::allocate_additional_child_of( *my_root_task ) ) + apply_body_task< continue_input< Output >, continue_msg >( *this, continue_msg() ) ); + } + + }; + + //! Implements methods for both executable and function nodes that puts Output to its successors + template< typename Output > + class function_output : public sender { + public: + + typedef Output output_type; + + function_output() { my_successors.set_owner(this); } + function_output(const function_output & /*other*/) : sender() { + my_successors.set_owner(this); + } + + //! Adds a new successor to this node + /* override */ bool register_successor( receiver &r ) { + successors().register_successor( r ); + return true; + } + + //! Removes a successor from this node + /* override */ bool remove_successor( receiver &r ) { + successors().remove_successor( r ); + return true; + } + + // for multifunction_node. The function_body that implements + // the node will have an input and an output tuple of ports. To put + // an item to a successor, the body should + // + // get(output_ports).try_put(output_value); + // + // return value will be bool returned from successors.try_put. + bool try_put(const output_type &i) { return my_successors.try_put(i); } + + protected: + broadcast_cache my_successors; + broadcast_cache &successors() { return my_successors; } + + }; + +} // internal + +#endif // __TBB__flow_graph_node_impl_H diff --git a/src/tbb/include/tbb/internal/_flow_graph_or_impl.h b/src/tbb/include/tbb/internal/_flow_graph_or_impl.h new file mode 100644 index 0000000..262c27e --- /dev/null +++ b/src/tbb/include/tbb/internal/_flow_graph_or_impl.h @@ -0,0 +1,270 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB__flow_graph_or_impl_H +#define __TBB__flow_graph_or_impl_H + +#ifndef __TBB_flow_graph_H +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + +#if TBB_PREVIEW_GRAPH_NODES +#include "tbb/internal/_flow_graph_types_impl.h" + +namespace internal { + + // Output of the or_node is a struct containing a std::tuple, and will be of + // the form + // + // struct { + // size_t indx; + // tuple_types result; + // }; + // + // where the value of indx will indicate which result was put to the + // successor. So if oval is the output to the successor, indx == 0 + // means std::get<0>(oval.result) is the output, and so on. + // + // tuple_types is the tuple that specified the possible outputs (and + // the corresponding inputs to the or_node.) + // + // the types of each element are represented by tuple_types, a typedef + // in the or_node. So the 2nd type in the union that is the + // output type for an or_node OrType is + // + // std::tuple_element<1,OrType::tuple_types>::type + + // the struct has an OutputTuple default constructed, with element index assigned + // the actual output value. + template + struct or_output_type { + typedef OutputTuple tuple_types; + typedef struct { + size_t indx; + OutputTuple result; + } type; + }; + + template + struct or_item_helper { + template + static inline void create_output_value(OutputType &o, void *v) { + o.indx = N; + std::get(o.result) = *(reinterpret_cast::type *>(v)); + } + }; + + template + struct or_helper { + template + static inline void create_output(OutputType &o, size_t i, void* v) { + if(i == N-1) { + or_item_helper::create_output_value(o,v); + } + else + or_helper::create_output(o,i,v); + } + template + static inline void set_or_node_pointer(PortTuple &my_input, PutBase *p) { + std::get(my_input).set_up(p, N-1); + or_helper::set_or_node_pointer(my_input, p); + } + }; + + template + struct or_helper { + template + static inline void create_output(OutputType &o, size_t i, void* v) { + if(i == 0) { + or_item_helper::create_output_value(o,v); + } + } + template + static inline void set_or_node_pointer(PortTuple &my_input, PutBase *p) { + std::get<0>(my_input).set_up(p, 0); + } + }; + + struct put_base { + virtual bool try_put_with_index(size_t index, void *v) = 0; + virtual ~put_base() { } + }; + + template + class or_input_port : public receiver { + private: + size_t my_index; + put_base *my_or_node; + public: + void set_up(put_base *p, size_t i) { my_index = i; my_or_node = p; } + bool try_put(const T &v) { + return my_or_node->try_put_with_index(my_index, reinterpret_cast(const_cast(&v))); + } + }; + + template + class or_node_FE : public put_base { + public: + static const int N = std::tuple_size::value; + typedef OutputType output_type; + typedef InputTuple input_type; + + or_node_FE( ) { + or_helper::set_or_node_pointer(my_inputs, this); + } + + input_type &input_ports() { return my_inputs; } + protected: + input_type my_inputs; + }; + + //! or_node_base + template + class or_node_base : public graph_node, public or_node_FE, + public sender { + using graph_node::my_graph; + public: + static const size_t N = std::tuple_size::value; + typedef OutputType output_type; + typedef StructTypes tuple_types; + typedef receiver successor_type; + typedef or_node_FE input_ports_type; + + private: + // ----------- Aggregator ------------ + enum op_type { reg_succ, rem_succ, try__put }; + enum op_stat {WAIT=0, SUCCEEDED, FAILED}; + typedef or_node_base my_class; + + class or_node_base_operation : public aggregated_operation { + public: + char type; + size_t indx; + union { + void *my_arg; + successor_type *my_succ; + }; + or_node_base_operation(size_t i, const void* e, op_type t) : + type(char(t)), indx(i), my_arg(const_cast(e)) {} + or_node_base_operation(const successor_type &s, op_type t) : type(char(t)), + my_succ(const_cast(&s)) {} + or_node_base_operation(op_type t) : type(char(t)) {} + }; + + typedef internal::aggregating_functor my_handler; + friend class internal::aggregating_functor; + aggregator my_aggregator; + + void handle_operations(or_node_base_operation* op_list) { + or_node_base_operation *current; + while(op_list) { + current = op_list; + op_list = op_list->next; + switch(current->type) { + + case reg_succ: + my_successors.register_successor(*(current->my_succ)); + __TBB_store_with_release(current->status, SUCCEEDED); + break; + + case rem_succ: + my_successors.remove_successor(*(current->my_succ)); + __TBB_store_with_release(current->status, SUCCEEDED); + break; + + case try__put: + output_type oval; + or_helper::create_output(oval,current->indx,current->my_arg); + bool res = my_successors.try_put(oval); + __TBB_store_with_release(current->status, res ? SUCCEEDED : FAILED); + break; + } + } + } + // ---------- end aggregator ----------- + public: + or_node_base(graph& g) : graph_node(g), input_ports_type() { + my_successors.set_owner(this); + my_aggregator.initialize_handler(my_handler(this)); + } + + or_node_base(const or_node_base& other) : graph_node(other.my_graph), input_ports_type(), sender() { + my_successors.set_owner(this); + my_aggregator.initialize_handler(my_handler(this)); + } + + bool register_successor(successor_type &r) { + or_node_base_operation op_data(r, reg_succ); + my_aggregator.execute(&op_data); + return op_data.status == SUCCEEDED; + } + + bool remove_successor( successor_type &r) { + or_node_base_operation op_data(r, rem_succ); + my_aggregator.execute(&op_data); + return op_data.status == SUCCEEDED; + } + + bool try_put_with_index(size_t indx, void *v) { + or_node_base_operation op_data(indx, v, try__put); + my_aggregator.execute(&op_data); + return op_data.status == SUCCEEDED; + } + + private: + broadcast_cache my_successors; + }; + + // type generators + template + struct or_types { + static const int N = std::tuple_size::value; + typedef typename wrap_tuple_elements::type input_ports_type; + typedef typename or_output_type::type output_type; + typedef internal::or_node_FE or_FE_type; + typedef internal::or_node_base or_base_type; + }; + + template + class unfolded_or_node : public or_types::or_base_type { + public: + typedef typename or_types::input_ports_type input_ports_type; + typedef OutputTuple tuple_types; + typedef typename or_types::output_type output_type; + private: + typedef typename or_types::or_base_type base_type; + public: + unfolded_or_node(graph& g) : base_type(g) {} + unfolded_or_node(const unfolded_or_node &other) : base_type(other) {} + }; + + +} /* namespace internal */ +#endif // TBB_PREVIEW_GRAPH_NODES + +#endif /* __TBB__flow_graph_or_impl_H */ diff --git a/src/tbb/include/tbb/internal/_flow_graph_tagged_buffer_impl.h b/src/tbb/include/tbb/internal/_flow_graph_tagged_buffer_impl.h new file mode 100644 index 0000000..b9d7acd --- /dev/null +++ b/src/tbb/include/tbb/internal/_flow_graph_tagged_buffer_impl.h @@ -0,0 +1,203 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// tagged buffer that can expand, and can support as many deletions as additions +// list-based, with elements of list held in std::vector (for destruction management), +// multiplicative hashing (like ets). No synchronization built-in. +// + +#ifndef __TBB__flow_graph_tagged_buffer_impl_H +#define __TBB__flow_graph_tagged_buffer_impl_H + +#ifndef __TBB_flow_graph_H +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + +template +struct buffer_element { + TagType t; + ValueType v; + buffer_element *next; + buffer_element() : t(NoTagMark), next(NULL) {} +}; + +template + < + typename TagType, + typename ValueType, + size_t NoTagMark = 0, + typename Allocator=tbb::cache_aligned_allocator< buffer_element > + > +class tagged_buffer { +public: + static const size_t INITIAL_SIZE = 8; // initial size of the hash pointer table + static const TagType NO_TAG = TagType(NoTagMark); + typedef ValueType value_type; + typedef buffer_element element_type; + typedef value_type *pointer_type; + typedef std::vector list_array_type; + typedef typename Allocator::template rebind::other pointer_array_allocator_type; + typedef typename Allocator::template rebind::other list_array_allocator; +private: + + size_t my_size; + size_t nelements; + element_type** array; + std::vector *lists; + element_type* free_list; + + size_t mask() { return my_size - 1; } + + static size_t hash(TagType t) { + return uintptr_t(t)*tbb::internal::size_t_select(0x9E3779B9,0x9E3779B97F4A7C15ULL); + } + + void set_up_free_list( element_type **p_free_list, list_array_type *la, size_t sz) { + for(size_t i=0; i < sz - 1; ++i ) { // construct free list + (*la)[i].next = &((*la)[i+1]); + (*la)[i].t = NO_TAG; + } + (*la)[sz-1].next = NULL; + *p_free_list = &((*la)[0]); + } + + void grow_array() { + // make the pointer array larger + element_type **new_array; + element_type **old_array = array; + size_t old_size = my_size; + my_size *=2; + new_array = pointer_array_allocator_type().allocate(my_size); + for(size_t i=0; i < my_size; ++i) new_array[i] = NULL; + list_array_type *new_list_array = new list_array_type(old_size, element_type(), Allocator()); + set_up_free_list(&free_list, new_list_array, old_size ); + + for(size_t i=0; i < old_size; ++i) { + for( element_type* op = old_array[i]; op; op = op->next) { + internal_tagged_insert(new_array, my_size, op->t, op->v); + } + } + pointer_array_allocator_type().deallocate(old_array, old_size); + + delete lists; // destroy and deallocate instead + array = new_array; + lists = new_list_array; + } + + void internal_tagged_insert( element_type **ar, size_t sz, TagType t, value_type v) { + size_t l_mask = sz-1; + size_t h = hash(t) & l_mask; + __TBB_ASSERT(free_list, "Error: free list not set up."); + element_type* my_elem = free_list; free_list = free_list->next; + my_elem->t = t; + my_elem->v = v; + my_elem->next = ar[h]; + ar[h] = my_elem; + } + +public: + tagged_buffer() : my_size(INITIAL_SIZE), nelements(0) { + array = pointer_array_allocator_type().allocate(my_size); + for(size_t i = 0; i < my_size; ++i) array[i] = NULL; + lists = new list_array_type(INITIAL_SIZE/2, element_type(), Allocator()); + set_up_free_list(&free_list, lists, INITIAL_SIZE/2); + } + + ~tagged_buffer() { + if(array) { + pointer_array_allocator_type().deallocate(array, my_size); + } + if(lists) { + delete lists; + } + } + + bool tagged_insert(TagType t, value_type v) { + pointer_type p; + if(tagged_find_ref(t, p)) { + *p = v; // replace the value + return false; + } + ++nelements; + if(nelements*2 > my_size) grow_array(); + internal_tagged_insert(array, my_size, t, v); + return true; + } + + // returns reference to array element.v + bool tagged_find_ref(TagType t, pointer_type &v) { + size_t i = hash(t) & mask(); + for(element_type* p = array[i]; p; p = p->next) { + if(p->t == t) { + v = &(p->v); + return true; + } + } + return false; + } + + bool tagged_find( TagType t, value_type &v) { + value_type *p; + if(tagged_find_ref(t, p)) { + v = *p; + return true; + } + else + return false; + } + + void tagged_delete(TagType t) { + size_t h = hash(t) & mask(); + element_type* prev = NULL; + for(element_type* p = array[h]; p; prev = p, p = p->next) { + if(p->t == t) { + p->t = NO_TAG; + if(prev) prev->next = p->next; + else array[h] = p->next; + p->next = free_list; + free_list = p; + --nelements; + return; + } + } + __TBB_ASSERT(false, "tag not found for delete"); + } + + // search for v in the array; if found {set t, return true} else return false + // we use this in join_node_FE to find if a tag's items are all available. + bool find_value_tag( TagType &t, value_type v) { + for(size_t i= 0; i < my_size / 2; ++i) { // remember the vector is half the size of the hash array + if( (*lists)[i].t != NO_TAG && (*lists)[i].v == v) { + t = (*lists)[i].t; + return true; + } + } + return false; + } +}; +#endif // __TBB__flow_graph_tagged_buffer_impl_H diff --git a/src/tbb/include/tbb/internal/_flow_graph_types_impl.h b/src/tbb/include/tbb/internal/_flow_graph_types_impl.h new file mode 100644 index 0000000..cedda32 --- /dev/null +++ b/src/tbb/include/tbb/internal/_flow_graph_types_impl.h @@ -0,0 +1,168 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB__flow_graph_types_impl_H +#define __TBB__flow_graph_types_impl_H + +#ifndef __TBB_flow_graph_H +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + +namespace internal { +// wrap each element of a tuple in a template, and make a tuple of the result. + + template class PT, typename TypeTuple> + struct wrap_tuple_elements; + + template class PT, typename TypeTuple> + struct wrap_tuple_elements<1, PT, TypeTuple> { + typedef typename std::tuple< + PT::type> > + type; + }; + + template class PT, typename TypeTuple> + struct wrap_tuple_elements<2, PT, TypeTuple> { + typedef typename std::tuple< + PT::type>, + PT::type> > + type; + }; + + template class PT, typename TypeTuple> + struct wrap_tuple_elements<3, PT, TypeTuple> { + typedef typename std::tuple< + PT::type>, + PT::type>, + PT::type> > + type; + }; + + template class PT, typename TypeTuple> + struct wrap_tuple_elements<4, PT, TypeTuple> { + typedef typename std::tuple< + PT::type>, + PT::type>, + PT::type>, + PT::type> > + type; + }; + + template class PT, typename TypeTuple> + struct wrap_tuple_elements<5, PT, TypeTuple> { + typedef typename std::tuple< + PT::type>, + PT::type>, + PT::type>, + PT::type>, + PT::type> > + type; + }; + +#if __TBB_VARIADIC_MAX >= 6 + template class PT, typename TypeTuple> + struct wrap_tuple_elements<6, PT, TypeTuple> { + typedef typename std::tuple< + PT::type>, + PT::type>, + PT::type>, + PT::type>, + PT::type>, + PT::type> > + type; + }; +#endif + +#if __TBB_VARIADIC_MAX >= 7 + template class PT, typename TypeTuple> + struct wrap_tuple_elements<7, PT, TypeTuple> { + typedef typename std::tuple< + PT::type>, + PT::type>, + PT::type>, + PT::type>, + PT::type>, + PT::type>, + PT::type> > + type; + }; +#endif + +#if __TBB_VARIADIC_MAX >= 8 + template class PT, typename TypeTuple> + struct wrap_tuple_elements<8, PT, TypeTuple> { + typedef typename std::tuple< + PT::type>, + PT::type>, + PT::type>, + PT::type>, + PT::type>, + PT::type>, + PT::type>, + PT::type> > + type; + }; +#endif + +#if __TBB_VARIADIC_MAX >= 9 + template class PT, typename TypeTuple> + struct wrap_tuple_elements<9, PT, TypeTuple> { + typedef typename std::tuple< + PT::type>, + PT::type>, + PT::type>, + PT::type>, + PT::type>, + PT::type>, + PT::type>, + PT::type>, + PT::type> > + type; + }; +#endif + +#if __TBB_VARIADIC_MAX >= 10 + template class PT, typename TypeTuple> + struct wrap_tuple_elements<10, PT, TypeTuple> { + typedef typename std::tuple< + PT::type>, + PT::type>, + PT::type>, + PT::type>, + PT::type>, + PT::type>, + PT::type>, + PT::type>, + PT::type>, + PT::type> > + type; + }; +#endif + +} // namespace internal +#endif /* __TBB__flow_graph_types_impl_H */ diff --git a/src/tbb/include/tbb/internal/_tbb_windef.h b/src/tbb/include/tbb/internal/_tbb_windef.h new file mode 100644 index 0000000..da0a587 --- /dev/null +++ b/src/tbb/include/tbb/internal/_tbb_windef.h @@ -0,0 +1,81 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_tbb_windef_H +#error Do not #include this internal file directly; use public TBB headers instead. +#endif /* __TBB_tbb_windef_H */ + +// Check that the target Windows version has all API calls requried for TBB. +// Do not increase the version in condition beyond 0x0500 without prior discussion! +#if defined(_WIN32_WINNT) && _WIN32_WINNT<0x0400 +#error TBB is unable to run on old Windows versions; _WIN32_WINNT must be 0x0400 or greater. +#endif + +#if !defined(_MT) +#error TBB requires linkage with multithreaded C/C++ runtime library. \ + Choose multithreaded DLL runtime in project settings, or use /MD[d] compiler switch. +#endif + +// Workaround for the problem with MVSC headers failing to define namespace std +namespace std { + using ::size_t; using ::ptrdiff_t; +} + +#define __TBB_STRING_AUX(x) #x +#define __TBB_STRING(x) __TBB_STRING_AUX(x) + +// Default setting of TBB_USE_DEBUG +#ifdef TBB_USE_DEBUG +# if TBB_USE_DEBUG +# if !defined(_DEBUG) +# pragma message(__FILE__ "(" __TBB_STRING(__LINE__) ") : Warning: Recommend using /MDd if compiling with TBB_USE_DEBUG!=0") +# endif +# else +# if defined(_DEBUG) +# pragma message(__FILE__ "(" __TBB_STRING(__LINE__) ") : Warning: Recommend using /MD if compiling with TBB_USE_DEBUG==0") +# endif +# endif +#endif + +#if (__TBB_BUILD || __TBBMALLOC_BUILD) && !defined(__TBB_NO_IMPLICIT_LINKAGE) +#define __TBB_NO_IMPLICIT_LINKAGE 1 +#endif + +#if _MSC_VER + #if !__TBB_NO_IMPLICIT_LINKAGE + #ifdef __TBB_LIB_NAME + #pragma comment(lib, __TBB_STRING(__TBB_LIB_NAME)) + #else + #ifdef _DEBUG + #pragma comment(lib, "tbb_debug.lib") + #else + #pragma comment(lib, "tbb.lib") + #endif + #endif + #endif +#endif diff --git a/src/tbb/include/tbb/machine/gcc_generic.h b/src/tbb/include/tbb/machine/gcc_generic.h new file mode 100644 index 0000000..e424283 --- /dev/null +++ b/src/tbb/include/tbb/machine/gcc_generic.h @@ -0,0 +1,124 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if !defined(__TBB_machine_H) || defined(__TBB_machine_gcc_generic_H) +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + +#define __TBB_machine_gcc_generic_H + +#include +#include + +#define __TBB_WORDSIZE __SIZEOF_POINTER__ + +#ifdef __BYTE_ORDER__ + #if __BYTE_ORDER__==__ORDER_BIG_ENDIAN__ + #define __TBB_BIG_ENDIAN 1 + #elif __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ + #define __TBB_BIG_ENDIAN 0 + #elif __BYTE_ORDER__==__ORDER_PDP_ENDIAN__ + #define __TBB_BIG_ENDIAN -1 // not currently supported + #endif +#endif + +/** As this generic implementation has absolutely no information about underlying + hardware, its performance most likely will be sub-optimal because of full memory + fence usages where a more lightweight synchronization means (or none at all) + could suffice. Thus if you use this header to enable TBB on a new platform, + consider forking it and relaxing below helpers as appropriate. **/ +#define __TBB_acquire_consistency_helper() __sync_synchronize() +#define __TBB_release_consistency_helper() __sync_synchronize() +#define __TBB_full_memory_fence() __sync_synchronize() +#define __TBB_control_consistency_helper() __sync_synchronize() + +#define __TBB_MACHINE_DEFINE_ATOMICS(S,T) \ +inline T __TBB_machine_cmpswp##S( volatile void *ptr, T value, T comparand ) { \ + return __sync_val_compare_and_swap(reinterpret_cast(ptr),comparand,value); \ +} \ + \ +inline T __TBB_machine_fetchadd##S( volatile void *ptr, T value ) { \ + return __sync_fetch_and_add(reinterpret_cast(ptr),value); \ +} \ + +__TBB_MACHINE_DEFINE_ATOMICS(1,int8_t) +__TBB_MACHINE_DEFINE_ATOMICS(2,int16_t) +__TBB_MACHINE_DEFINE_ATOMICS(4,int32_t) +__TBB_MACHINE_DEFINE_ATOMICS(8,int64_t) + +#undef __TBB_MACHINE_DEFINE_ATOMICS + +namespace tbb{ namespace internal { namespace gcc_builtins { + inline int clz(unsigned int x){ return __builtin_clz(x);}; + inline int clz(unsigned long int x){ return __builtin_clzl(x);}; + inline int clz(unsigned long long int x){ return __builtin_clzll(x);}; +}}} +//gcc __builtin_clz builtin count _number_ of leading zeroes +static inline intptr_t __TBB_machine_lg( uintptr_t x ) { + return sizeof(x)*8 - tbb::internal::gcc_builtins::clz(x) -1 ; +} + +static inline void __TBB_machine_or( volatile void *ptr, uintptr_t addend ) { + __sync_fetch_and_or(reinterpret_cast(ptr),addend); +} + +static inline void __TBB_machine_and( volatile void *ptr, uintptr_t addend ) { + __sync_fetch_and_and(reinterpret_cast(ptr),addend); +} + + +typedef unsigned char __TBB_Flag; + +typedef __TBB_atomic __TBB_Flag __TBB_atomic_flag; + +inline bool __TBB_machine_try_lock_byte( __TBB_atomic_flag &flag ) { + return __sync_lock_test_and_set(&flag,1)==0; +} + +inline void __TBB_machine_unlock_byte( __TBB_atomic_flag &flag , __TBB_Flag) { + __sync_lock_release(&flag); +} + +// Machine specific atomic operations +#define __TBB_AtomicOR(P,V) __TBB_machine_or(P,V) +#define __TBB_AtomicAND(P,V) __TBB_machine_and(P,V) + +#define __TBB_TryLockByte __TBB_machine_try_lock_byte +#define __TBB_UnlockByte __TBB_machine_unlock_byte + +// Definition of other functions +#define __TBB_Log2(V) __TBB_machine_lg(V) + +#define __TBB_USE_GENERIC_FETCH_STORE 1 +#define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1 +#define __TBB_USE_GENERIC_RELAXED_LOAD_STORE 1 +#define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1 + +#if __TBB_WORDSIZE==4 + #define __TBB_USE_GENERIC_DWORD_LOAD_STORE 1 +#endif diff --git a/src/tbb/include/tbb/machine/ibm_aix51.h b/src/tbb/include/tbb/machine/ibm_aix51.h new file mode 100644 index 0000000..4d880db --- /dev/null +++ b/src/tbb/include/tbb/machine/ibm_aix51.h @@ -0,0 +1,78 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// TODO: revise by comparing with mac_ppc.h + +#if !defined(__TBB_machine_H) || defined(__TBB_machine_ibm_aix51_H) +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + +#define __TBB_machine_ibm_aix51_H + +#define __TBB_WORDSIZE 8 +#define __TBB_BIG_ENDIAN 1 // assumption based on operating system + +#include +#include +#include + +extern "C" { +int32_t __TBB_machine_cas_32 (volatile void* ptr, int32_t value, int32_t comparand); +int64_t __TBB_machine_cas_64 (volatile void* ptr, int64_t value, int64_t comparand); +void __TBB_machine_flush (); +void __TBB_machine_lwsync (); +void __TBB_machine_isync (); +} + +// Mapping of old entry point names retained for the sake of backward binary compatibility +#define __TBB_machine_cmpswp4 __TBB_machine_cas_32 +#define __TBB_machine_cmpswp8 __TBB_machine_cas_64 + +#define __TBB_Yield() sched_yield() + +#define __TBB_USE_GENERIC_PART_WORD_CAS 1 +#define __TBB_USE_GENERIC_FETCH_ADD 1 +#define __TBB_USE_GENERIC_FETCH_STORE 1 +#define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1 +#define __TBB_USE_GENERIC_RELAXED_LOAD_STORE 1 +#define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1 + +#if __GNUC__ + #define __TBB_control_consistency_helper() __asm__ __volatile__( "isync": : :"memory") + #define __TBB_acquire_consistency_helper() __asm__ __volatile__("lwsync": : :"memory") + #define __TBB_release_consistency_helper() __asm__ __volatile__("lwsync": : :"memory") + #define __TBB_full_memory_fence() __asm__ __volatile__( "sync": : :"memory") +#else + // IBM C++ Compiler does not support inline assembly + // TODO: Since XL 9.0 or earlier GCC syntax is supported. Replace with more + // lightweight implementation (like in mac_ppc.h) + #define __TBB_control_consistency_helper() __TBB_machine_isync () + #define __TBB_acquire_consistency_helper() __TBB_machine_lwsync () + #define __TBB_release_consistency_helper() __TBB_machine_lwsync () + #define __TBB_full_memory_fence() __TBB_machine_flush () +#endif diff --git a/src/tbb/include/tbb/machine/linux_common.h b/src/tbb/include/tbb/machine/linux_common.h new file mode 100644 index 0000000..2eeffb9 --- /dev/null +++ b/src/tbb/include/tbb/machine/linux_common.h @@ -0,0 +1,91 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_machine_H +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + +#include +#define __TBB_Yield() sched_yield() + +/* Futex definitions */ +#include + +#if defined(SYS_futex) + +#define __TBB_USE_FUTEX 1 +#include +#include +// Unfortunately, some versions of Linux do not have a header that defines FUTEX_WAIT and FUTEX_WAKE. + +#ifdef FUTEX_WAIT +#define __TBB_FUTEX_WAIT FUTEX_WAIT +#else +#define __TBB_FUTEX_WAIT 0 +#endif + +#ifdef FUTEX_WAKE +#define __TBB_FUTEX_WAKE FUTEX_WAKE +#else +#define __TBB_FUTEX_WAKE 1 +#endif + +#ifndef __TBB_ASSERT +#error machine specific headers must be included after tbb_stddef.h +#endif + +namespace tbb { + +namespace internal { + +inline int futex_wait( void *futex, int comparand ) { + int r = ::syscall( SYS_futex,futex,__TBB_FUTEX_WAIT,comparand,NULL,NULL,0 ); +#if TBB_USE_ASSERT + int e = errno; + __TBB_ASSERT( r==0||r==EWOULDBLOCK||(r==-1&&(e==EAGAIN||e==EINTR)), "futex_wait failed." ); +#endif /* TBB_USE_ASSERT */ + return r; +} + +inline int futex_wakeup_one( void *futex ) { + int r = ::syscall( SYS_futex,futex,__TBB_FUTEX_WAKE,1,NULL,NULL,0 ); + __TBB_ASSERT( r==0||r==1, "futex_wakeup_one: more than one thread woken up?" ); + return r; +} + +inline int futex_wakeup_all( void *futex ) { + int r = ::syscall( SYS_futex,futex,__TBB_FUTEX_WAKE,INT_MAX,NULL,NULL,0 ); + __TBB_ASSERT( r>=0, "futex_wakeup_all: error in waking up threads" ); + return r; +} + +} /* namespace internal */ + +} /* namespace tbb */ + +#endif /* SYS_futex */ diff --git a/src/tbb/include/tbb/machine/linux_ia32.h b/src/tbb/include/tbb/machine/linux_ia32.h new file mode 100644 index 0000000..d243a74 --- /dev/null +++ b/src/tbb/include/tbb/machine/linux_ia32.h @@ -0,0 +1,252 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if !defined(__TBB_machine_H) || defined(__TBB_machine_linux_ia32_H) +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + +#define __TBB_machine_linux_ia32_H + +#include +#include + +#define __TBB_WORDSIZE 4 +#define __TBB_BIG_ENDIAN 0 + +#define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory") +#define __TBB_control_consistency_helper() __TBB_compiler_fence() +#define __TBB_acquire_consistency_helper() __TBB_compiler_fence() +#define __TBB_release_consistency_helper() __TBB_compiler_fence() +#define __TBB_full_memory_fence() __asm__ __volatile__("mfence": : :"memory") + +#if __TBB_ICC_ASM_VOLATILE_BROKEN +#define __TBB_VOLATILE +#else +#define __TBB_VOLATILE volatile +#endif + +#define __TBB_MACHINE_DEFINE_ATOMICS(S,T,X,R) \ +static inline T __TBB_machine_cmpswp##S (volatile void *ptr, T value, T comparand ) \ +{ \ + T result; \ + \ + __asm__ __volatile__("lock\ncmpxchg" X " %2,%1" \ + : "=a"(result), "=m"(*(__TBB_VOLATILE T*)ptr) \ + : "q"(value), "0"(comparand), "m"(*(__TBB_VOLATILE T*)ptr) \ + : "memory"); \ + return result; \ +} \ + \ +static inline T __TBB_machine_fetchadd##S(volatile void *ptr, T addend) \ +{ \ + T result; \ + __asm__ __volatile__("lock\nxadd" X " %0,%1" \ + : R (result), "=m"(*(__TBB_VOLATILE T*)ptr) \ + : "0"(addend), "m"(*(__TBB_VOLATILE T*)ptr) \ + : "memory"); \ + return result; \ +} \ + \ +static inline T __TBB_machine_fetchstore##S(volatile void *ptr, T value) \ +{ \ + T result; \ + __asm__ __volatile__("lock\nxchg" X " %0,%1" \ + : R (result), "=m"(*(__TBB_VOLATILE T*)ptr) \ + : "0"(value), "m"(*(__TBB_VOLATILE T*)ptr) \ + : "memory"); \ + return result; \ +} \ + +__TBB_MACHINE_DEFINE_ATOMICS(1,int8_t,"","=q") +__TBB_MACHINE_DEFINE_ATOMICS(2,int16_t,"","=r") +__TBB_MACHINE_DEFINE_ATOMICS(4,int32_t,"l","=r") + +#if __INTEL_COMPILER +#pragma warning( push ) +// reference to EBX in a function requiring stack alignment +#pragma warning( disable: 998 ) +#endif + +static inline int64_t __TBB_machine_cmpswp8 (volatile void *ptr, int64_t value, int64_t comparand ) { +#if __TBB_GCC_BUILTIN_ATOMICS_PRESENT + return __sync_val_compare_and_swap( reinterpret_cast(ptr), comparand, value ); +#else /* !__TBB_GCC_BUILTIN_ATOMICS_PRESENT */ + int64_t result; + union { + int64_t i64; + int32_t i32[2]; + }; + i64 = value; +#if __PIC__ + /* compiling position-independent code */ + // EBX register preserved for compliance with position-independent code rules on IA32 + int32_t tmp; + __asm__ __volatile__ ( + "movl %%ebx,%2\n\t" + "movl %5,%%ebx\n\t" +#if __GNUC__==3 + "lock\n\t cmpxchg8b %1\n\t" +#else + "lock\n\t cmpxchg8b (%3)\n\t" +#endif + "movl %2,%%ebx" + : "=A"(result) + , "=m"(*(__TBB_VOLATILE int64_t *)ptr) + , "=m"(tmp) +#if __GNUC__==3 + : "m"(*(__TBB_VOLATILE int64_t *)ptr) +#else + : "SD"(ptr) +#endif + , "0"(comparand) + , "m"(i32[0]), "c"(i32[1]) + : "memory" +#if __INTEL_COMPILER + ,"ebx" +#endif + ); +#else /* !__PIC__ */ + __asm__ __volatile__ ( + "lock\n\t cmpxchg8b %1\n\t" + : "=A"(result), "=m"(*(__TBB_VOLATILE int64_t *)ptr) + : "m"(*(__TBB_VOLATILE int64_t *)ptr) + , "0"(comparand) + , "b"(i32[0]), "c"(i32[1]) + : "memory" + ); +#endif /* __PIC__ */ + return result; +#endif /* !__TBB_GCC_BUILTIN_ATOMICS_PRESENT */ +} + +#if __INTEL_COMPILER +#pragma warning( pop ) +#endif // warning 998 is back + +static inline int32_t __TBB_machine_lg( uint32_t x ) { + int32_t j; + __asm__ ("bsr %1,%0" : "=r"(j) : "r"(x)); + return j; +} + +static inline void __TBB_machine_or( volatile void *ptr, uint32_t addend ) { + __asm__ __volatile__("lock\norl %1,%0" : "=m"(*(__TBB_VOLATILE uint32_t *)ptr) : "r"(addend), "m"(*(__TBB_VOLATILE uint32_t *)ptr) : "memory"); +} + +static inline void __TBB_machine_and( volatile void *ptr, uint32_t addend ) { + __asm__ __volatile__("lock\nandl %1,%0" : "=m"(*(__TBB_VOLATILE uint32_t *)ptr) : "r"(addend), "m"(*(__TBB_VOLATILE uint32_t *)ptr) : "memory"); +} + +static inline void __TBB_machine_pause( int32_t delay ) { + for (int32_t i = 0; i < delay; i++) { + __asm__ __volatile__("pause;"); + } + return; +} + +//TODO: Check if it possible and profitable for IA-32 on (Linux and Windows) +//to use of 64-bit load/store via floating point registers together with full fence +//for sequentially consistent load/store, instead of CAS. + +#if __clang__ +#define __TBB_fildq "fildll" +#define __TBB_fistpq "fistpll" +#else +#define __TBB_fildq "fildq" +#define __TBB_fistpq "fistpq" +#endif + +static inline int64_t __TBB_machine_load8 (const volatile void *ptr) { + int64_t result; + if( ((uint32_t)ptr&7u)==0 ) { + // Aligned load + __asm__ __volatile__ ( __TBB_fildq " %1\n\t" + __TBB_fistpq " %0" : "=m"(result) : "m"(*(const __TBB_VOLATILE uint64_t*)ptr) : "memory" ); + } else { + // Unaligned load + result = __TBB_machine_cmpswp8(const_cast(ptr),0,0); + } + return result; +} + +//! Handles misaligned 8-byte store +/** Defined in tbb_misc.cpp */ +extern "C" void __TBB_machine_store8_slow( volatile void *ptr, int64_t value ); +extern "C" void __TBB_machine_store8_slow_perf_warning( volatile void *ptr ); + +static inline void __TBB_machine_store8(volatile void *ptr, int64_t value) { + if( ((uint32_t)ptr&7u)==0 ) { + // Aligned store + __asm__ __volatile__ ( __TBB_fildq " %1\n\t" + __TBB_fistpq " %0" : "=m"(*(__TBB_VOLATILE int64_t*)ptr) : "m"(value) : "memory" ); + } else { + // Unaligned store +#if TBB_USE_PERFORMANCE_WARNINGS + __TBB_machine_store8_slow_perf_warning(ptr); +#endif /* TBB_USE_PERFORMANCE_WARNINGS */ + __TBB_machine_store8_slow(ptr,value); + } +} + +// Machine specific atomic operations +#define __TBB_AtomicOR(P,V) __TBB_machine_or(P,V) +#define __TBB_AtomicAND(P,V) __TBB_machine_and(P,V) + +// Definition of other functions +#define __TBB_Pause(V) __TBB_machine_pause(V) +#define __TBB_Log2(V) __TBB_machine_lg(V) + +#define __TBB_USE_GENERIC_DWORD_FETCH_ADD 1 +#define __TBB_USE_GENERIC_DWORD_FETCH_STORE 1 +#define __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE 1 +#define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1 +#define __TBB_USE_GENERIC_RELAXED_LOAD_STORE 1 +#define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1 + +// API to retrieve/update FPU control setting +#define __TBB_CPU_CTL_ENV_PRESENT 1 + +struct __TBB_cpu_ctl_env_t { + int mxcsr; + short x87cw; +}; + +inline void __TBB_get_cpu_ctl_env ( __TBB_cpu_ctl_env_t* ctl ) { + __asm__ __volatile__ ( + "stmxcsr %0\n\t" + "fstcw %1" + : "=m"(ctl->mxcsr), "=m"(ctl->x87cw) + ); +} +inline void __TBB_set_cpu_ctl_env ( const __TBB_cpu_ctl_env_t* ctl ) { + __asm__ __volatile__ ( + "ldmxcsr %0\n\t" + "fldcw %1" + : : "m"(ctl->mxcsr), "m"(ctl->x87cw) + ); +} diff --git a/src/tbb/include/tbb/machine/linux_ia64.h b/src/tbb/include/tbb/machine/linux_ia64.h new file mode 100644 index 0000000..b687239 --- /dev/null +++ b/src/tbb/include/tbb/machine/linux_ia64.h @@ -0,0 +1,189 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if !defined(__TBB_machine_H) || defined(__TBB_machine_linux_ia64_H) +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + +#define __TBB_machine_linux_ia64_H + +#include +#include +#include + +#define __TBB_WORDSIZE 8 +#define __TBB_BIG_ENDIAN 0 + +#if __INTEL_COMPILER + #define __TBB_compiler_fence() + #define __TBB_control_consistency_helper() __TBB_compiler_fence() + #define __TBB_acquire_consistency_helper() + #define __TBB_release_consistency_helper() + #define __TBB_full_memory_fence() __mf() +#else + #define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory") + #define __TBB_control_consistency_helper() __TBB_compiler_fence() + // Even though GCC imbues volatile loads with acquire semantics, it sometimes moves + // loads over the acquire fence. The following helpers stop such incorrect code motion. + #define __TBB_acquire_consistency_helper() __TBB_compiler_fence() + #define __TBB_release_consistency_helper() __TBB_compiler_fence() + #define __TBB_full_memory_fence() __asm__ __volatile__("mf": : :"memory") +#endif /* !__INTEL_COMPILER */ + +// Most of the functions will be in a .s file + +extern "C" { + int8_t __TBB_machine_fetchadd1__TBB_full_fence (volatile void *ptr, int8_t addend); + int8_t __TBB_machine_fetchadd1acquire(volatile void *ptr, int8_t addend); + int8_t __TBB_machine_fetchadd1release(volatile void *ptr, int8_t addend); + + int16_t __TBB_machine_fetchadd2__TBB_full_fence (volatile void *ptr, int16_t addend); + int16_t __TBB_machine_fetchadd2acquire(volatile void *ptr, int16_t addend); + int16_t __TBB_machine_fetchadd2release(volatile void *ptr, int16_t addend); + + int32_t __TBB_machine_fetchadd4__TBB_full_fence (volatile void *ptr, int32_t value); + int32_t __TBB_machine_fetchadd4acquire(volatile void *ptr, int32_t addend); + int32_t __TBB_machine_fetchadd4release(volatile void *ptr, int32_t addend); + + int64_t __TBB_machine_fetchadd8__TBB_full_fence (volatile void *ptr, int64_t value); + int64_t __TBB_machine_fetchadd8acquire(volatile void *ptr, int64_t addend); + int64_t __TBB_machine_fetchadd8release(volatile void *ptr, int64_t addend); + + int8_t __TBB_machine_fetchstore1__TBB_full_fence (volatile void *ptr, int8_t value); + int8_t __TBB_machine_fetchstore1acquire(volatile void *ptr, int8_t value); + int8_t __TBB_machine_fetchstore1release(volatile void *ptr, int8_t value); + + int16_t __TBB_machine_fetchstore2__TBB_full_fence (volatile void *ptr, int16_t value); + int16_t __TBB_machine_fetchstore2acquire(volatile void *ptr, int16_t value); + int16_t __TBB_machine_fetchstore2release(volatile void *ptr, int16_t value); + + int32_t __TBB_machine_fetchstore4__TBB_full_fence (volatile void *ptr, int32_t value); + int32_t __TBB_machine_fetchstore4acquire(volatile void *ptr, int32_t value); + int32_t __TBB_machine_fetchstore4release(volatile void *ptr, int32_t value); + + int64_t __TBB_machine_fetchstore8__TBB_full_fence (volatile void *ptr, int64_t value); + int64_t __TBB_machine_fetchstore8acquire(volatile void *ptr, int64_t value); + int64_t __TBB_machine_fetchstore8release(volatile void *ptr, int64_t value); + + int8_t __TBB_machine_cmpswp1__TBB_full_fence (volatile void *ptr, int8_t value, int8_t comparand); + int8_t __TBB_machine_cmpswp1acquire(volatile void *ptr, int8_t value, int8_t comparand); + int8_t __TBB_machine_cmpswp1release(volatile void *ptr, int8_t value, int8_t comparand); + + int16_t __TBB_machine_cmpswp2__TBB_full_fence (volatile void *ptr, int16_t value, int16_t comparand); + int16_t __TBB_machine_cmpswp2acquire(volatile void *ptr, int16_t value, int16_t comparand); + int16_t __TBB_machine_cmpswp2release(volatile void *ptr, int16_t value, int16_t comparand); + + int32_t __TBB_machine_cmpswp4__TBB_full_fence (volatile void *ptr, int32_t value, int32_t comparand); + int32_t __TBB_machine_cmpswp4acquire(volatile void *ptr, int32_t value, int32_t comparand); + int32_t __TBB_machine_cmpswp4release(volatile void *ptr, int32_t value, int32_t comparand); + + int64_t __TBB_machine_cmpswp8__TBB_full_fence (volatile void *ptr, int64_t value, int64_t comparand); + int64_t __TBB_machine_cmpswp8acquire(volatile void *ptr, int64_t value, int64_t comparand); + int64_t __TBB_machine_cmpswp8release(volatile void *ptr, int64_t value, int64_t comparand); + + int64_t __TBB_machine_lg(uint64_t value); + void __TBB_machine_pause(int32_t delay); + bool __TBB_machine_trylockbyte( volatile unsigned char &ptr ); + int64_t __TBB_machine_lockbyte( volatile unsigned char &ptr ); + + //! Retrieves the current RSE backing store pointer. IA64 specific. + void* __TBB_get_bsp(); + + int32_t __TBB_machine_load1_relaxed(const void *ptr); + int32_t __TBB_machine_load2_relaxed(const void *ptr); + int32_t __TBB_machine_load4_relaxed(const void *ptr); + int64_t __TBB_machine_load8_relaxed(const void *ptr); + + void __TBB_machine_store1_relaxed(void *ptr, int32_t value); + void __TBB_machine_store2_relaxed(void *ptr, int32_t value); + void __TBB_machine_store4_relaxed(void *ptr, int32_t value); + void __TBB_machine_store8_relaxed(void *ptr, int64_t value); +} // extern "C" + +// Mapping old entry points to the names corresponding to the new full_fence identifier. +#define __TBB_machine_fetchadd1full_fence __TBB_machine_fetchadd1__TBB_full_fence +#define __TBB_machine_fetchadd2full_fence __TBB_machine_fetchadd2__TBB_full_fence +#define __TBB_machine_fetchadd4full_fence __TBB_machine_fetchadd4__TBB_full_fence +#define __TBB_machine_fetchadd8full_fence __TBB_machine_fetchadd8__TBB_full_fence +#define __TBB_machine_fetchstore1full_fence __TBB_machine_fetchstore1__TBB_full_fence +#define __TBB_machine_fetchstore2full_fence __TBB_machine_fetchstore2__TBB_full_fence +#define __TBB_machine_fetchstore4full_fence __TBB_machine_fetchstore4__TBB_full_fence +#define __TBB_machine_fetchstore8full_fence __TBB_machine_fetchstore8__TBB_full_fence +#define __TBB_machine_cmpswp1full_fence __TBB_machine_cmpswp1__TBB_full_fence +#define __TBB_machine_cmpswp2full_fence __TBB_machine_cmpswp2__TBB_full_fence +#define __TBB_machine_cmpswp4full_fence __TBB_machine_cmpswp4__TBB_full_fence +#define __TBB_machine_cmpswp8full_fence __TBB_machine_cmpswp8__TBB_full_fence + +// Mapping relaxed operations to the entry points implementing them. +/** On IA64 RMW operations implicitly have acquire semantics. Thus one cannot + actually have completely relaxed RMW operation here. **/ +#define __TBB_machine_fetchadd1relaxed __TBB_machine_fetchadd1acquire +#define __TBB_machine_fetchadd2relaxed __TBB_machine_fetchadd2acquire +#define __TBB_machine_fetchadd4relaxed __TBB_machine_fetchadd4acquire +#define __TBB_machine_fetchadd8relaxed __TBB_machine_fetchadd8acquire +#define __TBB_machine_fetchstore1relaxed __TBB_machine_fetchstore1acquire +#define __TBB_machine_fetchstore2relaxed __TBB_machine_fetchstore2acquire +#define __TBB_machine_fetchstore4relaxed __TBB_machine_fetchstore4acquire +#define __TBB_machine_fetchstore8relaxed __TBB_machine_fetchstore8acquire +#define __TBB_machine_cmpswp1relaxed __TBB_machine_cmpswp1acquire +#define __TBB_machine_cmpswp2relaxed __TBB_machine_cmpswp2acquire +#define __TBB_machine_cmpswp4relaxed __TBB_machine_cmpswp4acquire +#define __TBB_machine_cmpswp8relaxed __TBB_machine_cmpswp8acquire + +#define __TBB_MACHINE_DEFINE_ATOMICS(S,V) \ + template \ + struct machine_load_store_relaxed { \ + static inline T load ( const T& location ) { \ + return (T)__TBB_machine_load##S##_relaxed(&location); \ + } \ + static inline void store ( T& location, T value ) { \ + __TBB_machine_store##S##_relaxed(&location, (V)value); \ + } \ + } + +namespace tbb { +namespace internal { + __TBB_MACHINE_DEFINE_ATOMICS(1,int8_t); + __TBB_MACHINE_DEFINE_ATOMICS(2,int16_t); + __TBB_MACHINE_DEFINE_ATOMICS(4,int32_t); + __TBB_MACHINE_DEFINE_ATOMICS(8,int64_t); +}} // namespaces internal, tbb + +#undef __TBB_MACHINE_DEFINE_ATOMICS + +#define __TBB_USE_FENCED_ATOMICS 1 +#define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1 +#define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1 + +// Definition of Lock functions +#define __TBB_TryLockByte(P) __TBB_machine_trylockbyte(P) +#define __TBB_LockByte(P) __TBB_machine_lockbyte(P) + +// Definition of other utility functions +#define __TBB_Pause(V) __TBB_machine_pause(V) +#define __TBB_Log2(V) __TBB_machine_lg(V) diff --git a/src/tbb/include/tbb/machine/linux_intel64.h b/src/tbb/include/tbb/machine/linux_intel64.h new file mode 100644 index 0000000..4803344 --- /dev/null +++ b/src/tbb/include/tbb/machine/linux_intel64.h @@ -0,0 +1,158 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if !defined(__TBB_machine_H) || defined(__TBB_machine_linux_intel64_H) +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + +#define __TBB_machine_linux_intel64_H + +#include +#include + +#define __TBB_WORDSIZE 8 +#define __TBB_BIG_ENDIAN 0 + +#define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory") +#define __TBB_control_consistency_helper() __TBB_compiler_fence() +#define __TBB_acquire_consistency_helper() __TBB_compiler_fence() +#define __TBB_release_consistency_helper() __TBB_compiler_fence() + +#ifndef __TBB_full_memory_fence +#define __TBB_full_memory_fence() __asm__ __volatile__("mfence": : :"memory") +#endif + +#define __TBB_MACHINE_DEFINE_ATOMICS(S,T,X) \ +static inline T __TBB_machine_cmpswp##S (volatile void *ptr, T value, T comparand ) \ +{ \ + T result; \ + \ + __asm__ __volatile__("lock\ncmpxchg" X " %2,%1" \ + : "=a"(result), "=m"(*(volatile T*)ptr) \ + : "q"(value), "0"(comparand), "m"(*(volatile T*)ptr) \ + : "memory"); \ + return result; \ +} \ + \ +static inline T __TBB_machine_fetchadd##S(volatile void *ptr, T addend) \ +{ \ + T result; \ + __asm__ __volatile__("lock\nxadd" X " %0,%1" \ + : "=r"(result),"=m"(*(volatile T*)ptr) \ + : "0"(addend), "m"(*(volatile T*)ptr) \ + : "memory"); \ + return result; \ +} \ + \ +static inline T __TBB_machine_fetchstore##S(volatile void *ptr, T value) \ +{ \ + T result; \ + __asm__ __volatile__("lock\nxchg" X " %0,%1" \ + : "=r"(result),"=m"(*(volatile T*)ptr) \ + : "0"(value), "m"(*(volatile T*)ptr) \ + : "memory"); \ + return result; \ +} \ + +__TBB_MACHINE_DEFINE_ATOMICS(1,int8_t,"") +__TBB_MACHINE_DEFINE_ATOMICS(2,int16_t,"") +__TBB_MACHINE_DEFINE_ATOMICS(4,int32_t,"") +__TBB_MACHINE_DEFINE_ATOMICS(8,int64_t,"q") + +#undef __TBB_MACHINE_DEFINE_ATOMICS + +static inline int64_t __TBB_machine_lg( uint64_t x ) { + __TBB_ASSERT(x, "__TBB_Log2(0) undefined"); + int64_t j; + __asm__ ("bsr %1,%0" : "=r"(j) : "r"(x)); + return j; +} + +static inline void __TBB_machine_or( volatile void *ptr, uint64_t value ) { + __asm__ __volatile__("lock\norq %1,%0" : "=m"(*(volatile uint64_t*)ptr) : "r"(value), "m"(*(volatile uint64_t*)ptr) : "memory"); +} + +static inline void __TBB_machine_and( volatile void *ptr, uint64_t value ) { + __asm__ __volatile__("lock\nandq %1,%0" : "=m"(*(volatile uint64_t*)ptr) : "r"(value), "m"(*(volatile uint64_t*)ptr) : "memory"); +} + +#define __TBB_AtomicOR(P,V) __TBB_machine_or(P,V) +#define __TBB_AtomicAND(P,V) __TBB_machine_and(P,V) + +// Definition of other functions +#ifndef __TBB_Pause +static inline void __TBB_machine_pause( int32_t delay ) { + for (int32_t i = 0; i < delay; i++) { + __asm__ __volatile__("pause;"); + } + return; +} +#define __TBB_Pause(V) __TBB_machine_pause(V) +#endif /* !__TBB_Pause */ + +#define __TBB_Log2(V) __TBB_machine_lg(V) + +#define __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE 1 +#define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1 +#define __TBB_USE_GENERIC_RELAXED_LOAD_STORE 1 +#define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1 + +// API to retrieve/update FPU control setting +#ifndef __TBB_CPU_CTL_ENV_PRESENT +#define __TBB_CPU_CTL_ENV_PRESENT 1 + +struct __TBB_cpu_ctl_env_t { + int mxcsr; + short x87cw; +}; + +inline void __TBB_get_cpu_ctl_env ( __TBB_cpu_ctl_env_t* ctl ) { +#if __TBB_ICC_12_0_INL_ASM_FSTCW_BROKEN + __TBB_cpu_ctl_env_t loc_ctl; + __asm__ __volatile__ ( + "stmxcsr %0\n\t" + "fstcw %1" + : "=m"(loc_ctl.mxcsr), "=m"(loc_ctl.x87cw) + ); + *ctl = loc_ctl; +#else + __asm__ __volatile__ ( + "stmxcsr %0\n\t" + "fstcw %1" + : "=m"(ctl->mxcsr), "=m"(ctl->x87cw) + ); +#endif +} +inline void __TBB_set_cpu_ctl_env ( const __TBB_cpu_ctl_env_t* ctl ) { + __asm__ __volatile__ ( + "ldmxcsr %0\n\t" + "fldcw %1" + : : "m"(ctl->mxcsr), "m"(ctl->x87cw) + ); +} +#endif /* !__TBB_CPU_CTL_ENV_PRESENT */ diff --git a/src/tbb/include/tbb/machine/mac_ppc.h b/src/tbb/include/tbb/machine/mac_ppc.h new file mode 100644 index 0000000..26c7b38 --- /dev/null +++ b/src/tbb/include/tbb/machine/mac_ppc.h @@ -0,0 +1,318 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if !defined(__TBB_machine_H) || defined(__TBB_machine_gcc_power_H) +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + +#define __TBB_machine_gcc_power_H + +#include +#include + +// TODO: rename to gcc_power.h? +// This file is for Power Architecture with compilers supporting GNU inline-assembler syntax (currently GNU g++ and IBM XL). +// Note that XL V9.0 (sometimes?) has trouble dealing with empty input and/or clobber lists, so they should be avoided. + +#if __powerpc64__ || __ppc64__ + // IBM XL documents __powerpc64__ (and __PPC64__). + // Apple documents __ppc64__ (with __ppc__ only on 32-bit). + #define __TBB_WORDSIZE 8 +#else + #define __TBB_WORDSIZE 4 +#endif + +#ifndef __BYTE_ORDER__ + // Hopefully endianness can be validly determined at runtime. + // This may silently fail in some embedded systems with page-specific endianness. +#elif __BYTE_ORDER__==__ORDER_BIG_ENDIAN__ + #define __TBB_BIG_ENDIAN 1 +#elif __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ + #define __TBB_BIG_ENDIAN 0 +#else + #define __TBB_BIG_ENDIAN -1 // not currently supported +#endif + +// On Power Architecture, (lock-free) 64-bit atomics require 64-bit hardware: +#if __TBB_WORDSIZE==8 + // Do not change the following definition, because TBB itself will use 64-bit atomics in 64-bit builds. + #define __TBB_64BIT_ATOMICS 1 +#elif __bgp__ + // Do not change the following definition, because this is known 32-bit hardware. + #define __TBB_64BIT_ATOMICS 0 +#else + // To enable 64-bit atomics in 32-bit builds, set the value below to 1 instead of 0. + // You must make certain that the program will only use them on actual 64-bit hardware + // (which typically means that the entire program is only executed on such hardware), + // because their implementation involves machine instructions that are illegal elsewhere. + // The setting can be chosen independently per compilation unit, + // which also means that TBB itself does not need to be rebuilt. + // Alternatively (but only for the current architecture and TBB version), + // override the default as a predefined macro when invoking the compiler. + #ifndef __TBB_64BIT_ATOMICS + #define __TBB_64BIT_ATOMICS 0 + #endif +#endif + +inline int32_t __TBB_machine_cmpswp4 (volatile void *ptr, int32_t value, int32_t comparand ) +{ + int32_t result; + + __asm__ __volatile__("sync\n" + "0:\n\t" + "lwarx %[res],0,%[ptr]\n\t" /* load w/ reservation */ + "cmpw %[res],%[cmp]\n\t" /* compare against comparand */ + "bne- 1f\n\t" /* exit if not same */ + "stwcx. %[val],0,%[ptr]\n\t" /* store new value */ + "bne- 0b\n" /* retry if reservation lost */ + "1:\n\t" /* the exit */ + "isync" + : [res]"=&r"(result) + , "+m"(* (int32_t*) ptr) /* redundant with "memory" */ + : [ptr]"r"(ptr) + , [val]"r"(value) + , [cmp]"r"(comparand) + : "memory" /* compiler full fence */ + , "cr0" /* clobbered by cmp and/or stwcx. */ + ); + return result; +} + +#if __TBB_WORDSIZE==8 + +inline int64_t __TBB_machine_cmpswp8 (volatile void *ptr, int64_t value, int64_t comparand ) +{ + int64_t result; + __asm__ __volatile__("sync\n" + "0:\n\t" + "ldarx %[res],0,%[ptr]\n\t" /* load w/ reservation */ + "cmpd %[res],%[cmp]\n\t" /* compare against comparand */ + "bne- 1f\n\t" /* exit if not same */ + "stdcx. %[val],0,%[ptr]\n\t" /* store new value */ + "bne- 0b\n" /* retry if reservation lost */ + "1:\n\t" /* the exit */ + "isync" + : [res]"=&r"(result) + , "+m"(* (int64_t*) ptr) /* redundant with "memory" */ + : [ptr]"r"(ptr) + , [val]"r"(value) + , [cmp]"r"(comparand) + : "memory" /* compiler full fence */ + , "cr0" /* clobbered by cmp and/or stdcx. */ + ); + return result; +} + +#elif __TBB_64BIT_ATOMICS /* && __TBB_WORDSIZE==4 */ + +inline int64_t __TBB_machine_cmpswp8 (volatile void *ptr, int64_t value, int64_t comparand ) +{ + int64_t result; + int64_t value_register, comparand_register, result_register; // dummy variables to allocate registers + __asm__ __volatile__("sync\n\t" + "ld %[val],%[valm]\n\t" + "ld %[cmp],%[cmpm]\n" + "0:\n\t" + "ldarx %[res],0,%[ptr]\n\t" /* load w/ reservation */ + "cmpd %[res],%[cmp]\n\t" /* compare against comparand */ + "bne- 1f\n\t" /* exit if not same */ + "stdcx. %[val],0,%[ptr]\n\t" /* store new value */ + "bne- 0b\n" /* retry if reservation lost */ + "1:\n\t" /* the exit */ + "std %[res],%[resm]\n\t" + "isync" + : [resm]"=m"(result) + , [res] "=&r"( result_register) + , [val] "=&r"( value_register) + , [cmp] "=&r"(comparand_register) + , "+m"(* (int64_t*) ptr) /* redundant with "memory" */ + : [ptr] "r"(ptr) + , [valm]"m"(value) + , [cmpm]"m"(comparand) + : "memory" /* compiler full fence */ + , "cr0" /* clobbered by cmpd and/or stdcx. */ + ); + return result; +} + +#endif /* __TBB_WORDSIZE==4 && __TBB_64BIT_ATOMICS */ + +#define __TBB_MACHINE_DEFINE_LOAD_STORE(S,ldx,stx,cmpx) \ + template \ + struct machine_load_store { \ + static inline T load_with_acquire(const volatile T& location) { \ + T result; \ + __asm__ __volatile__(ldx " %[res],0(%[ptr])\n" \ + "0:\n\t" \ + cmpx " %[res],%[res]\n\t" \ + "bne- 0b\n\t" \ + "isync" \ + : [res]"=r"(result) \ + : [ptr]"b"(&location) /* cannot use register 0 here */ \ + , "m"(location) /* redundant with "memory" */ \ + : "memory" /* compiler acquire fence */ \ + , "cr0" /* clobbered by cmpw/cmpd */); \ + return result; \ + } \ + static inline void store_with_release(volatile T &location, T value) { \ + __asm__ __volatile__("lwsync\n\t" \ + stx " %[val],0(%[ptr])" \ + : "=m"(location) /* redundant with "memory" */ \ + : [ptr]"b"(&location) /* cannot use register 0 here */ \ + , [val]"r"(value) \ + : "memory"/*compiler release fence*/ /*(cr0 not affected)*/); \ + } \ + }; \ + \ + template \ + struct machine_load_store_relaxed { \ + static inline T load (const __TBB_atomic T& location) { \ + T result; \ + __asm__ __volatile__(ldx " %[res],0(%[ptr])" \ + : [res]"=r"(result) \ + : [ptr]"b"(&location) /* cannot use register 0 here */ \ + , "m"(location) \ + ); /*(no compiler fence)*/ /*(cr0 not affected)*/ \ + return result; \ + } \ + static inline void store (__TBB_atomic T &location, T value) { \ + __asm__ __volatile__(stx " %[val],0(%[ptr])" \ + : "=m"(location) \ + : [ptr]"b"(&location) /* cannot use register 0 here */ \ + , [val]"r"(value) \ + ); /*(no compiler fence)*/ /*(cr0 not affected)*/ \ + } \ + }; + +namespace tbb { +namespace internal { + __TBB_MACHINE_DEFINE_LOAD_STORE(1,"lbz","stb","cmpw") + __TBB_MACHINE_DEFINE_LOAD_STORE(2,"lhz","sth","cmpw") + __TBB_MACHINE_DEFINE_LOAD_STORE(4,"lwz","stw","cmpw") + +#if __TBB_WORDSIZE==8 + + __TBB_MACHINE_DEFINE_LOAD_STORE(8,"ld" ,"std","cmpd") + +#elif __TBB_64BIT_ATOMICS /* && __TBB_WORDSIZE==4 */ + + template + struct machine_load_store { + static inline T load_with_acquire(const volatile T& location) { + T result; + T result_register; // dummy variable to allocate a register + __asm__ __volatile__("ld %[res],0(%[ptr])\n\t" + "std %[res],%[resm]\n" + "0:\n\t" + "cmpd %[res],%[res]\n\t" + "bne- 0b\n\t" + "isync" + : [resm]"=m"(result) + , [res]"=&r"(result_register) + : [ptr]"b"(&location) /* cannot use register 0 here */ + , "m"(location) /* redundant with "memory" */ + : "memory" /* compiler acquire fence */ + , "cr0" /* clobbered by cmpd */); + return result; + } + + static inline void store_with_release(volatile T &location, T value) { + T value_register; // dummy variable to allocate a register + __asm__ __volatile__("lwsync\n\t" + "ld %[val],%[valm]\n\t" + "std %[val],0(%[ptr])" + : "=m"(location) /* redundant with "memory" */ + , [val]"=&r"(value_register) + : [ptr]"b"(&location) /* cannot use register 0 here */ + , [valm]"m"(value) + : "memory"/*compiler release fence*/ /*(cr0 not affected)*/); + } + }; + + struct machine_load_store_relaxed { + static inline T load (const volatile T& location) { + T result; + T result_register; // dummy variable to allocate a register + __asm__ __volatile__("ld %[res],0(%[ptr])\n\t" + "std %[res],%[resm]" + : [resm]"=m"(result) + , [res]"=&r"(result_register) + : [ptr]"b"(&location) /* cannot use register 0 here */ + , "m"(location) + ); /*(no compiler fence)*/ /*(cr0 not affected)*/ + return result; + } + + static inline void store (volatile T &location, T value) { + T value_register; // dummy variable to allocate a register + __asm__ __volatile__("ld %[val],%[valm]\n\t" + "std %[val],0(%[ptr])" + : "=m"(location) + , [val]"=&r"(value_register) + : [ptr]"b"(&location) /* cannot use register 0 here */ + , [valm]"m"(value) + ); /*(no compiler fence)*/ /*(cr0 not affected)*/ + } + }; + #define __TBB_machine_load_store_relaxed_8 + +#endif /* __TBB_WORDSIZE==4 && __TBB_64BIT_ATOMICS */ + +}} // namespaces internal, tbb + +#undef __TBB_MACHINE_DEFINE_LOAD_STORE + +#define __TBB_USE_GENERIC_PART_WORD_CAS 1 +#define __TBB_USE_GENERIC_FETCH_ADD 1 +#define __TBB_USE_GENERIC_FETCH_STORE 1 +#define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1 + +#define __TBB_control_consistency_helper() __asm__ __volatile__("isync": : :"memory") +#define __TBB_full_memory_fence() __asm__ __volatile__( "sync": : :"memory") + +static inline intptr_t __TBB_machine_lg( uintptr_t x ) { + __TBB_ASSERT(x, "__TBB_Log2(0) undefined"); + // cntlzd/cntlzw starts counting at 2^63/2^31 (ignoring any higher-order bits), and does not affect cr0 +#if __TBB_WORDSIZE==8 + __asm__ __volatile__ ("cntlzd %0,%0" : "+r"(x)); + return 63-static_cast(x); +#else + __asm__ __volatile__ ("cntlzw %0,%0" : "+r"(x)); + return 31-static_cast(x); +#endif +} +#define __TBB_Log2(V) __TBB_machine_lg(V) + +// Assumes implicit alignment for any 32-bit value +typedef uint32_t __TBB_Flag; +#define __TBB_Flag __TBB_Flag + +inline bool __TBB_machine_trylockbyte( __TBB_atomic __TBB_Flag &flag ) { + return __TBB_machine_cmpswp4(&flag,1,0)==0; +} +#define __TBB_TryLockByte(P) __TBB_machine_trylockbyte(P) diff --git a/src/tbb/include/tbb/machine/macos_common.h b/src/tbb/include/tbb/machine/macos_common.h new file mode 100644 index 0000000..570032c --- /dev/null +++ b/src/tbb/include/tbb/machine/macos_common.h @@ -0,0 +1,145 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if !defined(__TBB_machine_H) || defined(__TBB_machine_macos_common_H) +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + +#define __TBB_machine_macos_common_H + +#include +#define __TBB_Yield() sched_yield() + +// __TBB_HardwareConcurrency + +#include +#include + +static inline int __TBB_macos_available_cpu() { + int name[2] = {CTL_HW, HW_AVAILCPU}; + int ncpu; + size_t size = sizeof(ncpu); + sysctl( name, 2, &ncpu, &size, NULL, 0 ); + return ncpu; +} + +#define __TBB_HardwareConcurrency() __TBB_macos_available_cpu() + +#ifndef __TBB_full_memory_fence + // TBB has not recognized the architecture (none of the architecture abstraction + // headers was included). + #define __TBB_UnknownArchitecture 1 +#endif + +#if __TBB_UnknownArchitecture || __TBB_WORDSIZE==4 +// In case of IA32 this is a workaround for compiler bugs triggered by inline +// assembly implementation of __TBB_machine_cmpswp8 in linux_ia32.h, which may +// lead to incorrect codegen (gcc) or compilation failures (any icc including 12.0.4). + +// Implementation of atomic operations based on OS provided primitives +#include + +static inline int64_t __TBB_machine_cmpswp8_OsX(volatile void *ptr, int64_t value, int64_t comparand) +{ + __TBB_ASSERT( !((uintptr_t)ptr&0x7), "address not properly aligned for Mac OS atomics"); + int64_t* address = (int64_t*)ptr; + while( !OSAtomicCompareAndSwap64Barrier(comparand, value, address) ){ +#if __TBB_WORDSIZE==8 + int64_t snapshot = *address; +#else + int64_t snapshot = OSAtomicAdd64( 0, address ); +#endif + if( snapshot!=comparand ) return snapshot; + } + return comparand; +} + +#define __TBB_machine_cmpswp8 __TBB_machine_cmpswp8_OsX + +#endif /* __TBB_UnknownArchitecture || __TBB_WORDSIZE==4 */ + +#if __TBB_UnknownArchitecture + +#ifndef __TBB_WORDSIZE +#define __TBB_WORDSIZE 4 +#endif + +#ifdef __TBB_BIG_ENDIAN + // Already determined based on hardware architecture. +#elif __BIG_ENDIAN__ + #define __TBB_BIG_ENDIAN 1 +#elif __LITTLE_ENDIAN__ + #define __TBB_BIG_ENDIAN 0 +#else + #define __TBB_BIG_ENDIAN -1 // not currently supported +#endif + +/** As this generic implementation has absolutely no information about underlying + hardware, its performance most likely will be sub-optimal because of full memory + fence usages where a more lightweight synchronization means (or none at all) + could suffice. Thus if you use this header to enable TBB on a new platform, + consider forking it and relaxing below helpers as appropriate. **/ +#define __TBB_control_consistency_helper() OSMemoryBarrier() +#define __TBB_acquire_consistency_helper() OSMemoryBarrier() +#define __TBB_release_consistency_helper() OSMemoryBarrier() +#define __TBB_full_memory_fence() OSMemoryBarrier() + +static inline int32_t __TBB_machine_cmpswp4(volatile void *ptr, int32_t value, int32_t comparand) +{ + __TBB_ASSERT( !((uintptr_t)ptr&0x3), "address not properly aligned for Mac OS atomics"); + int32_t* address = (int32_t*)ptr; + while( !OSAtomicCompareAndSwap32Barrier(comparand, value, address) ){ + int32_t snapshot = *address; + if( snapshot!=comparand ) return snapshot; + } + return comparand; +} + +static inline int32_t __TBB_machine_fetchadd4(volatile void *ptr, int32_t addend) +{ + __TBB_ASSERT( !((uintptr_t)ptr&0x3), "address not properly aligned for Mac OS atomics"); + return OSAtomicAdd32Barrier(addend, (int32_t*)ptr) - addend; +} + +static inline int64_t __TBB_machine_fetchadd8(volatile void *ptr, int64_t addend) +{ + __TBB_ASSERT( !((uintptr_t)ptr&0x7), "address not properly aligned for Mac OS atomics"); + return OSAtomicAdd64Barrier(addend, (int64_t*)ptr) - addend; +} + +#define __TBB_USE_GENERIC_PART_WORD_CAS 1 +#define __TBB_USE_GENERIC_PART_WORD_FETCH_ADD 1 +#define __TBB_USE_GENERIC_FETCH_STORE 1 +#define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1 +#define __TBB_USE_GENERIC_RELAXED_LOAD_STORE 1 +#if __TBB_WORDSIZE == 4 + #define __TBB_USE_GENERIC_DWORD_LOAD_STORE 1 +#endif +#define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1 + +#endif /* __TBB_UnknownArchitecture */ diff --git a/src/tbb/include/tbb/machine/sunos_sparc.h b/src/tbb/include/tbb/machine/sunos_sparc.h new file mode 100644 index 0000000..84ddbb3 --- /dev/null +++ b/src/tbb/include/tbb/machine/sunos_sparc.h @@ -0,0 +1,209 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + + +#if !defined(__TBB_machine_H) || defined(__TBB_machine_sunos_sparc_H) +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + +#define __TBB_machine_sunos_sparc_H + +#include +#include + +#define __TBB_WORDSIZE 8 +#define __TBB_BIG_ENDIAN 1 // assumption (hardware may support page-specific bi-endianness) + +/** To those working on SPARC hardware. Consider relaxing acquire and release + consistency helpers to no-op (as this port covers TSO mode only). **/ +#define __TBB_compiler_fence() __asm__ __volatile__ ("": : :"memory") +#define __TBB_control_consistency_helper() __TBB_compiler_fence() +#define __TBB_acquire_consistency_helper() __TBB_compiler_fence() +#define __TBB_release_consistency_helper() __TBB_compiler_fence() +#define __TBB_full_memory_fence() __asm__ __volatile__("membar #LoadLoad|#LoadStore|#StoreStore|#StoreLoad": : : "memory") + +//-------------------------------------------------- +// Compare and swap +//-------------------------------------------------- + +/** + * Atomic CAS for 32 bit values, if *ptr==comparand, then *ptr=value, returns *ptr + * @param ptr pointer to value in memory to be swapped with value if *ptr==comparand + * @param value value to assign *ptr to if *ptr==comparand + * @param comparand value to compare with *ptr + ( @return value originally in memory at ptr, regardless of success +*/ +static inline int32_t __TBB_machine_cmpswp4(volatile void *ptr, int32_t value, int32_t comparand ){ + int32_t result; + __asm__ __volatile__( + "cas\t[%5],%4,%1" + : "=m"(*(int32_t *)ptr), "=r"(result) + : "m"(*(int32_t *)ptr), "1"(value), "r"(comparand), "r"(ptr) + : "memory"); + return result; +} + +/** + * Atomic CAS for 64 bit values, if *ptr==comparand, then *ptr=value, returns *ptr + * @param ptr pointer to value in memory to be swapped with value if *ptr==comparand + * @param value value to assign *ptr to if *ptr==comparand + * @param comparand value to compare with *ptr + ( @return value originally in memory at ptr, regardless of success + */ +static inline int64_t __TBB_machine_cmpswp8(volatile void *ptr, int64_t value, int64_t comparand ){ + int64_t result; + __asm__ __volatile__( + "casx\t[%5],%4,%1" + : "=m"(*(int64_t *)ptr), "=r"(result) + : "m"(*(int64_t *)ptr), "1"(value), "r"(comparand), "r"(ptr) + : "memory"); + return result; +} + +//--------------------------------------------------- +// Fetch and add +//--------------------------------------------------- + +/** + * Atomic fetch and add for 32 bit values, in this case implemented by continuously checking success of atomicity + * @param ptr pointer to value to add addend to + * @param addened value to add to *ptr + * @return value at ptr before addened was added + */ +static inline int32_t __TBB_machine_fetchadd4(volatile void *ptr, int32_t addend){ + int32_t result; + __asm__ __volatile__ ( + "0:\t add\t %3, %4, %0\n" // do addition + "\t cas\t [%2], %3, %0\n" // cas to store result in memory + "\t cmp\t %3, %0\n" // check if value from memory is original + "\t bne,a,pn\t %%icc, 0b\n" // if not try again + "\t mov %0, %3\n" // use branch delay slot to move new value in memory to be added + : "=&r"(result), "=m"(*(int32_t *)ptr) + : "r"(ptr), "r"(*(int32_t *)ptr), "r"(addend), "m"(*(int32_t *)ptr) + : "ccr", "memory"); + return result; +} + +/** + * Atomic fetch and add for 64 bit values, in this case implemented by continuously checking success of atomicity + * @param ptr pointer to value to add addend to + * @param addened value to add to *ptr + * @return value at ptr before addened was added + */ +static inline int64_t __TBB_machine_fetchadd8(volatile void *ptr, int64_t addend){ + int64_t result; + __asm__ __volatile__ ( + "0:\t add\t %3, %4, %0\n" // do addition + "\t casx\t [%2], %3, %0\n" // cas to store result in memory + "\t cmp\t %3, %0\n" // check if value from memory is original + "\t bne,a,pn\t %%xcc, 0b\n" // if not try again + "\t mov %0, %3\n" // use branch delay slot to move new value in memory to be added + : "=&r"(result), "=m"(*(int64_t *)ptr) + : "r"(ptr), "r"(*(int64_t *)ptr), "r"(addend), "m"(*(int64_t *)ptr) + : "ccr", "memory"); + return result; +} + +//-------------------------------------------------------- +// Logarithm (base two, integer) +//-------------------------------------------------------- + +static inline int64_t __TBB_machine_lg( uint64_t x ) { + __TBB_ASSERT(x, "__TBB_Log2(0) undefined"); + uint64_t count; + // one hot encode + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + x |= (x >> 32); + // count 1's + __asm__ ("popc %1, %0" : "=r"(count) : "r"(x) ); + return count-1; +} + +//-------------------------------------------------------- + +static inline void __TBB_machine_or( volatile void *ptr, uint64_t value ) { + __asm__ __volatile__ ( + "0:\t or\t %2, %3, %%g1\n" // do operation + "\t casx\t [%1], %2, %%g1\n" // cas to store result in memory + "\t cmp\t %2, %%g1\n" // check if value from memory is original + "\t bne,a,pn\t %%xcc, 0b\n" // if not try again + "\t mov %%g1, %2\n" // use branch delay slot to move new value in memory to be added + : "=m"(*(int64_t *)ptr) + : "r"(ptr), "r"(*(int64_t *)ptr), "r"(value), "m"(*(int64_t *)ptr) + : "ccr", "g1", "memory"); +} + +static inline void __TBB_machine_and( volatile void *ptr, uint64_t value ) { + __asm__ __volatile__ ( + "0:\t and\t %2, %3, %%g1\n" // do operation + "\t casx\t [%1], %2, %%g1\n" // cas to store result in memory + "\t cmp\t %2, %%g1\n" // check if value from memory is original + "\t bne,a,pn\t %%xcc, 0b\n" // if not try again + "\t mov %%g1, %2\n" // use branch delay slot to move new value in memory to be added + : "=m"(*(int64_t *)ptr) + : "r"(ptr), "r"(*(int64_t *)ptr), "r"(value), "m"(*(int64_t *)ptr) + : "ccr", "g1", "memory"); +} + + +static inline void __TBB_machine_pause( int32_t delay ) { + // do nothing, inlined, doesn't matter +} + +// put 0xff in memory location, return memory value, +// generic trylockbyte puts 0x01, however this is fine +// because all that matters is that 0 is unlocked +static inline bool __TBB_machine_trylockbyte(unsigned char &flag){ + unsigned char result; + __asm__ __volatile__ ( + "ldstub\t [%2], %0\n" + : "=r"(result), "=m"(flag) + : "r"(&flag), "m"(flag) + : "memory"); + return result == 0; +} + +#define __TBB_USE_GENERIC_PART_WORD_CAS 1 +#define __TBB_USE_GENERIC_PART_WORD_FETCH_ADD 1 +#define __TBB_USE_GENERIC_FETCH_STORE 1 +#define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1 +#define __TBB_USE_GENERIC_RELAXED_LOAD_STORE 1 +#define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1 + +#define __TBB_AtomicOR(P,V) __TBB_machine_or(P,V) +#define __TBB_AtomicAND(P,V) __TBB_machine_and(P,V) + +// Definition of other functions +#define __TBB_Pause(V) __TBB_machine_pause(V) +#define __TBB_Log2(V) __TBB_machine_lg(V) + +#define __TBB_TryLockByte(P) __TBB_machine_trylockbyte(P) diff --git a/src/tbb/include/tbb/machine/windows_api.h b/src/tbb/include/tbb/machine/windows_api.h new file mode 100644 index 0000000..adb22e9 --- /dev/null +++ b/src/tbb/include/tbb/machine/windows_api.h @@ -0,0 +1,56 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_machine_windows_api_H +#define __TBB_machine_windows_api_H + +#if _WIN32 || _WIN64 + +#if _XBOX + +#define NONET +#define NOD3D +#include + +#else // Assume "usual" Windows + +#include + +#endif // _XBOX + +#if !defined(_WIN32_WINNT) +// The following Windows API function is declared explicitly; +// otherwise any user would have to specify /D_WIN32_WINNT=0x0400 +extern "C" BOOL WINAPI TryEnterCriticalSection( LPCRITICAL_SECTION ); +#endif + +#else +#error tbb/machine/windows_api.h should only be used for Windows based platforms +#endif // _WIN32 || _WIN64 + +#endif // __TBB_machine_windows_api_H diff --git a/src/tbb/include/tbb/machine/windows_ia32.h b/src/tbb/include/tbb/machine/windows_ia32.h new file mode 100644 index 0000000..d8e7092 --- /dev/null +++ b/src/tbb/include/tbb/machine/windows_ia32.h @@ -0,0 +1,218 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if !defined(__TBB_machine_H) || defined(__TBB_machine_windows_ia32_H) +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + +#define __TBB_machine_windows_ia32_H + +#define __TBB_WORDSIZE 4 +#define __TBB_BIG_ENDIAN 0 + +#if __INTEL_COMPILER + #define __TBB_compiler_fence() __asm { __asm nop } +#elif _MSC_VER >= 1300 + extern "C" void _ReadWriteBarrier(); + #pragma intrinsic(_ReadWriteBarrier) + #define __TBB_compiler_fence() _ReadWriteBarrier() +#else + #error Unsupported compiler - need to define __TBB_{control,acquire,release}_consistency_helper to support it +#endif + +#define __TBB_control_consistency_helper() __TBB_compiler_fence() +#define __TBB_acquire_consistency_helper() __TBB_compiler_fence() +#define __TBB_release_consistency_helper() __TBB_compiler_fence() +#define __TBB_full_memory_fence() __asm { __asm mfence } + +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) + // Workaround for overzealous compiler warnings in /Wp64 mode + #pragma warning (push) + #pragma warning (disable: 4244 4267) +#endif + +extern "C" { + __int64 __TBB_EXPORTED_FUNC __TBB_machine_cmpswp8 (volatile void *ptr, __int64 value, __int64 comparand ); + __int64 __TBB_EXPORTED_FUNC __TBB_machine_fetchadd8 (volatile void *ptr, __int64 addend ); + __int64 __TBB_EXPORTED_FUNC __TBB_machine_fetchstore8 (volatile void *ptr, __int64 value ); + void __TBB_EXPORTED_FUNC __TBB_machine_store8 (volatile void *ptr, __int64 value ); + __int64 __TBB_EXPORTED_FUNC __TBB_machine_load8 (const volatile void *ptr); +} + +#define __TBB_MACHINE_DEFINE_ATOMICS(S,T,U,A,C) \ +static inline T __TBB_machine_cmpswp##S ( volatile void * ptr, U value, U comparand ) { \ + T result; \ + volatile T *p = (T *)ptr; \ + __asm \ + { \ + __asm mov edx, p \ + __asm mov C , value \ + __asm mov A , comparand \ + __asm lock cmpxchg [edx], C \ + __asm mov result, A \ + } \ + return result; \ +} \ +\ +static inline T __TBB_machine_fetchadd##S ( volatile void * ptr, U addend ) { \ + T result; \ + volatile T *p = (T *)ptr; \ + __asm \ + { \ + __asm mov edx, p \ + __asm mov A, addend \ + __asm lock xadd [edx], A \ + __asm mov result, A \ + } \ + return result; \ +}\ +\ +static inline T __TBB_machine_fetchstore##S ( volatile void * ptr, U value ) { \ + T result; \ + volatile T *p = (T *)ptr; \ + __asm \ + { \ + __asm mov edx, p \ + __asm mov A, value \ + __asm lock xchg [edx], A \ + __asm mov result, A \ + } \ + return result; \ +} + + +__TBB_MACHINE_DEFINE_ATOMICS(1, __int8, __int8, al, cl) +__TBB_MACHINE_DEFINE_ATOMICS(2, __int16, __int16, ax, cx) +__TBB_MACHINE_DEFINE_ATOMICS(4, ptrdiff_t, ptrdiff_t, eax, ecx) + +#undef __TBB_MACHINE_DEFINE_ATOMICS + +#if ( _MSC_VER>=1400 && !defined(__INTEL_COMPILER) ) || (__INTEL_COMPILER>=1200) +// MSVC did not have this intrinsic prior to VC8. +// ICL 11.1 fails to compile a TBB example if __TBB_Log2 uses the intrinsic. +#define __TBB_LOG2_USE_BSR_INTRINSIC 1 +extern "C" unsigned char _BitScanReverse( unsigned long* i, unsigned long w ); +#pragma intrinsic(_BitScanReverse) +#endif + +static inline intptr_t __TBB_machine_lg( uintptr_t i ) { + unsigned long j; +#if __TBB_LOG2_USE_BSR_INTRINSIC + _BitScanReverse( &j, i ); +#else + __asm + { + bsr eax, i + mov j, eax + } +#endif + return j; +} + +static inline void __TBB_machine_OR( volatile void *operand, __int32 addend ) { + __asm + { + mov eax, addend + mov edx, [operand] + lock or [edx], eax + } +} + +static inline void __TBB_machine_AND( volatile void *operand, __int32 addend ) { + __asm + { + mov eax, addend + mov edx, [operand] + lock and [edx], eax + } +} + +static inline void __TBB_machine_pause (__int32 delay ) { + _asm + { + mov eax, delay + __TBB_L1: + pause + add eax, -1 + jne __TBB_L1 + } + return; +} + +#define __TBB_AtomicOR(P,V) __TBB_machine_OR(P,V) +#define __TBB_AtomicAND(P,V) __TBB_machine_AND(P,V) + +//TODO: Check if it possible and profitable for IA-32 on (Linux and Windows) +//to use of 64-bit load/store via floating point registers together with full fence +//for sequentially consistent load/store, instead of CAS. +#define __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE 1 +#define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1 +#define __TBB_USE_GENERIC_RELAXED_LOAD_STORE 1 +#define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1 + +// Definition of other functions +extern "C" __declspec(dllimport) int __stdcall SwitchToThread( void ); +#define __TBB_Yield() SwitchToThread() +#define __TBB_Pause(V) __TBB_machine_pause(V) +#define __TBB_Log2(V) __TBB_machine_lg(V) + +#if defined(_MSC_VER)&&_MSC_VER<1400 + static inline void* __TBB_machine_get_current_teb () { + void* pteb; + __asm mov eax, fs:[0x18] + __asm mov pteb, eax + return pteb; + } +#endif + +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) + #pragma warning (pop) +#endif // warnings 4244, 4267 are back + +// API to retrieve/update FPU control setting +#define __TBB_CPU_CTL_ENV_PRESENT 1 + +struct __TBB_cpu_ctl_env_t { + int mxcsr; + short x87cw; +}; +inline void __TBB_get_cpu_ctl_env ( __TBB_cpu_ctl_env_t* ctl ) { + __asm { + __asm mov eax, ctl + __asm stmxcsr [eax] + __asm fstcw [eax+4] + } +} +inline void __TBB_set_cpu_ctl_env ( const __TBB_cpu_ctl_env_t* ctl ) { + __asm { + __asm mov eax, ctl + __asm ldmxcsr [eax] + __asm fldcw [eax+4] + } +} + diff --git a/src/tbb/include/tbb/machine/windows_intel64.h b/src/tbb/include/tbb/machine/windows_intel64.h new file mode 100644 index 0000000..4f17a0c --- /dev/null +++ b/src/tbb/include/tbb/machine/windows_intel64.h @@ -0,0 +1,145 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if !defined(__TBB_machine_H) || defined(__TBB_machine_windows_intel64_H) +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + +#define __TBB_machine_windows_intel64_H + +#define __TBB_WORDSIZE 8 +#define __TBB_BIG_ENDIAN 0 + +#include + +#if !__INTEL_COMPILER + #pragma intrinsic(_InterlockedOr64) + #pragma intrinsic(_InterlockedAnd64) + #pragma intrinsic(_InterlockedCompareExchange) + #pragma intrinsic(_InterlockedCompareExchange64) + #pragma intrinsic(_InterlockedExchangeAdd) + #pragma intrinsic(_InterlockedExchangeAdd64) + #pragma intrinsic(_InterlockedExchange) + #pragma intrinsic(_InterlockedExchange64) +#endif /* !defined(__INTEL_COMPILER) */ + +#if __INTEL_COMPILER + #define __TBB_compiler_fence() __asm { __asm nop } + #define __TBB_full_memory_fence() __asm { __asm mfence } +#elif _MSC_VER >= 1300 + extern "C" void _ReadWriteBarrier(); + #pragma intrinsic(_ReadWriteBarrier) + #pragma intrinsic(_mm_mfence) + #pragma intrinsic(_mm_pause) + #define __TBB_compiler_fence() _ReadWriteBarrier() + #define __TBB_full_memory_fence() _mm_mfence() +#endif + +#define __TBB_control_consistency_helper() __TBB_compiler_fence() +#define __TBB_acquire_consistency_helper() __TBB_compiler_fence() +#define __TBB_release_consistency_helper() __TBB_compiler_fence() + +// ATTENTION: if you ever change argument types in machine-specific primitives, +// please take care of atomic_word<> specializations in tbb/atomic.h +extern "C" { + __int8 __TBB_EXPORTED_FUNC __TBB_machine_cmpswp1 (volatile void *ptr, __int8 value, __int8 comparand ); + __int8 __TBB_EXPORTED_FUNC __TBB_machine_fetchadd1 (volatile void *ptr, __int8 addend ); + __int8 __TBB_EXPORTED_FUNC __TBB_machine_fetchstore1 (volatile void *ptr, __int8 value ); + __int16 __TBB_EXPORTED_FUNC __TBB_machine_cmpswp2 (volatile void *ptr, __int16 value, __int16 comparand ); + __int16 __TBB_EXPORTED_FUNC __TBB_machine_fetchadd2 (volatile void *ptr, __int16 addend ); + __int16 __TBB_EXPORTED_FUNC __TBB_machine_fetchstore2 (volatile void *ptr, __int16 value ); +} + +inline long __TBB_machine_cmpswp4 (volatile void *ptr, __int32 value, __int32 comparand ) { + return _InterlockedCompareExchange( (long*)ptr, value, comparand ); +} +inline long __TBB_machine_fetchadd4 (volatile void *ptr, __int32 addend ) { + return _InterlockedExchangeAdd( (long*)ptr, addend ); +} +inline long __TBB_machine_fetchstore4 (volatile void *ptr, __int32 value ) { + return _InterlockedExchange( (long*)ptr, value ); +} + +inline __int64 __TBB_machine_cmpswp8 (volatile void *ptr, __int64 value, __int64 comparand ) { + return _InterlockedCompareExchange64( (__int64*)ptr, value, comparand ); +} +inline __int64 __TBB_machine_fetchadd8 (volatile void *ptr, __int64 addend ) { + return _InterlockedExchangeAdd64( (__int64*)ptr, addend ); +} +inline __int64 __TBB_machine_fetchstore8 (volatile void *ptr, __int64 value ) { + return _InterlockedExchange64( (__int64*)ptr, value ); +} + +inline void __TBB_machine_pause_v6 (__int32 delay ) { + for (;delay>0; --delay ) + _mm_pause(); +} + +#define __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE 1 +#define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1 +#define __TBB_USE_GENERIC_RELAXED_LOAD_STORE 1 +#define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1 + +extern "C" unsigned char _BitScanReverse64( unsigned long* i, unsigned __int64 w ); +#pragma intrinsic(_BitScanReverse64) + + +inline __int64 __TBB_machine_lg( unsigned __int64 i ) { + unsigned long j; + _BitScanReverse64( &j, i ); + return j; +} + +inline void __TBB_machine_OR( volatile void *operand, intptr_t addend ) { + _InterlockedOr64((__int64*)operand, addend); +} + +inline void __TBB_machine_AND( volatile void *operand, intptr_t addend ) { + _InterlockedAnd64((__int64*)operand, addend); +} + +#define __TBB_AtomicOR(P,V) __TBB_machine_OR(P,V) +#define __TBB_AtomicAND(P,V) __TBB_machine_AND(P,V) + +extern "C" __declspec(dllimport) int __stdcall SwitchToThread( void ); +#define __TBB_Yield() SwitchToThread() +#define __TBB_Pause(V) __TBB_machine_pause_v6(V) +#define __TBB_Log2(V) __TBB_machine_lg(V) + +// API to retrieve/update FPU control setting +#define __TBB_CPU_CTL_ENV_PRESENT 1 + +struct __TBB_cpu_ctl_env_t { + int mxcsr; + short x87cw; +}; + +extern "C" { + void __TBB_EXPORTED_FUNC __TBB_get_cpu_ctl_env ( __TBB_cpu_ctl_env_t* ); + void __TBB_EXPORTED_FUNC __TBB_set_cpu_ctl_env ( const __TBB_cpu_ctl_env_t* ); +} diff --git a/src/tbb/include/tbb/machine/xbox360_ppc.h b/src/tbb/include/tbb/machine/xbox360_ppc.h new file mode 100644 index 0000000..25aa40e --- /dev/null +++ b/src/tbb/include/tbb/machine/xbox360_ppc.h @@ -0,0 +1,127 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// TODO: revise by comparing with mac_ppc.h + +#if !defined(__TBB_machine_H) || defined(__TBB_machine_xbox360_ppc_H) +#error Do not #include this internal file directly; use public TBB headers instead. +#endif + +#define __TBB_machine_xbox360_ppc_H + +#define NONET +#define NOD3D +#include "xtl.h" +#include "ppcintrinsics.h" + +#if _MSC_VER >= 1300 +extern "C" void _MemoryBarrier(); +#pragma intrinsic(_MemoryBarrier) +#define __TBB_control_consistency_helper() __isync() +#define __TBB_acquire_consistency_helper() _MemoryBarrier() +#define __TBB_release_consistency_helper() _MemoryBarrier() +#endif + +#define __TBB_full_memory_fence() __sync() + +#define __TBB_WORDSIZE 4 +#define __TBB_BIG_ENDIAN 1 + +//todo: define __TBB_USE_FENCED_ATOMICS and define acquire/release primitives to maximize performance + +inline __int32 __TBB_machine_cmpswp4(volatile void *ptr, __int32 value, __int32 comparand ) { + __sync(); + __int32 result = InterlockedCompareExchange((volatile LONG*)ptr, value, comparand); + __isync(); + return result; +} + +inline __int64 __TBB_machine_cmpswp8(volatile void *ptr, __int64 value, __int64 comparand ) +{ + __sync(); + __int64 result = InterlockedCompareExchange64((volatile LONG64*)ptr, value, comparand); + __isync(); + return result; +} + +#define __TBB_USE_GENERIC_PART_WORD_CAS 1 +#define __TBB_USE_GENERIC_FETCH_ADD 1 +#define __TBB_USE_GENERIC_FETCH_STORE 1 +#define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1 +#define __TBB_USE_GENERIC_RELAXED_LOAD_STORE 1 +#define __TBB_USE_GENERIC_DWORD_LOAD_STORE 1 +#define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1 + +#pragma optimize( "", off ) +inline void __TBB_machine_pause (__int32 delay ) +{ + for (__int32 i=0; i> 0) & 1) + + ((__TBB_XBOX360_HARDWARE_THREAD_MASK >> 1) & 1) + + ((__TBB_XBOX360_HARDWARE_THREAD_MASK >> 2) & 1) + + ((__TBB_XBOX360_HARDWARE_THREAD_MASK >> 3) & 1) + + ((__TBB_XBOX360_HARDWARE_THREAD_MASK >> 4) & 1) + + ((__TBB_XBOX360_HARDWARE_THREAD_MASK >> 5) & 1) + 1; // +1 accomodates for the master thread +} + +static inline int __TBB_XBOX360_GetHardwareThreadIndex(int workerThreadIndex) +{ + workerThreadIndex %= __TBB_XBOX360_DetectNumberOfWorkers()-1; + int m = __TBB_XBOX360_HARDWARE_THREAD_MASK; + int index = 0; + int skipcount = workerThreadIndex; + while (true) + { + if ((m & 1)!=0) + { + if (skipcount==0) break; + skipcount--; + } + m >>= 1; + index++; + } + return index; +} + +#define __TBB_HardwareConcurrency() __TBB_XBOX360_DetectNumberOfWorkers() diff --git a/src/tbb/include/tbb/memory_pool.h b/src/tbb/include/tbb/memory_pool.h new file mode 100644 index 0000000..cf3ef91 --- /dev/null +++ b/src/tbb/include/tbb/memory_pool.h @@ -0,0 +1,269 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_memory_pool_H +#define __TBB_memory_pool_H + +#if !TBB_PREVIEW_MEMORY_POOL +#error Set TBB_PREVIEW_MEMORY_POOL to include memory_pool.h +#endif +/** @file */ + +#include "scalable_allocator.h" +#include "tbb_stddef.h" +#include "tbb_machine.h" // TODO: avoid linkage with libtbb on IA-64 +#include // std::bad_alloc +#if __TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_CPP11_STD_FORWARD_BROKEN +#include // std::forward +#endif + +#if __TBB_EXTRA_DEBUG +#define __TBBMALLOC_ASSERT ASSERT +#else +#define __TBBMALLOC_ASSERT(a,b) ((void)0) +#endif + +namespace tbb { +namespace interface6 { +//! @cond INTERNAL +namespace internal { + +//! Base of thread-safe pool allocator for variable-size requests +class pool_base : tbb::internal::no_copy { + // Pool interface is separate from standard allocator classes because it has + // to maintain internal state, no copy or assignment. Move and swap are possible. +public: + //! Reset pool to reuse its memory (free all objects at once) + void recycle() { rml::pool_reset(my_pool); } + + //! The "malloc" analogue to allocate block of memory of size bytes + void *malloc(size_t size) { return rml::pool_malloc(my_pool, size); } + + //! The "free" analogue to discard a previously allocated piece of memory. + void free(void* ptr) { rml::pool_free(my_pool, ptr); } + + //! The "realloc" analogue complementing pool_malloc. + // Enables some low-level optimization possibilities + void *realloc(void* ptr, size_t size) { + return rml::pool_realloc(my_pool, ptr, size); + } + +protected: + //! destroy pool - must be called in a child class + void destroy() { rml::pool_destroy(my_pool); } + + rml::MemoryPool *my_pool; +}; + +} // namespace internal +//! @endcond + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // Workaround for erroneous "unreferenced parameter" warning in method destroy. + #pragma warning (push) + #pragma warning (disable: 4100) +#endif + +//! Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5 +/** @ingroup memory_allocation */ +template +class memory_pool_allocator { +protected: + typedef P pool_type; + pool_type *my_pool; + template + friend class memory_pool_allocator; + template + friend bool operator==( const memory_pool_allocator& a, const memory_pool_allocator& b); + template + friend bool operator!=( const memory_pool_allocator& a, const memory_pool_allocator& b); +public: + typedef typename tbb::internal::allocator_type::value_type value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + template struct rebind { + typedef memory_pool_allocator other; + }; + + memory_pool_allocator(pool_type &pool) throw() : my_pool(&pool) {} + memory_pool_allocator(const memory_pool_allocator& src) throw() : my_pool(src.my_pool) {} + template + memory_pool_allocator(const memory_pool_allocator& src) throw() : my_pool(src.my_pool) {} + + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } + + //! Allocate space for n objects. + pointer allocate( size_type n, const void* /*hint*/ = 0) { + return static_cast( my_pool->malloc( n*sizeof(value_type) ) ); + } + //! Free previously allocated block of memory. + void deallocate( pointer p, size_type ) { + my_pool->free(p); + } + //! Largest value for which method allocate might succeed. + size_type max_size() const throw() { + size_type max = static_cast(-1) / sizeof (value_type); + return (max > 0 ? max : 1); + } + //! Copy-construct value at location pointed to by p. +#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT + template + void construct(pointer p, Args&&... args) + #if __TBB_CPP11_STD_FORWARD_BROKEN + { ::new((void *)p) T((args)...); } + #else + { ::new((void *)p) T(std::forward(args)...); } + #endif +#else // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT + void construct( pointer p, const value_type& value ) { ::new((void*)(p)) value_type(value); } +#endif // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT + + //! Destroy value at location pointed to by p. + void destroy( pointer p ) { p->~value_type(); } + +}; + +#if _MSC_VER && !defined(__INTEL_COMPILER) + #pragma warning (pop) +#endif // warning 4100 is back + +//! Analogous to std::allocator, as defined in ISO C++ Standard, Section 20.4.1 +/** @ingroup memory_allocation */ +template +class memory_pool_allocator { +public: + typedef P pool_type; + typedef void* pointer; + typedef const void* const_pointer; + typedef void value_type; + template struct rebind { + typedef memory_pool_allocator other; + }; + + memory_pool_allocator( pool_type &pool) throw() : my_pool(&pool) {} + memory_pool_allocator( const memory_pool_allocator& src) throw() : my_pool(src.my_pool) {} + template + memory_pool_allocator(const memory_pool_allocator& src) throw() : my_pool(src.my_pool) {} + +protected: + pool_type *my_pool; + template + friend class memory_pool_allocator; + template + friend bool operator==( const memory_pool_allocator& a, const memory_pool_allocator& b); + template + friend bool operator!=( const memory_pool_allocator& a, const memory_pool_allocator& b); +}; + +template +inline bool operator==( const memory_pool_allocator& a, const memory_pool_allocator& b) {return a.my_pool==b.my_pool;} + +template +inline bool operator!=( const memory_pool_allocator& a, const memory_pool_allocator& b) {return a.my_pool!=b.my_pool;} + + +//! Thread-safe growable pool allocator for variable-size requests +template +class memory_pool : public internal::pool_base { + Alloc my_alloc; // TODO: base-class optimization + static void *allocate_request(intptr_t pool_id, size_t & bytes); + static int deallocate_request(intptr_t pool_id, void*, size_t raw_bytes); + +public: + //! construct pool with underlying allocator + memory_pool(const Alloc &src = Alloc()); + + //! destroy pool + ~memory_pool() { destroy(); } // call the callbacks first and destroy my_alloc latter + +}; + +class fixed_pool : public internal::pool_base { + void *my_buffer; + size_t my_size; + inline static void *allocate_request(intptr_t pool_id, size_t & bytes); + +public: + //! construct pool with underlying allocator + inline fixed_pool(void *buf, size_t size); + //! destroy pool + ~fixed_pool() { destroy(); } +}; + +//////////////// Implementation /////////////// + +template +memory_pool::memory_pool(const Alloc &src) : my_alloc(src) { + rml::MemPoolPolicy args(allocate_request, deallocate_request, + sizeof(typename Alloc::value_type)); + rml::MemPoolError res = rml::pool_create_v1(intptr_t(this), &args, &my_pool); + if( res!=rml::POOL_OK ) __TBB_THROW(std::bad_alloc()); +} +template +void *memory_pool::allocate_request(intptr_t pool_id, size_t & bytes) { + memory_pool &self = *reinterpret_cast*>(pool_id); + const size_t unit_size = sizeof(typename Alloc::value_type); + __TBBMALLOC_ASSERT( 0 == bytes%unit_size, NULL); + void *ptr; + __TBB_TRY { ptr = self.my_alloc.allocate( bytes/unit_size ); } + __TBB_CATCH(...) { return 0; } + return ptr; +} +template +int memory_pool::deallocate_request(intptr_t pool_id, void* raw_ptr, size_t raw_bytes) { + memory_pool &self = *reinterpret_cast*>(pool_id); + const size_t unit_size = sizeof(typename Alloc::value_type); + __TBBMALLOC_ASSERT( 0 == raw_bytes%unit_size, NULL); + self.my_alloc.deallocate( static_cast(raw_ptr), raw_bytes/unit_size ); + return 0; +} +inline fixed_pool::fixed_pool(void *buf, size_t size) : my_buffer(buf), my_size(size) { + rml::MemPoolPolicy args(allocate_request, 0, size, /*fixedPool=*/true); + rml::MemPoolError res = rml::pool_create_v1(intptr_t(this), &args, &my_pool); + if( res!=rml::POOL_OK ) __TBB_THROW(std::bad_alloc()); +} +inline void *fixed_pool::allocate_request(intptr_t pool_id, size_t & bytes) { + fixed_pool &self = *reinterpret_cast(pool_id); + if( !__TBB_CompareAndSwapW(&self.my_size, 0, (bytes=self.my_size)) ) + return 0; // all the memory was given already + return self.my_buffer; +} + +} //namespace interface6 +using interface6::memory_pool_allocator; +using interface6::memory_pool; +using interface6::fixed_pool; +} //namespace tbb + +#undef __TBBMALLOC_ASSERT +#endif// __TBB_memory_pool_H diff --git a/src/tbb/include/tbb/mutex.h b/src/tbb/include/tbb/mutex.h new file mode 100644 index 0000000..3dc0a7c --- /dev/null +++ b/src/tbb/include/tbb/mutex.h @@ -0,0 +1,240 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_mutex_H +#define __TBB_mutex_H + +#if _WIN32||_WIN64 +#include "machine/windows_api.h" +#else +#include +#endif /* _WIN32||_WIN64 */ + +#include +#include "aligned_space.h" +#include "tbb_stddef.h" +#include "tbb_profiling.h" + +namespace tbb { + +//! Wrapper around the platform's native reader-writer lock. +/** For testing purposes only. + @ingroup synchronization */ +class mutex { +public: + //! Construct unacquired mutex. + mutex() { +#if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS + internal_construct(); +#else + #if _WIN32||_WIN64 + InitializeCriticalSection(&impl); + #else + int error_code = pthread_mutex_init(&impl,NULL); + if( error_code ) + tbb::internal::handle_perror(error_code,"mutex: pthread_mutex_init failed"); + #endif /* _WIN32||_WIN64*/ +#endif /* TBB_USE_ASSERT */ + }; + + ~mutex() { +#if TBB_USE_ASSERT + internal_destroy(); +#else + #if _WIN32||_WIN64 + DeleteCriticalSection(&impl); + #else + pthread_mutex_destroy(&impl); + + #endif /* _WIN32||_WIN64 */ +#endif /* TBB_USE_ASSERT */ + }; + + class scoped_lock; + friend class scoped_lock; + + //! The scoped locking pattern + /** It helps to avoid the common problem of forgetting to release lock. + It also nicely provides the "node" for queuing locks. */ + class scoped_lock : internal::no_copy { + public: + //! Construct lock that has not acquired a mutex. + scoped_lock() : my_mutex(NULL) {}; + + //! Acquire lock on given mutex. + scoped_lock( mutex& mutex ) { + acquire( mutex ); + } + + //! Release lock (if lock is held). + ~scoped_lock() { + if( my_mutex ) + release(); + } + + //! Acquire lock on given mutex. + void acquire( mutex& mutex ) { +#if TBB_USE_ASSERT + internal_acquire(mutex); +#else + mutex.lock(); + my_mutex = &mutex; +#endif /* TBB_USE_ASSERT */ + } + + //! Try acquire lock on given mutex. + bool try_acquire( mutex& mutex ) { +#if TBB_USE_ASSERT + return internal_try_acquire (mutex); +#else + bool result = mutex.try_lock(); + if( result ) + my_mutex = &mutex; + return result; +#endif /* TBB_USE_ASSERT */ + } + + //! Release lock + void release() { +#if TBB_USE_ASSERT + internal_release (); +#else + my_mutex->unlock(); + my_mutex = NULL; +#endif /* TBB_USE_ASSERT */ + } + + private: + //! The pointer to the current mutex to work + mutex* my_mutex; + + //! All checks from acquire using mutex.state were moved here + void __TBB_EXPORTED_METHOD internal_acquire( mutex& m ); + + //! All checks from try_acquire using mutex.state were moved here + bool __TBB_EXPORTED_METHOD internal_try_acquire( mutex& m ); + + //! All checks from release using mutex.state were moved here + void __TBB_EXPORTED_METHOD internal_release(); + + friend class mutex; + }; + + // Mutex traits + static const bool is_rw_mutex = false; + static const bool is_recursive_mutex = false; + static const bool is_fair_mutex = false; + + // ISO C++0x compatibility methods + + //! Acquire lock + void lock() { +#if TBB_USE_ASSERT + aligned_space tmp; + new(tmp.begin()) scoped_lock(*this); +#else + #if _WIN32||_WIN64 + EnterCriticalSection(&impl); + #else + pthread_mutex_lock(&impl); + #endif /* _WIN32||_WIN64 */ +#endif /* TBB_USE_ASSERT */ + } + + //! Try acquiring lock (non-blocking) + /** Return true if lock acquired; false otherwise. */ + bool try_lock() { +#if TBB_USE_ASSERT + aligned_space tmp; + scoped_lock& s = *tmp.begin(); + s.my_mutex = NULL; + return s.internal_try_acquire(*this); +#else + #if _WIN32||_WIN64 + return TryEnterCriticalSection(&impl)!=0; + #else + return pthread_mutex_trylock(&impl)==0; + #endif /* _WIN32||_WIN64 */ +#endif /* TBB_USE_ASSERT */ + } + + //! Release lock + void unlock() { +#if TBB_USE_ASSERT + aligned_space tmp; + scoped_lock& s = *tmp.begin(); + s.my_mutex = this; + s.internal_release(); +#else + #if _WIN32||_WIN64 + LeaveCriticalSection(&impl); + #else + pthread_mutex_unlock(&impl); + #endif /* _WIN32||_WIN64 */ +#endif /* TBB_USE_ASSERT */ + } + + //! Return native_handle + #if _WIN32||_WIN64 + typedef LPCRITICAL_SECTION native_handle_type; + #else + typedef pthread_mutex_t* native_handle_type; + #endif + native_handle_type native_handle() { return (native_handle_type) &impl; } + + enum state_t { + INITIALIZED=0x1234, + DESTROYED=0x789A, + HELD=0x56CD + }; +private: +#if _WIN32||_WIN64 + CRITICAL_SECTION impl; + enum state_t state; +#else + pthread_mutex_t impl; +#endif /* _WIN32||_WIN64 */ + + //! All checks from mutex constructor using mutex.state were moved here + void __TBB_EXPORTED_METHOD internal_construct(); + + //! All checks from mutex destructor using mutex.state were moved here + void __TBB_EXPORTED_METHOD internal_destroy(); + +#if _WIN32||_WIN64 +public: + //! Set the internal state + void set_state( state_t to ) { state = to; } +#endif +}; + +__TBB_DEFINE_PROFILING_SET_NAME(mutex) + +} // namespace tbb + +#endif /* __TBB_mutex_H */ diff --git a/src/tbb/include/tbb/null_mutex.h b/src/tbb/include/tbb/null_mutex.h new file mode 100644 index 0000000..ac73657 --- /dev/null +++ b/src/tbb/include/tbb/null_mutex.h @@ -0,0 +1,63 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_null_mutex_H +#define __TBB_null_mutex_H + +namespace tbb { + +//! A mutex which does nothing +/** A null_mutex does no operation and simulates success. + @ingroup synchronization */ +class null_mutex { + //! Deny assignment and copy construction + null_mutex( const null_mutex& ); + void operator=( const null_mutex& ); +public: + //! Represents acquisition of a mutex. + class scoped_lock { + public: + scoped_lock() {} + scoped_lock( null_mutex& ) {} + ~scoped_lock() {} + void acquire( null_mutex& ) {} + bool try_acquire( null_mutex& ) { return true; } + void release() {} + }; + + null_mutex() {} + + // Mutex traits + static const bool is_rw_mutex = false; + static const bool is_recursive_mutex = true; + static const bool is_fair_mutex = true; +}; + +} + +#endif /* __TBB_null_mutex_H */ diff --git a/src/tbb/include/tbb/null_rw_mutex.h b/src/tbb/include/tbb/null_rw_mutex.h new file mode 100644 index 0000000..4f08bbf --- /dev/null +++ b/src/tbb/include/tbb/null_rw_mutex.h @@ -0,0 +1,65 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_null_rw_mutex_H +#define __TBB_null_rw_mutex_H + +namespace tbb { + +//! A rw mutex which does nothing +/** A null_rw_mutex is a rw mutex that does nothing and simulates successful operation. + @ingroup synchronization */ +class null_rw_mutex { + //! Deny assignment and copy construction + null_rw_mutex( const null_rw_mutex& ); + void operator=( const null_rw_mutex& ); +public: + //! Represents acquisition of a mutex. + class scoped_lock { + public: + scoped_lock() {} + scoped_lock( null_rw_mutex& , bool = true ) {} + ~scoped_lock() {} + void acquire( null_rw_mutex& , bool = true ) {} + bool upgrade_to_writer() { return true; } + bool downgrade_to_reader() { return true; } + bool try_acquire( null_rw_mutex& , bool = true ) { return true; } + void release() {} + }; + + null_rw_mutex() {} + + // Mutex traits + static const bool is_rw_mutex = true; + static const bool is_recursive_mutex = true; + static const bool is_fair_mutex = true; +}; + +} + +#endif /* __TBB_null_rw_mutex_H */ diff --git a/src/tbb/include/tbb/parallel_do.h b/src/tbb/include/tbb/parallel_do.h new file mode 100644 index 0000000..0d33964 --- /dev/null +++ b/src/tbb/include/tbb/parallel_do.h @@ -0,0 +1,508 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_parallel_do_H +#define __TBB_parallel_do_H + +#include "task.h" +#include "aligned_space.h" +#include + +namespace tbb { + +//! @cond INTERNAL +namespace internal { + template class parallel_do_feeder_impl; + template class do_group_task; + + //! Strips its template type argument from 'cv' and '&' qualifiers + template + struct strip { typedef T type; }; + template + struct strip { typedef T type; }; + template + struct strip { typedef T type; }; + template + struct strip { typedef T type; }; + template + struct strip { typedef T type; }; + // Most of the compilers remove cv-qualifiers from non-reference function argument types. + // But unfortunately there are those that don't. + template + struct strip { typedef T type; }; + template + struct strip { typedef T type; }; + template + struct strip { typedef T type; }; +} // namespace internal +//! @endcond + +//! Class the user supplied algorithm body uses to add new tasks +/** \param Item Work item type **/ +template +class parallel_do_feeder: internal::no_copy +{ + parallel_do_feeder() {} + virtual ~parallel_do_feeder () {} + virtual void internal_add( const Item& item ) = 0; + template friend class internal::parallel_do_feeder_impl; +public: + //! Add a work item to a running parallel_do. + void add( const Item& item ) {internal_add(item);} +}; + +//! @cond INTERNAL +namespace internal { + //! For internal use only. + /** Selects one of the two possible forms of function call member operator. + @ingroup algorithms **/ + template + class parallel_do_operator_selector + { + typedef parallel_do_feeder Feeder; + template + static void internal_call( const Body& obj, A1& arg1, A2&, void (Body::*)(CvItem) const ) { + obj(arg1); + } + template + static void internal_call( const Body& obj, A1& arg1, A2& arg2, void (Body::*)(CvItem, parallel_do_feeder&) const ) { + obj(arg1, arg2); + } + + public: + template + static void call( const Body& obj, A1& arg1, A2& arg2 ) + { + internal_call( obj, arg1, arg2, &Body::operator() ); + } + }; + + //! For internal use only. + /** Executes one iteration of a do. + @ingroup algorithms */ + template + class do_iteration_task: public task + { + typedef parallel_do_feeder_impl feeder_type; + + Item my_value; + feeder_type& my_feeder; + + do_iteration_task( const Item& value, feeder_type& feeder ) : + my_value(value), my_feeder(feeder) + {} + + /*override*/ + task* execute() + { + parallel_do_operator_selector::call(*my_feeder.my_body, my_value, my_feeder); + return NULL; + } + + template friend class parallel_do_feeder_impl; + }; // class do_iteration_task + + template + class do_iteration_task_iter: public task + { + typedef parallel_do_feeder_impl feeder_type; + + Iterator my_iter; + feeder_type& my_feeder; + + do_iteration_task_iter( const Iterator& iter, feeder_type& feeder ) : + my_iter(iter), my_feeder(feeder) + {} + + /*override*/ + task* execute() + { + parallel_do_operator_selector::call(*my_feeder.my_body, *my_iter, my_feeder); + return NULL; + } + + template friend class do_group_task_forward; + template friend class do_group_task_input; + template friend class do_task_iter; + }; // class do_iteration_task_iter + + //! For internal use only. + /** Implements new task adding procedure. + @ingroup algorithms **/ + template + class parallel_do_feeder_impl : public parallel_do_feeder + { + /*override*/ + void internal_add( const Item& item ) + { + typedef do_iteration_task iteration_type; + + iteration_type& t = *new (task::allocate_additional_child_of(*my_barrier)) iteration_type(item, *this); + + t.spawn( t ); + } + public: + const Body* my_body; + empty_task* my_barrier; + + parallel_do_feeder_impl() + { + my_barrier = new( task::allocate_root() ) empty_task(); + __TBB_ASSERT(my_barrier, "root task allocation failed"); + } + +#if __TBB_TASK_GROUP_CONTEXT + parallel_do_feeder_impl(tbb::task_group_context &context) + { + my_barrier = new( task::allocate_root(context) ) empty_task(); + __TBB_ASSERT(my_barrier, "root task allocation failed"); + } +#endif + + ~parallel_do_feeder_impl() + { + my_barrier->destroy(*my_barrier); + } + }; // class parallel_do_feeder_impl + + + //! For internal use only + /** Unpacks a block of iterations. + @ingroup algorithms */ + + template + class do_group_task_forward: public task + { + static const size_t max_arg_size = 4; + + typedef parallel_do_feeder_impl feeder_type; + + feeder_type& my_feeder; + Iterator my_first; + size_t my_size; + + do_group_task_forward( Iterator first, size_t size, feeder_type& feeder ) + : my_feeder(feeder), my_first(first), my_size(size) + {} + + /*override*/ task* execute() + { + typedef do_iteration_task_iter iteration_type; + __TBB_ASSERT( my_size>0, NULL ); + task_list list; + task* t; + size_t k=0; + for(;;) { + t = new( allocate_child() ) iteration_type( my_first, my_feeder ); + ++my_first; + if( ++k==my_size ) break; + list.push_back(*t); + } + set_ref_count(int(k+1)); + spawn(list); + spawn_and_wait_for_all(*t); + return NULL; + } + + template friend class do_task_iter; + }; // class do_group_task_forward + + template + class do_group_task_input: public task + { + static const size_t max_arg_size = 4; + + typedef parallel_do_feeder_impl feeder_type; + + feeder_type& my_feeder; + size_t my_size; + aligned_space my_arg; + + do_group_task_input( feeder_type& feeder ) + : my_feeder(feeder), my_size(0) + {} + + /*override*/ task* execute() + { + typedef do_iteration_task_iter iteration_type; + __TBB_ASSERT( my_size>0, NULL ); + task_list list; + task* t; + size_t k=0; + for(;;) { + t = new( allocate_child() ) iteration_type( my_arg.begin() + k, my_feeder ); + if( ++k==my_size ) break; + list.push_back(*t); + } + set_ref_count(int(k+1)); + spawn(list); + spawn_and_wait_for_all(*t); + return NULL; + } + + ~do_group_task_input(){ + for( size_t k=0; k~Item(); + } + + template friend class do_task_iter; + }; // class do_group_task_input + + //! For internal use only. + /** Gets block of iterations and packages them into a do_group_task. + @ingroup algorithms */ + template + class do_task_iter: public task + { + typedef parallel_do_feeder_impl feeder_type; + + public: + do_task_iter( Iterator first, Iterator last , feeder_type& feeder ) : + my_first(first), my_last(last), my_feeder(feeder) + {} + + private: + Iterator my_first; + Iterator my_last; + feeder_type& my_feeder; + + /* Do not merge run(xxx) and run_xxx() methods. They are separated in order + to make sure that compilers will eliminate unused argument of type xxx + (that is will not put it on stack). The sole purpose of this argument + is overload resolution. + + An alternative could be using template functions, but explicit specialization + of member function templates is not supported for non specialized class + templates. Besides template functions would always fall back to the least + efficient variant (the one for input iterators) in case of iterators having + custom tags derived from basic ones. */ + /*override*/ task* execute() + { + typedef typename std::iterator_traits::iterator_category iterator_tag; + return run( (iterator_tag*)NULL ); + } + + /** This is the most restricted variant that operates on input iterators or + iterators with unknown tags (tags not derived from the standard ones). **/ + inline task* run( void* ) { return run_for_input_iterator(); } + + task* run_for_input_iterator() { + typedef do_group_task_input block_type; + + block_type& t = *new( allocate_additional_child_of(*my_feeder.my_barrier) ) block_type(my_feeder); + size_t k=0; + while( !(my_first == my_last) ) { + new (t.my_arg.begin() + k) Item(*my_first); + ++my_first; + if( ++k==block_type::max_arg_size ) { + if ( !(my_first == my_last) ) + recycle_to_reexecute(); + break; + } + } + if( k==0 ) { + destroy(t); + return NULL; + } else { + t.my_size = k; + return &t; + } + } + + inline task* run( std::forward_iterator_tag* ) { return run_for_forward_iterator(); } + + task* run_for_forward_iterator() { + typedef do_group_task_forward block_type; + + Iterator first = my_first; + size_t k=0; + while( !(my_first==my_last) ) { + ++my_first; + if( ++k==block_type::max_arg_size ) { + if ( !(my_first==my_last) ) + recycle_to_reexecute(); + break; + } + } + return k==0 ? NULL : new( allocate_additional_child_of(*my_feeder.my_barrier) ) block_type(first, k, my_feeder); + } + + inline task* run( std::random_access_iterator_tag* ) { return run_for_random_access_iterator(); } + + task* run_for_random_access_iterator() { + typedef do_group_task_forward block_type; + typedef do_iteration_task_iter iteration_type; + + size_t k = static_cast(my_last-my_first); + if( k > block_type::max_arg_size ) { + Iterator middle = my_first + k/2; + + empty_task& c = *new( allocate_continuation() ) empty_task; + do_task_iter& b = *new( c.allocate_child() ) do_task_iter(middle, my_last, my_feeder); + recycle_as_child_of(c); + + my_last = middle; + c.set_ref_count(2); + c.spawn(b); + return this; + }else if( k != 0 ) { + task_list list; + task* t; + size_t k1=0; + for(;;) { + t = new( allocate_child() ) iteration_type(my_first, my_feeder); + ++my_first; + if( ++k1==k ) break; + list.push_back(*t); + } + set_ref_count(int(k+1)); + spawn(list); + spawn_and_wait_for_all(*t); + } + return NULL; + } + }; // class do_task_iter + + //! For internal use only. + /** Implements parallel iteration over a range. + @ingroup algorithms */ + template + void run_parallel_do( Iterator first, Iterator last, const Body& body +#if __TBB_TASK_GROUP_CONTEXT + , task_group_context& context +#endif + ) + { + typedef do_task_iter root_iteration_task; +#if __TBB_TASK_GROUP_CONTEXT + parallel_do_feeder_impl feeder(context); +#else + parallel_do_feeder_impl feeder; +#endif + feeder.my_body = &body; + + root_iteration_task &t = *new( feeder.my_barrier->allocate_child() ) root_iteration_task(first, last, feeder); + + feeder.my_barrier->set_ref_count(2); + feeder.my_barrier->spawn_and_wait_for_all(t); + } + + //! For internal use only. + /** Detects types of Body's operator function arguments. + @ingroup algorithms **/ + template + void select_parallel_do( Iterator first, Iterator last, const Body& body, void (Body::*)(Item) const +#if __TBB_TASK_GROUP_CONTEXT + , task_group_context& context +#endif // __TBB_TASK_GROUP_CONTEXT + ) + { + run_parallel_do::type>( first, last, body +#if __TBB_TASK_GROUP_CONTEXT + , context +#endif // __TBB_TASK_GROUP_CONTEXT + ); + } + + //! For internal use only. + /** Detects types of Body's operator function arguments. + @ingroup algorithms **/ + template + void select_parallel_do( Iterator first, Iterator last, const Body& body, void (Body::*)(Item, parallel_do_feeder<_Item>&) const +#if __TBB_TASK_GROUP_CONTEXT + , task_group_context& context +#endif // __TBB_TASK_GROUP_CONTEXT + ) + { + run_parallel_do::type>( first, last, body +#if __TBB_TASK_GROUP_CONTEXT + , context +#endif // __TBB_TASK_GROUP_CONTEXT + ); + } + +} // namespace internal +//! @endcond + + +/** \page parallel_do_body_req Requirements on parallel_do body + Class \c Body implementing the concept of parallel_do body must define: + - \code + B::operator()( + cv_item_type item, + parallel_do_feeder& feeder + ) const + + OR + + B::operator()( cv_item_type& item ) const + \endcode Process item. + May be invoked concurrently for the same \c this but different \c item. + + - \code item_type( const item_type& ) \endcode + Copy a work item. + - \code ~item_type() \endcode Destroy a work item +**/ + +/** \name parallel_do + See also requirements on \ref parallel_do_body_req "parallel_do Body". **/ +//@{ +//! Parallel iteration over a range, with optional addition of more work. +/** @ingroup algorithms */ +template +void parallel_do( Iterator first, Iterator last, const Body& body ) +{ + if ( first == last ) + return; +#if __TBB_TASK_GROUP_CONTEXT + task_group_context context; +#endif // __TBB_TASK_GROUP_CONTEXT + internal::select_parallel_do( first, last, body, &Body::operator() +#if __TBB_TASK_GROUP_CONTEXT + , context +#endif // __TBB_TASK_GROUP_CONTEXT + ); +} + +#if __TBB_TASK_GROUP_CONTEXT +//! Parallel iteration over a range, with optional addition of more work and user-supplied context +/** @ingroup algorithms */ +template +void parallel_do( Iterator first, Iterator last, const Body& body, task_group_context& context ) +{ + if ( first == last ) + return; + internal::select_parallel_do( first, last, body, &Body::operator(), context ); +} +#endif // __TBB_TASK_GROUP_CONTEXT + +//@} + +} // namespace + +#endif /* __TBB_parallel_do_H */ diff --git a/src/tbb/include/tbb/parallel_for.h b/src/tbb/include/tbb/parallel_for.h new file mode 100644 index 0000000..bc32778 --- /dev/null +++ b/src/tbb/include/tbb/parallel_for.h @@ -0,0 +1,267 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_parallel_for_H +#define __TBB_parallel_for_H + +#include +#include "task.h" +#include "partitioner.h" +#include "blocked_range.h" +#include "tbb_exception.h" + +namespace tbb { + +namespace interface6 { +//! @cond INTERNAL +namespace internal { + + //! Task type used in parallel_for + /** @ingroup algorithms */ + template + class start_for: public task { + Range my_range; + const Body my_body; + typename Partitioner::task_partition_type my_partition; + /*override*/ task* execute(); + + public: + //! Constructor for root task. + start_for( const Range& range, const Body& body, Partitioner& partitioner ) : + my_range(range), + my_body(body), + my_partition(partitioner) + { + } + //! Splitting constructor used to generate children. + /** parent_ becomes left child. Newly constructed object is right child. */ + start_for( start_for& parent_, split ) : + my_range(parent_.my_range,split()), + my_body(parent_.my_body), + my_partition(parent_.my_partition, split()) + { + my_partition.set_affinity(*this); + } + //! Construct right child from the given range as response to the demand. + /** parent_ remains left child. Newly constructed object is right child. */ + start_for( start_for& parent_, const Range& r, depth_t d ) : + my_range(r), + my_body(parent_.my_body), + my_partition(parent_.my_partition,split()) + { + my_partition.set_affinity(*this); + my_partition.align_depth( d ); + } + //! Update affinity info, if any. + /*override*/ void note_affinity( affinity_id id ) { + my_partition.note_affinity( id ); + } + static void run( const Range& range, const Body& body, const Partitioner& partitioner ) { + if( !range.empty() ) { +#if !__TBB_TASK_GROUP_CONTEXT || TBB_JOIN_OUTER_TASK_GROUP + start_for& a = *new(task::allocate_root()) start_for(range,body,const_cast(partitioner)); +#else + // Bound context prevents exceptions from body to affect nesting or sibling algorithms, + // and allows users to handle exceptions safely by wrapping parallel_for in the try-block. + task_group_context context; + start_for& a = *new(task::allocate_root(context)) start_for(range,body,const_cast(partitioner)); +#endif /* __TBB_TASK_GROUP_CONTEXT && !TBB_JOIN_OUTER_TASK_GROUP */ + task::spawn_root_and_wait(a); + } + } +#if __TBB_TASK_GROUP_CONTEXT + static void run( const Range& range, const Body& body, const Partitioner& partitioner, task_group_context& context ) { + if( !range.empty() ) { + start_for& a = *new(task::allocate_root(context)) start_for(range,body,const_cast(partitioner)); + task::spawn_root_and_wait(a); + } + } +#endif /* __TBB_TASK_GROUP_CONTEXT */ + //! create a continuation task, serve as callback for partitioner + flag_task *create_continuation() { + return new( allocate_continuation() ) flag_task(); + } + //! Run body for range + void run_body( Range &r ) { my_body( r ); } + }; + + template + task* start_for::execute() { + my_partition.check_being_stolen( *this ); + my_partition.execute(*this, my_range); + return NULL; + } +} // namespace internal +//! @endcond +} // namespace interfaceX + +//! @cond INTERNAL +namespace internal { + using interface6::internal::start_for; + + //! Calls the function with values from range [begin, end) with a step provided + template + class parallel_for_body : internal::no_assign { + const Function &my_func; + const Index my_begin; + const Index my_step; + public: + parallel_for_body( const Function& _func, Index& _begin, Index& _step) + : my_func(_func), my_begin(_begin), my_step(_step) {} + + void operator()( tbb::blocked_range& r ) const { + for( Index i = r.begin(), k = my_begin + i * my_step; i < r.end(); i++, k = k + my_step) + my_func( k ); + } + }; +} // namespace internal +//! @endcond + +// Requirements on Range concept are documented in blocked_range.h + +/** \page parallel_for_body_req Requirements on parallel_for body + Class \c Body implementing the concept of parallel_for body must define: + - \code Body::Body( const Body& ); \endcode Copy constructor + - \code Body::~Body(); \endcode Destructor + - \code void Body::operator()( Range& r ) const; \endcode Function call operator applying the body to range \c r. +**/ + +/** \name parallel_for + See also requirements on \ref range_req "Range" and \ref parallel_for_body_req "parallel_for Body". **/ +//@{ + +//! Parallel iteration over range with default partitioner. +/** @ingroup algorithms **/ +template +void parallel_for( const Range& range, const Body& body ) { + internal::start_for::run(range,body,__TBB_DEFAULT_PARTITIONER()); +} + +//! Parallel iteration over range with simple partitioner. +/** @ingroup algorithms **/ +template +void parallel_for( const Range& range, const Body& body, const simple_partitioner& partitioner ) { + internal::start_for::run(range,body,partitioner); +} + +//! Parallel iteration over range with auto_partitioner. +/** @ingroup algorithms **/ +template +void parallel_for( const Range& range, const Body& body, const auto_partitioner& partitioner ) { + internal::start_for::run(range,body,partitioner); +} + +//! Parallel iteration over range with affinity_partitioner. +/** @ingroup algorithms **/ +template +void parallel_for( const Range& range, const Body& body, affinity_partitioner& partitioner ) { + internal::start_for::run(range,body,partitioner); +} + +#if __TBB_TASK_GROUP_CONTEXT +//! Parallel iteration over range with simple partitioner and user-supplied context. +/** @ingroup algorithms **/ +template +void parallel_for( const Range& range, const Body& body, const simple_partitioner& partitioner, task_group_context& context ) { + internal::start_for::run(range, body, partitioner, context); +} + +//! Parallel iteration over range with auto_partitioner and user-supplied context. +/** @ingroup algorithms **/ +template +void parallel_for( const Range& range, const Body& body, const auto_partitioner& partitioner, task_group_context& context ) { + internal::start_for::run(range, body, partitioner, context); +} + +//! Parallel iteration over range with affinity_partitioner and user-supplied context. +/** @ingroup algorithms **/ +template +void parallel_for( const Range& range, const Body& body, affinity_partitioner& partitioner, task_group_context& context ) { + internal::start_for::run(range,body,partitioner, context); +} +#endif /* __TBB_TASK_GROUP_CONTEXT */ +//@} + +namespace strict_ppl { + +//@{ +//! Parallel iteration over a range of integers with a step provided +template +void parallel_for(Index first, Index last, Index step, const Function& f) { + if (step <= 0 ) + internal::throw_exception(internal::eid_nonpositive_step); // throws std::invalid_argument + else if (last > first) { + // Above "else" avoids "potential divide by zero" warning on some platforms + Index end = (last - first - Index(1)) / step + Index(1); + tbb::blocked_range range(static_cast(0), end); + internal::parallel_for_body body(f, first, step); + tbb::parallel_for(range, body, tbb::auto_partitioner()); + } +} +//! Parallel iteration over a range of integers with a default step value +template +void parallel_for(Index first, Index last, const Function& f) { + parallel_for(first, last, static_cast(1), f); +} + +#if __TBB_TASK_GROUP_CONTEXT +//! Parallel iteration over a range of integers with explicit step and task group context +template +void parallel_for(Index first, Index last, Index step, const Function& f, tbb::task_group_context &context) { + if (step <= 0 ) + internal::throw_exception(internal::eid_nonpositive_step); // throws std::invalid_argument + else if (last > first) { + // Above "else" avoids "potential divide by zero" warning on some platforms + Index end = (last - first - Index(1)) / step + Index(1); + tbb::blocked_range range(static_cast(0), end); + internal::parallel_for_body body(f, first, step); + tbb::parallel_for(range, body, tbb::auto_partitioner(), context); + } +} +//! Parallel iteration over a range of integers with a default step value and explicit task group context +template +void parallel_for(Index first, Index last, const Function& f, tbb::task_group_context &context) { + parallel_for(first, last, static_cast(1), f, context); +} +#endif /* __TBB_TASK_GROUP_CONTEXT */ +//@} + +} // namespace strict_ppl + +using strict_ppl::parallel_for; + +} // namespace tbb + +#if TBB_PREVIEW_SERIAL_SUBSET +#define __TBB_NORMAL_EXECUTION +#include "../serial/tbb/parallel_for.h" +#undef __TBB_NORMAL_EXECUTION +#endif + +#endif /* __TBB_parallel_for_H */ + diff --git a/src/tbb/include/tbb/parallel_for_each.h b/src/tbb/include/tbb/parallel_for_each.h new file mode 100644 index 0000000..3495a50 --- /dev/null +++ b/src/tbb/include/tbb/parallel_for_each.h @@ -0,0 +1,77 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_parallel_for_each_H +#define __TBB_parallel_for_each_H + +#include "parallel_do.h" + +namespace tbb { + +//! @cond INTERNAL +namespace internal { + // The class calls user function in operator() + template + class parallel_for_each_body : internal::no_assign { + const Function &my_func; + public: + parallel_for_each_body(const Function &_func) : my_func(_func) {} + parallel_for_each_body(const parallel_for_each_body &_caller) : my_func(_caller.my_func) {} + + void operator() ( typename std::iterator_traits::reference value ) const { + my_func(value); + } + }; +} // namespace internal +//! @endcond + +/** \name parallel_for_each + **/ +//@{ +//! Calls function f for all items from [first, last) interval using user-supplied context +/** @ingroup algorithms */ +#if __TBB_TASK_GROUP_CONTEXT +template +void parallel_for_each(InputIterator first, InputIterator last, const Function& f, task_group_context &context) { + internal::parallel_for_each_body body(f); + tbb::parallel_do (first, last, body, context); +} +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +//! Uses default context +template +void parallel_for_each(InputIterator first, InputIterator last, const Function& f) { + internal::parallel_for_each_body body(f); + tbb::parallel_do (first, last, body); +} + +//@} + +} // namespace + +#endif /* __TBB_parallel_for_each_H */ diff --git a/src/tbb/include/tbb/parallel_invoke.h b/src/tbb/include/tbb/parallel_invoke.h new file mode 100644 index 0000000..f56cc62 --- /dev/null +++ b/src/tbb/include/tbb/parallel_invoke.h @@ -0,0 +1,371 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_parallel_invoke_H +#define __TBB_parallel_invoke_H + +#include "task.h" + +namespace tbb { + +#if !__TBB_TASK_GROUP_CONTEXT + /** Dummy to avoid cluttering the bulk of the header with enormous amount of ifdefs. **/ + struct task_group_context {}; +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +//! @cond INTERNAL +namespace internal { + // Simple task object, executing user method + template + class function_invoker : public task{ + public: + function_invoker(const function& _function) : my_function(_function) {} + private: + const function &my_function; + /*override*/ + task* execute() + { + my_function(); + return NULL; + } + }; + + // The class spawns two or three child tasks + template + class spawner : public task { + private: + const function1& my_func1; + const function2& my_func2; + const function3& my_func3; + bool is_recycled; + + task* execute (){ + if(is_recycled){ + return NULL; + }else{ + __TBB_ASSERT(N==2 || N==3, "Number of arguments passed to spawner is wrong"); + set_ref_count(N); + recycle_as_safe_continuation(); + internal::function_invoker* invoker2 = new (allocate_child()) internal::function_invoker(my_func2); + __TBB_ASSERT(invoker2, "Child task allocation failed"); + spawn(*invoker2); + size_t n = N; // To prevent compiler warnings + if (n>2) { + internal::function_invoker* invoker3 = new (allocate_child()) internal::function_invoker(my_func3); + __TBB_ASSERT(invoker3, "Child task allocation failed"); + spawn(*invoker3); + } + my_func1(); + is_recycled = true; + return NULL; + } + } // execute + + public: + spawner(const function1& _func1, const function2& _func2, const function3& _func3) : my_func1(_func1), my_func2(_func2), my_func3(_func3), is_recycled(false) {} + }; + + // Creates and spawns child tasks + class parallel_invoke_helper : public empty_task { + public: + // Dummy functor class + class parallel_invoke_noop { + public: + void operator() () const {} + }; + // Creates a helper object with user-defined number of children expected + parallel_invoke_helper(int number_of_children) + { + set_ref_count(number_of_children + 1); + } + // Adds child task and spawns it + template + void add_child (const function &_func) + { + internal::function_invoker* invoker = new (allocate_child()) internal::function_invoker(_func); + __TBB_ASSERT(invoker, "Child task allocation failed"); + spawn(*invoker); + } + + // Adds a task with multiple child tasks and spawns it + // two arguments + template + void add_children (const function1& _func1, const function2& _func2) + { + // The third argument is dummy, it is ignored actually. + parallel_invoke_noop noop; + internal::spawner<2, function1, function2, parallel_invoke_noop>& sub_root = *new(allocate_child())internal::spawner<2, function1, function2, parallel_invoke_noop>(_func1, _func2, noop); + spawn(sub_root); + } + // three arguments + template + void add_children (const function1& _func1, const function2& _func2, const function3& _func3) + { + internal::spawner<3, function1, function2, function3>& sub_root = *new(allocate_child())internal::spawner<3, function1, function2, function3>(_func1, _func2, _func3); + spawn(sub_root); + } + + // Waits for all child tasks + template + void run_and_finish(const F0& f0) + { + internal::function_invoker* invoker = new (allocate_child()) internal::function_invoker(f0); + __TBB_ASSERT(invoker, "Child task allocation failed"); + spawn_and_wait_for_all(*invoker); + } + }; + // The class destroys root if exception occurred as well as in normal case + class parallel_invoke_cleaner: internal::no_copy { + public: +#if __TBB_TASK_GROUP_CONTEXT + parallel_invoke_cleaner(int number_of_children, tbb::task_group_context& context) + : root(*new(task::allocate_root(context)) internal::parallel_invoke_helper(number_of_children)) +#else + parallel_invoke_cleaner(int number_of_children, tbb::task_group_context&) + : root(*new(task::allocate_root()) internal::parallel_invoke_helper(number_of_children)) +#endif /* !__TBB_TASK_GROUP_CONTEXT */ + {} + + ~parallel_invoke_cleaner(){ + root.destroy(root); + } + internal::parallel_invoke_helper& root; + }; +} // namespace internal +//! @endcond + +/** \name parallel_invoke + **/ +//@{ +//! Executes a list of tasks in parallel and waits for all tasks to complete. +/** @ingroup algorithms */ + +// parallel_invoke with user-defined context +// two arguments +template +void parallel_invoke(const F0& f0, const F1& f1, tbb::task_group_context& context) { + internal::parallel_invoke_cleaner cleaner(2, context); + internal::parallel_invoke_helper& root = cleaner.root; + + root.add_child(f1); + + root.run_and_finish(f0); +} + +// three arguments +template +void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, tbb::task_group_context& context) { + internal::parallel_invoke_cleaner cleaner(3, context); + internal::parallel_invoke_helper& root = cleaner.root; + + root.add_child(f2); + root.add_child(f1); + + root.run_and_finish(f0); +} + +// four arguments +template +void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, + tbb::task_group_context& context) +{ + internal::parallel_invoke_cleaner cleaner(4, context); + internal::parallel_invoke_helper& root = cleaner.root; + + root.add_child(f3); + root.add_child(f2); + root.add_child(f1); + + root.run_and_finish(f0); +} + +// five arguments +template +void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, + tbb::task_group_context& context) +{ + internal::parallel_invoke_cleaner cleaner(3, context); + internal::parallel_invoke_helper& root = cleaner.root; + + root.add_children(f4, f3); + root.add_children(f2, f1); + + root.run_and_finish(f0); +} + +// six arguments +template +void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, const F5& f5, + tbb::task_group_context& context) +{ + internal::parallel_invoke_cleaner cleaner(3, context); + internal::parallel_invoke_helper& root = cleaner.root; + + root.add_children(f5, f4, f3); + root.add_children(f2, f1); + + root.run_and_finish(f0); +} + +// seven arguments +template +void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, + const F5& f5, const F6& f6, + tbb::task_group_context& context) +{ + internal::parallel_invoke_cleaner cleaner(3, context); + internal::parallel_invoke_helper& root = cleaner.root; + + root.add_children(f6, f5, f4); + root.add_children(f3, f2, f1); + + root.run_and_finish(f0); +} + +// eight arguments +template +void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, + const F5& f5, const F6& f6, const F7& f7, + tbb::task_group_context& context) +{ + internal::parallel_invoke_cleaner cleaner(4, context); + internal::parallel_invoke_helper& root = cleaner.root; + + root.add_children(f7, f6, f5); + root.add_children(f4, f3); + root.add_children(f2, f1); + + root.run_and_finish(f0); +} + +// nine arguments +template +void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, + const F5& f5, const F6& f6, const F7& f7, const F8& f8, + tbb::task_group_context& context) +{ + internal::parallel_invoke_cleaner cleaner(4, context); + internal::parallel_invoke_helper& root = cleaner.root; + + root.add_children(f8, f7, f6); + root.add_children(f5, f4, f3); + root.add_children(f2, f1); + + root.run_and_finish(f0); +} + +// ten arguments +template +void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, + const F5& f5, const F6& f6, const F7& f7, const F8& f8, const F9& f9, + tbb::task_group_context& context) +{ + internal::parallel_invoke_cleaner cleaner(4, context); + internal::parallel_invoke_helper& root = cleaner.root; + + root.add_children(f9, f8, f7); + root.add_children(f6, f5, f4); + root.add_children(f3, f2, f1); + + root.run_and_finish(f0); +} + +// two arguments +template +void parallel_invoke(const F0& f0, const F1& f1) { + task_group_context context; + parallel_invoke(f0, f1, context); +} +// three arguments +template +void parallel_invoke(const F0& f0, const F1& f1, const F2& f2) { + task_group_context context; + parallel_invoke(f0, f1, f2, context); +} +// four arguments +template +void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3) { + task_group_context context; + parallel_invoke(f0, f1, f2, f3, context); +} +// five arguments +template +void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4) { + task_group_context context; + parallel_invoke(f0, f1, f2, f3, f4, context); +} +// six arguments +template +void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, const F5& f5) { + task_group_context context; + parallel_invoke(f0, f1, f2, f3, f4, f5, context); +} +// seven arguments +template +void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, + const F5& f5, const F6& f6) +{ + task_group_context context; + parallel_invoke(f0, f1, f2, f3, f4, f5, f6, context); +} +// eigth arguments +template +void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, + const F5& f5, const F6& f6, const F7& f7) +{ + task_group_context context; + parallel_invoke(f0, f1, f2, f3, f4, f5, f6, f7, context); +} +// nine arguments +template +void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, + const F5& f5, const F6& f6, const F7& f7, const F8& f8) +{ + task_group_context context; + parallel_invoke(f0, f1, f2, f3, f4, f5, f6, f7, f8, context); +} +// ten arguments +template +void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, const F4& f4, + const F5& f5, const F6& f6, const F7& f7, const F8& f8, const F9& f9) +{ + task_group_context context; + parallel_invoke(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, context); +} + +//@} + +} // namespace + +#endif /* __TBB_parallel_invoke_H */ diff --git a/src/tbb/include/tbb/parallel_reduce.h b/src/tbb/include/tbb/parallel_reduce.h new file mode 100644 index 0000000..44ca6a0 --- /dev/null +++ b/src/tbb/include/tbb/parallel_reduce.h @@ -0,0 +1,517 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_parallel_reduce_H +#define __TBB_parallel_reduce_H + +#include +#include "task.h" +#include "aligned_space.h" +#include "partitioner.h" +#include "tbb_profiling.h" + +namespace tbb { + +namespace interface6 { +//! @cond INTERNAL +namespace internal { + + using namespace tbb::internal; + + /** Values for reduction_context. */ + enum { + root_task, left_child, right_child + }; + + /** Represented as a char, not enum, for compactness. */ + typedef char reduction_context; + + //! Task type used to combine the partial results of parallel_reduce. + /** @ingroup algorithms */ + template + class finish_reduce: public flag_task { + //! Pointer to body, or NULL if the left child has not yet finished. + bool has_right_zombie; + const reduction_context my_context; + Body* my_body; + aligned_space zombie_space; + finish_reduce( reduction_context context_ ) : + has_right_zombie(false), // TODO: substitute by flag_task::child_stolen? + my_context(context_), + my_body(NULL) + { + } + task* execute() { + if( has_right_zombie ) { + // Right child was stolen. + Body* s = zombie_space.begin(); + my_body->join( *s ); + s->~Body(); + } + if( my_context==left_child ) + itt_store_word_with_release( static_cast(parent())->my_body, my_body ); + return NULL; + } + template + friend class start_reduce; + }; + + //! Task type used to split the work of parallel_reduce. + /** @ingroup algorithms */ + template + class start_reduce: public task { + typedef finish_reduce finish_type; + Body* my_body; + Range my_range; + typename Partitioner::task_partition_type my_partition; + reduction_context my_context; // TODO: factor out into start_reduce_base + /*override*/ task* execute(); + template + friend class finish_reduce; + +public: + //! Constructor used for root task + start_reduce( const Range& range, Body* body, Partitioner& partitioner ) : + my_body(body), + my_range(range), + my_partition(partitioner), + my_context(root_task) + { + } + //! Splitting constructor used to generate children. + /** parent_ becomes left child. Newly constructed object is right child. */ + start_reduce( start_reduce& parent_, split ) : + my_body(parent_.my_body), + my_range(parent_.my_range,split()), + my_partition(parent_.my_partition,split()), + my_context(right_child) + { + my_partition.set_affinity(*this); + parent_.my_context = left_child; + } + //! Construct right child from the given range as response to the demand. + /** parent_ remains left child. Newly constructed object is right child. */ + start_reduce( start_reduce& parent_, const Range& r, depth_t d ) : + my_body(parent_.my_body), + my_range(r), + my_partition(parent_.my_partition,split()), + my_context(right_child) + { + my_partition.set_affinity(*this); + my_partition.align_depth( d ); + parent_.my_context = left_child; + } + //! Update affinity info, if any + /*override*/ void note_affinity( affinity_id id ) { + my_partition.note_affinity( id ); + } + static void run( const Range& range, Body& body, Partitioner& partitioner ) { + if( !range.empty() ) { +#if !__TBB_TASK_GROUP_CONTEXT || TBB_JOIN_OUTER_TASK_GROUP + task::spawn_root_and_wait( *new(task::allocate_root()) start_reduce(range,&body,partitioner) ); +#else + // Bound context prevents exceptions from body to affect nesting or sibling algorithms, + // and allows users to handle exceptions safely by wrapping parallel_for in the try-block. + task_group_context context; + task::spawn_root_and_wait( *new(task::allocate_root(context)) start_reduce(range,&body,partitioner) ); +#endif /* __TBB_TASK_GROUP_CONTEXT && !TBB_JOIN_OUTER_TASK_GROUP */ + } + } +#if __TBB_TASK_GROUP_CONTEXT + static void run( const Range& range, Body& body, Partitioner& partitioner, task_group_context& context ) { + if( !range.empty() ) + task::spawn_root_and_wait( *new(task::allocate_root(context)) start_reduce(range,&body,partitioner) ); + } +#endif /* __TBB_TASK_GROUP_CONTEXT */ + //! create a continuation task, serve as callback for partitioner + finish_type *create_continuation() { + return new( allocate_continuation() ) finish_type(my_context); + } + //! Run body for range + void run_body( Range &r ) { (*my_body)( r ); } + }; + template + task* start_reduce::execute() { + my_partition.check_being_stolen( *this ); + if( my_context==right_child ) { + finish_type* parent_ptr = static_cast(parent()); + if( !itt_load_word_with_acquire(parent_ptr->my_body) ) { // TODO: replace by is_stolen_task() or by parent_ptr->ref_count() == 2??? + my_body = new( parent_ptr->zombie_space.begin() ) Body(*my_body,split()); + parent_ptr->has_right_zombie = true; + } + } else __TBB_ASSERT(my_context==root_task,NULL);// because left leaf spawns right leafs without recycling + my_partition.execute(*this, my_range); + if( my_context==left_child ) { + finish_type* parent_ptr = static_cast(parent()); + __TBB_ASSERT(my_body!=parent_ptr->zombie_space.begin(),NULL); + itt_store_word_with_release(parent_ptr->my_body, my_body ); + } + return NULL; + } + +#if TBB_PREVIEW_DETERMINISTIC_REDUCE + //! Task type used to combine the partial results of parallel_deterministic_reduce. + /** @ingroup algorithms */ + template + class finish_deterministic_reduce: public task { + Body &my_left_body; + Body my_right_body; + + finish_deterministic_reduce( Body &body ) : + my_left_body( body ), + my_right_body( body, split() ) + { + } + task* execute() { + my_left_body.join( my_right_body ); + return NULL; + } + template + friend class start_deterministic_reduce; + }; + + //! Task type used to split the work of parallel_deterministic_reduce. + /** @ingroup algorithms */ + template + class start_deterministic_reduce: public task { + typedef finish_deterministic_reduce finish_type; + Body &my_body; + Range my_range; + /*override*/ task* execute(); + + //! Constructor used for root task + start_deterministic_reduce( const Range& range, Body& body ) : + my_body( body ), + my_range( range ) + { + } + //! Splitting constructor used to generate children. + /** parent_ becomes left child. Newly constructed object is right child. */ + start_deterministic_reduce( start_deterministic_reduce& parent_, finish_type& c ) : + my_body( c.my_right_body ), + my_range( parent_.my_range, split() ) + { + } + +public: + static void run( const Range& range, Body& body ) { + if( !range.empty() ) { +#if !__TBB_TASK_GROUP_CONTEXT || TBB_JOIN_OUTER_TASK_GROUP + task::spawn_root_and_wait( *new(task::allocate_root()) start_deterministic_reduce(range,&body) ); +#else + // Bound context prevents exceptions from body to affect nesting or sibling algorithms, + // and allows users to handle exceptions safely by wrapping parallel_for in the try-block. + task_group_context context; + task::spawn_root_and_wait( *new(task::allocate_root(context)) start_deterministic_reduce(range,body) ); +#endif /* __TBB_TASK_GROUP_CONTEXT && !TBB_JOIN_OUTER_TASK_GROUP */ + } + } +#if __TBB_TASK_GROUP_CONTEXT + static void run( const Range& range, Body& body, task_group_context& context ) { + if( !range.empty() ) + task::spawn_root_and_wait( *new(task::allocate_root(context)) start_deterministic_reduce(range,body) ); + } +#endif /* __TBB_TASK_GROUP_CONTEXT */ + }; + + template + task* start_deterministic_reduce::execute() { + if( !my_range.is_divisible() ) { + my_body( my_range ); + return NULL; + } else { + finish_type& c = *new( allocate_continuation() ) finish_type( my_body ); + recycle_as_child_of(c); + c.set_ref_count(2); + start_deterministic_reduce& b = *new( c.allocate_child() ) start_deterministic_reduce( *this, c ); + task::spawn(b); + return this; + } + } +#endif /* TBB_PREVIEW_DETERMINISTIC_REDUCE */ +} // namespace internal +//! @endcond +} //namespace interfaceX + +//! @cond INTERNAL +namespace internal { + using interface6::internal::start_reduce; +#if TBB_PREVIEW_DETERMINISTIC_REDUCE + using interface6::internal::start_deterministic_reduce; +#endif + //! Auxiliary class for parallel_reduce; for internal use only. + /** The adaptor class that implements \ref parallel_reduce_body_req "parallel_reduce Body" + using given \ref parallel_reduce_lambda_req "anonymous function objects". + **/ + /** @ingroup algorithms */ + template + class lambda_reduce_body { + +//FIXME: decide if my_real_body, my_reduction, and identity_element should be copied or referenced +// (might require some performance measurements) + + const Value& identity_element; + const RealBody& my_real_body; + const Reduction& my_reduction; + Value my_value; + lambda_reduce_body& operator= ( const lambda_reduce_body& other ); + public: + lambda_reduce_body( const Value& identity, const RealBody& body, const Reduction& reduction ) + : identity_element(identity) + , my_real_body(body) + , my_reduction(reduction) + , my_value(identity) + { } + lambda_reduce_body( const lambda_reduce_body& other ) + : identity_element(other.identity_element) + , my_real_body(other.my_real_body) + , my_reduction(other.my_reduction) + , my_value(other.my_value) + { } + lambda_reduce_body( lambda_reduce_body& other, tbb::split ) + : identity_element(other.identity_element) + , my_real_body(other.my_real_body) + , my_reduction(other.my_reduction) + , my_value(other.identity_element) + { } + void operator()(Range& range) { + my_value = my_real_body(range, const_cast(my_value)); + } + void join( lambda_reduce_body& rhs ) { + my_value = my_reduction(const_cast(my_value), const_cast(rhs.my_value)); + } + Value result() const { + return my_value; + } + }; + +} // namespace internal +//! @endcond + +// Requirements on Range concept are documented in blocked_range.h + +/** \page parallel_reduce_body_req Requirements on parallel_reduce body + Class \c Body implementing the concept of parallel_reduce body must define: + - \code Body::Body( Body&, split ); \endcode Splitting constructor. + Must be able to run concurrently with operator() and method \c join + - \code Body::~Body(); \endcode Destructor + - \code void Body::operator()( Range& r ); \endcode Function call operator applying body to range \c r + and accumulating the result + - \code void Body::join( Body& b ); \endcode Join results. + The result in \c b should be merged into the result of \c this +**/ + +/** \page parallel_reduce_lambda_req Requirements on parallel_reduce anonymous function objects (lambda functions) + TO BE DOCUMENTED +**/ + +/** \name parallel_reduce + See also requirements on \ref range_req "Range" and \ref parallel_reduce_body_req "parallel_reduce Body". **/ +//@{ + +//! Parallel iteration with reduction and default partitioner. +/** @ingroup algorithms **/ +template +void parallel_reduce( const Range& range, Body& body ) { + internal::start_reduce::run( range, body, __TBB_DEFAULT_PARTITIONER() ); +} + +//! Parallel iteration with reduction and simple_partitioner +/** @ingroup algorithms **/ +template +void parallel_reduce( const Range& range, Body& body, const simple_partitioner& partitioner ) { + internal::start_reduce::run( range, body, partitioner ); +} + +//! Parallel iteration with reduction and auto_partitioner +/** @ingroup algorithms **/ +template +void parallel_reduce( const Range& range, Body& body, const auto_partitioner& partitioner ) { + internal::start_reduce::run( range, body, partitioner ); +} + +//! Parallel iteration with reduction and affinity_partitioner +/** @ingroup algorithms **/ +template +void parallel_reduce( const Range& range, Body& body, affinity_partitioner& partitioner ) { + internal::start_reduce::run( range, body, partitioner ); +} + +#if __TBB_TASK_GROUP_CONTEXT +//! Parallel iteration with reduction, simple partitioner and user-supplied context. +/** @ingroup algorithms **/ +template +void parallel_reduce( const Range& range, Body& body, const simple_partitioner& partitioner, task_group_context& context ) { + internal::start_reduce::run( range, body, partitioner, context ); +} + +//! Parallel iteration with reduction, auto_partitioner and user-supplied context +/** @ingroup algorithms **/ +template +void parallel_reduce( const Range& range, Body& body, const auto_partitioner& partitioner, task_group_context& context ) { + internal::start_reduce::run( range, body, partitioner, context ); +} + +//! Parallel iteration with reduction, affinity_partitioner and user-supplied context +/** @ingroup algorithms **/ +template +void parallel_reduce( const Range& range, Body& body, affinity_partitioner& partitioner, task_group_context& context ) { + internal::start_reduce::run( range, body, partitioner, context ); +} +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +/** parallel_reduce overloads that work with anonymous function objects + (see also \ref parallel_reduce_lambda_req "requirements on parallel_reduce anonymous function objects"). **/ + +//! Parallel iteration with reduction and default partitioner. +/** @ingroup algorithms **/ +template +Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction ) { + internal::lambda_reduce_body body(identity, real_body, reduction); + internal::start_reduce,const __TBB_DEFAULT_PARTITIONER> + ::run(range, body, __TBB_DEFAULT_PARTITIONER() ); + return body.result(); +} + +//! Parallel iteration with reduction and simple_partitioner. +/** @ingroup algorithms **/ +template +Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction, + const simple_partitioner& partitioner ) { + internal::lambda_reduce_body body(identity, real_body, reduction); + internal::start_reduce,const simple_partitioner> + ::run(range, body, partitioner ); + return body.result(); +} + +//! Parallel iteration with reduction and auto_partitioner +/** @ingroup algorithms **/ +template +Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction, + const auto_partitioner& partitioner ) { + internal::lambda_reduce_body body(identity, real_body, reduction); + internal::start_reduce,const auto_partitioner> + ::run( range, body, partitioner ); + return body.result(); +} + +//! Parallel iteration with reduction and affinity_partitioner +/** @ingroup algorithms **/ +template +Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction, + affinity_partitioner& partitioner ) { + internal::lambda_reduce_body body(identity, real_body, reduction); + internal::start_reduce,affinity_partitioner> + ::run( range, body, partitioner ); + return body.result(); +} + +#if __TBB_TASK_GROUP_CONTEXT +//! Parallel iteration with reduction, simple partitioner and user-supplied context. +/** @ingroup algorithms **/ +template +Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction, + const simple_partitioner& partitioner, task_group_context& context ) { + internal::lambda_reduce_body body(identity, real_body, reduction); + internal::start_reduce,const simple_partitioner> + ::run( range, body, partitioner, context ); + return body.result(); +} + +//! Parallel iteration with reduction, auto_partitioner and user-supplied context +/** @ingroup algorithms **/ +template +Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction, + const auto_partitioner& partitioner, task_group_context& context ) { + internal::lambda_reduce_body body(identity, real_body, reduction); + internal::start_reduce,const auto_partitioner> + ::run( range, body, partitioner, context ); + return body.result(); +} + +//! Parallel iteration with reduction, affinity_partitioner and user-supplied context +/** @ingroup algorithms **/ +template +Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction, + affinity_partitioner& partitioner, task_group_context& context ) { + internal::lambda_reduce_body body(identity, real_body, reduction); + internal::start_reduce,affinity_partitioner> + ::run( range, body, partitioner, context ); + return body.result(); +} +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +#if TBB_PREVIEW_DETERMINISTIC_REDUCE +//! Parallel iteration with deterministic reduction and default partitioner. +/** @ingroup algorithms **/ +template +void parallel_deterministic_reduce( const Range& range, Body& body ) { + internal::start_deterministic_reduce::run( range, body ); +} + +#if __TBB_TASK_GROUP_CONTEXT +//! Parallel iteration with deterministic reduction, simple partitioner and user-supplied context. +/** @ingroup algorithms **/ +template +void parallel_deterministic_reduce( const Range& range, Body& body, task_group_context& context ) { + internal::start_deterministic_reduce::run( range, body, context ); +} +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +/** parallel_reduce overloads that work with anonymous function objects + (see also \ref parallel_reduce_lambda_req "requirements on parallel_reduce anonymous function objects"). **/ + +//! Parallel iteration with deterministic reduction and default partitioner. +/** @ingroup algorithms **/ +template +Value parallel_deterministic_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction ) { + internal::lambda_reduce_body body(identity, real_body, reduction); + internal::start_deterministic_reduce > + ::run(range, body); + return body.result(); +} + +#if __TBB_TASK_GROUP_CONTEXT +//! Parallel iteration with deterministic reduction, simple partitioner and user-supplied context. +/** @ingroup algorithms **/ +template +Value parallel_deterministic_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction, + task_group_context& context ) { + internal::lambda_reduce_body body(identity, real_body, reduction); + internal::start_deterministic_reduce > + ::run( range, body, context ); + return body.result(); +} +#endif /* __TBB_TASK_GROUP_CONTEXT */ +#endif /* TBB_PREVIEW_DETERMINISTIC_REDUCE */ +//@} + +} // namespace tbb + +#endif /* __TBB_parallel_reduce_H */ + diff --git a/src/tbb/include/tbb/parallel_scan.h b/src/tbb/include/tbb/parallel_scan.h new file mode 100644 index 0000000..9cf8b5c --- /dev/null +++ b/src/tbb/include/tbb/parallel_scan.h @@ -0,0 +1,351 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_parallel_scan_H +#define __TBB_parallel_scan_H + +#include "task.h" +#include "aligned_space.h" +#include +#include "partitioner.h" + +namespace tbb { + +//! Used to indicate that the initial scan is being performed. +/** @ingroup algorithms */ +struct pre_scan_tag { + static bool is_final_scan() {return false;} +}; + +//! Used to indicate that the final scan is being performed. +/** @ingroup algorithms */ +struct final_scan_tag { + static bool is_final_scan() {return true;} +}; + +//! @cond INTERNAL +namespace internal { + + //! Performs final scan for a leaf + /** @ingroup algorithms */ + template + class final_sum: public task { + public: + Body body; + private: + aligned_space range; + //! Where to put result of last subrange, or NULL if not last subrange. + Body* stuff_last; + public: + final_sum( Body& body_ ) : + body(body_,split()) + { + poison_pointer(stuff_last); + } + ~final_sum() { + range.begin()->~Range(); + } + void finish_construction( const Range& range_, Body* stuff_last_ ) { + new( range.begin() ) Range(range_); + stuff_last = stuff_last_; + } + private: + /*override*/ task* execute() { + body( *range.begin(), final_scan_tag() ); + if( stuff_last ) + stuff_last->assign(body); + return NULL; + } + }; + + //! Split work to be done in the scan. + /** @ingroup algorithms */ + template + class sum_node: public task { + typedef final_sum final_sum_type; + public: + final_sum_type *incoming; + final_sum_type *body; + Body *stuff_last; + private: + final_sum_type *left_sum; + sum_node *left; + sum_node *right; + bool left_is_final; + Range range; + sum_node( const Range range_, bool left_is_final_ ) : + left_sum(NULL), + left(NULL), + right(NULL), + left_is_final(left_is_final_), + range(range_) + { + // Poison fields that will be set by second pass. + poison_pointer(body); + poison_pointer(incoming); + } + task* create_child( const Range& range_, final_sum_type& f, sum_node* n, final_sum_type* incoming_, Body* stuff_last_ ) { + if( !n ) { + f.recycle_as_child_of( *this ); + f.finish_construction( range_, stuff_last_ ); + return &f; + } else { + n->body = &f; + n->incoming = incoming_; + n->stuff_last = stuff_last_; + return n; + } + } + /*override*/ task* execute() { + if( body ) { + if( incoming ) + left_sum->body.reverse_join( incoming->body ); + recycle_as_continuation(); + sum_node& c = *this; + task* b = c.create_child(Range(range,split()),*left_sum,right,left_sum,stuff_last); + task* a = left_is_final ? NULL : c.create_child(range,*body,left,incoming,NULL); + set_ref_count( (a!=NULL)+(b!=NULL) ); + body = NULL; + if( a ) spawn(*b); + else a = b; + return a; + } else { + return NULL; + } + } + template + friend class start_scan; + + template + friend class finish_scan; + }; + + //! Combine partial results + /** @ingroup algorithms */ + template + class finish_scan: public task { + typedef sum_node sum_node_type; + typedef final_sum final_sum_type; + final_sum_type** const sum; + sum_node_type*& return_slot; + public: + final_sum_type* right_zombie; + sum_node_type& result; + + /*override*/ task* execute() { + __TBB_ASSERT( result.ref_count()==(result.left!=NULL)+(result.right!=NULL), NULL ); + if( result.left ) + result.left_is_final = false; + if( right_zombie && sum ) + ((*sum)->body).reverse_join(result.left_sum->body); + __TBB_ASSERT( !return_slot, NULL ); + if( right_zombie || result.right ) { + return_slot = &result; + } else { + destroy( result ); + } + if( right_zombie && !sum && !result.right ) destroy(*right_zombie); + return NULL; + } + + finish_scan( sum_node_type*& return_slot_, final_sum_type** sum_, sum_node_type& result_ ) : + sum(sum_), + return_slot(return_slot_), + right_zombie(NULL), + result(result_) + { + __TBB_ASSERT( !return_slot, NULL ); + } + }; + + //! Initial task to split the work + /** @ingroup algorithms */ + template + class start_scan: public task { + typedef sum_node sum_node_type; + typedef final_sum final_sum_type; + final_sum_type* body; + /** Non-null if caller is requesting total. */ + final_sum_type** sum; + sum_node_type** return_slot; + /** Null if computing root. */ + sum_node_type* parent_sum; + bool is_final; + bool is_right_child; + Range range; + typename Partitioner::partition_type partition; + /*override*/ task* execute(); + public: + start_scan( sum_node_type*& return_slot_, start_scan& parent_, sum_node_type* parent_sum_ ) : + body(parent_.body), + sum(parent_.sum), + return_slot(&return_slot_), + parent_sum(parent_sum_), + is_final(parent_.is_final), + is_right_child(false), + range(parent_.range,split()), + partition(parent_.partition,split()) + { + __TBB_ASSERT( !*return_slot, NULL ); + } + + start_scan( sum_node_type*& return_slot_, const Range& range_, final_sum_type& body_, const Partitioner& partitioner_) : + body(&body_), + sum(NULL), + return_slot(&return_slot_), + parent_sum(NULL), + is_final(true), + is_right_child(false), + range(range_), + partition(partitioner_) + { + __TBB_ASSERT( !*return_slot, NULL ); + } + + static void run( const Range& range_, Body& body_, const Partitioner& partitioner_ ) { + if( !range_.empty() ) { + typedef internal::start_scan start_pass1_type; + internal::sum_node* root = NULL; + typedef internal::final_sum final_sum_type; + final_sum_type* temp_body = new(task::allocate_root()) final_sum_type( body_ ); + start_pass1_type& pass1 = *new(task::allocate_root()) start_pass1_type( + /*return_slot=*/root, + range_, + *temp_body, + partitioner_ ); + task::spawn_root_and_wait( pass1 ); + if( root ) { + root->body = temp_body; + root->incoming = NULL; + root->stuff_last = &body_; + task::spawn_root_and_wait( *root ); + } else { + body_.assign(temp_body->body); + temp_body->finish_construction( range_, NULL ); + temp_body->destroy(*temp_body); + } + } + } + }; + + template + task* start_scan::execute() { + typedef internal::finish_scan finish_pass1_type; + finish_pass1_type* p = parent_sum ? static_cast( parent() ) : NULL; + // Inspecting p->result.left_sum would ordinarily be a race condition. + // But we inspect it only if we are not a stolen task, in which case we + // know that task assigning to p->result.left_sum has completed. + bool treat_as_stolen = is_right_child && (is_stolen_task() || body!=p->result.left_sum); + if( treat_as_stolen ) { + // Invocation is for right child that has been really stolen or needs to be virtually stolen + p->right_zombie = body = new( allocate_root() ) final_sum_type(body->body); + is_final = false; + } + task* next_task = NULL; + if( (is_right_child && !treat_as_stolen) || !range.is_divisible() || partition.should_execute_range(*this) ) { + if( is_final ) + (body->body)( range, final_scan_tag() ); + else if( sum ) + (body->body)( range, pre_scan_tag() ); + if( sum ) + *sum = body; + __TBB_ASSERT( !*return_slot, NULL ); + } else { + sum_node_type* result; + if( parent_sum ) + result = new(allocate_additional_child_of(*parent_sum)) sum_node_type(range,/*left_is_final=*/is_final); + else + result = new(task::allocate_root()) sum_node_type(range,/*left_is_final=*/is_final); + finish_pass1_type& c = *new( allocate_continuation()) finish_pass1_type(*return_slot,sum,*result); + // Split off right child + start_scan& b = *new( c.allocate_child() ) start_scan( /*return_slot=*/result->right, *this, result ); + b.is_right_child = true; + // Left child is recycling of *this. Must recycle this before spawning b, + // otherwise b might complete and decrement c.ref_count() to zero, which + // would cause c.execute() to run prematurely. + recycle_as_child_of(c); + c.set_ref_count(2); + c.spawn(b); + sum = &result->left_sum; + return_slot = &result->left; + is_right_child = false; + next_task = this; + parent_sum = result; + __TBB_ASSERT( !*return_slot, NULL ); + } + return next_task; + } +} // namespace internal +//! @endcond + +// Requirements on Range concept are documented in blocked_range.h + +/** \page parallel_scan_body_req Requirements on parallel_scan body + Class \c Body implementing the concept of parallel_scan body must define: + - \code Body::Body( Body&, split ); \endcode Splitting constructor. + Split \c b so that \c this and \c b can accumulate separately + - \code Body::~Body(); \endcode Destructor + - \code void Body::operator()( const Range& r, pre_scan_tag ); \endcode + Preprocess iterations for range \c r + - \code void Body::operator()( const Range& r, final_scan_tag ); \endcode + Do final processing for iterations of range \c r + - \code void Body::reverse_join( Body& a ); \endcode + Merge preprocessing state of \c a into \c this, where \c a was + created earlier from \c b by b's splitting constructor +**/ + +/** \name parallel_scan + See also requirements on \ref range_req "Range" and \ref parallel_scan_body_req "parallel_scan Body". **/ +//@{ + +//! Parallel prefix with default partitioner +/** @ingroup algorithms **/ +template +void parallel_scan( const Range& range, Body& body ) { + internal::start_scan::run(range,body,__TBB_DEFAULT_PARTITIONER()); +} + +//! Parallel prefix with simple_partitioner +/** @ingroup algorithms **/ +template +void parallel_scan( const Range& range, Body& body, const simple_partitioner& partitioner ) { + internal::start_scan::run(range,body,partitioner); +} + +//! Parallel prefix with auto_partitioner +/** @ingroup algorithms **/ +template +void parallel_scan( const Range& range, Body& body, const auto_partitioner& partitioner ) { + internal::start_scan::run(range,body,partitioner); +} +//@} + +} // namespace tbb + +#endif /* __TBB_parallel_scan_H */ + diff --git a/src/tbb/include/tbb/parallel_sort.h b/src/tbb/include/tbb/parallel_sort.h new file mode 100644 index 0000000..5a79294 --- /dev/null +++ b/src/tbb/include/tbb/parallel_sort.h @@ -0,0 +1,231 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_parallel_sort_H +#define __TBB_parallel_sort_H + +#include "parallel_for.h" +#include "blocked_range.h" +#include +#include +#include + +namespace tbb { + +//! @cond INTERNAL +namespace internal { + +//! Range used in quicksort to split elements into subranges based on a value. +/** The split operation selects a splitter and places all elements less than or equal + to the value in the first range and the remaining elements in the second range. + @ingroup algorithms */ +template +class quick_sort_range: private no_assign { + + inline size_t median_of_three(const RandomAccessIterator &array, size_t l, size_t m, size_t r) const { + return comp(array[l], array[m]) ? ( comp(array[m], array[r]) ? m : ( comp( array[l], array[r]) ? r : l ) ) + : ( comp(array[r], array[m]) ? m : ( comp( array[r], array[l] ) ? r : l ) ); + } + + inline size_t pseudo_median_of_nine( const RandomAccessIterator &array, const quick_sort_range &range ) const { + size_t offset = range.size/8u; + return median_of_three(array, + median_of_three(array, 0, offset, offset*2), + median_of_three(array, offset*3, offset*4, offset*5), + median_of_three(array, offset*6, offset*7, range.size - 1) ); + + } + +public: + + static const size_t grainsize = 500; + const Compare ∁ + RandomAccessIterator begin; + size_t size; + + quick_sort_range( RandomAccessIterator begin_, size_t size_, const Compare &comp_ ) : + comp(comp_), begin(begin_), size(size_) {} + + bool empty() const {return size==0;} + bool is_divisible() const {return size>=grainsize;} + + quick_sort_range( quick_sort_range& range, split ) : comp(range.comp) { + RandomAccessIterator array = range.begin; + RandomAccessIterator key0 = range.begin; + size_t m = pseudo_median_of_nine(array, range); + if (m) std::swap ( array[0], array[m] ); + + size_t i=0; + size_t j=range.size; + // Partition interval [i+1,j-1] with key *key0. + for(;;) { + __TBB_ASSERT( i +class quick_sort_pretest_body : internal::no_assign { + const Compare ∁ + +public: + quick_sort_pretest_body(const Compare &_comp) : comp(_comp) {} + + void operator()( const blocked_range& range ) const { + task &my_task = task::self(); + RandomAccessIterator my_end = range.end(); + + int i = 0; + for (RandomAccessIterator k = range.begin(); k != my_end; ++k, ++i) { + if ( i%64 == 0 && my_task.is_cancelled() ) break; + + // The k-1 is never out-of-range because the first chunk starts at begin+serial_cutoff+1 + if ( comp( *(k), *(k-1) ) ) { + my_task.cancel_group_execution(); + break; + } + } + } + +}; +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +//! Body class used to sort elements in a range that is smaller than the grainsize. +/** @ingroup algorithms */ +template +struct quick_sort_body { + void operator()( const quick_sort_range& range ) const { + //SerialQuickSort( range.begin, range.size, range.comp ); + std::sort( range.begin, range.begin + range.size, range.comp ); + } +}; + +//! Wrapper method to initiate the sort by calling parallel_for. +/** @ingroup algorithms */ +template +void parallel_quick_sort( RandomAccessIterator begin, RandomAccessIterator end, const Compare& comp ) { +#if __TBB_TASK_GROUP_CONTEXT + task_group_context my_context; + const int serial_cutoff = 9; + + __TBB_ASSERT( begin + serial_cutoff < end, "min_parallel_size is smaller than serial cutoff?" ); + RandomAccessIterator k; + for ( k = begin ; k != begin + serial_cutoff; ++k ) { + if ( comp( *(k+1), *k ) ) { + goto do_parallel_quick_sort; + } + } + + parallel_for( blocked_range(k+1, end), + quick_sort_pretest_body(comp), + auto_partitioner(), + my_context); + + if (my_context.is_group_execution_cancelled()) +do_parallel_quick_sort: +#endif /* __TBB_TASK_GROUP_CONTEXT */ + parallel_for( quick_sort_range(begin, end-begin, comp ), + quick_sort_body(), + auto_partitioner() ); +} + +} // namespace internal +//! @endcond + +/** \page parallel_sort_iter_req Requirements on iterators for parallel_sort + Requirements on value type \c T of \c RandomAccessIterator for \c parallel_sort: + - \code void swap( T& x, T& y ) \endcode Swaps \c x and \c y + - \code bool Compare::operator()( const T& x, const T& y ) \endcode + True if x comes before y; +**/ + +/** \name parallel_sort + See also requirements on \ref parallel_sort_iter_req "iterators for parallel_sort". **/ +//@{ + +//! Sorts the data in [begin,end) using the given comparator +/** The compare function object is used for all comparisons between elements during sorting. + The compare object must define a bool operator() function. + @ingroup algorithms **/ +template +void parallel_sort( RandomAccessIterator begin, RandomAccessIterator end, const Compare& comp) { + const int min_parallel_size = 500; + if( end > begin ) { + if (end - begin < min_parallel_size) { + std::sort(begin, end, comp); + } else { + internal::parallel_quick_sort(begin, end, comp); + } + } +} + +//! Sorts the data in [begin,end) with a default comparator \c std::less +/** @ingroup algorithms **/ +template +inline void parallel_sort( RandomAccessIterator begin, RandomAccessIterator end ) { + parallel_sort( begin, end, std::less< typename std::iterator_traits::value_type >() ); +} + +//! Sorts the data in the range \c [begin,end) with a default comparator \c std::less +/** @ingroup algorithms **/ +template +inline void parallel_sort( T * begin, T * end ) { + parallel_sort( begin, end, std::less< T >() ); +} +//@} + + +} // namespace tbb + +#endif + diff --git a/src/tbb/include/tbb/parallel_while.h b/src/tbb/include/tbb/parallel_while.h new file mode 100644 index 0000000..e2f0c83 --- /dev/null +++ b/src/tbb/include/tbb/parallel_while.h @@ -0,0 +1,194 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_parallel_while +#define __TBB_parallel_while + +#include "task.h" +#include + +namespace tbb { + +template +class parallel_while; + +//! @cond INTERNAL +namespace internal { + + template class while_task; + + //! For internal use only. + /** Executes one iteration of a while. + @ingroup algorithms */ + template + class while_iteration_task: public task { + const Body& my_body; + typename Body::argument_type my_value; + /*override*/ task* execute() { + my_body(my_value); + return NULL; + } + while_iteration_task( const typename Body::argument_type& value, const Body& body ) : + my_body(body), my_value(value) + {} + template friend class while_group_task; + friend class tbb::parallel_while; + }; + + //! For internal use only + /** Unpacks a block of iterations. + @ingroup algorithms */ + template + class while_group_task: public task { + static const size_t max_arg_size = 4; + const Body& my_body; + size_t size; + typename Body::argument_type my_arg[max_arg_size]; + while_group_task( const Body& body ) : my_body(body), size(0) {} + /*override*/ task* execute() { + typedef while_iteration_task iteration_type; + __TBB_ASSERT( size>0, NULL ); + task_list list; + task* t; + size_t k=0; + for(;;) { + t = new( allocate_child() ) iteration_type(my_arg[k],my_body); + if( ++k==size ) break; + list.push_back(*t); + } + set_ref_count(int(k+1)); + spawn(list); + spawn_and_wait_for_all(*t); + return NULL; + } + template friend class while_task; + }; + + //! For internal use only. + /** Gets block of iterations from a stream and packages them into a while_group_task. + @ingroup algorithms */ + template + class while_task: public task { + Stream& my_stream; + const Body& my_body; + empty_task& my_barrier; + /*override*/ task* execute() { + typedef while_group_task block_type; + block_type& t = *new( allocate_additional_child_of(my_barrier) ) block_type(my_body); + size_t k=0; + while( my_stream.pop_if_present(t.my_arg[k]) ) { + if( ++k==block_type::max_arg_size ) { + // There might be more iterations. + recycle_to_reexecute(); + break; + } + } + if( k==0 ) { + destroy(t); + return NULL; + } else { + t.size = k; + return &t; + } + } + while_task( Stream& stream, const Body& body, empty_task& barrier ) : + my_stream(stream), + my_body(body), + my_barrier(barrier) + {} + friend class tbb::parallel_while; + }; + +} // namespace internal +//! @endcond + +//! Parallel iteration over a stream, with optional addition of more work. +/** The Body b has the requirement: \n + "b(v)" \n + "b.argument_type" \n + where v is an argument_type + @ingroup algorithms */ +template +class parallel_while: internal::no_copy { +public: + //! Construct empty non-running parallel while. + parallel_while() : my_body(NULL), my_barrier(NULL) {} + + //! Destructor cleans up data members before returning. + ~parallel_while() { + if( my_barrier ) { + my_barrier->destroy(*my_barrier); + my_barrier = NULL; + } + } + + //! Type of items + typedef typename Body::argument_type value_type; + + //! Apply body.apply to each item in the stream. + /** A Stream s has the requirements \n + "S::value_type" \n + "s.pop_if_present(value) is convertible to bool */ + template + void run( Stream& stream, const Body& body ); + + //! Add a work item while running. + /** Should be executed only by body.apply or a thread spawned therefrom. */ + void add( const value_type& item ); + +private: + const Body* my_body; + empty_task* my_barrier; +}; + +template +template +void parallel_while::run( Stream& stream, const Body& body ) { + using namespace internal; + empty_task& barrier = *new( task::allocate_root() ) empty_task(); + my_body = &body; + my_barrier = &barrier; + my_barrier->set_ref_count(2); + while_task& w = *new( my_barrier->allocate_child() ) while_task( stream, body, barrier ); + my_barrier->spawn_and_wait_for_all(w); + my_barrier->destroy(*my_barrier); + my_barrier = NULL; + my_body = NULL; +} + +template +void parallel_while::add( const value_type& item ) { + __TBB_ASSERT(my_barrier,"attempt to add to parallel_while that is not running"); + typedef internal::while_iteration_task iteration_type; + iteration_type& i = *new( task::allocate_additional_child_of(*my_barrier) ) iteration_type(item,*my_body); + task::self().spawn( i ); +} + +} // namespace + +#endif /* __TBB_parallel_while */ diff --git a/src/tbb/include/tbb/partitioner.h b/src/tbb/include/tbb/partitioner.h new file mode 100644 index 0000000..7805bff --- /dev/null +++ b/src/tbb/include/tbb/partitioner.h @@ -0,0 +1,509 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_partitioner_H +#define __TBB_partitioner_H + +#ifndef __TBB_INITIAL_CHUNKS +#define __TBB_INITIAL_CHUNKS 2 +#endif +#ifndef __TBB_RANGE_POOL_CAPACITY +#define __TBB_RANGE_POOL_CAPACITY 8 +#endif +#ifndef __TBB_INIT_DEPTH +#define __TBB_INIT_DEPTH 5 +#endif + +#include "task.h" +#include "aligned_space.h" +#include "atomic.h" + +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) + // Workaround for overzealous compiler warnings + #pragma warning (push) + #pragma warning (disable: 4244) +#endif + +namespace tbb { + +class auto_partitioner; +class simple_partitioner; +class affinity_partitioner; +namespace interface6 { + namespace internal { + class affinity_partition_type; + } +} + +namespace internal { +size_t __TBB_EXPORTED_FUNC get_initial_auto_partitioner_divisor(); + +//! Defines entry point for affinity partitioner into tbb run-time library. +class affinity_partitioner_base_v3: no_copy { + friend class tbb::affinity_partitioner; + friend class tbb::interface6::internal::affinity_partition_type; + //! Array that remembers affinities of tree positions to affinity_id. + /** NULL if my_size==0. */ + affinity_id* my_array; + //! Number of elements in my_array. + size_t my_size; + //! Zeros the fields. + affinity_partitioner_base_v3() : my_array(NULL), my_size(0) {} + //! Deallocates my_array. + ~affinity_partitioner_base_v3() {resize(0);} + //! Resize my_array. + /** Retains values if resulting size is the same. */ + void __TBB_EXPORTED_METHOD resize( unsigned factor ); +}; + +//! Provides backward-compatible methods for partition objects without affinity. +class partition_type_base { +public: + void set_affinity( task & ) {} + void note_affinity( task::affinity_id ) {} + task* continue_after_execute_range() {return NULL;} + bool decide_whether_to_delay() {return false;} + void spawn_or_delay( bool, task& b ) { + task::spawn(b); + } +}; + +template class start_scan; + +} // namespace internal +//! @endcond + +namespace serial { +namespace interface6 { +template class start_for; +} +} + +namespace interface6 { +//! @cond INTERNAL +namespace internal { +using namespace tbb::internal; +template class start_for; +template class start_reduce; + +//! Join task node that contains shared flag for stealing feedback +class flag_task: public task { +public: + tbb::atomic child_stolen; + flag_task() { child_stolen = false; } + task* execute() { return NULL; } +}; + +//! Task to signal the demand without carrying the work +class signal_task: public task { +public: + task* execute() { + if( is_stolen_task() ) { + static_cast(parent())->child_stolen = true; + } + return NULL; + } +}; + +//! Depth is a relative depth of recursive division inside a range pool. Relative depth allows +//! infinite absolute depth of the recursion for heavily imbalanced workloads with range represented +//! by a number that cannot fit into machine word. +typedef unsigned char depth_t; + +//! Range pool stores ranges of type T in a circular buffer with MaxCapacity +template +class range_vector { + depth_t my_head; + depth_t my_tail; + depth_t my_size; + depth_t my_depth[MaxCapacity]; // relative depths of stored ranges + tbb::aligned_space my_pool; + +public: + //! initialize via first range in pool + range_vector(const T& elem) : my_head(0), my_tail(0), my_size(1) { + my_depth[0] = 0; + new( my_pool.begin() ) T(elem);//TODO: std::move? + } + ~range_vector() { + while( !empty() ) pop_back(); + } + bool empty() const { return my_size == 0; } + depth_t size() const { return my_size; } + //! Populates range pool via ranges up to max depth or while divisible + //! max_depth starts from 0, e.g. value 2 makes 3 ranges in the pool up to two 1/4 pieces + void split_to_fill(depth_t max_depth) { + while( my_size < MaxCapacity && my_depth[my_head] < max_depth + && my_pool.begin()[my_head].is_divisible() ) { + depth_t prev = my_head; + my_head = (my_head + 1) % MaxCapacity; + new(my_pool.begin()+my_head) T(my_pool.begin()[prev]); // copy TODO: std::move? + my_pool.begin()[prev].~T(); // instead of assignment + new(my_pool.begin()+prev) T(my_pool.begin()[my_head], split()); // do 'inverse' split + my_depth[my_head] = ++my_depth[prev]; + my_size++; + } + } + void pop_back() { + __TBB_ASSERT(my_size > 0, "range_vector::pop_back() with empty size"); + my_pool.begin()[my_head].~T(); + my_size--; + my_head = (my_head + MaxCapacity - 1) % MaxCapacity; + } + void pop_front() { + __TBB_ASSERT(my_size > 0, "range_vector::pop_front() with empty size"); + my_pool.begin()[my_tail].~T(); + my_size--; + my_tail = (my_tail + 1) % MaxCapacity; + } + T& back() { + __TBB_ASSERT(my_size > 0, "range_vector::back() with empty size"); + return my_pool.begin()[my_head]; + } + T& front() { + __TBB_ASSERT(my_size > 0, "range_vector::front() with empty size"); + return my_pool.begin()[my_tail]; + } + //! similarly to front(), returns depth of the first range in the pool + depth_t front_depth() { + __TBB_ASSERT(my_size > 0, "range_vector::front_depth() with empty size"); + return my_depth[my_tail]; + } +}; + +//! Provides default methods for partition objects and common algorithm blocks. +template +struct partition_type_base { + // decision makers + void set_affinity( task & ) {} + void note_affinity( task::affinity_id ) {} + bool check_being_stolen(task &) { return false; } // part of old should_execute_range() + bool check_for_demand(task &) { return false; } + bool divisions_left() { return true; } // part of old should_execute_range() + bool should_create_trap() { return false; } + depth_t max_depth() { return 0; } + void align_depth(depth_t) { } + // common function blocks + Partition& derived() { return *static_cast(this); } + template + flag_task* split_work(StartType &start) { + flag_task* parent_ptr = start.create_continuation(); // the type here is to express expectation + start.set_parent(parent_ptr); + parent_ptr->set_ref_count(2); + StartType& right_work = *new( parent_ptr->allocate_child() ) StartType(start, split()); + start.spawn(right_work); + return parent_ptr; + } + template + void execute(StartType &start, Range &range) { + // The algorithm in a few words ([]-denotes calls to decision methods of partitioner): + // [If this task is stolen, adjust depth and divisions if necessary, set flag]. + // If range is divisible { + // Spread the work while [initial divisions left]; + // Create trap task [if necessary]; + // } + // If not divisible or [max depth is reached], execute, else do the range pool part + task* parent_ptr = start.parent(); + if( range.is_divisible() ) { + if( derived().divisions_left() ) + do parent_ptr = split_work(start); // split until divisions_left() + while( range.is_divisible() && derived().divisions_left() ); + if( derived().should_create_trap() ) { // only for range pool + if( parent_ptr->ref_count() > 1 ) { // create new parent if necessary + parent_ptr = start.create_continuation(); + start.set_parent(parent_ptr); + } else __TBB_ASSERT(parent_ptr->ref_count() == 1, NULL); + parent_ptr->set_ref_count(2); // safe because parent has only one reference + signal_task& right_signal = *new( parent_ptr->allocate_child() ) signal_task(); + start.spawn(right_signal); // pure signal is to avoid deep recursion in the end + } + } + if( !range.is_divisible() || !derived().max_depth() ) + start.run_body( range ); // simple partitioner goes always here + else { // do range pool + internal::range_vector range_pool(range); + do { + range_pool.split_to_fill(derived().max_depth()); // fill range pool + if( derived().check_for_demand( start ) ) { + if( range_pool.size() > 1 ) { + parent_ptr = start.create_continuation(); + start.set_parent(parent_ptr); + parent_ptr->set_ref_count(2); + StartType& right_work = *new( parent_ptr->allocate_child() ) StartType(start, range_pool.front(), range_pool.front_depth()); + start.spawn(right_work); + range_pool.pop_front(); + continue; + } + if( range_pool.back().is_divisible() ) // was not enough depth to fork a task + continue; // note: check_for_demand() should guarantee increasing max_depth() next time + } + start.run_body( range_pool.back() ); + range_pool.pop_back(); + } while( !range_pool.empty() && !start.is_cancelled() ); + } + } +}; + +//! Provides default methods for auto (adaptive) partition objects. +template +struct auto_partition_type_base : partition_type_base { + size_t my_divisor; + depth_t my_max_depth; + auto_partition_type_base() : my_max_depth(__TBB_INIT_DEPTH) { + my_divisor = tbb::internal::get_initial_auto_partitioner_divisor()*__TBB_INITIAL_CHUNKS/4; + __TBB_ASSERT(my_divisor, "initial value of get_initial_auto_partitioner_divisor() is not valid"); + } + auto_partition_type_base(auto_partition_type_base &src, split) { + my_max_depth = src.my_max_depth; +#if __TBB_INITIAL_TASK_IMBALANCE + if( src.my_divisor <= 1 ) my_divisor = 0; + else my_divisor = src.my_divisor = (src.my_divisor+1u) / 2u; +#else + my_divisor = src.my_divisor / 2u; + src.my_divisor = src.my_divisor - my_divisor; // TODO: check the effect separately + if(my_divisor) src.my_max_depth += static_cast(__TBB_Log2(src.my_divisor/my_divisor)); +#endif + } + bool check_being_stolen( task &t) { // part of old should_execute_range() + if( !my_divisor ) { + my_divisor = 1; // todo: replace by on-stack flag (partition_state's member)? + if( t.is_stolen_task() ) { +#if TBB_USE_EXCEPTIONS + // RTTI is available, check whether the cast is valid + __TBB_ASSERT(dynamic_cast(t.parent()), 0); + // correctness of the cast relies on avoiding the root task for which: + // - initial value of my_divisor != 0 (protected by separate assertion) + // - is_stolen_task() always return false for the root task. +#endif + static_cast(t.parent())->child_stolen = true; + my_max_depth++; + return true; + } + } + return false; + } + bool divisions_left() { // part of old should_execute_range() + if( my_divisor > 1 ) return true; + if( my_divisor && my_max_depth > 1 ) { // can split the task and once more internally. TODO: on-stack flag instead + // keep same fragmentation while splitting for the local task pool + my_max_depth--; + my_divisor = 0; + return true; + } else return false; + } + bool should_create_trap() { + return my_divisor > 0; + } + bool check_for_demand(task &t) { + if( static_cast(t.parent())->child_stolen ) { + my_max_depth++; + return true; + } else return false; + } + void align_depth(depth_t base) { + __TBB_ASSERT(base <= my_max_depth, 0); + my_max_depth -= base; + } + depth_t max_depth() { return my_max_depth; } +}; + +//! Provides default methods for affinity (adaptive) partition objects. +class affinity_partition_type : public auto_partition_type_base { + static const unsigned factor_power = 4; + static const unsigned factor = 1< factor ) + d &= 0u-factor; + map_mid = map_end - d; + } +public: + affinity_partition_type( tbb::internal::affinity_partitioner_base_v3& ap ) { + __TBB_ASSERT( (factor&(factor-1))==0, "factor must be power of two" ); + ap.resize(factor); + my_array = ap.my_array; + map_begin = 0; + map_end = unsigned(ap.my_size); + set_mid(); + my_delay = true; + my_divisor /= __TBB_INITIAL_CHUNKS; // let exactly P tasks to be distributed across workers + my_max_depth = factor_power+1; // the first factor_power ranges will be spawned, and >=1 ranges should be left + __TBB_ASSERT( my_max_depth < __TBB_RANGE_POOL_CAPACITY, 0 ); + } + affinity_partition_type(affinity_partition_type& p, split) + : auto_partition_type_base(p, split()), my_array(p.my_array) { + __TBB_ASSERT( p.map_end-p.map_begin__TBB_Log2(map_end-map_mid), 0); + return true;// do not do my_max_depth++ here, but be sure my_max_depth is big enough + } + if( static_cast(t.parent())->child_stolen ) { + my_max_depth++; + return true; + } + } else my_delay = false; + return false; + } + bool divisions_left() { // part of old should_execute_range() + return my_divisor > 1; + } + bool should_create_trap() { + return true; // TODO: rethink for the stage after memorizing level + } + static const unsigned range_pool_size = __TBB_RANGE_POOL_CAPACITY; +}; + +class auto_partition_type: public auto_partition_type_base { +public: + auto_partition_type( const auto_partitioner& ) {} + auto_partition_type( auto_partition_type& src, split) + : auto_partition_type_base(src, split()) {} + static const unsigned range_pool_size = __TBB_RANGE_POOL_CAPACITY; +}; + +class simple_partition_type: public partition_type_base { +public: + simple_partition_type( const simple_partitioner& ) {} + simple_partition_type( const simple_partition_type&, split ) {} + //! simplified algorithm + template + void execute(StartType &start, Range &range) { + while( range.is_divisible() ) + split_work( start ); + start.run_body( range ); + } + //static const unsigned range_pool_size = 1; - not necessary because execute() is overridden +}; + +//! Backward-compatible partition for auto and affinity partition objects. +class old_auto_partition_type: public tbb::internal::partition_type_base { + size_t num_chunks; + static const size_t VICTIM_CHUNKS = 4; +public: + bool should_execute_range(const task &t) { + if( num_chunks friend class serial::interface6::start_for; + template friend class interface6::internal::start_for; + template friend class interface6::internal::start_reduce; + template friend class internal::start_scan; + // backward compatibility + class partition_type: public internal::partition_type_base { + public: + bool should_execute_range(const task& ) {return false;} + partition_type( const simple_partitioner& ) {} + partition_type( const partition_type&, split ) {} + }; + // new implementation just extends existing interface + typedef interface6::internal::simple_partition_type task_partition_type; +}; + +//! An auto partitioner +/** The range is initial divided into several large chunks. + Chunks are further subdivided into smaller pieces if demand detected and they are divisible. + @ingroup algorithms */ +class auto_partitioner { +public: + auto_partitioner() {} + +private: + template friend class serial::interface6::start_for; + template friend class interface6::internal::start_for; + template friend class interface6::internal::start_reduce; + template friend class internal::start_scan; + // backward compatibility + typedef interface6::internal::old_auto_partition_type partition_type; + // new implementation just extends existing interface + typedef interface6::internal::auto_partition_type task_partition_type; +}; + +//! An affinity partitioner +class affinity_partitioner: internal::affinity_partitioner_base_v3 { +public: + affinity_partitioner() {} + +private: + template friend class serial::interface6::start_for; + template friend class interface6::internal::start_for; + template friend class interface6::internal::start_reduce; + template friend class internal::start_scan; + // backward compatibility - for parallel_scan only + typedef interface6::internal::old_auto_partition_type partition_type; + // new implementation just extends existing interface + typedef interface6::internal::affinity_partition_type task_partition_type; +}; + +} // namespace tbb + +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) + #pragma warning (pop) +#endif // warning 4244 is back +#undef __TBB_INITIAL_CHUNKS +#undef __TBB_RANGE_POOL_CAPACITY +#undef __TBB_INIT_DEPTH +#endif /* __TBB_partitioner_H */ diff --git a/src/tbb/include/tbb/pipeline.h b/src/tbb/include/tbb/pipeline.h new file mode 100644 index 0000000..18f9d47 --- /dev/null +++ b/src/tbb/include/tbb/pipeline.h @@ -0,0 +1,662 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_pipeline_H +#define __TBB_pipeline_H + +#include "atomic.h" +#include "task.h" +#include "tbb_allocator.h" +#include + +#if !TBB_IMPLEMENT_CPP0X +#include +#endif + +namespace tbb { + +class pipeline; +class filter; + +//! @cond INTERNAL +namespace internal { + +// The argument for PIPELINE_VERSION should be an integer between 2 and 9 +#define __TBB_PIPELINE_VERSION(x) (unsigned char)(x-2)<<1 + +typedef unsigned long Token; +typedef long tokendiff_t; +class stage_task; +class input_buffer; +class pipeline_root_task; +class pipeline_cleaner; + +} // namespace internal + +namespace interface6 { + template class filter_t; + + namespace internal { + class pipeline_proxy; + } +} + +//! @endcond + +//! A stage in a pipeline. +/** @ingroup algorithms */ +class filter: internal::no_copy { +private: + //! Value used to mark "not in pipeline" + static filter* not_in_pipeline() {return reinterpret_cast(intptr_t(-1));} +protected: + //! The lowest bit 0 is for parallel vs. serial + static const unsigned char filter_is_serial = 0x1; + + //! 4th bit distinguishes ordered vs unordered filters. + /** The bit was not set for parallel filters in TBB 2.1 and earlier, + but is_ordered() function always treats parallel filters as out of order. */ + static const unsigned char filter_is_out_of_order = 0x1<<4; + + //! 5th bit distinguishes thread-bound and regular filters. + static const unsigned char filter_is_bound = 0x1<<5; + + //! 6th bit marks input filters emitting small objects + static const unsigned char filter_may_emit_null = 0x1<<6; + + //! 7th bit defines exception propagation mode expected by the application. + static const unsigned char exact_exception_propagation = +#if TBB_USE_CAPTURED_EXCEPTION + 0x0; +#else + 0x1<<7; +#endif /* TBB_USE_CAPTURED_EXCEPTION */ + + static const unsigned char current_version = __TBB_PIPELINE_VERSION(5); + static const unsigned char version_mask = 0x7<<1; // bits 1-3 are for version +public: + enum mode { + //! processes multiple items in parallel and in no particular order + parallel = current_version | filter_is_out_of_order, + //! processes items one at a time; all such filters process items in the same order + serial_in_order = current_version | filter_is_serial, + //! processes items one at a time and in no particular order + serial_out_of_order = current_version | filter_is_serial | filter_is_out_of_order, + //! @deprecated use serial_in_order instead + serial = serial_in_order + }; +protected: + filter( bool is_serial_ ) : + next_filter_in_pipeline(not_in_pipeline()), + my_input_buffer(NULL), + my_filter_mode(static_cast((is_serial_ ? serial : parallel) | exact_exception_propagation)), + prev_filter_in_pipeline(not_in_pipeline()), + my_pipeline(NULL), + next_segment(NULL) + {} + + filter( mode filter_mode ) : + next_filter_in_pipeline(not_in_pipeline()), + my_input_buffer(NULL), + my_filter_mode(static_cast(filter_mode | exact_exception_propagation)), + prev_filter_in_pipeline(not_in_pipeline()), + my_pipeline(NULL), + next_segment(NULL) + {} + + // signal end-of-input for concrete_filters + void __TBB_EXPORTED_METHOD set_end_of_input(); + +public: + //! True if filter is serial. + bool is_serial() const { + return bool( my_filter_mode & filter_is_serial ); + } + + //! True if filter must receive stream in order. + bool is_ordered() const { + return (my_filter_mode & (filter_is_out_of_order|filter_is_serial))==filter_is_serial; + } + + //! True if filter is thread-bound. + bool is_bound() const { + return ( my_filter_mode & filter_is_bound )==filter_is_bound; + } + + //! true if an input filter can emit null + bool object_may_be_null() { + return ( my_filter_mode & filter_may_emit_null ) == filter_may_emit_null; + } + + //! Operate on an item from the input stream, and return item for output stream. + /** Returns NULL if filter is a sink. */ + virtual void* operator()( void* item ) = 0; + + //! Destroy filter. + /** If the filter was added to a pipeline, the pipeline must be destroyed first. */ + virtual __TBB_EXPORTED_METHOD ~filter(); + +#if __TBB_TASK_GROUP_CONTEXT + //! Destroys item if pipeline was cancelled. + /** Required to prevent memory leaks. + Note it can be called concurrently even for serial filters.*/ + virtual void finalize( void* /*item*/ ) {}; +#endif + +private: + //! Pointer to next filter in the pipeline. + filter* next_filter_in_pipeline; + + //! has the filter not yet processed all the tokens it will ever see? + // (pipeline has not yet reached end_of_input or this filter has not yet + // seen the last token produced by input_filter) + bool has_more_work(); + + //! Buffer for incoming tokens, or NULL if not required. + /** The buffer is required if the filter is serial or follows a thread-bound one. */ + internal::input_buffer* my_input_buffer; + + friend class internal::stage_task; + friend class internal::pipeline_root_task; + friend class pipeline; + friend class thread_bound_filter; + + //! Storage for filter mode and dynamically checked implementation version. + const unsigned char my_filter_mode; + + //! Pointer to previous filter in the pipeline. + filter* prev_filter_in_pipeline; + + //! Pointer to the pipeline. + pipeline* my_pipeline; + + //! Pointer to the next "segment" of filters, or NULL if not required. + /** In each segment, the first filter is not thread-bound but follows a thread-bound one. */ + filter* next_segment; +}; + +//! A stage in a pipeline served by a user thread. +/** @ingroup algorithms */ +class thread_bound_filter: public filter { +public: + enum result_type { + // item was processed + success, + // item is currently not available + item_not_available, + // there are no more items to process + end_of_stream + }; +protected: + thread_bound_filter(mode filter_mode): + filter(static_cast(filter_mode | filter::filter_is_bound)) + {} +public: + //! If a data item is available, invoke operator() on that item. + /** This interface is non-blocking. + Returns 'success' if an item was processed. + Returns 'item_not_available' if no item can be processed now + but more may arrive in the future, or if token limit is reached. + Returns 'end_of_stream' if there are no more items to process. */ + result_type __TBB_EXPORTED_METHOD try_process_item(); + + //! Wait until a data item becomes available, and invoke operator() on that item. + /** This interface is blocking. + Returns 'success' if an item was processed. + Returns 'end_of_stream' if there are no more items to process. + Never returns 'item_not_available', as it blocks until another return condition applies. */ + result_type __TBB_EXPORTED_METHOD process_item(); + +private: + //! Internal routine for item processing + result_type internal_process_item(bool is_blocking); +}; + +//! A processing pipeline that applies filters to items. +/** @ingroup algorithms */ +class pipeline { +public: + //! Construct empty pipeline. + __TBB_EXPORTED_METHOD pipeline(); + + /** Though the current implementation declares the destructor virtual, do not rely on this + detail. The virtualness is deprecated and may disappear in future versions of TBB. */ + virtual __TBB_EXPORTED_METHOD ~pipeline(); + + //! Add filter to end of pipeline. + void __TBB_EXPORTED_METHOD add_filter( filter& filter_ ); + + //! Run the pipeline to completion. + void __TBB_EXPORTED_METHOD run( size_t max_number_of_live_tokens ); + +#if __TBB_TASK_GROUP_CONTEXT + //! Run the pipeline to completion with user-supplied context. + void __TBB_EXPORTED_METHOD run( size_t max_number_of_live_tokens, tbb::task_group_context& context ); +#endif + + //! Remove all filters from the pipeline. + void __TBB_EXPORTED_METHOD clear(); + +private: + friend class internal::stage_task; + friend class internal::pipeline_root_task; + friend class filter; + friend class thread_bound_filter; + friend class internal::pipeline_cleaner; + friend class tbb::interface6::internal::pipeline_proxy; + + //! Pointer to first filter in the pipeline. + filter* filter_list; + + //! Pointer to location where address of next filter to be added should be stored. + filter* filter_end; + + //! task who's reference count is used to determine when all stages are done. + task* end_counter; + + //! Number of idle tokens waiting for input stage. + atomic input_tokens; + + //! Global counter of tokens + atomic token_counter; + + //! False until fetch_input returns NULL. + bool end_of_input; + + //! True if the pipeline contains a thread-bound filter; false otherwise. + bool has_thread_bound_filters; + + //! Remove filter from pipeline. + void remove_filter( filter& filter_ ); + + //! Not used, but retained to satisfy old export files. + void __TBB_EXPORTED_METHOD inject_token( task& self ); + +#if __TBB_TASK_GROUP_CONTEXT + //! Does clean up if pipeline is cancelled or exception occured + void clear_filters(); +#endif +}; + +//------------------------------------------------------------------------ +// Support for lambda-friendly parallel_pipeline interface +//------------------------------------------------------------------------ + +namespace interface6 { + +namespace internal { + template class concrete_filter; +} + +//! input_filter control to signal end-of-input for parallel_pipeline +class flow_control { + bool is_pipeline_stopped; + flow_control() { is_pipeline_stopped = false; } + template friend class internal::concrete_filter; +public: + void stop() { is_pipeline_stopped = true; } +}; + +//! @cond INTERNAL +namespace internal { + +template struct tbb_large_object {enum { value = sizeof(T) > sizeof(void *) }; }; + +#if TBB_IMPLEMENT_CPP0X +// cannot use SFINAE in current compilers. Explicitly list the types we wish to be +// placed as-is in the pipeline input_buffers. +template struct tbb_trivially_copyable { enum { value = false }; }; +template struct tbb_trivially_copyable { enum { value = true }; }; +template<> struct tbb_trivially_copyable { enum { value = true }; }; +template<> struct tbb_trivially_copyable { enum { value = true }; }; +template<> struct tbb_trivially_copyable { enum { value = !tbb_large_object::value }; }; +template<> struct tbb_trivially_copyable { enum { value = !tbb_large_object::value }; }; +template<> struct tbb_trivially_copyable { enum { value = !tbb_large_object::value }; }; +template<> struct tbb_trivially_copyable { enum { value = !tbb_large_object::value }; }; +template<> struct tbb_trivially_copyable { enum { value = !tbb_large_object::value }; }; +template<> struct tbb_trivially_copyable { enum { value = !tbb_large_object::value }; }; +#else +#if __GNUC__==4 && __GNUC_MINOR__>=4 && __GXX_EXPERIMENTAL_CXX0X__ +template struct tbb_trivially_copyable { enum { value = std::has_trivial_copy_constructor::value }; }; +#else +template struct tbb_trivially_copyable { enum { value = std::is_trivially_copyable::value }; }; +#endif // +#endif // __TBB_USE_CPP0X + +template struct is_large_object {enum { value = tbb_large_object::value || !tbb_trivially_copyable::value }; }; + +template class token_helper; + +// large object helper (uses tbb_allocator) +template +class token_helper { + public: + typedef typename tbb::tbb_allocator allocator; + typedef T* pointer; + typedef T value_type; + static pointer create_token(const value_type & source) { + pointer output_t = allocator().allocate(1); + return new (output_t) T(source); + } + static value_type & token(pointer & t) { return *t;} + static void * cast_to_void_ptr(pointer ref) { return (void *) ref; } + static pointer cast_from_void_ptr(void * ref) { return (pointer)ref; } + static void destroy_token(pointer token) { + allocator().destroy(token); + allocator().deallocate(token,1); + } +}; + +// pointer specialization +template +class token_helper { + public: + typedef T* pointer; + typedef T* value_type; + static pointer create_token(const value_type & source) { return source; } + static value_type & token(pointer & t) { return t;} + static void * cast_to_void_ptr(pointer ref) { return (void *)ref; } + static pointer cast_from_void_ptr(void * ref) { return (pointer)ref; } + static void destroy_token( pointer /*token*/) {} +}; + +// small object specialization (converts void* to the correct type, passes objects directly.) +template +class token_helper { + typedef union { + T actual_value; + void * void_overlay; + } type_to_void_ptr_map; + public: + typedef T pointer; // not really a pointer in this case. + typedef T value_type; + static pointer create_token(const value_type & source) { + return source; } + static value_type & token(pointer & t) { return t;} + static void * cast_to_void_ptr(pointer ref) { + type_to_void_ptr_map mymap; + mymap.void_overlay = NULL; + mymap.actual_value = ref; + return mymap.void_overlay; + } + static pointer cast_from_void_ptr(void * ref) { + type_to_void_ptr_map mymap; + mymap.void_overlay = ref; + return mymap.actual_value; + } + static void destroy_token( pointer /*token*/) {} +}; + +template +class concrete_filter: public tbb::filter { + const Body& my_body; + typedef token_helper::value > t_helper; + typedef typename t_helper::pointer t_pointer; + typedef token_helper::value > u_helper; + typedef typename u_helper::pointer u_pointer; + + /*override*/ void* operator()(void* input) { + t_pointer temp_input = t_helper::cast_from_void_ptr(input); + u_pointer output_u = u_helper::create_token(my_body(t_helper::token(temp_input))); + t_helper::destroy_token(temp_input); + return u_helper::cast_to_void_ptr(output_u); + } + +public: + concrete_filter(tbb::filter::mode filter_mode, const Body& body) : filter(filter_mode), my_body(body) {} +}; + +// input +template +class concrete_filter: public filter { + const Body& my_body; + typedef token_helper::value > u_helper; + typedef typename u_helper::pointer u_pointer; + + /*override*/void* operator()(void*) { + flow_control control; + u_pointer output_u = u_helper::create_token(my_body(control)); + if(control.is_pipeline_stopped) { + u_helper::destroy_token(output_u); + set_end_of_input(); + return NULL; + } + return u_helper::cast_to_void_ptr(output_u); + } + +public: + concrete_filter(tbb::filter::mode filter_mode, const Body& body) : + filter(static_cast(filter_mode | filter_may_emit_null)), + my_body(body) + {} +}; + +template +class concrete_filter: public filter { + const Body& my_body; + typedef token_helper::value > t_helper; + typedef typename t_helper::pointer t_pointer; + + /*override*/ void* operator()(void* input) { + t_pointer temp_input = t_helper::cast_from_void_ptr(input); + my_body(t_helper::token(temp_input)); + t_helper::destroy_token(temp_input); + return NULL; + } +public: + concrete_filter(tbb::filter::mode filter_mode, const Body& body) : filter(filter_mode), my_body(body) {} +}; + +template +class concrete_filter: public filter { + const Body& my_body; + + /** Override privately because it is always called virtually */ + /*override*/ void* operator()(void*) { + flow_control control; + my_body(control); + void* output = control.is_pipeline_stopped ? NULL : (void*)(intptr_t)-1; + return output; + } +public: + concrete_filter(filter::mode filter_mode, const Body& body) : filter(filter_mode), my_body(body) {} +}; + +//! The class that represents an object of the pipeline for parallel_pipeline(). +/** It primarily serves as RAII class that deletes heap-allocated filter instances. */ +class pipeline_proxy { + tbb::pipeline my_pipe; +public: + pipeline_proxy( const filter_t& filter_chain ); + ~pipeline_proxy() { + while( filter* f = my_pipe.filter_list ) + delete f; // filter destructor removes it from the pipeline + } + tbb::pipeline* operator->() { return &my_pipe; } +}; + +//! Abstract base class that represents a node in a parse tree underlying a filter_t. +/** These nodes are always heap-allocated and can be shared by filter_t objects. */ +class filter_node: tbb::internal::no_copy { + /** Count must be atomic because it is hidden state for user, but might be shared by threads. */ + tbb::atomic ref_count; +protected: + filter_node() { + ref_count = 0; +#ifdef __TBB_TEST_FILTER_NODE_COUNT + ++(__TBB_TEST_FILTER_NODE_COUNT); +#endif + } +public: + //! Add concrete_filter to pipeline + virtual void add_to( pipeline& ) = 0; + //! Increment reference count + void add_ref() {++ref_count;} + //! Decrement reference count and delete if it becomes zero. + void remove_ref() { + __TBB_ASSERT(ref_count>0,"ref_count underflow"); + if( --ref_count==0 ) + delete this; + } + virtual ~filter_node() { +#ifdef __TBB_TEST_FILTER_NODE_COUNT + --(__TBB_TEST_FILTER_NODE_COUNT); +#endif + } +}; + +//! Node in parse tree representing result of make_filter. +template +class filter_node_leaf: public filter_node { + const tbb::filter::mode mode; + const Body body; + /*override*/void add_to( pipeline& p ) { + concrete_filter* f = new concrete_filter(mode,body); + p.add_filter( *f ); + } +public: + filter_node_leaf( tbb::filter::mode m, const Body& b ) : mode(m), body(b) {} +}; + +//! Node in parse tree representing join of two filters. +class filter_node_join: public filter_node { + friend class filter_node; // to suppress GCC 3.2 warnings + filter_node& left; + filter_node& right; + /*override*/~filter_node_join() { + left.remove_ref(); + right.remove_ref(); + } + /*override*/void add_to( pipeline& p ) { + left.add_to(p); + right.add_to(p); + } +public: + filter_node_join( filter_node& x, filter_node& y ) : left(x), right(y) { + left.add_ref(); + right.add_ref(); + } +}; + +} // namespace internal +//! @endcond + +//! Create a filter to participate in parallel_pipeline +template +filter_t make_filter(tbb::filter::mode mode, const Body& body) { + return new internal::filter_node_leaf(mode, body); +} + +template +filter_t operator& (const filter_t& left, const filter_t& right) { + __TBB_ASSERT(left.root,"cannot use default-constructed filter_t as left argument of '&'"); + __TBB_ASSERT(right.root,"cannot use default-constructed filter_t as right argument of '&'"); + return new internal::filter_node_join(*left.root,*right.root); +} + +//! Class representing a chain of type-safe pipeline filters +template +class filter_t { + typedef internal::filter_node filter_node; + filter_node* root; + filter_t( filter_node* root_ ) : root(root_) { + root->add_ref(); + } + friend class internal::pipeline_proxy; + template + friend filter_t make_filter(tbb::filter::mode, const Body& ); + template + friend filter_t operator& (const filter_t& , const filter_t& ); +public: + filter_t() : root(NULL) {} + filter_t( const filter_t& rhs ) : root(rhs.root) { + if( root ) root->add_ref(); + } + template + filter_t( tbb::filter::mode mode, const Body& body ) : + root( new internal::filter_node_leaf(mode, body) ) { + root->add_ref(); + } + + void operator=( const filter_t& rhs ) { + // Order of operations below carefully chosen so that reference counts remain correct + // in unlikely event that remove_ref throws exception. + filter_node* old = root; + root = rhs.root; + if( root ) root->add_ref(); + if( old ) old->remove_ref(); + } + ~filter_t() { + if( root ) root->remove_ref(); + } + void clear() { + // Like operator= with filter_t() on right side. + if( root ) { + filter_node* old = root; + root = NULL; + old->remove_ref(); + } + } +}; + +inline internal::pipeline_proxy::pipeline_proxy( const filter_t& filter_chain ) : my_pipe() { + __TBB_ASSERT( filter_chain.root, "cannot apply parallel_pipeline to default-constructed filter_t" ); + filter_chain.root->add_to(my_pipe); +} + +inline void parallel_pipeline(size_t max_number_of_live_tokens, const filter_t& filter_chain +#if __TBB_TASK_GROUP_CONTEXT + , tbb::task_group_context& context +#endif + ) { + internal::pipeline_proxy pipe(filter_chain); + // tbb::pipeline::run() is called via the proxy + pipe->run(max_number_of_live_tokens +#if __TBB_TASK_GROUP_CONTEXT + , context +#endif + ); +} + +#if __TBB_TASK_GROUP_CONTEXT +inline void parallel_pipeline(size_t max_number_of_live_tokens, const filter_t& filter_chain) { + tbb::task_group_context context; + parallel_pipeline(max_number_of_live_tokens, filter_chain, context); +} +#endif // __TBB_TASK_GROUP_CONTEXT + +} // interface6 + +using interface6::flow_control; +using interface6::filter_t; +using interface6::make_filter; +using interface6::parallel_pipeline; + +} // tbb + +#endif /* __TBB_pipeline_H */ diff --git a/src/tbb/include/tbb/queuing_mutex.h b/src/tbb/include/tbb/queuing_mutex.h new file mode 100644 index 0000000..04d675b --- /dev/null +++ b/src/tbb/include/tbb/queuing_mutex.h @@ -0,0 +1,131 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_queuing_mutex_H +#define __TBB_queuing_mutex_H + +#include "tbb_config.h" + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +#include "atomic.h" +#include "tbb_profiling.h" + +namespace tbb { + +//! Queuing mutex with local-only spinning. +/** @ingroup synchronization */ +class queuing_mutex { +public: + //! Construct unacquired mutex. + queuing_mutex() { + q_tail = NULL; +#if TBB_USE_THREADING_TOOLS + internal_construct(); +#endif + } + + //! The scoped locking pattern + /** It helps to avoid the common problem of forgetting to release lock. + It also nicely provides the "node" for queuing locks. */ + class scoped_lock: internal::no_copy { + //! Initialize fields to mean "no lock held". + void initialize() { + mutex = NULL; +#if TBB_USE_ASSERT + internal::poison_pointer(next); +#endif /* TBB_USE_ASSERT */ + } + + public: + //! Construct lock that has not acquired a mutex. + /** Equivalent to zero-initialization of *this. */ + scoped_lock() {initialize();} + + //! Acquire lock on given mutex. + scoped_lock( queuing_mutex& m ) { + initialize(); + acquire(m); + } + + //! Release lock (if lock is held). + ~scoped_lock() { + if( mutex ) release(); + } + + //! Acquire lock on given mutex. + void __TBB_EXPORTED_METHOD acquire( queuing_mutex& m ); + + //! Acquire lock on given mutex if free (i.e. non-blocking) + bool __TBB_EXPORTED_METHOD try_acquire( queuing_mutex& m ); + + //! Release lock. + void __TBB_EXPORTED_METHOD release(); + + private: + //! The pointer to the mutex owned, or NULL if not holding a mutex. + queuing_mutex* mutex; + + //! The pointer to the next competitor for a mutex + scoped_lock *next; + + //! The local spin-wait variable + /** Inverted (0 - blocked, 1 - acquired the mutex) for the sake of + zero-initialization. Defining it as an entire word instead of + a byte seems to help performance slightly. */ + uintptr_t going; + }; + + void __TBB_EXPORTED_METHOD internal_construct(); + + // Mutex traits + static const bool is_rw_mutex = false; + static const bool is_recursive_mutex = false; + static const bool is_fair_mutex = true; + +private: + //! The last competitor requesting the lock + atomic q_tail; + +}; + +__TBB_DEFINE_PROFILING_SET_NAME(queuing_mutex) + +} // namespace tbb + +#endif /* __TBB_queuing_mutex_H */ diff --git a/src/tbb/include/tbb/queuing_rw_mutex.h b/src/tbb/include/tbb/queuing_rw_mutex.h new file mode 100644 index 0000000..57e1d25 --- /dev/null +++ b/src/tbb/include/tbb/queuing_rw_mutex.h @@ -0,0 +1,171 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_queuing_rw_mutex_H +#define __TBB_queuing_rw_mutex_H + +#include "tbb_config.h" + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +#include "atomic.h" +#include "tbb_profiling.h" + +namespace tbb { + +//! Queuing reader-writer mutex with local-only spinning. +/** Adapted from Krieger, Stumm, et al. pseudocode at + http://www.eecg.toronto.edu/parallel/pubs_abs.html#Krieger_etal_ICPP93 + @ingroup synchronization */ +class queuing_rw_mutex { +public: + //! Construct unacquired mutex. + queuing_rw_mutex() { + q_tail = NULL; +#if TBB_USE_THREADING_TOOLS + internal_construct(); +#endif + } + + //! Destructor asserts if the mutex is acquired, i.e. q_tail is non-NULL + ~queuing_rw_mutex() { +#if TBB_USE_ASSERT + __TBB_ASSERT( !q_tail, "destruction of an acquired mutex"); +#endif + } + + //! The scoped locking pattern + /** It helps to avoid the common problem of forgetting to release lock. + It also nicely provides the "node" for queuing locks. */ + class scoped_lock: internal::no_copy { + //! Initialize fields to mean "no lock held". + void initialize() { + my_mutex = NULL; +#if TBB_USE_ASSERT + my_state = 0xFF; // Set to invalid state + internal::poison_pointer(my_next); + internal::poison_pointer(my_prev); +#endif /* TBB_USE_ASSERT */ + } + + public: + //! Construct lock that has not acquired a mutex. + /** Equivalent to zero-initialization of *this. */ + scoped_lock() {initialize();} + + //! Acquire lock on given mutex. + scoped_lock( queuing_rw_mutex& m, bool write=true ) { + initialize(); + acquire(m,write); + } + + //! Release lock (if lock is held). + ~scoped_lock() { + if( my_mutex ) release(); + } + + //! Acquire lock on given mutex. + void acquire( queuing_rw_mutex& m, bool write=true ); + + //! Acquire lock on given mutex if free (i.e. non-blocking) + bool try_acquire( queuing_rw_mutex& m, bool write=true ); + + //! Release lock. + void release(); + + //! Upgrade reader to become a writer. + /** Returns whether the upgrade happened without releasing and re-acquiring the lock */ + bool upgrade_to_writer(); + + //! Downgrade writer to become a reader. + bool downgrade_to_reader(); + + private: + //! The pointer to the mutex owned, or NULL if not holding a mutex. + queuing_rw_mutex* my_mutex; + + //! The pointer to the previous and next competitors for a mutex + scoped_lock *__TBB_atomic my_prev, *__TBB_atomic my_next; + + typedef unsigned char state_t; + + //! State of the request: reader, writer, active reader, other service states + atomic my_state; + + //! The local spin-wait variable + /** Corresponds to "spin" in the pseudocode but inverted for the sake of zero-initialization */ + unsigned char __TBB_atomic my_going; + + //! A tiny internal lock + unsigned char my_internal_lock; + + //! Acquire the internal lock + void acquire_internal_lock(); + + //! Try to acquire the internal lock + /** Returns true if lock was successfully acquired. */ + bool try_acquire_internal_lock(); + + //! Release the internal lock + void release_internal_lock(); + + //! Wait for internal lock to be released + void wait_for_release_of_internal_lock(); + + //! A helper function + void unblock_or_wait_on_internal_lock( uintptr_t ); + }; + + void __TBB_EXPORTED_METHOD internal_construct(); + + // Mutex traits + static const bool is_rw_mutex = true; + static const bool is_recursive_mutex = false; + static const bool is_fair_mutex = true; + +private: + //! The last competitor requesting the lock + atomic q_tail; + +}; + +__TBB_DEFINE_PROFILING_SET_NAME(queuing_rw_mutex) + +} // namespace tbb + +#endif /* __TBB_queuing_rw_mutex_H */ diff --git a/src/tbb/include/tbb/reader_writer_lock.h b/src/tbb/include/tbb/reader_writer_lock.h new file mode 100644 index 0000000..23084de --- /dev/null +++ b/src/tbb/include/tbb/reader_writer_lock.h @@ -0,0 +1,240 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_reader_writer_lock_H +#define __TBB_reader_writer_lock_H + +#include "tbb_thread.h" +#include "tbb_allocator.h" +#include "atomic.h" + +namespace tbb { +namespace interface5 { +//! Writer-preference reader-writer lock with local-only spinning on readers. +/** Loosely adapted from Mellor-Crummey and Scott pseudocode at + http://www.cs.rochester.edu/research/synchronization/pseudocode/rw.html#s_wp + @ingroup synchronization */ + class reader_writer_lock : tbb::internal::no_copy { + public: + friend class scoped_lock; + friend class scoped_lock_read; + //! Status type for nodes associated with lock instances + /** waiting_nonblocking: the wait state for nonblocking lock + instances; for writes, these transition straight to active + states; for reads, these are unused. + + waiting: the start and spin state for all lock instances; these will + transition to active state when appropriate. Non-blocking write locks + transition from this state to waiting_nonblocking immediately. + + active: the active state means that the lock instance holds + the lock; it will transition to invalid state during node deletion + + invalid: the end state for all nodes; this is set in the + destructor so if we encounter this state, we are looking at + memory that has already been freed + + The state diagrams below describe the status transitions. + Single arrows indicate that the thread that owns the node is + responsible for the transition; double arrows indicate that + any thread could make the transition. + + State diagram for scoped_lock status: + + waiting ----------> waiting_nonblocking + | _____________/ | + V V V + active -----------------> invalid + + State diagram for scoped_lock_read status: + + waiting + | + V + active ----------------->invalid + + */ + enum status_t { waiting_nonblocking, waiting, active, invalid }; + + //! Constructs a new reader_writer_lock + reader_writer_lock() { + internal_construct(); + } + + //! Destructs a reader_writer_lock object + ~reader_writer_lock() { + internal_destroy(); + } + + //! The scoped lock pattern for write locks + /** Scoped locks help avoid the common problem of forgetting to release the lock. + This type also serves as the node for queuing locks. */ + class scoped_lock : tbb::internal::no_copy { + public: + friend class reader_writer_lock; + + //! Construct with blocking attempt to acquire write lock on the passed-in lock + scoped_lock(reader_writer_lock& lock) { + internal_construct(lock); + } + + //! Destructor, releases the write lock + ~scoped_lock() { + internal_destroy(); + } + + void* operator new(size_t s) { + return tbb::internal::allocate_via_handler_v3(s); + } + void operator delete(void* p) { + tbb::internal::deallocate_via_handler_v3(p); + } + + private: + //! The pointer to the mutex to lock + reader_writer_lock *mutex; + //! The next queued competitor for the mutex + scoped_lock* next; + //! Status flag of the thread associated with this node + atomic status; + + //! Construct scoped_lock that is not holding lock + scoped_lock(); + + void __TBB_EXPORTED_METHOD internal_construct(reader_writer_lock&); + void __TBB_EXPORTED_METHOD internal_destroy(); + }; + + //! The scoped lock pattern for read locks + class scoped_lock_read : tbb::internal::no_copy { + public: + friend class reader_writer_lock; + + //! Construct with blocking attempt to acquire read lock on the passed-in lock + scoped_lock_read(reader_writer_lock& lock) { + internal_construct(lock); + } + + //! Destructor, releases the read lock + ~scoped_lock_read() { + internal_destroy(); + } + + void* operator new(size_t s) { + return tbb::internal::allocate_via_handler_v3(s); + } + void operator delete(void* p) { + tbb::internal::deallocate_via_handler_v3(p); + } + + private: + //! The pointer to the mutex to lock + reader_writer_lock *mutex; + //! The next queued competitor for the mutex + scoped_lock_read *next; + //! Status flag of the thread associated with this node + atomic status; + + //! Construct scoped_lock_read that is not holding lock + scoped_lock_read(); + + void __TBB_EXPORTED_METHOD internal_construct(reader_writer_lock&); + void __TBB_EXPORTED_METHOD internal_destroy(); + }; + + //! Acquires the reader_writer_lock for write. + /** If the lock is currently held in write mode by another + context, the writer will block by spinning on a local + variable. Exceptions thrown: improper_lock The context tries + to acquire a reader_writer_lock that it already has write + ownership of.*/ + void __TBB_EXPORTED_METHOD lock(); + + //! Tries to acquire the reader_writer_lock for write. + /** This function does not block. Return Value: True or false, + depending on whether the lock is acquired or not. If the lock + is already held by this acquiring context, try_lock() returns + false. */ + bool __TBB_EXPORTED_METHOD try_lock(); + + //! Acquires the reader_writer_lock for read. + /** If the lock is currently held by a writer, this reader will + block and wait until the writers are done. Exceptions thrown: + improper_lock The context tries to acquire a + reader_writer_lock that it already has write ownership of. */ + void __TBB_EXPORTED_METHOD lock_read(); + + //! Tries to acquire the reader_writer_lock for read. + /** This function does not block. Return Value: True or false, + depending on whether the lock is acquired or not. */ + bool __TBB_EXPORTED_METHOD try_lock_read(); + + //! Releases the reader_writer_lock + void __TBB_EXPORTED_METHOD unlock(); + + private: + void __TBB_EXPORTED_METHOD internal_construct(); + void __TBB_EXPORTED_METHOD internal_destroy(); + + //! Attempts to acquire write lock + /** If unavailable, spins in blocking case, returns false in non-blocking case. */ + bool start_write(scoped_lock *); + //! Sets writer_head to w and attempts to unblock + void set_next_writer(scoped_lock *w); + //! Relinquishes write lock to next waiting writer or group of readers + void end_write(scoped_lock *); + //! Checks if current thread holds write lock + bool is_current_writer(); + + //! Attempts to acquire read lock + /** If unavailable, spins in blocking case, returns false in non-blocking case. */ + void start_read(scoped_lock_read *); + //! Unblocks pending readers + void unblock_readers(); + //! Relinquishes read lock by decrementing counter; last reader wakes pending writer + void end_read(); + + //! The list of pending readers + atomic reader_head; + //! The list of pending writers + atomic writer_head; + //! The last node in the list of pending writers + atomic writer_tail; + //! Writer that owns the mutex; tbb_thread::id() otherwise. + tbb_thread::id my_current_writer; + //! Status of mutex + atomic rdr_count_and_flags; // used with __TBB_AtomicOR, which assumes uintptr_t +}; + +} // namespace interface5 + +using interface5::reader_writer_lock; + +} // namespace tbb + +#endif /* __TBB_reader_writer_lock_H */ diff --git a/src/tbb/include/tbb/recursive_mutex.h b/src/tbb/include/tbb/recursive_mutex.h new file mode 100644 index 0000000..458eb48 --- /dev/null +++ b/src/tbb/include/tbb/recursive_mutex.h @@ -0,0 +1,240 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_recursive_mutex_H +#define __TBB_recursive_mutex_H + +#if _WIN32||_WIN64 +#include "machine/windows_api.h" +#else +#include +#endif /* _WIN32||_WIN64 */ + +#include +#include "aligned_space.h" +#include "tbb_stddef.h" +#include "tbb_profiling.h" + +namespace tbb { +//! Mutex that allows recursive mutex acquisition. +/** Mutex that allows recursive mutex acquisition. + @ingroup synchronization */ +class recursive_mutex { +public: + //! Construct unacquired recursive_mutex. + recursive_mutex() { +#if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS + internal_construct(); +#else + #if _WIN32||_WIN64 + InitializeCriticalSection(&impl); + #else + pthread_mutexattr_t mtx_attr; + int error_code = pthread_mutexattr_init( &mtx_attr ); + if( error_code ) + tbb::internal::handle_perror(error_code,"recursive_mutex: pthread_mutexattr_init failed"); + + pthread_mutexattr_settype( &mtx_attr, PTHREAD_MUTEX_RECURSIVE ); + error_code = pthread_mutex_init( &impl, &mtx_attr ); + if( error_code ) + tbb::internal::handle_perror(error_code,"recursive_mutex: pthread_mutex_init failed"); + + pthread_mutexattr_destroy( &mtx_attr ); + #endif /* _WIN32||_WIN64*/ +#endif /* TBB_USE_ASSERT */ + }; + + ~recursive_mutex() { +#if TBB_USE_ASSERT + internal_destroy(); +#else + #if _WIN32||_WIN64 + DeleteCriticalSection(&impl); + #else + pthread_mutex_destroy(&impl); + + #endif /* _WIN32||_WIN64 */ +#endif /* TBB_USE_ASSERT */ + }; + + class scoped_lock; + friend class scoped_lock; + + //! The scoped locking pattern + /** It helps to avoid the common problem of forgetting to release lock. + It also nicely provides the "node" for queuing locks. */ + class scoped_lock: internal::no_copy { + public: + //! Construct lock that has not acquired a recursive_mutex. + scoped_lock() : my_mutex(NULL) {}; + + //! Acquire lock on given mutex. + scoped_lock( recursive_mutex& mutex ) { +#if TBB_USE_ASSERT + my_mutex = &mutex; +#endif /* TBB_USE_ASSERT */ + acquire( mutex ); + } + + //! Release lock (if lock is held). + ~scoped_lock() { + if( my_mutex ) + release(); + } + + //! Acquire lock on given mutex. + void acquire( recursive_mutex& mutex ) { +#if TBB_USE_ASSERT + internal_acquire( mutex ); +#else + my_mutex = &mutex; + mutex.lock(); +#endif /* TBB_USE_ASSERT */ + } + + //! Try acquire lock on given recursive_mutex. + bool try_acquire( recursive_mutex& mutex ) { +#if TBB_USE_ASSERT + return internal_try_acquire( mutex ); +#else + bool result = mutex.try_lock(); + if( result ) + my_mutex = &mutex; + return result; +#endif /* TBB_USE_ASSERT */ + } + + //! Release lock + void release() { +#if TBB_USE_ASSERT + internal_release(); +#else + my_mutex->unlock(); + my_mutex = NULL; +#endif /* TBB_USE_ASSERT */ + } + + private: + //! The pointer to the current recursive_mutex to work + recursive_mutex* my_mutex; + + //! All checks from acquire using mutex.state were moved here + void __TBB_EXPORTED_METHOD internal_acquire( recursive_mutex& m ); + + //! All checks from try_acquire using mutex.state were moved here + bool __TBB_EXPORTED_METHOD internal_try_acquire( recursive_mutex& m ); + + //! All checks from release using mutex.state were moved here + void __TBB_EXPORTED_METHOD internal_release(); + + friend class recursive_mutex; + }; + + // Mutex traits + static const bool is_rw_mutex = false; + static const bool is_recursive_mutex = true; + static const bool is_fair_mutex = false; + + // C++0x compatibility interface + + //! Acquire lock + void lock() { +#if TBB_USE_ASSERT + aligned_space tmp; + new(tmp.begin()) scoped_lock(*this); +#else + #if _WIN32||_WIN64 + EnterCriticalSection(&impl); + #else + pthread_mutex_lock(&impl); + #endif /* _WIN32||_WIN64 */ +#endif /* TBB_USE_ASSERT */ + } + + //! Try acquiring lock (non-blocking) + /** Return true if lock acquired; false otherwise. */ + bool try_lock() { +#if TBB_USE_ASSERT + aligned_space tmp; + return (new(tmp.begin()) scoped_lock)->internal_try_acquire(*this); +#else + #if _WIN32||_WIN64 + return TryEnterCriticalSection(&impl)!=0; + #else + return pthread_mutex_trylock(&impl)==0; + #endif /* _WIN32||_WIN64 */ +#endif /* TBB_USE_ASSERT */ + } + + //! Release lock + void unlock() { +#if TBB_USE_ASSERT + aligned_space tmp; + scoped_lock& s = *tmp.begin(); + s.my_mutex = this; + s.internal_release(); +#else + #if _WIN32||_WIN64 + LeaveCriticalSection(&impl); + #else + pthread_mutex_unlock(&impl); + #endif /* _WIN32||_WIN64 */ +#endif /* TBB_USE_ASSERT */ + } + + //! Return native_handle + #if _WIN32||_WIN64 + typedef LPCRITICAL_SECTION native_handle_type; + #else + typedef pthread_mutex_t* native_handle_type; + #endif + native_handle_type native_handle() { return (native_handle_type) &impl; } + +private: +#if _WIN32||_WIN64 + CRITICAL_SECTION impl; + enum state_t { + INITIALIZED=0x1234, + DESTROYED=0x789A, + } state; +#else + pthread_mutex_t impl; +#endif /* _WIN32||_WIN64 */ + + //! All checks from mutex constructor using mutex.state were moved here + void __TBB_EXPORTED_METHOD internal_construct(); + + //! All checks from mutex destructor using mutex.state were moved here + void __TBB_EXPORTED_METHOD internal_destroy(); +}; + +__TBB_DEFINE_PROFILING_SET_NAME(recursive_mutex) + +} // namespace tbb + +#endif /* __TBB_recursive_mutex_H */ diff --git a/src/tbb/include/tbb/runtime_loader.h b/src/tbb/include/tbb/runtime_loader.h new file mode 100644 index 0000000..7b0ee60 --- /dev/null +++ b/src/tbb/include/tbb/runtime_loader.h @@ -0,0 +1,188 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_runtime_loader_H +#define __TBB_runtime_loader_H + +#if ! TBB_PREVIEW_RUNTIME_LOADER + #error Set TBB_PREVIEW_RUNTIME_LOADER to include runtime_loader.h +#endif + +#include "tbb/tbb_stddef.h" +#include + +#if _MSC_VER + #if ! __TBB_NO_IMPLICIT_LINKAGE + #ifdef _DEBUG + #pragma comment( linker, "/nodefaultlib:tbb_debug.lib" ) + #pragma comment( linker, "/defaultlib:tbbproxy_debug.lib" ) + #else + #pragma comment( linker, "/nodefaultlib:tbb.lib" ) + #pragma comment( linker, "/defaultlib:tbbproxy.lib" ) + #endif + #endif +#endif + +namespace tbb { + +namespace interface6 { + +//! Load TBB at runtime. +/*! + +\b Usage: + +In source code: + +\code +#include "tbb/runtime_loader.h" + +char const * path[] = { "/lib/ia32", NULL }; +tbb::runtime_loader loader( path ); + +// Now use TBB. +\endcode + +Link with \c tbbproxy.lib (or \c libtbbproxy.a) instead of \c tbb.lib (\c libtbb.dylib, +\c libtbb.so). + +TBB library will be loaded at runtime from \c /lib/ia32 directory. + +\b Attention: + +All \c runtime_loader objects (in the same module, i.e. exe or dll) share some global state. +The most noticeable piece of global state is loaded TBB library. +There are some implications: + + - Only one TBB library can be loaded per module. + + - If one object has already loaded TBB library, another object will not load TBB. + If the loaded TBB library is suitable for the second object, both will use TBB + cooperatively, otherwise the second object will report an error. + + - \c runtime_loader objects will not work (correctly) in parallel due to absence of + syncronization. + +*/ + +class runtime_loader : tbb::internal::no_copy { + + public: + + //! Error mode constants. + enum error_mode { + em_status, //!< Save status of operation and continue. + em_throw, //!< Throw an exception of tbb::runtime_loader::error_code type. + em_abort //!< Print message to \c stderr and call \c abort(). + }; // error_mode + + //! Error codes. + enum error_code { + ec_ok, //!< No errors. + ec_bad_call, //!< Invalid function call (e. g. load() called when TBB is already loaded). + ec_bad_arg, //!< Invalid argument passed. + ec_bad_lib, //!< Invalid library found (e. g. \c TBB_runtime_version symbol not found). + ec_bad_ver, //!< TBB found but version is not suitable. + ec_no_lib //!< No suitable TBB library found. + }; // error_code + + //! Initialize object but do not load TBB. + runtime_loader( error_mode mode = em_abort ); + + //! Initialize object and load TBB. + /*! + See load() for details. + + If error mode is \c em_status, call status() to check whether TBB was loaded or not. + */ + runtime_loader( + char const * path[], //!< List of directories to search TBB in. + int min_ver = TBB_INTERFACE_VERSION, //!< Minimal suitable version of TBB. + int max_ver = INT_MAX, //!< Maximal suitable version of TBB. + error_mode mode = em_abort //!< Error mode for this object. + ); + + //! Destroy object. + ~runtime_loader(); + + //! Load TBB. + /*! + The method searches the directories specified in \c path[] array for the TBB library. + When the library is found, it is loaded and its version is checked. If the version is + not suitable, the library is unloaded, and the search continues. + + \b Note: + + For security reasons, avoid using relative directory names. For example, never load + TBB from current (\c "."), parent (\c "..") or any other relative directory (like + \c "lib" ). Use only absolute directory names (e. g. "/usr/local/lib"). + + For the same security reasons, avoid using system default directories (\c "") on + Windows. (See http://www.microsoft.com/technet/security/advisory/2269637.mspx for + details.) + + Neglecting these rules may cause your program to execute 3-rd party malicious code. + + \b Errors: + - \c ec_bad_call - TBB already loaded by this object. + - \c ec_bad_arg - \p min_ver and/or \p max_ver negative or zero, + or \p min_ver > \p max_ver. + - \c ec_bad_ver - TBB of unsuitable version already loaded by another object. + - \c ec_no_lib - No suitable library found. + */ + error_code + load( + char const * path[], //!< List of directories to search TBB in. + int min_ver = TBB_INTERFACE_VERSION, //!< Minimal suitable version of TBB. + int max_ver = INT_MAX //!< Maximal suitable version of TBB. + + ); + + + //! Report status. + /*! + If error mode is \c em_status, the function returns status of the last operation. + */ + error_code status(); + + private: + + error_mode const my_mode; + error_code my_status; + bool my_loaded; + +}; // class runtime_loader + +} // namespace interface6 + +using interface6::runtime_loader; + +} // namespace tbb + +#endif /* __TBB_runtime_loader_H */ + diff --git a/src/tbb/include/tbb/scalable_allocator.h b/src/tbb/include/tbb/scalable_allocator.h new file mode 100644 index 0000000..25bdf39 --- /dev/null +++ b/src/tbb/include/tbb/scalable_allocator.h @@ -0,0 +1,281 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_scalable_allocator_H +#define __TBB_scalable_allocator_H +/** @file */ + +#include /* Need ptrdiff_t and size_t from here. */ +#if !_MSC_VER +#include /* Need intptr_t from here. */ +#endif + +#if !defined(__cplusplus) && __ICC==1100 + #pragma warning (push) + #pragma warning (disable: 991) +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if _MSC_VER >= 1400 +#define __TBB_EXPORTED_FUNC __cdecl +#else +#define __TBB_EXPORTED_FUNC +#endif + +/** The "malloc" analogue to allocate block of memory of size bytes. + * @ingroup memory_allocation */ +void * __TBB_EXPORTED_FUNC scalable_malloc (size_t size); + +/** The "free" analogue to discard a previously allocated piece of memory. + @ingroup memory_allocation */ +void __TBB_EXPORTED_FUNC scalable_free (void* ptr); + +/** The "realloc" analogue complementing scalable_malloc. + @ingroup memory_allocation */ +void * __TBB_EXPORTED_FUNC scalable_realloc (void* ptr, size_t size); + +/** The "calloc" analogue complementing scalable_malloc. + @ingroup memory_allocation */ +void * __TBB_EXPORTED_FUNC scalable_calloc (size_t nobj, size_t size); + +/** The "posix_memalign" analogue. + @ingroup memory_allocation */ +int __TBB_EXPORTED_FUNC scalable_posix_memalign (void** memptr, size_t alignment, size_t size); + +/** The "_aligned_malloc" analogue. + @ingroup memory_allocation */ +void * __TBB_EXPORTED_FUNC scalable_aligned_malloc (size_t size, size_t alignment); + +/** The "_aligned_realloc" analogue. + @ingroup memory_allocation */ +void * __TBB_EXPORTED_FUNC scalable_aligned_realloc (void* ptr, size_t size, size_t alignment); + +/** The "_aligned_free" analogue. + @ingroup memory_allocation */ +void __TBB_EXPORTED_FUNC scalable_aligned_free (void* ptr); + +/** The analogue of _msize/malloc_size/malloc_usable_size. + Returns the usable size of a memory block previously allocated by scalable_*, + or 0 (zero) if ptr does not point to such a block. + @ingroup memory_allocation */ +size_t __TBB_EXPORTED_FUNC scalable_msize (void* ptr); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#ifdef __cplusplus + +namespace rml { +class MemoryPool; + +typedef void *(*rawAllocType)(intptr_t pool_id, size_t &bytes); +typedef int (*rawFreeType)(intptr_t pool_id, void* raw_ptr, size_t raw_bytes); + +/* +MemPoolPolicy extension must be compatible with such structure fields layout + +struct MemPoolPolicy { + rawAllocType pAlloc; + rawFreeType pFree; + size_t granularity; // granularity of pAlloc allocations +}; +*/ + +struct MemPoolPolicy { + enum { + VERSION = 1 + }; + + rawAllocType pAlloc; + rawFreeType pFree; + // granularity of pAlloc allocations. 0 means default used. + size_t granularity; + int version; + // all memory consumed at 1st pAlloc call and never returned, + // no more pAlloc calls after 1st + unsigned fixedPool : 1, + // memory consumed but returned only at pool termination + keepAllMemory : 1, + reserved : 30; + + MemPoolPolicy(rawAllocType pAlloc_, rawFreeType pFree_, + size_t granularity_ = 0, bool fixedPool_ = false, + bool keepAllMemory_ = false) : + pAlloc(pAlloc_), pFree(pFree_), granularity(granularity_), version(VERSION), + fixedPool(fixedPool_), keepAllMemory(keepAllMemory_), + reserved(0) {} +}; + +enum MemPoolError { + POOL_OK, // pool created successfully + INVALID_POLICY, // invalid policy parameters found + UNSUPPORTED_POLICY, // requested pool policy is not supported by allocator library + NO_MEMORY // lack of memory during pool creation +}; + +MemPoolError pool_create_v1(intptr_t pool_id, const MemPoolPolicy *policy, + rml::MemoryPool **pool); + +bool pool_destroy(MemoryPool* memPool); +void *pool_malloc(MemoryPool* memPool, size_t size); +void *pool_realloc(MemoryPool* memPool, void *object, size_t size); +void *pool_aligned_malloc(MemoryPool* mPool, size_t size, size_t alignment); +void *pool_aligned_realloc(MemoryPool* mPool, void *ptr, size_t size, size_t alignment); +bool pool_reset(MemoryPool* memPool); +bool pool_free(MemoryPool *memPool, void *object); +} + +#include /* To use new with the placement argument */ + +/* Ensure that including this header does not cause implicit linkage with TBB */ +#ifndef __TBB_NO_IMPLICIT_LINKAGE + #define __TBB_NO_IMPLICIT_LINKAGE 1 + #include "tbb_stddef.h" + #undef __TBB_NO_IMPLICIT_LINKAGE +#else + #include "tbb_stddef.h" +#endif + +#if __TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_CPP11_STD_FORWARD_BROKEN + #include // std::forward +#endif + +namespace tbb { + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // Workaround for erroneous "unreferenced parameter" warning in method destroy. + #pragma warning (push) + #pragma warning (disable: 4100) +#endif + +//! Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5 +/** The members are ordered the same way they are in section 20.4.1 + of the ISO C++ standard. + @ingroup memory_allocation */ +template +class scalable_allocator { +public: + typedef typename internal::allocator_type::value_type value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + template struct rebind { + typedef scalable_allocator other; + }; + + scalable_allocator() throw() {} + scalable_allocator( const scalable_allocator& ) throw() {} + template scalable_allocator(const scalable_allocator&) throw() {} + + pointer address(reference x) const {return &x;} + const_pointer address(const_reference x) const {return &x;} + + //! Allocate space for n objects. + pointer allocate( size_type n, const void* /*hint*/ =0 ) { + return static_cast( scalable_malloc( n * sizeof(value_type) ) ); + } + + //! Free previously allocated block of memory + void deallocate( pointer p, size_type ) { + scalable_free( p ); + } + + //! Largest value for which method allocate might succeed. + size_type max_size() const throw() { + size_type absolutemax = static_cast(-1) / sizeof (value_type); + return (absolutemax > 0 ? absolutemax : 1); + } +#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT + template + void construct(pointer p, Args&&... args) + #if __TBB_CPP11_STD_FORWARD_BROKEN + { ::new((void *)p) T((args)...); } + #else + { ::new((void *)p) T(std::forward(args)...); } + #endif +#else // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT + void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);} +#endif // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT + void destroy( pointer p ) {p->~value_type();} +}; + +#if _MSC_VER && !defined(__INTEL_COMPILER) + #pragma warning (pop) +#endif // warning 4100 is back + +//! Analogous to std::allocator, as defined in ISO C++ Standard, Section 20.4.1 +/** @ingroup memory_allocation */ +template<> +class scalable_allocator { +public: + typedef void* pointer; + typedef const void* const_pointer; + typedef void value_type; + template struct rebind { + typedef scalable_allocator other; + }; +}; + +template +inline bool operator==( const scalable_allocator&, const scalable_allocator& ) {return true;} + +template +inline bool operator!=( const scalable_allocator&, const scalable_allocator& ) {return false;} + +} // namespace tbb + +#if _MSC_VER + #if (__TBB_BUILD || __TBBMALLOC_BUILD) && !defined(__TBBMALLOC_NO_IMPLICIT_LINKAGE) + #define __TBBMALLOC_NO_IMPLICIT_LINKAGE 1 + #endif + + #if !__TBBMALLOC_NO_IMPLICIT_LINKAGE + #ifdef _DEBUG + #pragma comment(lib, "tbbmalloc_debug.lib") + #else + #pragma comment(lib, "tbbmalloc.lib") + #endif + #endif + + +#endif + +#endif /* __cplusplus */ + +#if !defined(__cplusplus) && __ICC==1100 + #pragma warning (pop) +#endif // ICC 11.0 warning 991 is back + +#endif /* __TBB_scalable_allocator_H */ diff --git a/src/tbb/include/tbb/spin_mutex.h b/src/tbb/include/tbb/spin_mutex.h new file mode 100644 index 0000000..2ed29b4 --- /dev/null +++ b/src/tbb/include/tbb/spin_mutex.h @@ -0,0 +1,192 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_spin_mutex_H +#define __TBB_spin_mutex_H + +#include +#include +#include "aligned_space.h" +#include "tbb_stddef.h" +#include "tbb_machine.h" +#include "tbb_profiling.h" + +namespace tbb { + +//! A lock that occupies a single byte. +/** A spin_mutex is a spin mutex that fits in a single byte. + It should be used only for locking short critical sections + (typically less than 20 instructions) when fairness is not an issue. + If zero-initialized, the mutex is considered unheld. + @ingroup synchronization */ +class spin_mutex { + //! 0 if lock is released, 1 if lock is acquired. + __TBB_atomic_flag flag; + +public: + //! Construct unacquired lock. + /** Equivalent to zero-initialization of *this. */ + spin_mutex() : flag(0) { +#if TBB_USE_THREADING_TOOLS + internal_construct(); +#endif + } + + //! Represents acquisition of a mutex. + class scoped_lock : internal::no_copy { + private: + //! Points to currently held mutex, or NULL if no lock is held. + spin_mutex* my_mutex; + + //! Value to store into spin_mutex::flag to unlock the mutex. + __TBB_Flag my_unlock_value; + + //! Like acquire, but with ITT instrumentation. + void __TBB_EXPORTED_METHOD internal_acquire( spin_mutex& m ); + + //! Like try_acquire, but with ITT instrumentation. + bool __TBB_EXPORTED_METHOD internal_try_acquire( spin_mutex& m ); + + //! Like release, but with ITT instrumentation. + void __TBB_EXPORTED_METHOD internal_release(); + + friend class spin_mutex; + + public: + //! Construct without acquiring a mutex. + scoped_lock() : my_mutex(NULL), my_unlock_value(0) {} + + //! Construct and acquire lock on a mutex. + scoped_lock( spin_mutex& m ) { +#if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT + my_mutex=NULL; + internal_acquire(m); +#else + my_unlock_value = __TBB_LockByte(m.flag); + my_mutex=&m; +#endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT*/ + } + + //! Acquire lock. + void acquire( spin_mutex& m ) { +#if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT + internal_acquire(m); +#else + my_unlock_value = __TBB_LockByte(m.flag); + my_mutex = &m; +#endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT*/ + } + + //! Try acquiring lock (non-blocking) + /** Return true if lock acquired; false otherwise. */ + bool try_acquire( spin_mutex& m ) { +#if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT + return internal_try_acquire(m); +#else + bool result = __TBB_TryLockByte(m.flag); + if( result ) { + my_unlock_value = 0; + my_mutex = &m; + } + return result; +#endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT*/ + } + + //! Release lock + void release() { +#if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT + internal_release(); +#else + __TBB_UnlockByte(my_mutex->flag, my_unlock_value); + my_mutex = NULL; +#endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */ + } + + //! Destroy lock. If holding a lock, releases the lock first. + ~scoped_lock() { + if( my_mutex ) { +#if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT + internal_release(); +#else + __TBB_UnlockByte(my_mutex->flag, my_unlock_value); +#endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */ + } + } + }; + + void __TBB_EXPORTED_METHOD internal_construct(); + + // Mutex traits + static const bool is_rw_mutex = false; + static const bool is_recursive_mutex = false; + static const bool is_fair_mutex = false; + + // ISO C++0x compatibility methods + + //! Acquire lock + void lock() { +#if TBB_USE_THREADING_TOOLS + aligned_space tmp; + new(tmp.begin()) scoped_lock(*this); +#else + __TBB_LockByte(flag); +#endif /* TBB_USE_THREADING_TOOLS*/ + } + + //! Try acquiring lock (non-blocking) + /** Return true if lock acquired; false otherwise. */ + bool try_lock() { +#if TBB_USE_THREADING_TOOLS + aligned_space tmp; + return (new(tmp.begin()) scoped_lock)->internal_try_acquire(*this); +#else + return __TBB_TryLockByte(flag); +#endif /* TBB_USE_THREADING_TOOLS*/ + } + + //! Release lock + void unlock() { +#if TBB_USE_THREADING_TOOLS + aligned_space tmp; + scoped_lock& s = *tmp.begin(); + s.my_mutex = this; + s.my_unlock_value = 0; + s.internal_release(); +#else + __TBB_store_with_release(flag, 0); +#endif /* TBB_USE_THREADING_TOOLS */ + } + + friend class scoped_lock; +}; + +__TBB_DEFINE_PROFILING_SET_NAME(spin_mutex) + +} // namespace tbb + +#endif /* __TBB_spin_mutex_H */ diff --git a/src/tbb/include/tbb/spin_rw_mutex.h b/src/tbb/include/tbb/spin_rw_mutex.h new file mode 100644 index 0000000..83c3c67 --- /dev/null +++ b/src/tbb/include/tbb/spin_rw_mutex.h @@ -0,0 +1,227 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_spin_rw_mutex_H +#define __TBB_spin_rw_mutex_H + +#include "tbb_stddef.h" +#include "tbb_machine.h" +#include "tbb_profiling.h" + +namespace tbb { + +class spin_rw_mutex_v3; +typedef spin_rw_mutex_v3 spin_rw_mutex; + +//! Fast, unfair, spinning reader-writer lock with backoff and writer-preference +/** @ingroup synchronization */ +class spin_rw_mutex_v3 { + //! @cond INTERNAL + + //! Internal acquire write lock. + bool __TBB_EXPORTED_METHOD internal_acquire_writer(); + + //! Out of line code for releasing a write lock. + /** This code has debug checking and instrumentation for Intel(R) Thread Checker and Intel(R) Thread Profiler. */ + void __TBB_EXPORTED_METHOD internal_release_writer(); + + //! Internal acquire read lock. + void __TBB_EXPORTED_METHOD internal_acquire_reader(); + + //! Internal upgrade reader to become a writer. + bool __TBB_EXPORTED_METHOD internal_upgrade(); + + //! Out of line code for downgrading a writer to a reader. + /** This code has debug checking and instrumentation for Intel(R) Thread Checker and Intel(R) Thread Profiler. */ + void __TBB_EXPORTED_METHOD internal_downgrade(); + + //! Internal release read lock. + void __TBB_EXPORTED_METHOD internal_release_reader(); + + //! Internal try_acquire write lock. + bool __TBB_EXPORTED_METHOD internal_try_acquire_writer(); + + //! Internal try_acquire read lock. + bool __TBB_EXPORTED_METHOD internal_try_acquire_reader(); + + //! @endcond +public: + //! Construct unacquired mutex. + spin_rw_mutex_v3() : state(0) { +#if TBB_USE_THREADING_TOOLS + internal_construct(); +#endif + } + +#if TBB_USE_ASSERT + //! Destructor asserts if the mutex is acquired, i.e. state is zero. + ~spin_rw_mutex_v3() { + __TBB_ASSERT( !state, "destruction of an acquired mutex"); + }; +#endif /* TBB_USE_ASSERT */ + + //! The scoped locking pattern + /** It helps to avoid the common problem of forgetting to release lock. + It also nicely provides the "node" for queuing locks. */ + class scoped_lock : internal::no_copy { + public: + //! Construct lock that has not acquired a mutex. + /** Equivalent to zero-initialization of *this. */ + scoped_lock() : mutex(NULL), is_writer(false) {} + + //! Acquire lock on given mutex. + scoped_lock( spin_rw_mutex& m, bool write = true ) : mutex(NULL) { + acquire(m, write); + } + + //! Release lock (if lock is held). + ~scoped_lock() { + if( mutex ) release(); + } + + //! Acquire lock on given mutex. + void acquire( spin_rw_mutex& m, bool write = true ) { + __TBB_ASSERT( !mutex, "holding mutex already" ); + is_writer = write; + mutex = &m; + if( write ) mutex->internal_acquire_writer(); + else mutex->internal_acquire_reader(); + } + + //! Upgrade reader to become a writer. + /** Returns whether the upgrade happened without releasing and re-acquiring the lock */ + bool upgrade_to_writer() { + __TBB_ASSERT( mutex, "lock is not acquired" ); + __TBB_ASSERT( !is_writer, "not a reader" ); + is_writer = true; + return mutex->internal_upgrade(); + } + + //! Release lock. + void release() { + __TBB_ASSERT( mutex, "lock is not acquired" ); + spin_rw_mutex *m = mutex; + mutex = NULL; +#if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT + if( is_writer ) m->internal_release_writer(); + else m->internal_release_reader(); +#else + if( is_writer ) __TBB_AtomicAND( &m->state, READERS ); + else __TBB_FetchAndAddWrelease( &m->state, -(intptr_t)ONE_READER); +#endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */ + } + + //! Downgrade writer to become a reader. + bool downgrade_to_reader() { + __TBB_ASSERT( mutex, "lock is not acquired" ); + __TBB_ASSERT( is_writer, "not a writer" ); +#if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT + mutex->internal_downgrade(); +#else + __TBB_FetchAndAddW( &mutex->state, ((intptr_t)ONE_READER-WRITER)); +#endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */ + is_writer = false; + return true; + } + + //! Try acquire lock on given mutex. + bool try_acquire( spin_rw_mutex& m, bool write = true ) { + __TBB_ASSERT( !mutex, "holding mutex already" ); + bool result; + is_writer = write; + result = write? m.internal_try_acquire_writer() + : m.internal_try_acquire_reader(); + if( result ) + mutex = &m; + return result; + } + + protected: + //! The pointer to the current mutex that is held, or NULL if no mutex is held. + spin_rw_mutex* mutex; + + //! If mutex!=NULL, then is_writer is true if holding a writer lock, false if holding a reader lock. + /** Not defined if not holding a lock. */ + bool is_writer; + }; + + // Mutex traits + static const bool is_rw_mutex = true; + static const bool is_recursive_mutex = false; + static const bool is_fair_mutex = false; + + // ISO C++0x compatibility methods + + //! Acquire writer lock + void lock() {internal_acquire_writer();} + + //! Try acquiring writer lock (non-blocking) + /** Return true if lock acquired; false otherwise. */ + bool try_lock() {return internal_try_acquire_writer();} + + //! Release lock + void unlock() { +#if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT + if( state&WRITER ) internal_release_writer(); + else internal_release_reader(); +#else + if( state&WRITER ) __TBB_AtomicAND( &state, READERS ); + else __TBB_FetchAndAddWrelease( &state, -(intptr_t)ONE_READER); +#endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */ + } + + // Methods for reader locks that resemble ISO C++0x compatibility methods. + + //! Acquire reader lock + void lock_read() {internal_acquire_reader();} + + //! Try acquiring reader lock (non-blocking) + /** Return true if reader lock acquired; false otherwise. */ + bool try_lock_read() {return internal_try_acquire_reader();} + +private: + typedef intptr_t state_t; + static const state_t WRITER = 1; + static const state_t WRITER_PENDING = 2; + static const state_t READERS = ~(WRITER | WRITER_PENDING); + static const state_t ONE_READER = 4; + static const state_t BUSY = WRITER | READERS; + //! State of lock + /** Bit 0 = writer is holding lock + Bit 1 = request by a writer to acquire lock (hint to readers to wait) + Bit 2..N = number of readers holding lock */ + state_t state; + + void __TBB_EXPORTED_METHOD internal_construct(); +}; + +__TBB_DEFINE_PROFILING_SET_NAME(spin_rw_mutex) + +} // namespace tbb + +#endif /* __TBB_spin_rw_mutex_H */ diff --git a/src/tbb/include/tbb/task.h b/src/tbb/include/tbb/task.h new file mode 100644 index 0000000..9cbad16 --- /dev/null +++ b/src/tbb/include/tbb/task.h @@ -0,0 +1,962 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_task_H +#define __TBB_task_H + +#include "tbb_stddef.h" +#include "tbb_machine.h" +#include + +typedef struct ___itt_caller *__itt_caller; + +namespace tbb { + +class task; +class task_list; + +#if __TBB_TASK_GROUP_CONTEXT +class task_group_context; +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +// MSVC does not allow taking the address of a member that was defined +// privately in task_base and made public in class task via a using declaration. +#if _MSC_VER || (__GNUC__==3 && __GNUC_MINOR__<3) +#define __TBB_TASK_BASE_ACCESS public +#else +#define __TBB_TASK_BASE_ACCESS private +#endif + +namespace internal { + + class allocate_additional_child_of_proxy: no_assign { + //! No longer used, but retained for binary layout compatibility. Always NULL. + task* self; + task& parent; + public: + explicit allocate_additional_child_of_proxy( task& parent_ ) : self(NULL), parent(parent_) {} + task& __TBB_EXPORTED_METHOD allocate( size_t size ) const; + void __TBB_EXPORTED_METHOD free( task& ) const; + }; + +} + +namespace interface5 { + namespace internal { + //! Base class for methods that became static in TBB 3.0. + /** TBB's evolution caused the "this" argument for several methods to become obsolete. + However, for backwards binary compatibility, the new methods need distinct names, + otherwise the One Definition Rule would be broken. Hence the new methods are + defined in this private base class, and then exposed in class task via + using declarations. */ + class task_base: tbb::internal::no_copy { + __TBB_TASK_BASE_ACCESS: + friend class tbb::task; + + //! Schedule task for execution when a worker becomes available. + static void spawn( task& t ); + + //! Spawn multiple tasks and clear list. + static void spawn( task_list& list ); + + //! Like allocate_child, except that task's parent becomes "t", not this. + /** Typically used in conjunction with schedule_to_reexecute to implement while loops. + Atomically increments the reference count of t.parent() */ + static tbb::internal::allocate_additional_child_of_proxy allocate_additional_child_of( task& t ) { + return tbb::internal::allocate_additional_child_of_proxy(t); + } + + //! Destroy a task. + /** Usually, calling this method is unnecessary, because a task is + implicitly deleted after its execute() method runs. However, + sometimes a task needs to be explicitly deallocated, such as + when a root task is used as the parent in spawn_and_wait_for_all. */ + static void __TBB_EXPORTED_FUNC destroy( task& victim ); + }; + } // internal +} // interface5 + +//! @cond INTERNAL +namespace internal { + + class scheduler: no_copy { + public: + //! For internal use only + virtual void spawn( task& first, task*& next ) = 0; + + //! For internal use only + virtual void wait_for_all( task& parent, task* child ) = 0; + + //! For internal use only + virtual void spawn_root_and_wait( task& first, task*& next ) = 0; + + //! Pure virtual destructor; + // Have to have it just to shut up overzealous compilation warnings + virtual ~scheduler() = 0; + + //! For internal use only + virtual void enqueue( task& t, void* reserved ) = 0; + }; + + //! A reference count + /** Should always be non-negative. A signed type is used so that underflow can be detected. */ + typedef intptr_t reference_count; + + //! An id as used for specifying affinity. + typedef unsigned short affinity_id; + +#if __TBB_TASK_GROUP_CONTEXT + class generic_scheduler; + + struct context_list_node_t { + context_list_node_t *my_prev, + *my_next; + }; + + class allocate_root_with_context_proxy: no_assign { + task_group_context& my_context; + public: + allocate_root_with_context_proxy ( task_group_context& ctx ) : my_context(ctx) {} + task& __TBB_EXPORTED_METHOD allocate( size_t size ) const; + void __TBB_EXPORTED_METHOD free( task& ) const; + }; +#endif /* __TBB_TASK_GROUP_CONTEXT */ + + class allocate_root_proxy: no_assign { + public: + static task& __TBB_EXPORTED_FUNC allocate( size_t size ); + static void __TBB_EXPORTED_FUNC free( task& ); + }; + + class allocate_continuation_proxy: no_assign { + public: + task& __TBB_EXPORTED_METHOD allocate( size_t size ) const; + void __TBB_EXPORTED_METHOD free( task& ) const; + }; + + class allocate_child_proxy: no_assign { + public: + task& __TBB_EXPORTED_METHOD allocate( size_t size ) const; + void __TBB_EXPORTED_METHOD free( task& ) const; + }; + + //! Memory prefix to a task object. + /** This class is internal to the library. + Do not reference it directly, except within the library itself. + Fields are ordered in way that preserves backwards compatibility and yields + good packing on typical 32-bit and 64-bit platforms. + + In case task prefix size exceeds 32 or 64 bytes on IA32 and Intel64 + architectures correspondingly, consider dynamic setting of task_alignment + and task_prefix_reservation_size based on the maximal operand size supported + by the current CPU. + + @ingroup task_scheduling */ + class task_prefix { + private: + friend class tbb::task; + friend class tbb::interface5::internal::task_base; + friend class tbb::task_list; + friend class internal::scheduler; + friend class internal::allocate_root_proxy; + friend class internal::allocate_child_proxy; + friend class internal::allocate_continuation_proxy; + friend class internal::allocate_additional_child_of_proxy; + +#if __TBB_TASK_GROUP_CONTEXT + //! Shared context that is used to communicate asynchronous state changes + /** Currently it is used to broadcast cancellation requests generated both + by users and as the result of unhandled exceptions in the task::execute() + methods. */ + task_group_context *context; +#endif /* __TBB_TASK_GROUP_CONTEXT */ + + //! The scheduler that allocated the task, or NULL if the task is big. + /** Small tasks are pooled by the scheduler that allocated the task. + If a scheduler needs to free a small task allocated by another scheduler, + it returns the task to that other scheduler. This policy avoids + memory space blowup issues for memory allocators that allocate from + thread-specific pools. */ + scheduler* origin; + +#if __TBB_TASK_PRIORITY + union { +#endif /* __TBB_TASK_PRIORITY */ + //! Obsolete. The scheduler that owns the task. + /** Retained only for the sake of backward binary compatibility. + Still used by inline methods in the task.h header. **/ + scheduler* owner; + +#if __TBB_TASK_PRIORITY + //! Pointer to the next offloaded lower priority task. + /** Used to maintain a list of offloaded tasks inside the scheduler. **/ + task* next_offloaded; + }; +#endif /* __TBB_TASK_PRIORITY */ + + //! The task whose reference count includes me. + /** In the "blocking style" of programming, this field points to the parent task. + In the "continuation-passing style" of programming, this field points to the + continuation of the parent. */ + tbb::task* parent; + + //! Reference count used for synchronization. + /** In the "continuation-passing style" of programming, this field is + the difference of the number of allocated children minus the + number of children that have completed. + In the "blocking style" of programming, this field is one more than the difference. */ + __TBB_atomic reference_count ref_count; + + //! Obsolete. Used to be scheduling depth before TBB 2.2 + /** Retained only for the sake of backward binary compatibility. + Not used by TBB anymore. **/ + int depth; + + //! A task::state_type, stored as a byte for compactness. + /** This state is exposed to users via method task::state(). */ + unsigned char state; + + //! Miscellaneous state that is not directly visible to users, stored as a byte for compactness. + /** 0x0 -> version 1.0 task + 0x1 -> version >=2.1 task + 0x10 -> task was enqueued + 0x20 -> task_proxy + 0x40 -> task has live ref_count + 0x80 -> a stolen task */ + unsigned char extra_state; + + affinity_id affinity; + + //! "next" field for list of task + tbb::task* next; + + //! The task corresponding to this task_prefix. + tbb::task& task() {return *reinterpret_cast(this+1);} + }; + +} // namespace internal +//! @endcond + +#if __TBB_TASK_GROUP_CONTEXT + +#if __TBB_TASK_PRIORITY +namespace internal { + static const int priority_stride_v4 = INT_MAX / 4; +} + +enum priority_t { + priority_normal = internal::priority_stride_v4 * 2, + priority_low = priority_normal - internal::priority_stride_v4, + priority_high = priority_normal + internal::priority_stride_v4 +}; + +#endif /* __TBB_TASK_PRIORITY */ + +#if TBB_USE_CAPTURED_EXCEPTION + class tbb_exception; +#else + namespace internal { + class tbb_exception_ptr; + } +#endif /* !TBB_USE_CAPTURED_EXCEPTION */ + +class task_scheduler_init; + +//! Used to form groups of tasks +/** @ingroup task_scheduling + The context services explicit cancellation requests from user code, and unhandled + exceptions intercepted during tasks execution. Intercepting an exception results + in generating internal cancellation requests (which is processed in exactly the + same way as external ones). + + The context is associated with one or more root tasks and defines the cancellation + group that includes all the descendants of the corresponding root task(s). Association + is established when a context object is passed as an argument to the task::allocate_root() + method. See task_group_context::task_group_context for more details. + + The context can be bound to another one, and other contexts can be bound to it, + forming a tree-like structure: parent -> this -> children. Arrows here designate + cancellation propagation direction. If a task in a cancellation group is cancelled + all the other tasks in this group and groups bound to it (as children) get cancelled too. + + IMPLEMENTATION NOTE: + When adding new members to task_group_context or changing types of existing ones, + update the size of both padding buffers (_leading_padding and _trailing_padding) + appropriately. See also VERSIONING NOTE at the constructor definition below. **/ +class task_group_context : internal::no_copy { +private: + friend class internal::generic_scheduler; + friend class task_scheduler_init; + +#if TBB_USE_CAPTURED_EXCEPTION + typedef tbb_exception exception_container_type; +#else + typedef internal::tbb_exception_ptr exception_container_type; +#endif + + enum version_traits_word_layout { + traits_offset = 16, + version_mask = 0xFFFF, + traits_mask = 0xFFFFul << traits_offset + }; + +public: + enum kind_type { + isolated, + bound + }; + + enum traits_type { + exact_exception = 0x0001ul << traits_offset, + concurrent_wait = 0x0004ul << traits_offset, +#if TBB_USE_CAPTURED_EXCEPTION + default_traits = 0 +#else + default_traits = exact_exception +#endif /* !TBB_USE_CAPTURED_EXCEPTION */ + }; + +private: + enum state { + may_have_children = 1 + }; + + union { + //! Flavor of this context: bound or isolated. + kind_type my_kind; + uintptr_t _my_kind_aligner; + }; + + //! Pointer to the context of the parent cancellation group. NULL for isolated contexts. + task_group_context *my_parent; + + //! Used to form the thread specific list of contexts without additional memory allocation. + /** A context is included into the list of the current thread when its binding to + its parent happens. Any context can be present in the list of one thread only. **/ + internal::context_list_node_t my_node; + + //! Used to set and maintain stack stitching point for Intel Performance Tools. + __itt_caller itt_caller; + + //! Leading padding protecting accesses to frequently used members from false sharing. + /** Read accesses to the field my_cancellation_requested are on the hot path inside + the scheduler. This padding ensures that this field never shares the same cache + line with a local variable that is frequently written to. **/ + char _leading_padding[internal::NFS_MaxLineSize + - 2 * sizeof(uintptr_t)- sizeof(void*) - sizeof(internal::context_list_node_t) + - sizeof(__itt_caller)]; + + //! Specifies whether cancellation was request for this task group. + uintptr_t my_cancellation_requested; + + //! Version for run-time checks and behavioral traits of the context. + /** Version occupies low 16 bits, and traits (zero or more ORed enumerators + from the traits_type enumerations) take the next 16 bits. + Original (zeroth) version of the context did not support any traits. **/ + uintptr_t my_version_and_traits; + + //! Pointer to the container storing exception being propagated across this task group. + exception_container_type *my_exception; + + //! Scheduler instance that registered this context in its thread specific list. + internal::generic_scheduler *my_owner; + + //! Internal state (combination of state flags). + uintptr_t my_state; + +#if __TBB_TASK_PRIORITY + //! Priority level of the task group (in normalized representation) + intptr_t my_priority; +#endif /* __TBB_TASK_PRIORITY */ + + //! Trailing padding protecting accesses to frequently used members from false sharing + /** \sa _leading_padding **/ + char _trailing_padding[internal::NFS_MaxLineSize - 2 * sizeof(uintptr_t) - 2 * sizeof(void*) +#if __TBB_TASK_PRIORITY + - sizeof(intptr_t) +#endif /* __TBB_TASK_PRIORITY */ + ]; + +public: + //! Default & binding constructor. + /** By default a bound context is created. That is this context will be bound + (as child) to the context of the task calling task::allocate_root(this_context) + method. Cancellation requests passed to the parent context are propagated + to all the contexts bound to it. Similarly priority change is propagated + from the parent context to its children. + + If task_group_context::isolated is used as the argument, then the tasks associated + with this context will never be affected by events in any other context. + + Creating isolated contexts involve much less overhead, but they have limited + utility. Normally when an exception occurs in an algorithm that has nested + ones running, it is desirably to have all the nested algorithms cancelled + as well. Such a behavior requires nested algorithms to use bound contexts. + + There is one good place where using isolated algorithms is beneficial. It is + a master thread. That is if a particular algorithm is invoked directly from + the master thread (not from a TBB task), supplying it with explicitly + created isolated context will result in a faster algorithm startup. + + VERSIONING NOTE: + Implementation(s) of task_group_context constructor(s) cannot be made + entirely out-of-line because the run-time version must be set by the user + code. This will become critically important for binary compatibility, if + we ever have to change the size of the context object. + + Boosting the runtime version will also be necessary if new data fields are + introduced in the currently unused padding areas and these fields are updated + by inline methods. **/ + task_group_context ( kind_type relation_with_parent = bound, + uintptr_t traits = default_traits ) + : my_kind(relation_with_parent) + , my_version_and_traits(1 | traits) + { + init(); + } + + __TBB_EXPORTED_METHOD ~task_group_context (); + + //! Forcefully reinitializes the context after the task tree it was associated with is completed. + /** Because the method assumes that all the tasks that used to be associated with + this context have already finished, calling it while the context is still + in use somewhere in the task hierarchy leads to undefined behavior. + + IMPORTANT: This method is not thread safe! + + The method does not change the context's parent if it is set. **/ + void __TBB_EXPORTED_METHOD reset (); + + //! Initiates cancellation of all tasks in this cancellation group and its subordinate groups. + /** \return false if cancellation has already been requested, true otherwise. + + Note that canceling never fails. When false is returned, it just means that + another thread (or this one) has already sent cancellation request to this + context or to one of its ancestors (if this context is bound). It is guaranteed + that when this method is concurrently called on the same not yet cancelled + context, true will be returned by one and only one invocation. **/ + bool __TBB_EXPORTED_METHOD cancel_group_execution (); + + //! Returns true if the context received cancellation request. + bool __TBB_EXPORTED_METHOD is_group_execution_cancelled () const; + + //! Records the pending exception, and cancels the task group. + /** May be called only from inside a catch-block. If the context is already + cancelled, does nothing. + The method brings the task group associated with this context exactly into + the state it would be in, if one of its tasks threw the currently pending + exception during its execution. In other words, it emulates the actions + of the scheduler's dispatch loop exception handler. **/ + void __TBB_EXPORTED_METHOD register_pending_exception (); + +#if __TBB_TASK_PRIORITY + //! Changes priority of the task group + void set_priority ( priority_t ); + + //! Retrieves current priority of the current task group + priority_t priority () const; +#endif /* __TBB_TASK_PRIORITY */ + +protected: + //! Out-of-line part of the constructor. + /** Singled out to ensure backward binary compatibility of the future versions. **/ + void __TBB_EXPORTED_METHOD init (); + +private: + friend class task; + friend class internal::allocate_root_with_context_proxy; + + static const kind_type binding_required = bound; + static const kind_type binding_completed = kind_type(bound+1); + static const kind_type detached = kind_type(binding_completed+1); + static const kind_type dying = kind_type(detached+1); + + //! Propagates state change (if any) from an ancestor + /** Checks if one of this object's ancestors is in a new state, and propagates + the new state to all its descendants in this object's heritage line. **/ + template + void propagate_state_from_ancestors ( T task_group_context::*mptr_state, T new_state ); + + //! Makes sure that the context is registered with a scheduler instance. + inline void finish_initialization ( internal::generic_scheduler *local_sched ); + + //! Registers this context with the local scheduler and binds it to its parent context + void bind_to ( internal::generic_scheduler *local_sched ); + + //! Registers this context with the local scheduler + void register_with ( internal::generic_scheduler *local_sched ); + +}; // class task_group_context + +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +//! Base class for user-defined tasks. +/** @ingroup task_scheduling */ +class task: __TBB_TASK_BASE_ACCESS interface5::internal::task_base { + + //! Set reference count + void __TBB_EXPORTED_METHOD internal_set_ref_count( int count ); + + //! Decrement reference count and return its new value. + internal::reference_count __TBB_EXPORTED_METHOD internal_decrement_ref_count(); + +protected: + //! Default constructor. + task() {prefix().extra_state=1;} + +public: + //! Destructor. + virtual ~task() {} + + //! Should be overridden by derived classes. + virtual task* execute() = 0; + + //! Enumeration of task states that the scheduler considers. + enum state_type { + //! task is running, and will be destroyed after method execute() completes. + executing, + //! task to be rescheduled. + reexecute, + //! task is in ready pool, or is going to be put there, or was just taken off. + ready, + //! task object is freshly allocated or recycled. + allocated, + //! task object is on free list, or is going to be put there, or was just taken off. + freed, + //! task to be recycled as continuation + recycle + }; + + //------------------------------------------------------------------------ + // Allocating tasks + //------------------------------------------------------------------------ + + //! Returns proxy for overloaded new that allocates a root task. + static internal::allocate_root_proxy allocate_root() { + return internal::allocate_root_proxy(); + } + +#if __TBB_TASK_GROUP_CONTEXT + //! Returns proxy for overloaded new that allocates a root task associated with user supplied context. + static internal::allocate_root_with_context_proxy allocate_root( task_group_context& ctx ) { + return internal::allocate_root_with_context_proxy(ctx); + } +#endif /* __TBB_TASK_GROUP_CONTEXT */ + + //! Returns proxy for overloaded new that allocates a continuation task of *this. + /** The continuation's parent becomes the parent of *this. */ + internal::allocate_continuation_proxy& allocate_continuation() { + return *reinterpret_cast(this); + } + + //! Returns proxy for overloaded new that allocates a child task of *this. + internal::allocate_child_proxy& allocate_child() { + return *reinterpret_cast(this); + } + + //! Define recommended static form via import from base class. + using task_base::allocate_additional_child_of; + +#if __TBB_DEPRECATED_TASK_INTERFACE + //! Destroy a task. + /** Usually, calling this method is unnecessary, because a task is + implicitly deleted after its execute() method runs. However, + sometimes a task needs to be explicitly deallocated, such as + when a root task is used as the parent in spawn_and_wait_for_all. */ + void __TBB_EXPORTED_METHOD destroy( task& t ); +#else /* !__TBB_DEPRECATED_TASK_INTERFACE */ + //! Define recommended static form via import from base class. + using task_base::destroy; +#endif /* !__TBB_DEPRECATED_TASK_INTERFACE */ + + //------------------------------------------------------------------------ + // Recycling of tasks + //------------------------------------------------------------------------ + + //! Change this to be a continuation of its former self. + /** The caller must guarantee that the task's refcount does not become zero until + after the method execute() returns. Typically, this is done by having + method execute() return a pointer to a child of the task. If the guarantee + cannot be made, use method recycle_as_safe_continuation instead. + + Because of the hazard, this method may be deprecated in the future. */ + void recycle_as_continuation() { + __TBB_ASSERT( prefix().state==executing, "execute not running?" ); + prefix().state = allocated; + } + + //! Recommended to use, safe variant of recycle_as_continuation + /** For safety, it requires additional increment of ref_count. + With no descendants and ref_count of 1, it has the semantics of recycle_to_reexecute. */ + void recycle_as_safe_continuation() { + __TBB_ASSERT( prefix().state==executing, "execute not running?" ); + prefix().state = recycle; + } + + //! Change this to be a child of new_parent. + void recycle_as_child_of( task& new_parent ) { + internal::task_prefix& p = prefix(); + __TBB_ASSERT( prefix().state==executing||prefix().state==allocated, "execute not running, or already recycled" ); + __TBB_ASSERT( prefix().ref_count==0, "no child tasks allowed when recycled as a child" ); + __TBB_ASSERT( p.parent==NULL, "parent must be null" ); + __TBB_ASSERT( new_parent.prefix().state<=recycle, "corrupt parent's state" ); + __TBB_ASSERT( new_parent.prefix().state!=freed, "parent already freed" ); + p.state = allocated; + p.parent = &new_parent; +#if __TBB_TASK_GROUP_CONTEXT + p.context = new_parent.prefix().context; +#endif /* __TBB_TASK_GROUP_CONTEXT */ + } + + //! Schedule this for reexecution after current execute() returns. + /** Made obsolete by recycle_as_safe_continuation; may become deprecated. */ + void recycle_to_reexecute() { + __TBB_ASSERT( prefix().state==executing, "execute not running, or already recycled" ); + __TBB_ASSERT( prefix().ref_count==0, "no child tasks allowed when recycled for reexecution" ); + prefix().state = reexecute; + } + + // All depth-related methods are obsolete, and are retained for the sake + // of backward source compatibility only + intptr_t depth() const {return 0;} + void set_depth( intptr_t ) {} + void add_to_depth( int ) {} + + + //------------------------------------------------------------------------ + // Spawning and blocking + //------------------------------------------------------------------------ + + //! Set reference count + void set_ref_count( int count ) { +#if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT + internal_set_ref_count(count); +#else + prefix().ref_count = count; +#endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */ + } + + //! Atomically increment reference count and returns its old value. + /** Has acquire semantics */ + void increment_ref_count() { + __TBB_FetchAndIncrementWacquire( &prefix().ref_count ); + } + + //! Atomically decrement reference count and returns its new value. + /** Has release semantics. */ + int decrement_ref_count() { +#if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT + return int(internal_decrement_ref_count()); +#else + return int(__TBB_FetchAndDecrementWrelease( &prefix().ref_count ))-1; +#endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */ + } + + //! Define recommended static forms via import from base class. + using task_base::spawn; + + //! Similar to spawn followed by wait_for_all, but more efficient. + void spawn_and_wait_for_all( task& child ) { + prefix().owner->wait_for_all( *this, &child ); + } + + //! Similar to spawn followed by wait_for_all, but more efficient. + void __TBB_EXPORTED_METHOD spawn_and_wait_for_all( task_list& list ); + + //! Spawn task allocated by allocate_root, wait for it to complete, and deallocate it. + static void spawn_root_and_wait( task& root ) { + root.prefix().owner->spawn_root_and_wait( root, root.prefix().next ); + } + + //! Spawn root tasks on list and wait for all of them to finish. + /** If there are more tasks than worker threads, the tasks are spawned in + order of front to back. */ + static void spawn_root_and_wait( task_list& root_list ); + + //! Wait for reference count to become one, and set reference count to zero. + /** Works on tasks while waiting. */ + void wait_for_all() { + prefix().owner->wait_for_all( *this, NULL ); + } + + //! Enqueue task for starvation-resistant execution. +#if __TBB_TASK_PRIORITY + /** The task will be enqueued on the normal priority level disregarding the + priority of its task group. + + The rationale of such semantics is that priority of an enqueued task is + statically fixed at the moment of its enqueuing, while task group priority + is dynamic. Thus automatic priority inheritance would be generally a subject + to the race, which may result in unexpected behavior. + + Use enqueue() overload with explicit priority value and task::group_priority() + method to implement such priority inheritance when it is really necessary. **/ +#endif /* __TBB_TASK_PRIORITY */ + static void enqueue( task& t ) { + t.prefix().owner->enqueue( t, NULL ); + } + +#if __TBB_TASK_PRIORITY + //! Enqueue task for starvation-resistant execution on the specified priority level. + static void enqueue( task& t, priority_t p ) { + __TBB_ASSERT( p == priority_low || p == priority_normal || p == priority_high, "Invalid priority level value" ); + t.prefix().owner->enqueue( t, (void*)p ); + } +#endif /* __TBB_TASK_PRIORITY */ + + //! The innermost task being executed or destroyed by the current thread at the moment. + static task& __TBB_EXPORTED_FUNC self(); + + //! task on whose behalf this task is working, or NULL if this is a root. + task* parent() const {return prefix().parent;} + + //! sets parent task pointer to specified value + void set_parent(task* p) { +#if __TBB_TASK_GROUP_CONTEXT + __TBB_ASSERT(prefix().context == p->prefix().context, "The tasks must be in the same context"); +#endif + prefix().parent = p; + } + +#if __TBB_TASK_GROUP_CONTEXT + //! This method is deprecated and will be removed in the future. + /** Use method group() instead. **/ + task_group_context* context() {return prefix().context;} + + //! Pointer to the task group descriptor. + task_group_context* group () { return prefix().context; } +#endif /* __TBB_TASK_GROUP_CONTEXT */ + + //! True if task was stolen from the task pool of another thread. + bool is_stolen_task() const { + return (prefix().extra_state & 0x80)!=0; + } + + //------------------------------------------------------------------------ + // Debugging + //------------------------------------------------------------------------ + + //! Current execution state + state_type state() const {return state_type(prefix().state);} + + //! The internal reference count. + int ref_count() const { +#if TBB_USE_ASSERT + internal::reference_count ref_count_ = prefix().ref_count; + __TBB_ASSERT( ref_count_==int(ref_count_), "integer overflow error"); +#endif + return int(prefix().ref_count); + } + + //! Obsolete, and only retained for the sake of backward compatibility. Always returns true. + bool __TBB_EXPORTED_METHOD is_owned_by_current_thread() const; + + //------------------------------------------------------------------------ + // Affinity + //------------------------------------------------------------------------ + + //! An id as used for specifying affinity. + /** Guaranteed to be integral type. Value of 0 means no affinity. */ + typedef internal::affinity_id affinity_id; + + //! Set affinity for this task. + void set_affinity( affinity_id id ) {prefix().affinity = id;} + + //! Current affinity of this task + affinity_id affinity() const {return prefix().affinity;} + + //! Invoked by scheduler to notify task that it ran on unexpected thread. + /** Invoked before method execute() runs, if task is stolen, or task has + affinity but will be executed on another thread. + + The default action does nothing. */ + virtual void __TBB_EXPORTED_METHOD note_affinity( affinity_id id ); + +#if __TBB_TASK_GROUP_CONTEXT + //! Moves this task from its current group into another one. + /** Argument ctx specifies the new group. + + The primary purpose of this method is to associate unique task group context + with a task allocated for subsequent enqueuing. In contrast to spawned tasks + enqueued ones normally outlive the scope where they were created. This makes + traditional usage model where task group context are allocated locally on + the stack inapplicable. Dynamic allocation of context objects is performance + inefficient. Method change_group() allows to make task group context object + a member of the task class, and then associate it with its containing task + object in the latter's constructor. **/ + void __TBB_EXPORTED_METHOD change_group ( task_group_context& ctx ); + + //! Initiates cancellation of all tasks in this cancellation group and its subordinate groups. + /** \return false if cancellation has already been requested, true otherwise. **/ + bool cancel_group_execution () { return prefix().context->cancel_group_execution(); } + + //! Returns true if the context has received cancellation request. + bool is_cancelled () const { return prefix().context->is_group_execution_cancelled(); } +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +#if __TBB_TASK_PRIORITY + //! Changes priority of the task group this task belongs to. + void set_group_priority ( priority_t p ) { prefix().context->set_priority(p); } + + //! Retrieves current priority of the task group this task belongs to. + priority_t group_priority () const { return prefix().context->priority(); } + +#endif /* __TBB_TASK_PRIORITY */ + +private: + friend class interface5::internal::task_base; + friend class task_list; + friend class internal::scheduler; + friend class internal::allocate_root_proxy; +#if __TBB_TASK_GROUP_CONTEXT + friend class internal::allocate_root_with_context_proxy; +#endif /* __TBB_TASK_GROUP_CONTEXT */ + friend class internal::allocate_continuation_proxy; + friend class internal::allocate_child_proxy; + friend class internal::allocate_additional_child_of_proxy; + + //! Get reference to corresponding task_prefix. + /** Version tag prevents loader on Linux from using the wrong symbol in debug builds. **/ + internal::task_prefix& prefix( internal::version_tag* = NULL ) const { + return reinterpret_cast(const_cast(this))[-1]; + } +}; // class task + +//! task that does nothing. Useful for synchronization. +/** @ingroup task_scheduling */ +class empty_task: public task { + /*override*/ task* execute() { + return NULL; + } +}; + +//! A list of children. +/** Used for method task::spawn_children + @ingroup task_scheduling */ +class task_list: internal::no_copy { +private: + task* first; + task** next_ptr; + friend class task; + friend class interface5::internal::task_base; +public: + //! Construct empty list + task_list() : first(NULL), next_ptr(&first) {} + + //! Destroys the list, but does not destroy the task objects. + ~task_list() {} + + //! True if list if empty; false otherwise. + bool empty() const {return !first;} + + //! Push task onto back of list. + void push_back( task& task ) { + task.prefix().next = NULL; + *next_ptr = &task; + next_ptr = &task.prefix().next; + } + + //! Pop the front task from the list. + task& pop_front() { + __TBB_ASSERT( !empty(), "attempt to pop item from empty task_list" ); + task* result = first; + first = result->prefix().next; + if( !first ) next_ptr = &first; + return *result; + } + + //! Clear the list + void clear() { + first=NULL; + next_ptr=&first; + } +}; + +inline void interface5::internal::task_base::spawn( task& t ) { + t.prefix().owner->spawn( t, t.prefix().next ); +} + +inline void interface5::internal::task_base::spawn( task_list& list ) { + if( task* t = list.first ) { + t->prefix().owner->spawn( *t, *list.next_ptr ); + list.clear(); + } +} + +inline void task::spawn_root_and_wait( task_list& root_list ) { + if( task* t = root_list.first ) { + t->prefix().owner->spawn_root_and_wait( *t, *root_list.next_ptr ); + root_list.clear(); + } +} + +} // namespace tbb + +inline void *operator new( size_t bytes, const tbb::internal::allocate_root_proxy& ) { + return &tbb::internal::allocate_root_proxy::allocate(bytes); +} + +inline void operator delete( void* task, const tbb::internal::allocate_root_proxy& ) { + tbb::internal::allocate_root_proxy::free( *static_cast(task) ); +} + +#if __TBB_TASK_GROUP_CONTEXT +inline void *operator new( size_t bytes, const tbb::internal::allocate_root_with_context_proxy& p ) { + return &p.allocate(bytes); +} + +inline void operator delete( void* task, const tbb::internal::allocate_root_with_context_proxy& p ) { + p.free( *static_cast(task) ); +} +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +inline void *operator new( size_t bytes, const tbb::internal::allocate_continuation_proxy& p ) { + return &p.allocate(bytes); +} + +inline void operator delete( void* task, const tbb::internal::allocate_continuation_proxy& p ) { + p.free( *static_cast(task) ); +} + +inline void *operator new( size_t bytes, const tbb::internal::allocate_child_proxy& p ) { + return &p.allocate(bytes); +} + +inline void operator delete( void* task, const tbb::internal::allocate_child_proxy& p ) { + p.free( *static_cast(task) ); +} + +inline void *operator new( size_t bytes, const tbb::internal::allocate_additional_child_of_proxy& p ) { + return &p.allocate(bytes); +} + +inline void operator delete( void* task, const tbb::internal::allocate_additional_child_of_proxy& p ) { + p.free( *static_cast(task) ); +} + +#endif /* __TBB_task_H */ diff --git a/src/tbb/include/tbb/task_group.h b/src/tbb/include/tbb/task_group.h new file mode 100644 index 0000000..4a890d6 --- /dev/null +++ b/src/tbb/include/tbb/task_group.h @@ -0,0 +1,252 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_task_group_H +#define __TBB_task_group_H + +#include "task.h" +#include "tbb_exception.h" + +#if __TBB_TASK_GROUP_CONTEXT + +namespace tbb { + +namespace internal { + template class task_handle_task; +} + +template +class task_handle : internal::no_assign { + template friend class internal::task_handle_task; + + static const intptr_t scheduled = 0x1; + + F my_func; + intptr_t my_state; + + void mark_scheduled () { + // The check here is intentionally lax to avoid the impact of interlocked operation + if ( my_state & scheduled ) + internal::throw_exception( internal::eid_invalid_multiple_scheduling ); + my_state |= scheduled; + } +public: + task_handle( const F& f ) : my_func(f), my_state(0) {} + + void operator() () const { my_func(); } +}; + +enum task_group_status { + not_complete, + complete, + canceled +}; + +namespace internal { + +// Suppress gratuitous warnings from icc 11.0 when lambda expressions are used in instances of function_task. +//#pragma warning(disable: 588) + +template +class function_task : public task { + F my_func; + /*override*/ task* execute() { + my_func(); + return NULL; + } +public: + function_task( const F& f ) : my_func(f) {} +}; + +template +class task_handle_task : public task { + task_handle& my_handle; + /*override*/ task* execute() { + my_handle(); + return NULL; + } +public: + task_handle_task( task_handle& h ) : my_handle(h) { h.mark_scheduled(); } +}; + +class task_group_base : internal::no_copy { +protected: + empty_task* my_root; + task_group_context my_context; + + task& owner () { return *my_root; } + + template + task_group_status internal_run_and_wait( F& f ) { + __TBB_TRY { + if ( !my_context.is_group_execution_cancelled() ) + f(); + } __TBB_CATCH( ... ) { + my_context.register_pending_exception(); + } + return wait(); + } + + template + void internal_run( F& f ) { + owner().spawn( *new( owner().allocate_additional_child_of(*my_root) ) Task(f) ); + } + +public: + task_group_base( uintptr_t traits = 0 ) + : my_context(task_group_context::bound, task_group_context::default_traits | traits) + { + my_root = new( task::allocate_root(my_context) ) empty_task; + my_root->set_ref_count(1); + } + + ~task_group_base() { + if( my_root->ref_count() > 1 ) { + bool stack_unwinding_in_progress = std::uncaught_exception(); + // Always attempt to do proper cleanup to avoid inevitable memory corruption + // in case of missing wait (for the sake of better testability & debuggability) + if ( !is_canceling() ) + cancel(); + __TBB_TRY { + my_root->wait_for_all(); + } __TBB_CATCH (...) { + task::destroy(*my_root); + __TBB_RETHROW(); + } + task::destroy(*my_root); + if ( !stack_unwinding_in_progress ) + internal::throw_exception( internal::eid_missing_wait ); + } + else { + task::destroy(*my_root); + } + } + + template + void run( task_handle& h ) { + internal_run< task_handle, internal::task_handle_task >( h ); + } + + task_group_status wait() { + __TBB_TRY { + my_root->wait_for_all(); + } __TBB_CATCH( ... ) { + my_context.reset(); + __TBB_RETHROW(); + } + if ( my_context.is_group_execution_cancelled() ) { + my_context.reset(); + return canceled; + } + return complete; + } + + bool is_canceling() { + return my_context.is_group_execution_cancelled(); + } + + void cancel() { + my_context.cancel_group_execution(); + } +}; // class task_group_base + +} // namespace internal + +class task_group : public internal::task_group_base { +public: + task_group () : task_group_base( task_group_context::concurrent_wait ) {} + +#if TBB_DEPRECATED + ~task_group() __TBB_TRY { + __TBB_ASSERT( my_root->ref_count() != 0, NULL ); + if( my_root->ref_count() > 1 ) + my_root->wait_for_all(); + } +#if TBB_USE_EXCEPTIONS + catch (...) { + // Have to destroy my_root here as the base class destructor won't be called + task::destroy(*my_root); + throw; + } +#endif /* TBB_USE_EXCEPTIONS */ +#endif /* TBB_DEPRECATED */ + +#if __SUNPRO_CC + template + void run( task_handle& h ) { + internal_run< task_handle, internal::task_handle_task >( h ); + } +#else + using task_group_base::run; +#endif + + template + void run( const F& f ) { + internal_run< const F, internal::function_task >( f ); + } + + template + task_group_status run_and_wait( const F& f ) { + return internal_run_and_wait( f ); + } + + template + task_group_status run_and_wait( task_handle& h ) { + return internal_run_and_wait< task_handle >( h ); + } +}; // class task_group + +class structured_task_group : public internal::task_group_base { +public: + template + task_group_status run_and_wait ( task_handle& h ) { + return internal_run_and_wait< task_handle >( h ); + } + + task_group_status wait() { + task_group_status res = task_group_base::wait(); + my_root->set_ref_count(1); + return res; + } +}; // class structured_task_group + +inline +bool is_current_task_group_canceling() { + return task::self().is_cancelled(); +} + +template +task_handle make_task( const F& f ) { + return task_handle( f ); +} + +} // namespace tbb + +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +#endif /* __TBB_task_group_H */ diff --git a/src/tbb/include/tbb/task_scheduler_init.h b/src/tbb/include/tbb/task_scheduler_init.h new file mode 100644 index 0000000..0f0bb2a --- /dev/null +++ b/src/tbb/include/tbb/task_scheduler_init.h @@ -0,0 +1,147 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_task_scheduler_init_H +#define __TBB_task_scheduler_init_H + +#include "tbb_stddef.h" +#include "limits.h" + +namespace tbb { + +typedef std::size_t stack_size_type; + +//! @cond INTERNAL +namespace internal { + //! Internal to library. Should not be used by clients. + /** @ingroup task_scheduling */ + class scheduler; +} // namespace internal +//! @endcond + +//! Class delimiting the scope of task scheduler activity. +/** A thread can construct a task_scheduler_init object and keep it alive + while it uses TBB's tasking subsystem (including parallel algorithms). + + This class allows to customize properties of the TBB task pool to some extent. + For example it can limit concurrency level of parallel work initiated by the + given thread. It also can be used to specify stack size of the TBB worker threads, + though this setting is not effective if the thread pool has already been created. + + If a parallel construct is used without task_scheduler_init object previously + created, the scheduler will be initialized automatically with default settings, + and will persist until this thread exits. Default concurrency level is defined + as described in task_scheduler_init::initialize(). + @ingroup task_scheduling */ +class task_scheduler_init: internal::no_copy { + enum ExceptionPropagationMode { + propagation_mode_exact = 1u, + propagation_mode_captured = 2u, + propagation_mode_mask = propagation_mode_exact | propagation_mode_captured + }; + + /** NULL if not currently initialized. */ + internal::scheduler* my_scheduler; +public: + + //! Typedef for number of threads that is automatic. + static const int automatic = -1; + + //! Argument to initialize() or constructor that causes initialization to be deferred. + static const int deferred = -2; + + //! Ensure that scheduler exists for this thread + /** A value of -1 lets TBB decide on the number of threads, which is usually + maximal hardware concurrency for this process, that is the number of logical + CPUs on the machine (possibly limited by the processor affinity mask of this + process (Windows) or of this thread (Linux, FreeBSD). It is preferable option + for production code because it helps to avoid nasty surprises when several + TBB based components run side-by-side or in a nested fashion inside the same + process. + + The number_of_threads is ignored if any other task_scheduler_inits + currently exist. A thread may construct multiple task_scheduler_inits. + Doing so does no harm because the underlying scheduler is reference counted. */ + void __TBB_EXPORTED_METHOD initialize( int number_of_threads=automatic ); + + //! The overloaded method with stack size parameter + /** Overloading is necessary to preserve ABI compatibility */ + void __TBB_EXPORTED_METHOD initialize( int number_of_threads, stack_size_type thread_stack_size ); + + //! Inverse of method initialize. + void __TBB_EXPORTED_METHOD terminate(); + + //! Shorthand for default constructor followed by call to initialize(number_of_threads). + task_scheduler_init( int number_of_threads=automatic, stack_size_type thread_stack_size=0 ) : my_scheduler(NULL) { + // Two lowest order bits of the stack size argument may be taken to communicate + // default exception propagation mode of the client to be used when the + // client manually creates tasks in the master thread and does not use + // explicit task group context object. This is necessary because newer + // TBB binaries with exact propagation enabled by default may be used + // by older clients that expect tbb::captured_exception wrapper. + // All zeros mean old client - no preference. + __TBB_ASSERT( !(thread_stack_size & propagation_mode_mask), "Requested stack size is not aligned" ); +#if TBB_USE_EXCEPTIONS + thread_stack_size |= TBB_USE_CAPTURED_EXCEPTION ? propagation_mode_captured : propagation_mode_exact; +#endif /* TBB_USE_EXCEPTIONS */ + initialize( number_of_threads, thread_stack_size ); + } + + //! Destroy scheduler for this thread if thread has no other live task_scheduler_inits. + ~task_scheduler_init() { + if( my_scheduler ) + terminate(); + internal::poison_pointer( my_scheduler ); + } + //! Returns the number of threads TBB scheduler would create if initialized by default. + /** Result returned by this method does not depend on whether the scheduler + has already been initialized. + + Because tbb 2.0 does not support blocking tasks yet, you may use this method + to boost the number of threads in the tbb's internal pool, if your tasks are + doing I/O operations. The optimal number of additional threads depends on how + much time your tasks spend in the blocked state. + + Before TBB 3.0 U4 this method returned the number of logical CPU in the + system. Currently on Windows, Linux and FreeBSD it returns the number of + logical CPUs available to the current process in accordance with its affinity + mask. + + NOTE: The return value of this method never changes after its first invocation. + This means that changes in the process affinity mask that took place after + this method was first invoked will not affect the number of worker threads + in the TBB worker threads pool. */ + static int __TBB_EXPORTED_FUNC default_num_threads (); + + //! Returns true if scheduler is active (initialized); false otherwise + bool is_active() const { return my_scheduler != NULL; } +}; + +} // namespace tbb + +#endif /* __TBB_task_scheduler_init_H */ diff --git a/src/tbb/include/tbb/task_scheduler_observer.h b/src/tbb/include/tbb/task_scheduler_observer.h new file mode 100644 index 0000000..c7af037 --- /dev/null +++ b/src/tbb/include/tbb/task_scheduler_observer.h @@ -0,0 +1,74 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_task_scheduler_observer_H +#define __TBB_task_scheduler_observer_H + +#include "atomic.h" + +#if __TBB_SCHEDULER_OBSERVER + +namespace tbb { + +namespace internal { + +class observer_proxy; + +class task_scheduler_observer_v3 { + friend class observer_proxy; + observer_proxy* my_proxy; + atomic my_busy_count; +public: + //! Enable or disable observation + void __TBB_EXPORTED_METHOD observe( bool state=true ); + + //! True if observation is enables; false otherwise. + bool is_observing() const {return my_proxy!=NULL;} + + //! Construct observer with observation disabled. + task_scheduler_observer_v3() : my_proxy(NULL) {my_busy_count=0;} + + //! Called by thread before first steal since observation became enabled + virtual void on_scheduler_entry( bool /*is_worker*/ ) {} + + //! Called by thread when it no longer takes part in task stealing. + virtual void on_scheduler_exit( bool /*is_worker*/ ) {} + + //! Destructor + virtual ~task_scheduler_observer_v3() {observe(false);} +}; + +} // namespace internal + +typedef internal::task_scheduler_observer_v3 task_scheduler_observer; + +} // namespace tbb + +#endif /* __TBB_SCHEDULER_OBSERVER */ + +#endif /* __TBB_task_scheduler_observer_H */ diff --git a/src/tbb/include/tbb/tbb.h b/src/tbb/include/tbb/tbb.h new file mode 100644 index 0000000..1581bd9 --- /dev/null +++ b/src/tbb/include/tbb/tbb.h @@ -0,0 +1,84 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_tbb_H +#define __TBB_tbb_H + +/** + This header bulk-includes declarations or definitions of all the functionality + provided by TBB (save for malloc dependent headers). + + If you use only a few TBB constructs, consider including specific headers only. + Any header listed below can be included independently of others. +**/ + +#if TBB_PREVIEW_AGGREGATOR +#include "aggregator.h" +#endif +#include "aligned_space.h" +#include "atomic.h" +#include "blocked_range.h" +#include "blocked_range2d.h" +#include "blocked_range3d.h" +#include "cache_aligned_allocator.h" +#include "combinable.h" +#include "concurrent_unordered_map.h" +#include "concurrent_hash_map.h" +#include "concurrent_queue.h" +#include "concurrent_vector.h" +#include "critical_section.h" +#include "enumerable_thread_specific.h" +#include "mutex.h" +#include "null_mutex.h" +#include "null_rw_mutex.h" +#include "parallel_do.h" +#include "parallel_for.h" +#include "parallel_for_each.h" +#include "parallel_invoke.h" +#include "parallel_reduce.h" +#include "parallel_scan.h" +#include "parallel_sort.h" +#include "partitioner.h" +#include "pipeline.h" +#include "queuing_mutex.h" +#include "queuing_rw_mutex.h" +#include "reader_writer_lock.h" +#include "concurrent_priority_queue.h" +#include "recursive_mutex.h" +#include "spin_mutex.h" +#include "spin_rw_mutex.h" +#include "task.h" +#include "task_group.h" +#include "task_scheduler_init.h" +#include "task_scheduler_observer.h" +#include "tbb_allocator.h" +#include "tbb_exception.h" +#include "tbb_thread.h" +#include "tick_count.h" + +#endif /* __TBB_tbb_H */ diff --git a/src/tbb/include/tbb/tbb_allocator.h b/src/tbb/include/tbb/tbb_allocator.h new file mode 100644 index 0000000..f4e366c --- /dev/null +++ b/src/tbb/include/tbb/tbb_allocator.h @@ -0,0 +1,227 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_tbb_allocator_H +#define __TBB_tbb_allocator_H + +#include "tbb_stddef.h" +#include +#if __TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_CPP11_STD_FORWARD_BROKEN + #include // std::forward +#endif + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +namespace tbb { + +//! @cond INTERNAL +namespace internal { + + //! Deallocates memory using FreeHandler + /** The function uses scalable_free if scalable allocator is available and free if not*/ + void __TBB_EXPORTED_FUNC deallocate_via_handler_v3( void *p ); + + //! Allocates memory using MallocHandler + /** The function uses scalable_malloc if scalable allocator is available and malloc if not*/ + void* __TBB_EXPORTED_FUNC allocate_via_handler_v3( size_t n ); + + //! Returns true if standard malloc/free are used to work with memory. + bool __TBB_EXPORTED_FUNC is_malloc_used_v3(); +} +//! @endcond + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // Workaround for erroneous "unreferenced parameter" warning in method destroy. + #pragma warning (push) + #pragma warning (disable: 4100) +#endif + +//! Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5 +/** The class selects the best memory allocation mechanism available + from scalable_malloc and standard malloc. + The members are ordered the same way they are in section 20.4.1 + of the ISO C++ standard. + @ingroup memory_allocation */ +template +class tbb_allocator { +public: + typedef typename internal::allocator_type::value_type value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + template struct rebind { + typedef tbb_allocator other; + }; + + //! Specifies current allocator + enum malloc_type { + scalable, + standard + }; + + tbb_allocator() throw() {} + tbb_allocator( const tbb_allocator& ) throw() {} + template tbb_allocator(const tbb_allocator&) throw() {} + + pointer address(reference x) const {return &x;} + const_pointer address(const_reference x) const {return &x;} + + //! Allocate space for n objects. + pointer allocate( size_type n, const void* /*hint*/ = 0) { + return pointer(internal::allocate_via_handler_v3( n * sizeof(value_type) )); + } + + //! Free previously allocated block of memory. + void deallocate( pointer p, size_type ) { + internal::deallocate_via_handler_v3(p); + } + + //! Largest value for which method allocate might succeed. + size_type max_size() const throw() { + size_type max = static_cast(-1) / sizeof (value_type); + return (max > 0 ? max : 1); + } + + //! Copy-construct value at location pointed to by p. +#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT + template + void construct(pointer p, Args&&... args) + #if __TBB_CPP11_STD_FORWARD_BROKEN + { ::new((void *)p) T((args)...); } + #else + { ::new((void *)p) T(std::forward(args)...); } + #endif +#else // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT + void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);} +#endif // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT + + //! Destroy value at location pointed to by p. + void destroy( pointer p ) {p->~value_type();} + + //! Returns current allocator + static malloc_type allocator_type() { + return internal::is_malloc_used_v3() ? standard : scalable; + } +}; + +#if _MSC_VER && !defined(__INTEL_COMPILER) + #pragma warning (pop) +#endif // warning 4100 is back + +//! Analogous to std::allocator, as defined in ISO C++ Standard, Section 20.4.1 +/** @ingroup memory_allocation */ +template<> +class tbb_allocator { +public: + typedef void* pointer; + typedef const void* const_pointer; + typedef void value_type; + template struct rebind { + typedef tbb_allocator other; + }; +}; + +template +inline bool operator==( const tbb_allocator&, const tbb_allocator& ) {return true;} + +template +inline bool operator!=( const tbb_allocator&, const tbb_allocator& ) {return false;} + +//! Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5 +/** The class is an adapter over an actual allocator that fills the allocation + using memset function with template argument C as the value. + The members are ordered the same way they are in section 20.4.1 + of the ISO C++ standard. + @ingroup memory_allocation */ +template class Allocator = tbb_allocator> +class zero_allocator : public Allocator +{ +public: + typedef Allocator base_allocator_type; + typedef typename base_allocator_type::value_type value_type; + typedef typename base_allocator_type::pointer pointer; + typedef typename base_allocator_type::const_pointer const_pointer; + typedef typename base_allocator_type::reference reference; + typedef typename base_allocator_type::const_reference const_reference; + typedef typename base_allocator_type::size_type size_type; + typedef typename base_allocator_type::difference_type difference_type; + template struct rebind { + typedef zero_allocator other; + }; + + zero_allocator() throw() { } + zero_allocator(const zero_allocator &a) throw() : base_allocator_type( a ) { } + template + zero_allocator(const zero_allocator &a) throw() : base_allocator_type( Allocator( a ) ) { } + + pointer allocate(const size_type n, const void *hint = 0 ) { + pointer ptr = base_allocator_type::allocate( n, hint ); + std::memset( ptr, 0, n * sizeof(value_type) ); + return ptr; + } +}; + +//! Analogous to std::allocator, as defined in ISO C++ Standard, Section 20.4.1 +/** @ingroup memory_allocation */ +template class Allocator> +class zero_allocator : public Allocator { +public: + typedef Allocator base_allocator_type; + typedef typename base_allocator_type::value_type value_type; + typedef typename base_allocator_type::pointer pointer; + typedef typename base_allocator_type::const_pointer const_pointer; + template struct rebind { + typedef zero_allocator other; + }; +}; + +template class B1, typename T2, template class B2> +inline bool operator==( const zero_allocator &a, const zero_allocator &b) { + return static_cast< B1 >(a) == static_cast< B2 >(b); +} +template class B1, typename T2, template class B2> +inline bool operator!=( const zero_allocator &a, const zero_allocator &b) { + return static_cast< B1 >(a) != static_cast< B2 >(b); +} + +} // namespace tbb + +#endif /* __TBB_tbb_allocator_H */ diff --git a/src/tbb/include/tbb/tbb_config.h b/src/tbb/include/tbb/tbb_config.h new file mode 100644 index 0000000..aed2a8f --- /dev/null +++ b/src/tbb/include/tbb/tbb_config.h @@ -0,0 +1,337 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_tbb_config_H +#define __TBB_tbb_config_H + +/** This header is supposed to contain macro definitions and C style comments only. + The macros defined here are intended to control such aspects of TBB build as + - presence of compiler features + - compilation modes + - feature sets + - known compiler/platform issues +**/ + +#define __TBB_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#if __clang__ +#define __TBB_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) +#endif + +/** Presence of compiler features **/ + +#if (__TBB_GCC_VERSION >= 40400) && !defined(__INTEL_COMPILER) + /** warning suppression pragmas available in GCC since 4.4 **/ + #define __TBB_GCC_WARNING_SUPPRESSION_PRESENT 1 +#endif + + +/* Select particular features of C++11 based on compiler version. + ICC 12.1 (Linux), GCC 4.3 and higher, clang 2.9 and higher + set __GXX_EXPERIMENTAL_CXX0X__ in c++11 mode. + + Compilers that mimics other compilers (ICC, clang) must be processed before + compilers they mimic. + + TODO: The following conditions should be extended when new compilers/runtimes + support added. + */ + +#if __INTEL_COMPILER + #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT __GXX_EXPERIMENTAL_CXX0X__ && __VARIADIC_TEMPLATES + #define __TBB_CPP11_RVALUE_REF_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ || _MSC_VER >= 1600) && (__INTEL_COMPILER >= 1200) + #define __TBB_EXCEPTION_PTR_PRESENT 0 +#elif __clang__ + #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __TBB_CLANG_VERSION >= 20900) + #define __TBB_CPP11_RVALUE_REF_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __TBB_CLANG_VERSION >= 20900) + #define __TBB_EXCEPTION_PTR_PRESENT __GXX_EXPERIMENTAL_CXX0X__ +#elif __GNUC__ + #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT __GXX_EXPERIMENTAL_CXX0X__ + #define __TBB_CPP11_RVALUE_REF_PRESENT __GXX_EXPERIMENTAL_CXX0X__ + #define __TBB_EXCEPTION_PTR_PRESENT __GXX_EXPERIMENTAL_CXX0X__ +#elif _MSC_VER + #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT 0 + #define __TBB_CPP11_RVALUE_REF_PRESENT 0 + #define __TBB_EXCEPTION_PTR_PRESENT (_MSC_VER >= 1600) +#else + #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT 0 + #define __TBB_CPP11_RVALUE_REF_PRESENT 0 + #define __TBB_EXCEPTION_PTR_PRESENT 0 +#endif + +// Work around a bug in MinGW32 +#if __MINGW32__ && __TBB_EXCEPTION_PTR_PRESENT && !defined(_GLIBCXX_ATOMIC_BUILTINS_4) + #define _GLIBCXX_ATOMIC_BUILTINS_4 +#endif + +#if __GNUC__ || __SUNPRO_CC || __IBMCPP__ + /* ICC defines __GNUC__ and so is covered */ + #define __TBB_ATTRIBUTE_ALIGNED_PRESENT 1 +#elif _MSC_VER && (_MSC_VER >= 1300 || __INTEL_COMPILER) + #define __TBB_DECLSPEC_ALIGN_PRESENT 1 +#endif + +/* TODO: change the version back to 4.1.2 once macro __TBB_WORD_SIZE become optional */ +#if (__TBB_GCC_VERSION >= 40306) && !defined(__INTEL_COMPILER) + /** built-in atomics available in GCC since 4.1.2 **/ + #define __TBB_GCC_BUILTIN_ATOMICS_PRESENT 1 +#endif + +/** User controlled TBB features & modes **/ + +#ifndef TBB_USE_DEBUG +#ifdef TBB_DO_ASSERT +#define TBB_USE_DEBUG TBB_DO_ASSERT +#else +#ifdef _DEBUG +#define TBB_USE_DEBUG _DEBUG +#else +#define TBB_USE_DEBUG 0 +#endif +#endif /* TBB_DO_ASSERT */ +#endif /* TBB_USE_DEBUG */ + +#ifndef TBB_USE_ASSERT +#ifdef TBB_DO_ASSERT +#define TBB_USE_ASSERT TBB_DO_ASSERT +#else +#define TBB_USE_ASSERT TBB_USE_DEBUG +#endif /* TBB_DO_ASSERT */ +#endif /* TBB_USE_ASSERT */ + +#ifndef TBB_USE_THREADING_TOOLS +#ifdef TBB_DO_THREADING_TOOLS +#define TBB_USE_THREADING_TOOLS TBB_DO_THREADING_TOOLS +#else +#define TBB_USE_THREADING_TOOLS TBB_USE_DEBUG +#endif /* TBB_DO_THREADING_TOOLS */ +#endif /* TBB_USE_THREADING_TOOLS */ + +#ifndef TBB_USE_PERFORMANCE_WARNINGS +#ifdef TBB_PERFORMANCE_WARNINGS +#define TBB_USE_PERFORMANCE_WARNINGS TBB_PERFORMANCE_WARNINGS +#else +#define TBB_USE_PERFORMANCE_WARNINGS TBB_USE_DEBUG +#endif /* TBB_PEFORMANCE_WARNINGS */ +#endif /* TBB_USE_PERFORMANCE_WARNINGS */ + +#if __MIC__ || __MIC2__ +#define __TBB_DEFINE_MIC 1 +#endif + +#if !defined(__EXCEPTIONS) && !defined(_CPPUNWIND) && !defined(__SUNPRO_CC) || defined(_XBOX) + #if TBB_USE_EXCEPTIONS + #error Compilation settings do not support exception handling. Please do not set TBB_USE_EXCEPTIONS macro or set it to 0. + #elif !defined(TBB_USE_EXCEPTIONS) + #define TBB_USE_EXCEPTIONS 0 + #endif +#elif !defined(TBB_USE_EXCEPTIONS) + #if __TBB_DEFINE_MIC + #define TBB_USE_EXCEPTIONS 0 + #else + #define TBB_USE_EXCEPTIONS 1 + #endif +#elif TBB_USE_EXCEPTIONS && __TBB_DEFINE_MIC + #error Please do not set TBB_USE_EXCEPTIONS macro or set it to 0. +#endif + +#ifndef TBB_IMPLEMENT_CPP0X + /** By default, use C++0x classes if available **/ + #if __GNUC__==4 && __GNUC_MINOR__>=4 && __GXX_EXPERIMENTAL_CXX0X__ + #define TBB_IMPLEMENT_CPP0X 0 + #else + #define TBB_IMPLEMENT_CPP0X 1 + #endif +#endif /* TBB_IMPLEMENT_CPP0X */ + +#ifndef TBB_USE_CAPTURED_EXCEPTION + #if __TBB_EXCEPTION_PTR_PRESENT + #define TBB_USE_CAPTURED_EXCEPTION 0 + #else + #define TBB_USE_CAPTURED_EXCEPTION 1 + #endif +#else /* defined TBB_USE_CAPTURED_EXCEPTION */ + #if !TBB_USE_CAPTURED_EXCEPTION && !__TBB_EXCEPTION_PTR_PRESENT + #error Current runtime does not support std::exception_ptr. Set TBB_USE_CAPTURED_EXCEPTION and make sure that your code is ready to catch tbb::captured_exception. + #endif +#endif /* defined TBB_USE_CAPTURED_EXCEPTION */ + +/** Check whether the request to use GCC atomics can be satisfied **/ +#if (TBB_USE_GCC_BUILTINS && !__TBB_GCC_BUILTIN_ATOMICS_PRESENT) + #error "GCC atomic built-ins are not supported." +#endif + +/** Internal TBB features & modes **/ + +/** __TBB_DYNAMIC_LOAD_ENABLED describes the system possibility to dynamic load libraries + __TBB_SOURCE_DIRECTLY_INCLUDED is a mode used in whitebox testing when + it's necessary to test internal functions not exported from TBB DLLs +**/ + +#ifndef __TBB_DYNAMIC_LOAD_ENABLED + #define __TBB_DYNAMIC_LOAD_ENABLED 1 +#elif !(_WIN32||_WIN64) && !__TBB_DYNAMIC_LOAD_ENABLED + #define __TBB_WEAK_SYMBOLS 1 +#endif + +#if (_WIN32||_WIN64) && __TBB_SOURCE_DIRECTLY_INCLUDED + #define __TBB_NO_IMPLICIT_LINKAGE 1 + #define __TBBMALLOC_NO_IMPLICIT_LINKAGE 1 +#endif + +#ifndef __TBB_COUNT_TASK_NODES + #define __TBB_COUNT_TASK_NODES TBB_USE_ASSERT +#endif + +#ifndef __TBB_TASK_GROUP_CONTEXT + #define __TBB_TASK_GROUP_CONTEXT 1 +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +#if TBB_USE_EXCEPTIONS && !__TBB_TASK_GROUP_CONTEXT + #error TBB_USE_EXCEPTIONS requires __TBB_TASK_GROUP_CONTEXT to be enabled +#endif + +#ifndef __TBB_SCHEDULER_OBSERVER + #define __TBB_SCHEDULER_OBSERVER 1 +#endif /* __TBB_SCHEDULER_OBSERVER */ + +#ifndef __TBB_TASK_PRIORITY + #define __TBB_TASK_PRIORITY __TBB_TASK_GROUP_CONTEXT +#endif /* __TBB_TASK_PRIORITY */ + +#if __TBB_TASK_PRIORITY && !__TBB_TASK_GROUP_CONTEXT + #error __TBB_TASK_PRIORITY requires __TBB_TASK_GROUP_CONTEXT to be enabled +#endif + +#if !defined(__TBB_SURVIVE_THREAD_SWITCH) && (_WIN32 || _WIN64 || __linux__) + #define __TBB_SURVIVE_THREAD_SWITCH 1 +#endif /* __TBB_SURVIVE_THREAD_SWITCH */ + +#ifndef __TBB_DEFAULT_PARTITIONER +#if TBB_DEPRECATED +/** Default partitioner for parallel loop templates in TBB 1.0-2.1 */ +#define __TBB_DEFAULT_PARTITIONER tbb::simple_partitioner +#else +/** Default partitioner for parallel loop templates since TBB 2.2 */ +#define __TBB_DEFAULT_PARTITIONER tbb::auto_partitioner +#endif /* TBB_DEPRECATED */ +#endif /* !defined(__TBB_DEFAULT_PARTITIONER */ + +#ifdef _VARIADIC_MAX +#define __TBB_VARIADIC_MAX _VARIADIC_MAX +#else +#if _MSC_VER >= 1700 +#define __TBB_VARIADIC_MAX 5 // current VS11 setting, may change. +#else +#define __TBB_VARIADIC_MAX 10 +#endif +#endif + +/** Macros of the form __TBB_XXX_BROKEN denote known issues that are caused by + the bugs in compilers, standard or OS specific libraries. They should be + removed as soon as the corresponding bugs are fixed or the buggy OS/compiler + versions go out of the support list. +**/ + +#if __GNUC__ && __TBB_x86_64 && __INTEL_COMPILER == 1200 + #define __TBB_ICC_12_0_INL_ASM_FSTCW_BROKEN 1 +#endif + +#if _MSC_VER && __INTEL_COMPILER && (__INTEL_COMPILER<1110 || __INTEL_COMPILER==1110 && __INTEL_COMPILER_BUILD_DATE < 20091012) + /** Necessary to avoid ICL error (or warning in non-strict mode): + "exception specification for implicitly declared virtual destructor is + incompatible with that of overridden one". **/ + #define __TBB_DEFAULT_DTOR_THROW_SPEC_BROKEN 1 +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1500 && !defined(__INTEL_COMPILER) + /** VS2005 and earlier do not allow declaring template class as a friend + of classes defined in other namespaces. **/ + #define __TBB_TEMPLATE_FRIENDS_BROKEN 1 +#endif + +#if __GLIBC__==2 && __GLIBC_MINOR__==3 || __MINGW32__ || (__APPLE__ && __INTEL_COMPILER==1200 && !TBB_USE_DEBUG) + //! Macro controlling EH usages in TBB tests + /** Some older versions of glibc crash when exception handling happens concurrently. **/ + #define __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN 1 +#endif + +#if (_WIN32||_WIN64) && __INTEL_COMPILER == 1110 + /** That's a bug in Intel compiler 11.1.044/IA-32/Windows, that leads to a worker thread crash on the thread's startup. **/ + #define __TBB_ICL_11_1_CODE_GEN_BROKEN 1 +#endif + +#if __clang__ || (__GNUC__==3 && __GNUC_MINOR__==3 && !defined(__INTEL_COMPILER)) + /** Bugs with access to nested classes declared in protected area */ + #define __TBB_PROTECTED_NESTED_CLASS_BROKEN 1 +#endif + +#if __MINGW32__ && (__GNUC__<4 || __GNUC__==4 && __GNUC_MINOR__<2) + /** MinGW has a bug with stack alignment for routines invoked from MS RTLs. + Since GCC 4.2, the bug can be worked around via a special attribute. **/ + #define __TBB_SSE_STACK_ALIGNMENT_BROKEN 1 +#endif + +#if __GNUC__==4 && __GNUC_MINOR__==3 && __GNUC_PATCHLEVEL__==0 + // GCC of this version may rashly ignore control dependencies + #define __TBB_GCC_OPTIMIZER_ORDERING_BROKEN 1 +#endif + +#if __FreeBSD__ + /** A bug in FreeBSD 8.0 results in kernel panic when there is contention + on a mutex created with this attribute. **/ + #define __TBB_PRIO_INHERIT_BROKEN 1 + + /** A bug in FreeBSD 8.0 results in test hanging when an exception occurs + during (concurrent?) object construction by means of placement new operator. **/ + #define __TBB_PLACEMENT_NEW_EXCEPTION_SAFETY_BROKEN 1 +#endif /* __FreeBSD__ */ + +#if (__linux__ || __APPLE__) && __i386__ && defined(__INTEL_COMPILER) + /** The Intel compiler for IA-32 (Linux|Mac OS X) crashes or generates + incorrect code when __asm__ arguments have a cast to volatile. **/ + #define __TBB_ICC_ASM_VOLATILE_BROKEN 1 +#endif + +#if !__INTEL_COMPILER && (_MSC_VER || __GNUC__==3 && __GNUC_MINOR__<=2) + /** Bug in GCC 3.2 and MSVC compilers that sometimes return 0 for __alignof(T) + when T has not yet been instantiated. **/ + #define __TBB_ALIGNOF_NOT_INSTANTIATED_TYPES_BROKEN 1 +#endif + +#if __INTEL_COMPILER + #define __TBB_CPP11_STD_FORWARD_BROKEN 1 +#else + #define __TBB_CPP11_STD_FORWARD_BROKEN 0 +#endif + +#if __TBB_DEFINE_MIC + /** Main thread and user's thread have different default thread affinity masks. **/ + #define __TBB_MAIN_THREAD_AFFINITY_BROKEN 1 +#endif + +#endif /* __TBB_tbb_config_H */ diff --git a/src/tbb/include/tbb/tbb_exception.h b/src/tbb/include/tbb/tbb_exception.h new file mode 100644 index 0000000..7754dbc --- /dev/null +++ b/src/tbb/include/tbb/tbb_exception.h @@ -0,0 +1,367 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_exception_H +#define __TBB_exception_H + +#include "tbb_stddef.h" + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include +#include // required to construct std exception classes + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +namespace tbb { + +//! Exception for concurrent containers +class bad_last_alloc : public std::bad_alloc { +public: + /*override*/ const char* what() const throw(); +#if __TBB_DEFAULT_DTOR_THROW_SPEC_BROKEN + /*override*/ ~bad_last_alloc() throw() {} +#endif +}; + +//! Exception for PPL locks +class improper_lock : public std::exception { +public: + /*override*/ const char* what() const throw(); +}; + +//! Exception for user-initiated abort +class user_abort : public std::exception { +public: + /*override*/ const char* what() const throw(); +}; + +//! Exception for missing wait on structured_task_group +class missing_wait : public std::exception { +public: + /*override*/ const char* what() const throw(); +}; + +//! Exception for repeated scheduling of the same task_handle +class invalid_multiple_scheduling : public std::exception { +public: + /*override*/ const char* what() const throw(); +}; + +namespace internal { +//! Obsolete +void __TBB_EXPORTED_FUNC throw_bad_last_alloc_exception_v4(); + +enum exception_id { + eid_bad_alloc = 1, + eid_bad_last_alloc, + eid_nonpositive_step, + eid_out_of_range, + eid_segment_range_error, + eid_index_range_error, + eid_missing_wait, + eid_invalid_multiple_scheduling, + eid_improper_lock, + eid_possible_deadlock, + eid_operation_not_permitted, + eid_condvar_wait_failed, + eid_invalid_load_factor, + eid_reserved, // free slot for backward compatibility, can be reused. + eid_invalid_swap, + eid_reservation_length_error, + eid_invalid_key, + eid_user_abort, + //! The last enumerator tracks the number of defined IDs. It must remain the last one. + /** When adding new IDs, place them immediately _before_ this comment (that is + _after_ all the existing IDs. NEVER insert new IDs between the existing ones. **/ + eid_max +}; + +//! Gathers all throw operators in one place. +/** Its purpose is to minimize code bloat that can be caused by throw operators + scattered in multiple places, especially in templates. **/ +void __TBB_EXPORTED_FUNC throw_exception_v4 ( exception_id ); + +//! Versionless convenience wrapper for throw_exception_v4() +inline void throw_exception ( exception_id eid ) { throw_exception_v4(eid); } + +} // namespace internal +} // namespace tbb + +#if __TBB_TASK_GROUP_CONTEXT +#include "tbb_allocator.h" +#include +#include +#include + +namespace tbb { + +//! Interface to be implemented by all exceptions TBB recognizes and propagates across the threads. +/** If an unhandled exception of the type derived from tbb::tbb_exception is intercepted + by the TBB scheduler in one of the worker threads, it is delivered to and re-thrown in + the root thread. The root thread is the thread that has started the outermost algorithm + or root task sharing the same task_group_context with the guilty algorithm/task (the one + that threw the exception first). + + Note: when documentation mentions workers with respect to exception handling, + masters are implied as well, because they are completely equivalent in this context. + Consequently a root thread can be master or worker thread. + + NOTE: In case of nested algorithms or complex task hierarchies when the nested + levels share (explicitly or by means of implicit inheritance) the task group + context of the outermost level, the exception may be (re-)thrown multiple times + (ultimately - in each worker on each nesting level) before reaching the root + thread at the outermost level. IMPORTANT: if you intercept an exception derived + from this class on a nested level, you must re-throw it in the catch block by means + of the "throw;" operator. + + TBB provides two implementations of this interface: tbb::captured_exception and + template class tbb::movable_exception. See their declarations for more info. **/ +class tbb_exception : public std::exception +{ + /** No operator new is provided because the TBB usage model assumes dynamic + creation of the TBB exception objects only by means of applying move() + operation on an exception thrown out of TBB scheduler. **/ + void* operator new ( size_t ); + +public: + //! Creates and returns pointer to the deep copy of this exception object. + /** Move semantics is allowed. **/ + virtual tbb_exception* move () throw() = 0; + + //! Destroys objects created by the move() method. + /** Frees memory and calls destructor for this exception object. + Can and must be used only on objects created by the move method. **/ + virtual void destroy () throw() = 0; + + //! Throws this exception object. + /** Make sure that if you have several levels of derivation from this interface + you implement or override this method on the most derived level. The implementation + is as simple as "throw *this;". Failure to do this will result in exception + of a base class type being thrown. **/ + virtual void throw_self () = 0; + + //! Returns RTTI name of the originally intercepted exception + virtual const char* name() const throw() = 0; + + //! Returns the result of originally intercepted exception's what() method. + virtual const char* what() const throw() = 0; + + /** Operator delete is provided only to allow using existing smart pointers + with TBB exception objects obtained as the result of applying move() + operation on an exception thrown out of TBB scheduler. + + When overriding method move() make sure to override operator delete as well + if memory is allocated not by TBB's scalable allocator. **/ + void operator delete ( void* p ) { + internal::deallocate_via_handler_v3(p); + } +}; + +//! This class is used by TBB to propagate information about unhandled exceptions into the root thread. +/** Exception of this type is thrown by TBB in the root thread (thread that started a parallel + algorithm ) if an unhandled exception was intercepted during the algorithm execution in one + of the workers. + \sa tbb::tbb_exception **/ +class captured_exception : public tbb_exception +{ +public: + captured_exception ( const captured_exception& src ) + : tbb_exception(src), my_dynamic(false) + { + set(src.my_exception_name, src.my_exception_info); + } + + captured_exception ( const char* name_, const char* info ) + : my_dynamic(false) + { + set(name_, info); + } + + __TBB_EXPORTED_METHOD ~captured_exception () throw(); + + captured_exception& operator= ( const captured_exception& src ) { + if ( this != &src ) { + clear(); + set(src.my_exception_name, src.my_exception_info); + } + return *this; + } + + /*override*/ + captured_exception* __TBB_EXPORTED_METHOD move () throw(); + + /*override*/ + void __TBB_EXPORTED_METHOD destroy () throw(); + + /*override*/ + void throw_self () { __TBB_THROW(*this); } + + /*override*/ + const char* __TBB_EXPORTED_METHOD name() const throw(); + + /*override*/ + const char* __TBB_EXPORTED_METHOD what() const throw(); + + void __TBB_EXPORTED_METHOD set ( const char* name, const char* info ) throw(); + void __TBB_EXPORTED_METHOD clear () throw(); + +private: + //! Used only by method clone(). + captured_exception() {} + + //! Functionally equivalent to {captured_exception e(name,info); return e.clone();} + static captured_exception* allocate ( const char* name, const char* info ); + + bool my_dynamic; + const char* my_exception_name; + const char* my_exception_info; +}; + +//! Template that can be used to implement exception that transfers arbitrary ExceptionData to the root thread +/** Code using TBB can instantiate this template with an arbitrary ExceptionData type + and throw this exception object. Such exceptions are intercepted by the TBB scheduler + and delivered to the root thread (). + \sa tbb::tbb_exception **/ +template +class movable_exception : public tbb_exception +{ + typedef movable_exception self_type; + +public: + movable_exception ( const ExceptionData& data_ ) + : my_exception_data(data_) + , my_dynamic(false) + , my_exception_name( +#if TBB_USE_EXCEPTIONS + typeid(self_type).name() +#else /* !TBB_USE_EXCEPTIONS */ + "movable_exception" +#endif /* !TBB_USE_EXCEPTIONS */ + ) + {} + + movable_exception ( const movable_exception& src ) throw () + : tbb_exception(src) + , my_exception_data(src.my_exception_data) + , my_dynamic(false) + , my_exception_name(src.my_exception_name) + {} + + ~movable_exception () throw() {} + + const movable_exception& operator= ( const movable_exception& src ) { + if ( this != &src ) { + my_exception_data = src.my_exception_data; + my_exception_name = src.my_exception_name; + } + return *this; + } + + ExceptionData& data () throw() { return my_exception_data; } + + const ExceptionData& data () const throw() { return my_exception_data; } + + /*override*/ const char* name () const throw() { return my_exception_name; } + + /*override*/ const char* what () const throw() { return "tbb::movable_exception"; } + + /*override*/ + movable_exception* move () throw() { + void* e = internal::allocate_via_handler_v3(sizeof(movable_exception)); + if ( e ) { + ::new (e) movable_exception(*this); + ((movable_exception*)e)->my_dynamic = true; + } + return (movable_exception*)e; + } + /*override*/ + void destroy () throw() { + __TBB_ASSERT ( my_dynamic, "Method destroy can be called only on dynamically allocated movable_exceptions" ); + if ( my_dynamic ) { + this->~movable_exception(); + internal::deallocate_via_handler_v3(this); + } + } + /*override*/ + void throw_self () { __TBB_THROW( *this ); } + +protected: + //! User data + ExceptionData my_exception_data; + +private: + //! Flag specifying whether this object has been dynamically allocated (by the move method) + bool my_dynamic; + + //! RTTI name of this class + /** We rely on the fact that RTTI names are static string constants. **/ + const char* my_exception_name; +}; + +#if !TBB_USE_CAPTURED_EXCEPTION +namespace internal { + +//! Exception container that preserves the exact copy of the original exception +/** This class can be used only when the appropriate runtime support (mandated + by C++0x) is present **/ +class tbb_exception_ptr { + std::exception_ptr my_ptr; + +public: + static tbb_exception_ptr* allocate (); + static tbb_exception_ptr* allocate ( const tbb_exception& tag ); + //! This overload uses move semantics (i.e. it empties src) + static tbb_exception_ptr* allocate ( captured_exception& src ); + + //! Destroys this objects + /** Note that objects of this type can be created only by the allocate() method. **/ + void destroy () throw(); + + //! Throws the contained exception . + void throw_self () { std::rethrow_exception(my_ptr); } + +private: + tbb_exception_ptr ( const std::exception_ptr& src ) : my_ptr(src) {} + tbb_exception_ptr ( const captured_exception& src ) : my_ptr(std::copy_exception(src)) {} +}; // class tbb::internal::tbb_exception_ptr + +} // namespace internal +#endif /* !TBB_USE_CAPTURED_EXCEPTION */ + +} // namespace tbb + +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +#endif /* __TBB_exception_H */ diff --git a/src/tbb/include/tbb/tbb_machine.h b/src/tbb/include/tbb/tbb_machine.h new file mode 100644 index 0000000..6c83942 --- /dev/null +++ b/src/tbb/include/tbb/tbb_machine.h @@ -0,0 +1,875 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_machine_H +#define __TBB_machine_H + +/** This header provides basic platform abstraction layer by hooking up appropriate + architecture/OS/compiler specific headers from the /include/tbb/machine directory. + If a plug-in header does not implement all the required APIs, it must specify + the missing ones by setting one or more of the following macros: + + __TBB_USE_GENERIC_PART_WORD_CAS + __TBB_USE_GENERIC_PART_WORD_FETCH_ADD + __TBB_USE_GENERIC_PART_WORD_FETCH_STORE + __TBB_USE_GENERIC_FETCH_ADD + __TBB_USE_GENERIC_FETCH_STORE + __TBB_USE_GENERIC_DWORD_FETCH_ADD + __TBB_USE_GENERIC_DWORD_FETCH_STORE + __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE + __TBB_USE_GENERIC_FULL_FENCED_LOAD_STORE + __TBB_USE_GENERIC_RELAXED_LOAD_STORE + __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE + + In this case tbb_machine.h will add missing functionality based on a minimal set + of APIs that are required to be implemented by all plug-n headers as described + further. + Note that these generic implementations may be sub-optimal for a particular + architecture, and thus should be relied upon only after careful evaluation + or as the last resort. + + Additionally __TBB_64BIT_ATOMICS can be set to 0 on a 32-bit architecture to + indicate that the port is not going to support double word atomics. It may also + be set to 1 explicitly, though normally this is not necessary as tbb_machine.h + will set it automatically. + + __TBB_BIG_ENDIAN macro can be defined by the implementation as well. + It is used only if the __TBB_USE_GENERIC_PART_WORD_CAS is set. + Possible values are: + - 1 if the system is big endian, + - 0 if it is little endian, + - or -1 to explicitly state that __TBB_USE_GENERIC_PART_WORD_CAS can not be used. + -1 should be used when it is known in advance that endianness can change in run time + or it is not simple big or little but something more complex. + The system will try to detect it in run time if it is not set(in assumption that it + is either a big or little one). + + Prerequisites for each architecture port + ---------------------------------------- + The following functions and macros have no generic implementation. Therefore they must be + implemented in each machine architecture specific header either as a conventional + function or as a functional macro. + + __TBB_WORDSIZE + This is the size of machine word in bytes, i.e. for 32 bit systems it + should be defined to 4. + + __TBB_Yield() + Signals OS that the current thread is willing to relinquish the remainder + of its time quantum. + + __TBB_full_memory_fence() + Must prevent all memory operations from being reordered across it (both + by hardware and compiler). All such fences must be totally ordered (or + sequentially consistent). + + __TBB_machine_cmpswp4( volatile void *ptr, int32_t value, int32_t comparand ) + Must be provided if __TBB_USE_FENCED_ATOMICS is not set. + + __TBB_machine_cmpswp8( volatile void *ptr, int32_t value, int64_t comparand ) + Must be provided for 64-bit architectures if __TBB_USE_FENCED_ATOMICS is not set, + and for 32-bit architectures if __TBB_64BIT_ATOMICS is set + + __TBB_machine_(...), where + = {cmpswp, fetchadd, fetchstore} + = {1, 2, 4, 8} + = {full_fence, acquire, release, relaxed} + Must be provided if __TBB_USE_FENCED_ATOMICS is set. + + __TBB_control_consistency_helper() + Bridges the memory-semantics gap between architectures providing only + implicit C++0x "consume" semantics (like Power Architecture) and those + also implicitly obeying control dependencies (like IA-64). + It must be used only in conditional code where the condition is itself + data-dependent, and will then make subsequent code behave as if the + original data dependency were acquired. + It needs only a compiler fence where implied by the architecture + either specifically (like IA-64) or because generally stronger "acquire" + semantics are enforced (like x86). + It is always valid, though potentially suboptimal, to replace + control with acquire on the load and then remove the helper. + + __TBB_acquire_consistency_helper(), __TBB_release_consistency_helper() + Must be provided if __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE is set. + Enforce acquire and release semantics in generic implementations of fenced + store and load operations. Depending on the particular architecture/compiler + combination they may be a hardware fence, a compiler fence, both or nothing. + **/ + +#include "tbb_stddef.h" + +namespace tbb { +namespace internal { + +//////////////////////////////////////////////////////////////////////////////// +// Overridable helpers declarations +// +// A machine/*.h file may choose to define these templates, otherwise it must +// request default implementation by setting appropriate __TBB_USE_GENERIC_XXX macro(s). +// +template +struct machine_load_store; + +template +struct machine_load_store_relaxed; + +template +struct machine_load_store_seq_cst; +// +// End of overridable helpers declarations +//////////////////////////////////////////////////////////////////////////////// + +template struct atomic_selector; + +template<> struct atomic_selector<1> { + typedef int8_t word; + inline static word fetch_store ( volatile void* location, word value ); +}; + +template<> struct atomic_selector<2> { + typedef int16_t word; + inline static word fetch_store ( volatile void* location, word value ); +}; + +template<> struct atomic_selector<4> { +#if _MSC_VER && !_WIN64 + // Work-around that avoids spurious /Wp64 warnings + typedef intptr_t word; +#else + typedef int32_t word; +#endif + inline static word fetch_store ( volatile void* location, word value ); +}; + +template<> struct atomic_selector<8> { + typedef int64_t word; + inline static word fetch_store ( volatile void* location, word value ); +}; + +}} // namespaces internal, tbb + +#if _WIN32||_WIN64 + +#ifdef _MANAGED +#pragma managed(push, off) +#endif + + #if __MINGW64__ || __MINGW32__ + extern "C" __declspec(dllimport) int __stdcall SwitchToThread( void ); + #define __TBB_Yield() SwitchToThread() + #if (TBB_USE_GCC_BUILTINS && __TBB_GCC_BUILTIN_ATOMICS_PRESENT) + #include "machine/gcc_generic.h" + #elif __MINGW64__ + #include "machine/linux_intel64.h" + #elif __MINGW32__ + #include "machine/linux_ia32.h" + #endif + #elif defined(_M_IX86) + #include "machine/windows_ia32.h" + #elif defined(_M_X64) + #include "machine/windows_intel64.h" + #elif _XBOX + #include "machine/xbox360_ppc.h" + #endif + +#ifdef _MANAGED +#pragma managed(pop) +#endif + +#elif __TBB_DEFINE_MIC + + #include "machine/mic_common.h" + #include "machine/linux_intel64.h" + +#elif __linux__ || __FreeBSD__ || __NetBSD__ + + #if (TBB_USE_GCC_BUILTINS && __TBB_GCC_BUILTIN_ATOMICS_PRESENT) + #include "machine/gcc_generic.h" + #elif __i386__ + #include "machine/linux_ia32.h" + #elif __x86_64__ + #include "machine/linux_intel64.h" + #elif __ia64__ + #include "machine/linux_ia64.h" + #elif __powerpc__ + #include "machine/mac_ppc.h" + #elif __TBB_GCC_BUILTIN_ATOMICS_PRESENT + #include "machine/gcc_generic.h" + #endif + #include "machine/linux_common.h" + +#elif __APPLE__ + + #if __i386__ + #include "machine/linux_ia32.h" + #elif __x86_64__ + #include "machine/linux_intel64.h" + #elif __POWERPC__ + #include "machine/mac_ppc.h" + #endif + #include "machine/macos_common.h" + +#elif _AIX + + #include "machine/ibm_aix51.h" + +#elif __sun || __SUNPRO_CC + + #define __asm__ asm + #define __volatile__ volatile + + #if __i386 || __i386__ + #include "machine/linux_ia32.h" + #elif __x86_64__ + #include "machine/linux_intel64.h" + #elif __sparc + #include "machine/sunos_sparc.h" + #endif + #include + + #define __TBB_Yield() sched_yield() + +#endif /* OS selection */ + +#ifndef __TBB_64BIT_ATOMICS + #define __TBB_64BIT_ATOMICS 1 +#endif + +// Special atomic functions +#if __TBB_USE_FENCED_ATOMICS + #define __TBB_machine_cmpswp1 __TBB_machine_cmpswp1full_fence + #define __TBB_machine_cmpswp2 __TBB_machine_cmpswp2full_fence + #define __TBB_machine_cmpswp4 __TBB_machine_cmpswp4full_fence + #define __TBB_machine_cmpswp8 __TBB_machine_cmpswp8full_fence + + #if __TBB_WORDSIZE==8 + #define __TBB_machine_fetchadd8 __TBB_machine_fetchadd8full_fence + #define __TBB_machine_fetchstore8 __TBB_machine_fetchstore8full_fence + #define __TBB_FetchAndAddWrelease(P,V) __TBB_machine_fetchadd8release(P,V) + #define __TBB_FetchAndIncrementWacquire(P) __TBB_machine_fetchadd8acquire(P,1) + #define __TBB_FetchAndDecrementWrelease(P) __TBB_machine_fetchadd8release(P,(-1)) + #else + #error Define macros for 4-byte word, similarly to the above __TBB_WORDSIZE==8 branch. + #endif /* __TBB_WORDSIZE==4 */ +#else /* !__TBB_USE_FENCED_ATOMICS */ + #define __TBB_FetchAndAddWrelease(P,V) __TBB_FetchAndAddW(P,V) + #define __TBB_FetchAndIncrementWacquire(P) __TBB_FetchAndAddW(P,1) + #define __TBB_FetchAndDecrementWrelease(P) __TBB_FetchAndAddW(P,(-1)) +#endif /* !__TBB_USE_FENCED_ATOMICS */ + +#if __TBB_WORDSIZE==4 + #define __TBB_CompareAndSwapW(P,V,C) __TBB_machine_cmpswp4(P,V,C) + #define __TBB_FetchAndAddW(P,V) __TBB_machine_fetchadd4(P,V) + #define __TBB_FetchAndStoreW(P,V) __TBB_machine_fetchstore4(P,V) +#elif __TBB_WORDSIZE==8 + #if __TBB_USE_GENERIC_DWORD_LOAD_STORE || __TBB_USE_GENERIC_DWORD_FETCH_ADD || __TBB_USE_GENERIC_DWORD_FETCH_STORE + #error These macros should only be used on 32-bit platforms. + #endif + + #define __TBB_CompareAndSwapW(P,V,C) __TBB_machine_cmpswp8(P,V,C) + #define __TBB_FetchAndAddW(P,V) __TBB_machine_fetchadd8(P,V) + #define __TBB_FetchAndStoreW(P,V) __TBB_machine_fetchstore8(P,V) +#else /* __TBB_WORDSIZE != 8 */ + #error Unsupported machine word size. +#endif /* __TBB_WORDSIZE */ + +#ifndef __TBB_Pause + inline void __TBB_Pause(int32_t) { + __TBB_Yield(); + } +#endif + +namespace tbb { + +//! Sequentially consistent full memory fence. +inline void atomic_fence () { __TBB_full_memory_fence(); } + +namespace internal { + +//! Class that implements exponential backoff. +/** See implementation of spin_wait_while_eq for an example. */ +class atomic_backoff : no_copy { + //! Time delay, in units of "pause" instructions. + /** Should be equal to approximately the number of "pause" instructions + that take the same time as an context switch. */ + static const int32_t LOOPS_BEFORE_YIELD = 16; + int32_t count; +public: + atomic_backoff() : count(1) {} + + //! Pause for a while. + void pause() { + if( count<=LOOPS_BEFORE_YIELD ) { + __TBB_Pause(count); + // Pause twice as long the next time. + count*=2; + } else { + // Pause is so long that we might as well yield CPU to scheduler. + __TBB_Yield(); + } + } + + // pause for a few times and then return false immediately. + bool bounded_pause() { + if( count<=LOOPS_BEFORE_YIELD ) { + __TBB_Pause(count); + // Pause twice as long the next time. + count*=2; + return true; + } else { + return false; + } + } + + void reset() { + count = 1; + } +}; + +//! Spin WHILE the value of the variable is equal to a given value +/** T and U should be comparable types. */ +template +void spin_wait_while_eq( const volatile T& location, U value ) { + atomic_backoff backoff; + while( location==value ) backoff.pause(); +} + +//! Spin UNTIL the value of the variable is equal to a given value +/** T and U should be comparable types. */ +template +void spin_wait_until_eq( const volatile T& location, const U value ) { + atomic_backoff backoff; + while( location!=value ) backoff.pause(); +} + +//TODO: add static_assert for the requirements stated below +//TODO: check if it works with signed types + +// there are following restrictions/limitations for this operation: +// - T should be unsigned, otherwise sign propagation will break correctness of bit manipulations. +// - T should be integer type of at most 4 bytes, for the casts and calculations to work. +// (Together, these rules limit applicability of Masked CAS to uint8_t and uint16_t only, +// as it does nothing useful for 4 bytes). +// - The operation assumes that the architecture consistently uses either little-endian or big-endian: +// it does not support mixed-endian or page-specific bi-endian architectures. +// This function is the only use of __TBB_BIG_ENDIAN. +#if (__TBB_BIG_ENDIAN!=-1) + #if ( __TBB_USE_GENERIC_PART_WORD_CAS) + #error generic implementation of part-word CAS was explicitly disabled for this configuration + #endif +template +inline T __TBB_MaskedCompareAndSwap (volatile T * const ptr, const T value, const T comparand ) { + struct endianness{ static bool is_big_endian(){ + #ifndef __TBB_BIG_ENDIAN + const uint32_t probe = 0x03020100; + return (((const char*)(&probe))[0]==0x03); + #elif (__TBB_BIG_ENDIAN==0) || (__TBB_BIG_ENDIAN==1) + return __TBB_BIG_ENDIAN; + #else + #error unexpected value of __TBB_BIG_ENDIAN + #endif + }}; + + const uint32_t byte_offset = (uint32_t) ((uintptr_t)ptr & 0x3); + volatile uint32_t * const aligned_ptr = (uint32_t*)((uintptr_t)ptr - byte_offset ); + + // location of T within uint32_t for a C++ shift operation + const uint32_t bits_to_shift = 8*(endianness::is_big_endian() ? (4 - sizeof(T) - (byte_offset)) : byte_offset); + const uint32_t mask = (((uint32_t)1<<(sizeof(T)*8)) - 1 )<> bits_to_shift); + } + else continue; // CAS failed but the bits of interest left unchanged + } +} +#endif +template +inline T __TBB_CompareAndSwapGeneric (volatile void *ptr, T value, T comparand ); + +template<> +inline uint8_t __TBB_CompareAndSwapGeneric <1,uint8_t> (volatile void *ptr, uint8_t value, uint8_t comparand ) { +#if __TBB_USE_GENERIC_PART_WORD_CAS + return __TBB_MaskedCompareAndSwap((volatile uint8_t *)ptr,value,comparand); +#else + return __TBB_machine_cmpswp1(ptr,value,comparand); +#endif +} + +template<> +inline uint16_t __TBB_CompareAndSwapGeneric <2,uint16_t> (volatile void *ptr, uint16_t value, uint16_t comparand ) { +#if __TBB_USE_GENERIC_PART_WORD_CAS + return __TBB_MaskedCompareAndSwap((volatile uint16_t *)ptr,value,comparand); +#else + return __TBB_machine_cmpswp2(ptr,value,comparand); +#endif +} + +template<> +inline uint32_t __TBB_CompareAndSwapGeneric <4,uint32_t> (volatile void *ptr, uint32_t value, uint32_t comparand ) { + // Cast shuts up /Wp64 warning + return (uint32_t)__TBB_machine_cmpswp4(ptr,value,comparand); +} + +#if __TBB_64BIT_ATOMICS +template<> +inline uint64_t __TBB_CompareAndSwapGeneric <8,uint64_t> (volatile void *ptr, uint64_t value, uint64_t comparand ) { + return __TBB_machine_cmpswp8(ptr,value,comparand); +} +#endif + +template +inline T __TBB_FetchAndAddGeneric (volatile void *ptr, T addend) { + atomic_backoff b; + T result; + for(;;) { + result = *reinterpret_cast(ptr); + // __TBB_CompareAndSwapGeneric presumed to have full fence. + if( __TBB_CompareAndSwapGeneric ( ptr, result+addend, result )==result ) + break; + b.pause(); + } + return result; +} + +template +inline T __TBB_FetchAndStoreGeneric (volatile void *ptr, T value) { + atomic_backoff b; + T result; + for(;;) { + result = *reinterpret_cast(ptr); + // __TBB_CompareAndSwapGeneric presumed to have full fence. + if( __TBB_CompareAndSwapGeneric ( ptr, value, result )==result ) + break; + b.pause(); + } + return result; +} + +#if __TBB_USE_GENERIC_PART_WORD_CAS +#define __TBB_machine_cmpswp1 tbb::internal::__TBB_CompareAndSwapGeneric<1,uint8_t> +#define __TBB_machine_cmpswp2 tbb::internal::__TBB_CompareAndSwapGeneric<2,uint16_t> +#endif + +#if __TBB_USE_GENERIC_FETCH_ADD || __TBB_USE_GENERIC_PART_WORD_FETCH_ADD +#define __TBB_machine_fetchadd1 tbb::internal::__TBB_FetchAndAddGeneric<1,uint8_t> +#define __TBB_machine_fetchadd2 tbb::internal::__TBB_FetchAndAddGeneric<2,uint16_t> +#endif + +#if __TBB_USE_GENERIC_FETCH_ADD +#define __TBB_machine_fetchadd4 tbb::internal::__TBB_FetchAndAddGeneric<4,uint32_t> +#endif + +#if __TBB_USE_GENERIC_FETCH_ADD || __TBB_USE_GENERIC_DWORD_FETCH_ADD +#define __TBB_machine_fetchadd8 tbb::internal::__TBB_FetchAndAddGeneric<8,uint64_t> +#endif + +#if __TBB_USE_GENERIC_FETCH_STORE || __TBB_USE_GENERIC_PART_WORD_FETCH_STORE +#define __TBB_machine_fetchstore1 tbb::internal::__TBB_FetchAndStoreGeneric<1,uint8_t> +#define __TBB_machine_fetchstore2 tbb::internal::__TBB_FetchAndStoreGeneric<2,uint16_t> +#endif + +#if __TBB_USE_GENERIC_FETCH_STORE +#define __TBB_machine_fetchstore4 tbb::internal::__TBB_FetchAndStoreGeneric<4,uint32_t> +#endif + +#if __TBB_USE_GENERIC_FETCH_STORE || __TBB_USE_GENERIC_DWORD_FETCH_STORE +#define __TBB_machine_fetchstore8 tbb::internal::__TBB_FetchAndStoreGeneric<8,uint64_t> +#endif + +#if __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE +#define __TBB_MACHINE_DEFINE_ATOMIC_SELECTOR_FETCH_STORE(S) \ + atomic_selector::word atomic_selector::fetch_store ( volatile void* location, word value ) { \ + return __TBB_machine_fetchstore##S( location, value ); \ + } + +__TBB_MACHINE_DEFINE_ATOMIC_SELECTOR_FETCH_STORE(1) +__TBB_MACHINE_DEFINE_ATOMIC_SELECTOR_FETCH_STORE(2) +__TBB_MACHINE_DEFINE_ATOMIC_SELECTOR_FETCH_STORE(4) +__TBB_MACHINE_DEFINE_ATOMIC_SELECTOR_FETCH_STORE(8) + +#undef __TBB_MACHINE_DEFINE_ATOMIC_SELECTOR_FETCH_STORE +#endif /* __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE */ + +#if __TBB_USE_GENERIC_DWORD_LOAD_STORE +inline void __TBB_machine_store8 (volatile void *ptr, int64_t value) { + for(;;) { + int64_t result = *(int64_t *)ptr; + if( __TBB_machine_cmpswp8(ptr,value,result)==result ) break; + } +} + +inline int64_t __TBB_machine_load8 (const volatile void *ptr) { + // Comparand and new value may be anything, they only must be equal, and + // the value should have a low probability to be actually found in 'location'. + const int64_t anyvalue = 2305843009213693951LL; + return __TBB_machine_cmpswp8(const_cast(ptr),anyvalue,anyvalue); +} +#endif /* __TBB_USE_GENERIC_DWORD_LOAD_STORE */ + +#if __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE +/** Fenced operations use volatile qualifier to prevent compiler from optimizing + them out, and on on architectures with weak memory ordering to induce compiler + to generate code with appropriate acquire/release semantics. + On architectures like IA32, Intel64 (and likely and Sparc TSO) volatile has + no effect on code gen, and consistency helpers serve as a compiler fence (the + latter being true for IA64/gcc as well to fix a bug in some gcc versions). **/ +template +struct machine_load_store { + static T load_with_acquire ( const volatile T& location ) { + T to_return = location; + __TBB_acquire_consistency_helper(); + return to_return; + } + static void store_with_release ( volatile T &location, T value ) { + __TBB_release_consistency_helper(); + location = value; + } +}; + +//in general, plain load and store of 32bit compiler is not atomic for 64bit types +#if __TBB_WORDSIZE==4 && __TBB_64BIT_ATOMICS +template +struct machine_load_store { + static T load_with_acquire ( const volatile T& location ) { + return (T)__TBB_machine_load8( (const volatile void*)&location ); + } + static void store_with_release ( volatile T& location, T value ) { + __TBB_machine_store8( (volatile void*)&location, (int64_t)value ); + } +}; +#endif /* __TBB_WORDSIZE==4 && __TBB_64BIT_ATOMICS */ +#endif /* __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE */ + +#if __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE +template +struct machine_load_store_seq_cst { + static T load ( const volatile T& location ) { + __TBB_full_memory_fence(); + return machine_load_store::load_with_acquire( location ); + } +#if __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE + static void store ( volatile T &location, T value ) { + atomic_selector::fetch_store( (volatile void*)&location, (typename atomic_selector::word)value ); + } +#else /* !__TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE */ + static void store ( volatile T &location, T value ) { + machine_load_store::store_with_release( location, value ); + __TBB_full_memory_fence(); + } +#endif /* !__TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE */ +}; + +#if __TBB_WORDSIZE==4 && __TBB_64BIT_ATOMICS +/** The implementation does not use functions __TBB_machine_load8/store8 as they + are not required to be sequentially consistent. **/ +template +struct machine_load_store_seq_cst { + static T load ( const volatile T& location ) { + // Comparand and new value may be anything, they only must be equal, and + // the value should have a low probability to be actually found in 'location'. + const int64_t anyvalue = 2305843009213693951LL; + return __TBB_machine_cmpswp8( (volatile void*)const_cast(&location), anyvalue, anyvalue ); + } + static void store ( volatile T &location, T value ) { + int64_t result = (volatile int64_t&)location; + while ( __TBB_machine_cmpswp8((volatile void*)&location, (int64_t)value, result) != result ) + result = (volatile int64_t&)location; + } +}; +#endif /* __TBB_WORDSIZE==4 && __TBB_64BIT_ATOMICS */ +#endif /*__TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE */ + +#if __TBB_USE_GENERIC_RELAXED_LOAD_STORE +// Relaxed operations add volatile qualifier to prevent compiler from optimizing them out. +/** Volatile should not incur any additional cost on IA32, Intel64, and Sparc TSO + architectures. However on architectures with weak memory ordering compiler may + generate code with acquire/release semantics for operations on volatile data. **/ +template +struct machine_load_store_relaxed { + static inline T load ( const volatile T& location ) { + return location; + } + static inline void store ( volatile T& location, T value ) { + location = value; + } +}; + +#if __TBB_WORDSIZE==4 && __TBB_64BIT_ATOMICS +template +struct machine_load_store_relaxed { + static inline T load ( const volatile T& location ) { + return (T)__TBB_machine_load8( (const volatile void*)&location ); + } + static inline void store ( volatile T& location, T value ) { + __TBB_machine_store8( (volatile void*)&location, (int64_t)value ); + } +}; +#endif /* __TBB_WORDSIZE==4 && __TBB_64BIT_ATOMICS */ +#endif /* __TBB_USE_GENERIC_RELAXED_LOAD_STORE */ + +#undef __TBB_WORDSIZE //this macro is forbidden to use outside of atomic machinery + +template +inline T __TBB_load_with_acquire(const volatile T &location) { + return machine_load_store::load_with_acquire( location ); +} +template +inline void __TBB_store_with_release(volatile T& location, V value) { + machine_load_store::store_with_release( location, T(value) ); +} +//! Overload that exists solely to avoid /Wp64 warnings. +inline void __TBB_store_with_release(volatile size_t& location, size_t value) { + machine_load_store::store_with_release( location, value ); +} + +template +inline T __TBB_load_full_fence(const volatile T &location) { + return machine_load_store_seq_cst::load( location ); +} +template +inline void __TBB_store_full_fence(volatile T& location, V value) { + machine_load_store_seq_cst::store( location, T(value) ); +} +//! Overload that exists solely to avoid /Wp64 warnings. +inline void __TBB_store_full_fence(volatile size_t& location, size_t value) { + machine_load_store_seq_cst::store( location, value ); +} + +template +inline T __TBB_load_relaxed (const volatile T& location) { + return machine_load_store_relaxed::load( const_cast(location) ); +} +template +inline void __TBB_store_relaxed ( volatile T& location, V value ) { + machine_load_store_relaxed::store( const_cast(location), T(value) ); +} +//! Overload that exists solely to avoid /Wp64 warnings. +inline void __TBB_store_relaxed ( volatile size_t& location, size_t value ) { + machine_load_store_relaxed::store( const_cast(location), value ); +} + +// Macro __TBB_TypeWithAlignmentAtLeastAsStrict(T) should be a type with alignment at least as +// strict as type T. The type should have a trivial default constructor and destructor, so that +// arrays of that type can be declared without initializers. +// It is correct (but perhaps a waste of space) if __TBB_TypeWithAlignmentAtLeastAsStrict(T) expands +// to a type bigger than T. +// The default definition here works on machines where integers are naturally aligned and the +// strictest alignment is 64. +#ifndef __TBB_TypeWithAlignmentAtLeastAsStrict + +#if __TBB_ATTRIBUTE_ALIGNED_PRESENT + +#define __TBB_DefineTypeWithAlignment(PowerOf2) \ +struct __TBB_machine_type_with_alignment_##PowerOf2 { \ + uint32_t member[PowerOf2/sizeof(uint32_t)]; \ +} __attribute__((aligned(PowerOf2))); +#define __TBB_alignof(T) __alignof__(T) + +#elif __TBB_DECLSPEC_ALIGN_PRESENT + +#define __TBB_DefineTypeWithAlignment(PowerOf2) \ +__declspec(align(PowerOf2)) \ +struct __TBB_machine_type_with_alignment_##PowerOf2 { \ + uint32_t member[PowerOf2/sizeof(uint32_t)]; \ +}; +#define __TBB_alignof(T) __alignof(T) + +#else /* A compiler with unknown syntax for data alignment */ +#error Must define __TBB_TypeWithAlignmentAtLeastAsStrict(T) +#endif + +/* Now declare types aligned to useful powers of two */ +// TODO: Is __TBB_DefineTypeWithAlignment(8) needed on 32 bit platforms? +__TBB_DefineTypeWithAlignment(16) +__TBB_DefineTypeWithAlignment(32) +__TBB_DefineTypeWithAlignment(64) + +typedef __TBB_machine_type_with_alignment_64 __TBB_machine_type_with_strictest_alignment; + +// Primary template is a declaration of incomplete type so that it fails with unknown alignments +template struct type_with_alignment; + +// Specializations for allowed alignments +template<> struct type_with_alignment<1> { char member; }; +template<> struct type_with_alignment<2> { uint16_t member; }; +template<> struct type_with_alignment<4> { uint32_t member; }; +template<> struct type_with_alignment<8> { uint64_t member; }; +template<> struct type_with_alignment<16> {__TBB_machine_type_with_alignment_16 member; }; +template<> struct type_with_alignment<32> {__TBB_machine_type_with_alignment_32 member; }; +template<> struct type_with_alignment<64> {__TBB_machine_type_with_alignment_64 member; }; + +#if __TBB_ALIGNOF_NOT_INSTANTIATED_TYPES_BROKEN +//! Work around for bug in GNU 3.2 and MSVC compilers. +/** Bug is that compiler sometimes returns 0 for __alignof(T) when T has not yet been instantiated. + The work-around forces instantiation by forcing computation of sizeof(T) before __alignof(T). */ +template +struct work_around_alignment_bug { + static const size_t alignment = __TBB_alignof(T); +}; +#define __TBB_TypeWithAlignmentAtLeastAsStrict(T) tbb::internal::type_with_alignment::alignment> +#else +#define __TBB_TypeWithAlignmentAtLeastAsStrict(T) tbb::internal::type_with_alignment<__TBB_alignof(T)> +#endif /* __TBB_ALIGNOF_NOT_INSTANTIATED_TYPES_BROKEN */ + +#endif /* __TBB_TypeWithAlignmentAtLeastAsStrict */ + +// Template class here is to avoid instantiation of the static data for modules that don't use it +template +struct reverse { + static const T byte_table[256]; +}; +// An efficient implementation of the reverse function utilizes a 2^8 lookup table holding the bit-reversed +// values of [0..2^8 - 1]. Those values can also be computed on the fly at a slightly higher cost. +template +const T reverse::byte_table[256] = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF +}; + +} // namespace internal +} // namespace tbb + +// Preserving access to legacy APIs +using tbb::internal::__TBB_load_with_acquire; +using tbb::internal::__TBB_store_with_release; + +// Mapping historically used names to the ones expected by atomic_load_store_traits +#define __TBB_load_acquire __TBB_load_with_acquire +#define __TBB_store_release __TBB_store_with_release + +#ifndef __TBB_Log2 +inline intptr_t __TBB_Log2( uintptr_t x ) { + if( x==0 ) return -1; + intptr_t result = 0; + uintptr_t tmp; + + if( sizeof(x)>4 && (tmp = ((uint64_t)x)>>32)) { x=tmp; result += 32; } + if( (tmp = x>>16) ) { x=tmp; result += 16; } + if( (tmp = x>>8) ) { x=tmp; result += 8; } + if( (tmp = x>>4) ) { x=tmp; result += 4; } + if( (tmp = x>>2) ) { x=tmp; result += 2; } + return (x&2)? result+1: result; +} +#endif + +#ifndef __TBB_AtomicOR +inline void __TBB_AtomicOR( volatile void *operand, uintptr_t addend ) { + tbb::internal::atomic_backoff b; + for(;;) { + uintptr_t tmp = *(volatile uintptr_t *)operand; + uintptr_t result = __TBB_CompareAndSwapW(operand, tmp|addend, tmp); + if( result==tmp ) break; + b.pause(); + } +} +#endif + +#ifndef __TBB_AtomicAND +inline void __TBB_AtomicAND( volatile void *operand, uintptr_t addend ) { + tbb::internal::atomic_backoff b; + for(;;) { + uintptr_t tmp = *(volatile uintptr_t *)operand; + uintptr_t result = __TBB_CompareAndSwapW(operand, tmp&addend, tmp); + if( result==tmp ) break; + b.pause(); + } +} +#endif + +#ifndef __TBB_Flag +typedef unsigned char __TBB_Flag; +#endif +typedef __TBB_atomic __TBB_Flag __TBB_atomic_flag; + +#ifndef __TBB_TryLockByte +inline bool __TBB_TryLockByte( __TBB_atomic_flag &flag ) { + return __TBB_machine_cmpswp1(&flag,1,0)==0; +} +#endif + +#ifndef __TBB_LockByte +inline __TBB_Flag __TBB_LockByte( __TBB_atomic_flag& flag ) { + if ( !__TBB_TryLockByte(flag) ) { + tbb::internal::atomic_backoff b; + do { + b.pause(); + } while ( !__TBB_TryLockByte(flag) ); + } + return 0; +} +#endif + +#ifndef __TBB_UnlockByte +#define __TBB_UnlockByte __TBB_store_with_release +#endif + +#ifndef __TBB_ReverseByte +inline unsigned char __TBB_ReverseByte(unsigned char src) { + return tbb::internal::reverse::byte_table[src]; +} +#endif + +template +T __TBB_ReverseBits(T src) { + T dst; + unsigned char *original = (unsigned char *) &src; + unsigned char *reversed = (unsigned char *) &dst; + + for( int i = sizeof(T)-1; i >= 0; i-- ) + reversed[i] = __TBB_ReverseByte( original[sizeof(T)-i-1] ); + + return dst; +} + +#endif /* __TBB_machine_H */ diff --git a/src/tbb/include/tbb/tbb_profiling.h b/src/tbb/include/tbb/tbb_profiling.h new file mode 100644 index 0000000..23c7292 --- /dev/null +++ b/src/tbb/include/tbb/tbb_profiling.h @@ -0,0 +1,205 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_profiling_H +#define __TBB_profiling_H + +// Check if the tools support is enabled +#if (_WIN32||_WIN64||__linux__) && !__MINGW32__ && TBB_USE_THREADING_TOOLS + +#if _WIN32||_WIN64 +#include /* mbstowcs_s */ +#endif +#include "tbb_stddef.h" + +namespace tbb { + namespace internal { +#if _WIN32||_WIN64 + void __TBB_EXPORTED_FUNC itt_set_sync_name_v3( void *obj, const wchar_t* name ); + inline size_t multibyte_to_widechar( wchar_t* wcs, const char* mbs, size_t bufsize) { +#if _MSC_VER>=1400 + size_t len; + mbstowcs_s( &len, wcs, bufsize, mbs, _TRUNCATE ); + return len; // mbstowcs_s counts null terminator +#else + size_t len = mbstowcs( wcs, mbs, bufsize ); + if(wcs && len!=size_t(-1) ) + wcs[len + inline void itt_store_word_with_release(tbb::atomic& dst, U src) { +#if TBB_USE_THREADING_TOOLS + // This assertion should be replaced with static_assert + __TBB_ASSERT(sizeof(T) == sizeof(void *), "Type must be word-sized."); + itt_store_pointer_with_release_v3(&dst, (void *)uintptr_t(src)); +#else + dst = src; +#endif // TBB_USE_THREADING_TOOLS + } + + template + inline T itt_load_word_with_acquire(const tbb::atomic& src) { +#if TBB_USE_THREADING_TOOLS + // This assertion should be replaced with static_assert + __TBB_ASSERT(sizeof(T) == sizeof(void *), "Type must be word-sized."); +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) + // Workaround for overzealous compiler warnings + #pragma warning (push) + #pragma warning (disable: 4311) +#endif + T result = (T)itt_load_pointer_with_acquire_v3(&src); +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) + #pragma warning (pop) +#endif + return result; +#else + return src; +#endif // TBB_USE_THREADING_TOOLS + } + + template + inline void itt_store_word_with_release(T& dst, T src) { +#if TBB_USE_THREADING_TOOLS + // This assertion should be replaced with static_assert + __TBB_ASSERT(sizeof(T) == sizeof(void *), "Type must be word-sized."); + itt_store_pointer_with_release_v3(&dst, (void *)src); +#else + __TBB_store_with_release(dst, src); +#endif // TBB_USE_THREADING_TOOLS + } + + template + inline T itt_load_word_with_acquire(const T& src) { +#if TBB_USE_THREADING_TOOLS + // This assertion should be replaced with static_assert + __TBB_ASSERT(sizeof(T) == sizeof(void *), "Type must be word-sized"); + return (T)itt_load_pointer_with_acquire_v3(&src); +#else + return __TBB_load_with_acquire(src); +#endif // TBB_USE_THREADING_TOOLS + } + + template + inline void itt_hide_store_word(T& dst, T src) { +#if TBB_USE_THREADING_TOOLS + // This assertion should be replaced with static_assert + __TBB_ASSERT(sizeof(T) == sizeof(void *), "Type must be word-sized"); + itt_store_pointer_with_release_v3(&dst, (void *)src); +#else + dst = src; +#endif + } + + template + inline T itt_hide_load_word(const T& src) { +#if TBB_USE_THREADING_TOOLS + // This assertion should be replaced with static_assert + __TBB_ASSERT(sizeof(T) == sizeof(void *), "Type must be word-sized."); + return (T)itt_load_pointer_v3(&src); +#else + return src; +#endif + } + +#if TBB_USE_THREADING_TOOLS + inline void call_itt_notify(notify_type t, void *ptr) { + call_itt_notify_v5((int)t, ptr); + } +#else + inline void call_itt_notify(notify_type /*t*/, void * /*ptr*/) {} +#endif // TBB_USE_THREADING_TOOLS + + } // namespace internal +} // namespace tbb + +#endif /* __TBB_profiling_H */ diff --git a/src/tbb/include/tbb/tbb_stddef.h b/src/tbb/include/tbb/tbb_stddef.h new file mode 100644 index 0000000..5f527b7 --- /dev/null +++ b/src/tbb/include/tbb/tbb_stddef.h @@ -0,0 +1,396 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_tbb_stddef_H +#define __TBB_tbb_stddef_H + +// Marketing-driven product version +#define TBB_VERSION_MAJOR 4 +#define TBB_VERSION_MINOR 0 + +// Engineering-focused interface version +#define TBB_INTERFACE_VERSION 6005 +#define TBB_INTERFACE_VERSION_MAJOR TBB_INTERFACE_VERSION/1000 + +// The oldest major interface version still supported +// To be used in SONAME, manifests, etc. +#define TBB_COMPATIBLE_INTERFACE_VERSION 2 + +#define __TBB_STRING_AUX(x) #x +#define __TBB_STRING(x) __TBB_STRING_AUX(x) + +// We do not need defines below for resource processing on windows +#if !defined RC_INVOKED + +// Define groups for Doxygen documentation +/** + * @defgroup algorithms Algorithms + * @defgroup containers Containers + * @defgroup memory_allocation Memory Allocation + * @defgroup synchronization Synchronization + * @defgroup timing Timing + * @defgroup task_scheduling Task Scheduling + */ + +// Simple text that is displayed on the main page of Doxygen documentation. +/** + * \mainpage Main Page + * + * Click the tabs above for information about the + * - Modules (groups of functionality) implemented by the library + * - Classes provided by the library + * - Files constituting the library. + * . + * Please note that significant part of TBB functionality is implemented in the form of + * template functions, descriptions of which are not accessible on the Classes + * tab. Use Modules or Namespace/Namespace Members + * tabs to find them. + * + * Additional pieces of information can be found here + * - \subpage concepts + * . + */ + +/** \page concepts TBB concepts + + A concept is a set of requirements to a type, which are necessary and sufficient + for the type to model a particular behavior or a set of behaviors. Some concepts + are specific to a particular algorithm (e.g. algorithm body), while other ones + are common to several algorithms (e.g. range concept). + + All TBB algorithms make use of different classes implementing various concepts. + Implementation classes are supplied by the user as type arguments of template + parameters and/or as objects passed as function call arguments. The library + provides predefined implementations of some concepts (e.g. several kinds of + \ref range_req "ranges"), while other ones must always be implemented by the user. + + TBB defines a set of minimal requirements each concept must conform to. Here is + the list of different concepts hyperlinked to the corresponding requirements specifications: + - \subpage range_req + - \subpage parallel_do_body_req + - \subpage parallel_for_body_req + - \subpage parallel_reduce_body_req + - \subpage parallel_scan_body_req + - \subpage parallel_sort_iter_req +**/ + +// Define preprocessor symbols used to determine architecture +#if _WIN32||_WIN64 +# if defined(_M_X64)||defined(__x86_64__) // the latter for MinGW support +# define __TBB_x86_64 1 +# elif defined(_M_IA64) +# define __TBB_ipf 1 +# elif defined(_M_IX86)||defined(__i386__) // the latter for MinGW support +# define __TBB_x86_32 1 +# endif +#else /* Assume generic Unix */ +# if !__linux__ && !__APPLE__ +# define __TBB_generic_os 1 +# endif +# if __x86_64__ +# define __TBB_x86_64 1 +# elif __ia64__ +# define __TBB_ipf 1 +# elif __i386__||__i386 // __i386 is for Sun OS +# define __TBB_x86_32 1 +# else +# define __TBB_generic_arch 1 +# endif +#endif + +// tbb_config.h should be included the first since it contains macro definitions used in other headers +#include "tbb_config.h" + +#if _MSC_VER >=1400 + #define __TBB_EXPORTED_FUNC __cdecl + #define __TBB_EXPORTED_METHOD __thiscall +#else + #define __TBB_EXPORTED_FUNC + #define __TBB_EXPORTED_METHOD +#endif + +#if __INTEL_COMPILER || _MSC_VER +#define __TBB_NOINLINE(decl) __declspec(noinline) decl +#elif __GNUC__ +#define __TBB_NOINLINE(decl) decl __attribute__ ((noinline)) +#else +#define __TBB_NOINLINE(decl) decl +#endif + +#include /* Need size_t and ptrdiff_t */ + +#if _MSC_VER + #define __TBB_tbb_windef_H + #include "internal/_tbb_windef.h" + #undef __TBB_tbb_windef_H +#endif +#if !defined(_MSC_VER) || _MSC_VER>=1600 + #include +#endif + +//! Type for an assertion handler +typedef void(*assertion_handler_type)( const char* filename, int line, const char* expression, const char * comment ); + +#if TBB_USE_ASSERT + + #define __TBB_ASSERT_NS(predicate,message,ns) ((predicate)?((void)0) : ns::assertion_failure(__FILE__,__LINE__,#predicate,message)) + //! Assert that x is true. + /** If x is false, print assertion failure message. + If the comment argument is not NULL, it is printed as part of the failure message. + The comment argument has no other effect. */ +#if __TBBMALLOC_BUILD +namespace rml { namespace internal { + #define __TBB_ASSERT(predicate,message) __TBB_ASSERT_NS(predicate,message,rml::internal) +#else +namespace tbb { + #define __TBB_ASSERT(predicate,message) __TBB_ASSERT_NS(predicate,message,tbb) +#endif + + #define __TBB_ASSERT_EX __TBB_ASSERT + + //! Set assertion handler and return previous value of it. + assertion_handler_type __TBB_EXPORTED_FUNC set_assertion_handler( assertion_handler_type new_handler ); + + //! Process an assertion failure. + /** Normally called from __TBB_ASSERT macro. + If assertion handler is null, print message for assertion failure and abort. + Otherwise call the assertion handler. */ + void __TBB_EXPORTED_FUNC assertion_failure( const char* filename, int line, const char* expression, const char* comment ); + +#if __TBBMALLOC_BUILD +}} // namespace rml::internal +#else +} // namespace tbb +#endif +#else /* !TBB_USE_ASSERT */ + + //! No-op version of __TBB_ASSERT. + #define __TBB_ASSERT(predicate,comment) ((void)0) + //! "Extended" version is useful to suppress warnings if a variable is only used with an assert + #define __TBB_ASSERT_EX(predicate,comment) ((void)(1 && (predicate))) + +#endif /* !TBB_USE_ASSERT */ + +//! The namespace tbb contains all components of the library. +namespace tbb { + +#if _MSC_VER && _MSC_VER<1600 + namespace internal { + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + } // namespace internal +#else /* Posix */ + namespace internal { + using ::int8_t; + using ::int16_t; + using ::int32_t; + using ::int64_t; + using ::uint8_t; + using ::uint16_t; + using ::uint32_t; + using ::uint64_t; + } // namespace internal +#endif /* Posix */ + + using std::size_t; + using std::ptrdiff_t; + +//! The function returns the interface version of the TBB shared library being used. +/** + * The version it returns is determined at runtime, not at compile/link time. + * So it can be different than the value of TBB_INTERFACE_VERSION obtained at compile time. + */ +extern "C" int __TBB_EXPORTED_FUNC TBB_runtime_interface_version(); + +//! Dummy type that distinguishes splitting constructor from copy constructor. +/** + * See description of parallel_for and parallel_reduce for example usages. + * @ingroup algorithms + */ +class split { +}; + +/** + * @cond INTERNAL + * @brief Identifiers declared inside namespace internal should never be used directly by client code. + */ +namespace internal { + +//! Compile-time constant that is upper bound on cache line/sector size. +/** It should be used only in situations where having a compile-time upper + bound is more useful than a run-time exact answer. + @ingroup memory_allocation */ +const size_t NFS_MaxLineSize = 128; + +/** Label for data that may be accessed from different threads, and that may eventually become wrapped + in a formal atomic type. + + Note that no problems have yet been observed relating to the definition currently being empty, + even if at least "volatile" would seem to be in order to avoid data sometimes temporarily hiding + in a register (although "volatile" as a "poor man's atomic" lacks several other features of a proper + atomic, some of which are now provided instead through specialized functions). + + Note that usage is intentionally compatible with a definition as qualifier "volatile", + both as a way to have the compiler help enforce use of the label and to quickly rule out + one potential issue. + + Note however that, with some architecture/compiler combinations, e.g. on IA-64, "volatile" + also has non-portable memory semantics that are needlessly expensive for "relaxed" operations. + + Note that this must only be applied to data that will not change bit patterns when cast to/from + an integral type of the same length; tbb::atomic must be used instead for, e.g., floating-point types. + + TODO: apply wherever relevant **/ +#define __TBB_atomic // intentionally empty, see above + +template +struct padded_base : T { + char pad[NFS_MaxLineSize - sizeof(T) % NFS_MaxLineSize]; +}; +template struct padded_base : T {}; + +//! Pads type T to fill out to a multiple of cache line size. +template +struct padded : padded_base {}; + +//! Extended variant of the standard offsetof macro +/** The standard offsetof macro is not sufficient for TBB as it can be used for + POD-types only. The constant 0x1000 (not NULL) is necessary to appease GCC. **/ +#define __TBB_offsetof(class_name, member_name) \ + ((ptrdiff_t)&(reinterpret_cast(0x1000)->member_name) - 0x1000) + +//! Returns address of the object containing a member with the given name and address +#define __TBB_get_object_ref(class_name, member_name, member_addr) \ + (*reinterpret_cast((char*)member_addr - __TBB_offsetof(class_name, member_name))) + +//! Throws std::runtime_error with what() returning error_code description prefixed with aux_info +void __TBB_EXPORTED_FUNC handle_perror( int error_code, const char* aux_info ); + +#if TBB_USE_EXCEPTIONS + #define __TBB_TRY try + #define __TBB_CATCH(e) catch(e) + #define __TBB_THROW(e) throw e + #define __TBB_RETHROW() throw +#else /* !TBB_USE_EXCEPTIONS */ + inline bool __TBB_false() { return false; } + #define __TBB_TRY + #define __TBB_CATCH(e) if ( tbb::internal::__TBB_false() ) + #define __TBB_THROW(e) ((void)0) + #define __TBB_RETHROW() ((void)0) +#endif /* !TBB_USE_EXCEPTIONS */ + +//! Report a runtime warning. +void __TBB_EXPORTED_FUNC runtime_warning( const char* format, ... ); + +#if TBB_USE_ASSERT +static void* const poisoned_ptr = reinterpret_cast(-1); + +//! Set p to invalid pointer value. +template +inline void poison_pointer( T*& p ) { p = reinterpret_cast(poisoned_ptr); } + +/** Expected to be used in assertions only, thus no empty form is defined. **/ +template +inline bool is_poisoned( T* p ) { return p == reinterpret_cast(poisoned_ptr); } +#else +template +inline void poison_pointer( T* ) {/*do nothing*/} +#endif /* !TBB_USE_ASSERT */ + +//! Cast pointer from U* to T. +/** This method should be used sparingly as a last resort for dealing with + situations that inherently break strict ISO C++ aliasing rules. */ +template +inline T punned_cast( U* ptr ) { + uintptr_t x = reinterpret_cast(ptr); + return reinterpret_cast(x); +} + +//! Base class for types that should not be assigned. +class no_assign { + // Deny assignment + void operator=( const no_assign& ); +public: +#if __GNUC__ + //! Explicitly define default construction, because otherwise gcc issues gratuitous warning. + no_assign() {} +#endif /* __GNUC__ */ +}; + +//! Base class for types that should not be copied or assigned. +class no_copy: no_assign { + //! Deny copy construction + no_copy( const no_copy& ); +public: + //! Allow default construction + no_copy() {} +}; + +//! Class for determining type of std::allocator::value_type. +template +struct allocator_type { + typedef T value_type; +}; + +#if _MSC_VER +//! Microsoft std::allocator has non-standard extension that strips const from a type. +template +struct allocator_type { + typedef T value_type; +}; +#endif + +//! A function to select either 32-bit or 64-bit value, depending on machine word size. +inline size_t size_t_select( unsigned u, unsigned long long ull ) { + /* Explicit cast of the arguments to size_t is done to avoid compiler warnings + (e.g. by Clang and MSVC) about possible truncation. The value of the right size, + which is selected by ?:, is anyway not truncated or promoted. + MSVC still warns if this trick is applied directly to constants, hence this function. */ + return (sizeof(size_t)==sizeof(u)) ? size_t(u) : size_t(ull); +} + +// Struct to be used as a version tag for inline functions. +/** Version tag can be necessary to prevent loader on Linux from using the wrong + symbol in debug builds (when inline functions are compiled as out-of-line). **/ +struct version_tag_v3 {}; + +typedef version_tag_v3 version_tag; + +} // internal +//! @endcond + +} // tbb + +#endif /* RC_INVOKED */ +#endif /* __TBB_tbb_stddef_H */ diff --git a/src/tbb/include/tbb/tbb_thread.h b/src/tbb/include/tbb/tbb_thread.h new file mode 100644 index 0000000..1edaa2e --- /dev/null +++ b/src/tbb/include/tbb/tbb_thread.h @@ -0,0 +1,302 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_tbb_thread_H +#define __TBB_tbb_thread_H + +#if _WIN32||_WIN64 +#include "machine/windows_api.h" +#define __TBB_NATIVE_THREAD_ROUTINE unsigned WINAPI +#define __TBB_NATIVE_THREAD_ROUTINE_PTR(r) unsigned (WINAPI* r)( void* ) +#else +#define __TBB_NATIVE_THREAD_ROUTINE void* +#define __TBB_NATIVE_THREAD_ROUTINE_PTR(r) void* (*r)( void* ) +#include +#endif // _WIN32||_WIN64 + +#include "tbb_stddef.h" +#include "tick_count.h" + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +namespace tbb { + +//! @cond INTERNAL +namespace internal { + + class tbb_thread_v3; + +} // namespace internal + +inline void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 ); + +namespace internal { + + //! Allocate a closure + void* __TBB_EXPORTED_FUNC allocate_closure_v3( size_t size ); + //! Free a closure allocated by allocate_closure_v3 + void __TBB_EXPORTED_FUNC free_closure_v3( void* ); + + struct thread_closure_base { + void* operator new( size_t size ) {return allocate_closure_v3(size);} + void operator delete( void* ptr ) {free_closure_v3(ptr);} + }; + + template struct thread_closure_0: thread_closure_base { + F function; + + static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) { + thread_closure_0 *self = static_cast(c); + self->function(); + delete self; + return 0; + } + thread_closure_0( const F& f ) : function(f) {} + }; + //! Structure used to pass user function with 1 argument to thread. + template struct thread_closure_1: thread_closure_base { + F function; + X arg1; + //! Routine passed to Windows's _beginthreadex by thread::internal_start() inside tbb.dll + static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) { + thread_closure_1 *self = static_cast(c); + self->function(self->arg1); + delete self; + return 0; + } + thread_closure_1( const F& f, const X& x ) : function(f), arg1(x) {} + }; + template struct thread_closure_2: thread_closure_base { + F function; + X arg1; + Y arg2; + //! Routine passed to Windows's _beginthreadex by thread::internal_start() inside tbb.dll + static __TBB_NATIVE_THREAD_ROUTINE start_routine( void* c ) { + thread_closure_2 *self = static_cast(c); + self->function(self->arg1, self->arg2); + delete self; + return 0; + } + thread_closure_2( const F& f, const X& x, const Y& y ) : function(f), arg1(x), arg2(y) {} + }; + + //! Versioned thread class. + class tbb_thread_v3 { + tbb_thread_v3(const tbb_thread_v3&); // = delete; // Deny access + public: +#if _WIN32||_WIN64 + typedef HANDLE native_handle_type; +#else + typedef pthread_t native_handle_type; +#endif // _WIN32||_WIN64 + + class id; + //! Constructs a thread object that does not represent a thread of execution. + tbb_thread_v3() : my_handle(0) +#if _WIN32||_WIN64 + , my_thread_id(0) +#endif // _WIN32||_WIN64 + {} + + //! Constructs an object and executes f() in a new thread + template explicit tbb_thread_v3(F f) { + typedef internal::thread_closure_0 closure_type; + internal_start(closure_type::start_routine, new closure_type(f)); + } + //! Constructs an object and executes f(x) in a new thread + template tbb_thread_v3(F f, X x) { + typedef internal::thread_closure_1 closure_type; + internal_start(closure_type::start_routine, new closure_type(f,x)); + } + //! Constructs an object and executes f(x,y) in a new thread + template tbb_thread_v3(F f, X x, Y y) { + typedef internal::thread_closure_2 closure_type; + internal_start(closure_type::start_routine, new closure_type(f,x,y)); + } + + tbb_thread_v3& operator=(tbb_thread_v3& x) { + if (joinable()) detach(); + my_handle = x.my_handle; + x.my_handle = 0; +#if _WIN32||_WIN64 + my_thread_id = x.my_thread_id; + x.my_thread_id = 0; +#endif // _WIN32||_WIN64 + return *this; + } + void swap( tbb_thread_v3& t ) {tbb::swap( *this, t );} + bool joinable() const {return my_handle!=0; } + //! The completion of the thread represented by *this happens before join() returns. + void __TBB_EXPORTED_METHOD join(); + //! When detach() returns, *this no longer represents the possibly continuing thread of execution. + void __TBB_EXPORTED_METHOD detach(); + ~tbb_thread_v3() {if( joinable() ) detach();} + inline id get_id() const; + native_handle_type native_handle() { return my_handle; } + + //! The number of hardware thread contexts. + /** Before TBB 3.0 U4 this methods returned the number of logical CPU in + the system. Currently on Windows, Linux and FreeBSD it returns the + number of logical CPUs available to the current process in accordance + with its affinity mask. + + NOTE: The return value of this method never changes after its first + invocation. This means that changes in the process affinity mask that + took place after this method was first invoked will not affect the + number of worker threads in the TBB worker threads pool. **/ + static unsigned __TBB_EXPORTED_FUNC hardware_concurrency(); + private: + native_handle_type my_handle; +#if _WIN32||_WIN64 + DWORD my_thread_id; +#endif // _WIN32||_WIN64 + + /** Runs start_routine(closure) on another thread and sets my_handle to the handle of the created thread. */ + void __TBB_EXPORTED_METHOD internal_start( __TBB_NATIVE_THREAD_ROUTINE_PTR(start_routine), + void* closure ); + friend void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 ); + friend void tbb::swap( tbb_thread_v3& t1, tbb_thread_v3& t2 ); + }; + + class tbb_thread_v3::id { +#if _WIN32||_WIN64 + DWORD my_id; + id( DWORD id_ ) : my_id(id_) {} +#else + pthread_t my_id; + id( pthread_t id_ ) : my_id(id_) {} +#endif // _WIN32||_WIN64 + friend class tbb_thread_v3; + public: + id() : my_id(0) {} + + friend bool operator==( tbb_thread_v3::id x, tbb_thread_v3::id y ); + friend bool operator!=( tbb_thread_v3::id x, tbb_thread_v3::id y ); + friend bool operator<( tbb_thread_v3::id x, tbb_thread_v3::id y ); + friend bool operator<=( tbb_thread_v3::id x, tbb_thread_v3::id y ); + friend bool operator>( tbb_thread_v3::id x, tbb_thread_v3::id y ); + friend bool operator>=( tbb_thread_v3::id x, tbb_thread_v3::id y ); + + template + friend std::basic_ostream& + operator<< (std::basic_ostream &out, + tbb_thread_v3::id id) + { + out << id.my_id; + return out; + } + friend tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3(); + }; // tbb_thread_v3::id + + tbb_thread_v3::id tbb_thread_v3::get_id() const { +#if _WIN32||_WIN64 + return id(my_thread_id); +#else + return id(my_handle); +#endif // _WIN32||_WIN64 + } + void __TBB_EXPORTED_FUNC move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 ); + tbb_thread_v3::id __TBB_EXPORTED_FUNC thread_get_id_v3(); + void __TBB_EXPORTED_FUNC thread_yield_v3(); + void __TBB_EXPORTED_FUNC thread_sleep_v3(const tick_count::interval_t &i); + + inline bool operator==(tbb_thread_v3::id x, tbb_thread_v3::id y) + { + return x.my_id == y.my_id; + } + inline bool operator!=(tbb_thread_v3::id x, tbb_thread_v3::id y) + { + return x.my_id != y.my_id; + } + inline bool operator<(tbb_thread_v3::id x, tbb_thread_v3::id y) + { + return x.my_id < y.my_id; + } + inline bool operator<=(tbb_thread_v3::id x, tbb_thread_v3::id y) + { + return x.my_id <= y.my_id; + } + inline bool operator>(tbb_thread_v3::id x, tbb_thread_v3::id y) + { + return x.my_id > y.my_id; + } + inline bool operator>=(tbb_thread_v3::id x, tbb_thread_v3::id y) + { + return x.my_id >= y.my_id; + } + +} // namespace internal; + +//! Users reference thread class by name tbb_thread +typedef internal::tbb_thread_v3 tbb_thread; + +using internal::operator==; +using internal::operator!=; +using internal::operator<; +using internal::operator>; +using internal::operator<=; +using internal::operator>=; + +inline void move( tbb_thread& t1, tbb_thread& t2 ) { + internal::move_v3(t1, t2); +} + +inline void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 ) { + tbb::tbb_thread::native_handle_type h = t1.my_handle; + t1.my_handle = t2.my_handle; + t2.my_handle = h; +#if _WIN32||_WIN64 + DWORD i = t1.my_thread_id; + t1.my_thread_id = t2.my_thread_id; + t2.my_thread_id = i; +#endif /* _WIN32||_WIN64 */ +} + +namespace this_tbb_thread { + inline tbb_thread::id get_id() { return internal::thread_get_id_v3(); } + //! Offers the operating system the opportunity to schedule another thread. + inline void yield() { internal::thread_yield_v3(); } + //! The current thread blocks at least until the time specified. + inline void sleep(const tick_count::interval_t &i) { + internal::thread_sleep_v3(i); + } +} // namespace this_tbb_thread + +} // namespace tbb + +#endif /* __TBB_tbb_thread_H */ diff --git a/src/tbb/include/tbb/tbbmalloc_proxy.h b/src/tbb/include/tbb/tbbmalloc_proxy.h new file mode 100644 index 0000000..181144f --- /dev/null +++ b/src/tbb/include/tbb/tbbmalloc_proxy.h @@ -0,0 +1,74 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* +Replacing the standard memory allocation routines in Microsoft* C/C++ RTL +(malloc/free, global new/delete, etc.) with the TBB memory allocator. + +Include the following header to a source of any binary which is loaded during +application startup + +#include "tbb/tbbmalloc_proxy.h" + +or add following parameters to the linker options for the binary which is +loaded during application startup. It can be either exe-file or dll. + +For win32 +tbbmalloc_proxy.lib /INCLUDE:"___TBB_malloc_proxy" +win64 +tbbmalloc_proxy.lib /INCLUDE:"__TBB_malloc_proxy" +*/ + +#ifndef __TBB_tbbmalloc_proxy_H +#define __TBB_tbbmalloc_proxy_H + +#if _MSC_VER + +#ifdef _DEBUG + #pragma comment(lib, "tbbmalloc_proxy_debug.lib") +#else + #pragma comment(lib, "tbbmalloc_proxy.lib") +#endif + +#if defined(_WIN64) + #pragma comment(linker, "/include:__TBB_malloc_proxy") +#else + #pragma comment(linker, "/include:___TBB_malloc_proxy") +#endif + +#else +/* Primarily to support MinGW */ + +extern "C" void __TBB_malloc_proxy(); +struct __TBB_malloc_proxy_caller { + __TBB_malloc_proxy_caller() { __TBB_malloc_proxy(); } +} volatile __TBB_malloc_proxy_helper_object; + +#endif // _MSC_VER + +#endif //__TBB_tbbmalloc_proxy_H diff --git a/src/tbb/include/tbb/tick_count.h b/src/tbb/include/tbb/tick_count.h new file mode 100644 index 0000000..4c56e4e --- /dev/null +++ b/src/tbb/include/tbb/tick_count.h @@ -0,0 +1,155 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_tick_count_H +#define __TBB_tick_count_H + +#include "tbb_stddef.h" + +#if _WIN32||_WIN64 +#include "machine/windows_api.h" +#elif __linux__ +#include +#else /* generic Unix */ +#include +#endif /* (choice of OS) */ + +namespace tbb { + +//! Absolute timestamp +/** @ingroup timing */ +class tick_count { +public: + //! Relative time interval. + class interval_t { + long long value; + explicit interval_t( long long value_ ) : value(value_) {} + public: + //! Construct a time interval representing zero time duration + interval_t() : value(0) {}; + + //! Construct a time interval representing sec seconds time duration + explicit interval_t( double sec ); + + //! Return the length of a time interval in seconds + double seconds() const; + + friend class tbb::tick_count; + + //! Extract the intervals from the tick_counts and subtract them. + friend interval_t operator-( const tick_count& t1, const tick_count& t0 ); + + //! Add two intervals. + friend interval_t operator+( const interval_t& i, const interval_t& j ) { + return interval_t(i.value+j.value); + } + + //! Subtract two intervals. + friend interval_t operator-( const interval_t& i, const interval_t& j ) { + return interval_t(i.value-j.value); + } + + //! Accumulation operator + interval_t& operator+=( const interval_t& i ) {value += i.value; return *this;} + + //! Subtraction operator + interval_t& operator-=( const interval_t& i ) {value -= i.value; return *this;} + }; + + //! Construct an absolute timestamp initialized to zero. + tick_count() : my_count(0) {}; + + //! Return current time. + static tick_count now(); + + //! Subtract two timestamps to get the time interval between + friend interval_t operator-( const tick_count& t1, const tick_count& t0 ); + +private: + long long my_count; +}; + +inline tick_count tick_count::now() { + tick_count result; +#if _WIN32||_WIN64 + LARGE_INTEGER qpcnt; + QueryPerformanceCounter(&qpcnt); + result.my_count = qpcnt.QuadPart; +#elif __linux__ + struct timespec ts; +#if TBB_USE_ASSERT + int status = +#endif /* TBB_USE_ASSERT */ + clock_gettime( CLOCK_REALTIME, &ts ); + __TBB_ASSERT( status==0, "CLOCK_REALTIME not supported" ); + result.my_count = static_cast(1000000000UL)*static_cast(ts.tv_sec) + static_cast(ts.tv_nsec); +#else /* generic Unix */ + struct timeval tv; +#if TBB_USE_ASSERT + int status = +#endif /* TBB_USE_ASSERT */ + gettimeofday(&tv, NULL); + __TBB_ASSERT( status==0, "gettimeofday failed" ); + result.my_count = static_cast(1000000)*static_cast(tv.tv_sec) + static_cast(tv.tv_usec); +#endif /*(choice of OS) */ + return result; +} + +inline tick_count::interval_t::interval_t( double sec ) +{ +#if _WIN32||_WIN64 + LARGE_INTEGER qpfreq; + QueryPerformanceFrequency(&qpfreq); + value = static_cast(sec*qpfreq.QuadPart); +#elif __linux__ + value = static_cast(sec*1E9); +#else /* generic Unix */ + value = static_cast(sec*1E6); +#endif /* (choice of OS) */ +} + +inline tick_count::interval_t operator-( const tick_count& t1, const tick_count& t0 ) { + return tick_count::interval_t( t1.my_count-t0.my_count ); +} + +inline double tick_count::interval_t::seconds() const { +#if _WIN32||_WIN64 + LARGE_INTEGER qpfreq; + QueryPerformanceFrequency(&qpfreq); + return value/(double)qpfreq.QuadPart; +#elif __linux__ + return value*1E-9; +#else /* generic Unix */ + return value*1E-6; +#endif /* (choice of OS) */ +} + +} // namespace tbb + +#endif /* __TBB_tick_count_H */ + diff --git a/src/tbb/index.html b/src/tbb/index.html new file mode 100644 index 0000000..7abe0f4 --- /dev/null +++ b/src/tbb/index.html @@ -0,0 +1,43 @@ + + + +

    Overview

    +Top level directory for Intel® Threading Building Blocks (Intel® TBB). +

    +To build Intel TBB, use the top-level Makefile; see also the build directions. +To port Intel TBB to a new platform, operating system or architecture, see the porting directions. +

    + +

    Files

    +
    +
    Makefile +
    Top-level Makefile for Intel TBB. See also the build directions. +
    + +

    Directories

    +
    +
    doc +
    Documentation for the library. +
    include +
    Include files required for compiling code that uses the library. +
    examples +
    Examples of how to use the library. +
    src +
    Source code for the library. +
    build +
    Internal Makefile infrastructure for Intel TBB. Do not use directly; see the build directions. +
    ia32, intel64, ia64 +
    Platform-specific binary files for the library. +
    + +
    +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + + diff --git a/src/tbb/src/Makefile b/src/tbb/src/Makefile new file mode 100644 index 0000000..74546b6 --- /dev/null +++ b/src/tbb/src/Makefile @@ -0,0 +1,228 @@ +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +tbb_root?=.. +examples_root:=$(tbb_root)/examples +include $(tbb_root)/build/common.inc + +.PHONY: all tbb tbbmalloc tbbproxy test test_no_depends release debug examples clean + +all: release debug examples + +tbb: tbb_release tbb_debug + +tbbmalloc: tbbmalloc_release tbbmalloc_debug + +tbbproxy: tbbproxy_release tbbproxy_debug + +rml: rml_release rml_debug + +test: tbbmalloc_test_release $(if $(use_proxy),tbbproxy_test_release) rml_test_release test_release tbbmalloc_test_debug $(if $(use_proxy),tbbproxy_test_debug) rml_test_debug test_debug + +test_no_depends: tbbmalloc_test_release_no_depends $(if $(use_proxy),tbbproxy_test_release_no_depends) test_release_no_depends tbbmalloc_test_debug_no_depends $(if $(use_proxy),tbbproxy_test_debug_no_depends) test_debug_no_depends + @echo done + +release: tbb_release tbbmalloc_release $(if $(use_proxy),tbbproxy_release) +release: $(call cross_cfg,tbbmalloc_test_release) $(call cross_cfg,test_release) + +debug: tbb_debug tbbmalloc_debug $(if $(use_proxy),tbbproxy_debug) +debug: $(call cross_cfg,tbbmalloc_test_debug) $(call cross_cfg, test_debug) + +examples: tbb tbbmalloc examples_debug clean_examples examples_release + +clean: clean_release clean_debug clean_examples + @echo clean done + +.PHONY: full +full: + $(MAKE) -s -i -r --no-print-directory -f Makefile tbb_root=. clean all +ifeq ($(tbb_os),windows) + $(MAKE) -s -i -r --no-print-directory -f Makefile tbb_root=. compiler=icl clean all native_examples +else + $(MAKE) -s -i -r --no-print-directory -f Makefile tbb_root=. compiler=icc clean all native_examples +endif +ifeq ($(arch),intel64) + $(MAKE) -s -i -r --no-print-directory -f Makefile tbb_root=. arch=ia32 clean all +endif +# it doesn't test compiler=icc arch=ia32 on intel64 systems due to enviroment settings of icc + +native_examples: tbb tbbmalloc + $(MAKE) -C $(examples_root) -r -f Makefile tbb_root=.. compiler=$(native_compiler) tbb_build_prefix=$(tbb_build_prefix) debug test + $(MAKE) -C $(examples_root) -r -f Makefile tbb_root=.. compiler=$(native_compiler) tbb_build_prefix=$(tbb_build_prefix) clean release test + +../examples/% examples/%:: + $(MAKE) -C $(examples_root) -r -f Makefile tbb_root=.. $(subst examples/,,$(subst ../,,$@)) + +debug_%:: cfg?=debug +debug_%:: run_cmd=$(debugger) +test_% stress_% time_% perf_%:: cfg?=release +debug_% test_% stress_% time_% perf_%:: + $(MAKE) -C "$(work_dir)_$(cfg)" -r -f $(tbb_root)/build/Makefile.test cfg=$(cfg) run_cmd="$(run_cmd)" tbb_root=$(tbb_root) $@ + +clean_%:: +ifeq ($(cfg),) + @$(MAKE) -C "$(work_dir)_release" -r -f $(tbb_root)/build/Makefile.test cfg=release tbb_root=$(tbb_root) $@ + @$(MAKE) -C "$(work_dir)_debug" -r -f $(tbb_root)/build/Makefile.test cfg=debug tbb_root=$(tbb_root) $@ +else + @$(MAKE) -C "$(work_dir)_$(cfg)" -r -f $(tbb_root)/build/Makefile.test cfg=$(cfg) tbb_root=$(tbb_root) $@ +endif + +.PHONY: tbb_release tbb_debug test_release test_debug test_release_no_depends test_debug_no_depends + +# do not delete double-space after -C option +tbb_release: mkdir_release + $(MAKE) -C "$(work_dir)_release" -r -f $(tbb_root)/build/Makefile.tbb cfg=release tbb_root=$(tbb_root) + +tbb_debug: mkdir_debug + $(MAKE) -C "$(work_dir)_debug" -r -f $(tbb_root)/build/Makefile.tbb cfg=debug tbb_root=$(tbb_root) + +test_release: $(call cross_cfg,mkdir_release) $(call cross_cfg,tbb_release) $(if $(use_proxy),$(call cross_cfg,tbbproxy_release)) test_release_no_depends +test_release_no_depends: + $(MAKE) -C "$(call cross_cfg,$(work_dir)_release)" -r -f $(tbb_root)/build/Makefile.test cfg=release tbb_root=$(tbb_root) + +test_debug: $(call cross_cfg,mkdir_debug) $(call cross_cfg,tbb_debug) $(if $(use_proxy),$(call cross_cfg,tbbproxy_debug)) test_debug_no_depends +test_debug_no_depends: + $(MAKE) -C "$(call cross_cfg,$(work_dir)_debug)" -r -f $(tbb_root)/build/Makefile.test cfg=debug tbb_root=$(tbb_root) + +.PHONY: tbbmalloc_release tbbmalloc_debug +.PHONY: tbbmalloc_dll_release tbbmalloc_dll_debug tbbmalloc_proxy_dll_release tbbmalloc_proxy_dll_debug +.PHONY: tbbmalloc_test tbbmalloc_test_release tbbmalloc_test_debug tbbmalloc_test_release_no_depends tbbmalloc_test_debug_no_depends + +tbbmalloc_release: mkdir_release + $(MAKE) -C "$(work_dir)_release" -r -f $(tbb_root)/build/Makefile.tbbmalloc cfg=release malloc tbb_root=$(tbb_root) + +tbbmalloc_debug: mkdir_debug + $(MAKE) -C "$(work_dir)_debug" -r -f $(tbb_root)/build/Makefile.tbbmalloc cfg=debug malloc tbb_root=$(tbb_root) + +tbbmalloc_dll_release: mkdir_release + $(MAKE) -C "$(work_dir)_release" -r -f $(tbb_root)/build/Makefile.tbbmalloc cfg=release malloc_dll tbb_root=$(tbb_root) + +tbbmalloc_proxy_dll_release: mkdir_release + $(MAKE) -C "$(work_dir)_release" -r -f $(tbb_root)/build/Makefile.tbbmalloc cfg=release malloc_proxy_dll tbb_root=$(tbb_root) + +tbbmalloc_dll_debug: mkdir_debug + $(MAKE) -C "$(work_dir)_debug" -r -f $(tbb_root)/build/Makefile.tbbmalloc cfg=debug malloc_dll tbb_root=$(tbb_root) + +tbbmalloc_proxy_dll_debug: mkdir_debug + $(MAKE) -C "$(work_dir)_debug" -r -f $(tbb_root)/build/Makefile.tbbmalloc cfg=debug malloc_proxy_dll tbb_root=$(tbb_root) + +tbbmalloc_test: tbbmalloc_test_release tbbmalloc_test_debug + +tbbmalloc_test_release: $(call cross_cfg,mkdir_release) $(call cross_cfg,tbbmalloc_release) tbbmalloc_test_release_no_depends +tbbmalloc_test_release_no_depends: + $(MAKE) -C "$(call cross_cfg,$(work_dir)_release)" -r -f $(tbb_root)/build/Makefile.tbbmalloc cfg=release malloc_test_no_depends tbb_root=$(tbb_root) + +tbbmalloc_test_debug: $(call cross_cfg,mkdir_debug) $(call cross_cfg,tbbmalloc_debug) tbbmalloc_test_debug_no_depends +tbbmalloc_test_debug_no_depends: + $(MAKE) -C "$(call cross_cfg,$(work_dir)_debug)" -r -f $(tbb_root)/build/Makefile.tbbmalloc cfg=debug malloc_test_no_depends tbb_root=$(tbb_root) + +.PHONY: tbbproxy_release tbbproxy_debug +.PHONY: tbbproxy_test tbbproxy_test_release tbbproxy_test_debug tbbproxy_test_release_no_depends tbbproxy_test_debug_no_depends + +tbbproxy_release: mkdir_release tbb_release + $(MAKE) -C "$(work_dir)_release" -r -f $(tbb_root)/build/Makefile.tbbproxy cfg=release tbbproxy tbb_root=$(tbb_root) + +tbbproxy_debug: mkdir_debug tbb_debug + $(MAKE) -C "$(work_dir)_debug" -r -f $(tbb_root)/build/Makefile.tbbproxy cfg=debug tbbproxy tbb_root=$(tbb_root) + +tbbproxy_test: tbbproxy_test_release tbbproxy_test_debug + +tbbproxy_test_release: $(call cross_cfg,mkdir_release) $(call cross_cfg,tbb_release) $(call cross_cfg,tbbproxy_release) tbbproxy_test_release_no_depends +tbbproxy_test_release_no_depends: + $(MAKE) -C "$(call cross_cfg,$(work_dir)_release)" -r -f $(tbb_root)/build/Makefile.tbbproxy cfg=release tbbproxy_test tbb_root=$(tbb_root) + +tbbproxy_test_debug: $(call cross_cfg,mkdir_debug) $(call cross_cfg,tbb_debug) $(call cross_cfg,tbbproxy_debug) tbbproxy_test_debug_no_depends +tbbproxy_test_debug_no_depends: + $(MAKE) -C "$(call cross_cfg,$(work_dir)_debug)" -r -f $(tbb_root)/build/Makefile.tbbproxy cfg=debug tbbproxy_test tbb_root=$(tbb_root) + +.PHONY: rml_release rml_debug rml_test_release rml_test_debug +.PHONY: rml_test_release_no_depends rml_test_debug_no_depends + +rml_release: mkdir_release + $(MAKE) -C "$(work_dir)_release" -r -f $(tbb_root)/build/Makefile.rml cfg=release tbb_root=$(tbb_root) rml + +rml_debug: mkdir_debug + $(MAKE) -C "$(work_dir)_debug" -r -f $(tbb_root)/build/Makefile.rml cfg=debug tbb_root=$(tbb_root) rml + +rml_test_release: $(call cross_cfg,mkdir_release) $(call cross_cfg,rml_release) rml_test_release_no_depends +rml_test_release_no_depends: + $(MAKE) -C "$(call cross_cfg,$(work_dir)_release)" -r -f $(tbb_root)/build/Makefile.rml cfg=release rml_test tbb_root=$(tbb_root) + +rml_test_debug: $(call cross_cfg,mkdir_debug) $(call cross_cfg,rml_debug) rml_test_debug_no_depends +rml_test_debug_no_depends: + $(MAKE) -C "$(call cross_cfg,$(work_dir)_debug)" -r -f $(tbb_root)/build/Makefile.rml cfg=debug rml_test tbb_root=$(tbb_root) + +.PHONY: examples_release examples_debug + +examples_release: tbb_release tbbmalloc_release + $(MAKE) -C $(examples_root) -r -f Makefile tbb_root=.. release test + +examples_debug: tbb_debug tbbmalloc_debug + $(MAKE) -C $(examples_root) -r -f Makefile tbb_root=.. debug test + +.PHONY: clean_release clean_debug clean_examples + +clean_release: + $(shell $(RM) $(work_dir)_release$(SLASH)*.* >$(NUL) 2>$(NUL)) + $(shell $(RD) $(work_dir)_release >$(NUL) 2>$(NUL)) + +clean_debug: + $(shell $(RM) $(work_dir)_debug$(SLASH)*.* >$(NUL) 2>$(NUL)) + $(shell $(RD) $(work_dir)_debug >$(NUL) 2>$(NUL)) + +clean_examples: + $(shell $(MAKE) -s -i -r -C $(examples_root) -f Makefile tbb_root=.. clean >$(NUL) 2>$(NUL)) + +.PHONY: mkdir_release mkdir_debug codecov do_codecov info + +mkdir_release: + $(shell $(MD) "$(work_dir)_release" >$(NUL) 2>$(NUL)) + @echo Created $(work_dir)_release directory + +mkdir_debug: + $(shell $(MD) "$(work_dir)_debug" >$(NUL) 2>$(NUL)) + @echo Created $(work_dir)_debug directory + +codecov: compiler=$(if $(findstring windows,$(tbb_os)),icl,icc) +codecov: + $(MAKE) tbb_root=.. codecov=yes do_codecov + +do_codecov: + $(MAKE) RML=yes tbbmalloc_test_release test_release + $(MAKE) clean_test_* cfg=release + $(MAKE) RML=yes crosstest=yes tbbmalloc_test_debug test_debug + $(MAKE) clean_test_* cfg=release + $(MAKE) rml_test_release + $(MAKE) clean_test_* cfg=release + $(MAKE) crosstest=yes rml_test_debug + $(MAKE) -C "$(work_dir)_release" -r -f $(tbb_root)/build/Makefile.test tbb_root=$(tbb_root) cfg=release codecov=yes codecov_gen + +info: + @echo OS: $(tbb_os) + @echo arch=$(arch) + @echo compiler=$(compiler) + @echo runtime=$(runtime) + @echo tbb_build_prefix=$(tbb_build_prefix) diff --git a/src/tbb/src/index.html b/src/tbb/src/index.html new file mode 100644 index 0000000..cf2a66a --- /dev/null +++ b/src/tbb/src/index.html @@ -0,0 +1,76 @@ + + + +

    Overview

    +This directory contains the source code and unit tests for Threading Building Blocks. + +

    Directories

    +
    +
    tbb +
    Source code of the TBB library core. +
    tbbmalloc +
    Source code of the TBB scalable memory allocator. +
    test +
    Source code of the TBB unit tests. +
    rml +
    Source code of the Resource Management Layer (RML). +
    perf +
    Source code of microbenchmarks. +
    old +
    Source code of deprecated TBB entities that are still shipped as part of the TBB library for the sake of backward compatibility. +
    + +

    Files

    +
    +
    Makefile +
    Advanced Makefile for developing and debugging of TBB. See the basic build directions. Additional targets and options: +
    +
    make test_{name} time_{name} +
    Make and run individual test or benchmark.
    +
    make stress_{name} +
    Equivalent to 'make test_{name}' but runs until a failure detected or terminated by user.
    +
    make run_cmd="{command}" [(above options or targets)] +
    Command prefix for tests execution. Also, "run_cmd=-" will ignore test execution failures. See also -k and -i options of the GNU make for more options to keep building and testing despite of failures.
    +
    make debug_{name} +
    Equivalent to 'make test_{name}' but compiles in debug mode and runs under debugger ("run_cmd=$(debugger)").
    +
    make args="{command-line arguments}" [(above options or targets)] +
    Additional arguments for the run.
    +
    make repeat="{N}" [(above options or targets)] +
    Repeats execution N times.
    +
    make clean_{filename} +
    Removes executable, object, and other intermediate files with specified filename ('*' also works).
    +
    make cfg={debug|release} [(above options or targets)] +
    Specifies a build mode or corresponding directory to work in.
    +
    make tbb_strict=1 [(above options or targets)] +
    Enables warnings as errors.
    +
    make examples/{target} +
    Invokes examples/Makefile with specified target.
    +
    make clean_release clean_debug clean_examples +
    Removes release or debug build directories, or cleans all examples.
    +
    make test_no_depends +
    Equivalent to 'make test' but does not check for libraries updates.
    +
    make info +
    Output information about build configuration and directories.
    +
    make cpp0x=1 [(above options or targets)] +
    Enables C++0x extensions like lambdas for compilers that implement them as experimental features.
    +
    make CXXFLAGS={Flags} [(above options or targets)] +
    Specifies additional options for compiler.
    +
    make target={name} [(above options or targets)] +
    Includes additional build/{name}.inc file after OS-specific one.
    +
    make extra_inc={filename} [(above options or targets)] +
    Includes additional makefile.
    + +
    + + +
    +Up to parent directory +

    +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +

    +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +

    +* Other names and brands may be claimed as the property of others. + + diff --git a/src/tbb/src/old/concurrent_queue_v2.cpp b/src/tbb/src/old/concurrent_queue_v2.cpp new file mode 100644 index 0000000..4e7101e --- /dev/null +++ b/src/tbb/src/old/concurrent_queue_v2.cpp @@ -0,0 +1,378 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "concurrent_queue_v2.h" +#include "tbb/cache_aligned_allocator.h" +#include "tbb/spin_mutex.h" +#include "tbb/atomic.h" +#include +#include + +#if defined(_MSC_VER) && defined(_Wp64) + // Workaround for overzealous compiler warnings in /Wp64 mode + #pragma warning (disable: 4267) +#endif + +#define RECORD_EVENTS 0 + +using namespace std; + +namespace tbb { + +namespace internal { + +class concurrent_queue_rep; + +//! A queue using simple locking. +/** For efficiency, this class has no constructor. + The caller is expected to zero-initialize it. */ +struct micro_queue { + typedef concurrent_queue_base::page page; + typedef size_t ticket; + + atomic head_page; + atomic head_counter; + + atomic tail_page; + atomic tail_counter; + + spin_mutex page_mutex; + + class push_finalizer: no_copy { + ticket my_ticket; + micro_queue& my_queue; + public: + push_finalizer( micro_queue& queue, ticket k ) : + my_ticket(k), my_queue(queue) + {} + ~push_finalizer() { + my_queue.tail_counter = my_ticket; + } + }; + + void push( const void* item, ticket k, concurrent_queue_base& base ); + + class pop_finalizer: no_copy { + ticket my_ticket; + micro_queue& my_queue; + page* my_page; + public: + pop_finalizer( micro_queue& queue, ticket k, page* p ) : + my_ticket(k), my_queue(queue), my_page(p) + {} + ~pop_finalizer() { + page* p = my_page; + if( p ) { + spin_mutex::scoped_lock lock( my_queue.page_mutex ); + page* q = p->next; + my_queue.head_page = q; + if( !q ) { + my_queue.tail_page = NULL; + } + } + my_queue.head_counter = my_ticket; + if( p ) + operator delete(p); + } + }; + + bool pop( void* dst, ticket k, concurrent_queue_base& base ); +}; + +//! Internal representation of a ConcurrentQueue. +/** For efficiency, this class has no constructor. + The caller is expected to zero-initialize it. */ +class concurrent_queue_rep { +public: + typedef size_t ticket; + +private: + friend struct micro_queue; + + //! Approximately n_queue/golden ratio + static const size_t phi = 3; + +public: + //! Must be power of 2 + static const size_t n_queue = 8; + + //! Map ticket to an array index + static size_t index( ticket k ) { + return k*phi%n_queue; + } + + atomic head_counter; + char pad1[NFS_MaxLineSize-sizeof(atomic)]; + + atomic tail_counter; + char pad2[NFS_MaxLineSize-sizeof(atomic)]; + micro_queue array[n_queue]; + + micro_queue& choose( ticket k ) { + // The formula here approximates LRU in a cache-oblivious way. + return array[index(k)]; + } + + //! Value for effective_capacity that denotes unbounded queue. + static const ptrdiff_t infinite_capacity = ptrdiff_t(~size_t(0)/2); +}; + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // unary minus operator applied to unsigned type, result still unsigned + #pragma warning( push ) + #pragma warning( disable: 4146 ) +#endif + +//------------------------------------------------------------------------ +// micro_queue +//------------------------------------------------------------------------ +void micro_queue::push( const void* item, ticket k, concurrent_queue_base& base ) { + k &= -concurrent_queue_rep::n_queue; + page* p = NULL; + size_t index = (k/concurrent_queue_rep::n_queue & base.items_per_page-1); + if( !index ) { + size_t n = sizeof(page) + base.items_per_page*base.item_size; + p = static_cast(operator new( n )); + p->mask = 0; + p->next = NULL; + } + { + push_finalizer finalizer( *this, k+concurrent_queue_rep::n_queue ); + spin_wait_until_eq( tail_counter, k ); + if( p ) { + spin_mutex::scoped_lock lock( page_mutex ); + if( page* q = tail_page ) + q->next = p; + else + head_page = p; + tail_page = p; + } else { + p = tail_page; + } + base.copy_item( *p, index, item ); + // If no exception was thrown, mark item as present. + p->mask |= uintptr_t(1)<1 ? item_sz : 2); + my_rep = cache_aligned_allocator().allocate(1); + __TBB_ASSERT( (size_t)my_rep % NFS_GetLineSize()==0, "alignment error" ); + __TBB_ASSERT( (size_t)&my_rep->head_counter % NFS_GetLineSize()==0, "alignment error" ); + __TBB_ASSERT( (size_t)&my_rep->tail_counter % NFS_GetLineSize()==0, "alignment error" ); + __TBB_ASSERT( (size_t)&my_rep->array % NFS_GetLineSize()==0, "alignment error" ); + memset(my_rep,0,sizeof(concurrent_queue_rep)); + this->item_size = item_sz; +} + +concurrent_queue_base::~concurrent_queue_base() { + size_t nq = my_rep->n_queue; + for( size_t i=0; iarray[i].tail_page; + __TBB_ASSERT( my_rep->array[i].head_page==tp, "at most one page should remain" ); + if( tp!=NULL ) + delete tp; + } + cache_aligned_allocator().deallocate(my_rep,1); +} + +void concurrent_queue_base::internal_push( const void* src ) { + concurrent_queue_rep& r = *my_rep; + concurrent_queue_rep::ticket k = r.tail_counter++; + ptrdiff_t e = my_capacity; + if( e(my_capacity); + } + } + r.choose(k).push(src,k,*this); +} + +void concurrent_queue_base::internal_pop( void* dst ) { + concurrent_queue_rep& r = *my_rep; + concurrent_queue_rep::ticket k; + do { + k = r.head_counter++; + } while( !r.choose(k).pop(dst,k,*this) ); +} + +bool concurrent_queue_base::internal_pop_if_present( void* dst ) { + concurrent_queue_rep& r = *my_rep; + concurrent_queue_rep::ticket k; + do { + for( atomic_backoff backoff;;backoff.pause() ) { + k = r.head_counter; + if( r.tail_counter<=k ) { + // Queue is empty + return false; + } + // Queue had item with ticket k when we looked. Attempt to get that item. + if( r.head_counter.compare_and_swap(k+1,k)==k ) { + break; + } + // Another thread snatched the item, so pause and retry. + } + } while( !r.choose(k).pop(dst,k,*this) ); + return true; +} + +bool concurrent_queue_base::internal_push_if_not_full( const void* src ) { + concurrent_queue_rep& r = *my_rep; + concurrent_queue_rep::ticket k; + for( atomic_backoff backoff;;backoff.pause() ) { + k = r.tail_counter; + if( (ptrdiff_t)(k-r.head_counter)>=my_capacity ) { + // Queue is full + return false; + } + // Queue had empty slot with ticket k when we looked. Attempt to claim that slot. + if( r.tail_counter.compare_and_swap(k+1,k)==k ) + break; + // Another thread claimed the slot, so pause and retry. + } + r.choose(k).push(src,k,*this); + return true; +} + +ptrdiff_t concurrent_queue_base::internal_size() const { + __TBB_ASSERT( sizeof(ptrdiff_t)<=sizeof(size_t), NULL ); + return ptrdiff_t(my_rep->tail_counter-my_rep->head_counter); +} + +void concurrent_queue_base::internal_set_capacity( ptrdiff_t capacity, size_t /*item_sz*/ ) { + my_capacity = capacity<0 ? concurrent_queue_rep::infinite_capacity : capacity; +} + +//------------------------------------------------------------------------ +// concurrent_queue_iterator_rep +//------------------------------------------------------------------------ +class concurrent_queue_iterator_rep: no_assign { +public: + typedef concurrent_queue_rep::ticket ticket; + ticket head_counter; + const concurrent_queue_base& my_queue; + concurrent_queue_base::page* array[concurrent_queue_rep::n_queue]; + concurrent_queue_iterator_rep( const concurrent_queue_base& queue ) : + head_counter(queue.my_rep->head_counter), + my_queue(queue) + { + const concurrent_queue_rep& rep = *queue.my_rep; + for( size_t k=0; ktail_counter ) + return NULL; + else { + concurrent_queue_base::page* p = array[concurrent_queue_rep::index(k)]; + __TBB_ASSERT(p,NULL); + size_t i = k/concurrent_queue_rep::n_queue & my_queue.items_per_page-1; + return static_cast(static_cast(p+1)) + my_queue.item_size*i; + } + } +}; + +//------------------------------------------------------------------------ +// concurrent_queue_iterator_base +//------------------------------------------------------------------------ +concurrent_queue_iterator_base::concurrent_queue_iterator_base( const concurrent_queue_base& queue ) { + my_rep = new concurrent_queue_iterator_rep(queue); + my_item = my_rep->choose(my_rep->head_counter); +} + +void concurrent_queue_iterator_base::assign( const concurrent_queue_iterator_base& other ) { + if( my_rep!=other.my_rep ) { + if( my_rep ) { + delete my_rep; + my_rep = NULL; + } + if( other.my_rep ) { + my_rep = new concurrent_queue_iterator_rep( *other.my_rep ); + } + } + my_item = other.my_item; +} + +void concurrent_queue_iterator_base::advance() { + __TBB_ASSERT( my_item, "attempt to increment iterator past end of queue" ); + size_t k = my_rep->head_counter; + const concurrent_queue_base& queue = my_rep->my_queue; + __TBB_ASSERT( my_item==my_rep->choose(k), NULL ); + size_t i = k/concurrent_queue_rep::n_queue & queue.items_per_page-1; + if( i==queue.items_per_page-1 ) { + concurrent_queue_base::page*& root = my_rep->array[concurrent_queue_rep::index(k)]; + root = root->next; + } + my_rep->head_counter = k+1; + my_item = my_rep->choose(k+1); +} + +concurrent_queue_iterator_base::~concurrent_queue_iterator_base() { + delete my_rep; + my_rep = NULL; +} + +} // namespace internal + +} // namespace tbb diff --git a/src/tbb/src/old/concurrent_queue_v2.h b/src/tbb/src/old/concurrent_queue_v2.h new file mode 100644 index 0000000..ed3dc13 --- /dev/null +++ b/src/tbb/src/old/concurrent_queue_v2.h @@ -0,0 +1,332 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_concurrent_queue_H +#define __TBB_concurrent_queue_H + +#include "tbb/tbb_stddef.h" +#include + +namespace tbb { + +template class concurrent_queue; + +//! @cond INTERNAL +namespace internal { + +class concurrent_queue_rep; +class concurrent_queue_iterator_rep; +template class concurrent_queue_iterator; + +//! For internal use only. +/** Type-independent portion of concurrent_queue. + @ingroup containers */ +class concurrent_queue_base: no_copy { + //! Internal representation + concurrent_queue_rep* my_rep; + + friend class concurrent_queue_rep; + friend struct micro_queue; + friend class concurrent_queue_iterator_rep; + friend class concurrent_queue_iterator_base; + + // In C++ 1998/2003 (but quite likely not beyond), friend micro_queue's rights + // do not apply to the declaration of micro_queue::pop_finalizer::my_page, + // as a member of a class nested within that friend class, so... +public: + //! Prefix on a page + struct page { + page* next; + uintptr_t mask; + }; + +protected: + //! Capacity of the queue + ptrdiff_t my_capacity; + + //! Always a power of 2 + size_t items_per_page; + + //! Size of an item + size_t item_size; +private: + virtual void copy_item( page& dst, size_t index, const void* src ) = 0; + virtual void assign_and_destroy_item( void* dst, page& src, size_t index ) = 0; +protected: + __TBB_EXPORTED_METHOD concurrent_queue_base( size_t item_size ); + virtual __TBB_EXPORTED_METHOD ~concurrent_queue_base(); + + //! Enqueue item at tail of queue + void __TBB_EXPORTED_METHOD internal_push( const void* src ); + + //! Dequeue item from head of queue + void __TBB_EXPORTED_METHOD internal_pop( void* dst ); + + //! Attempt to enqueue item onto queue. + bool __TBB_EXPORTED_METHOD internal_push_if_not_full( const void* src ); + + //! Attempt to dequeue item from queue. + /** NULL if there was no item to dequeue. */ + bool __TBB_EXPORTED_METHOD internal_pop_if_present( void* dst ); + + //! Get size of queue + ptrdiff_t __TBB_EXPORTED_METHOD internal_size() const; + + void __TBB_EXPORTED_METHOD internal_set_capacity( ptrdiff_t capacity, size_t element_size ); +}; + +//! Type-independent portion of concurrent_queue_iterator. +/** @ingroup containers */ +class concurrent_queue_iterator_base { + //! concurrent_queue over which we are iterating. + /** NULL if one past last element in queue. */ + concurrent_queue_iterator_rep* my_rep; + + template + friend bool operator==( const concurrent_queue_iterator& i, const concurrent_queue_iterator& j ); + + template + friend bool operator!=( const concurrent_queue_iterator& i, const concurrent_queue_iterator& j ); +protected: + //! Pointer to current item + mutable void* my_item; + + //! Default constructor + __TBB_EXPORTED_METHOD concurrent_queue_iterator_base() : my_rep(NULL), my_item(NULL) {} + + //! Copy constructor + concurrent_queue_iterator_base( const concurrent_queue_iterator_base& i ) : my_rep(NULL), my_item(NULL) { + assign(i); + } + + //! Construct iterator pointing to head of queue. + concurrent_queue_iterator_base( const concurrent_queue_base& queue ); + + //! Assignment + void __TBB_EXPORTED_METHOD assign( const concurrent_queue_iterator_base& i ); + + //! Advance iterator one step towards tail of queue. + void __TBB_EXPORTED_METHOD advance(); + + //! Destructor + __TBB_EXPORTED_METHOD ~concurrent_queue_iterator_base(); +}; + +//! Meets requirements of a forward iterator for STL. +/** Value is either the T or const T type of the container. + @ingroup containers */ +template +class concurrent_queue_iterator: public concurrent_queue_iterator_base { +#if !defined(_MSC_VER) || defined(__INTEL_COMPILER) + template + friend class ::tbb::concurrent_queue; +#else +public: // workaround for MSVC +#endif + //! Construct iterator pointing to head of queue. + concurrent_queue_iterator( const concurrent_queue_base& queue ) : + concurrent_queue_iterator_base(queue) + { + } +public: + concurrent_queue_iterator() {} + + /** If Value==Container::value_type, then this routine is the copy constructor. + If Value==const Container::value_type, then this routine is a conversion constructor. */ + concurrent_queue_iterator( const concurrent_queue_iterator& other ) : + concurrent_queue_iterator_base(other) + {} + + //! Iterator assignment + concurrent_queue_iterator& operator=( const concurrent_queue_iterator& other ) { + assign(other); + return *this; + } + + //! Reference to current item + Value& operator*() const { + return *static_cast(my_item); + } + + Value* operator->() const {return &operator*();} + + //! Advance to next item in queue + concurrent_queue_iterator& operator++() { + advance(); + return *this; + } + + //! Post increment + Value* operator++(int) { + Value* result = &operator*(); + operator++(); + return result; + } +}; // concurrent_queue_iterator + +template +bool operator==( const concurrent_queue_iterator& i, const concurrent_queue_iterator& j ) { + return i.my_item==j.my_item; +} + +template +bool operator!=( const concurrent_queue_iterator& i, const concurrent_queue_iterator& j ) { + return i.my_item!=j.my_item; +} + +} // namespace internal; +//! @endcond + +//! A high-performance thread-safe queue. +/** Multiple threads may each push and pop concurrently. + Assignment and copy construction are not allowed. + @ingroup containers */ +template +class concurrent_queue: public internal::concurrent_queue_base { + template friend class internal::concurrent_queue_iterator; + + //! Class used to ensure exception-safety of method "pop" + class destroyer { + T& my_value; + public: + destroyer( T& value ) : my_value(value) {} + ~destroyer() {my_value.~T();} + }; + + T& get_ref( page& pg, size_t index ) { + __TBB_ASSERT( index(static_cast(&pg+1))[index]; + } + + /*override*/ virtual void copy_item( page& dst, size_t index, const void* src ) { + new( &get_ref(dst,index) ) T(*static_cast(src)); + } + + /*override*/ virtual void assign_and_destroy_item( void* dst, page& src, size_t index ) { + T& from = get_ref(src,index); + destroyer d(from); + *static_cast(dst) = from; + } + +public: + //! Element type in the queue. + typedef T value_type; + + //! Reference type + typedef T& reference; + + //! Const reference type + typedef const T& const_reference; + + //! Integral type for representing size of the queue. + /** Note that the size_type is a signed integral type. + This is because the size can be negative if there are pending pops without corresponding pushes. */ + typedef std::ptrdiff_t size_type; + + //! Difference type for iterator + typedef std::ptrdiff_t difference_type; + + //! Construct empty queue + concurrent_queue() : + concurrent_queue_base( sizeof(T) ) + { + } + + //! Destroy queue + ~concurrent_queue(); + + //! Enqueue an item at tail of queue. + void push( const T& source ) { + internal_push( &source ); + } + + //! Dequeue item from head of queue. + /** Block until an item becomes available, and then dequeue it. */ + void pop( T& destination ) { + internal_pop( &destination ); + } + + //! Enqueue an item at tail of queue if queue is not already full. + /** Does not wait for queue to become not full. + Returns true if item is pushed; false if queue was already full. */ + bool push_if_not_full( const T& source ) { + return internal_push_if_not_full( &source ); + } + + //! Attempt to dequeue an item from head of queue. + /** Does not wait for item to become available. + Returns true if successful; false otherwise. */ + bool pop_if_present( T& destination ) { + return internal_pop_if_present( &destination ); + } + + //! Return number of pushes minus number of pops. + /** Note that the result can be negative if there are pops waiting for the + corresponding pushes. The result can also exceed capacity() if there + are push operations in flight. */ + size_type size() const {return internal_size();} + + //! Equivalent to size()<=0. + bool empty() const {return size()<=0;} + + //! Maximum number of allowed elements + size_type capacity() const { + return my_capacity; + } + + //! Set the capacity + /** Setting the capacity to 0 causes subsequent push_if_not_full operations to always fail, + and subsequent push operations to block forever. */ + void set_capacity( size_type new_capacity ) { + internal_set_capacity( new_capacity, sizeof(T) ); + } + + typedef internal::concurrent_queue_iterator iterator; + typedef internal::concurrent_queue_iterator const_iterator; + + //------------------------------------------------------------------------ + // The iterators are intended only for debugging. They are slow and not thread safe. + //------------------------------------------------------------------------ + iterator begin() {return iterator(*this);} + iterator end() {return iterator();} + const_iterator begin() const {return const_iterator(*this);} + const_iterator end() const {return const_iterator();} + +}; + +template +concurrent_queue::~concurrent_queue() { + while( !empty() ) { + T value; + internal_pop(&value); + } +} + +} // namespace tbb + +#endif /* __TBB_concurrent_queue_H */ diff --git a/src/tbb/src/old/concurrent_vector_v2.cpp b/src/tbb/src/old/concurrent_vector_v2.cpp new file mode 100644 index 0000000..9480eb8 --- /dev/null +++ b/src/tbb/src/old/concurrent_vector_v2.cpp @@ -0,0 +1,276 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "concurrent_vector_v2.h" +#include "tbb/tbb_machine.h" +#include "../tbb/itt_notify.h" +#include "tbb/task.h" + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include // std::length_error +#include + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +#if defined(_MSC_VER) && defined(_Wp64) + // Workaround for overzealous compiler warnings in /Wp64 mode + #pragma warning (disable: 4267) +#endif + +namespace tbb { + +namespace internal { + +void concurrent_vector_base::internal_grow_to_at_least( size_type new_size, size_type element_size, internal_array_op1 init ) { + size_type e = my_early_size; + while( e=pointers_per_short_segment && v.my_segment==v.my_storage ) { + extend_segment(v); + } + } +}; + +void concurrent_vector_base::helper::extend_segment( concurrent_vector_base& v ) { + const size_t pointers_per_long_segment = sizeof(void*)==4 ? 32 : 64; + segment_t* s = (segment_t*)NFS_Allocate( pointers_per_long_segment, sizeof(segment_t), NULL ); + std::memset( s, 0, pointers_per_long_segment*sizeof(segment_t) ); + // If other threads are trying to set pointers in the short segment, wait for them to finish their + // assignments before we copy the short segment to the long segment. + atomic_backoff backoff; + while( !v.my_storage[0].array || !v.my_storage[1].array ) { + backoff.pause(); + } + s[0] = v.my_storage[0]; + s[1] = v.my_storage[1]; + if( v.my_segment.compare_and_swap( s, v.my_storage )!=v.my_storage ) + NFS_Free(s); +} + +concurrent_vector_base::size_type concurrent_vector_base::internal_capacity() const { + return segment_base( helper::find_segment_end(*this) ); +} + +void concurrent_vector_base::internal_reserve( size_type n, size_type element_size, size_type max_size ) { + if( n>max_size ) { + __TBB_THROW( std::length_error("argument to concurrent_vector::reserve exceeds concurrent_vector::max_size()") ); + } + for( segment_index_t k = helper::find_segment_end(*this); segment_base(k)n-b ) m = n-b; + copy( my_segment[k].array, src.my_segment[k].array, m ); + } + } +} + +void concurrent_vector_base::internal_assign( const concurrent_vector_base& src, size_type element_size, internal_array_op1 destroy, internal_array_op2 assign, internal_array_op2 copy ) { + size_type n = src.my_early_size; + while( my_early_size>n ) { + segment_index_t k = segment_index_of( my_early_size-1 ); + size_type b=segment_base(k); + size_type new_end = b>=n ? b : n; + __TBB_ASSERT( my_early_size>new_end, NULL ); + destroy( (char*)my_segment[k].array+element_size*(new_end-b), my_early_size-new_end ); + my_early_size = new_end; + } + size_type dst_initialized_size = my_early_size; + my_early_size = n; + size_type b; + for( segment_index_t k=0; (b=segment_base(k))n-b ) m = n-b; + size_type a = 0; + if( dst_initialized_size>b ) { + a = dst_initialized_size-b; + if( a>m ) a = m; + assign( my_segment[k].array, src.my_segment[k].array, a ); + m -= a; + a *= element_size; + } + if( m>0 ) + copy( (char*)my_segment[k].array+a, (char*)src.my_segment[k].array+a, m ); + } + __TBB_ASSERT( src.my_early_size==n, "detected use of concurrent_vector::operator= with right side that was concurrently modified" ); +} + +void* concurrent_vector_base::internal_push_back( size_type element_size, size_type& index ) { + __TBB_ASSERT( sizeof(my_early_size)==sizeof(reference_count), NULL ); + //size_t tmp = __TBB_FetchAndIncrementWacquire(*(tbb::internal::reference_count*)&my_early_size); + size_t tmp = __TBB_FetchAndIncrementWacquire((tbb::internal::reference_count*)&my_early_size); + index = tmp; + segment_index_t k_old = segment_index_of( tmp ); + size_type base = segment_base(k_old); + helper::extend_segment_if_necessary(*this,k_old); + segment_t& s = my_segment[k_old]; + void* array = s.array; + if( !array ) { + // FIXME - consider factoring this out and share with internal_grow_by + if( base==tmp ) { + __TBB_ASSERT( !s.array, NULL ); + size_t n = segment_size(k_old); + array = NFS_Allocate( n, element_size, NULL ); + ITT_NOTIFY( sync_releasing, &s.array ); + s.array = array; + } else { + ITT_NOTIFY(sync_prepare, &s.array); + spin_wait_while_eq( s.array, (void*)0 ); + ITT_NOTIFY(sync_acquired, &s.array); + array = s.array; + } + } + size_type j_begin = tmp-base; + return (void*)((char*)array+element_size*j_begin); +} + +concurrent_vector_base::size_type concurrent_vector_base::internal_grow_by( size_type delta, size_type element_size, internal_array_op1 init ) { + size_type result = my_early_size.fetch_and_add(delta); + internal_grow( result, result+delta, element_size, init ); + return result; +} + +void concurrent_vector_base::internal_grow( const size_type start, size_type finish, size_type element_size, internal_array_op1 init ) { + __TBB_ASSERT( start finish-base ? finish-base : n; + (*init)( (void*)((char*)array+element_size*j_begin), j_end-j_begin ); + tmp = base+j_end; + } while( tmp0 ) { + segment_index_t k_old = segment_index_of(finish-1); + segment_t& s = my_segment[k_old]; + __TBB_ASSERT( s.array, NULL ); + size_type base = segment_base(k_old); + size_type j_end = finish-base; + __TBB_ASSERT( j_end, NULL ); + (*destroy)( s.array, j_end ); + finish = base; + } + + // Free the arrays + if( reclaim_storage ) { + size_t k = helper::find_segment_end(*this); + while( k>0 ) { + --k; + segment_t& s = my_segment[k]; + void* array = s.array; + s.array = NULL; + NFS_Free( array ); + } + // Clear short segment. + my_storage[0].array = NULL; + my_storage[1].array = NULL; + segment_t* s = my_segment; + if( s!=my_storage ) { + my_segment = my_storage; + NFS_Free( s ); + } + } +} + +} // namespace internal + +} // tbb diff --git a/src/tbb/src/old/concurrent_vector_v2.h b/src/tbb/src/old/concurrent_vector_v2.h new file mode 100644 index 0000000..6f07736 --- /dev/null +++ b/src/tbb/src/old/concurrent_vector_v2.h @@ -0,0 +1,531 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_concurrent_vector_H +#define __TBB_concurrent_vector_H + +#include "tbb/tbb_stddef.h" +#include "tbb/atomic.h" +#include "tbb/cache_aligned_allocator.h" +#include "tbb/blocked_range.h" +#include "tbb/tbb_machine.h" +#include + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +namespace tbb { + +template +class concurrent_vector; + +//! @cond INTERNAL +namespace internal { + + //! Base class of concurrent vector implementation. + /** @ingroup containers */ + class concurrent_vector_base { + protected: + + // Basic types declarations + typedef unsigned long segment_index_t; + typedef size_t size_type; + + //! Log2 of "min_segment_size". + static const int lg_min_segment_size = 4; + + //! Minimum size (in physical items) of a segment. + static const int min_segment_size = segment_index_t(1)<>1< my_early_size; + + /** Can be zero-initialized. */ + struct segment_t { + /** Declared volatile because in weak memory model, must have ld.acq/st.rel */ + void* volatile array; +#if TBB_USE_ASSERT + ~segment_t() { + __TBB_ASSERT( !array, "should have been set to NULL by clear" ); + } +#endif /* TBB_USE_ASSERT */ + }; + + // Data fields + + //! Pointer to the segments table + atomic my_segment; + + //! embedded storage of segment pointers + segment_t my_storage[2]; + + // Methods + + concurrent_vector_base() { + my_early_size = 0; + my_storage[0].array = NULL; + my_storage[1].array = NULL; + my_segment = my_storage; + } + + //! An operation on an n-element array starting at begin. + typedef void(__TBB_EXPORTED_FUNC *internal_array_op1)(void* begin, size_type n ); + + //! An operation on n-element destination array and n-element source array. + typedef void(__TBB_EXPORTED_FUNC *internal_array_op2)(void* dst, const void* src, size_type n ); + + void __TBB_EXPORTED_METHOD internal_grow_to_at_least( size_type new_size, size_type element_size, internal_array_op1 init ); + void internal_grow( size_type start, size_type finish, size_type element_size, internal_array_op1 init ); + size_type __TBB_EXPORTED_METHOD internal_grow_by( size_type delta, size_type element_size, internal_array_op1 init ); + void* __TBB_EXPORTED_METHOD internal_push_back( size_type element_size, size_type& index ); + void __TBB_EXPORTED_METHOD internal_clear( internal_array_op1 destroy, bool reclaim_storage ); + void __TBB_EXPORTED_METHOD internal_copy( const concurrent_vector_base& src, size_type element_size, internal_array_op2 copy ); + void __TBB_EXPORTED_METHOD internal_assign( const concurrent_vector_base& src, size_type element_size, + internal_array_op1 destroy, internal_array_op2 assign, internal_array_op2 copy ); +private: + //! Private functionality that does not cross DLL boundary. + class helper; + friend class helper; + }; + + //! Meets requirements of a forward iterator for STL and a Value for a blocked_range.*/ + /** Value is either the T or const T type of the container. + @ingroup containers */ + template + class vector_iterator +#if defined(_WIN64) && defined(_MSC_VER) + // Ensure that Microsoft's internal template function _Val_type works correctly. + : public std::iterator +#endif /* defined(_WIN64) && defined(_MSC_VER) */ + { + //! concurrent_vector over which we are iterating. + Container* my_vector; + + //! Index into the vector + size_t my_index; + + //! Caches my_vector->internal_subscript(my_index) + /** NULL if cached value is not available */ + mutable Value* my_item; + + template + friend bool operator==( const vector_iterator& i, const vector_iterator& j ); + + template + friend bool operator<( const vector_iterator& i, const vector_iterator& j ); + + template + friend ptrdiff_t operator-( const vector_iterator& i, const vector_iterator& j ); + + template + friend class internal::vector_iterator; + +#if !defined(_MSC_VER) || defined(__INTEL_COMPILER) + template + friend class tbb::concurrent_vector; +#else +public: // workaround for MSVC +#endif + + vector_iterator( const Container& vector, size_t index ) : + my_vector(const_cast(&vector)), + my_index(index), + my_item(NULL) + {} + + public: + //! Default constructor + vector_iterator() : my_vector(NULL), my_index(~size_t(0)), my_item(NULL) {} + + vector_iterator( const vector_iterator& other ) : + my_vector(other.my_vector), + my_index(other.my_index), + my_item(other.my_item) + {} + + vector_iterator operator+( ptrdiff_t offset ) const { + return vector_iterator( *my_vector, my_index+offset ); + } + friend vector_iterator operator+( ptrdiff_t offset, const vector_iterator& v ) { + return vector_iterator( *v.my_vector, v.my_index+offset ); + } + vector_iterator operator+=( ptrdiff_t offset ) { + my_index+=offset; + my_item = NULL; + return *this; + } + vector_iterator operator-( ptrdiff_t offset ) const { + return vector_iterator( *my_vector, my_index-offset ); + } + vector_iterator operator-=( ptrdiff_t offset ) { + my_index-=offset; + my_item = NULL; + return *this; + } + Value& operator*() const { + Value* item = my_item; + if( !item ) { + item = my_item = &my_vector->internal_subscript(my_index); + } + __TBB_ASSERT( item==&my_vector->internal_subscript(my_index), "corrupt cache" ); + return *item; + } + Value& operator[]( ptrdiff_t k ) const { + return my_vector->internal_subscript(my_index+k); + } + Value* operator->() const {return &operator*();} + + //! Pre increment + vector_iterator& operator++() { + size_t k = ++my_index; + if( my_item ) { + // Following test uses 2's-complement wizardry and fact that + // min_segment_size is a power of 2. + if( (k& k-concurrent_vector::min_segment_size)==0 ) { + // k is a power of two that is at least k-min_segment_size + my_item= NULL; + } else { + ++my_item; + } + } + return *this; + } + + //! Pre decrement + vector_iterator& operator--() { + __TBB_ASSERT( my_index>0, "operator--() applied to iterator already at beginning of concurrent_vector" ); + size_t k = my_index--; + if( my_item ) { + // Following test uses 2's-complement wizardry and fact that + // min_segment_size is a power of 2. + if( (k& k-concurrent_vector::min_segment_size)==0 ) { + // k is a power of two that is at least k-min_segment_size + my_item= NULL; + } else { + --my_item; + } + } + return *this; + } + + //! Post increment + vector_iterator operator++(int) { + vector_iterator result = *this; + operator++(); + return result; + } + + //! Post decrement + vector_iterator operator--(int) { + vector_iterator result = *this; + operator--(); + return result; + } + + // STL support + + typedef ptrdiff_t difference_type; + typedef Value value_type; + typedef Value* pointer; + typedef Value& reference; + typedef std::random_access_iterator_tag iterator_category; + }; + + template + bool operator==( const vector_iterator& i, const vector_iterator& j ) { + return i.my_index==j.my_index; + } + + template + bool operator!=( const vector_iterator& i, const vector_iterator& j ) { + return !(i==j); + } + + template + bool operator<( const vector_iterator& i, const vector_iterator& j ) { + return i.my_index + bool operator>( const vector_iterator& i, const vector_iterator& j ) { + return j + bool operator>=( const vector_iterator& i, const vector_iterator& j ) { + return !(i + bool operator<=( const vector_iterator& i, const vector_iterator& j ) { + return !(j + ptrdiff_t operator-( const vector_iterator& i, const vector_iterator& j ) { + return ptrdiff_t(i.my_index)-ptrdiff_t(j.my_index); + } + +} // namespace internal +//! @endcond + +//! Concurrent vector +/** @ingroup containers */ +template +class concurrent_vector: private internal::concurrent_vector_base { +public: + using internal::concurrent_vector_base::size_type; +private: + template + class generic_range_type: public blocked_range { + public: + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; + typedef I iterator; + typedef ptrdiff_t difference_type; + generic_range_type( I begin_, I end_, size_t grainsize_ ) : blocked_range(begin_,end_,grainsize_) {} + generic_range_type( generic_range_type& r, split ) : blocked_range(r,split()) {} + }; + + template + friend class internal::vector_iterator; +public: + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + typedef ptrdiff_t difference_type; + + //! Construct empty vector. + concurrent_vector() {} + + //! Copy a vector. + concurrent_vector( const concurrent_vector& vector ) : internal::concurrent_vector_base() + { internal_copy(vector,sizeof(T),©_array); } + + //! Assignment + concurrent_vector& operator=( const concurrent_vector& vector ) { + if( this!=&vector ) + internal_assign(vector,sizeof(T),&destroy_array,&assign_array,©_array); + return *this; + } + + //! Clear and destroy vector. + ~concurrent_vector() {internal_clear(&destroy_array,/*reclaim_storage=*/true);} + + //------------------------------------------------------------------------ + // Concurrent operations + //------------------------------------------------------------------------ + //! Grow by "delta" elements. + /** Returns old size. */ + size_type grow_by( size_type delta ) { + return delta ? internal_grow_by( delta, sizeof(T), &initialize_array ) : my_early_size; + } + + //! Grow array until it has at least n elements. + void grow_to_at_least( size_type n ) { + if( my_early_size iterator; + typedef internal::vector_iterator const_iterator; + +#if !defined(_MSC_VER) || _CPPLIB_VER>=300 + // Assume ISO standard definition of std::reverse_iterator + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; +#else + // Use non-standard std::reverse_iterator + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; +#endif /* defined(_MSC_VER) && (_MSC_VER<1300) */ + + // Forward sequence + iterator begin() {return iterator(*this,0);} + iterator end() {return iterator(*this,size());} + const_iterator begin() const {return const_iterator(*this,0);} + const_iterator end() const {return const_iterator(*this,size());} + + // Reverse sequence + reverse_iterator rbegin() {return reverse_iterator(end());} + reverse_iterator rend() {return reverse_iterator(begin());} + const_reverse_iterator rbegin() const {return const_reverse_iterator(end());} + const_reverse_iterator rend() const {return const_reverse_iterator(begin());} + + //------------------------------------------------------------------------ + // Support for TBB algorithms (ranges) + //------------------------------------------------------------------------ + typedef generic_range_type range_type; + typedef generic_range_type const_range_type; + + //! Get range to use with parallel algorithms + range_type range( size_t grainsize = 1 ) { + return range_type( begin(), end(), grainsize ); + } + + //! Get const range for iterating with parallel algorithms + const_range_type range( size_t grainsize = 1 ) const { + return const_range_type( begin(), end(), grainsize ); + } + + //------------------------------------------------------------------------ + // Size and capacity + //------------------------------------------------------------------------ + //! Return size of vector. + size_type size() const {return my_early_size;} + + //! Return false if vector is not empty. + bool empty() const {return !my_early_size;} + + //! Maximum size to which array can grow without allocating more memory. + size_type capacity() const {return internal_capacity();} + + //! Allocate enough space to grow to size n without having to allocate more memory later. + /** Like most of the methods provided for STL compatibility, this method is *not* thread safe. + The capacity afterwards may be bigger than the requested reservation. */ + void reserve( size_type n ) { + if( n ) + internal_reserve(n, sizeof(T), max_size()); + } + + //! Upper bound on argument to reserve. + size_type max_size() const {return (~size_t(0))/sizeof(T);} + + //! Not thread safe + /** Does not change capacity. */ + void clear() {internal_clear(&destroy_array,/*reclaim_storage=*/false);} +private: + //! Get reference to element at given index. + T& internal_subscript( size_type index ) const; + + //! Construct n instances of T, starting at "begin". + static void __TBB_EXPORTED_FUNC initialize_array( void* begin, size_type n ); + + //! Construct n instances of T, starting at "begin". + static void __TBB_EXPORTED_FUNC copy_array( void* dst, const void* src, size_type n ); + + //! Assign n instances of T, starting at "begin". + static void __TBB_EXPORTED_FUNC assign_array( void* dst, const void* src, size_type n ); + + //! Destroy n instances of T, starting at "begin". + static void __TBB_EXPORTED_FUNC destroy_array( void* begin, size_type n ); +}; + +template +T& concurrent_vector::internal_subscript( size_type index ) const { + __TBB_ASSERT( index(my_segment[k].array)[j]; +} + +template +void concurrent_vector::initialize_array( void* begin, size_type n ) { + T* array = static_cast(begin); + for( size_type j=0; j +void concurrent_vector::copy_array( void* dst, const void* src, size_type n ) { + T* d = static_cast(dst); + const T* s = static_cast(src); + for( size_type j=0; j +void concurrent_vector::assign_array( void* dst, const void* src, size_type n ) { + T* d = static_cast(dst); + const T* s = static_cast(src); + for( size_type j=0; j +void concurrent_vector::destroy_array( void* begin, size_type n ) { + T* array = static_cast(begin); + for( size_type j=n; j>0; --j ) + array[j-1].~T(); +} + +} // namespace tbb + +#endif /* __TBB_concurrent_vector_H */ diff --git a/src/tbb/src/old/spin_rw_mutex_v2.cpp b/src/tbb/src/old/spin_rw_mutex_v2.cpp new file mode 100644 index 0000000..3c99b80 --- /dev/null +++ b/src/tbb/src/old/spin_rw_mutex_v2.cpp @@ -0,0 +1,163 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "spin_rw_mutex_v2.h" +#include "tbb/tbb_machine.h" +#include "../tbb/itt_notify.h" + +namespace tbb { + +using namespace internal; + +static inline bool CAS(volatile uintptr_t &addr, uintptr_t newv, uintptr_t oldv) { + return __TBB_CompareAndSwapW((volatile void *)&addr, (intptr_t)newv, (intptr_t)oldv) == (intptr_t)oldv; +} + +//! Signal that write lock is released +void spin_rw_mutex::internal_itt_releasing(spin_rw_mutex *mutex) { + __TBB_ASSERT_EX(mutex, NULL); // To prevent compiler warnings + ITT_NOTIFY(sync_releasing, mutex); +} + +//! Acquire write (exclusive) lock on the given mutex. +bool spin_rw_mutex::internal_acquire_writer(spin_rw_mutex *mutex) +{ + ITT_NOTIFY(sync_prepare, mutex); + for( atomic_backoff backoff;;backoff.pause() ) { + state_t s = mutex->state; + if( !(s & BUSY) ) { // no readers, no writers + if( CAS(mutex->state, WRITER, s) ) + break; // successfully stored writer flag + backoff.reset(); // we could be very close to complete op. + } else if( !(s & WRITER_PENDING) ) { // no pending writers + __TBB_AtomicOR(&mutex->state, WRITER_PENDING); + } + } + ITT_NOTIFY(sync_acquired, mutex); + __TBB_ASSERT( (mutex->state & BUSY)==WRITER, "invalid state of a write lock" ); + return false; +} + +//! Release write lock on the given mutex +void spin_rw_mutex::internal_release_writer(spin_rw_mutex *mutex) { + __TBB_ASSERT( (mutex->state & BUSY)==WRITER, "invalid state of a write lock" ); + ITT_NOTIFY(sync_releasing, mutex); + mutex->state = 0; +} + +//! Acquire read (shared) lock on the given mutex. +void spin_rw_mutex::internal_acquire_reader(spin_rw_mutex *mutex) { + ITT_NOTIFY(sync_prepare, mutex); + for( atomic_backoff backoff;;backoff.pause() ) { + state_t s = mutex->state; + if( !(s & (WRITER|WRITER_PENDING)) ) { // no writer or write requests + if( CAS(mutex->state, s+ONE_READER, s) ) + break; // successfully stored increased number of readers + backoff.reset(); // we could be very close to complete op. + } + } + ITT_NOTIFY(sync_acquired, mutex); + __TBB_ASSERT( mutex->state & READERS, "invalid state of a read lock: no readers" ); + __TBB_ASSERT( !(mutex->state & WRITER), "invalid state of a read lock: active writer" ); +} + +//! Upgrade reader to become a writer. +/** Returns whether the upgrade happened without releasing and re-acquiring the lock */ +bool spin_rw_mutex::internal_upgrade(spin_rw_mutex *mutex) { + state_t s = mutex->state; + __TBB_ASSERT( s & READERS, "invalid state before upgrade: no readers " ); + __TBB_ASSERT( !(s & WRITER), "invalid state before upgrade: active writer " ); + // check and set writer-pending flag + // required conditions: either no pending writers, or we are the only reader + // (with multiple readers and pending writer, another upgrade could have been requested) + while( (s & READERS)==ONE_READER || !(s & WRITER_PENDING) ) { + if( CAS(mutex->state, s | WRITER_PENDING, s) ) + { + ITT_NOTIFY(sync_prepare, mutex); + for( atomic_backoff backoff; (mutex->state & READERS) != ONE_READER; ) + backoff.pause(); // while more than 1 reader + __TBB_ASSERT(mutex->state == (ONE_READER | WRITER_PENDING),"invalid state when upgrading to writer"); + // both new readers and writers are blocked at this time + mutex->state = WRITER; + ITT_NOTIFY(sync_acquired, mutex); + __TBB_ASSERT( (mutex->state & BUSY) == WRITER, "invalid state after upgrade" ); + return true; // successfully upgraded + } else { + s = mutex->state; // re-read + } + } + // slow reacquire + internal_release_reader(mutex); + return internal_acquire_writer(mutex); // always returns false +} + +//! Downgrade writer to a reader +void spin_rw_mutex::internal_downgrade(spin_rw_mutex *mutex) { + __TBB_ASSERT( (mutex->state & BUSY) == WRITER, "invalid state before downgrade" ); + ITT_NOTIFY(sync_releasing, mutex); + mutex->state = ONE_READER; + __TBB_ASSERT( mutex->state & READERS, "invalid state after downgrade: no readers" ); + __TBB_ASSERT( !(mutex->state & WRITER), "invalid state after downgrade: active writer" ); +} + +//! Release read lock on the given mutex +void spin_rw_mutex::internal_release_reader(spin_rw_mutex *mutex) +{ + __TBB_ASSERT( mutex->state & READERS, "invalid state of a read lock: no readers" ); + __TBB_ASSERT( !(mutex->state & WRITER), "invalid state of a read lock: active writer" ); + ITT_NOTIFY(sync_releasing, mutex); // release reader + __TBB_FetchAndAddWrelease((volatile void *)&(mutex->state),-(intptr_t)ONE_READER); +} + +//! Try to acquire write lock on the given mutex +bool spin_rw_mutex::internal_try_acquire_writer( spin_rw_mutex * mutex ) +{ + // for a writer: only possible to acquire if no active readers or writers + state_t s = mutex->state; // on IA-64, this volatile load has acquire semantic + if( !(s & BUSY) ) // no readers, no writers; mask is 1..1101 + if( CAS(mutex->state, WRITER, s) ) { + ITT_NOTIFY(sync_acquired, mutex); + return true; // successfully stored writer flag + } + return false; +} + +//! Try to acquire read lock on the given mutex +bool spin_rw_mutex::internal_try_acquire_reader( spin_rw_mutex * mutex ) +{ + // for a reader: acquire if no active or waiting writers + state_t s = mutex->state; // on IA-64, a load of volatile variable has acquire semantic + while( !(s & (WRITER|WRITER_PENDING)) ) // no writers + if( CAS(mutex->state, s+ONE_READER, s) ) { + ITT_NOTIFY(sync_acquired, mutex); + return true; // successfully stored increased number of readers + } + return false; +} + +} // namespace tbb diff --git a/src/tbb/src/old/spin_rw_mutex_v2.h b/src/tbb/src/old/spin_rw_mutex_v2.h new file mode 100644 index 0000000..1bffe5e --- /dev/null +++ b/src/tbb/src/old/spin_rw_mutex_v2.h @@ -0,0 +1,183 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_spin_rw_mutex_H +#define __TBB_spin_rw_mutex_H + +#include "tbb/tbb_stddef.h" + +namespace tbb { + +//! Fast, unfair, spinning reader-writer lock with backoff and writer-preference +/** @ingroup synchronization */ +class spin_rw_mutex { + //! @cond INTERNAL + + //! Present so that 1.0 headers work with 1.1 dynamic library. + static void __TBB_EXPORTED_FUNC internal_itt_releasing(spin_rw_mutex *); + + //! Internal acquire write lock. + static bool __TBB_EXPORTED_FUNC internal_acquire_writer(spin_rw_mutex *); + + //! Out of line code for releasing a write lock. + /** This code has debug checking and instrumentation for Intel(R) Thread Checker and Intel(R) Thread Profiler. */ + static void __TBB_EXPORTED_FUNC internal_release_writer(spin_rw_mutex *); + + //! Internal acquire read lock. + static void __TBB_EXPORTED_FUNC internal_acquire_reader(spin_rw_mutex *); + + //! Internal upgrade reader to become a writer. + static bool __TBB_EXPORTED_FUNC internal_upgrade(spin_rw_mutex *); + + //! Out of line code for downgrading a writer to a reader. + /** This code has debug checking and instrumentation for Intel(R) Thread Checker and Intel(R) Thread Profiler. */ + static void __TBB_EXPORTED_FUNC internal_downgrade(spin_rw_mutex *); + + //! Internal release read lock. + static void __TBB_EXPORTED_FUNC internal_release_reader(spin_rw_mutex *); + + //! Internal try_acquire write lock. + static bool __TBB_EXPORTED_FUNC internal_try_acquire_writer(spin_rw_mutex *); + + //! Internal try_acquire read lock. + static bool __TBB_EXPORTED_FUNC internal_try_acquire_reader(spin_rw_mutex *); + + //! @endcond +public: + //! Construct unacquired mutex. + spin_rw_mutex() : state(0) {} + +#if TBB_USE_ASSERT + //! Destructor asserts if the mutex is acquired, i.e. state is zero. + ~spin_rw_mutex() { + __TBB_ASSERT( !state, "destruction of an acquired mutex"); + }; +#endif /* TBB_USE_ASSERT */ + + //! The scoped locking pattern + /** It helps to avoid the common problem of forgetting to release lock. + It also nicely provides the "node" for queuing locks. */ + class scoped_lock : internal::no_copy { + public: + //! Construct lock that has not acquired a mutex. + /** Equivalent to zero-initialization of *this. */ + scoped_lock() : mutex(NULL) {} + + //! Construct and acquire lock on given mutex. + scoped_lock( spin_rw_mutex& m, bool write = true ) : mutex(NULL) { + acquire(m, write); + } + + //! Release lock (if lock is held). + ~scoped_lock() { + if( mutex ) release(); + } + + //! Acquire lock on given mutex. + void acquire( spin_rw_mutex& m, bool write = true ) { + __TBB_ASSERT( !mutex, "holding mutex already" ); + mutex = &m; + is_writer = write; + if( write ) internal_acquire_writer(mutex); + else internal_acquire_reader(mutex); + } + + //! Upgrade reader to become a writer. + /** Returns whether the upgrade happened without releasing and re-acquiring the lock */ + bool upgrade_to_writer() { + __TBB_ASSERT( mutex, "lock is not acquired" ); + __TBB_ASSERT( !is_writer, "not a reader" ); + is_writer = true; + return internal_upgrade(mutex); + } + + //! Release lock. + void release() { + __TBB_ASSERT( mutex, "lock is not acquired" ); + spin_rw_mutex *m = mutex; + mutex = NULL; + if( is_writer ) { +#if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT + internal_release_writer(m); +#else + m->state = 0; +#endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */ + } else { + internal_release_reader(m); + } + }; + + //! Downgrade writer to become a reader. + bool downgrade_to_reader() { + __TBB_ASSERT( mutex, "lock is not acquired" ); + __TBB_ASSERT( is_writer, "not a writer" ); +#if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT + internal_downgrade(mutex); +#else + mutex->state = 4; // Bit 2 - reader, 00..00100 +#endif + is_writer = false; + return true; + } + + //! Try acquire lock on given mutex. + bool try_acquire( spin_rw_mutex& m, bool write = true ) { + __TBB_ASSERT( !mutex, "holding mutex already" ); + bool result; + is_writer = write; + result = write? internal_try_acquire_writer(&m) + : internal_try_acquire_reader(&m); + if( result ) mutex = &m; + return result; + } + + private: + //! The pointer to the current mutex that is held, or NULL if no mutex is held. + spin_rw_mutex* mutex; + + //! If mutex!=NULL, then is_writer is true if holding a writer lock, false if holding a reader lock. + /** Not defined if not holding a lock. */ + bool is_writer; + }; + +private: + typedef uintptr_t state_t; + static const state_t WRITER = 1; + static const state_t WRITER_PENDING = 2; + static const state_t READERS = ~(WRITER | WRITER_PENDING); + static const state_t ONE_READER = 4; + static const state_t BUSY = WRITER | READERS; + /** Bit 0 = writer is holding lock + Bit 1 = request by a writer to acquire lock (hint to readers to wait) + Bit 2..N = number of readers holding lock */ + volatile state_t state; +}; + +} // namespace tbb + +#endif /* __TBB_spin_rw_mutex_H */ diff --git a/src/tbb/src/old/task_v2.cpp b/src/tbb/src/old/task_v2.cpp new file mode 100644 index 0000000..96dd3d9 --- /dev/null +++ b/src/tbb/src/old/task_v2.cpp @@ -0,0 +1,46 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* This compilation unit provides definition of task::destroy( task& ) + that is binary compatible with TBB 2.x. In TBB 3.0, the method became + static, and its name decoration changed, though the definition remained. + + The macro switch should be set prior to including task.h + or any TBB file that might bring task.h up. +*/ +#define __TBB_DEPRECATED_TASK_INTERFACE 1 +#include "tbb/task.h" + +namespace tbb { + +void task::destroy( task& victim ) { + // Forward to static version + task_base::destroy( victim ); +} + +} // namespace tbb diff --git a/src/tbb/src/old/test_concurrent_queue_v2.cpp b/src/tbb/src/old/test_concurrent_queue_v2.cpp new file mode 100644 index 0000000..9dc24ae --- /dev/null +++ b/src/tbb/src/old/test_concurrent_queue_v2.cpp @@ -0,0 +1,356 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/concurrent_queue.h" +#include "tbb/atomic.h" +#include "tbb/tick_count.h" + +#include "../test/harness_assert.h" +#include "../test/harness.h" + +static tbb::atomic FooConstructed; +static tbb::atomic FooDestroyed; + +class Foo { + enum state_t{ + LIVE=0x1234, + DEAD=0xDEAD + }; + state_t state; +public: + int thread_id; + int serial; + Foo() : state(LIVE) { + ++FooConstructed; + } + Foo( const Foo& item ) : state(LIVE) { + ASSERT( item.state==LIVE, NULL ); + ++FooConstructed; + thread_id = item.thread_id; + serial = item.serial; + } + ~Foo() { + ASSERT( state==LIVE, NULL ); + ++FooDestroyed; + state=DEAD; + thread_id=0xDEAD; + serial=0xDEAD; + } + void operator=( Foo& item ) { + ASSERT( item.state==LIVE, NULL ); + ASSERT( state==LIVE, NULL ); + thread_id = item.thread_id; + serial = item.serial; + } + bool is_const() {return false;} + bool is_const() const {return true;} +}; + +const size_t MAXTHREAD = 256; + +static int Sum[MAXTHREAD]; + +//! Count of various pop operations +/** [0] = pop_if_present that failed + [1] = pop_if_present that succeeded + [2] = pop */ +static tbb::atomic PopKind[3]; + +const int M = 10000; + +struct Body: NoAssign { + tbb::concurrent_queue* queue; + const int nthread; + Body( int nthread_ ) : nthread(nthread_) {} + void operator()( long thread_id ) const { + long pop_kind[3] = {0,0,0}; + int serial[MAXTHREAD+1]; + memset( serial, 0, nthread*sizeof(unsigned) ); + ASSERT( thread_idpop_if_present(f); + ++pop_kind[prepopped]; + } + Foo g; + g.thread_id = thread_id; + g.serial = j+1; + queue->push( g ); + if( !prepopped ) { + queue->pop(f); + ++pop_kind[2]; + } + ASSERT( f.thread_id<=nthread, NULL ); + ASSERT( f.thread_id==nthread || serial[f.thread_id]0, "nthread must be positive" ); + if( prefill+1>=capacity ) + return; + bool success = false; + for( int k=0; k<3; ++k ) + PopKind[k] = 0; + for( int trial=0; !success; ++trial ) { + FooConstructed = 0; + FooDestroyed = 0; + Body body(nthread); + tbb::concurrent_queue queue; + queue.set_capacity( capacity ); + body.queue = &queue; + for( int i=0; i=0; ) { + ASSERT( !queue.empty(), NULL ); + Foo f; + queue.pop(f); + ASSERT( queue.size()==i, NULL ); + sum += f.serial-1; + } + ASSERT( queue.empty(), NULL ); + ASSERT( queue.size()==0, NULL ); + if( sum!=expected ) + printf("sum=%d expected=%d\n",sum,expected); + ASSERT( FooConstructed==FooDestroyed, NULL ); + + success = true; + if( nthread>1 && prefill==0 ) { + // Check that pop_if_present got sufficient exercise + for( int k=0; k<2; ++k ) { +#if (_WIN32||_WIN64) + // The TBB library on Windows seems to have a tough time generating + // the desired interleavings for pop_if_present, so the code tries longer, and settles + // for fewer desired interleavings. + const int max_trial = 100; + const int min_requirement = 20; +#else + const int min_requirement = 100; + const int max_trial = 20; +#endif /* _WIN32||_WIN64 */ + if( PopKind[k]=max_trial ) { + if( Verbose ) + printf("Warning: %d threads had only %ld pop_if_present operations %s after %d trials (expected at least %d). " + "This problem may merely be unlucky scheduling. " + "Investigate only if it happens repeatedly.\n", + nthread, long(PopKind[k]), k==0?"failed":"succeeded", max_trial, min_requirement); + else + printf("Warning: the number of %s pop_if_present operations is less than expected for %d threads. Investigate if it happens repeatedly.\n", + k==0?"failed":"succeeded", nthread ); + } else { + success = false; + } + } + } + } + } +} + +template +void TestIteratorAux( Iterator1 i, Iterator2 j, int size ) { + // Now test iteration + Iterator1 old_i; + for( int k=0; k" + ASSERT( k+2==i->serial, NULL ); + } + // Test assignment + old_i = i; + } + ASSERT( k+1==f.serial, NULL ); + } + ASSERT( !(i!=j), NULL ); + ASSERT( i==j, NULL ); +} + +template +void TestIteratorAssignment( Iterator2 j ) { + Iterator1 i(j); + ASSERT( i==j, NULL ); + ASSERT( !(i!=j), NULL ); + Iterator1 k; + k = j; + ASSERT( k==j, NULL ); + ASSERT( !(k!=j), NULL ); +} + +//! Test the iterators for concurrent_queue +void TestIterator() { + tbb::concurrent_queue queue; + tbb::concurrent_queue& const_queue = queue; + for( int j=0; j<500; ++j ) { + TestIteratorAux( queue.begin(), queue.end(), j ); + TestIteratorAux( const_queue.begin(), const_queue.end(), j ); + TestIteratorAux( const_queue.begin(), queue.end(), j ); + TestIteratorAux( queue.begin(), const_queue.end(), j ); + Foo f; + f.serial = j+1; + queue.push(f); + } + TestIteratorAssignment::const_iterator>( const_queue.begin() ); + TestIteratorAssignment::const_iterator>( queue.begin() ); + TestIteratorAssignment:: iterator>( queue.begin() ); +} + +void TestConcurrentQueueType() { + AssertSameType( tbb::concurrent_queue::value_type(), Foo() ); + Foo f; + const Foo g; + tbb::concurrent_queue::reference r = f; + ASSERT( &r==&f, NULL ); + ASSERT( !r.is_const(), NULL ); + tbb::concurrent_queue::const_reference cr = g; + ASSERT( &cr==&g, NULL ); + ASSERT( cr.is_const(), NULL ); +} + +template +void TestEmptyQueue() { + const tbb::concurrent_queue queue; + ASSERT( queue.size()==0, NULL ); + ASSERT( queue.capacity()>0, NULL ); + ASSERT( size_t(queue.capacity())>=size_t(-1)/(sizeof(void*)+sizeof(T)), NULL ); +} + +void TestFullQueue() { + for( int n=0; n<10; ++n ) { + FooConstructed = 0; + FooDestroyed = 0; + tbb::concurrent_queue queue; + queue.set_capacity(n); + for( int i=0; i<=n; ++i ) { + Foo f; + f.serial = i; + bool result = queue.push_if_not_full( f ); + ASSERT( result==(i +struct TestNegativeQueueBody: NoAssign { + tbb::concurrent_queue& queue; + const int nthread; + TestNegativeQueueBody( tbb::concurrent_queue& q, int n ) : queue(q), nthread(n) {} + void operator()( int k ) const { + if( k==0 ) { + int number_of_pops = nthread-1; + // Wait for all pops to pend. + while( queue.size()>-number_of_pops ) { + __TBB_Yield(); + } + for( int i=0; ; ++i ) { + ASSERT( queue.size()==i-number_of_pops, NULL ); + ASSERT( queue.empty()==(queue.size()<=0), NULL ); + if( i==number_of_pops ) break; + // Satisfy another pop + queue.push( T() ); + } + } else { + // Pop item from queue + T item; + queue.pop(item); + } + } +}; + +//! Test a queue with a negative size. +template +void TestNegativeQueue( int nthread ) { + tbb::concurrent_queue queue; + NativeParallelFor( nthread, TestNegativeQueueBody(queue,nthread) ); +} + +int TestMain () { + TestEmptyQueue(); + TestEmptyQueue(); + TestFullQueue(); + TestConcurrentQueueType(); + TestIterator(); + + // Test concurrent operations + for( int nthread=MinThread; nthread<=MaxThread; ++nthread ) { + TestNegativeQueue(nthread); + for( int prefill=0; prefill<64; prefill+=(1+prefill/3) ) { + TestPushPop(prefill,ptrdiff_t(-1),nthread); + TestPushPop(prefill,ptrdiff_t(1),nthread); + TestPushPop(prefill,ptrdiff_t(2),nthread); + TestPushPop(prefill,ptrdiff_t(10),nthread); + TestPushPop(prefill,ptrdiff_t(100),nthread); + } + } + return Harness::Done; +} diff --git a/src/tbb/src/old/test_concurrent_vector_v2.cpp b/src/tbb/src/old/test_concurrent_vector_v2.cpp new file mode 100644 index 0000000..ad9c12a --- /dev/null +++ b/src/tbb/src/old/test_concurrent_vector_v2.cpp @@ -0,0 +1,566 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "concurrent_vector_v2.h" +#include +#include +#include "../test/harness_assert.h" + +tbb::atomic FooCount; + +//! Problem size +const size_t N = 500000; + +struct Foo { + int my_bar; +public: + enum State { + DefaultInitialized=0x1234, + CopyInitialized=0x89ab, + Destroyed=0x5678 + } state; + int& bar() { + ASSERT( state==DefaultInitialized||state==CopyInitialized, NULL ); + return my_bar; + } + int bar() const { + ASSERT( state==DefaultInitialized||state==CopyInitialized, NULL ); + return my_bar; + } + static const int initial_value_of_bar = 42; + Foo() { + state = DefaultInitialized; + ++FooCount; + my_bar = initial_value_of_bar; + } + Foo( const Foo& foo ) { + state = CopyInitialized; + ++FooCount; + my_bar = foo.my_bar; + } + ~Foo() { + ASSERT( state==DefaultInitialized||state==CopyInitialized, NULL ); + state = Destroyed; + my_bar = ~initial_value_of_bar; + --FooCount; + } + bool is_const() const {return true;} + bool is_const() {return false;} +}; + +class FooWithAssign: public Foo { +public: + void operator=( const FooWithAssign& x ) { + ASSERT( x.state==DefaultInitialized||x.state==CopyInitialized, NULL ); + ASSERT( state==DefaultInitialized||state==CopyInitialized, NULL ); + my_bar = x.my_bar; + } +}; + +inline void NextSize( int& s ) { + if( s<=32 ) ++s; + else s += s/10; +} + +static void CheckVector( const tbb::concurrent_vector& cv, size_t expected_size, size_t old_size ) { + ASSERT( cv.size()==expected_size, NULL ); + ASSERT( cv.empty()==(expected_size==0), NULL ); + for( int j=0; j vector_t; + for( int old_size=0; old_size<=128; NextSize( old_size ) ) { + for( int new_size=old_size; new_size<=128; NextSize( new_size ) ) { + long count = FooCount; + vector_t v; + ASSERT( count==FooCount, NULL ); + v.grow_by(old_size); + ASSERT( count+old_size==FooCount, NULL ); + for( int j=0; j vector_t; + vector_t v; + v.reserve( old_size ); + ASSERT( v.capacity()>=old_size, NULL ); + v.reserve( new_size ); + ASSERT( v.capacity()>=old_size, NULL ); + ASSERT( v.capacity()>=new_size, NULL ); + for( size_t i=0; i<2*new_size; ++i ) { + ASSERT( size_t(FooCount)==count+i, NULL ); + size_t j = v.grow_by(1); + ASSERT( j==i, NULL ); + } + } + ASSERT( FooCount==count, NULL ); + } + } +} + +struct AssignElement { + typedef tbb::concurrent_vector::range_type::iterator iterator; + iterator base; + void operator()( const tbb::concurrent_vector::range_type& range ) const { + for( iterator i=range.begin(); i!=range.end(); ++i ) { + if( *i!=0 ) + std::printf("ERROR for v[%ld]\n", long(i-base)); + *i = int(i-base); + } + } + AssignElement( iterator base_ ) : base(base_) {} +}; + +struct CheckElement { + typedef tbb::concurrent_vector::const_range_type::iterator iterator; + iterator base; + void operator()( const tbb::concurrent_vector::const_range_type& range ) const { + for( iterator i=range.begin(); i!=range.end(); ++i ) + if( *i != int(i-base) ) + std::printf("ERROR for v[%ld]\n", long(i-base)); + } + CheckElement( iterator base_ ) : base(base_) {} +}; + +#include "tbb/tick_count.h" +#include "tbb/parallel_for.h" +#include "../test/harness.h" + +//! Test parallel access by iterators +void TestParallelFor( int nthread ) { + typedef tbb::concurrent_vector vector_t; + vector_t v; + v.grow_to_at_least(N); + tbb::tick_count t0 = tbb::tick_count::now(); + if( Verbose ) + std::printf("Calling parallel_for.h with %ld threads\n",long(nthread)); + tbb::parallel_for( v.range(10000), AssignElement(v.begin()) ); + tbb::tick_count t1 = tbb::tick_count::now(); + const vector_t& u = v; + tbb::parallel_for( u.range(10000), CheckElement(u.begin()) ); + tbb::tick_count t2 = tbb::tick_count::now(); + if( Verbose ) + std::printf("Time for parallel_for.h: assign time = %8.5f, check time = %8.5f\n", + (t1-t0).seconds(),(t2-t1).seconds()); + for( long i=0; size_t(i) +void TestIteratorAssignment( Iterator2 j ) { + Iterator1 i(j); + ASSERT( i==j, NULL ); + ASSERT( !(i!=j), NULL ); + Iterator1 k; + k = j; + ASSERT( k==j, NULL ); + ASSERT( !(k!=j), NULL ); +} + +template +void TestIteratorTraits() { + AssertSameType( static_cast(0), static_cast(0) ); + AssertSameType( static_cast(0), static_cast(0) ); + AssertSameType( static_cast(0), static_cast(0) ); + AssertSameType( static_cast(0), static_cast(0) ); + T x; + typename Iterator::reference xr = x; + typename Iterator::pointer xp = &x; + ASSERT( &xr==xp, NULL ); +} + +template +void CheckConstIterator( const Vector& u, int i, const Iterator& cp ) { + typename Vector::const_reference pref = *cp; + if( pref.bar()!=i ) + std::printf("ERROR for u[%ld] using const_iterator\n", long(i)); + typename Vector::difference_type delta = cp-u.begin(); + ASSERT( delta==i, NULL ); + if( u[i].bar()!=i ) + std::printf("ERROR for u[%ld] using subscripting\n", long(i)); + ASSERT( u.begin()[i].bar()==i, NULL ); +} + +template +void CheckIteratorComparison( V& u ) { + Iterator1 i = u.begin(); + for( int i_count=0; i_count<100; ++i_count ) { + Iterator2 j = u.begin(); + for( int j_count=0; j_count<100; ++j_count ) { + ASSERT( (i==j)==(i_count==j_count), NULL ); + ASSERT( (i!=j)==(i_count!=j_count), NULL ); + ASSERT( (i-j)==(i_count-j_count), NULL ); + ASSERT( (ij)==(i_count>j_count), NULL ); + ASSERT( (i<=j)==(i_count<=j_count), NULL ); + ASSERT( (i>=j)==(i_count>=j_count), NULL ); + ++j; + } + ++i; + } +} + +//! Test sequential iterators for vector type V. +/** Also does timing. */ +template +void TestSequentialFor() { + V v; + v.grow_by(N); + + // Check iterator + tbb::tick_count t0 = tbb::tick_count::now(); + typename V::iterator p = v.begin(); + ASSERT( !(*p).is_const(), NULL ); + ASSERT( !p->is_const(), NULL ); + for( int i=0; size_t(i)is_const(), NULL ); + for( int i=0; size_t(i)0; ) { + --i; + --cp; + if( i>0 ) { + typename V::const_iterator cp_old = cp--; + int here = (*cp_old).bar(); + ASSERT( here==u[i].bar(), NULL ); + typename V::const_iterator cp_new = cp++; + int prev = (*cp_new).bar(); + ASSERT( prev==u[i-1].bar(), NULL ); + } + CheckConstIterator(u,i,cp); + } + + // Now go forwards and backwards + cp = u.begin(); + ptrdiff_t k = 0; + for( size_t i=0; i(v); + CheckIteratorComparison(v); + CheckIteratorComparison(v); + CheckIteratorComparison(v); + + TestIteratorAssignment( u.begin() ); + TestIteratorAssignment( v.begin() ); + TestIteratorAssignment( v.begin() ); + + // Check reverse_iterator + typename V::reverse_iterator rp = v.rbegin(); + for( size_t i=v.size(); i>0; --i, ++rp ) { + typename V::reference pref = *rp; + ASSERT( size_t(pref.bar())==i-1, NULL ); + ASSERT( rp!=v.rend(), NULL ); + } + ASSERT( rp==v.rend(), NULL ); + + // Check const_reverse_iterator + typename V::const_reverse_iterator crp = u.rbegin(); + for( size_t i=v.size(); i>0; --i, ++crp ) { + typename V::const_reference cpref = *crp; + ASSERT( size_t(cpref.bar())==i-1, NULL ); + ASSERT( crp!=u.rend(), NULL ); + } + ASSERT( crp==u.rend(), NULL ); + + TestIteratorAssignment( u.rbegin() ); + TestIteratorAssignment( v.rbegin() ); +} + +static const size_t Modulus = 7; + +typedef tbb::concurrent_vector MyVector; + +class GrowToAtLeast { + MyVector& my_vector; +public: + void operator()( const tbb::blocked_range& range ) const { + for( size_t i=range.begin(); i!=range.end(); ++i ) { + size_t n = my_vector.size(); + size_t k = n==0 ? 0 : i % (2*n+1); + my_vector.grow_to_at_least(k+1); + ASSERT( my_vector.size()>=k+1, NULL ); + } + } + GrowToAtLeast( MyVector& vector ) : my_vector(vector) {} +}; + +void TestConcurrentGrowToAtLeast() { + MyVector v; + for( size_t s=1; s<1000; s*=10 ) { + tbb::parallel_for( tbb::blocked_range(0,1000000,100), GrowToAtLeast(v) ); + } +} + +//! Test concurrent invocations of method concurrent_vector::grow_by +class GrowBy { + MyVector& my_vector; +public: + void operator()( const tbb::blocked_range& range ) const { + for( int i=range.begin(); i!=range.end(); ++i ) { + if( i%3 ) { + Foo& element = my_vector[my_vector.grow_by(1)]; + element.bar() = i; + } else { + Foo f; + f.bar() = i; + size_t k = my_vector.push_back( f ); + ASSERT( my_vector[k].bar()==i, NULL ); + } + } + } + GrowBy( MyVector& vector ) : my_vector(vector) {} +}; + +//! Test concurrent invocations of method concurrent_vector::grow_by +void TestConcurrentGrowBy( int nthread ) { + int m = 100000; + MyVector v; + tbb::parallel_for( tbb::blocked_range(0,m,1000), GrowBy(v) ); + ASSERT( v.size()==size_t(m), NULL ); + + // Verify that v is a permutation of 0..m + int inversions = 0; + bool* found = new bool[m]; + memset( found, 0, m ); + for( int i=0; i0 ) + inversions += v[i].bar()1 || v[i].bar()==i, "sequential execution is wrong" ); + } + delete[] found; + if( nthread>1 && inversions vector_t; + for( int dst_size=1; dst_size<=128; NextSize( dst_size ) ) { + for( int src_size=2; src_size<=128; NextSize( src_size ) ) { + vector_t u; + u.grow_to_at_least(src_size); + for( int i=0; i + +typedef unsigned long Number; + +static tbb::concurrent_vector Primes; + +class FindPrimes { + bool is_prime( Number val ) const { + int limit, factor = 3; + if( val<5u ) + return val==2; + else { + limit = long(sqrtf(float(val))+0.5f); + while( factor<=limit && val % factor ) + ++factor; + return factor>limit; + } + } +public: + void operator()( const tbb::blocked_range& r ) const { + for( Number i=r.begin(); i!=r.end(); ++i ) { + if( i%2 && is_prime(i) ) { + Primes[Primes.grow_by(1)] = i; + } + } + } +}; + +static double TimeFindPrimes( int nthread ) { + Primes.clear(); + tbb::task_scheduler_init init(nthread); + tbb::tick_count t0 = tbb::tick_count::now(); + tbb::parallel_for( tbb::blocked_range(0,1000000,500), FindPrimes() ); + tbb::tick_count t1 = tbb::tick_count::now(); + return (t1-t0).seconds(); +} + +static void TestFindPrimes() { + // Time fully subscribed run. + double t2 = TimeFindPrimes( tbb::task_scheduler_init::automatic ); + + // Time parallel run that is very likely oversubscribed. + double t128 = TimeFindPrimes(128); + + if( Verbose ) + std::printf("TestFindPrimes: t2==%g t128=%g\n", t2, t128 ); + + // We allow the 128-thread run a little extra time to allow for thread overhead. + // Theoretically, following test will fail on machine with >128 processors. + // But that situation is not going to come up in the near future, + // and the generalization to fix the issue is not worth the trouble. + if( t128>1.10*t2 ) { + std::printf("Warning: grow_by is pathetically slow: t2==%g t128=%g\n", t2, t128); + } +} + +//------------------------------------------------------------------------ +// Test compatibility with STL sort. +//------------------------------------------------------------------------ + +#include + +void TestSort() { + for( int n=1; n<100; n*=3 ) { + tbb::concurrent_vector array; + array.grow_by( n ); + for( int i=0; i::iterator,Foo>(); + TestIteratorTraits::const_iterator,const Foo>(); + TestSequentialFor > (); + TestResizeAndCopy(); + TestAssign(); + TestCapacity(); + for( int nthread=MinThread; nthread<=MaxThread; ++nthread ) { + tbb::task_scheduler_init init( nthread ); + TestParallelFor( nthread ); + TestConcurrentGrowToAtLeast(); + TestConcurrentGrowBy( nthread ); + } + TestFindPrimes(); + TestSort(); + return Harness::Done; +} diff --git a/src/tbb/src/old/test_mutex_v2.cpp b/src/tbb/src/old/test_mutex_v2.cpp new file mode 100644 index 0000000..24fb32b --- /dev/null +++ b/src/tbb/src/old/test_mutex_v2.cpp @@ -0,0 +1,248 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +//------------------------------------------------------------------------ +// Test TBB mutexes when used with parallel_for.h +// +// Usage: test_Mutex.exe [-v] nthread +// +// The -v option causes timing information to be printed. +// +// Compile with _OPENMP and -openmp +//------------------------------------------------------------------------ +#include "tbb/atomic.h" +#include "tbb/blocked_range.h" +#include "tbb/parallel_for.h" +#include "tbb/tick_count.h" +#include "../test/harness.h" +#include "spin_rw_mutex_v2.h" +#include +#include + +// This test deliberately avoids a "using tbb" statement, +// so that the error of putting types in the wrong namespace will be caught. + +template +struct Counter { + typedef M mutex_type; + M mutex; + volatile long value; +}; + +//! Function object for use with parallel_for.h. +template +struct AddOne: NoAssign { + C& counter; + /** Increments counter once for each iteration in the iteration space. */ + void operator()( tbb::blocked_range& range ) const { + for( size_t i=range.begin(); i!=range.end(); ++i ) { + if( i&1 ) { + // Try implicit acquire and explicit release + typename C::mutex_type::scoped_lock lock(counter.mutex); + counter.value = counter.value+1; + lock.release(); + } else { + // Try explicit acquire and implicit release + typename C::mutex_type::scoped_lock lock; + lock.acquire(counter.mutex); + counter.value = counter.value+1; + } + } + } + AddOne( C& counter_ ) : counter(counter_) {} +}; + +//! Generic test of a TBB mutex type M. +/** Does not test features specific to reader-writer locks. */ +template +void Test( const char * name ) { + if( Verbose ) { + printf("%s time = ",name); + fflush(stdout); + } + Counter counter; + counter.value = 0; + const int n = 100000; + tbb::tick_count t0 = tbb::tick_count::now(); + tbb::parallel_for(tbb::blocked_range(0,n,n/10),AddOne >(counter)); + tbb::tick_count t1 = tbb::tick_count::now(); + if( Verbose ) + printf("%g usec\n",(t1-t0).seconds()); + if( counter.value!=n ) + printf("ERROR for %s: counter.value=%ld\n",name,counter.value); +} + +template +struct Invariant { + typedef M mutex_type; + M mutex; + const char* mutex_name; + volatile long value[N]; + volatile long single_value; + Invariant( const char* mutex_name_ ) : + mutex_name(mutex_name_) + { + single_value = 0; + for( size_t k=0; k +struct TwiddleInvariant: NoAssign { + I& invariant; + TwiddleInvariant( I& invariant_ ) : invariant(invariant_) {} + + /** Increments counter once for each iteration in the iteration space. */ + void operator()( tbb::blocked_range& range ) const { + for( size_t i=range.begin(); i!=range.end(); ++i ) { + //! Every 8th access is a write access + const bool write = (i%8)==7; + bool okay = true; + bool lock_kept = true; + if( (i/8)&1 ) { + // Try implicit acquire and explicit release + typename I::mutex_type::scoped_lock lock(invariant.mutex,write); + execute_aux(lock, i, write, okay, lock_kept); + lock.release(); + } else { + // Try explicit acquire and implicit release + typename I::mutex_type::scoped_lock lock; + lock.acquire(invariant.mutex,write); + execute_aux(lock, i, write, okay, lock_kept); + } + if( !okay ) { + printf( "ERROR for %s at %ld: %s %s %s %s\n",invariant.mutex_name, long(i), + write ? "write," : "read,", + write ? (i%16==7?"downgrade,":"") : (i%8==3?"upgrade,":""), + lock_kept ? "lock kept," : "lock not kept,", // TODO: only if downgrade/upgrade + (i/8)&1 ? "impl/expl" : "expl/impl" ); + } + } + } +private: + void execute_aux(typename I::mutex_type::scoped_lock & lock, const size_t i, const bool write, bool & okay, bool & lock_kept) const { + if( write ) { + long my_value = invariant.value[0]; + invariant.update(); + if( i%16==7 ) { + lock_kept = lock.downgrade_to_reader(); + if( !lock_kept ) + my_value = invariant.value[0] - 1; + okay = invariant.value_is(my_value+1); + } + } else { + okay = invariant.is_okay(); + if( i%8==3 ) { + long my_value = invariant.value[0]; + lock_kept = lock.upgrade_to_writer(); + if( !lock_kept ) + my_value = invariant.value[0]; + invariant.update(); + okay = invariant.value_is(my_value+1); + } + } + } +}; + +/** This test is generic so that we can test any other kinds of ReaderWriter locks we write later. */ +template +void TestReaderWriterLock( const char * mutex_name ) { + if( Verbose ) { + printf("%s readers & writers time = ",mutex_name); + fflush(stdout); + } + Invariant invariant(mutex_name); + const size_t n = 500000; + tbb::tick_count t0 = tbb::tick_count::now(); + tbb::parallel_for(tbb::blocked_range(0,n,n/100),TwiddleInvariant >(invariant)); + tbb::tick_count t1 = tbb::tick_count::now(); + // There is either a writer or a reader upgraded to a writer for each 4th iteration + long expected_value = n/4; + if( !invariant.value_is(expected_value) ) + printf("ERROR for %s: final invariant value is wrong\n",mutex_name); + if( Verbose ) + printf("%g usec\n", (t1-t0).seconds()); +} + +/** Test try_acquire functionality of a non-reenterable mutex */ +template +void TestTryAcquire_OneThread( const char * mutex_name ) { + M tested_mutex; + typename M::scoped_lock lock1; + if( lock1.try_acquire(tested_mutex) ) + lock1.release(); + else + printf("ERROR for %s: try_acquire failed though it should not\n", mutex_name); + { + typename M::scoped_lock lock2(tested_mutex); + if( lock1.try_acquire(tested_mutex) ) + printf("ERROR for %s: try_acquire succeeded though it should not\n", mutex_name); + } + if( lock1.try_acquire(tested_mutex) ) + lock1.release(); + else + printf("ERROR for %s: try_acquire failed though it should not\n", mutex_name); +} + +#include "tbb/task_scheduler_init.h" + +int TestMain () { + for( int p=MinThread; p<=MaxThread; ++p ) { + tbb::task_scheduler_init init( p ); + if( Verbose ) + printf( "testing with %d workers\n", static_cast(p) ); + const int n = 3; + // Run each test several times. + for( int i=0; i( "Spin RW Mutex" ); + TestTryAcquire_OneThread("Spin RW Mutex"); // only tests try_acquire for writers + TestReaderWriterLock( "Spin RW Mutex" ); + } + if( Verbose ) + printf( "calling destructor for task_scheduler_init\n" ); + } + return Harness::Done; +} diff --git a/src/tbb/src/perf/coarse_grained_raii_lru_cache.h b/src/tbb/src/perf/coarse_grained_raii_lru_cache.h new file mode 100644 index 0000000..b087d94 --- /dev/null +++ b/src/tbb/src/perf/coarse_grained_raii_lru_cache.h @@ -0,0 +1,153 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef coarse_grained_raii_lru_cache_H +#define coarse_grained_raii_lru_cache_H + +#include +#include + +#include "tbb/spin_mutex.h" +#include "tbb/tbb_stddef.h" +template +class coarse_grained_raii_lru_cache : tbb::internal::no_assign{ + typedef value_functor_type value_function_type; + + typedef std::size_t ref_counter_type; + struct map_value_type; + typedef std::map map_storage_type; + typedef std::list lru_list_type; + struct map_value_type { + value_type my_value; + ref_counter_type my_ref_counter; + typename lru_list_type::iterator my_lru_list_iterator; + bool my_is_ready; + + map_value_type (value_type const& a_value, ref_counter_type a_ref_counter, typename lru_list_type::iterator a_lru_list_iterator, bool a_is_ready) + : my_value(a_value), my_ref_counter(a_ref_counter), my_lru_list_iterator (a_lru_list_iterator) + ,my_is_ready(a_is_ready) + {} + }; + + class handle_object; +public: + typedef handle_object handle; + + coarse_grained_raii_lru_cache(value_function_type f, std::size_t number_of_lru_history_items): my_value_function(f),my_number_of_lru_history_items(number_of_lru_history_items){} + handle_object operator[](key_type k){ + tbb::spin_mutex::scoped_lock lock(my_mutex); + bool is_new_value_needed = false; + typename map_storage_type::iterator it = my_map_storage.find(k); + if (it == my_map_storage.end()){ + it = my_map_storage.insert(it,std::make_pair(k,map_value_type(value_type(),0,my_lru_list.end(),false))); + is_new_value_needed = true; + }else { + typename lru_list_type::iterator list_it = it->second.my_lru_list_iterator; + if (list_it!=my_lru_list.end()) { + my_lru_list.erase(list_it); + it->second.my_lru_list_iterator= my_lru_list.end(); + } + } + typename map_storage_type::reference value_ref = *it; + //increase ref count + ++(value_ref.second.my_ref_counter); + if (is_new_value_needed){ + lock.release(); + value_ref.second.my_value = my_value_function(k); + __TBB_store_with_release(value_ref.second.my_is_ready, true); + + }else{ + if (!value_ref.second.my_is_ready){ + lock.release(); + tbb::internal::spin_wait_while_eq(value_ref.second.my_is_ready,false); + } + } + return handle_object(*this,(value_ref)); + } +private: + void signal_end_of_usage(typename map_storage_type::reference value_ref){ + tbb::spin_mutex::scoped_lock lock(my_mutex); + typename map_storage_type::iterator it = my_map_storage.find(value_ref.first); + __TBB_ASSERT(it!=my_map_storage.end(),"cache should not return past-end iterators to outer world"); + __TBB_ASSERT(&(*it) == &value_ref,"dangling reference has been returned to outside world? data race ?"); + __TBB_ASSERT( my_lru_list.end()== std::find(my_lru_list.begin(),my_lru_list.end(),it), + "object in use should not be in list of unused objects "); + if (! --(it->second.my_ref_counter)){ //decrease ref count, and check if it was the last reference + if (my_lru_list.size()>=my_number_of_lru_history_items){ + size_t number_of_elements_to_evict = 1 + my_lru_list.size() - my_number_of_lru_history_items; + for (size_t i=0; isecond.my_lru_list_iterator = my_lru_list.begin(); + } + } +private: + value_function_type my_value_function; + std::size_t const my_number_of_lru_history_items; + map_storage_type my_map_storage; + lru_list_type my_lru_list; + tbb::spin_mutex my_mutex; +private: + struct handle_move_t:tbb::internal::no_assign{ + coarse_grained_raii_lru_cache & my_cache_ref; + typename map_storage_type::reference my_value_ref; + handle_move_t(coarse_grained_raii_lru_cache & cache_ref, typename map_storage_type::reference value_ref):my_cache_ref(cache_ref),my_value_ref(value_ref) {}; + }; + class handle_object { + coarse_grained_raii_lru_cache * my_cache_pointer; + typename map_storage_type::reference my_value_ref; + public: + handle_object(coarse_grained_raii_lru_cache & cache_ref, typename map_storage_type::reference value_ref):my_cache_pointer(&cache_ref), my_value_ref(value_ref) {} + handle_object(handle_move_t m):my_cache_pointer(&m.my_cache_ref), my_value_ref(m.my_value_ref){} + operator handle_move_t(){ return move(*this);} + value_type& value(){return my_value_ref.second.my_value;} + ~handle_object(){ + if (my_cache_pointer){ + my_cache_pointer->signal_end_of_usage(my_value_ref); + } + } + private: + friend handle_move_t move(handle_object& h){ + return handle_object::move(h); + } + static handle_move_t move(handle_object& h){ + __TBB_ASSERT(h.my_cache_pointer,"move from the same object twice ?"); + coarse_grained_raii_lru_cache * cache_pointer = NULL; + std::swap(cache_pointer,h.my_cache_pointer); + return handle_move_t(*cache_pointer,h.my_value_ref); + } + private: + void operator=(handle_object&); + handle_object(handle_object &); + }; +}; +#endif //coarse_grained_raii_lru_cache_H diff --git a/src/tbb/src/perf/fibonacci_cutoff.cpp b/src/tbb/src/perf/fibonacci_cutoff.cpp new file mode 100644 index 0000000..0da712f --- /dev/null +++ b/src/tbb/src/perf/fibonacci_cutoff.cpp @@ -0,0 +1,134 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include +#include + +#include "tbb/task_scheduler_init.h" +#include "tbb/task.h" +#include "tbb/tick_count.h" + +long CutOff = 1; + +long SerialFib( const long n ); + +long ParallelFib( const long n ); + +inline void dump_title() { + printf("Serial/Parallel, P, N, cutoff, repetitions, time, fib, speedup\n"); +} + +inline void output(int P, long n, long c, int T, double serial_elapsed, double elapsed, long result) { + printf("%s, %d, %ld, %ld, %d, %g, %ld, %g\n", ( (P == 0) ? "Serial" : "Parallel" ), P, n, c, T, elapsed, result, serial_elapsed / elapsed); +} + +#define MOVE_BY_FOURTHS 1 +inline long calculate_new_cutoff(const long lo, const long hi) { +#if MOVE_BY_FOURTHS + return lo + (3 + hi - lo ) / 4; +#else + return (hi + lo)/2; +#endif +} + +void find_cutoff(const int P, const long n, const int T, const double serial_elapsed) { + long lo = 1, hi = n; + double elapsed = 0, lo_elapsed = 0, hi_elapsed = 0; + long final_cutoff = -1; + + tbb::task_scheduler_init init(P); + + while(true) { + CutOff = calculate_new_cutoff(lo, hi); + long result = 0; + tbb::tick_count t0; + for (int t = -1; t < T; ++t) { + if (t == 0) t0 = tbb::tick_count::now(); + result += ParallelFib(n); + } + elapsed = (tbb::tick_count::now() - t0).seconds(); + output(P,n,CutOff,T,serial_elapsed,elapsed,result); + + if (serial_elapsed / elapsed >= P/2.0) { + final_cutoff = CutOff; + if (hi == CutOff) { + if (hi == lo) { + // we have had this value at both above and below 50% + lo = 1; lo_elapsed = 0; + } else { + break; + } + } + hi = CutOff; + hi_elapsed = elapsed; + } else { + if (lo == CutOff) break; + lo = CutOff; + lo_elapsed = elapsed; + } + } + + double interpolated_cutoff = lo + ( P/2.0 - serial_elapsed/lo_elapsed ) * ( (hi - lo) / ( serial_elapsed/hi_elapsed - serial_elapsed/lo_elapsed )); + + if (final_cutoff != -1) { + printf("50%% efficiency cutoff is %ld ( linearly interpolated cutoff is %g )\n", final_cutoff, interpolated_cutoff); + } else { + printf("Cannot achieve 50%% efficiency\n"); + } + + return; +} + +int main(int argc, char *argv[]) { + if (argc < 4) { + printf("Usage: %s threads n repetitions\n",argv[0]); + return 1; + } + + dump_title(); + + int P = atoi(argv[1]); + long n = atol(argv[2]); + int T = atoi(argv[3]); + + // collect serial time + long serial_result = 0; + tbb::tick_count t0; + for (int t = -1; t < T; ++t) { + if (t == 0) t0 = tbb::tick_count::now(); + serial_result += SerialFib(n); + } + double serial_elapsed = (tbb::tick_count::now() - t0).seconds(); + output(0,n,0,T,serial_elapsed,serial_elapsed,serial_result); + + // perform search + find_cutoff(P,n,T,serial_elapsed); + + return 0; +} + diff --git a/src/tbb/src/perf/fibonacci_impl_tbb.cpp b/src/tbb/src/perf/fibonacci_impl_tbb.cpp new file mode 100644 index 0000000..c33471a --- /dev/null +++ b/src/tbb/src/perf/fibonacci_impl_tbb.cpp @@ -0,0 +1,86 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include +#include + +#include "tbb/task_scheduler_init.h" +#include "tbb/task.h" +#include "tbb/tick_count.h" + +extern long CutOff; + +long SerialFib( const long n ) { + if( n<2 ) + return n; + else + return SerialFib(n-1)+SerialFib(n-2); +} + +struct FibContinuation: public tbb::task { + long* const sum; + long x, y; + FibContinuation( long* sum_ ) : sum(sum_) {} + tbb::task* execute() { + *sum = x+y; + return NULL; + } +}; + +struct FibTask: public tbb::task { + long n; + long * sum; + FibTask( const long n_, long * const sum_ ) : + n(n_), sum(sum_) + {} + tbb::task* execute() { + if( n +#include +#include +#include +#include + +#include "tbb/tick_count.h" + +#define HARNESS_CUSTOM_MAIN 1 +#include "../src/test/harness.h" +#include "../src/test/harness_barrier.h" + +#include "tbb/task_scheduler_init.h" +#include "tbb/task.h" +#include "tbb/atomic.h" + +#if __linux__ || __APPLE__ || __FreeBSD__ || __NetBSD__ + #include +#endif + +__TBB_PERF_API int NumCpus = tbb::task_scheduler_init::default_num_threads(), + NumThreads, + MaxConcurrency; + +namespace Perf { + +SessionSettings theSettings; + +namespace internal { + + typedef std::vector durations_t; + + static uintptr_t NumRuns = 7; + static duration_t RunDuration = 0.01; + + static const int RateFieldLen = 10; + static const int OvhdFieldLen = 12; + + const char* TestNameColumnTitle = "Test name"; + const char* WorkloadNameColumnTitle = "Workload"; + + size_t TitleFieldLen = 0; + size_t WorkloadFieldLen = 0; + + int TotalConfigs = 0; + int MaxTbbMasters = 1; + + //! Defines the mapping between threads and cores in the undersubscription mode + /** When adding new enumerator, insert it before amLast, and do not specify + its value explicitly. **/ + enum AffinitizationMode { + amFirst = 0, + amDense = amFirst, + amSparse, + //! Used to track the number of supported affinitization modes + amLast + }; + + static const int NumAffinitizationModes = amLast - amFirst; + + const char* AffinitizationModeNames[] = { "dense", "sparse" }; + + int NumActiveAffModes = 1; + + //! Settings of a test run configuration + struct RunConfig { + int my_maxConcurrency; + int my_numThreads; // For task scheduler tests this is number of workers + 1 + int my_numMasters; // Used for task scheduler tests only + int my_affinityMode; // Used for task scheduler tests only + int my_workloadID; + + int NumMasters () const { + return theSettings.my_opts & UseTaskScheduler ? my_numMasters : my_numThreads; + } + }; + + double StandardDeviation ( double avg, const durations_t& d ) { + double std_dev = 0; + for ( uintptr_t i = 0; i < d.size(); ++i ) { + double dev = fabs(d[i] - avg); + std_dev += dev * dev; + } + std_dev = sqrt(std_dev / d.size()); + return std_dev / avg * 100; + } + + void Statistics ( const durations_t& d, + duration_t& avgTime, double& stdDev, + duration_t& minTime, duration_t& maxTime ) + { + minTime = maxTime = avgTime = d[0]; + for ( size_t i = 1; i < d.size(); ++i ) { + avgTime += d[i]; + if ( minTime > d[i] ) + minTime = d[i]; + else if ( maxTime < d[i] ) + maxTime = d[i]; + } + avgTime = avgTime / d.size(); + stdDev = StandardDeviation( avgTime, d ); + } + + //! Timing data for the series of repeated runs and results of their statistical processing + struct TimingSeries { + //! Statistical timing series + durations_t my_durations; + + //! Average time obtained from my_durations data + duration_t my_avgTime; + + //! Minimal time obtained from my_durations data + duration_t my_minTime; + + //! Minimal time obtained from my_durations data + duration_t my_maxTime; + + //! Standard deviation of my_avgTime value (per cent) + double my_stdDev; + + TimingSeries ( uintptr_t nruns = NumRuns ) + : my_durations(nruns), my_avgTime(0), my_minTime(0), my_maxTime(0) + {} + + void CalculateStatistics () { + Statistics( my_durations, my_avgTime, my_stdDev, my_minTime, my_maxTime ); + } + }; // struct TimingSeries + + //! Settings and timing results for a test run configuration + struct RunResults { + //! Run configuration settings + RunConfig my_config; + + //! Timing results for this run configuration + TimingSeries my_timing; + }; + + typedef std::vector names_t; + typedef std::vector timings_t; + typedef std::vector test_results_t; + + enum TestMethods { + idRunSerial = 0x01, + idOnStart = 0x02, + idOnFinish = 0x04, + idPrePostProcess = idOnStart | idOnFinish + }; + + //! Set of flags identifying methods not overridden by the currently active test + /** Used as a scratch var. **/ + uintptr_t g_absentMethods; + + //! Test object and timing results for all of its configurations + struct TestResults { + //! Pointer to the test object interface + Test* my_test; + + //! Set of flags identifying optional methods overridden by my_test + /** A set of ORed TestMethods flags **/ + uintptr_t my_availableMethods; + + //! Vector of serial times for each workload supported by this test + /** Element index in the vector serves as a zero based workload ID. **/ + timings_t my_serialBaselines; + + //! Common baselines for both parallel and serial variants + /** Element index in the vector serves as a zero based workload ID. **/ + timings_t my_baselines; + + //! Strings identifying workloads to be used in output + names_t my_workloadNames; + + //! Vector of timings for all run configurations of my_test + test_results_t my_results; + + const char* my_testName; + + mutable bool my_hasOwnership; + + TestResults ( Test* t, const char* className, bool takeOwnership ) + : my_test(t), my_availableMethods(0), my_testName(className), my_hasOwnership(takeOwnership) + {} + + TestResults ( const TestResults& tr ) + : my_test(tr.my_test) + , my_availableMethods(0) + , my_testName(tr.my_testName) + , my_hasOwnership(tr.my_hasOwnership) + { + tr.my_hasOwnership = false; + } + + ~TestResults () { + for ( size_t i = 0; i < my_workloadNames.size(); ++i ) + delete my_workloadNames[i]; + if ( my_hasOwnership ) + delete my_test; + } + }; // struct TestResults + + typedef std::vector session_t; + + session_t theSession; + + TimingSeries CalibrationTiming; + + const uintptr_t CacheSize = 8*1024*1024; + volatile intptr_t W[CacheSize]; + + struct WiperBody { + void operator()( int ) const { + volatile intptr_t sink = 0; + for ( uintptr_t i = 0; i < CacheSize; ++i ) + sink += W[i]; + } + }; + + void TraceHistogram ( const durations_t& t, const char* histogramFileName ) { + FILE* f = histogramFileName ? fopen(histogramFileName, "wt") : stdout; + uintptr_t n = t.size(); + const uintptr_t num_buckets = 100; + double min_val = *std::min_element(t.begin(), t.end()), + max_val = *std::max_element(t.begin(), t.end()), + bucket_size = (max_val - min_val) / num_buckets; + std::vector hist(num_buckets + 1, 0); + for ( uintptr_t i = 0; i < n; ++i ) + ++hist[uintptr_t((t[i]-min_val)/bucket_size)]; + ASSERT (hist[num_buckets] == 1, ""); + ++hist[num_buckets - 1]; + hist.resize(num_buckets); + fprintf (f, "Histogram: nvals = %u, min = %g, max = %g, nbuckets = %u\n", (unsigned)n, min_val, max_val, (unsigned)num_buckets); + double bucket = min_val; + for ( uintptr_t i = 0; i < num_buckets; ++i, bucket+=bucket_size ) + fprintf (f, "%12g\t%u\n", bucket, (unsigned)hist[i]); + fclose(f); + } + +#if _MSC_VER + typedef DWORD_PTR cpu_set_t; + + class AffinityHelper { + static const unsigned MaxAffinitySetSize = sizeof(cpu_set_t) * 8; + static unsigned AffinitySetSize; + + //! Mapping from a CPU index to a valid affinity cpu_mask + /** The first element is not used. **/ + static cpu_set_t m_affinities[MaxAffinitySetSize + 1]; + + static cpu_set_t m_processMask; + + class Initializer { + public: + Initializer () { + SYSTEM_INFO si; + GetSystemInfo(&si); + ASSERT( si.dwNumberOfProcessors <= MaxAffinitySetSize, "Too many CPUs" ); + AffinitySetSize = min (si.dwNumberOfProcessors, MaxAffinitySetSize); + cpu_set_t systemMask = 0; + GetProcessAffinityMask( GetCurrentProcess(), &m_processMask, &systemMask ); + cpu_set_t cpu_mask = 1; + for ( DWORD i = 0; i < AffinitySetSize; ++i ) { + while ( !(cpu_mask & m_processMask) && cpu_mask ) + cpu_mask <<= 1; + ASSERT( cpu_mask != 0, "Process affinity set is culled?" ); + m_affinities[i] = cpu_mask; + cpu_mask <<= 1; + } + } + }; // class AffinityHelper::Initializer + + static Initializer m_initializer; + + public: + static cpu_set_t CpuAffinity ( int cpuIndex ) { + return m_affinities[cpuIndex % AffinitySetSize]; + } + + static const cpu_set_t& ProcessMask () { return m_processMask; } + }; // class AffinityHelper + + unsigned AffinityHelper::AffinitySetSize = 0; + cpu_set_t AffinityHelper::m_affinities[AffinityHelper::MaxAffinitySetSize + 1] = {0}; + cpu_set_t AffinityHelper::m_processMask = 0; + AffinityHelper::Initializer AffinityHelper::m_initializer; + + #define CPU_ZERO(cpu_mask) (*cpu_mask = 0) + #define CPU_SET(cpu_idx, cpu_mask) (*cpu_mask |= AffinityHelper::CpuAffinity(cpu_idx)) + #define CPU_CLR(cpu_idx, cpu_mask) (*cpu_mask &= ~AffinityHelper::CpuAffinity(cpu_idx)) + #define CPU_ISSET(cpu_idx, cpu_mask) ((*cpu_mask & AffinityHelper::CpuAffinity(cpu_idx)) != 0) + +#elif __linux__ /* end of _MSC_VER */ + + #include + #include + #include + + pid_t gettid() { return (pid_t)syscall(__NR_gettid); } + + #define GET_MASK(cpu_set) (*(unsigned*)(void*)&cpu_set) + #define RES_STAT(res) (res != 0 ? "failed" : "ok") + + class AffinityHelper { + static cpu_set_t m_processMask; + + class Initializer { + public: + Initializer () { + CPU_ZERO (&m_processMask); + int res = sched_getaffinity( getpid(), sizeof(cpu_set_t), &m_processMask ); + ASSERT ( res == 0, "sched_getaffinity failed" ); + } + }; // class AffinityHelper::Initializer + + static Initializer m_initializer; + + public: + static const cpu_set_t& ProcessMask () { return m_processMask; } + }; // class AffinityHelper + + cpu_set_t AffinityHelper::m_processMask; + AffinityHelper::Initializer AffinityHelper::m_initializer; +#endif /* __linux__ */ + + bool PinTheThread ( int cpu_idx, tbb::atomic& nThreads ) { + cpu_set_t orig_mask, target_mask; + CPU_ZERO( &target_mask ); + CPU_SET( cpu_idx, &target_mask ); + ASSERT ( CPU_ISSET(cpu_idx, &target_mask), "CPU_SET failed" ); + #if _MSC_VER + orig_mask = SetThreadAffinityMask( GetCurrentThread(), target_mask ); + if ( !orig_mask ) + return false; + #elif __linux__ + CPU_ZERO( &orig_mask ); + int res = sched_getaffinity( gettid(), sizeof(cpu_set_t), &orig_mask ); + ASSERT ( res == 0, "sched_getaffinity failed" ); + res = sched_setaffinity( gettid(), sizeof(cpu_set_t), &target_mask ); + ASSERT ( res == 0, "sched_setaffinity failed" ); + #endif /* _MSC_VER */ + --nThreads; + while ( nThreads ) + __TBB_Yield(); + #if _MSC_VER + SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_HIGHEST); + #endif + return true; + } + + class AffinitySetterTask : tbb::task { + static bool m_result; + static tbb::atomic m_nThreads; + int m_idx; + + tbb::task* execute () { + //TestAffinityOps(); + m_result = PinTheThread( m_idx, m_nThreads ); + return NULL; + } + + public: + AffinitySetterTask ( int idx ) : m_idx(idx) {} + + friend bool AffinitizeTBB ( int, int /*mode*/ ); + }; + + bool AffinitySetterTask::m_result = true; + tbb::atomic AffinitySetterTask::m_nThreads; + + bool AffinitizeTBB ( int p, int affMode ) { + #if _MSC_VER + SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_HIGHEST); + SetPriorityClass (GetCurrentProcess(), HIGH_PRIORITY_CLASS); + #endif + AffinitySetterTask::m_result = true; + AffinitySetterTask::m_nThreads = p; + tbb::task_list tl; + for ( int i = 0; i < p; ++i ) { + tbb::task &t = *new( tbb::task::allocate_root() ) AffinitySetterTask( affMode == amSparse ? i * NumCpus / p : i ); + t.set_affinity( tbb::task::affinity_id(i + 1) ); + tl.push_back( t ); + } + tbb::task::spawn_root_and_wait(tl); + return AffinitySetterTask::m_result; + } + + inline + void Affinitize ( int p, int affMode ) { + if ( !AffinitizeTBB (p, affMode) ) + REPORT("Warning: Failed to set affinity for %d TBB threads\n", p); + } + + class TbbWorkersTrapper { + tbb::atomic my_refcount; + tbb::task *my_root; + tbb::task_group_context my_context; + Harness::SpinBarrier my_barrier; + + friend class TrapperTask; + + class TrapperTask : public tbb::task { + TbbWorkersTrapper& my_owner; + + tbb::task* execute () { + my_owner.my_barrier.wait(); + my_owner.my_root->wait_for_all(); + my_owner.my_barrier.wait(); + return NULL; + } + public: + TrapperTask ( TbbWorkersTrapper& owner ) : my_owner(owner) {} + }; + + public: + TbbWorkersTrapper () + : my_context(tbb::task_group_context::bound, + tbb::task_group_context::default_traits | tbb::task_group_context::concurrent_wait) + { + my_root = new ( tbb::task::allocate_root(my_context) ) tbb::empty_task; + my_root->set_ref_count(2); + my_barrier.initialize(NumThreads); + for ( int i = 1; i < NumThreads; ++i ) + tbb::task::spawn( *new(tbb::task::allocate_root()) TrapperTask(*this) ); + my_barrier.wait(); // Wait util all workers are ready + } + + ~TbbWorkersTrapper () { + my_root->decrement_ref_count(); + my_barrier.wait(); // Make sure no tasks are referencing us + tbb::task::destroy(*my_root); + } + }; // TbbWorkersTrapper + + +#if __TBB_STATISTICS + static bool StatisticsMode = true; +#else + static bool StatisticsMode = false; +#endif + +//! Suppresses silly warning +inline bool __TBB_bool( bool b ) { return b; } + +#define START_WORKERS(needScheduler, p, a, setWorkersAffinity, trapWorkers) \ + tbb::task_scheduler_init init(tbb::task_scheduler_init::deferred); \ + TbbWorkersTrapper *trapper = NULL; \ + if ( theSettings.my_opts & UseTaskScheduler \ + && (needScheduler) && ((setWorkersAffinity) || (trapWorkers)) ) \ + { \ + init.initialize( p ); \ + if ( __TBB_bool(setWorkersAffinity) ) \ + Affinitize( p, a ); \ + if ( __TBB_bool(trapWorkers) ) \ + trapper = new TbbWorkersTrapper; \ + } + +#define STOP_WORKERS() \ + if ( theSettings.my_opts & UseTaskScheduler && init.is_active() ) { \ + if ( trapper ) \ + delete trapper; \ + init.terminate(); \ + /* Give asynchronous deinitialization time to complete */ \ + Harness::Sleep(50); \ + } + + typedef void (Test::*RunMemFnPtr)( Test::ThreadInfo& ); + + TimingSeries *TlsTimings; + Harness::SpinBarrier multipleMastersBarrier; + + class TimingFunctor { + Test* my_test; + RunConfig *my_cfg; + RunMemFnPtr my_fnRun; + size_t my_numRuns; + size_t my_numRepeats; + uintptr_t my_availableMethods; + + duration_t TimeSingleRun ( Test::ThreadInfo& ti ) const { + if ( my_availableMethods & idOnStart ) + my_test->OnStart(ti); + // Warming run + (my_test->*my_fnRun)(ti); + multipleMastersBarrier.wait(); + tbb::tick_count t0 = tbb::tick_count::now(); + (my_test->*my_fnRun)(ti); + duration_t t = (tbb::tick_count::now() - t0).seconds(); + if ( my_availableMethods & idOnFinish ) + my_test->OnFinish(ti); + return t; + } + + public: + TimingFunctor ( Test* test, RunConfig *cfg, RunMemFnPtr fnRun, + size_t numRuns, size_t nRepeats, uintptr_t availableMethods ) + : my_test(test), my_cfg(cfg), my_fnRun(fnRun) + , my_numRuns(numRuns), my_numRepeats(nRepeats), my_availableMethods(availableMethods) + {} + + void operator()( int tid ) const { + Test::ThreadInfo ti = { tid, NULL }; + durations_t &d = TlsTimings[tid].my_durations; + bool singleMaster = my_cfg->my_numMasters == 1; + START_WORKERS( (!singleMaster || (singleMaster && StatisticsMode)) && my_fnRun != &Test::RunSerial, + my_cfg->my_numThreads, my_cfg->my_affinityMode, singleMaster, singleMaster ); + for ( uintptr_t k = 0; k < my_numRuns; ++k ) { + if ( my_numRepeats > 1 ) { + d[k] = 0; + if ( my_availableMethods & idPrePostProcess ) { + for ( uintptr_t i = 0; i < my_numRepeats; ++i ) + d[k] += TimeSingleRun(ti); + } + else { + multipleMastersBarrier.wait(); + tbb::tick_count t0 = tbb::tick_count::now(); + for ( uintptr_t i = 0; i < my_numRepeats; ++i ) + (my_test->*my_fnRun)(ti); + d[k] = (tbb::tick_count::now() - t0).seconds(); + } + d[k] /= my_numRepeats; + } + else + d[k] = TimeSingleRun(ti); + } + STOP_WORKERS(); + TlsTimings[tid].CalculateStatistics(); + } + }; // class TimingFunctor + + void DoTiming ( TestResults& tr, RunConfig &cfg, RunMemFnPtr fnRun, size_t nRepeats, TimingSeries& ts ) { + int numThreads = cfg.NumMasters(); + size_t numRuns = ts.my_durations.size() / numThreads; + TimingFunctor body( tr.my_test, &cfg, fnRun, numRuns, nRepeats, tr.my_availableMethods ); + multipleMastersBarrier.initialize(numThreads); + tr.my_test->SetWorkload(cfg.my_workloadID); + if ( numThreads == 1 ) { + TimingSeries *t = TlsTimings; + TlsTimings = &ts; + body(0); + TlsTimings = t; + } + else { + ts.my_durations.resize(numThreads * numRuns); + NativeParallelFor( numThreads, body ); + for ( int i = 0, j = 0; i < numThreads; ++i ) { + durations_t &d = TlsTimings[i].my_durations; + for ( size_t k = 0; k < numRuns; ++k, ++j ) + ts.my_durations[j] = d[k]; + } + ts.CalculateStatistics(); + } + } + + //! Runs the test function, does statistical processing, and, if title is nonzero, prints results. + /** If histogramFileName is a string, the histogram of individual runs is generated and stored + in a file with the given name. If it is NULL then the histogram is printed on the console. + By default no histogram is generated. + The histogram format is: "rate bucket start" "number of tests in this bucket". **/ + void RunTestImpl ( TestResults& tr, RunConfig &cfg, RunMemFnPtr pfnTest, TimingSeries& ts ) { + // nRepeats is a number of repeated calls to the test function made as + // part of the same run. It is determined experimentally by the following + // calibration process so that the total run time was approx. RunDuration. + // This is helpful to increase the measurement precision in case of very + // short tests. + size_t nRepeats = 1; + // A minimal stats is enough when doing calibration + CalibrationTiming.my_durations.resize( (NumRuns < 4 ? NumRuns : 3) * cfg.NumMasters() ); + // There's no need to be too precise when calculating nRepeats. And reasonably + // far extrapolation can speed up the process significantly. + for (;;) { + DoTiming( tr, cfg, pfnTest, nRepeats, CalibrationTiming ); + if ( CalibrationTiming.my_avgTime * nRepeats > 1e-4 ) + break; + nRepeats *= 2; + } + nRepeats *= (uintptr_t)ceil( RunDuration / (CalibrationTiming.my_avgTime * nRepeats) ); + + DoTiming(tr, cfg, pfnTest, nRepeats, ts); + + // No histogram for baseline measurements + if ( pfnTest != &Test::RunSerial && pfnTest != &Test::Baseline ) { + const char* histogramName = theSettings.my_histogramName; + if ( histogramName != NoHistogram && tr.my_test->HistogramName() != DefaultHistogram ) + histogramName = tr.my_test->HistogramName(); + if ( histogramName != NoHistogram ) + TraceHistogram( ts.my_durations, histogramName ); + } + } // RunTestImpl + + typedef void (*TestActionFn) ( TestResults&, int mastersRange, int w, int p, int m, int a, int& numTests ); + + int TestResultIndex ( int mastersRange, int w, int p, int m, int a ) { + return ((w * (MaxThread - MinThread + 1) + (p - MinThread)) * mastersRange + m) * NumActiveAffModes + a; + } + + void RunTest ( TestResults& tr, int mastersRange, int w, int p, int m, int a, int& numTests ) { + size_t r = TestResultIndex(mastersRange, w, p, m, a); + ASSERT( r < tr.my_results.size(), NULL ); + RunConfig &rc = tr.my_results[r].my_config; + rc.my_maxConcurrency = MaxConcurrency; + rc.my_numThreads = p; + rc.my_numMasters = m + tr.my_test->MinNumMasters(); + rc.my_affinityMode = a; + rc.my_workloadID = w; + RunTestImpl( tr, rc, &Test::Run, tr.my_results[r].my_timing ); + printf( "Running tests: %04.1f%%\r", ++numTests * 100. / TotalConfigs ); fflush(stdout); + } + + void WalkTests ( TestActionFn fn, int& numTests, bool setAffinity, bool trapWorkers, bool multipleMasters ) { + for ( int p = MinThread; p <= MaxThread; ++p ) { + NumThreads = p; + MaxConcurrency = p < NumCpus ? p : NumCpus; + for ( int a = 0; a < NumActiveAffModes; ++a ) { + START_WORKERS( multipleMasters || !StatisticsMode, p, a, setAffinity, trapWorkers ); + for ( size_t i = 0; i < theSession.size(); ++i ) { + TestResults &tr = theSession[i]; + Test *t = tr.my_test; + int mastersRange = t->MaxNumMasters() - t->MinNumMasters() + 1; + int numWorkloads = theSettings.my_opts & UseSmallestWorkloadOnly ? 1 : t->NumWorkloads(); + for ( int w = 0; w < numWorkloads; ++w ) { + if ( multipleMasters ) + for ( int m = 1; m < mastersRange; ++m ) + fn( tr, mastersRange, w, p, m, a, numTests ); + else + fn( tr, mastersRange, w, p, 0, a, numTests ); + } + } + STOP_WORKERS(); + } + } + } + + void RunTests () { + int numTests = 0; + WalkTests( &RunTest, numTests, !StatisticsMode, !StatisticsMode, false ); + if ( MaxTbbMasters > 1 ) + WalkTests( &RunTest, numTests, true, false, true ); + } + + void InitTestData ( TestResults& tr, int mastersRange, int w, int p, int m, int a, int& ) { + size_t r = TestResultIndex(mastersRange, w, p, m, a); + ASSERT( r < tr.my_results.size(), NULL ); + tr.my_results[r].my_timing.my_durations.resize( + (theSettings.my_opts & UseTaskScheduler ? tr.my_test->MinNumMasters() + m : p) * NumRuns ); + } + + char WorkloadName[MaxWorkloadNameLen + 1]; + + void PrepareTests () { + printf( "Initializing...\r" ); + NumActiveAffModes = theSettings.my_opts & UseAffinityModes ? NumAffinitizationModes : 1; + TotalConfigs = 0; + TitleFieldLen = strlen( TestNameColumnTitle ); + WorkloadFieldLen = strlen( WorkloadNameColumnTitle ); + int numThreads = MaxThread - MinThread + 1; + int numConfigsBase = numThreads * NumActiveAffModes; + int totalWorkloads = 0; + for ( size_t i = 0; i < theSession.size(); ++i ) { + TestResults &tr = theSession[i]; + Test &t = *tr.my_test; + int numWorkloads = theSettings.my_opts & UseSmallestWorkloadOnly ? 1 : t.NumWorkloads(); + int numConfigs = numConfigsBase * numWorkloads; + if ( t.MaxNumMasters() > 1 ) { + ASSERT( theSettings.my_opts & UseTaskScheduler, "Multiple masters mode is only valid for task scheduler tests" ); + if ( MaxTbbMasters < t.MaxNumMasters() ) + MaxTbbMasters = t.MaxNumMasters(); + numConfigs *= t.MaxNumMasters() - t.MinNumMasters() + 1; + } + totalWorkloads += numWorkloads; + TotalConfigs += numConfigs; + + const char* testName = t.Name(); + if ( testName ) + tr.my_testName = testName; + ASSERT( tr.my_testName, "Neither Test::Name() is implemented, nor RTTI is enabled" ); + TitleFieldLen = max( TitleFieldLen, strlen(tr.my_testName) ); + + tr.my_results.resize( numConfigs ); + tr.my_serialBaselines.resize( numWorkloads ); + tr.my_baselines.resize( numWorkloads ); + tr.my_workloadNames.resize( numWorkloads ); + } + TimingSeries tmpTiming; + TlsTimings = &tmpTiming; // All measurements are serial here + int n = 0; + for ( size_t i = 0; i < theSession.size(); ++i ) { + TestResults &tr = theSession[i]; + Test &t = *tr.my_test; + // Detect which methods are overridden by the test implementation + g_absentMethods = 0; + Test::ThreadInfo ti = { 0 }; + t.SetWorkload(0); + t.OnStart(ti); + t.RunSerial(ti); + t.OnFinish(ti); + if ( theSettings.my_opts & UseSerialBaseline && !(g_absentMethods & idRunSerial) ) + tr.my_availableMethods |= idRunSerial; + if ( !(g_absentMethods & idOnStart) ) + tr.my_availableMethods |= idOnStart; + + RunConfig rc = { 1, 1, 1, 0, 0 }; + int numWorkloads = theSettings.my_opts & UseSmallestWorkloadOnly ? 1 : t.NumWorkloads(); + for ( int w = 0; w < numWorkloads; ++w ) { + WorkloadName[0] = 0; + t.SetWorkload(w); + if ( !WorkloadName[0] ) + sprintf( WorkloadName, "%d", w ); + size_t len = strlen(WorkloadName); + tr.my_workloadNames[w] = new char[len + 1]; + strcpy ( (char*)tr.my_workloadNames[w], WorkloadName ); + WorkloadFieldLen = max( WorkloadFieldLen, len ); + + rc.my_workloadID = w; + if ( theSettings.my_opts & UseBaseline ) + RunTestImpl( tr, rc, &Test::Baseline, tr.my_baselines[w] ); + if ( tr.my_availableMethods & idRunSerial ) + RunTestImpl( tr, rc, &Test::RunSerial, tr.my_serialBaselines[w] ); + printf( "Measuring baselines: %04.1f%%\r", ++n * 100. / totalWorkloads ); fflush(stdout); + } + } + TlsTimings = new TimingSeries[MaxThread + MaxTbbMasters - 1]; + if ( theSettings.my_opts & UseTaskScheduler ? MaxTbbMasters : MaxThread ) + WalkTests( &InitTestData, n, false, false, theSettings.my_opts & UseTaskScheduler ? true : false ); + CalibrationTiming.my_durations.reserve( MaxTbbMasters * 3 ); + printf( " \r"); + } + + FILE* ResFile = NULL; + + void Report ( char const* fmt, ... ) { + va_list args; + if ( ResFile ) { + va_start( args, fmt ); + vfprintf( ResFile, fmt, args ); + va_end( args ); + } + va_start( args, fmt ); + vprintf( fmt, args ); + va_end( args ); + } + + void PrintResults () { + if ( theSettings.my_resFile ) + ResFile = fopen( theSettings.my_resFile, "w" ); + Report( "%-*s %-*s %s", TitleFieldLen, "Test name", WorkloadFieldLen, "Workload", + MaxTbbMasters > 1 ? "W M " : "T " ); + if ( theSettings.my_opts & UseAffinityModes ) + Report( "Aff " ); + Report( "%-*s SD, %% %-*s %-*s %-*s ", + RateFieldLen, "Avg.time", OvhdFieldLen, "Par.ovhd,%", + RateFieldLen, "Min.time", RateFieldLen, "Max.time" ); + Report( " | Repeats = %lu, CPUs %d\n", (unsigned long)NumRuns, NumCpus ); + for ( size_t i = 0; i < theSession.size(); ++i ) { + TestResults &tr = theSession[i]; + for ( size_t j = 0; j < tr.my_results.size(); ++j ) { + RunResults &rr = tr.my_results[j]; + RunConfig &rc = rr.my_config; + int w = rc.my_workloadID; + TimingSeries &ts = rr.my_timing; + duration_t baselineTime = tr.my_baselines[w].my_avgTime, + cleanTime = ts.my_avgTime - baselineTime; + Report( "%-*s %-*s ", TitleFieldLen, tr.my_testName, WorkloadFieldLen, tr.my_workloadNames[w] ); + if ( MaxTbbMasters > 1 ) + Report( "%-4d %-4d ", rc.my_numThreads - 1, rc.my_numMasters ); + else + Report( "%-4d ", rc.my_numThreads ); + if ( theSettings.my_opts & UseAffinityModes ) + Report( "%%-8s ", AffinitizationModeNames[rc.my_affinityMode] ); + Report( "%-*.2e %-6.1f ", RateFieldLen, cleanTime, ts.my_stdDev); + if ( tr.my_availableMethods & idRunSerial ) { + duration_t serialTime = (tr.my_serialBaselines[w].my_avgTime - baselineTime) / rc.my_maxConcurrency; + Report( "%-*.1f ", OvhdFieldLen, 100*(cleanTime - serialTime)/serialTime ); + } + else + Report( "%*s%*s ", OvhdFieldLen/2, "-", OvhdFieldLen - OvhdFieldLen/2, "" ); + Report( "%-*.2e %-*.2e ", RateFieldLen, ts.my_minTime - baselineTime, RateFieldLen, ts.my_maxTime - baselineTime); + Report( "\n" ); + } + } + delete [] TlsTimings; + if ( ResFile ) + fclose(ResFile); + } + + __TBB_PERF_API void RegisterTest ( Test* t, const char* className, bool takeOwnership ) { + // Just collect test objects at this stage + theSession.push_back( TestResults(t, className, takeOwnership) ); + } + +} // namespace internal + +__TBB_PERF_API void Test::Baseline ( ThreadInfo& ) {} + +__TBB_PERF_API void Test::RunSerial ( ThreadInfo& ) { internal::g_absentMethods |= internal::idRunSerial; } + +__TBB_PERF_API void Test::OnStart ( ThreadInfo& ) { internal::g_absentMethods |= internal::idOnStart; } + +__TBB_PERF_API void Test::OnFinish ( ThreadInfo& ) { internal::g_absentMethods |= internal::idOnFinish; } + +__TBB_PERF_API void WipeCaches () { NativeParallelFor( NumCpus, internal::WiperBody() ); } + +__TBB_PERF_API void EmptyFunc () {} +__TBB_PERF_API void AnchorFunc ( void* ) {} +__TBB_PERF_API void AnchorFunc2 ( void*, void* ) {} + +__TBB_PERF_API void SetWorkloadName( const char* format, ... ) { + internal::WorkloadName[MaxWorkloadNameLen] = 0; + va_list args; + va_start(args, format); + vsnprintf( internal::WorkloadName, MaxWorkloadNameLen, format, args ); + va_end(args); +} + + +__TBB_PERF_API int TestMain( int argc, char* argv[], const SessionSettings* defaultSettings ) { +#if _MSC_VER + HANDLE hMutex = CreateMutex( NULL, FALSE, "Global\\TBB_OMP_PerfSession" ); + WaitForSingleObject( hMutex, INFINITE ); +#endif + MinThread = MaxThread = NumCpus; + if ( defaultSettings ) + theSettings = *defaultSettings; + ParseCommandLine( argc, argv ); // May override data in theSettings + + internal::PrepareTests (); + internal::RunTests (); + internal::PrintResults(); + REPORT("\n"); +#if _MSC_VER + ReleaseMutex( hMutex ); + CloseHandle( hMutex ); +#endif + return 0; +} + +} // namespace Perf diff --git a/src/tbb/src/perf/perf.h b/src/tbb/src/perf/perf.h new file mode 100644 index 0000000..0403fd5 --- /dev/null +++ b/src/tbb/src/perf/perf.h @@ -0,0 +1,265 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __tbb_perf_h__ +#define __tbb_perf_h__ + +#ifndef TBB_PERF_TYPEINFO +#define TBB_PERF_TYPEINFO 1 +#endif + +#if TBB_PERF_TYPEINFO + #include + #define __TBB_PERF_TEST_CLASS_NAME(T) typeid(T).name() +#else /* !TBB_PERF_TYPEINFO */ + #define __TBB_PERF_TEST_CLASS_NAME(T) NULL +#endif /* !TBB_PERF_TYPEINFO */ + + +#include "tbb/tick_count.h" + +// TODO: Fix build scripts to provide more reliable build phase identification means +#ifndef __TBB_PERF_API +#if _USRDLL + #if _MSC_VER + #define __TBB_PERF_API __declspec(dllexport) + #else /* !_MSC_VER */ + #define __TBB_PERF_API + #endif /* !_MSC_VER */ +#else /* !_USRDLL */ + #if _MSC_VER + #define __TBB_PERF_API __declspec(dllimport) + #else /* !_MSC_VER */ + #define __TBB_PERF_API + #endif /* !_MSC_VER */ +#endif /* !_USRDLL */ +#endif /* !__TBB_PERF_API */ + +#if _WIN32||_WIN64 + +namespace Perf { + typedef unsigned __int64 tick_t; + #if defined(_M_X64) + inline tick_t rdtsc () { return __rdtsc(); } + #elif _M_IX86 + inline tick_t rdtsc () { __asm { rdtsc } } + #else + #error Unsupported ISA + #endif +} // namespace Perf + +#elif __linux__ || __APPLE__ + +#include + +namespace Perf { + typedef uint64_t tick_t; + #if __x86_64__ || __i386__ || __i386 + inline tick_t rdtsc () { + uint32_t lo, hi; + __asm__ __volatile__ ( "rdtsc" : "=a" (lo), "=d" (hi) ); + return (tick_t)lo | ((tick_t)hi) << 32; + } + #else + #error Unsupported ISA + #endif +} // namespace Perf + +#else + #error Unsupported OS +#endif /* OS */ + +__TBB_PERF_API extern int NumThreads, + MaxConcurrency, + NumCpus; + +// Functions and global variables provided by the benchmarking framework +namespace Perf { + +typedef double duration_t; + +static const int MaxWorkloadNameLen = 64; + +static const char* NoHistogram = (char*)-1; +static const char* DefaultHistogram = (char*)-2; + +__TBB_PERF_API void AnchorFunc ( void* ); +__TBB_PERF_API void AnchorFunc2 ( void*, void* ); + +//! Helper that can be used in the preprocess handler to clean caches +/** Cleaning caches is necessary to obtain reproducible results when a test + accesses significant ranges of memory. **/ +__TBB_PERF_API void WipeCaches (); + +//! Specifies the name to be used to designate the current workload in output +/** Should be used from Test::SetWorkload(). If necessary workload name will be + truncated to MaxWorkloadNameLen characters. **/ +__TBB_PERF_API void SetWorkloadName( const char* format, ... ); + +class __TBB_PERF_API Test { +public: + virtual ~Test () {} + + //! Struct used by tests running in multiple masters mode + struct ThreadInfo { + //! Zero based thread ID + int tid; + //! Pointer to test specific data + /** If used by the test, should be initialized by OnStartLocal(), and + finalized by OnFinishLocal(). **/ + void* data; + }; + + //////////////////////////////////////////////////////////////////////////////// + // Mandatory methods + + //! Returns the number of workloads supported + virtual int NumWorkloads () = 0; + + //! Set workload info for the subsequent calls to Run() and RunSerial() + /** This method can use global helper function Perf::SetWorkloadName() in order + to specify the name of the current workload, which will be used in output + to designate the workload. If SetWorkloadName is not called, workloadIndex + will be used for this purpose. + + When testing task scheduler, make sure that this method does not trigger + its automatic initialization. **/ + virtual void SetWorkload ( int workloadIndex ) = 0; + + //! Test implementation + /** Called by the timing framework several times in a loop to achieve approx. + RunDuration time, and this loop is timed NumRuns times to collect statistics. + Argument ti specifies information about the master thread calling this method. **/ + virtual void Run ( ThreadInfo& ti ) = 0; + + //////////////////////////////////////////////////////////////////////////////// + // Optional methods + + //! Returns short title string to be used in the regular output to identify the test + /** Should uniquely identify the test among other ones in the given benchmark suite. + If not implemented, the test implementation class' RTTI name is used. **/ + virtual const char* Name () { return NULL; }; + + //! Returns minimal number of master threads + /** Used for task scheduler tests only (when UseTbbScheduler option is specified + in session settings). **/ + virtual int MinNumMasters () { return 1; } + + //! Returns maximal number of master threads + /** Used for task scheduler tests only (when UseTbbScheduler option is specified + in session settings). **/ + virtual int MaxNumMasters () { return 1; } + + //! Executes serial workload equivalent to the one processed by Run() + /** Called by the timing framework several times in a loop to collect statistics. **/ + virtual void RunSerial ( ThreadInfo& ti ); + + //! Invoked before each call to Run() + /** Can be used to preinitialize data necessary for the test, clean up + caches (see Perf::WipeCaches), etc. + In multiple masters mode this method is called on each thread. **/ + virtual void OnStart ( ThreadInfo& ti ); + + //! Invoked after each call to Run() + /** Can be used to free resources allocated by OnStart(). + Note that this method must work correctly independently of whether Run(), + RunSerial() or nothing is called between OnStart() and OnFinish(). + In multiple masters mode this method is called on each thread. **/ + virtual void OnFinish ( ThreadInfo& ti ); + + //! Functionality, the cost of which has to be factored out from timing results + /** Applies to both parallel and serial versions. **/ + virtual void Baseline ( ThreadInfo& ); + + //! Returns description string to be used in the benchmark info/summary output + virtual const char* Description () { return NULL; } + + //! Specifies if the histogram of individual run times in a series + /** If the method is not overridden, histogramName argument of TestMain is used. **/ + virtual const char* HistogramName () { return DefaultHistogram; } +}; // class Test + +namespace internal { + __TBB_PERF_API void RegisterTest ( Test*, const char* testClassName, bool takeOwnership ); +} + +template +void RegisterTest() { internal::RegisterTest( new T, __TBB_PERF_TEST_CLASS_NAME(T), true ); } + +template +void RegisterTest( T& t ) { internal::RegisterTest( &t, __TBB_PERF_TEST_CLASS_NAME(T), false ); } + +enum SessionOptions { + //! Use Test::RunSerial if present + UseBaseline = 0x01, + UseSerialBaseline = 0x02, + UseBaselines = UseBaseline | UseSerialBaseline, + UseTaskScheduler = 0x10, + UseAffinityModes = 0x20, + UseSmallestWorkloadOnly = 0x40 +}; + +struct SessionSettings { + //! A combination of SessionOptions flags + uintptr_t my_opts; + + //! Name of a file to store performance results + /** These results are duplicates of what is printed on the console. **/ + const char* my_resFile; + + //! Output destination for the histogram of individual run times in a series + /** If it is a string, the histogram is stored in a file with such name. + If it is NULL, the histogram is printed on the console. By default histograms + are suppressed. + + The histogram is formatted as two column table: + "time bucket start" "number of tests in this bucket" + + When this setting enables histogram generation, an individual test + can override it by implementing HistogramName method. **/ + const char* my_histogramName; + + SessionSettings ( uintptr_t opts = 0, const char* resFile = NULL, const char* histogram = NoHistogram ) + : my_opts(opts) + , my_resFile(resFile) + , my_histogramName(histogram) + {} +}; // struct SessionSettings + +//! Benchmarking session entry point +/** Executes all the individual tests registered previously by means of + RegisterTest **/ +__TBB_PERF_API int TestMain( int argc, char* argv[], + const SessionSettings* defaultSettings = NULL ); + + +} // namespace Perf + +#endif /* __tbb_perf_h__ */ + + diff --git a/src/tbb/src/perf/perf_sched.cpp b/src/tbb/src/perf/perf_sched.cpp new file mode 100644 index 0000000..fa64ef4 --- /dev/null +++ b/src/tbb/src/perf/perf_sched.cpp @@ -0,0 +1,464 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "perf.h" + +#include + +#include "tbb/blocked_range.h" +#include "tbb/parallel_for.h" +#include "tbb/parallel_reduce.h" + +#define NUM_CHILD_TASKS 2096 +#define NUM_ROOT_TASKS 256 + +#define N 100000000 +#define FINEST_GRAIN 10 +#define FINE_GRAIN 50 +#define MED_GRAIN 200 +#define COARSE_GRAIN 1000 + + +typedef int count_t; + +const count_t N_finest = (count_t)(N/log((double)N)/10); +const count_t N_fine = N_finest * 20; +const count_t N_med = N_fine * (count_t)log((double)N) / 5; + +class StaticTaskHolder { +public: + tbb::task *my_leafTaskPtr; + StaticTaskHolder (); +}; + +static StaticTaskHolder s_tasks; + +static count_t NumIterations; +static count_t NumLeafTasks; +static count_t NumRootTasks; + +class LeafTaskBase : public tbb::task { +public: + count_t my_ID; + + LeafTaskBase () {} + LeafTaskBase ( count_t id ) : my_ID(id) {} +}; + +class SimpleLeafTask : public LeafTaskBase { + task* execute () { + volatile count_t anchor = 0; + for ( count_t i=0; i < NumIterations; ++i ) + anchor += i; + return NULL; + } +public: + SimpleLeafTask ( count_t ) {} +}; + +StaticTaskHolder::StaticTaskHolder () { + static SimpleLeafTask s_t1(0); + my_leafTaskPtr = &s_t1; +} + +class Test_SPMC : public Perf::Test { +protected: + static const int numWorkloads = 4; + static const count_t workloads[numWorkloads]; + + LeafTaskBase* my_leafTaskPtr; + + const char* Name () { return "SPMC"; } + + int NumWorkloads () { return numWorkloads; } + + void SetWorkload ( int idx ) { + NumRootTasks = 1; + NumIterations = workloads[idx]; + NumLeafTasks = NUM_CHILD_TASKS * NUM_ROOT_TASKS / (NumIterations > 1000 ? 32 : 8); + Perf::SetWorkloadName( "%d x %d", NumLeafTasks, NumIterations ); + } + + void Run ( ThreadInfo& ) { + tbb::empty_task &r = *new( tbb::task::allocate_root() ) tbb::empty_task; + r.set_ref_count( NumLeafTasks + 1 ); + for ( count_t i = 0; i < NumLeafTasks; ++i ) + r.spawn( *new(r.allocate_child()) SimpleLeafTask(0) ); + r.wait_for_all(); + tbb::task::destroy(r); + } + + void RunSerial ( ThreadInfo& ) { + const count_t n = NumLeafTasks * NumRootTasks; + for ( count_t i=0; i < n; ++i ) { + my_leafTaskPtr->my_ID = i; + my_leafTaskPtr->execute(); + } + } + +public: + Test_SPMC ( LeafTaskBase* leafTaskPtr = NULL ) { + static SimpleLeafTask t(0); + my_leafTaskPtr = leafTaskPtr ? leafTaskPtr : &t; + } +}; // class Test_SPMC + +const count_t Test_SPMC::workloads[Test_SPMC::numWorkloads] = { 1, 50, 500, 5000 }; + +template +class LeavesLauncherTask : public tbb::task { + count_t my_groupId; + + task* execute () { + count_t base = my_groupId * NumLeafTasks; + set_ref_count(NumLeafTasks + 1); + for ( count_t i = 0; i < NumLeafTasks; ++i ) + spawn( *new(allocate_child()) LeafTask(base + i) ); + wait_for_all(); + return NULL; + } +public: + LeavesLauncherTask ( count_t groupId ) : my_groupId(groupId) {} +}; + +template +void RunShallowTree () { + tbb::empty_task &r = *new( tbb::task::allocate_root() ) tbb::empty_task; + r.set_ref_count( NumRootTasks + 1 ); + for ( count_t i = 0; i < NumRootTasks; ++i ) + r.spawn( *new(r.allocate_child()) LeavesLauncherTask(i) ); + r.wait_for_all(); + tbb::task::destroy(r); +} + +class Test_ShallowTree : public Test_SPMC { + const char* Name () { return "ShallowTree"; } + + void SetWorkload ( int idx ) { + NumRootTasks = NUM_ROOT_TASKS; + NumIterations = workloads[idx]; + NumLeafTasks = NumIterations > 200 ? NUM_CHILD_TASKS / 10 : + (NumIterations > 50 ? NUM_CHILD_TASKS / 2 : NUM_CHILD_TASKS * 2); + Perf::SetWorkloadName( "%d x %d", NumRootTasks * NumLeafTasks, NumIterations ); + } + + void Run ( ThreadInfo& ) { + RunShallowTree(); + } +}; // class Test_ShallowTree + +class LeafTaskSkewed : public LeafTaskBase { + task* execute () { + volatile count_t anchor = 0; + double K = (double)NumRootTasks * NumLeafTasks; + count_t n = count_t(sqrt(double(my_ID)) * double(my_ID) * my_ID / (4 * K * K)); + for ( count_t i = 0; i < n; ++i ) + anchor += i; + return NULL; + } +public: + LeafTaskSkewed ( count_t id ) : LeafTaskBase(id) {} +}; + +class Test_ShallowTree_Skewed : public Test_SPMC { + static LeafTaskSkewed SerialTaskBody; + + const char* Name () { return "ShallowTree_Skewed"; } + + int NumWorkloads () { return 1; } + + void SetWorkload ( int ) { + NumRootTasks = NUM_ROOT_TASKS; + NumLeafTasks = NUM_CHILD_TASKS; + Perf::SetWorkloadName( "%d", NumRootTasks * NumLeafTasks ); + } + + void Run ( ThreadInfo& ) { + RunShallowTree(); + } + +public: + Test_ShallowTree_Skewed () : Test_SPMC(&SerialTaskBody) {} +}; // class Test_ShallowTree_Skewed + +LeafTaskSkewed Test_ShallowTree_Skewed::SerialTaskBody(0); + +typedef tbb::blocked_range range_t; + +static count_t IterRange = N, + IterGrain = 1; + +enum PartitionerType { + SimplePartitioner = 0, + AutoPartitioner = 1 +}; + +class Test_Algs : public Perf::Test { +protected: + static const int numWorkloads = 4; + static const count_t algRanges[numWorkloads]; + static const count_t algGrains[numWorkloads]; + + tbb::simple_partitioner my_simplePartitioner; + tbb::auto_partitioner my_autoPartitioner; + PartitionerType my_partitionerType; + + bool UseAutoPartitioner () const { return my_partitionerType == AutoPartitioner; } + + int NumWorkloads () { return UseAutoPartitioner() ? 3 : numWorkloads; } + + void SetWorkload ( int idx ) { + if ( UseAutoPartitioner() ) { + IterRange = algRanges[idx ? numWorkloads - 1 : 0]; + IterGrain = idx > 1 ? algGrains[numWorkloads - 1] : 1; + } + else { + IterRange = algRanges[idx]; + IterGrain = algGrains[idx]; + } + Perf::SetWorkloadName( "%d / %d", IterRange, IterGrain ); + } +public: + Test_Algs ( PartitionerType pt = SimplePartitioner ) : my_partitionerType(pt) {} +}; // class Test_Algs + +const count_t Test_Algs::algRanges[] = {N_finest, N_fine, N_med, N}; +const count_t Test_Algs::algGrains[] = {1, FINE_GRAIN, MED_GRAIN, COARSE_GRAIN}; + +template +class Test_PFor : public Test_Algs { +protected: + void Run ( ThreadInfo& ) { + if ( UseAutoPartitioner() ) + tbb::parallel_for( range_t(0, IterRange, IterGrain), Body(), my_autoPartitioner ); + else + tbb::parallel_for( range_t(0, IterRange, IterGrain), Body(), my_simplePartitioner ); + } + + void RunSerial ( ThreadInfo& ) { + Body body; + body( range_t(0, IterRange, IterGrain) ); + } +public: + Test_PFor ( PartitionerType pt = SimplePartitioner ) : Test_Algs(pt) {} +}; // class Test_PFor + +class SimpleForBody { +public: + void operator()( const range_t& r ) const { + count_t end = r.end(); + volatile count_t anchor = 0; + for( count_t i = r.begin(); i < end; ++i ) + anchor += i; + } +}; // class SimpleForBody + +class Test_PFor_Simple : public Test_PFor { +protected: + const char* Name () { return UseAutoPartitioner() ? "PFor-AP" : "PFor"; } +public: + Test_PFor_Simple ( PartitionerType pt = SimplePartitioner ) : Test_PFor(pt) {} +}; // class Test_PFor_Simple + +class SkewedForBody { +public: + void operator()( const range_t& r ) const { + count_t end = (r.end() + 1) * (r.end() + 1); + volatile count_t anchor = 0; + for( count_t i = r.begin() * r.begin(); i < end; ++i ) + anchor += i; + } +}; // class SkewedForBody + +class Test_PFor_Skewed : public Test_PFor { + typedef Test_PFor base_type; +protected: + const char* Name () { return UseAutoPartitioner() ? "PFor-Skewed-AP" : "PFor-Skewed"; } + + void SetWorkload ( int idx ) { + base_type::SetWorkload(idx); + IterRange = (count_t)(sqrt((double)IterRange) * sqrt(sqrt((double)N / IterRange))); + Perf::SetWorkloadName( "%d", IterRange ); + } + +public: + Test_PFor_Skewed ( PartitionerType pt = SimplePartitioner ) : base_type(pt) {} +}; // class Test_PFor_Skewed + +PartitionerType gPartitionerType; +count_t NestingRange; +count_t NestingGrain; + +class NestingForBody { + count_t my_depth; + tbb::simple_partitioner my_simplePartitioner; + tbb::auto_partitioner my_autoPartitioner; + + template + void run ( const range_t& r, Partitioner& p ) const { + count_t end = r.end(); + if ( my_depth > 1 ) + for ( count_t i = r.begin(); i < end; ++i ) + tbb::parallel_for( range_t(0, IterRange, IterGrain), NestingForBody(my_depth - 1), p ); + else + for ( count_t i = r.begin(); i < end; ++i ) + tbb::parallel_for( range_t(0, IterRange, IterGrain), SimpleForBody(), p ); + } +public: + void operator()( const range_t& r ) const { + if ( gPartitionerType == AutoPartitioner ) + run( r, my_autoPartitioner ); + else + run( r, my_simplePartitioner ); + } + NestingForBody ( count_t depth = 1 ) : my_depth(depth) {} +}; // class NestingForBody + +enum NestingType { + HollowNesting, + ShallowNesting, + DeepNesting +}; + +class Test_PFor_Nested : public Test_Algs { + typedef Test_Algs base_type; + + NestingType my_nestingType; + count_t my_nestingDepth; + +protected: + const char* Name () { + static const char* names[] = { "PFor-HollowNested", "PFor-HollowNested-AP", + "PFor-ShallowNested", "PFor-ShallowNested-AP", + "PFor-DeeplyNested", "PFor-DeeplyNested-AP" }; + return names[my_nestingType * 2 + my_partitionerType]; + } + + int NumWorkloads () { return my_nestingType == ShallowNesting ? (UseAutoPartitioner() ? 3 : 2) : 1; } + + void SetWorkload ( int idx ) { + gPartitionerType = my_partitionerType; + if ( my_nestingType == DeepNesting ) { + NestingRange = 1024; + IterGrain = NestingGrain = 1; + IterRange = 4; + my_nestingDepth = 4; + } + else if ( my_nestingType == ShallowNesting ) { + int i = idx ? numWorkloads - 1 : 0; + count_t baseRange = algRanges[i]; + count_t baseGrain = !UseAutoPartitioner() || idx > 1 ? algGrains[i] : 1; + NestingRange = IterRange = (count_t)sqrt((double)baseRange); + NestingGrain = IterGrain = (count_t)sqrt((double)baseGrain); + } + else { + NestingRange = N / 100; + NestingGrain = COARSE_GRAIN / 10; + IterRange = 2; + IterGrain = 1; + } + Perf::SetWorkloadName( "%d / %d", NestingRange, NestingGrain ); + } + + void Run ( ThreadInfo& ) { + if ( UseAutoPartitioner() ) + tbb::parallel_for( range_t(0, NestingRange, NestingGrain), NestingForBody(my_nestingDepth), my_autoPartitioner ); + else + tbb::parallel_for( range_t(0, NestingRange, NestingGrain), NestingForBody(my_nestingDepth), my_simplePartitioner ); + } + + void RunSerial ( ThreadInfo& ) { + for ( int i = 0; i < NestingRange; ++i ) { + SimpleForBody body; + body( range_t(0, IterRange, IterGrain) ); + } + } +public: + Test_PFor_Nested ( NestingType nt, PartitionerType pt ) : base_type(pt), my_nestingType(nt), my_nestingDepth(1) {} +}; // class Test_PFor_Nested + +class SimpleReduceBody { +public: + count_t my_sum; + SimpleReduceBody () : my_sum(0) {} + SimpleReduceBody ( SimpleReduceBody&, tbb::split ) : my_sum(0) {} + void join( SimpleReduceBody& rhs ) { my_sum += rhs.my_sum;} + void operator()( const range_t& r ) { + count_t end = r.end(); + volatile count_t anchor = 0; + for( count_t i = r.begin(); i < end; ++i ) + anchor += i; + my_sum = anchor; + } +}; // class SimpleReduceBody + +class Test_PReduce : public Test_Algs { +protected: + const char* Name () { return UseAutoPartitioner() ? "PReduce-AP" : "PReduce"; } + + void Run ( ThreadInfo& ) { + SimpleReduceBody body; + if ( UseAutoPartitioner() ) + tbb::parallel_reduce( range_t(0, IterRange, IterGrain), body, my_autoPartitioner ); + else + tbb::parallel_reduce( range_t(0, IterRange, IterGrain), body, my_simplePartitioner ); + } + + void RunSerial ( ThreadInfo& ) { + SimpleReduceBody body; + body( range_t(0, IterRange, IterGrain) ); + } +public: + Test_PReduce ( PartitionerType pt = SimplePartitioner ) : Test_Algs(pt) {} +}; // class Test_PReduce + +int main( int argc, char* argv[] ) { + Perf::SessionSettings opts (Perf::UseTaskScheduler | Perf::UseSerialBaseline, "perf_sched.txt"); // Perf::UseBaseline, Perf::UseSmallestWorkloadOnly + Perf::RegisterTest(); + Perf::RegisterTest(); + Perf::RegisterTest(); + Test_PFor_Simple pf_sp(SimplePartitioner), pf_ap(AutoPartitioner); + Perf::RegisterTest(pf_sp); + Perf::RegisterTest(pf_ap); + Test_PReduce pr_sp(SimplePartitioner), pr_ap(AutoPartitioner); + Perf::RegisterTest(pr_sp); + Perf::RegisterTest(pr_ap); + Test_PFor_Skewed pf_s_sp(SimplePartitioner), pf_s_ap(AutoPartitioner); + Perf::RegisterTest(pf_s_sp); + Perf::RegisterTest(pf_s_ap); + Test_PFor_Nested pf_hn_sp(HollowNesting, SimplePartitioner), pf_hn_ap(HollowNesting, AutoPartitioner), + pf_sn_sp(ShallowNesting, SimplePartitioner), pf_sn_ap(ShallowNesting, AutoPartitioner), + pf_dn_sp(DeepNesting, SimplePartitioner), pf_dn_ap(DeepNesting, AutoPartitioner); + Perf::RegisterTest(pf_hn_sp); + Perf::RegisterTest(pf_hn_ap); + Perf::RegisterTest(pf_sn_sp); + Perf::RegisterTest(pf_sn_ap); + Perf::RegisterTest(pf_dn_sp); + Perf::RegisterTest(pf_dn_ap); + return Perf::TestMain(argc, argv, &opts); +} diff --git a/src/tbb/src/perf/run_statistics.sh b/src/tbb/src/perf/run_statistics.sh new file mode 100644 index 0000000..183efdd --- /dev/null +++ b/src/tbb/src/perf/run_statistics.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# +# Copyright 2005-2012 Intel Corporation. All Rights Reserved. +# +# This file is part of Threading Building Blocks. +# +# Threading Building Blocks is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# version 2 as published by the Free Software Foundation. +# +# Threading Building Blocks is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Threading Building Blocks; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# As a special exception, you may use this file as part of a free software +# library without restriction. Specifically, if other files instantiate +# templates or use macros or inline functions from this file, or you compile +# this file and link it with other files to produce an executable, this +# file does not by itself cause the resulting executable to be covered by +# the GNU General Public License. This exception does not however +# invalidate any other reasons why the executable file might be covered by +# the GNU General Public License. + +export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH +#setting output format .csv, 'pivot' - is pivot table mode, ++ means append +export STAT_FORMAT=pivot-csv++ +#check existing files because of apend mode +ls *.csv +rm -i *.csv +#setting a delimiter in txt or csv file +#export STAT_DELIMITER=, +export STAT_RUNINFO1=Host=`hostname -s` +#append a suffix after the filename +#export STAT_SUFFIX=$STAT_RUNINFO1 +for ((i=1;i<=${repeat:=100};++i)); do echo $i of $repeat: && STAT_RUNINFO2=Run=$i $* || break; done diff --git a/src/tbb/src/perf/statistics.cpp b/src/tbb/src/perf/statistics.cpp new file mode 100644 index 0000000..cf73533 --- /dev/null +++ b/src/tbb/src/perf/statistics.cpp @@ -0,0 +1,452 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "statistics.h" +#include "statistics_xml.h" + +#define COUNT_PARAMETERS 3 + +#ifdef _MSC_VER +#define snprintf _snprintf +#endif + +void GetTime(char* buff,int size_buff) +{ + tm *newtime; + time_t timer; + time(&timer); + newtime=localtime(&timer); + strftime(buff,size_buff,"%H:%M:%S",newtime); +} + +void GetDate(char* buff,int size_buff) +{ + tm *newtime; + time_t timer; + time(&timer); + newtime=localtime(&timer); + strftime(buff,size_buff,"%Y-%m-%d",newtime); +} + + +StatisticsCollector::TestCase StatisticsCollector::SetTestCase(const char *name, const char *mode, int threads) +{ + string KeyName(name); + switch (SortMode) + { + case ByThreads: KeyName += Format("_%02d_%s", threads, mode); break; + default: + case ByAlg: KeyName += Format("_%s_%02d", mode, threads); break; + } + CurrentKey = Statistics[KeyName]; + if(!CurrentKey) { + CurrentKey = new StatisticResults; + CurrentKey->Mode = mode; + CurrentKey->Name = name; + CurrentKey->Threads = threads; + CurrentKey->Results.reserve(RoundTitles.size()); + Statistics[KeyName] = CurrentKey; + } + return TestCase(CurrentKey); +} + +StatisticsCollector::~StatisticsCollector() +{ + for(Statistics_t::iterator i = Statistics.begin(); i != Statistics.end(); i++) + delete i->second; +} + +void StatisticsCollector::ReserveRounds(size_t index) +{ + size_t i = RoundTitles.size(); + if (i > index) return; + char buf[16]; + RoundTitles.resize(index+1); + for(; i <= index; i++) { + snprintf( buf, 15, "%u", unsigned(i+1) ); + RoundTitles[i] = buf; + } + for(Statistics_t::iterator i = Statistics.begin(); i != Statistics.end(); i++) { + if(!i->second) printf("!!!'%s' = NULL\n", i->first.c_str()); + else i->second->Results.reserve(index+1); + } +} + +void StatisticsCollector::AddRoundResult(const TestCase &key, value_t v) +{ + ReserveRounds(key.access->Results.size()); + key.access->Results.push_back(v); +} + +void StatisticsCollector::SetRoundTitle(size_t index, const char *fmt, ...) +{ + vargf2buff(buff, 128, fmt); + ReserveRounds(index); + RoundTitles[index] = buff; +} + +void StatisticsCollector::AddStatisticValue(const TestCase &key, const char *type, const char *fmt, ...) +{ + vargf2buff(buff, 128, fmt); + AnalysisTitles.insert(type); + key.access->Analysis[type] = buff; +} + +void StatisticsCollector::AddStatisticValue(const char *type, const char *fmt, ...) +{ + vargf2buff(buff, 128, fmt); + AnalysisTitles.insert(type); + CurrentKey->Analysis[type] = buff; +} + +void StatisticsCollector::SetRunInfo(const char *title, const char *fmt, ...) +{ + vargf2buff(buff, 256, fmt); + RunInfo.push_back(make_pair(title, buff)); +} + +void StatisticsCollector::SetStatisticFormula(const char *name, const char *formula) +{ + Formulas[name] = formula; +} + +void StatisticsCollector::SetTitle(const char *fmt, ...) +{ + vargf2buff(buff, 256, fmt); + Title = buff; +} + +string ExcelFormula(const string &fmt, size_t place, size_t rounds, bool is_horizontal) +{ + char buff[16]; + if(is_horizontal) + snprintf(buff, 15, "RC[%u]:RC[%u]", unsigned(place), unsigned(place+rounds-1)); + else + snprintf(buff, 15, "R[%u]C:R[%u]C", unsigned(place+1), unsigned(place+rounds)); + string result(fmt); size_t pos = 0; + while ( (pos = result.find("ROUNDS", pos, 6)) != string::npos ) + result.replace(pos, 6, buff); + return result; +} + +void StatisticsCollector::Print(int dataOutput, const char *ModeName) +{ + FILE *OutputFile; + const char *file_suffix = getenv("STAT_SUFFIX"); + if( !file_suffix ) file_suffix = ""; + const char *file_format = getenv("STAT_FORMAT"); + if( file_format ) { + dataOutput = 0; + if( strstr(file_format, "con")||strstr(file_format, "std") ) dataOutput |= StatisticsCollector::Stdout; + if( strstr(file_format, "txt")||strstr(file_format, "csv") ) dataOutput |= StatisticsCollector::TextFile; + if( strstr(file_format, "excel")||strstr(file_format, "xml") ) dataOutput |= StatisticsCollector::ExcelXML; + if( strstr(file_format, "htm") ) dataOutput |= StatisticsCollector::HTMLFile; + if( strstr(file_format, "pivot") ) dataOutput |= StatisticsCollector::PivotMode; + } + for(int i = 1; i < 10; i++) { + string env = Format("STAT_RUNINFO%d", i); + const char *info = getenv(env.c_str()); + if( info ) { + string title(info); + size_t pos = title.find('='); + if( pos != string::npos ) { + env = title.substr(pos+1); + title.resize(pos); + } else env = title; + RunInfo.push_back(make_pair(title, env)); + } + } + + if (dataOutput & StatisticsCollector::Stdout) + { + printf("\n-=# %s #=-\n", Title.c_str()); + if(SortMode == ByThreads) + printf(" Name | # | %s ", ModeName); + else + printf(" Name | %s | # ", ModeName); + for (AnalysisTitles_t::iterator i = AnalysisTitles.begin(); i != AnalysisTitles.end(); i++) + printf("|%s", i->c_str()+1); + + for (Statistics_t::iterator i = Statistics.begin(); i != Statistics.end(); i++) + { + if(SortMode == ByThreads) + printf("\n%12s|% 5d|%6s", i->second->Name.c_str(), i->second->Threads, i->second->Mode.c_str()); + else + printf("\n%12s|%6s|% 5d", i->second->Name.c_str(), i->second->Mode.c_str(), i->second->Threads); + Analysis_t &analisis = i->second->Analysis; + AnalysisTitles_t::iterator t = AnalysisTitles.begin(); + for (Analysis_t::iterator a = analisis.begin(); a != analisis.end(); t++) + { + char fmt[8]; snprintf(fmt, 7, "|%% %us", unsigned(max(size_t(3), t->size()))); + if(*t != a->first) + printf(fmt, ""); + else { + printf(fmt, a->second.c_str()); a++; + } + } + } + printf("\n"); + } + if (dataOutput & StatisticsCollector::TextFile) + { + bool append = false; + const char *file_ext = ".txt"; + if( file_format && strstr(file_format, "++") ) append = true; + if( file_format && strstr(file_format, "csv") ) file_ext = ".csv"; + if ((OutputFile = fopen((Name+file_suffix+file_ext).c_str(), append?"at":"wt")) == NULL) { + printf("Can't open .txt file\n"); + } else { + const char *delim = getenv("STAT_DELIMITER"); + if( !delim || !delim[0] ) { + if( file_format && strstr(file_format, "csv") ) delim = ","; + else delim = "\t"; + } + if( !append || !ftell(OutputFile) ) { // header needed + append = false; + if(SortMode == ByThreads) fprintf(OutputFile, "Name%s#%s%s", delim, delim, ModeName); + else fprintf(OutputFile, "Name%s%s%s#", delim, ModeName, delim); + for( size_t k = 0; k < RunInfo.size(); k++ ) + fprintf(OutputFile, "%s%s", delim, RunInfo[k].first.c_str()); + } + if(dataOutput & StatisticsCollector::PivotMode) { + if( !append) fprintf(OutputFile, "%sColumn%sValue", delim, delim); + for (Statistics_t::iterator i = Statistics.begin(); i != Statistics.end(); i++) + { + string RowHead; + if(SortMode == ByThreads) + RowHead = Format("\n%s%s%d%s%s%s", i->second->Name.c_str(), delim, i->second->Threads, delim, i->second->Mode.c_str(), delim); + else + RowHead = Format("\n%s%s%s%s%d%s", i->second->Name.c_str(), delim, i->second->Mode.c_str(), delim, i->second->Threads, delim); + for( size_t k = 0; k < RunInfo.size(); k++ ) + RowHead.append(RunInfo[k].second + delim); + Analysis_t &analisis = i->second->Analysis; + for (Analysis_t::iterator a = analisis.begin(); a != analisis.end(); ++a) + fprintf(OutputFile, "%s%s%s%s", RowHead.c_str(), a->first.c_str(), delim, a->second.c_str()); + Results_t &r = i->second->Results; + for (size_t k = 0; k < r.size(); k++) { + fprintf(OutputFile, "%s%s%s", RowHead.c_str(), RoundTitles[k].c_str(), delim); + fprintf(OutputFile, ResultsFmt, r[k]); + } + } + } else { + if( !append ) { + for( size_t k = 0; k < RunInfo.size(); k++ ) + fprintf(OutputFile, "%s%s", delim, RunInfo[k].first.c_str()); + for (AnalysisTitles_t::iterator i = AnalysisTitles.begin(); i != AnalysisTitles.end(); i++) + fprintf(OutputFile, "%s%s", delim, i->c_str()+1); + for (size_t i = 0; i < RoundTitles.size(); i++) + fprintf(OutputFile, "%s%s", delim, RoundTitles[i].c_str()); + } + for (Statistics_t::iterator i = Statistics.begin(); i != Statistics.end(); i++) + { + if(SortMode == ByThreads) + fprintf(OutputFile, "\n%s%s%d%s%s", i->second->Name.c_str(), delim, i->second->Threads, delim, i->second->Mode.c_str()); + else + fprintf(OutputFile, "\n%s%s%s%s%d", i->second->Name.c_str(), delim, i->second->Mode.c_str(), delim, i->second->Threads); + for( size_t k = 0; k < RunInfo.size(); k++ ) + fprintf(OutputFile, "%s%s", delim, RunInfo[k].second.c_str()); + Analysis_t &analisis = i->second->Analysis; + AnalysisTitles_t::iterator t = AnalysisTitles.begin(); + for (Analysis_t::iterator a = analisis.begin(); a != analisis.end(); ++t) { + fprintf(OutputFile, "%s", delim); + if(*t == a->first) { + fprintf(OutputFile, "%s", a->second.c_str()); ++a; + } + } + //data + Results_t &r = i->second->Results; + for (size_t k = 0; k < r.size(); k++) + { + fprintf(OutputFile, "%s", delim); + fprintf(OutputFile, ResultsFmt, r[k]); + } + } + } + fprintf(OutputFile, "\n"); + fclose(OutputFile); + } + } + if (dataOutput & StatisticsCollector::HTMLFile) + { + if ((OutputFile = fopen((Name+file_suffix+".html").c_str(), "w+t")) == NULL) { + printf("Can't open .html file\n"); + } else { + char TimerBuff[100], DateBuff[100]; + GetTime(TimerBuff,sizeof(TimerBuff)); + GetDate(DateBuff,sizeof(DateBuff)); + fprintf(OutputFile, "\n%s\n\n", Title.c_str()); + //----------------------- + fprintf(OutputFile, "\n"); + fprintf(OutputFile, "" + "\n", ModeName); + for (AnalysisTitles_t::iterator i = AnalysisTitles.begin(); i != AnalysisTitles.end(); i++) + fprintf(OutputFile, "", i->c_str()+1); + for (size_t i = 0; i < RoundTitles.size(); i++) + fprintf(OutputFile, "", RoundTitles[i].c_str()); + for (Statistics_t::iterator i = Statistics.begin(); i != Statistics.end(); i++) + { + fprintf(OutputFile, "\n", + i->second->Name.c_str(), i->second->Threads, i->second->Mode.c_str()); + //statistics + AnalysisTitles_t::iterator t = AnalysisTitles.begin(); + for (Analysis_t::iterator j = i->second->Analysis.begin(); j != i->second->Analysis.end(); t++) + { + fprintf(OutputFile, "", (*t != j->first)?" ":(i->second->Analysis[j->first]).c_str()); + if(*t == j->first) j++; + } + //data + Results_t &r = i->second->Results; + for (size_t k = 0; k < r.size(); k++) + { + fprintf(OutputFile, ""); + } + } + fprintf(OutputFile, "\n
    Flip[H]%s%s%s", + DateBuff, TimerBuff, unsigned(AnalysisTitles.size() + RoundTitles.size()), Title.c_str()); + for( size_t k = 0; k < RunInfo.size(); k++ ) + fprintf(OutputFile, "; %s: %s", RunInfo[k].first.c_str(), RunInfo[k].second.c_str()); + fprintf(OutputFile, "
    NameThreads%s%s%s
    %s%d%4s%s"); + fprintf(OutputFile, ResultsFmt, r[k]); + fprintf(OutputFile, "
    \n"); + ////////////////////////////////////////////////////// + fprintf(OutputFile, "\n"); + fprintf(OutputFile, "\n" + "", + DateBuff, TimerBuff, unsigned(max(Statistics.size()-2,size_t(1))), Title.c_str()); + + fprintf(OutputFile, "\n"); + for (Statistics_t::iterator i = Statistics.begin(); i != Statistics.end(); i++) + fprintf(OutputFile, "", i->second->Name.c_str()); + fprintf(OutputFile, "\n"); + for (Statistics_t::iterator n = Statistics.begin(); n != Statistics.end(); n++) + fprintf(OutputFile, "", n->second->Threads); + fprintf(OutputFile, "\n", ModeName); + for (Statistics_t::iterator m = Statistics.begin(); m != Statistics.end(); m++) + fprintf(OutputFile, "", m->second->Mode.c_str()); + + for (AnalysisTitles_t::iterator t = AnalysisTitles.begin(); t != AnalysisTitles.end(); t++) + { + fprintf(OutputFile, "\n", t->c_str()+1); + for (Statistics_t::iterator i = Statistics.begin(); i != Statistics.end(); i++) + fprintf(OutputFile, "", i->second->Analysis.count(*t)?i->second->Analysis[*t].c_str():" "); + } + + for (size_t r = 0; r < RoundTitles.size(); r++) + { + fprintf(OutputFile, "\n", RoundTitles[r].c_str()); + for (Statistics_t::iterator i = Statistics.begin(); i != Statistics.end(); i++) + { + Results_t &result = i->second->Results; + fprintf(OutputFile, ""); + } + } + fprintf(OutputFile, "\n
    Flip[V]%s%s%s
    Name%s
    Threads%d
    %s%s
    %s%s
    %s"); + if(result.size() > r) + fprintf(OutputFile, ResultsFmt, result[r]); + fprintf(OutputFile, "
    \n\n"); + fclose(OutputFile); + } + } + if (dataOutput & StatisticsCollector::ExcelXML) + { + if ((OutputFile = fopen((Name+file_suffix+".xml").c_str(), "w+t")) == NULL) { + printf("Can't open .xml file\n"); + } else { + // TODO:PivotMode + char UserName[100]; + char TimerBuff[100], DateBuff[100]; +#if _WIN32 || _WIN64 + strcpy(UserName,getenv("USERNAME")); +#else + strcpy(UserName,getenv("USER")); +#endif + //-------------------------------- + GetTime(TimerBuff,sizeof(TimerBuff)); + GetDate(DateBuff,sizeof(DateBuff)); + //-------------------------- + fprintf(OutputFile, XMLHead, UserName, TimerBuff); + fprintf(OutputFile, XMLStyles); + fprintf(OutputFile, XMLBeginSheet, "Horizontal"); + fprintf(OutputFile, XMLNames,1,1,1,int(AnalysisTitles.size()+Formulas.size()+COUNT_PARAMETERS)); + fprintf(OutputFile, XMLBeginTable, int(RoundTitles.size()+Formulas.size()+AnalysisTitles.size()+COUNT_PARAMETERS+1/*title*/), int(Statistics.size()+1)); + fprintf(OutputFile, XMLBRow); + fprintf(OutputFile, XMLCellTopName); + fprintf(OutputFile, XMLCellTopThread); + fprintf(OutputFile, XMLCellTopMode, ModeName); + for (AnalysisTitles_t::iterator j = AnalysisTitles.begin(); j != AnalysisTitles.end(); j++) + fprintf(OutputFile, XMLAnalysisTitle, j->c_str()+1); + for (Formulas_t::iterator j = Formulas.begin(); j != Formulas.end(); j++) + fprintf(OutputFile, XMLAnalysisTitle, j->first.c_str()+1); + for (RoundTitles_t::iterator j = RoundTitles.begin(); j != RoundTitles.end(); j++) + fprintf(OutputFile, XMLAnalysisTitle, j->c_str()); + string Info = Title; + for( size_t k = 0; k < RunInfo.size(); k++ ) + Info.append("; " + RunInfo[k].first + "=" + RunInfo[k].second); + fprintf(OutputFile, XMLCellEmptyWhite, Info.c_str()); + fprintf(OutputFile, XMLERow); + //------------------------ + for (Statistics_t::iterator i = Statistics.begin(); i != Statistics.end(); i++) + { + fprintf(OutputFile, XMLBRow); + fprintf(OutputFile, XMLCellName, i->second->Name.c_str()); + fprintf(OutputFile, XMLCellThread,i->second->Threads); + fprintf(OutputFile, XMLCellMode, i->second->Mode.c_str()); + //statistics + AnalysisTitles_t::iterator at = AnalysisTitles.begin(); + for (Analysis_t::iterator j = i->second->Analysis.begin(); j != i->second->Analysis.end(); at++) + { + fprintf(OutputFile, XMLCellAnalysis, (*at != j->first)?"":(i->second->Analysis[j->first]).c_str()); + if(*at == j->first) j++; + } + //formulas + size_t place = 0; + Results_t &v = i->second->Results; + for (Formulas_t::iterator f = Formulas.begin(); f != Formulas.end(); f++, place++) + fprintf(OutputFile, XMLCellFormula, ExcelFormula(f->second, Formulas.size()-place, v.size(), true).c_str()); + //data + for (size_t k = 0; k < v.size(); k++) + { + fprintf(OutputFile, XMLCellData, v[k]); + } + if(v.size() < RoundTitles.size()) + fprintf(OutputFile, XMLMergeRow, int(RoundTitles.size() - v.size())); + fprintf(OutputFile, XMLERow); + } + //------------------------ + fprintf(OutputFile, XMLEndTable); + fprintf(OutputFile, XMLWorkSheetProperties,1,1,3,3,int(RoundTitles.size()+AnalysisTitles.size()+Formulas.size()+COUNT_PARAMETERS)); + fprintf(OutputFile, XMLAutoFilter,1,1,1,int(AnalysisTitles.size()+Formulas.size()+COUNT_PARAMETERS)); + fprintf(OutputFile, XMLEndWorkSheet); + //---------------------------------------- + fprintf(OutputFile, XMLEndWorkbook); + fclose(OutputFile); + } + } +} diff --git a/src/tbb/src/perf/statistics.h b/src/tbb/src/perf/statistics.h new file mode 100644 index 0000000..aec3e93 --- /dev/null +++ b/src/tbb/src/perf/statistics.h @@ -0,0 +1,199 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Internal Intel tool + +#ifndef __STATISTICS_H__ +#define __STATISTICS_H__ + +#define _CRT_SECURE_NO_DEPRECATE 1 + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +typedef double value_t; + +/* + Statistical collector class. + + Resulting table output: + +---------------------------------------------------------------------------+ + | [Date] ... | + +----------+----v----+--v---+----------------+------------+-..-+------------+ + | TestName | Threads | Mode | Rounds results | Stat_type1 | .. | Stat_typeN | + +----------+---------+------+-+-+-+-..-+-+-+-+------------+-..-+------------+ + | | | | | | | .. | | | | | | | + .. ... ... .................. ...... .. + | | | | | | | .. | | | | | | | + +----------+---------+------+-+-+-+-..-+-+-+-+------------+-..-+------------+ + + Iterating table output: + +---------------------------------------------------------------------------+ + | [Date] <TestName>, Threads: <N>, Mode: <M>; for <Title>... | + +----------+----v----+--v---+----------------+------------+-..-+------------+ + +*/ + +class StatisticsCollector +{ +public: + typedef map<string, string> Analysis_t; + typedef vector<value_t> Results_t; + +protected: + StatisticsCollector(const StatisticsCollector &); + + struct StatisticResults + { + string Name; + string Mode; + int Threads; + Results_t Results; + Analysis_t Analysis; + }; + + // internal members + //bool OpenFile; + StatisticResults *CurrentKey; + string Title; + const char /**Name,*/ *ResultsFmt; + string Name; + //! Data + typedef map<string, StatisticResults*> Statistics_t; + Statistics_t Statistics; + typedef vector<string> RoundTitles_t; + RoundTitles_t RoundTitles; + //TODO: merge those into one structure + typedef map<string, string> Formulas_t; + Formulas_t Formulas; + typedef set<string> AnalysisTitles_t; + AnalysisTitles_t AnalysisTitles; + typedef vector<pair<string, string> > RunInfo_t; + RunInfo_t RunInfo; + +public: + struct TestCase { + StatisticResults *access; + TestCase() : access(0) {} + TestCase(StatisticResults *link) : access(link) {} + const char *getName() const { return access->Name.c_str(); } + const char *getMode() const { return access->Mode.c_str(); } + int getThreads() const { return access->Threads; } + const Results_t &getResults() const { return access->Results; } + const Analysis_t &getAnalysis() const { return access->Analysis; } + }; + + enum Sorting { + ByThreads, ByAlg + }; + + //! Data and output types + enum DataOutput { + // Verbosity level enumeration + Statistic = 1, //< Analytical data - computed after all iterations and rounds passed + Result = 2, //< Testing data - collected after all iterations passed + Iteration = 3, //< Verbose data - collected at each iteration (for each size - in case of containers) + // ExtraVerbose is not applicabe yet :) be happy, but flexibility is always welcome + + // Next constants are bit-fields + Stdout = 1<<8, //< Output to the console + TextFile = 1<<9, //< Output to plain text file "name.txt" (delimiter is TAB by default) + ExcelXML = 1<<10, //< Output to Excel-readable XML-file "name.xml" + HTMLFile = 1<<11, //< Output to HTML file "name.html" + PivotMode= 1<<15 //< Puts all the rounds into one columt to better fit for pivot table in Excel + }; + + //! Constructor. Specify tests set name which used as name of output files + StatisticsCollector(const char *name, Sorting mode = ByThreads, const char *fmt = "%g") + : CurrentKey(NULL), ResultsFmt(fmt), Name(name), SortMode(mode) {} + + ~StatisticsCollector(); + + //! Set tests set title, supporting printf-like arguments + void SetTitle(const char *fmt, ...); + + //! Specify next test key + TestCase SetTestCase(const char *name, const char *mode, int threads); + //! Specify next test key + void SetTestCase(const TestCase &t) { SetTestCase(t.getName(), t.getMode(), t.getThreads()); } + //! Reserve specified number of rounds. Use for effeciency. Used mostly internally + void ReserveRounds(size_t index); + //! Add result of the measure + void AddRoundResult(const TestCase &, value_t v); + //! Add result of the current measure + void AddRoundResult(value_t v) { if(CurrentKey) AddRoundResult(TestCase(CurrentKey), v); } + //! Add title of round + void SetRoundTitle(size_t index, const char *fmt, ...); + //! Add numbered title of round + void SetRoundTitle(size_t index, int num) { SetRoundTitle(index, "%d", num); } + //! Get number of rounds + size_t GetRoundsCount() const { return RoundTitles.size(); } + // Set statistic value for the test + void AddStatisticValue(const TestCase &, const char *type, const char *fmt, ...); + // Set statistic value for the current test + void AddStatisticValue(const char *type, const char *fmt, ...); + //! Add Excel-processing formulas. @arg formula can contain more than one instances of + //! ROUNDS template which transforms into the range of cells with result values + //TODO://! #1 .. #n templates represent data cells from the first to the last + //TODO: merge with Analisis + void SetStatisticFormula(const char *name, const char *formula); + //! Add information about run or compile parameters + void SetRunInfo(const char *title, const char *fmt, ...); + void SetRunInfo(const char *title, int num) { SetRunInfo(title, "%d", num); } + + //! Data output + void Print(int dataOutput, const char *ModeName = "Mode"); + +private: + Sorting SortMode; +}; + +//! using: Func(const char *fmt, ...) { vargf2buff(buff, 128, fmt);... +#define vargf2buff(name, size, fmt) \ + char name[size]; memset(name, 0, size); \ + va_list args; va_start(args, fmt); \ + vsnprintf(name, size-1, fmt, args); \ + va_end(args); + + +inline std::string Format(const char *fmt, ...) { + vargf2buff(buf, 1024, fmt); // from statistics.h + return std::string(buf); +} + +#ifdef STATISTICS_INLINE +#include "statistics.cpp" +#endif +#endif //__STATISTICS_H__ diff --git a/src/tbb/src/perf/statistics_xml.h b/src/tbb/src/perf/statistics_xml.h new file mode 100644 index 0000000..c3aed3c --- /dev/null +++ b/src/tbb/src/perf/statistics_xml.h @@ -0,0 +1,208 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +const char XMLBRow[]= +" <Row>\n"; + +const char XMLERow[]= +" </Row>\n"; + +const char XMLHead[]= +"<?xml version=\"1.0\"?>\n" +"<?mso-application progid=\"Excel.Sheet\"?>\n\ +<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"\n\ + xmlns:o=\"urn:schemas-microsoft-com:office:office\"\n\ + xmlns:x=\"urn:schemas-microsoft-com:office:excel\"\n\ + xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"\n\ + xmlns:html=\"http://www.w3.org/TR/REC-html40\">\n\ + <DocumentProperties xmlns=\"urn:schemas-microsoft-com:office:office\">\n\ + <Author>%s</Author>\n\ + <Created>%s</Created>\n\ + <Company>Intel Corporation</Company>\n\ + </DocumentProperties>\n\ + <ExcelWorkbook xmlns=\"urn:schemas-microsoft-com:office:excel\">\n\ + <RefModeR1C1/>\n\ + </ExcelWorkbook>\n"; + + const char XMLStyles[]= + " <Styles>\n\ + <Style ss:ID=\"Default\" ss:Name=\"Normal\">\n\ + <Alignment ss:Vertical=\"Bottom\" ss:Horizontal=\"Left\" ss:WrapText=\"0\"/>\n\ + </Style>\n\ + <Style ss:ID=\"s26\">\n\ + <Alignment ss:Vertical=\"Top\" ss:Horizontal=\"Left\" ss:WrapText=\"0\"/>\n\ + <Borders>\n\ + <Border ss:Position=\"Bottom\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n\ + <Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n\ + <Border ss:Position=\"Right\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n\ + <Border ss:Position=\"Top\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n\ + </Borders>\n\ + <Interior ss:Color=\"#FFFF99\" ss:Pattern=\"Solid\"/>\n\ + </Style>\n\ + <Style ss:ID=\"s25\">\n\ + <Alignment ss:Vertical=\"Top\" ss:Horizontal=\"Left\" ss:WrapText=\"0\"/>\n\ + <Borders>\n\ + <Border ss:Position=\"Bottom\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n\ + <Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n\ + <Border ss:Position=\"Right\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n\ + <Border ss:Position=\"Top\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n\ + </Borders>\n\ + <Interior ss:Color=\"#CCFFFF\" ss:Pattern=\"Solid\"/>\n\ + </Style>\n\ + <Style ss:ID=\"s24\">\n\ + <Alignment ss:Vertical=\"Top\" ss:Horizontal=\"Left\" ss:WrapText=\"0\"/>\n\ + <Borders>\n\ + <Border ss:Position=\"Bottom\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n\ + <Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n\ + <Border ss:Position=\"Right\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n\ + <Border ss:Position=\"Top\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n\ + </Borders>\n\ + <Interior ss:Color=\"#CCFFCC\" ss:Pattern=\"Solid\"/>\n\ + </Style>\n\ + <Style ss:ID=\"s23\">\n\ + <Alignment ss:Vertical=\"Top\" ss:Horizontal=\"Left\" ss:WrapText=\"0\"/>\n\ + <Borders>\n\ + <Border ss:Position=\"Bottom\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n\ + <Border ss:Position=\"Left\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n\ + <Border ss:Position=\"Right\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n\ + <Border ss:Position=\"Top\" ss:LineStyle=\"Continuous\" ss:Weight=\"1\"/>\n\ + </Borders>\n\ + </Style>\n\ + </Styles>\n"; + +const char XMLBeginSheet[]= +" <Worksheet ss:Name=\"%s\">\n"; + +const char XMLNames[]= +" <Names>\n\ + <NamedRange ss:Name=\"_FilterDatabase\" ss:RefersTo=\"R%dC%d:R%dC%d\" ss:Hidden=\"1\"/>\n\ + </Names>\n"; + +const char XMLBeginTable[]= +" <Table ss:ExpandedColumnCount=\"%d\" ss:ExpandedRowCount=\"%d\" x:FullColumns=\"1\"\n\ + x:FullRows=\"1\">\n"; + +const char XMLColumsHorizontalTable[]= +" <Column ss:Index=\"1\" ss:Width=\"108.75\"/>\n\ + <Column ss:Index=\"%d\" ss:Width=\"77.25\" ss:Span=\"%d\"/>\n"; + +const char XMLColumsVerticalTable[]= +" <Column ss:Index=\"1\" ss:Width=\"77.25\" ss:Span=\"%d\"/>\n"; + +const char XMLNameAndTime[]= +" <Cell><Data ss:Type=\"String\">%s</Data></Cell>\n\ + <Cell><Data ss:Type=\"String\">%s</Data></Cell>\n\ + <Cell><Data ss:Type=\"String\">%s</Data></Cell>\n"; + +const char XMLTableParamAndTitle[]= +" <Cell><Data ss:Type=\"Number\">%d</Data></Cell>\n\ + <Cell><Data ss:Type=\"Number\">%d</Data></Cell>\n\ + <Cell><Data ss:Type=\"Number\">%d</Data></Cell>\n\ + <Cell><Data ss:Type=\"String\">%s</Data></Cell>\n"; + +//-------------- +const char XMLCellTopName[]= +" <Cell ss:StyleID=\"s25\"><Data ss:Type=\"String\">Name</Data></Cell>\n"; +const char XMLCellTopThread[]= +" <Cell ss:StyleID=\"s25\"><Data ss:Type=\"String\">Threads</Data></Cell>\n"; +const char XMLCellTopMode[]= +" <Cell ss:StyleID=\"s25\"><Data ss:Type=\"String\">%s</Data></Cell>\n"; +//--------------------- +const char XMLAnalysisTitle[]= +" <Cell ss:StyleID=\"s25\"><Data ss:Type=\"String\">%s</Data></Cell>\n"; + +const char XMLCellName[]= +" <Cell ss:StyleID=\"s24\"><Data ss:Type=\"String\">%s</Data></Cell>\n"; + +const char XMLCellThread[]= +" <Cell ss:StyleID=\"s24\"><Data ss:Type=\"Number\">%d</Data></Cell>\n"; + +const char XMLCellMode[]= +" <Cell ss:StyleID=\"s24\"><Data ss:Type=\"String\">%s</Data></Cell>\n"; + +const char XMLCellAnalysis[]= +" <Cell ss:StyleID=\"s26\"><Data ss:Type=\"String\">%s</Data></Cell>\n"; + +const char XMLCellFormula[]= +" <Cell ss:StyleID=\"s26\" ss:Formula=\"%s\"><Data ss:Type=\"Number\"></Data></Cell>\n"; + +const char XMLCellData[]= +" <Cell ss:StyleID=\"s23\"><Data ss:Type=\"Number\">%g</Data></Cell>\n"; + +const char XMLMergeRow[]= +" <Cell ss:StyleID=\"s23\" ss:MergeAcross=\"%d\" ><Data ss:Type=\"String\"></Data></Cell>\n"; + +const char XMLCellEmptyWhite[]= +" <Cell><Data ss:Type=\"String\">%s</Data></Cell>\n"; + +const char XMLCellEmptyTitle[]= +" <Cell ss:StyleID=\"s25\"><Data ss:Type=\"String\"></Data></Cell>\n"; + +const char XMLEndTable[]= +" </Table>\n"; + +const char XMLAutoFilter[]= +" <AutoFilter x:Range=\"R%dC%d:R%dC%d\" xmlns=\"urn:schemas-microsoft-com:office:excel\">\n\ + </AutoFilter>\n"; + +const char XMLEndWorkSheet[]= + " </Worksheet>\n"; + +const char XMLWorkSheetProperties[]= +" <WorksheetOptions xmlns=\"urn:schemas-microsoft-com:office:excel\">\n\ + <Unsynced/>\n\ + <Selected/>\n\ + <FreezePanes/>\n\ + <FrozenNoSplit/>\n\ + <SplitHorizontal>%d</SplitHorizontal>\n\ + <TopRowBottomPane>%d</TopRowBottomPane>\n\ + <SplitVertical>%d</SplitVertical>\n\ + <LeftColumnRightPane>%d</LeftColumnRightPane>\n\ + <ActivePane>0</ActivePane>\n\ + <Panes>\n\ + <Pane>\n\ + <Number>3</Number>\n\ + </Pane>\n\ + <Pane>\n\ + <Number>1</Number>\n\ + </Pane>\n\ + <Pane>\n\ + <Number>2</Number>\n\ + </Pane>\n\ + <Pane>\n\ + <Number>0</Number>\n\ + <ActiveRow>0</ActiveRow>\n\ + <ActiveCol>%d</ActiveCol>\n\ + </Pane>\n\ + </Panes>\n\ + <ProtectObjects>False</ProtectObjects>\n\ + <ProtectScenarios>False</ProtectScenarios>\n\ + </WorksheetOptions>\n"; + +const char XMLEndWorkbook[]= + "</Workbook>\n"; diff --git a/src/tbb/src/perf/time_framework.h b/src/tbb/src/perf/time_framework.h new file mode 100644 index 0000000..ffcde42 --- /dev/null +++ b/src/tbb/src/perf/time_framework.h @@ -0,0 +1,359 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TIME_FRAMEWORK_H__ +#define __TIME_FRAMEWORK_H__ + +#include <cstdlib> +#include <math.h> +#include <vector> +#include <string> +#include <sstream> +#include "tbb/tbb_stddef.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/tick_count.h" +#define HARNESS_CUSTOM_MAIN 1 +#include "../test/harness.h" +#include "../test/harness_barrier.h" +#define STATISTICS_INLINE +#include "statistics.h" + +#ifndef ARG_TYPE +typedef intptr_t arg_t; +#else +typedef ARG_TYPE arg_t; +#endif + +class Timer { + tbb::tick_count tick; +public: + Timer() { tick = tbb::tick_count::now(); } + double get_time() { return (tbb::tick_count::now() - tick).seconds(); } + double diff_time(const Timer &newer) { return (newer.tick - tick).seconds(); } + double mark_time() { tbb::tick_count t1(tbb::tick_count::now()), t2(tick); tick = t1; return (t1 - t2).seconds(); } + double mark_time(const Timer &newer) { tbb::tick_count t(tick); tick = newer.tick; return (tick - t).seconds(); } +}; + +class TesterBase /*: public tbb::internal::no_copy*/ { +protected: + friend class TestProcessor; + friend class TestRunner; + + //! it is barrier for synchronizing between threads + Harness::SpinBarrier *barrier; + + //! number of tests per this tester + const int tests_count; + + //! number of threads to operate + int threads_count; + + //! some value for tester + arg_t value; + + //! tester name + const char *tester_name; + + // avoid false sharing + char pad[128 - sizeof(arg_t) - sizeof(int)*2 - sizeof(void*)*2 ]; + +public: + //! init tester base. @arg ntests is number of embeded tests in this tester. + TesterBase(int ntests) + : barrier(NULL), tests_count(ntests) + {} + virtual ~TesterBase() {} + + //! internal function + void base_init(arg_t v, int t, Harness::SpinBarrier &b) { + threads_count = t; + barrier = &b; + value = v; + init(); + } + + //! optionally override to init after value and threads count were set. + virtual void init() { } + + //! Override to provide your names + virtual std::string get_name(int testn) { + return Format("test %d", testn); + } + + //! optionally override to init test mode just before execution for a given thread number. + virtual void test_prefix(int testn, int threadn) { } + + //! Override to provide main test's entry function returns a value to record + virtual value_t test(int testn, int threadn) = 0; + + //! Type of aggregation from results of threads + enum result_t { + SUM, AVG, MIN, MAX + }; + + //! Override to change result type for the test. Return postfix for test name or 0 if result type is not needed. + virtual const char *get_result_type(int /*testn*/, result_t type) const { + return type == AVG ? "" : 0; // only average result by default + } +}; + +/***** +a user's tester concept: + +class tester: public TesterBase { +public: + //! init tester with known amount of work + tester() : TesterBase(<user-specified tests count>) { ... } + + //! run a test with sequental number @arg test_number for @arg thread. + / *override* / value_t test(int test_number, int thread); +}; + +******/ + +template<typename Tester, int scale = 1> +class TimeTest : public Tester { + /*override*/ value_t test(int testn, int threadn) { + Timer timer; + Tester::test(testn, threadn); + return timer.get_time() * double(scale); + } +}; + +template<typename Tester> +class NanosecPerValue : public Tester { + /*override*/ value_t test(int testn, int threadn) { + Timer timer; + Tester::test(testn, threadn); + // return time (ns) per value + return timer.get_time()*1000000.0/double(Tester::value); + } +}; + +template<typename Tester, int scale = 1> +class ValuePerSecond : public Tester { + /*override*/ value_t test(int testn, int threadn) { + Timer timer; + Tester::test(testn, threadn); + // return value per seconds/scale + return double(Tester::value)/(timer.get_time()*scale); + } +}; + +template<typename Tester, int scale = 1> +class NumberPerSecond : public Tester { + /*override*/ value_t test(int testn, int threadn) { + Timer timer; + Tester::test(testn, threadn); + // return a scale per seconds + return double(scale)/timer.get_time(); + } +}; + +// operate with single tester +class TestRunner { + friend class TestProcessor; + friend struct RunArgsBody; + TestRunner(const TestRunner &); // don't copy + + const char *tester_name; + StatisticsCollector *stat; + std::vector<std::vector<StatisticsCollector::TestCase> > keys; + +public: + TesterBase &tester; + + template<typename Test> + TestRunner(const char *name, Test *test) + : tester_name(name), tester(*static_cast<TesterBase*>(test)) + { + test->tester_name = name; + } + + ~TestRunner() { delete &tester; } + + void init(arg_t value, int threads, Harness::SpinBarrier &barrier, StatisticsCollector *s) { + tester.base_init(value, threads, barrier); + stat = s; + keys.resize(tester.tests_count); + for(int testn = 0; testn < tester.tests_count; testn++) { + keys[testn].resize(threads); + std::string test_name(tester.get_name(testn)); + for(int threadn = 0; threadn < threads; threadn++) + keys[testn][threadn] = stat->SetTestCase(tester_name, test_name.c_str(), threadn); + } + } + + void run_test(int threadn) { + for(int testn = 0; testn < tester.tests_count; testn++) { + tester.test_prefix(testn, threadn); + tester.barrier->wait(); // <<<<<<<<<<<<<<<<< Barrier before running test mode + value_t result = tester.test(testn, threadn); + stat->AddRoundResult(keys[testn][threadn], result); + } + } + + void post_process(StatisticsCollector &report) { + const int threads = tester.threads_count; + for(int testn = 0; testn < tester.tests_count; testn++) { + size_t coln = keys[testn][0].getResults().size()-1; + value_t rsum = keys[testn][0].getResults()[coln]; + value_t rmin = rsum, rmax = rsum; + for(int threadn = 1; threadn < threads; threadn++) { + value_t result = keys[testn][threadn].getResults()[coln]; + rsum += result; // for both SUM or AVG + if(rmin > result) rmin = result; + if(rmax < result) rmax = result; + } + std::string test_name(tester.get_name(testn)); + const char *rname = tester.get_result_type(testn, TesterBase::SUM); + if( rname ) { + report.SetTestCase(tester_name, (test_name+rname).c_str(), threads); + report.AddRoundResult(rsum); + } + rname = tester.get_result_type(testn, TesterBase::MIN); + if( rname ) { + report.SetTestCase(tester_name, (test_name+rname).c_str(), threads); + report.AddRoundResult(rmin); + } + rname = tester.get_result_type(testn, TesterBase::AVG); + if( rname ) { + report.SetTestCase(tester_name, (test_name+rname).c_str(), threads); + report.AddRoundResult(rsum / threads); + } + rname = tester.get_result_type(testn, TesterBase::MAX); + if( rname ) { + report.SetTestCase(tester_name, (test_name+rname).c_str(), threads); + report.AddRoundResult(rmax); + } + } + } +}; + +struct RunArgsBody { + const vector<TestRunner*> &run_list; + RunArgsBody(const vector<TestRunner*> &a) : run_list(a) { } +#ifndef __TBB_parallel_for_H + void operator()(int thread) const { +#else + void operator()(const tbb::blocked_range<int> &r) const { + ASSERT( r.begin() + 1 == r.end(), 0); + int thread = r.begin(); +#endif + for(size_t i = 0; i < run_list.size(); i++) + run_list[i]->run_test(thread); + } +}; + +//! Main test processor. +/** Override or use like this: + class MyTestCollection : public TestProcessor { + void factory(arg_t value, int threads) { + process( value, threads, + run("my1", new tester<my1>() ), + run("my2", new tester<my2>() ), + end ); + if(value == threads) + stat->Print(); + } +}; +*/ + +class TestProcessor { + friend class TesterBase; + + // <threads, collector> + typedef std::map<int, StatisticsCollector *> statistics_collection; + statistics_collection stat_by_threads; + +protected: + // Members + const char *collection_name; + // current stat + StatisticsCollector *stat; + // token + size_t end; + +public: + StatisticsCollector report; + + // token of tests list + template<typename Test> + TestRunner *run(const char *name, Test *test) { + return new TestRunner(name, test); + } + + // iteration processing + void process(arg_t value, int threads, ...) { + // prepare items + stat = stat_by_threads[threads]; + if(!stat) { + stat_by_threads[threads] = stat = new StatisticsCollector((collection_name + Format("@%d", threads)).c_str(), StatisticsCollector::ByAlg); + stat->SetTitle("Detailed log of %s running with %d threads.", collection_name, threads); + } + Harness::SpinBarrier barrier(threads); + // init args + va_list args; va_start(args, threads); + vector<TestRunner*> run_list; run_list.reserve(16); + while(true) { + TestRunner *item = va_arg(args, TestRunner*); + if( !item ) break; + item->init(value, threads, barrier, stat); + run_list.push_back(item); + } + va_end(args); + std::ostringstream buf; + buf << value; + const size_t round_number = stat->GetRoundsCount(); + stat->SetRoundTitle(round_number, buf.str().c_str()); + report.SetRoundTitle(round_number, buf.str().c_str()); + // run them +#ifndef __TBB_parallel_for_H + NativeParallelFor(threads, RunArgsBody(run_list)); +#else + tbb::parallel_for(tbb::blocked_range<int>(0,threads,1), RunArgsBody(run_list)); +#endif + // destroy args + for(size_t i = 0; i < run_list.size(); i++) { + run_list[i]->post_process(report); + delete run_list[i]; + } + } + +public: + TestProcessor(const char *name, StatisticsCollector::Sorting sort_by = StatisticsCollector::ByAlg) + : collection_name(name), stat(NULL), end(0), report(collection_name, sort_by) + { } + + ~TestProcessor() { + for(statistics_collection::iterator i = stat_by_threads.begin(); i != stat_by_threads.end(); i++) + delete i->second; + } +}; + +#endif// __TIME_FRAMEWORK_H__ diff --git a/src/tbb/src/perf/time_hash_map.cpp b/src/tbb/src/perf/time_hash_map.cpp new file mode 100644 index 0000000..a3ee3c5 --- /dev/null +++ b/src/tbb/src/perf/time_hash_map.cpp @@ -0,0 +1,268 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// configuration: +#define TBB_USE_THREADING_TOOLS 0 + +//! enable/disable std::map tests +#define STDTABLE 0 + +//! enable/disable old implementation tests (correct include file also) +#define OLDTABLE 0 +#define OLDTABLEHEADER "tbb/concurrent_hash_map-5468.h"//-4329 + +//! enable/disable experimental implementation tests (correct include file also) +#define TESTTABLE 1 +#define TESTTABLEHEADER "tbb/concurrent_unordered_map.h" + +//! avoid erase() +#define TEST_ERASE 0 + +////////////////////////////////////////////////////////////////////////////////// + +#include <cstdlib> +#include <math.h> +#include "tbb/tbb_stddef.h" +#include <vector> +#include <map> +// needed by hash_maps +#include <stdexcept> +#include <iterator> +#include <algorithm> // std::swap +#include <utility> // Need std::pair from here +#include "tbb/cache_aligned_allocator.h" +#include "tbb/tbb_allocator.h" +#include "tbb/spin_rw_mutex.h" +#include "tbb/aligned_space.h" +#include "tbb/atomic.h" +#include "tbb/internal/_concurrent_unordered_impl.h" +// for test +#include "tbb/spin_mutex.h" +#include "time_framework.h" + + +using namespace tbb; +using namespace tbb::internal; + +struct IntHashCompare { + size_t operator() ( int x ) const { return x; } + bool operator() ( int x, int y ) const { return x==y; } + static long hash( int x ) { return x; } + bool equal( int x, int y ) const { return x==y; } +}; + +namespace version_current { + namespace tbb { using namespace ::tbb; namespace internal { using namespace ::tbb::internal; } } + namespace tbb { namespace interface5 { using namespace ::tbb::interface5; namespace internal { using namespace ::tbb::interface5::internal; } } } + #include "tbb/concurrent_hash_map.h" +} +typedef version_current::tbb::concurrent_hash_map<int,int> IntTable; + +#if OLDTABLE +#undef __TBB_concurrent_hash_map_H +namespace version_base { + namespace tbb { using namespace ::tbb; namespace internal { using namespace ::tbb::internal; } } + namespace tbb { namespace interface5 { using namespace ::tbb::interface5; namespace internal { using namespace ::tbb::interface5::internal; } } } + #include OLDTABLEHEADER +} +typedef version_base::tbb::concurrent_hash_map<int,int> OldTable; +#endif + +#if TESTTABLE +#undef __TBB_concurrent_hash_map_H +namespace version_new { + namespace tbb { using namespace ::tbb; namespace internal { using namespace ::tbb::internal; } } + namespace tbb { namespace interface5 { using namespace ::tbb::interface5; namespace internal { using namespace ::tbb::interface5::internal; } } } + #include TESTTABLEHEADER +} +typedef version_new::tbb::concurrent_unordered_map<int,int> TestTable; +#define TESTTABLE 1 +#endif + +/////////////////////////////////////// + +static const char *map_testnames[] = { + "1.insert", "2.count1st", "3.count2nd", "4.insert existing", "5.erase" +}; + +template<typename TableType> +struct TestTBBMap : TesterBase { + TableType Table; + int n_items; + + TestTBBMap() : TesterBase(4+TEST_ERASE), Table(MaxThread*4) {} + void init() { n_items = value/threads_count; } + + std::string get_name(int testn) { + return std::string(map_testnames[testn]); + } + + double test(int test, int t) + { + switch(test) { + case 0: // fill + for(int i = t*n_items, e = (t+1)*n_items; i < e; i++) { + Table.insert( std::make_pair(i,i) ); + } + break; + case 1: // work1 + for(int i = t*n_items, e = (t+1)*n_items; i < e; i++) { + size_t c = Table.count( i ); + ASSERT( c == 1, NULL); + } + break; + case 2: // work2 + for(int i = t*n_items, e = (t+1)*n_items; i < e; i++) { + Table.count( i ); + } + break; + case 3: // work3 + for(int i = t*n_items, e = (t+1)*n_items; i < e; i++) { + Table.insert( std::make_pair(i,i) ); + } + break; +#if TEST_ERASE + case 4: // clean + for(int i = t*n_items, e = (t+1)*n_items; i < e; i++) { + ASSERT( Table.erase( i ), NULL); + } +#endif + } + return 0; + } +}; + +template<typename M> +struct TestSTLMap : TesterBase { + std::map<int, int> Table; + M mutex; + + int n_items; + TestSTLMap() : TesterBase(4+TEST_ERASE) {} + void init() { n_items = value/threads_count; } + + std::string get_name(int testn) { + return std::string(map_testnames[testn]); + } + + double test(int test, int t) + { + switch(test) { + case 0: // fill + for(int i = t*n_items, e = (t+1)*n_items; i < e; i++) { + typename M::scoped_lock with(mutex); + Table[i] = 0; + } + break; + case 1: // work1 + for(int i = t*n_items, e = (t+1)*n_items; i < e; i++) { + typename M::scoped_lock with(mutex); + size_t c = Table.count(i); + ASSERT( c == 1, NULL); + } + break; + case 2: // work2 + for(int i = t*n_items, e = (t+1)*n_items; i < e; i++) { + typename M::scoped_lock with(mutex); + Table.count(i); + } + break; + case 3: // work3 + for(int i = t*n_items, e = (t+1)*n_items; i < e; i++) { + typename M::scoped_lock with(mutex); + Table.insert(std::make_pair(i,i)); + } + break; + case 4: // clean + for(int i = t*n_items, e = (t+1)*n_items; i < e; i++) { + typename M::scoped_lock with(mutex); + Table.erase(i); + } + } + return 0; + } +}; + +class fake_mutex { +public: + class scoped_lock { + fake_mutex *p; + + public: + scoped_lock() {} + scoped_lock( fake_mutex &m ) { p = &m; } + ~scoped_lock() { } + void acquire( fake_mutex &m ) { p = &m; } + void release() { } + }; +}; + +class test_hash_map : public TestProcessor { +public: + test_hash_map() : TestProcessor("test_hash_map") {} + void factory(int value, int threads) { + if(Verbose) printf("Processing with %d threads: %d...\n", threads, value); + process( value, threads, +#if STDTABLE + run("std::map ", new NanosecPerValue<TestSTLMap<spin_mutex> >() ), +#endif +#if OLDTABLE + run("old::hmap", new NanosecPerValue<TestTBBMap<OldTable> >() ), +#endif + run("tbb::hmap", new NanosecPerValue<TestTBBMap<IntTable> >() ), +#if TESTTABLE + run("new::hmap", new NanosecPerValue<TestTBBMap<TestTable> >() ), +#endif + end ); + //stat->Print(StatisticsCollector::Stdout); + //if(value >= 2097152) stat->Print(StatisticsCollector::HTMLFile); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////// + +int main(int argc, char* argv[]) { + if(argc>1) Verbose = true; + //if(argc>2) ExtraVerbose = true; + MinThread = 1; MaxThread = task_scheduler_init::default_num_threads(); + ParseCommandLine( argc, argv ); + + ASSERT(tbb_allocator<int>::allocator_type() == tbb_allocator<int>::scalable, "expecting scalable allocator library to be loaded. Please build it by:\n\t\tmake tbbmalloc"); + + { + test_hash_map the_test; + for( int t=MinThread; t <= MaxThread; t++) + for( int o=/*2048*/(1<<8)*8; o<2200000; o*=2 ) + the_test.factory(o, t); + the_test.report.SetTitle("Nanoseconds per operation of (Mode) for N items in container (Name)"); + the_test.report.SetStatisticFormula("1AVG per size", "=AVERAGE(ROUNDS)"); + the_test.report.Print(StatisticsCollector::HTMLFile|StatisticsCollector::ExcelXML); + } + return 0; +} + diff --git a/src/tbb/src/perf/time_hash_map_fill.cpp b/src/tbb/src/perf/time_hash_map_fill.cpp new file mode 100644 index 0000000..0c27b24 --- /dev/null +++ b/src/tbb/src/perf/time_hash_map_fill.cpp @@ -0,0 +1,170 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// configuration: + +// Size of final table (must be multiple of STEP_*) +int MAX_TABLE_SIZE = 2000000; + +// Specify list of unique percents (5-30,100) to test against. Max 10 values +#define UNIQUE_PERCENTS PERCENT(5); PERCENT(10); PERCENT(20); PERCENT(30); PERCENT(100) + +// enable/disable tests for: +#define BOX1 "CHMap" +#define BOX1TEST ValuePerSecond<Uniques<tbb::concurrent_hash_map<int,int> >, 1000000/*ns*/> +#define BOX1HEADER "tbb/concurrent_hash_map.h" + +// enable/disable tests for: +#define BOX2 "CUMap" +#define BOX2TEST ValuePerSecond<Uniques<tbb::concurrent_unordered_map<int,int> >, 1000000/*ns*/> +#define BOX2HEADER "tbb/concurrent_unordered_map.h" + +// enable/disable tests for: +//#define BOX3 "OLD" +#define BOX3TEST ValuePerSecond<Uniques<tbb::concurrent_hash_map<int,int> >, 1000000/*ns*/> +#define BOX3HEADER "tbb/concurrent_hash_map-5468.h" + +#define TBB_USE_THREADING_TOOLS 0 +////////////////////////////////////////////////////////////////////////////////// + +#include <cstdlib> +#include <math.h> +#include "tbb/tbb_stddef.h" +#include <vector> +#include <map> +// needed by hash_maps +#include <stdexcept> +#include <iterator> +#include <algorithm> // std::swap +#include <utility> // Need std::pair +#include <cstring> // Need std::memset +#include <typeinfo> +#include "tbb/cache_aligned_allocator.h" +#include "tbb/tbb_allocator.h" +#include "tbb/spin_rw_mutex.h" +#include "tbb/aligned_space.h" +#include "tbb/atomic.h" +#include "tbb/internal/_concurrent_unordered_impl.h" +// for test +#include "tbb/spin_mutex.h" +#include "time_framework.h" + + +using namespace tbb; +using namespace tbb::internal; + +///////////////////////////////////////////////////////////////////////////////////////// +// Input data built for test +int *Data; + +// Main test class used to run the timing tests. All overridden methods are called by the framework +template<typename TableType> +struct Uniques : TesterBase { + TableType Table; + int n_items; + + // Initializes base class with number of test modes + Uniques() : TesterBase(2), Table(MaxThread*16) { + //Table->max_load_factor(1); // add stub into hash_map to uncomment it + } + ~Uniques() {} + + // Returns name of test mode specified by number + /*override*/ std::string get_name(int testn) { + if(testn == 1) return "find"; + return "insert"; + } + + // Informs the class that value and threads number become known + /*override*/ void init() { + n_items = value/threads_count; // operations + } + + // Informs the class that the test mode for specified thread is about to start + /*override*/ void test_prefix(int testn, int t) { + barrier->wait(); + if(Verbose && !t && testn) printf("%s: inserted %u, %g%% of operations\n", tester_name, unsigned(Table.size()), 100.0*Table.size()/(value*testn)); + } + + // Executes test mode for a given thread. Return value is ignored when used with timing wrappers. + /*override*/ double test(int testn, int t) + { + if( testn != 1 ) { // do insertions + for(int i = testn*value+t*n_items, e = testn*value+(t+1)*n_items; i < e; i++) { + Table.insert( std::make_pair(Data[i],t) ); + } + } else { // do last finds + for(int i = t*n_items, e = (t+1)*n_items; i < e; i++) { + size_t c = + Table.count( Data[i] ); + ASSERT( c == 1, NULL ); // must exist + } + } + return 0; + } +}; + +///////////////////////////////////////////////////////////////////////////////////////// +#include <limits> + +// Using BOX declarations from configuration +#include "time_sandbox.h" + +int rounds = 0; +// Prepares the input data for given unique percent +void execute_percent(test_sandbox &the_test, int p) { + int input_size = MAX_TABLE_SIZE*100/p; + Data = new int[input_size]; + int uniques = p==100?std::numeric_limits<int>::max() : MAX_TABLE_SIZE; + ASSERT(p==100 || p <= 30, "Function is broken for %% > 30 except for 100%%"); + for(int i = 0; i < input_size; i++) + Data[i] = rand()%uniques; + for(int t = MinThread; t <= MaxThread; t++) + the_test.factory(input_size, t); // executes the tests specified in BOX-es for given 'value' and threads + the_test.report.SetRoundTitle(rounds++, "%d%%", p); +} +#define PERCENT(x) execute_percent(the_test, x) + +int main(int argc, char* argv[]) { + if(argc>1) Verbose = true; + //if(argc>2) ExtraVerbose = true; + MinThread = 1; MaxThread = task_scheduler_init::default_num_threads(); + ParseCommandLine( argc, argv ); + if(getenv("TABLE_SIZE")) + MAX_TABLE_SIZE = atoi(getenv("TABLE_SIZE")); + + ASSERT(tbb_allocator<int>::allocator_type() == tbb_allocator<int>::scalable, "expecting scalable allocator library to be loaded. Please build it by:\n\t\tmake tbbmalloc"); + // Declares test processor + test_sandbox the_test("time_hash_map_fill"/*, StatisticsCollector::ByThreads*/); + srand(10101); + UNIQUE_PERCENTS; // test the percents + the_test.report.SetTitle("Operations per nanosecond"); + the_test.report.SetRunInfo("Items", MAX_TABLE_SIZE); + the_test.report.Print(StatisticsCollector::HTMLFile|StatisticsCollector::ExcelXML); // Write files + return 0; +} diff --git a/src/tbb/src/perf/time_hash_map_fill.html b/src/tbb/src/perf/time_hash_map_fill.html new file mode 100644 index 0000000..5d62c3a --- /dev/null +++ b/src/tbb/src/perf/time_hash_map_fill.html @@ -0,0 +1,120 @@ +<HTML><BODY> +<H2>time_hash_map_fill</H2> +<P><a href=time_hash_map_fill.cpp>time_hash_map_fill.cpp</a> is a micro-benchmark specifically designed to highlight aspects of concurrent resizing algorithm of the hash tables. +It was derived from the Count Strings example that counts the number of unique words. But to exclude synchronization on the counters from the picture, +it was simplified to build just a set of unique numbers from an input array. The array is filled evenly by using a pseudo-random number generator from the standard C library for various proportions of unique numbers. +For example, for 5% of unique numbers, the same number is repeated 20 times on average. Together, it gives 5% of actual insertions and 95% are just lookups. However, in the beginning, there are more new keys occur than in the end. +In addition, a size of the source array correlates with input rates in order to produce the same number of unique keys at the end, and so exclude cache effects from the equation. +<H2>Diagram</H2><img src="time_hash_map_fill.gif"> +<H3>Prepare results</H3> +<P>This benchmark outputs results in Excel* and html file formats by default. To generate text (CSV) file instead, specify STAT_FORMAT=pivot-csv evironment variable. To change the default table size, set TABLE_SIZE. +<code><b><pre>src$ make time_hash_map_fill args=-v STAT_FORMAT=pivot-csv TABLE_SIZE=250000</pre></b></code>Or to get statistics from different runs: +<code><b><pre>src$ make time_hash_map_fill TABLE_SIZE=50000 run_cmd="bash ../../src/perf/<a href=run_statistics.sh>run_statistics.sh</a>"</pre></b></code> +<H3>Build diagram</H3>You can use <a href="http://ploticus.sourceforge.net/">Ploticus</a> to build diagram from the prepared data using this html file as a script. But first, the input data file should be sorted to join lines from different runs together, e.g.: +<code><b><pre>src$ sort -t , -k 1dr,2 -k 3n,4 -k 7n,7 ../build/<i>{scrambled_path}</i>/time_hash_map_fill.csv -o perf/time_hash_map_fill.csv</pre></b></code>Here, field 7 is "Column" field that contains input rates because run_statistics.sh adds hostname and number of the run as 5 and 6 fields. Now, to build gif diagram, run: +<code><b><pre>perf$ pl -maxrows 200000 -maxfields 1500000 -maxvector 1200000 -gif -scale 1.8 time_hash_map_fill.html</pre></b></code> +<H3>Script body</H3> +<hr><pre> + +#setifnotgiven NAMES = $makelist("1.CHMap 2.CUMap 3.OLD") +#setifnotgiven LABLESIZE = 0.06 + +#proc settings + encodenames: yes + units: cm + +#proc getdata + file: time_hash_map_fill.csv + fieldnameheader: yes + delim: comma + showdata: no + select: @@Mode = insert + pf_fieldnames: Name Mode Threads Value + filter: + ##print @@Name,"@@Items on @@Column",@@3,@@Value + +#endproc + +#proc page + pagesize: 70 50 + tightcrop: yes +#endproc + +#proc processdata + action: summary + fields: Name Mode Threads + valfield: Value + fieldnames: Name Mode Threads Average sd sem n_obs Min Max + showdata: no + +#proc categories + axis: x + datafield: Mode + +#proc areadef + title: Throughput on Insert operation + titledetails: size=14 align=C + areaname: slide + xscaletype: categories + xautorange: datafield=Mode + xaxis.stubs: usecategories + xaxis.label: Threads across table sizes and % of input rates +// yrange: 0 70 + yautorange: datafield=Max,Min + yaxis.stubs: inc + yaxis.label: ops/ns +// yaxis.stubformat: %3.1f + autowidth: 1.1 + autoheight: 0.07 + frame: yes + +#for LABEL in @NAMES +#set NLABEL = $arithl(@NLABEL+1) +#set COLOR = $icolor( @NLABEL ) +#proc legendentry + label: @LABEL + sampletype: color + details: @COLOR + +#procdef catlines + select: @Name = @LABEL + catfield: Mode + subcatfield: Threads + subcats: auto + plotwidth: 0.8 + #saveas C + +#proc catlines + #clone C + dpsymbol: shape=square radius=@LABLESIZE style=solid color=@COLOR + valfield: Average + errfield: sd + +#proc catlines + #clone C + valfield: Max + dpsymbol: shape=triangle radius=@LABLESIZE style=solid color=@COLOR + +#proc catlines + #clone C + valfield: Min + dpsymbol: shape=downtriangle radius=@LABLESIZE style=solid color=@COLOR + +#endloop + +#proc legend + location: 3.2 max + seglen: 0.2 +#endproc +</pre> +<HR> +<A HREF="../index.html">Up to parent directory</A> +<p></p> +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +<P></P> +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +<p></p> +* Other names and brands may be claimed as the property of others. +</BODY> +</HTML> diff --git a/src/tbb/src/perf/time_locked_work.cpp b/src/tbb/src/perf/time_locked_work.cpp new file mode 100644 index 0000000..30255f5 --- /dev/null +++ b/src/tbb/src/perf/time_locked_work.cpp @@ -0,0 +1,174 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +////// Test configuration //////////////////////////////////////////////////// +#define SECONDS_RATIO 1000000 // microseconds + +#ifndef REPEAT_K +#define REPEAT_K 50 // repeat coefficient +#endif + +int outer_work[] = {/*256,*/ 64, 16, 4, 0}; +int inner_work[] = {32, 8, 0 }; + +// keep it to calibrate the time of work without synchronization +#define BOX1 "baseline" +#define BOX1TEST TimeTest< TBB_Mutex<tbb::null_mutex>, SECONDS_RATIO > + +// enable/disable tests for: +#define BOX2 "spin_mutex" +#define BOX2TEST TimeTest< TBB_Mutex<tbb::spin_mutex>, SECONDS_RATIO > + +// enable/disable tests for: +#define BOX3 "spin_rw_mutex" +#define BOX3TEST TimeTest< TBB_Mutex<tbb::spin_rw_mutex>, SECONDS_RATIO > + +// enable/disable tests for: +#define BOX4 "queuing_mutex" +#define BOX4TEST TimeTest< TBB_Mutex<tbb::queuing_mutex>, SECONDS_RATIO > + +// enable/disable tests for: +//#define BOX5 "queuing_rw_mutex" +#define BOX5TEST TimeTest< TBB_Mutex<tbb::queuing_rw_mutex>, SECONDS_RATIO > + +////////////////////////////////////////////////////////////////////////////// + +#include <cstdlib> +#include <math.h> +#include <algorithm> // std::swap +#include <utility> // Need std::pair from here +#include <sstream> +#include "tbb/tbb_stddef.h" +#include "tbb/null_mutex.h" +#include "tbb/spin_rw_mutex.h" +#include "tbb/spin_mutex.h" +#include "tbb/queuing_mutex.h" +#include "tbb/queuing_rw_mutex.h" +#include "tbb/mutex.h" + +#if INTEL_TRIAL==2 +#include "tbb/parallel_for.h" // enable threading by TBB scheduler +#include "tbb/task_scheduler_init.h" +#include "tbb/blocked_range.h" +#endif +// for test +#include "time_framework.h" + +using namespace tbb; +using namespace tbb::internal; + +///////////////////////////////////////////////////////////////////////////////////////// + +//! base class for tests family +struct TestLocks : TesterBase { + // Inherits "value", "threads_count", and other variables + TestLocks() : TesterBase(/*number of modes*/sizeof(outer_work)/sizeof(int)) {} + //! returns name of test part/mode + /*override*/std::string get_name(int testn) { + std::ostringstream buf; + buf.width(4); buf.fill('0'); + buf << outer_work[testn]; // mode number + return buf.str(); + } + //! enables results types and returns theirs suffixes + /*override*/const char *get_result_type(int, result_t type) const { + switch(type) { + case MIN: return " min"; + case MAX: return " max"; + default: return 0; + } + } + //! repeats count + int repeat_until(int /*test_n*/) const { + return REPEAT_K*100;//TODO: suggest better? + } + //! fake work + void do_work(int work) volatile { + for(int i = 0; i < work; i++) { + volatile int x = i; + __TBB_Pause(0); // just to call inline assembler + x *= work/threads_count; + } + } +}; + +//! template test unit for any of TBB mutexes +template<typename M> +struct TBB_Mutex : TestLocks { + M mutex; + + double test(int testn, int /*threadn*/) + { + for(int r = 0; r < repeat_until(testn); ++r) { + do_work(outer_work[testn]); + { + typename M::scoped_lock with(mutex); + do_work(/*inner work*/value); + } + } + return 0; + } +}; + +///////////////////////////////////////////////////////////////////////////////////////// + +//Using BOX declarations +#include "time_sandbox.h" + +// run tests for each of inner work value +void RunLoops(test_sandbox &the_test, int thread) { + for( unsigned i=0; i<sizeof(inner_work)/sizeof(int); ++i ) + the_test.factory(inner_work[i], thread); +} + +int main(int argc, char* argv[]) { + if(argc>1) Verbose = true; + int DefThread = task_scheduler_init::default_num_threads(); + MinThread = 1; MaxThread = DefThread+1; + ParseCommandLine( argc, argv ); + ASSERT(MinThread <= MaxThread, 0); +#if INTEL_TRIAL && defined(__TBB_parallel_for_H) + task_scheduler_init me(MaxThread); +#endif + { + test_sandbox the_test("time_locked_work", StatisticsCollector::ByThreads); + //TODO: refactor this out as RunThreads(test&) + for( int t = MinThread; t < DefThread && t <= MaxThread; t *= 2) + RunLoops( the_test, t ); // execute undersubscribed threads + if( DefThread > MinThread && DefThread <= MaxThread ) + RunLoops( the_test, DefThread ); // execute on all hw threads + if( DefThread < MaxThread) + RunLoops( the_test, MaxThread ); // execute requested oversubscribed threads + + the_test.report.SetTitle("Time of lock/unlock for mutex Name with Outer and Inner work"); + //the_test.report.SetStatisticFormula("1AVG per size", "=AVERAGE(ROUNDS)"); + the_test.report.Print(StatisticsCollector::HTMLFile|StatisticsCollector::ExcelXML, /*ModeName*/ "Outer work"); + } + return 0; +} + diff --git a/src/tbb/src/perf/time_lru_cache_throughput.cpp b/src/tbb/src/perf/time_lru_cache_throughput.cpp new file mode 100644 index 0000000..63e04f2 --- /dev/null +++ b/src/tbb/src/perf/time_lru_cache_throughput.cpp @@ -0,0 +1,224 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "../examples/common/utility/utility.h" +#include "tbb/tick_count.h" +//#include <tbb/parallel_for.h> +#include "tbb/task_scheduler_init.h" //for number of threads +#include <functional> + +#include "coarse_grained_raii_lru_cache.h" +#define TBB_PREVIEW_CONCURRENT_LRU_CACHE 1 +#include "tbb/concurrent_lru_cache.h" + +#define HARNESS_CUSTOM_MAIN 1 +#define HARNESS_NO_PARSE_COMMAND_LINE 1 + +#include "../src/test/harness.h" +#include "../src/test/harness_barrier.h" + +#include <vector> +#include <algorithm> +#include "tbb/mutex.h" + +//TODO: probably move this to separate header utlity file +namespace micro_benchmarking{ +namespace utils{ + template <typename type> + void disable_elimination(type const& v){ + volatile type dummy = v; + (void) dummy; + } + //Busy work and calibration helpers + unsigned int one_us_iters = 345; // default value + + //TODO: add a CLI parameter for calibration run + // if user wants to calibrate to microseconds on particular machine, call + // this at beginning of program; sets one_us_iters to number of iters to + // busy_wait for approx. 1 us + void calibrate_busy_wait() { + tbb::tick_count t0 = tbb::tick_count::now(); + for (volatile unsigned int i=0; i<1000000; ++i) continue; + tbb::tick_count t1 = tbb::tick_count::now(); + + one_us_iters = (unsigned int)((1000000.0/(t1-t0).seconds())*0.000001); + } + + void busy_wait(int us) + { + unsigned int iter = us*one_us_iters; + for (volatile unsigned int i=0; i<iter; ++i) continue; + } +} +} + +struct parameter_pack{ + size_t time_window_sec; + size_t time_check_granularity_ops; + size_t cache_lru_history_size; + size_t time_of_item_use_usec; + size_t cache_miss_percent; + int threads_number; + size_t weight_of_initiation_call_usec; + bool use_serial_initiation_function; + parameter_pack( + size_t a_time_window_sec + ,size_t a_time_check_granularity_ops + ,size_t a_cache_lru_history_size + ,size_t a_time_of_item_use_usec, size_t a_cache_miss_percent + , int a_threads_number ,size_t a_weight_of_initiation_call_usec + , bool a_use_serial_initiation_function + ) : + time_window_sec(a_time_window_sec) + ,time_check_granularity_ops(a_time_check_granularity_ops) + ,cache_lru_history_size(a_cache_lru_history_size) + ,time_of_item_use_usec(a_time_of_item_use_usec) + ,cache_miss_percent(a_cache_miss_percent) + ,threads_number(a_threads_number) + ,weight_of_initiation_call_usec(a_weight_of_initiation_call_usec) + ,use_serial_initiation_function(a_use_serial_initiation_function) + {} +}; + +struct return_size_t { + size_t m_weight_of_initiation_call_usec; + bool use_serial_initiation_function; + return_size_t(size_t a_weight_of_initiation_call_usec, bool a_use_serial_initiation_function) + :m_weight_of_initiation_call_usec(a_weight_of_initiation_call_usec), use_serial_initiation_function(a_use_serial_initiation_function) + {} + size_t operator()(size_t key){ + static tbb::mutex mtx; + if (use_serial_initiation_function){ + mtx.lock(); + } + micro_benchmarking::utils::busy_wait(m_weight_of_initiation_call_usec); + if (use_serial_initiation_function){ + mtx.unlock(); + } + + return key; + } +}; + +template< typename a_cache_type> +struct throughput { + typedef throughput self_type; + typedef a_cache_type cache_type; + + parameter_pack m_parameter_pack; + + + const size_t per_thread_sample_size ; + typedef std::vector<size_t> access_sequence_type; + access_sequence_type m_access_sequence; + cache_type m_cache; + Harness::SpinBarrier m_barrier; + tbb::atomic<size_t> loops_count; + + throughput(parameter_pack a_parameter_pack) + :m_parameter_pack(a_parameter_pack) + ,per_thread_sample_size(m_parameter_pack.cache_lru_history_size *(1 + m_parameter_pack.cache_miss_percent/100)) + ,m_access_sequence(m_parameter_pack.threads_number * per_thread_sample_size ) + ,m_cache(return_size_t(m_parameter_pack.weight_of_initiation_call_usec,m_parameter_pack.use_serial_initiation_function),m_parameter_pack.cache_lru_history_size) + + { + loops_count=0; + //TODO: check if changing from generating longer sequence to generating indexes in a specified range (i.e. making per_thread_sample_size fixed) give any change + std::generate(m_access_sequence.begin(),m_access_sequence.end(),std::rand); + } + + size_t operator()(){ + struct _{ static void retrieve_from_cache(self_type* _this, size_t thread_index){ + parameter_pack& p = _this->m_parameter_pack; + access_sequence_type::iterator const begin_it =_this->m_access_sequence.begin()+ thread_index * _this->per_thread_sample_size; + access_sequence_type::iterator const end_it = begin_it + _this->per_thread_sample_size; + + _this->m_barrier.wait(); + tbb::tick_count start = tbb::tick_count::now(); + + size_t local_loops_count =0; + do { + size_t part_of_the_sample_so_far = (local_loops_count * p.time_check_granularity_ops) % _this->per_thread_sample_size; + access_sequence_type::iterator const iteration_begin_it = begin_it + part_of_the_sample_so_far; + access_sequence_type::iterator const iteration_end_it = iteration_begin_it + + (std::min)(p.time_check_granularity_ops, _this->per_thread_sample_size - part_of_the_sample_so_far); + + for (access_sequence_type::iterator it = iteration_begin_it; it < iteration_end_it; ++it){ + typename cache_type::handle h = _this->m_cache(*it); + micro_benchmarking::utils::busy_wait(p.time_of_item_use_usec); + micro_benchmarking::utils::disable_elimination(h.value()); + } + ++local_loops_count; + }while((tbb::tick_count::now()-start).seconds() < p.time_window_sec); + _this->loops_count+=local_loops_count; + }}; + m_barrier.initialize(m_parameter_pack.threads_number); + + NativeParallelFor(m_parameter_pack.threads_number,std::bind1st(std::ptr_fun(&_::retrieve_from_cache),this)); + + return loops_count * m_parameter_pack.time_check_granularity_ops; + } +}; + +int main(int argc,const char** args ){ + + size_t time_window_sec = 10; + size_t cache_lru_history_size = 1000; + size_t time_check_granularity_ops = 200; + size_t time_of_item_use_usec = 100; + size_t cache_miss_percent = 5; + int threads_number =tbb::task_scheduler_init::default_num_threads(); + size_t weight_of_initiation_call_usec =1000; + bool use_serial_initiation_function = false; + bool use_coarse_grained_locked_cache = false; + + parameter_pack p(time_window_sec, time_check_granularity_ops, cache_lru_history_size,time_of_item_use_usec,cache_miss_percent,threads_number,weight_of_initiation_call_usec,use_serial_initiation_function); + + utility::parse_cli_arguments(argc,args,utility::cli_argument_pack() + .arg(p.cache_lru_history_size,"cache-lru-history-size","") + .arg(p.time_window_sec,"time-window","time frame for measuring, in seconds") + .arg(p.threads_number,"n-of-threads","number of threads to run on") + .arg(p.time_of_item_use_usec,"time-of-item-use","time between consequent requests to the cache, in microseconds") + .arg(p.cache_miss_percent,"cache-miss-percent","cache miss percent ") + .arg(p.weight_of_initiation_call_usec,"initiation-call-weight","time occupied by a single call to initiation function, in microseconds") + .arg(p.use_serial_initiation_function,"use-serial-initiation-function","limit lock-based serial initiation function") + .arg(use_coarse_grained_locked_cache,"use-locked-version","use stl coarse grained lock based version") + ); + + typedef tbb::concurrent_lru_cache<size_t,size_t,return_size_t> tbb_cache; + typedef coarse_grained_raii_lru_cache<size_t,size_t,return_size_t> coarse_grained_locked_cache; + + size_t operations =0; + if (!use_coarse_grained_locked_cache){ + operations = throughput<tbb_cache>(p)(); + }else{ + operations = throughput<coarse_grained_locked_cache>(p)(); + } + std::cout<<"operations: "<<operations<<std::endl; + return 0; +} diff --git a/src/tbb/src/perf/time_sandbox.h b/src/tbb/src/perf/time_sandbox.h new file mode 100644 index 0000000..76cf975 --- /dev/null +++ b/src/tbb/src/perf/time_sandbox.h @@ -0,0 +1,179 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TIME_FRAMEWORK_H__ +#error time_framework.h must be included +#endif + +#define INJECT_TBB namespace tbb { using namespace ::tbb; namespace internal { using namespace ::tbb::internal; } } +#define INJECT_TBB5 namespace tbb { namespace interface5 { using namespace ::tbb::interface5; namespace internal { using namespace ::tbb::interface5::internal; } } } + +#ifndef INJECT_BOX_NAMES +#if defined(__TBB_task_H) || defined(__TBB_concurrent_unordered_internal_H) || defined(__TBB_reader_writer_lock_H) +#define INJECT_BOX_NAMES INJECT_TBB INJECT_TBB5 +#else +#define INJECT_BOX_NAMES INJECT_TBB +#endif +#endif + +#ifdef BOX1 +namespace sandbox1 { + INJECT_BOX_NAMES +# ifdef BOX1HEADER +# include BOX1HEADER +# endif + typedef ::BOX1TEST testbox; +} +#endif +#ifdef BOX2 +namespace sandbox2 { + INJECT_BOX_NAMES +# ifdef BOX2HEADER +# include BOX2HEADER +# endif + typedef ::BOX2TEST testbox; +} +#endif +#ifdef BOX3 +namespace sandbox3 { + INJECT_BOX_NAMES +# ifdef BOX3HEADER +# include BOX3HEADER +# endif + typedef ::BOX3TEST testbox; +} +#endif +#ifdef BOX4 +namespace sandbox4 { + INJECT_BOX_NAMES +# ifdef BOX4HEADER +# include BOX4HEADER +# endif + typedef ::BOX4TEST testbox; +} +#endif +#ifdef BOX5 +namespace sandbox5 { + INJECT_BOX_NAMES +# ifdef BOX5HEADER +# include BOX5HEADER +# endif + typedef ::BOX5TEST testbox; +} +#endif +#ifdef BOX6 +namespace sandbox6 { + INJECT_BOX_NAMES +# ifdef BOX6HEADER +# include BOX6HEADER +# endif + typedef ::BOX6TEST testbox; +} +#endif +#ifdef BOX7 +namespace sandbox7 { + INJECT_BOX_NAMES +# ifdef BOX7HEADER +# include BOX7HEADER +# endif + typedef ::BOX7TEST testbox; +} +#endif +#ifdef BOX8 +namespace sandbox8 { + INJECT_BOX_NAMES +# ifdef BOX8HEADER +# include BOX8HEADER +# endif + typedef ::BOX8TEST testbox; +} +#endif +#ifdef BOX9 +namespace sandbox9 { + INJECT_BOX_NAMES +# ifdef BOX9HEADER +# include BOX9HEADER +# endif + typedef ::BOX9TEST testbox; +} +#endif + +//if harness.h included +#if defined(ASSERT) && !HARNESS_NO_PARSE_COMMAND_LINE +#ifndef TEST_PREFIX +#define TEST_PREFIX if(Verbose) printf("Processing with %d threads: %ld...\n", threads, long(value)); +#endif +#endif//harness included + +#ifndef TEST_PROCESSOR_NAME +#define TEST_PROCESSOR_NAME test_sandbox +#endif + +class TEST_PROCESSOR_NAME : public TestProcessor { +public: + TEST_PROCESSOR_NAME(const char *name, StatisticsCollector::Sorting sort_by = StatisticsCollector::ByAlg) + : TestProcessor(name, sort_by) {} + void factory(arg_t value, int threads) { +#ifdef TEST_PREFIX + TEST_PREFIX +#endif + process( value, threads, +#define RUNBOX(n) run(#n"."BOX##n, new sandbox##n::testbox() ) +#ifdef BOX1 + RUNBOX(1), +#endif +#ifdef BOX2 + RUNBOX(2), +#endif +#ifdef BOX3 + RUNBOX(3), +#endif +#ifdef BOX4 + RUNBOX(4), +#endif +#ifdef BOX5 + RUNBOX(5), +#endif +#ifdef BOX6 + RUNBOX(6), +#endif +#ifdef BOX7 + RUNBOX(7), +#endif +#ifdef BOX8 + RUNBOX(8), +#endif +#ifdef BOX9 + RUNBOX(9), +#endif + end ); +#ifdef TEST_POSTFIX + TEST_POSTFIX +#endif + } +}; diff --git a/src/tbb/src/perf/time_vector.cpp b/src/tbb/src/perf/time_vector.cpp new file mode 100644 index 0000000..951c0c0 --- /dev/null +++ b/src/tbb/src/perf/time_vector.cpp @@ -0,0 +1,257 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +//#define DO_SCALABLEALLOC + +#include <cstdlib> +#include <cmath> +#include <vector> +#include <algorithm> +#include <functional> +#include <numeric> +#include "tbb/tbb_stddef.h" +#include "tbb/spin_mutex.h" +#ifdef DO_SCALABLEALLOC +#include "tbb/scalable_allocator.h" +#endif +#include "tbb/concurrent_vector.h" +#include "tbb/tbb_allocator.h" +#include "tbb/cache_aligned_allocator.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/parallel_for.h" +#include "tbb/tick_count.h" +#include "tbb/blocked_range.h" +#define HARNESS_CUSTOM_MAIN 1 +#include "../test/harness.h" +//#include "harness_barrier.h" +#include "../test/harness_allocator.h" +#define STATISTICS_INLINE +#include "statistics.h" + +using namespace tbb; +bool ExtraVerbose = false; + +class Timer { + tbb::tick_count tick; +public: + Timer() { tick = tbb::tick_count::now(); } + double get_time() { return (tbb::tick_count::now() - tick).seconds(); } + double diff_time(const Timer &newer) { return (newer.tick - tick).seconds(); } + double mark_time() { tick_count t1(tbb::tick_count::now()), t2(tick); tick = t1; return (t1 - t2).seconds(); } + double mark_time(const Timer &newer) { tick_count t(tick); tick = newer.tick; return (tick - t).seconds(); } +}; + +/************************************************************************/ +/* TEST1 */ +/************************************************************************/ +#define mk_vector_test1(v, a) vector_test1<v<Timer, static_counting_allocator<a<Timer> > >, v<double, static_counting_allocator<a<double> > > > +template<class timers_vector_t, class values_vector_t> +class vector_test1 { + const char *mode; + StatisticsCollector &stat; + StatisticsCollector::TestCase key[16]; + +public: + vector_test1(const char *m, StatisticsCollector &s) : mode(m), stat(s) {} + + vector_test1 &operator()(size_t len) { + if(Verbose) printf("test1<%s>(%u): collecting timing statistics\n", mode, unsigned(len)); + __TBB_ASSERT(sizeof(Timer) == sizeof(double), NULL); + static const char *test_names[] = { + "b)creation wholly", + "a)creation by push", + "c)operation time per item", + 0 }; + for(int i = 0; test_names[i]; ++i) key[i] = stat.SetTestCase(test_names[i], mode, len); + + Timer timer0; timers_vector_t::allocator_type::init_counters(); + timers_vector_t tv(len); + Timer timer1; values_vector_t::allocator_type::init_counters(); + values_vector_t dv; + for (size_t i = 0; i < len; ++i) + dv.push_back( i ); + Timer timer2; + for (size_t i = 0; i < len; ++i) + { + dv[len-i-1] = timer0.diff_time(tv[i]); + tv[i].mark_time(); + } + stat.AddStatisticValue( key[2], "1total, ms", "%.3f", timer2.get_time()*1000.0 ); + stat.AddStatisticValue( key[1], "1total, ms", "%.3f", timer1.diff_time(timer2)*1000.0 ); + stat.AddStatisticValue( key[0], "1total, ms", "%.3f", timer0.diff_time(timer1)*1000.0 ); + //allocator statistics + stat.AddStatisticValue( key[0], "2total allocations", "%d", int(timers_vector_t::allocator_type::allocations) ); + stat.AddStatisticValue( key[1], "2total allocations", "%d", int(values_vector_t::allocator_type::allocations) ); + stat.AddStatisticValue( key[2], "2total allocations", "%d", 0); + stat.AddStatisticValue( key[0], "3total alloc#items", "%d", int(timers_vector_t::allocator_type::items_allocated) ); + stat.AddStatisticValue( key[1], "3total alloc#items", "%d", int(values_vector_t::allocator_type::items_allocated) ); + stat.AddStatisticValue( key[2], "3total alloc#items", "%d", 0); + //remarks + stat.AddStatisticValue( key[0], "9note", "segment creation time, ns:"); + stat.AddStatisticValue( key[2], "9note", "average op-time per item, ns:"); + Timer last_timer(timer2); double last_value = 0; + for (size_t j = 0, i = 2; i < len; i *= 2, j++) { + stat.AddRoundResult( key[0], (dv[len-i-1]-last_value)*1000000.0 ); + last_value = dv[len-i-1]; + stat.AddRoundResult( key[2], last_timer.diff_time(tv[i])/double(i)*1000000.0 ); + last_timer = tv[i]; + stat.SetRoundTitle(j, i); + } + tv.clear(); dv.clear(); + //__TBB_ASSERT(timers_vector_t::allocator_type::items_allocated == timers_vector_t::allocator_type::items_freed, NULL); + //__TBB_ASSERT(values_vector_t::allocator_type::items_allocated == values_vector_t::allocator_type::items_freed, NULL); + return *this; + } +}; + +/************************************************************************/ +/* TEST2 */ +/************************************************************************/ +#define mk_vector_test2(v, a) vector_test2<v<size_t, a<size_t> > > +template<class vector_t> +class vector_test2 { + const char *mode; + static const int ntrial = 10; + StatisticsCollector &stat; + +public: + vector_test2(const char *m, StatisticsCollector &s) : mode(m), stat(s) {} + + vector_test2 &operator()(size_t len) { + if(Verbose) printf("test2<%s>(%u): performing standard transformation sequence on vector\n", mode, unsigned(len)); + StatisticsCollector::TestCase init_key = stat.SetTestCase("allocate", mode, len); + StatisticsCollector::TestCase fill_key = stat.SetTestCase("fill", mode, len); + StatisticsCollector::TestCase proc_key = stat.SetTestCase("process", mode, len); + StatisticsCollector::TestCase full_key = stat.SetTestCase("total time", mode, len); + for (int i = 0; i < ntrial; i++) { + Timer timer0; + vector_t v1(len); + vector_t v2(len); + Timer timer1; + std::generate(v1.begin(), v1.end(), values(0)); + std::generate(v2.begin(), v2.end(), values(size_t(-len))); + Timer timer2; + std::reverse(v1.rbegin(), v1.rend()); + std::inner_product(v1.begin(), v1.end(), v2.rbegin(), 1); + std::sort(v1.rbegin(), v1.rend()); + std::sort(v2.rbegin(), v2.rend()); + std::set_intersection(v1.begin(), v1.end(), v2.rbegin(), v2.rend(), v1.begin()); + Timer timer3; + stat.AddRoundResult( proc_key, timer2.diff_time(timer3)*1000.0 ); + stat.AddRoundResult( fill_key, timer1.diff_time(timer2)*1000.0 ); + stat.AddRoundResult( init_key, timer0.diff_time(timer1)*1000.0 ); + stat.AddRoundResult( full_key, timer0.diff_time(timer3)*1000.0 ); + } + stat.SetStatisticFormula("1Average", "=AVERAGE(ROUNDS)"); + stat.SetStatisticFormula("2+/-", "=(MAX(ROUNDS)-MIN(ROUNDS))/2"); + return *this; + } + + class values + { + size_t value; + public: + values(size_t i) : value(i) {} + size_t operator()() { + return value++%(1|(value^55)); + } + }; +}; + +/************************************************************************/ +/* TEST3 */ +/************************************************************************/ +#define mk_vector_test3(v, a) vector_test3<v<char, local_counting_allocator<a<char>, size_t > > > +template<class vector_t> +class vector_test3 { + const char *mode; + StatisticsCollector &stat; + +public: + vector_test3(const char *m, StatisticsCollector &s) : mode(m), stat(s) {} + + vector_test3 &operator()(size_t len) { + if(Verbose) printf("test3<%s>(%u): collecting allocator statistics\n", mode, unsigned(len)); + static const size_t sz = 1024; + vector_t V[sz]; + StatisticsCollector::TestCase vinst_key = stat.SetTestCase("instances number", mode, len); + StatisticsCollector::TestCase count_key = stat.SetTestCase("allocations count", mode, len); + StatisticsCollector::TestCase items_key = stat.SetTestCase("allocated items", mode, len); + //stat.ReserveRounds(sz-1); + for (size_t c = 0, i = 0, s = sz/2; s >= 1 && i < sz; s /= 2, c++) + { + const size_t count = c? 1<<(c-1) : 0; + for (size_t e = i+s; i < e; i++) { + //if(count >= 16) V[i].reserve(count); + for (size_t j = 0; j < count; j++) + V[i].push_back(j); + } + stat.SetRoundTitle ( c, count ); + stat.AddRoundResult( vinst_key, s ); + stat.AddRoundResult( count_key, V[i-1].get_allocator().allocations ); + stat.AddRoundResult( items_key, V[i-1].get_allocator().items_allocated ); + } + return *this; + } +}; + +/************************************************************************/ +/* TYPES SET FOR TESTS */ +/************************************************************************/ +#define types_set(n, title, op) { StatisticsCollector Collector("time_vector"#n); Collector.SetTitle title; \ + {mk_vector_test##n(tbb::concurrent_vector, tbb::cache_aligned_allocator) ("TBB:NFS", Collector)op;} \ + {mk_vector_test##n(tbb::concurrent_vector, tbb::tbb_allocator) ("TBB:TBB", Collector)op;} \ + {mk_vector_test##n(tbb::concurrent_vector, std::allocator) ("TBB:STD", Collector)op;} \ + {mk_vector_test##n(std::vector, tbb::cache_aligned_allocator) ("STL:NFS", Collector)op;} \ + {mk_vector_test##n(std::vector, tbb::tbb_allocator) ("STL:TBB", Collector)op;} \ + {mk_vector_test##n(std::vector, std::allocator) ("STL:STD", Collector)op;} \ + Collector.Print(StatisticsCollector::Stdout|StatisticsCollector::HTMLFile|StatisticsCollector::ExcelXML); } + + +/************************************************************************/ +/* MAIN DRIVER */ +/************************************************************************/ +int main(int argc, char* argv[]) { + if(argc>1) Verbose = true; + if(argc>2) ExtraVerbose = true; + MinThread = 0; MaxThread = 500000; // use in another meaning - test#:problem size + ParseCommandLine( argc, argv ); + + ASSERT(tbb_allocator<int>::allocator_type() == tbb_allocator<int>::scalable, "expecting scalable allocator library to be loaded"); + + if(!MinThread || MinThread == 1) + types_set(1, ("Vectors performance test #1 for %d", MaxThread), (MaxThread) ) + if(!MinThread || MinThread == 2) + types_set(2, ("Vectors performance test #2 for %d", MaxThread), (MaxThread) ) + if(!MinThread || MinThread == 3) + types_set(3, ("Vectors performance test #3 for %d", MaxThread), (MaxThread) ) + + if(!Verbose) printf("done\n"); + return 0; +} + diff --git a/src/tbb/src/rml/client/index.html b/src/tbb/src/rml/client/index.html new file mode 100644 index 0000000..c013c8f --- /dev/null +++ b/src/tbb/src/rml/client/index.html @@ -0,0 +1,42 @@ +<HTML> +<BODY> +<H2>Overview</H2> + +This directory has source code that must be statically linked into an RML client. + +<H2>Files</H2> + +<DL> +<DT><P><A HREF="rml_factory.h">rml_factory.h</A> +<DD>Text shared by <A HREF="rml_omp.cpp">rml_omp.cpp</A> and <A HREF="rml_tbb.cpp">rml_tbb.cpp</A>. + This is not an ordinary include file, so it does not have an #ifndef guard.</P> +</DL> + +<H3> Specific to client=OpenMP</H3> +<DL> +<DT><P><A HREF="rml_omp.cpp">rml_omp.cpp</A> +<DD>Source file for OpenMP client.</P> +<DT><P><A HREF="omp_dynamic_link.h">omp_dynamic_link.h</A> +<DT><A HREF="omp_dynamic_link.cpp">omp_dynamic_link.cpp</A> +<DD>Source files for dynamic linking support. + The code is the code from the TBB source directory, but adjusted so that it + appears in namespace <TT>__kmp</TT> instead of namespace <TT>tbb::internal</TT>. +</DL> +<H3> Specific to client=TBB</H3> +<DL> +<DT><P><A HREF="rml_tbb.cpp">rml_tbb.cpp</A> +<DD>Source file for TBB client. It uses the dynamic linking support from the TBB source directory. +</DL> + +<HR> +<A HREF="../index.html">Up to parent directory</A> +<p></p> +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +<P></P> +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +<p></p> +* Other names and brands may be claimed as the property of others. +</BODY> +</HTML> + diff --git a/src/tbb/src/rml/client/library_assert.h b/src/tbb/src/rml/client/library_assert.h new file mode 100644 index 0000000..9b8cd50 --- /dev/null +++ b/src/tbb/src/rml/client/library_assert.h @@ -0,0 +1,41 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef LIBRARY_ASSERT_H +#define LIBRARY_ASSERT_H + +#ifndef LIBRARY_ASSERT +#ifdef KMP_ASSERT2 +#define LIBRARY_ASSERT(x,y) KMP_ASSERT2((x),(y)) +#else +#include <assert.h> +#define LIBRARY_ASSERT(x,y) assert(x) +#endif +#endif /* LIBRARY_ASSERT */ + +#endif /* LIBRARY_ASSERT_H */ diff --git a/src/tbb/src/rml/client/omp_dynamic_link.cpp b/src/tbb/src/rml/client/omp_dynamic_link.cpp new file mode 100644 index 0000000..d38b230 --- /dev/null +++ b/src/tbb/src/rml/client/omp_dynamic_link.cpp @@ -0,0 +1,32 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "omp_dynamic_link.h" +#include "library_assert.h" +#include "tbb/dynamic_link.cpp" // Refers to src/tbb, not include/tbb + diff --git a/src/tbb/src/rml/client/omp_dynamic_link.h b/src/tbb/src/rml/client/omp_dynamic_link.h new file mode 100644 index 0000000..d3cfd61 --- /dev/null +++ b/src/tbb/src/rml/client/omp_dynamic_link.h @@ -0,0 +1,37 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __KMP_omp_dynamic_link_H +#define __KMP_omp_dynamic_link_H + +#define OPEN_INTERNAL_NAMESPACE namespace __kmp { +#define CLOSE_INTERNAL_NAMESPACE } + +#include "tbb/dynamic_link.h" // Refers to src/tbb, not include/tbb + +#endif /* __KMP_omp_dynamic_link_H */ diff --git a/src/tbb/src/rml/client/rml_factory.h b/src/tbb/src/rml/client/rml_factory.h new file mode 100644 index 0000000..3af8447 --- /dev/null +++ b/src/tbb/src/rml/client/rml_factory.h @@ -0,0 +1,108 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// No ifndef guard because this file is not a normal include file. + +#if TBB_USE_DEBUG +#define DEBUG_SUFFIX "_debug" +#else +#define DEBUG_SUFFIX +#endif /* TBB_USE_DEBUG */ + +// RML_SERVER_NAME is the name of the RML server library. +#if _WIN32||_WIN64 +#define RML_SERVER_NAME "irml" DEBUG_SUFFIX ".dll" +#elif __APPLE__ +#define RML_SERVER_NAME "libirml" DEBUG_SUFFIX ".dylib" +#elif __linux__ +#define RML_SERVER_NAME "libirml" DEBUG_SUFFIX ".so.1" +#elif __FreeBSD__ || __NetBSD__ || __sun || _AIX +#define RML_SERVER_NAME "libirml" DEBUG_SUFFIX ".so" +#else +#error Unknown OS +#endif + +#include "library_assert.h" + +const ::rml::versioned_object::version_type CLIENT_VERSION = 2; + +#if __TBB_WEAK_SYMBOLS + #pragma weak __RML_open_factory + #pragma weak __TBB_make_rml_server + #pragma weak __RML_close_factory + #pragma weak __TBB_call_with_my_server_info + extern "C" { + ::rml::factory::status_type __RML_open_factory ( ::rml::factory&, ::rml::versioned_object::version_type&, ::rml::versioned_object::version_type ); + ::rml::factory::status_type __TBB_make_rml_server( tbb::internal::rml::tbb_factory& f, tbb::internal::rml::tbb_server*& server, tbb::internal::rml::tbb_client& client ); + void __TBB_call_with_my_server_info( ::rml::server_info_callback_t cb, void* arg ); + void __RML_close_factory( ::rml::factory& f ); + } +#endif /* __TBB_WEAK_SYMBOLS */ + +::rml::factory::status_type FACTORY::open() { + // Failure of following assertion indicates that factory is already open, or not zero-inited. + LIBRARY_ASSERT( !library_handle, NULL ); + status_type (*open_factory_routine)( factory&, version_type&, version_type ); + dynamic_link_descriptor server_link_table[4] = { + DLD(__RML_open_factory,open_factory_routine), + MAKE_SERVER(my_make_server_routine), + DLD(__RML_close_factory,my_wait_to_close_routine), + GET_INFO(my_call_with_server_info_routine), + }; + status_type result; + if( dynamic_link( RML_SERVER_NAME, server_link_table, 4, 4, &library_handle ) ) { + version_type server_version; + result = (*open_factory_routine)( *this, server_version, CLIENT_VERSION ); + // server_version can be checked here for incompatibility here if necessary. + } else { + library_handle = NULL; + result = st_not_found; + } + return result; +} + +void FACTORY::close() { + if( library_handle ) + (*my_wait_to_close_routine)(*this); + if( (size_t)library_handle>FACTORY::c_dont_unload ) { + dynamic_unlink(library_handle); + library_handle = NULL; + } +} + +::rml::factory::status_type FACTORY::make_server( SERVER*& s, CLIENT& c) { + // Failure of following assertion means that factory was not successfully opened. + LIBRARY_ASSERT( my_make_server_routine, NULL ); + return (*my_make_server_routine)(*this,s,c); +} + +void FACTORY::call_with_server_info( ::rml::server_info_callback_t cb, void* arg ) const { + // Failure of following assertion means that factory was not successfully opened. + LIBRARY_ASSERT( my_call_with_server_info_routine, NULL ); + (*my_call_with_server_info_routine)( cb, arg ); +} diff --git a/src/tbb/src/rml/client/rml_omp.cpp b/src/tbb/src/rml/client/rml_omp.cpp new file mode 100644 index 0000000..7f961d4 --- /dev/null +++ b/src/tbb/src/rml/client/rml_omp.cpp @@ -0,0 +1,44 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "rml_omp.h" +#include "omp_dynamic_link.h" +#include <assert.h> + +namespace __kmp { +namespace rml { + +#define MAKE_SERVER(x) DLD(__KMP_make_rml_server,x) +#define GET_INFO(x) DLD(__KMP_call_with_my_server_info,x) +#define SERVER omp_server +#define CLIENT omp_client +#define FACTORY omp_factory +#include "rml_factory.h" + +} // rml +} // __kmp diff --git a/src/tbb/src/rml/client/rml_tbb.cpp b/src/tbb/src/rml/client/rml_tbb.cpp new file mode 100644 index 0000000..b2d8a4d --- /dev/null +++ b/src/tbb/src/rml/client/rml_tbb.cpp @@ -0,0 +1,46 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "../include/rml_tbb.h" +#include "tbb/dynamic_link.h" +#include <assert.h> + +namespace tbb { +namespace internal { +namespace rml { + +#define MAKE_SERVER(x) DLD(__TBB_make_rml_server,x) +#define GET_INFO(x) DLD(__TBB_call_with_my_server_info,x) +#define SERVER tbb_server +#define CLIENT tbb_client +#define FACTORY tbb_factory +#include "rml_factory.h" + +} // rml +} // internal +} // tbb diff --git a/src/tbb/src/rml/include/index.html b/src/tbb/src/rml/include/index.html new file mode 100644 index 0000000..b377757 --- /dev/null +++ b/src/tbb/src/rml/include/index.html @@ -0,0 +1,29 @@ +<HTML> +<BODY> +<H2>Overview</H2> + +This directory has the include files for the Resource Management Layer (RML). + +<H2>Files</H2> + +<DL> +<DT><P><A HREF="rml_base.h">rml_base.h</A> +<DD>Interfaces shared by TBB and OpenMP.</P> +<DT><P><A HREF="rml_omp.h">rml_omp.h</A> +<DD>Interface exclusive to OpenMP.</P> +<DT><P><A HREF="rml_tbb.h">rml_tbb.h</A> +<DD>Interface exclusive to TBB.</P> +</DL> + +<HR> +<A HREF="../index.html">Up to parent directory</A> +<p></p> +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +<P></P> +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +<p></p> +* Other names and brands may be claimed as the property of others. +</BODY> +</HTML> + diff --git a/src/tbb/src/rml/include/rml_base.h b/src/tbb/src/rml/include/rml_base.h new file mode 100644 index 0000000..6f32b7d --- /dev/null +++ b/src/tbb/src/rml/include/rml_base.h @@ -0,0 +1,196 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Header guard and namespace names follow rml conventions. + +#ifndef __RML_rml_base_H +#define __RML_rml_base_H + +#include <cstddef> + +#if _WIN32||_WIN64 +#include <windows.h> +#endif /* _WIN32||_WIN64 */ + +#ifdef RML_PURE_VIRTUAL_HANDLER +#define RML_PURE(T) {RML_PURE_VIRTUAL_HANDLER(); return (T)0;} +#else +#define RML_PURE(T) = 0; +#endif + +namespace rml { + +//! Base class for denying assignment and copy constructor. +class no_copy { + void operator=( no_copy& ); + no_copy( no_copy& ); +public: + no_copy() {} +}; + +class server; + +class versioned_object { +public: + //! A version number + typedef unsigned version_type; + + //! Get version of this object + /** The version number is incremented when a incompatible change is introduced. + The version number is invariant for the lifetime of the object. */ + virtual version_type version() const RML_PURE(version_type) +}; + +//! Represents a client's job for an execution context. +/** A job object is constructed by the client. + Not derived from versioned_object because version is same as for client. */ +class job { + friend class server; + + //! Word for use by server + /** Typically the server uses it to speed up internal lookup. + Clients must not modify the word. */ + void* scratch_ptr; +}; + +//! Information that client provides to server when asking for a server. +/** The instance must endure at least until acknowledge_close_connection is called. */ +class client: public versioned_object { +public: + //! Typedef for convenience of derived classes in other namespaces. + typedef ::rml::job job; + + //! Index of a job in a job pool + typedef unsigned size_type; + + //! Maximum number of threads that client can exploit profitably if nothing else is running on the machine. + /** The returned value should remain invariant for the lifetime of the connection. [idempotent] */ + virtual size_type max_job_count() const RML_PURE(size_type) + + //! Minimum stack size for each job. 0 means to use default stack size. [idempotent] + virtual std::size_t min_stack_size() const RML_PURE(std::size_t) + + //! Server calls this routine when it needs client to create a job object. + virtual job* create_one_job() RML_PURE(job*) + + //! Acknowledge that all jobs have been cleaned up. + /** Called by server in response to request_close_connection + after cleanup(job) has been called for each job. */ + virtual void acknowledge_close_connection() RML_PURE(void) + + enum policy_type {turnaround,throughput}; + + //! Inform server of desired policy. [idempotent] + virtual policy_type policy() const RML_PURE(policy_type) + + //! Inform client that server is done with *this. + /** Client should destroy the job. + Not necessarily called by execution context represented by *this. + Never called while any other thread is working on the job. */ + virtual void cleanup( job& ) RML_PURE(void) + + // In general, we should not add new virtual methods, because that would + // break derived classes. Think about reserving some vtable slots. +}; + +// Information that server provides to client. +// Virtual functions are routines provided by the server for the client to call. +class server: public versioned_object { +public: + //! Typedef for convenience of derived classes. + typedef ::rml::job job; + +#if _WIN32||_WIN64 + typedef void* execution_resource_t; +#endif + + //! Request that connection to server be closed. + /** Causes each job associated with the client to have its cleanup method called, + possibly by a thread different than the thread that created the job. + This method can return before all cleanup methods return. + Actions that have to wait after all cleanup methods return should be part of + client::acknowledge_close_connection. + Pass true as exiting if request_close_connection() is called because exit() is + called. In that case, it is the client's responsibility to make sure all threads + are terminated. In all other cases, pass false. */ + virtual void request_close_connection( bool exiting = false ) = 0; + + //! Called by client thread when it reaches a point where it cannot make progress until other threads do. + virtual void yield() = 0; + + //! Called by client to indicate a change in the number of non-RML threads that are running. + /** This is a performance hint to the RML to adjust how many threads it should let run + concurrently. The delta is the change in the number of non-RML threads that are running. + For example, a value of 1 means the client has started running another thread, and a value + of -1 indicates that the client has blocked or terminated one of its threads. */ + virtual void independent_thread_number_changed( int delta ) = 0; + + //! Default level of concurrency for which RML strives when there are no non-RML threads running. + /** Normally, the value is the hardware concurrency minus one. + The "minus one" accounts for the thread created by main(). */ + virtual unsigned default_concurrency() const = 0; + +protected: + static void*& scratch_ptr( job& j ) {return j.scratch_ptr;} +}; + +class factory { +public: + //! status results + enum status_type { + st_success=0, + st_connection_exists, + st_not_found, + st_incompatible + }; + + //! Scratch pointer for use by RML. + void* scratch_ptr; + +protected: + //! Pointer to routine that waits for server to indicate when client can close itself. + status_type (*my_wait_to_close_routine)( factory& ); + +public: + //! Library handle for use by RML. +#if _WIN32||_WIN64 + HMODULE library_handle; +#else + void* library_handle; +#endif /* _WIN32||_WIN64 */ + + //! Special marker to keep dll from being unloaded prematurely + static const std::size_t c_dont_unload = 1; +}; + +//! Typedef for callback functions to print server info +typedef void (*server_info_callback_t)( void* arg, const char* server_info ); + +} // namespace rml + +#endif /* __RML_rml_base_H */ diff --git a/src/tbb/src/rml/include/rml_omp.h b/src/tbb/src/rml/include/rml_omp.h new file mode 100644 index 0000000..ad17a0d --- /dev/null +++ b/src/tbb/src/rml/include/rml_omp.h @@ -0,0 +1,138 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Header guard and namespace names follow OpenMP runtime conventions. + +#ifndef KMP_RML_OMP_H +#define KMP_RML_OMP_H + +#include "rml_base.h" + +namespace __kmp { +namespace rml { + +class omp_client; + +//------------------------------------------------------------------------ +// Classes instantiated by the server +//------------------------------------------------------------------------ + +//! Represents a set of omp worker threads provided by the server. +class omp_server: public ::rml::server { +public: + //! A number of coins (i.e., threads) + typedef unsigned size_type; + + //! Return the number of coins in the bank. (negative if machine is oversubscribed). + virtual int current_balance() const = 0; + + //! Request n coins. Returns number of coins granted. Oversubscription amount if negative. + /** Always granted if is_strict is true. + - Positive or zero result indicates that the number of coins was taken from the bank. + - Negative result indicates that no coins were taken, and that the bank has deficit + by that amount and the caller (if being a good citizen) should return that many coins. + */ + virtual int try_increase_load( size_type /*n*/, bool /*strict*/ ) = 0; + + //! Return n coins into the bank. + virtual void decrease_load( size_type /*n*/ ) = 0; + + //! Convert n coins into n threads. + /** When a thread returns, it is converted back into a coin and the coin is returned to the bank. */ + virtual void get_threads( size_type /*m*/, void* /*cookie*/, job* /*array*/[] ) = 0; + + /** Putting a thread to sleep - convert a thread into a coin + Waking up a thread - convert a coin into a thread + + Note: conversion between a coin and a thread does not affect the accounting. + */ +#if _WIN32||_WIN64 + //! Inform server of a tbb master thread. + virtual void register_master( execution_resource_t& /*v*/ ) = 0; + + //! Inform server that the tbb master thread is done with its work. + virtual void unregister_master( execution_resource_t /*v*/ ) = 0; + + //! deactivate + /** give control to ConcRT RM */ + virtual void deactivate( job* ) = 0; + + //! reactivate + virtual void reactivate( job* ) = 0; +#endif /* _WIN32||_WIN64 */ +}; + + +//------------------------------------------------------------------------ +// Classes (or base classes thereof) instantiated by the client +//------------------------------------------------------------------------ + +class omp_client: public ::rml::client { +public: + //! Called by server thread when it delivers a thread to client + /** The index argument is a 0-origin index of the job for this thread within the array + returned by method get_threads. Server decreases the load by 1 (i.e., returning the coin + back to the bank) after this method returns. */ + virtual void process( job&, void* /*cookie*/, size_type /*index*/ ) RML_PURE(void) +}; + +/** Client must ensure that instance is zero-inited, typically by being a file-scope object. */ +class omp_factory: public ::rml::factory { + + //! Pointer to routine that creates an RML server. + status_type (*my_make_server_routine)( omp_factory&, omp_server*&, omp_client& ); + + //! Pointer to routine that calls callback function with server version info. + void (*my_call_with_server_info_routine)( ::rml::server_info_callback_t cb, void* arg ); + +public: + typedef ::rml::versioned_object::version_type version_type; + typedef omp_client client_type; + typedef omp_server server_type; + + //! Open factory. + /** Dynamically links against RML library. + Returns st_success, st_incompatible, or st_not_found. */ + status_type open(); + + //! Factory method to be called by client to create a server object. + /** Factory must be open. + Returns st_success or st_incompatible . */ + status_type make_server( server_type*&, client_type& ); + + //! Close factory. + void close(); + + //! Call the callback with the server build info. + void call_with_server_info( ::rml::server_info_callback_t cb, void* arg ) const; +}; + +} // namespace rml +} // namespace __kmp + +#endif /* KMP_RML_OMP_H */ diff --git a/src/tbb/src/rml/include/rml_tbb.h b/src/tbb/src/rml/include/rml_tbb.h new file mode 100644 index 0000000..af8fafd --- /dev/null +++ b/src/tbb/src/rml/include/rml_tbb.h @@ -0,0 +1,108 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Header guard and namespace names follow TBB conventions. + +#ifndef __TBB_rml_tbb_H +#define __TBB_rml_tbb_H + +#include "rml_base.h" + +namespace tbb { +namespace internal { +namespace rml { + +class tbb_client; + +//------------------------------------------------------------------------ +// Classes instantiated by the server +//------------------------------------------------------------------------ + +//! Represents a set of tbb worker threads provided by the server. +class tbb_server: public ::rml::server { +public: + //! Inform server of adjustments in the number of workers that the client can profitably use. + virtual void adjust_job_count_estimate( int delta ) = 0; + +#if _WIN32||_WIN64 + //! Inform server of a tbb master thread. + virtual void register_master( execution_resource_t& v ) = 0; + + //! Inform server that the tbb master thread is done with its work. + virtual void unregister_master( execution_resource_t v ) = 0; +#endif /* _WIN32||_WIN64 */ +}; + +//------------------------------------------------------------------------ +// Classes instantiated by the client +//------------------------------------------------------------------------ + +class tbb_client: public ::rml::client { +public: + //! Defined by TBB to steal a task and execute it. + /** Called by server when it wants an execution context to do some TBB work. + The method should return when it is okay for the thread to yield indefinitely. */ + virtual void process( job& ) RML_PURE(void) +}; + +/** Client must ensure that instance is zero-inited, typically by being a file-scope object. */ +class tbb_factory: public ::rml::factory { + + //! Pointer to routine that creates an RML server. + status_type (*my_make_server_routine)( tbb_factory&, tbb_server*&, tbb_client& ); + + //! Pointer to routine that calls callback function with server version info. + void (*my_call_with_server_info_routine)( ::rml::server_info_callback_t cb, void* arg ); + +public: + typedef ::rml::versioned_object::version_type version_type; + typedef tbb_client client_type; + typedef tbb_server server_type; + + //! Open factory. + /** Dynamically links against RML library. + Returns st_success, st_incompatible, or st_not_found. */ + status_type open(); + + //! Factory method to be called by client to create a server object. + /** Factory must be open. + Returns st_success, or st_incompatible . */ + status_type make_server( server_type*&, client_type& ); + + //! Close factory + void close(); + + //! Call the callback with the server build info + void call_with_server_info( ::rml::server_info_callback_t cb, void* arg ) const; +}; + +} // namespace rml +} // namespace internal +} // namespace tbb + +#endif /*__TBB_rml_tbb_H */ diff --git a/src/tbb/src/rml/index.html b/src/tbb/src/rml/index.html new file mode 100644 index 0000000..8527d21 --- /dev/null +++ b/src/tbb/src/rml/index.html @@ -0,0 +1,31 @@ +<HTML> +<BODY> +<H2>Overview</H2> + +The subdirectories pertain to the Resource Management Layer (RML). + +<H2>Directories</H2> + +<DL> +<DT><P><A HREF="include/index.html">include/</A> +<DD>Include files used by clients of RML.</P> +<DT><P><A HREF="client/index.html">client/</A> +<DD>Source files for code that must be statically linked with a client.</P> +<DT><P><A HREF="server/index.html">server/</A> +<DD>Source files for the RML server.</P> +<DT><P><A HREF="test">test/</A> +<DD>Unit tests for RML server and its components.</P> +</DL> + +<HR> +<A HREF="../index.html">Up to parent directory</A> +<p></p> +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +<P></P> +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +<p></p> +* Other names and brands may be claimed as the property of others. +</BODY> +</HTML> + diff --git a/src/tbb/src/rml/perfor/omp_nested.cpp b/src/tbb/src/rml/perfor/omp_nested.cpp new file mode 100644 index 0000000..0844cb4 --- /dev/null +++ b/src/tbb/src/rml/perfor/omp_nested.cpp @@ -0,0 +1,152 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include <cstddef> +#include <cstdlib> +#include <cstdio> +#include <float.h> +#include <math.h> +#include <time.h> + +#include <omp.h> +#include <assert.h> + +#include "thread_level.h" + +#if _WIN32||_WIN64 +#include <Windows.h> /* Need Sleep */ +#else +#include <unistd.h> /* Need usleep */ +#endif + +void MilliSleep( unsigned milliseconds ) { +#if _WIN32||_WIN64 + Sleep( milliseconds ); +#else + usleep( milliseconds*1000 ); +#endif /* _WIN32||_WIN64 */ +} + +// Algorithm parameters +const int Max_OMP_Outer_Threads = 8; + +// Global variables +int max_outer_threads = Max_OMP_Outer_Threads; + +// Print help on command-line arguments +void help_message(char *prog_name) { + fprintf(stderr, "\n%s usage:\n", prog_name); + fprintf(stderr, + " Parameters:\n" + " -o<num> : max # of threads OMP should use at outer level\n" + "\n Help:\n" + " -h : print this help message\n"); +} + +// Process command-line arguments +void process_args(int argc, char *argv[], int *max_outer_t) { + (*max_outer_t) = omp_get_max_threads(); + for (int i=1; i<argc; ++i) { + if (argv[i][0] == '-') { + switch (argv[i][1]) { + case 'o': // set max_outer_threads + if (sscanf(&argv[i][2], "%d", max_outer_t) != 1 || *max_outer_t < 1) { + fprintf(stderr, "%s Warning: argument of -o option unacceptable: %s\n", argv[0], &argv[i][2]); + help_message(argv[0]); + } + break; + case 'h': // print help message + help_message(argv[0]); + exit(0); + break; + default: + fprintf(stderr, "%s: Warning: command-line option ignored: %s\n", argv[0], argv[i]); + help_message(argv[0]); + break; + } + } else { + fprintf(stderr, "%s: Warning: command-line option ignored: %s\n", argv[0], argv[i]); + help_message(argv[0]); + } + } +} + +int main(int argc, char *argv[]) { + process_args(argc, argv, &max_outer_threads); +#ifdef LOG_THREADS + TotalThreadLevel.init(); +#endif + + double start, end; + start = omp_get_wtime( ); + +#pragma omp parallel num_threads(max_outer_threads) + { + int omp_thread = omp_get_thread_num(); +#ifdef LOG_THREADS + if (omp_thread == 0) + TotalThreadLevel.change_level(omp_get_num_threads(), omp_outer); +#endif + if (omp_thread == 0) { + MilliSleep(3000); +#ifdef LOG_THREADS + TotalThreadLevel.change_level(-1, omp_outer); +#endif +#pragma omp parallel + { + int my_omp_thread = omp_get_thread_num(); +#ifdef LOG_THREADS + if (my_omp_thread == 0) + TotalThreadLevel.change_level(omp_get_num_threads(), omp_inner); +#endif + printf("Inner thread %d nested inside outer thread %d\n", my_omp_thread, omp_thread); +#ifdef LOG_THREADS + if (my_omp_thread == 0) + TotalThreadLevel.change_level(-omp_get_num_threads(), omp_inner); +#endif + } +#ifdef LOG_THREADS + TotalThreadLevel.change_level(1, omp_outer); +#endif + } + else { + MilliSleep(6000); + } +#ifdef LOG_THREADS + if (omp_thread == 0) + TotalThreadLevel.change_level(-omp_get_num_threads(), omp_outer); +#endif + } + end = omp_get_wtime( ); + printf("Simple test of nested OMP (%d outer threads max) took: %6.6f\n", + max_outer_threads, end-start); +#ifdef LOG_THREADS + TotalThreadLevel.dump(); +#endif + return 0; +} diff --git a/src/tbb/src/rml/perfor/omp_simple.cpp b/src/tbb/src/rml/perfor/omp_simple.cpp new file mode 100644 index 0000000..14215b6 --- /dev/null +++ b/src/tbb/src/rml/perfor/omp_simple.cpp @@ -0,0 +1,168 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include <cstddef> +#include <cstdlib> +#include <cstdio> +#include <float.h> +#include <math.h> +#include <time.h> + +#include <omp.h> +#include <assert.h> + +#include "thread_level.h" + +#include "tbb/task.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/parallel_for.h" +#include "tbb/blocked_range.h" + +#if _WIN32||_WIN64 +#include <Windows.h> /* Need Sleep */ +#else +#include <unistd.h> /* Need usleep */ +#endif + +void MilliSleep( unsigned milliseconds ) { +#if _WIN32||_WIN64 + Sleep( milliseconds ); +#else + usleep( milliseconds*1000 ); +#endif /* _WIN32||_WIN64 */ +} + +using namespace std; +using namespace tbb; + +// Algorithm parameters +const int Max_TBB_Threads = 16; +const int Max_OMP_Threads = 16; + +// Global variables +int max_tbb_threads = Max_TBB_Threads; +int max_omp_threads = Max_OMP_Threads; + +// Print help on command-line arguments +void help_message(char *prog_name) { + fprintf(stderr, "\n%s usage:\n", prog_name); + fprintf(stderr, + " Parameters:\n" + " -t<num> : max # of threads TBB should use\n" + " -o<num> : max # of threads OMP should use\n" + "\n Help:\n" + " -h : print this help message\n"); +} + +// Process command-line arguments +void process_args(int argc, char *argv[], int *max_tbb_t, int *max_omp_t) { + for (int i=1; i<argc; ++i) { + if (argv[i][0] == '-') { + switch (argv[i][1]) { + case 't': // set max_tbb_threads + if (sscanf(&argv[i][2], "%d", max_tbb_t) != 1 || *max_tbb_t < 1) { + fprintf(stderr, "%s Warning: argument of -t option unacceptable: %s\n", argv[0], &argv[i][2]); + help_message(argv[0]); + } + break; + case 'o': // set max_omp_threads + if (sscanf(&argv[i][2], "%d", max_omp_t) != 1 || *max_omp_t < 1) { + fprintf(stderr, "%s Warning: argument of -o option unacceptable: %s\n", argv[0], &argv[i][2]); + help_message(argv[0]); + } + break; + case 'h': // print help message + help_message(argv[0]); + exit(0); + break; + default: + fprintf(stderr, "%s: Warning: command-line option ignored: %s\n", argv[0], argv[i]); + help_message(argv[0]); + break; + } + } else { + fprintf(stderr, "%s: Warning: command-line option ignored: %s\n", argv[0], argv[i]); + help_message(argv[0]); + } + } +} + +int main(int argc, char *argv[]) { + process_args(argc, argv, &max_tbb_threads, &max_omp_threads); + TotalThreadLevel.init(); + + double start, end; + start = omp_get_wtime(); + +#pragma omp parallel num_threads(max_omp_threads) + { + int omp_thread = omp_get_thread_num(); +#ifdef LOG_THREADS + if (omp_thread == 0) + TotalThreadLevel.change_level(omp_get_num_threads(), omp_outer); +#endif + task_scheduler_init phase(max_tbb_threads); + if (omp_thread == 0) { + MilliSleep(3000); +#ifdef LOG_THREADS + TotalThreadLevel.change_level(-1, omp_outer); +#endif + parallel_for(blocked_range<size_t>(0, 1000), + [=](const blocked_range<size_t>& range) { +#ifdef LOG_THREADS + TotalThreadLevel.change_level(1, tbb_inner); +#endif +#pragma ivdep + for (size_t i=range.begin(); i!=range.end(); ++i) { + if (i==range.begin()) + printf("TBB range starting at %d on OMP thread %d\n", (int)i, omp_thread); + } +#ifdef LOG_THREADS + TotalThreadLevel.change_level(-1, tbb_inner); +#endif + }, auto_partitioner()); +#ifdef LOG_THREADS + TotalThreadLevel.change_level(1, omp_outer); +#endif + } + else { + MilliSleep(6000); + } +#ifdef LOG_THREADS + if (omp_thread == 0) + TotalThreadLevel.change_level(-omp_get_num_threads(), omp_outer); +#endif + } + end = omp_get_wtime(); + printf("Simple test of OMP (%d threads max) with TBB (%d threads max) inside took: %6.6f\n", + max_omp_threads, max_tbb_threads, end-start); +#ifdef LOG_THREADS + TotalThreadLevel.dump(); +#endif + return 0; +} diff --git a/src/tbb/src/rml/perfor/tbb_multi_omp.cpp b/src/tbb/src/rml/perfor/tbb_multi_omp.cpp new file mode 100644 index 0000000..97a6404 --- /dev/null +++ b/src/tbb/src/rml/perfor/tbb_multi_omp.cpp @@ -0,0 +1,194 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include <cstddef> +#include <cstdlib> +#include <cstdio> +#include <float.h> +#include <math.h> +#include <time.h> + +#include <omp.h> +#include <assert.h> + +#include "thread_level.h" + +#include "tbb/task.h" +#include "tbb/tick_count.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/scalable_allocator.h" + +#if _WIN32||_WIN64 +#include <Windows.h> /* Need Sleep */ +#else +#include <unistd.h> /* Need usleep */ +#endif + +void MilliSleep( unsigned milliseconds ) { +#if _WIN32||_WIN64 + Sleep( milliseconds ); +#else + usleep( milliseconds*1000 ); +#endif /* _WIN32||_WIN64 */ +} + +using namespace std; +using namespace tbb; + +// Algorithm parameters +const int Max_TBB_Threads = 16; +const int Max_OMP_Threads = 16; + +// Global variables +int max_tbb_threads = Max_TBB_Threads; +int max_omp_threads = Max_OMP_Threads; + +// Print help on command-line arguments +void help_message(char *prog_name) { + fprintf(stderr, "\n%s usage:\n", prog_name); + fprintf(stderr, + " Parameters:\n" + " -t<num> : max # of threads TBB should use\n" + " -o<num> : max # of threads OMP should use\n" + "\n Help:\n" + " -h : print this help message\n"); +} + +// Process command-line arguments +void process_args(int argc, char *argv[], int *max_tbb_t, int *max_omp_t) { + for (int i=1; i<argc; ++i) { + if (argv[i][0] == '-') { + switch (argv[i][1]) { + case 't': // set max_tbb_threads + if (sscanf(&argv[i][2], "%d", max_tbb_t) != 1 || *max_tbb_t < 1) { + fprintf(stderr, "%s Warning: argument of -t option unacceptable: %s\n", argv[0], &argv[i][2]); + help_message(argv[0]); + } + break; + case 'o': // set max_omp_threads + if (sscanf(&argv[i][2], "%d", max_omp_t) != 1 || *max_omp_t < 1) { + fprintf(stderr, "%s Warning: argument of -o option unacceptable: %s\n", argv[0], &argv[i][2]); + help_message(argv[0]); + } + break; + case 'h': // print help message + help_message(argv[0]); + exit(0); + break; + default: + fprintf(stderr, "%s: Warning: command-line option ignored: %s\n", argv[0], argv[i]); + help_message(argv[0]); + break; + } + } else { + fprintf(stderr, "%s: Warning: command-line option ignored: %s\n", argv[0], argv[i]); + help_message(argv[0]); + } + } +} + +class SimpleTask : public task { + bool isLeaf; + int myId; +public: + SimpleTask(bool isLeaf_, int myId_) : isLeaf(isLeaf_), myId(myId_) {} + task* execute() { +#ifdef LOG_THREADS + TotalThreadLevel.change_level(1, tbb_outer); +#endif + omp_set_num_threads(max_omp_threads); + if (!isLeaf) { + set_ref_count(65); + for (int i=0; i<64; ++i) { + SimpleTask& st = *new(allocate_child()) SimpleTask(true, i); + spawn(st); + } +#ifdef LOG_THREADS + TotalThreadLevel.change_level(-1, tbb_outer); +#endif + wait_for_all(); +#ifdef LOG_THREADS + TotalThreadLevel.change_level(1, tbb_outer); +#endif + } + else { + if (myId%2 == 0) { + MilliSleep(3000); +#pragma omp parallel + { +#ifdef LOG_THREADS + if (omp_get_thread_num() == 0) + TotalThreadLevel.change_level(omp_get_num_threads()-1, omp_inner); +#endif + //printf("In OMP parallel region on TBB task with myId=0: thread %d of %d\n", omp_get_thread_num(), omp_get_num_threads()); +#ifdef LOG_THREADS + if (omp_get_thread_num() == 0) + TotalThreadLevel.change_level(-(omp_get_num_threads()-1), omp_inner); +#endif + } + } + else { + MilliSleep(6000); + } + } +#ifdef LOG_THREADS + TotalThreadLevel.change_level(-1, tbb_outer); +#endif + return NULL; + } +}; + + +int main(int argc, char *argv[]) { +#ifdef LOG_THREADS + TotalThreadLevel.init(); + TotalThreadLevel.change_level(1, tbb_outer); +#endif + process_args(argc, argv, &max_tbb_threads, &max_omp_threads); + + task_scheduler_init phase(max_tbb_threads); + tick_count start, end; + start = tick_count::now(); + SimpleTask& st = *new(task::allocate_root()) SimpleTask(false, -1); +#ifdef LOG_THREADS + TotalThreadLevel.change_level(-1, tbb_outer); +#endif + task::spawn_root_and_wait(st); +#ifdef LOG_THREADS + TotalThreadLevel.change_level(1, tbb_outer); +#endif + end = tick_count::now(); + printf("Simple Test of TBB (%d threads max) with OMP (%d threads max) inside took: %6.6f\n", + max_tbb_threads, max_omp_threads, (end-start).seconds()); + +#ifdef LOG_THREADS + TotalThreadLevel.change_level(-1, tbb_outer); + TotalThreadLevel.dump(); +#endif + return 0; +} diff --git a/src/tbb/src/rml/perfor/tbb_simple.cpp b/src/tbb/src/rml/perfor/tbb_simple.cpp new file mode 100644 index 0000000..e63831f --- /dev/null +++ b/src/tbb/src/rml/perfor/tbb_simple.cpp @@ -0,0 +1,199 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include <cstddef> +#include <cstdlib> +#include <cstdio> +#include <float.h> +#include <math.h> +#include <time.h> + +#include <omp.h> +#include <assert.h> + +#include "thread_level.h" + +#include "tbb/task.h" +#include "tbb/tick_count.h" +#include "tbb/task_scheduler_init.h" + +#if _WIN32||_WIN64 +#include <Windows.h> /* Need Sleep */ +#else +#include <unistd.h> /* Need usleep */ +#endif + +void MilliSleep( unsigned milliseconds ) { +#if _WIN32||_WIN64 + Sleep( milliseconds ); +#else + usleep( milliseconds*1000 ); +#endif /* _WIN32||_WIN64 */ +} + +using namespace std; +using namespace tbb; + +// Algorithm parameters +const int Max_TBB_Threads = 16; +const int Max_OMP_Threads = 16; + +// Global variables +int max_tbb_threads = Max_TBB_Threads; +int max_omp_threads = Max_OMP_Threads; + +// Print help on command-line arguments +void help_message(char *prog_name) { + fprintf(stderr, "\n%s usage:\n", prog_name); + fprintf(stderr, + " Parameters:\n" + " -t<num> : max # of threads TBB should use\n" + " -o<num> : max # of threads OMP should use\n" + "\n Help:\n" + " -h : print this help message\n"); +} + +// Process command-line arguments +void process_args(int argc, char *argv[], int *max_tbb_t, int *max_omp_t) { + for (int i=1; i<argc; ++i) { + if (argv[i][0] == '-') { + switch (argv[i][1]) { + case 't': // set max_tbb_threads + if (sscanf(&argv[i][2], "%d", max_tbb_t) != 1 || *max_tbb_t < 1) { + fprintf(stderr, "%s Warning: argument of -t option unacceptable: %s\n", argv[0], &argv[i][2]); + help_message(argv[0]); + } + break; + case 'o': // set max_omp_threads + if (sscanf(&argv[i][2], "%d", max_omp_t) != 1 || *max_omp_t < 1) { + fprintf(stderr, "%s Warning: argument of -o option unacceptable: %s\n", argv[0], &argv[i][2]); + help_message(argv[0]); + } + break; + case 'h': // print help message + help_message(argv[0]); + exit(0); + break; + default: + fprintf(stderr, "%s: Warning: command-line option ignored: %s\n", argv[0], argv[i]); + help_message(argv[0]); + break; + } + } else { + fprintf(stderr, "%s: Warning: command-line option ignored: %s\n", argv[0], argv[i]); + help_message(argv[0]); + } + } +} + +class SimpleTask : public task { + bool isLeaf; + int myId; +public: + SimpleTask(bool isLeaf_, int myId_) : isLeaf(isLeaf_), myId(myId_) {} + task* execute() { +#ifdef LOG_THREADS + TotalThreadLevel.change_level(1, tbb_outer); +#endif + omp_set_num_threads(max_omp_threads); + if (!isLeaf) { + set_ref_count(17); + for (int i=0; i<16; ++i) { + SimpleTask& st = *new(allocate_child()) SimpleTask(true, i); + spawn(st); + } +#ifdef LOG_THREADS + TotalThreadLevel.change_level(-1, tbb_outer); +#endif + wait_for_all(); +#ifdef LOG_THREADS + TotalThreadLevel.change_level(1, tbb_outer); +#endif + } + else { + if (myId == 0) { + MilliSleep(3000); +#ifdef LOG_THREADS + TotalThreadLevel.change_level(-1, tbb_outer); +#endif +#pragma omp parallel + { +#ifdef LOG_THREADS + if (omp_get_thread_num() == 0) + TotalThreadLevel.change_level(omp_get_num_threads(), omp_inner); +#endif + printf("In OMP parallel region on TBB task with myId=0: thread %d of %d\n", + omp_get_thread_num(), omp_get_num_threads()); +#ifdef LOG_THREADS + if (omp_get_thread_num() == 0) + TotalThreadLevel.change_level(-omp_get_num_threads(), omp_inner); +#endif + } +#ifdef LOG_THREADS + TotalThreadLevel.change_level(1, tbb_outer); +#endif + } + else { + MilliSleep(6000); + } + } +#ifdef LOG_THREADS + TotalThreadLevel.change_level(-1, tbb_outer); +#endif + return NULL; + } +}; + + +int main(int argc, char *argv[]) { +#ifdef LOG_THREADS + TotalThreadLevel.init(); + TotalThreadLevel.change_level(1, tbb_outer); +#endif + process_args(argc, argv, &max_tbb_threads, &max_omp_threads); + + task_scheduler_init phase(max_tbb_threads); + tick_count start, end; + start = tick_count::now(); + SimpleTask& st = *new(task::allocate_root()) SimpleTask(false, -1); +#ifdef LOG_THREADS + TotalThreadLevel.change_level(-1, tbb_outer); +#endif + task::spawn_root_and_wait(st); +#ifdef LOG_THREADS + TotalThreadLevel.change_level(1, tbb_outer); +#endif + end = tick_count::now(); + printf("Simple Test of TBB (%d threads max) with OMP (%d threads max) inside took: %6.6f\n", + max_tbb_threads, max_omp_threads, (end-start).seconds()); +#ifdef LOG_THREADS + TotalThreadLevel.change_level(-1, tbb_outer); + TotalThreadLevel.dump(); +#endif + return 0; +} diff --git a/src/tbb/src/rml/perfor/thread_level.h b/src/tbb/src/rml/perfor/thread_level.h new file mode 100644 index 0000000..9c323da --- /dev/null +++ b/src/tbb/src/rml/perfor/thread_level.h @@ -0,0 +1,142 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Thread level recorder +#ifndef __THREAD_LEVEL_H +#define __THREAD_LEVEL_H +#include <cstdio> +#include <omp.h> +#include <assert.h> +#include "tbb/atomic.h" +#include "tbb/tick_count.h" + +//#define LOG_THREADS // use this to ifdef out calls to this class +//#define NO_BAIL_OUT // continue execution after detecting oversubscription + +using namespace tbb; + +typedef enum {tbb_outer, tbb_inner, omp_outer, omp_inner} client_t; + +class ThreadLevelRecorder { + tbb::atomic<int> tbb_outer_level; + tbb::atomic<int> tbb_inner_level; + tbb::atomic<int> omp_outer_level; + tbb::atomic<int> omp_inner_level; + struct record { + tbb::tick_count time; + int n_tbb_outer_thread; + int n_tbb_inner_thread; + int n_omp_outer_thread; + int n_omp_inner_thread; + }; + tbb::atomic<unsigned> next; + /** Must be power of two */ + static const unsigned max_record_count = 1<<20; + record array[max_record_count]; + int max_threads; + bool fail; + public: + void change_level(int delta, client_t whichClient); + void dump(); + void init(); +}; + +void ThreadLevelRecorder::change_level(int delta, client_t whichClient) { + int tox=tbb_outer_level, tix=tbb_inner_level, oox=omp_outer_level, oix=omp_inner_level; + if (whichClient == tbb_outer) { + tox = tbb_outer_level+=delta; + } else if (whichClient == tbb_inner) { + tix = tbb_inner_level+=delta; + } else if (whichClient == omp_outer) { + oox = omp_outer_level+=delta; + } else if (whichClient == omp_inner) { + oix = omp_inner_level+=delta; + } else { + printf("WARNING: Bad client type; ignoring.\n"); + return; + } + // log non-negative entries + tbb::tick_count t = tbb::tick_count::now(); + unsigned k = next++; + if (k<max_record_count) { + record& r = array[k]; + r.time = t; + r.n_tbb_outer_thread = tox>=0?tox:0; + r.n_omp_outer_thread = oox>=0?oox:0; + r.n_tbb_inner_thread = tix>=0?tix:0; + r.n_omp_inner_thread = oix>=0?oix:0; + } + char errStr[100]; + int tot_threads; + tot_threads = tox+tix+oox+oix; + sprintf(errStr, "ERROR: Number of threads (%d+%d+%d+%d=%d) in use exceeds maximum (%d).\n", + tox, tix, oox, oix, tot_threads, max_threads); + if (tot_threads > max_threads) { +#ifdef NO_BAIL_OUT + if (!fail) { + printf("%sContinuing...\n", errStr); + fail = true; + } +#else + dump(); + printf("%s\n", errStr); + assert(tot_threads <= max_threads); +#endif + } +} + +void ThreadLevelRecorder::dump() { + FILE* f = fopen("time.txt","w"); + if (!f) { + perror("fopen(time.txt)\n"); + exit(1); + } + unsigned limit = next; + if (limit>max_record_count) { // Clip + limit = max_record_count; + } + for (unsigned i=0; i<limit; ++i) { + fprintf(f,"%f\t%d\t%d\t%d\t%d\n",(array[i].time-array[0].time).seconds(), array[i].n_tbb_outer_thread, + array[i].n_tbb_inner_thread, array[i].n_omp_outer_thread, array[i].n_omp_inner_thread); + } + fclose(f); + int tox=tbb_outer_level, tix=tbb_inner_level, oox=omp_outer_level, oix=omp_inner_level; + int tot_threads; + tot_threads = tox+tix+oox+oix; + if (!fail) printf("INFO: Passed.\n"); + else printf("INFO: Failed.\n"); +} + +void ThreadLevelRecorder::init() { + fail = false; + max_threads = omp_get_max_threads(); + printf("INFO: Getting maximum hardware threads... %d.\n", max_threads); +} + +ThreadLevelRecorder TotalThreadLevel; +#endif diff --git a/src/tbb/src/rml/server/index.html b/src/tbb/src/rml/server/index.html new file mode 100644 index 0000000..4107716 --- /dev/null +++ b/src/tbb/src/rml/server/index.html @@ -0,0 +1,18 @@ +<HTML> +<BODY> +<H2>Overview</H2> + +This directory has source code internal to the server. + +<HR> +<A HREF="../index.html">Up to parent directory</A> +<p></p> +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +<P></P> +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +<p></p> +* Other names and brands may be claimed as the property of others. +</BODY> +</HTML> + diff --git a/src/tbb/src/rml/server/irml.rc b/src/tbb/src/rml/server/irml.rc new file mode 100644 index 0000000..1ed76ba --- /dev/null +++ b/src/tbb/src/rml/server/irml.rc @@ -0,0 +1,126 @@ +// Copyright 2005-2012 Intel Corporation. All Rights Reserved. +// +// This file is part of Threading Building Blocks. +// +// Threading Building Blocks is free software; you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// Threading Building Blocks is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Threading Building Blocks; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// Microsoft Visual C++ generated resource script. +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include <winresrc.h> +#define ENDL "\r\n" +#include "tbb/tbb_version.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Neutral resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// manifest integration +#ifdef TBB_MANIFEST +#include "winuser.h" +2 RT_MANIFEST tbbmanifest.exe.manifest +#endif + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION TBB_VERNUMBERS + PRODUCTVERSION TBB_VERNUMBERS + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "CompanyName", "Intel Corporation\0" + VALUE "FileDescription", "Threading Building Blocks resource manager library\0" + VALUE "FileVersion", TBB_VERSION "\0" +//what is it? VALUE "InternalName", "irml\0" + VALUE "LegalCopyright", "Copyright 2005-2012 Intel Corporation. All Rights Reserved.\0" + VALUE "LegalTrademarks", "\0" +#ifndef TBB_USE_DEBUG + VALUE "OriginalFilename", "irml.dll\0" +#else + VALUE "OriginalFilename", "irml_debug.dll\0" +#endif + VALUE "ProductName", "Intel(R) Threading Building Blocks for Windows\0" + VALUE "ProductVersion", TBB_VERSION "\0" + VALUE "Comments", TBB_VERSION_STRINGS "\0" + VALUE "PrivateBuild", "\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END + +#endif // Neutral resources +///////////////////////////////////////////////////////////////////////////// + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/tbb/src/rml/server/job_automaton.h b/src/tbb/src/rml/server/job_automaton.h new file mode 100644 index 0000000..8720cbe --- /dev/null +++ b/src/tbb/src/rml/server/job_automaton.h @@ -0,0 +1,153 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __RML_job_automaton_H +#define __RML_job_automaton_H + +#include "rml_base.h" +#include "tbb/atomic.h" + +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) + // Workaround for overzealous compiler warnings + #pragma warning (push) + #pragma warning (disable: 4244) +#endif + +namespace rml { + +namespace internal { + +//! Finite state machine. +/** /--------------\ + / V + 0 --> 1--> ptr --> -1 + ^ + | + | + V + ptr|1 + +"owner" = corresponding server_thread. +Odd states (except -1) indicate that someone is executing code on the job. +Most transitions driven only by owner. +Transition 0-->-1 is driven by non-owner. +Transition ptr->-1 is driven by owner or non-owner. +*/ +class job_automaton: no_copy { +private: + tbb::atomic<intptr_t> my_job; +public: + /** Created by non-owner */ + job_automaton() { + my_job = 0; + } + + ~job_automaton() { + __TBB_ASSERT( my_job==-1, "must plug before destroying" ); + } + + //! Try to transition 0-->1 or ptr-->ptr|1. + /** Should only be called by owner. */ + bool try_acquire() { + intptr_t snapshot = my_job; + if( snapshot==-1 ) { + return false; + } else { + __TBB_ASSERT( (snapshot&1)==0, "already marked that way" ); + intptr_t old = my_job.compare_and_swap( snapshot|1, snapshot ); + __TBB_ASSERT( old==snapshot || old==-1, "unexpected interference" ); + return old==snapshot; + } + } + //! Transition ptr|1-->ptr + /** Should only be called by owner. */ + void release() { + intptr_t snapshot = my_job; + __TBB_ASSERT( snapshot&1, NULL ); + // Atomic store suffices here. + my_job = snapshot&~1; + } + + //! Transition 1-->ptr + /** Should only be called by owner. */ + void set_and_release( rml::job& job ) { + intptr_t value = reinterpret_cast<intptr_t>(&job); + __TBB_ASSERT( (value&1)==0, "job misaligned" ); + __TBB_ASSERT( value!=0, "null job" ); + __TBB_ASSERT( my_job==1, "already set, or not marked busy?" ); + // Atomic store suffices here. + my_job = value; + } + + //! Transition 0-->-1 + /** If successful, return true. called by non-owner (for TBB and the likes) */ + bool try_plug_null() { + return my_job.compare_and_swap( -1, 0 )==0; + } + + //! Try to transition to -1. If successful, set j to contents and return true. + /** Called by owner or non-owner. (for OpenMP and the likes) */ + bool try_plug( rml::job*&j ) { + for(;;) { + intptr_t snapshot = my_job; + if( snapshot&1 ) { + j = NULL; + return false; + } + // Not busy + if( my_job.compare_and_swap( -1, snapshot )==snapshot ) { + j = reinterpret_cast<rml::job*>(snapshot); + return true; + } + // Need to retry, because current thread may be non-owner that read a 0, and owner might have + // caused transition 0->1->ptr after we took our snapshot. + } + } + + /** Called by non-owner to wait for transition to ptr. */ + rml::job& wait_for_job() const { + intptr_t snapshot; + for(;;) { + snapshot = my_job; + if( snapshot&~1 ) break; + __TBB_Yield(); + } + __TBB_ASSERT( snapshot!=-1, "wait on plugged job_automaton" ); + return *reinterpret_cast<rml::job*>(snapshot&~1); + } +}; + +} // namespace internal +} // namespace rml + + +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) + #pragma warning (pop) +#endif // warning 4244 are back + +#endif /* __RML_job_automaton_H */ diff --git a/src/tbb/src/rml/server/lin-rml-export.def b/src/tbb/src/rml/server/lin-rml-export.def new file mode 100644 index 0000000..780c18c --- /dev/null +++ b/src/tbb/src/rml/server/lin-rml-export.def @@ -0,0 +1,38 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +{ +global: +__RML_open_factory; +__RML_close_factory; +__TBB_make_rml_server; +__KMP_make_rml_server; +__TBB_call_with_my_server_info; +__KMP_call_with_my_server_info; +local:*; +}; diff --git a/src/tbb/src/rml/server/rml_server.cpp b/src/tbb/src/rml/server/rml_server.cpp new file mode 100644 index 0000000..7a0fd63 --- /dev/null +++ b/src/tbb/src/rml/server/rml_server.cpp @@ -0,0 +1,3327 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "rml_tbb.h" +#define private public /* Sleazy trick to avoid publishing internal names in public header. */ +#include "rml_omp.h" +#undef private + +#include "tbb/tbb_allocator.h" +#include "tbb/cache_aligned_allocator.h" +#include "tbb/aligned_space.h" +#include "tbb/atomic.h" +#include "tbb/spin_mutex.h" +#include "tbb/tbb_misc.h" // Get AvailableHwConcurrency() from here. +#if _MSC_VER==1500 && !defined(__INTEL_COMPILER) +// VS2008/VC9 seems to have an issue; +#pragma warning( push ) +#pragma warning( disable: 4985 ) +#endif +#include "tbb/concurrent_vector.h" +#if _MSC_VER==1500 && !defined(__INTEL_COMPILER) +#pragma warning( pop ) +#endif +#if _MSC_VER && defined(_Wp64) +// Workaround for overzealous compiler warnings +#pragma warning (push) +#pragma warning (disable: 4244) +#endif + +#include "job_automaton.h" +#include "wait_counter.h" +#include "thread_monitor.h" + +#if RML_USE_WCRM +#include <concrt.h> +#include <concrtrm.h> +using namespace Concurrency; +#include <vector> +#include <hash_map> +#define __RML_REMOVE_VIRTUAL_PROCESSORS_DISABLED 0 +#endif /* RML_USE_WCRM */ + +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) + +namespace rml { +namespace internal { + +using tbb::internal::rml::tbb_client; +using tbb::internal::rml::tbb_server; + +using __kmp::rml::omp_client; +using __kmp::rml::omp_server; + +typedef versioned_object::version_type version_type; + +#define SERVER_VERSION 2 +#define EARLIEST_COMPATIBLE_CLIENT_VERSION 2 + +static const size_t cache_line_size = tbb::internal::NFS_MaxLineSize; + +template<typename Server, typename Client> class generic_connection; +class tbb_connection_v2; +class omp_connection_v2; + +#if RML_USE_WCRM +//! State of a server_thread +/** Below are diagrams of legal state transitions. + + ts_busy + ^ ^ + / \ + / V + ts_done <----- ts_asleep <------> ts_idle +*/ + +enum thread_state_t { + ts_idle, + ts_asleep, + ts_busy, + ts_done +}; + +//! Extra state of an omp server thread +enum thread_extra_state_t { + ts_none, + ts_removed, + ts_lent +}; + +//! Results from try_grab_for() +enum thread_grab_t { + wk_failed, + wk_from_asleep, + wk_from_idle +}; + +#else /* !RML_USE_WCRM */ + +//! State of a server_thread +/** Below are diagrams of legal state transitions. + + OMP + ts_omp_busy + ^ ^ + / \ + / V + ts_asleep <-----------> ts_idle + + + ts_deactivated + ^ ^ + / \ + V \ + ts_none <--------------> ts_reactivated + + TBB + ts_tbb_busy + ^ ^ + / \ + / V + ts_asleep <-----------> ts_idle --> ts_done + + For TBB only. Extra state transition. + + ts_created -> ts_started -> ts_visited + */ +enum thread_state_t { + //! Thread not doing anything useful, but running and looking for work. + ts_idle, + //! Thread not doing anything useful and is asleep */ + ts_asleep, + //! Thread is enlisted into OpenMP team + ts_omp_busy, + //! Thread is busy doing TBB work. + ts_tbb_busy, + //! For tbb threads only + ts_done, + ts_created, + ts_started, + ts_visited, + //! For omp threads only + ts_none, + ts_deactivated, + ts_reactivated +}; +#endif /* RML_USE_WCRM */ + +#if TBB_USE_ASSERT +#define PRODUCE_ARG(x) ,x +#else +#define PRODUCE_ARG(x) +#endif /* TBB_USE_ASSERT */ + +//! Synchronizes dispatch of OpenMP work. +class omp_dispatch_type { + typedef ::rml::job job_type; + omp_client* client; + void* cookie; + omp_client::size_type index; + tbb::atomic<job_type*> job; +#if TBB_USE_ASSERT + omp_connection_v2* server; +#endif /* TBB_USE_ASSERT */ +public: + omp_dispatch_type() {job=NULL;} + void consume(); + void produce( omp_client& c, job_type& j, void* cookie_, omp_client::size_type index_ PRODUCE_ARG( omp_connection_v2& s )) { + __TBB_ASSERT( &j, NULL ); + __TBB_ASSERT( !job, "job already set" ); + client = &c; +#if TBB_USE_ASSERT + server = &s; +#endif /* TBB_USE_ASSERT */ + cookie = cookie_; + index = index_; + // Must be last + job = &j; + } +}; + +//! A reference count. +/** No default constructor, because users of ref_count must be very careful about whether the + initial reference count is 0 or 1. */ +class ref_count: no_copy { + friend class thread_map; + tbb::atomic<int> my_ref_count; +public: + ref_count(int k ) {my_ref_count=k;} + ~ref_count() {__TBB_ASSERT( !my_ref_count, "premature destruction of refcounted object" );} + //! Add one and return new value. + int add_ref() { + int k = ++my_ref_count; + __TBB_ASSERT(k>=1,"reference count underflowed before add_ref"); + return k; + } + //! Subtract one and return new value. + int remove_ref() { + int k = --my_ref_count; + __TBB_ASSERT(k>=0,"reference count underflow"); + return k; + } +}; + +#if RML_USE_WCRM + +#if USE_UMS_THREAD +#define RML_THREAD_KIND UmsThreadDefault +#define RML_THREAD_KIND_STRING "UmsThread" +#else +#define RML_THREAD_KIND ThreadScheduler +#define RML_THREAD_KIND_STRING "WinThread" +#endif + +// Forward declaration +class thread_map; + +static const IExecutionResource* c_remove_prepare = (IExecutionResource*)0; +static const IExecutionResource* c_remove_returned = (IExecutionResource*)1; + +//! Server thread representation +class server_thread_rep : no_copy { + friend class thread_map; + friend class omp_connection_v2; + friend class server_thread; + friend class tbb_server_thread; + friend class omp_server_thread; + template<typename Connection> friend void make_job( Connection& c, typename Connection::server_thread_type& t ); + typedef int thread_state_rep_t; +public: + //! Ctor + server_thread_rep( bool assigned, IScheduler* s, IExecutionResource* r, thread_map& map, rml::client& cl ) : + uid( GetExecutionContextId() ), my_scheduler(s), my_proxy(NULL), + my_thread_map(map), my_client(cl), my_job(NULL) + { + my_state = assigned ? ts_busy : ts_idle; + my_extra_state = ts_none; + terminate = false; + my_execution_resource = r; + } + //! Dtor + ~server_thread_rep() {} + + //! Synchronization routine + inline rml::job* wait_for_job() { + if( !my_job ) my_job = &my_job_automaton.wait_for_job(); + return my_job; + } + + // Getters and setters + inline thread_state_t read_state() const { thread_state_rep_t s = my_state; return static_cast<thread_state_t>(s); } + inline void set_state( thread_state_t to ) {my_state = to;} + inline void set_removed() { __TBB_ASSERT( my_extra_state==ts_none, NULL ); my_extra_state = ts_removed; } + inline bool is_removed() const { return my_extra_state==ts_removed; } + inline bool is_lent() const {return my_extra_state==ts_lent;} + inline void set_lent() { my_extra_state=ts_lent; } + inline void set_returned() { my_extra_state=ts_none; } + inline IExecutionResource* get_execution_resource() { return my_execution_resource; } + inline IVirtualProcessorRoot* get_virtual_processor() { return (IVirtualProcessorRoot*)get_execution_resource(); } + + //! Enlist the thread for work + inline bool wakeup( thread_state_t to, thread_state_t from ) { + __TBB_ASSERT( from==ts_asleep && (to==ts_idle||to==ts_busy||to==ts_done), NULL ); + return my_state.compare_and_swap( to, from )==from; + } + + //! Enlist the thread for. + thread_grab_t try_grab_for(); + + //! Destroy the client job associated with the thread + template<typename Connection> bool destroy_job( Connection* c ); + + //! Try to re-use the thread + void revive( IScheduler* s, IExecutionResource* r, rml::client& c ) { + // the variables may not have been set before a thread was told to quit + __TBB_ASSERT( my_scheduler==s, "my_scheduler has been altered?\n" ); + my_scheduler = s; + __TBB_ASSERT( &my_client==&c, "my_client has been altered?\n" ); + if( r ) my_execution_resource = r; + my_client = c; + my_state = ts_idle; + __TBB_ASSERT( my_extra_state==ts_removed, NULL ); + my_extra_state = ts_none; + } + +protected: + const int uid; + IScheduler* my_scheduler; + IThreadProxy* my_proxy; + tbb::atomic<IExecutionResource*> my_execution_resource; /* for non-masters, it is IVirtualProcessorRoot */ + thread_map& my_thread_map; + rml::client& my_client; + job* my_job; + job_automaton my_job_automaton; + tbb::atomic<bool> terminate; + tbb::atomic<thread_state_rep_t> my_state; + tbb::atomic<thread_extra_state_t> my_extra_state; +}; + +//! Class that implements IExecutionContext +class server_thread : public IExecutionContext, public server_thread_rep { + friend class tbb_connection_v2; + friend class omp_connection_v2; + friend class tbb_server_thread; + friend class omp_server_thread; + friend class thread_map; + template<typename Connection> friend void make_job( Connection& c, typename Connection::server_thread_type& t ); +protected: + server_thread( bool is_tbb, bool assigned, IScheduler* s, IExecutionResource* r, thread_map& map, rml::client& cl ) : server_thread_rep(assigned,s,r,map,cl), tbb_thread(is_tbb) {} + ~server_thread() {} + /*override*/ unsigned int GetId() const { return uid; } + /*override*/ IScheduler* GetScheduler() { return my_scheduler; } + /*override*/ IThreadProxy* GetProxy() { return my_proxy; } + /*override*/ void SetProxy( IThreadProxy* thr_proxy ) { my_proxy = thr_proxy; } + +private: + bool tbb_thread; +}; + +// Forward declaration +class tbb_connection_v2; +class omp_connection_v2; + +//! TBB server thread +class tbb_server_thread : public server_thread { + friend class tbb_connection_v2; +public: + tbb_server_thread( bool assigned, IScheduler* s, IExecutionResource* r, tbb_connection_v2* con, thread_map& map, rml::client& cl ) : server_thread(true,assigned,s,r,map,cl), my_conn(con) { + activation_count = 0; + } + ~tbb_server_thread() {} + /*override*/ void Dispatch( DispatchState* ); + inline bool initiate_termination(); + bool sleep_perhaps(); + //! Switch out this thread + bool switch_out(); +private: + tbb_connection_v2* my_conn; +public: + tbb::atomic<int> activation_count; +}; + +//! OMP server thread +class omp_server_thread : public server_thread { + friend class omp_connection_v2; +public: + omp_server_thread( bool assigned, IScheduler* s, IExecutionResource* r, omp_connection_v2* con, thread_map& map, rml::client& cl ) : + server_thread(false,assigned,s,r,map,cl), my_conn(con), my_cookie(NULL), my_index(UINT_MAX) {} + ~omp_server_thread() {} + /*override*/ void Dispatch( DispatchState* ); + inline void* get_cookie() {return my_cookie;} + inline ::__kmp::rml::omp_client::size_type get_index() {return my_index;} + + inline IExecutionResource* get_execution_resource() { return get_execution_resource(); } + inline bool initiate_termination() { return destroy_job( (omp_connection_v2*) my_conn ); } + void sleep_perhaps(); +private: + omp_connection_v2* my_conn; + void* my_cookie; + ::__kmp::rml::omp_client::size_type my_index; + omp_dispatch_type omp_data; +}; + +//! Class that implements IScheduler +template<typename Connection> +class scheduler : no_copy, public IScheduler { +public: + /*override*/ unsigned int GetId() const {return uid;} + /*override*/ void Statistics( unsigned int* /*pTaskCompletionRate*/, unsigned int* /*pTaskArrivalRate*/, unsigned int* /*pNumberOfTaskEnqueued*/) {} + /*override*/ SchedulerPolicy GetPolicy() const { __TBB_ASSERT(my_policy,NULL); return *my_policy; } + /*override*/ void AddVirtualProcessors( IVirtualProcessorRoot** vproots, unsigned int count ) { if( !my_conn.is_closing() ) my_conn.add_virtual_processors( vproots, count); } + /*override*/ void RemoveVirtualProcessors( IVirtualProcessorRoot** vproots, unsigned int count ); + /*override*/ void NotifyResourcesExternallyIdle( IVirtualProcessorRoot** vproots, unsigned int count ) { __TBB_ASSERT( false, "This call is not allowed for TBB" ); } + /*override*/ void NotifyResourcesExternallyBusy( IVirtualProcessorRoot** vproots, unsigned int count ) { __TBB_ASSERT( false, "This call is not allowed for TBB" ); } +protected: + scheduler( Connection& conn ); + virtual ~scheduler() { __TBB_ASSERT( my_policy, NULL ); delete my_policy; } + +public: + static scheduler* create( Connection& conn ) {return new scheduler( conn );} + +private: + const int uid; + Connection& my_conn; + SchedulerPolicy* my_policy; +}; + + +/* + * --> ts_busy --> ts_done + */ +class thread_scavenger_thread : public IExecutionContext, no_copy { +public: + thread_scavenger_thread( IScheduler* s, IVirtualProcessorRoot* r, thread_map& map ) : + uid( GetExecutionContextId() ), my_scheduler(s), my_virtual_processor_root(r), my_proxy(NULL), my_thread_map(map) + { + my_state = ts_busy; +#if TBB_USE_ASSERT + activation_count = 0; +#endif + } + ~thread_scavenger_thread() {} + /*override*/ unsigned int GetId() const { return uid; } + /*override*/ IScheduler* GetScheduler() { return my_scheduler; } + /*override*/ IThreadProxy* GetProxy() { return my_proxy; } + /*override*/ void SetProxy( IThreadProxy* thr_proxy ) { my_proxy = thr_proxy; } + /*override*/ void Dispatch( DispatchState* ); + inline thread_state_t read_state() { return my_state; } + inline void set_state( thread_state_t s ) { my_state = s; } + inline IVirtualProcessorRoot* get_virtual_processor() { return my_virtual_processor_root; } +private: + const int uid; + IScheduler* my_scheduler; + IVirtualProcessorRoot* my_virtual_processor_root; + IThreadProxy* my_proxy; + thread_map& my_thread_map; + tbb::atomic<thread_state_t> my_state; +#if TBB_USE_ASSERT +public: + tbb::atomic<int> activation_count; +#endif +}; + +static const thread_scavenger_thread* c_claimed = reinterpret_cast<thread_scavenger_thread*>(1); + +struct garbage_connection_queue { + tbb::atomic<uintptr_t> head; + tbb::atomic<uintptr_t> tail; + static const uintptr_t empty = 0; // connection scavenger thread empty list + static const uintptr_t plugged = 1; // end of use of the list + static const uintptr_t plugged_acked = 2; // connection scavenger saw the plugged flag, and it freed all connections +}; + +//! Connection scavenger +/** It collects closed connection objects, wait for worker threads belonging to the connection to return to ConcRT RM + * then return the object to the memory manager. + */ +class connection_scavenger_thread { + friend void assist_cleanup_connections(); + /* + * connection_scavenger_thread's state + * ts_busy <----> ts_asleep <-- + */ + tbb::atomic<thread_state_t> state; + + /* We steal two bits from a connection pointer to encode + * whether the connection is for TBB or for OMP. + * + * ---------------------------------- + * | | | | + * ---------------------------------- + * ^ ^ + * / | + * 1 : tbb, 0 : omp | + * if set, terminate + */ + // FIXME: pad these? + thread_monitor monitor; + HANDLE thr_handle; +#if TBB_USE_ASSERT + tbb::atomic<int> n_scavenger_threads; +#endif + +public: + connection_scavenger_thread() : thr_handle(NULL) { + state = ts_asleep; +#if TBB_USE_ASSERT + n_scavenger_threads = 0; +#endif + } + + ~connection_scavenger_thread() {} + + void wakeup() { + if( state.compare_and_swap( ts_busy, ts_asleep )==ts_asleep ) + monitor.notify(); + } + + void sleep_perhaps(); + + void process_requests( uintptr_t conn_ex ); + + static __RML_DECL_THREAD_ROUTINE thread_routine( void* arg ); + + void launch() { + thread_monitor::launch( connection_scavenger_thread::thread_routine, this, NULL ); + } + + template<typename Server, typename Client> + void add_request( generic_connection<Server,Client>* conn_to_close ); + + template<typename Server, typename Client> + uintptr_t grab_and_prepend( generic_connection<Server,Client>* last_conn_to_close ); +}; + +void free_all_connections( uintptr_t ); + +#endif /* RML_USE_WCRM */ + +#if !RML_USE_WCRM +class server_thread; + +//! thread_map_base; we need to make the iterator type available to server_thread +struct thread_map_base { + //! A value in the map + class value_type { + public: + server_thread& thread() { + __TBB_ASSERT( my_thread, "thread_map::value_type::thread() called when !my_thread" ); + return *my_thread; + } + rml::job& job() { + __TBB_ASSERT( my_job, "thread_map::value_type::job() called when !my_job" ); + return *my_job; + } + value_type() : my_thread(NULL), my_job(NULL) {} + server_thread& wait_for_thread() const { + for(;;) { + server_thread* ptr=const_cast<server_thread*volatile&>(my_thread); + if( ptr ) + return *ptr; + __TBB_Yield(); + } + } + /** Shortly after when a connection is established, it is possible for the server + to grab a server_thread that has not yet created a job object for that server. */ + rml::job& wait_for_job() const { + if( !my_job ) { + my_job = &my_automaton.wait_for_job(); + } + return *my_job; + } + private: + server_thread* my_thread; + /** Marked mutable because though it is physically modified, conceptually it is a duplicate of + the job held by job_automaton. */ + mutable rml::job* my_job; + job_automaton my_automaton; + // FIXME - pad out to cache line, because my_automaton is hit hard by thread() + friend class thread_map; + }; + typedef tbb::concurrent_vector<value_type,tbb::zero_allocator<value_type,tbb::cache_aligned_allocator> > array_type; +}; +#endif /* !RML_USE_WCRM */ + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // Suppress overzealous compiler warnings about uninstantiatble class + #pragma warning(push) + #pragma warning(disable:4510 4610) +#endif + +template<typename T> +class padded: public T { + char pad[cache_line_size - sizeof(T)%cache_line_size]; +}; + +#if _MSC_VER && !defined(__INTEL_COMPILER) + #pragma warning(pop) +#endif + +// FIXME - should we pad out memory to avoid false sharing of our global variables? +static unsigned the_default_concurrency; +static tbb::atomic<int> the_balance; +static tbb::atomic<tbb::internal::do_once_state> rml_module_state; + +#if !RML_USE_WCRM +//! Per thread information +/** ref_count holds number of clients that are using this, + plus 1 if a host thread owns this instance. */ +class server_thread: public ref_count { + friend class thread_map; + template<typename Server, typename Client> friend class generic_connection; + friend class tbb_connection_v2; + friend class omp_connection_v2; + //! Integral type that can hold a thread_state_t + typedef int thread_state_rep_t; + tbb::atomic<thread_state_rep_t> state; +public: + thread_monitor monitor; +private: + bool is_omp_thread; + tbb::atomic<thread_state_rep_t> my_extra_state; + server_thread* link; + thread_map_base::array_type::iterator my_map_pos; + rml::server *my_conn; + rml::job* my_job; + job_automaton* my_ja; + size_t my_index; + tbb::atomic<bool> terminate; + omp_dispatch_type omp_dispatch; + +#if TBB_USE_ASSERT + //! Flag used to check if thread is still using *this. + bool has_active_thread; +#endif /* TBB_USE_ASSERT */ + + //! Volunteer to sleep. + void sleep_perhaps( thread_state_t asleep ); + + //! Destroy job corresponding to given client + /** Return true if thread must quit. */ + template<typename Connection> + bool destroy_job( Connection& c ); + + //! Do terminate the thread + /** Return true if thread must quit. */ + bool do_termination(); + + void loop(); + static __RML_DECL_THREAD_ROUTINE thread_routine( void* arg ); + +public: + server_thread(); + + ~server_thread(); + + //! Read the thread state + thread_state_t read_state() const { + thread_state_rep_t s = state; + __TBB_ASSERT( unsigned(s)<=unsigned(ts_done), "corrupted server thread?" ); + return thread_state_t(s); + } + + //! Read the tbb-specific extra thread state + thread_state_t read_extra_state() const { + thread_state_rep_t s = my_extra_state; + return thread_state_t(s); + } + + //! Launch a thread that is bound to *this. + void launch( size_t stack_size ); + + //! Attempt to wakeup a thread + /** The value "to" is the new state for the thread, if it was woken up. + Returns true if thread was woken up, false otherwise. */ + bool wakeup( thread_state_t to, thread_state_t from ); + + //! Attempt to enslave a thread for OpenMP/TBB. + /** Returns true if state is successfully changed. 's' takes either ts_omp_busy or ts_tbb_busy */ + bool try_grab_for( thread_state_t s ); + +#if _WIN32||_WIN64 + //! Send the worker thread to sleep temporarily + void deactivate(); + + //! Wake the worker thread up + void reactivate(); +#endif /* _WIN32||_WIN64 */ +}; + +//! Bag of threads that are private to a client. +class private_thread_bag { + struct list_thread: server_thread { + list_thread* next; + }; + //! Root of atomic linked list of list_thread + /** ABA problem is avoided because items are only atomically pushed, never popped. */ + tbb::atomic<list_thread*> my_root; + tbb::cache_aligned_allocator<padded<list_thread> > my_allocator; +public: + //! Construct empty bag + private_thread_bag() {my_root=NULL;} + + //! Create a fresh server_thread object. + server_thread& add_one_thread() { + list_thread* t = my_allocator.allocate(1); + new( t ) list_thread; + // Atomically add to list + list_thread* old_root; + do { + old_root = my_root; + t->next = old_root; + } while( my_root.compare_and_swap( t, old_root )!=old_root ); + return *t; + } + + //! Destroy the bag and threads in it. + ~private_thread_bag() { + while( my_root ) { + // Unlink thread from list. + list_thread* t = my_root; + my_root = t->next; + // Destroy and deallocate the thread. + t->~list_thread(); + my_allocator.deallocate(static_cast<padded<list_thread>*>(t),1); + } + } +}; + +//! Forward declaration +void wakeup_some_tbb_threads(); + +//! Type-independent part of class generic_connection. +/** One to one map from server threads to jobs, and associated reference counting. */ +class thread_map : public thread_map_base { +public: + typedef rml::client::size_type size_type; + //! ctor + thread_map( wait_counter& fc, ::rml::client& client ) : + all_visited_at_least_once(false), my_min_stack_size(0), my_server_ref_count(1), + my_client_ref_count(1), my_client(client), my_factory_counter(fc) + { my_unrealized_threads = 0; } + //! dtor + ~thread_map() {} + typedef array_type::iterator iterator; + iterator begin() {return my_array.begin();} + iterator end() {return my_array.end();} + void bind(); + void unbind(); + void assist_cleanup( bool assist_null_only ); + + /** Returns number of unrealized threads to create. */ + size_type wakeup_tbb_threads( size_type n ); + bool wakeup_next_thread( iterator i, tbb_connection_v2& conn ); + void release_tbb_threads( server_thread* t ); + void adjust_balance( int delta ); + + //! Add a server_thread object to the map, but do not bind it. + /** Return NULL if out of unrealized threads. */ + value_type* add_one_thread( bool is_omp_thread_ ); + + void bind_one_thread( rml::server& server, value_type& x ); + + void remove_client_ref(); + int add_server_ref() {return my_server_ref_count.add_ref();} + int remove_server_ref() {return my_server_ref_count.remove_ref();} + + ::rml::client& client() const {return my_client;} + + size_type get_unrealized_threads() { return my_unrealized_threads; } + +private: + private_thread_bag my_private_threads; + bool all_visited_at_least_once; + array_type my_array; + size_t my_min_stack_size; + tbb::atomic<size_type> my_unrealized_threads; + + //! Number of threads referencing *this, plus one extra. + /** When it becomes zero, the containing server object can be safely deleted. */ + ref_count my_server_ref_count; + + //! Number of jobs that need cleanup, plus one extra. + /** When it becomes zero, acknowledge_close_connection is called. */ + ref_count my_client_ref_count; + + ::rml::client& my_client; + //! Counter owned by factory that produced this thread_map. + wait_counter& my_factory_counter; +}; + +void thread_map::bind_one_thread( rml::server& server, value_type& x ) { + // Add one to account for the thread referencing this map hereforth. + server_thread& t = x.thread(); + my_server_ref_count.add_ref(); + my_client_ref_count.add_ref(); +#if TBB_USE_ASSERT + __TBB_ASSERT( t.add_ref()==1, NULL ); +#else + t.add_ref(); +#endif + // Have responsibility to start the thread. + t.my_conn = &server; + t.my_ja = &x.my_automaton; + t.launch( my_min_stack_size ); + /* Must wake thread up so it can fill in its "my_job" field in *this. + Otherwise deadlock can occur where wait_for_job spins on thread that is sleeping. */ + __TBB_ASSERT( t.state!=ts_tbb_busy, NULL ); + t.wakeup( ts_idle, ts_asleep ); +} + +thread_map::value_type* thread_map::add_one_thread( bool is_omp_thread_ ) { + size_type u; + do { + u = my_unrealized_threads; + if( !u ) return NULL; + } while( my_unrealized_threads.compare_and_swap(u-1,u)!=u ); + server_thread& t = my_private_threads.add_one_thread(); + t.is_omp_thread = is_omp_thread_; + __TBB_ASSERT( u>=1, NULL ); + t.my_index = u - 1; + __TBB_ASSERT( t.state!=ts_tbb_busy, NULL ); + t.my_extra_state = t.is_omp_thread ? ts_none : ts_created; + + iterator i = t.my_map_pos = my_array.grow_by(1); + value_type& v = *i; + v.my_thread = &t; + return &v; +} + +void thread_map::bind() { + ++my_factory_counter; + my_min_stack_size = my_client.min_stack_size(); + __TBB_ASSERT( my_unrealized_threads==0, "already called bind?" ); + my_unrealized_threads = my_client.max_job_count(); +} + +void thread_map::unbind() { + // Ask each server_thread to cleanup its job for this server. + for( iterator i=begin(); i!=end(); ++i ) { + server_thread& t = i->thread(); + t.terminate = true; + t.wakeup( ts_idle, ts_asleep ); + } + // Remove extra ref to client. + remove_client_ref(); +} + +void thread_map::assist_cleanup( bool assist_null_only ) { + // To avoid deadlock, the current thread *must* help out with cleanups that have not started, + // becausd the thread that created the job may be busy for a long time. + for( iterator i = begin(); i!=end(); ++i ) { + rml::job* j=0; + job_automaton& ja = i->my_automaton; + if( assist_null_only ? ja.try_plug_null() : ja.try_plug(j) ) { + if( j ) { + my_client.cleanup(*j); + } else { + // server thread did not get a chance to create a job. + } + remove_client_ref(); + } + } +} + +thread_map::size_type thread_map::wakeup_tbb_threads( size_type n ) { + __TBB_ASSERT(n>0,"must specify positive number of threads to wake up"); + iterator e = end(); + for( iterator k=begin(); k!=e; ++k ) { + // If another thread added *k, there is a tiny timing window where thread() is invalid. + server_thread& t = k->wait_for_thread(); + thread_state_t thr_s = t.read_state(); + if( t.read_extra_state()==ts_created || thr_s==ts_tbb_busy || thr_s==ts_done ) + continue; + if( --the_balance>=0 ) { // try to withdraw a coin from the deposit + while( !t.try_grab_for( ts_tbb_busy ) ) { + thr_s = t.read_state(); + if( thr_s==ts_tbb_busy || thr_s==ts_done ) { + // we lost; move on to the next. + ++the_balance; + goto skip; + } + } + if( --n==0 ) + return 0; + } else { + // overdraft. + ++the_balance; + break; + } +skip: + ; + } + return n<my_unrealized_threads ? n : my_unrealized_threads; +} +#else /* RML_USE_WCRM */ + +class thread_map : no_copy { + friend class omp_connection_v2; + typedef ::std::hash_map<uintptr_t,server_thread*> hash_map_type; + size_t my_min_stack_size; + size_t my_unrealized_threads; + ::rml::client& my_client; + //! Counter owned by factory that produced this thread_map. + wait_counter& my_factory_counter; + //! Ref counters + ref_count my_server_ref_count; + ref_count my_client_ref_count; + // FIXME: pad this? + hash_map_type my_map; + bool shutdown_in_progress; + std::vector<IExecutionResource*> original_exec_resources; + tbb::cache_aligned_allocator<padded<tbb_server_thread> > my_tbb_allocator; + tbb::cache_aligned_allocator<padded<omp_server_thread> > my_omp_allocator; + tbb::cache_aligned_allocator<padded<thread_scavenger_thread> > my_scavenger_allocator; + IResourceManager* my_concrt_resource_manager; + IScheduler* my_scheduler; + ISchedulerProxy* my_scheduler_proxy; + tbb::atomic<thread_scavenger_thread*> my_thread_scavenger_thread; +#if TBB_USE_ASSERT + tbb::atomic<int> n_add_vp_requests; + tbb::atomic<int> n_thread_scavengers_created; +#endif +public: + thread_map( wait_counter& fc, ::rml::client& client ) : + my_min_stack_size(0), my_client(client), my_factory_counter(fc), + my_server_ref_count(1), my_client_ref_count(1), shutdown_in_progress(false), + my_concrt_resource_manager(NULL), my_scheduler(NULL), my_scheduler_proxy(NULL) + { + my_thread_scavenger_thread = NULL; +#if TBB_USE_ASSERT + n_add_vp_requests = 0; + n_thread_scavengers_created; +#endif + } + + ~thread_map() { + __TBB_ASSERT( n_thread_scavengers_created<=1, "too many scavenger thread created" ); + // if thread_scavenger_thread is launched, wait for it to complete + if( my_thread_scavenger_thread ) { + __TBB_ASSERT( my_thread_scavenger_thread!=c_claimed, NULL ); + while( my_thread_scavenger_thread->read_state()==ts_busy ) + __TBB_Yield(); + thread_scavenger_thread* tst = my_thread_scavenger_thread; + my_scavenger_allocator.deallocate(static_cast<padded<thread_scavenger_thread>*>(tst),1); + } + // deallocate thread contexts + for( hash_map_type::const_iterator hi=my_map.begin(); hi!=my_map.end(); ++hi ) { + server_thread* thr = hi->second; + if( thr->tbb_thread ) { + while( ((tbb_server_thread*)thr)->activation_count>1 ) + __TBB_Yield(); + ((tbb_server_thread*)thr)->~tbb_server_thread(); + my_tbb_allocator.deallocate(static_cast<padded<tbb_server_thread>*>(thr),1); + } else { + ((omp_server_thread*)thr)->~omp_server_thread(); + my_omp_allocator.deallocate(static_cast<padded<omp_server_thread>*>(thr),1); + } + } + if( my_scheduler_proxy ) { + my_scheduler_proxy->Shutdown(); + my_concrt_resource_manager->Release(); + __TBB_ASSERT( my_scheduler, NULL ); + delete my_scheduler; + } else { + __TBB_ASSERT( !my_scheduler, NULL ); + } + } + typedef hash_map_type::key_type key_type; + typedef hash_map_type::value_type value_type; + typedef hash_map_type::iterator iterator; + iterator begin() {return my_map.begin();} + iterator end() {return my_map.end();} + iterator find( key_type k ) {return my_map.find( k );} + iterator insert( key_type k, server_thread* v ) { + std::pair<iterator,bool> res = my_map.insert( value_type(k,v) ); + return res.first; + } + void bind( IScheduler* s ) { + ++my_factory_counter; + if( s ) { + my_unrealized_threads = s->GetPolicy().GetPolicyValue( MaxConcurrency ); + __TBB_ASSERT( my_unrealized_threads>0, NULL ); + my_scheduler = s; + my_concrt_resource_manager = CreateResourceManager(); // reference count==3 when first created. + my_scheduler_proxy = my_concrt_resource_manager->RegisterScheduler( s, CONCRT_RM_VERSION_1 ); + my_scheduler_proxy->RequestInitialVirtualProcessors( false ); + } + } + bool is_closing() { return shutdown_in_progress; } + void unbind( rml::server& server, ::tbb::spin_mutex& mtx ); + void add_client_ref() { my_server_ref_count.add_ref(); } + void remove_client_ref(); + void add_server_ref() {my_server_ref_count.add_ref();} + int remove_server_ref() {return my_server_ref_count.remove_ref();} + int get_server_ref_count() { int k = my_server_ref_count.my_ref_count; return k; } + void assist_cleanup( bool assist_null_only ); + void adjust_balance( int delta ); + int current_balance() const {int k = the_balance; return k;} + ::rml::client& client() const {return my_client;} + void register_as_master( server::execution_resource_t& v ) const { (IExecutionResource*&)v = my_scheduler_proxy ? my_scheduler_proxy->SubscribeCurrentThread() : NULL; } + // Rremove() should be called from the same thread that subscribed the current h/w thread (i.e., the one that + // called register_as_master() ). + void unregister( server::execution_resource_t v ) const {if( v ) ((IExecutionResource*)v)->Remove( my_scheduler );} + void add_virtual_processors( IVirtualProcessorRoot** vprocs, unsigned int count, tbb_connection_v2& conn, ::tbb::spin_mutex& mtx ); + void add_virtual_processors( IVirtualProcessorRoot** vprocs, unsigned int count, omp_connection_v2& conn, ::tbb::spin_mutex& mtx ); + void remove_virtual_processors( IVirtualProcessorRoot** vproots, unsigned count, ::tbb::spin_mutex& mtx ); + void mark_virtual_processors_as_lent( IVirtualProcessorRoot** vproots, unsigned count, ::tbb::spin_mutex& mtx ); + void create_oversubscribers( unsigned n, std::vector<server_thread*>& thr_vec, omp_connection_v2& conn, ::tbb::spin_mutex& mtx ); + void wakeup_tbb_threads( int c, ::tbb::spin_mutex& mtx ); + void mark_virtual_processors_as_returned( IVirtualProcessorRoot** vprocs, unsigned int count, tbb::spin_mutex& mtx ); + inline void addto_original_exec_resources( IExecutionResource* r, ::tbb::spin_mutex& mtx ) { + ::tbb::spin_mutex::scoped_lock lck(mtx); + __TBB_ASSERT( !is_closing(), "try to regster master while connection is being shutdown?" ); + original_exec_resources.push_back( r ); + } +#if !__RML_REMOVE_VIRTUAL_PROCESSORS_DISABLED + void allocate_thread_scavenger( IExecutionResource* v ); +#endif + inline thread_scavenger_thread* get_thread_scavenger() { return my_thread_scavenger_thread; } +}; + +garbage_connection_queue connections_to_reclaim; +connection_scavenger_thread connection_scavenger; + +#endif /* !RML_USE_WCRM */ + +//------------------------------------------------------------------------ +// generic_connection +//------------------------------------------------------------------------ + +template<typename Server, typename Client> +struct connection_traits {}; + +// head of the active tbb connections +static tbb::atomic<uintptr_t> active_tbb_connections; +static tbb::atomic<int> current_tbb_conn_readers; +static size_t current_tbb_conn_reader_epoch; +static tbb::atomic<size_t> close_tbb_connection_event_count; + +#if RML_USE_WCRM +template<typename Connection> +void make_job( Connection& c, server_thread& t ); +#endif + +template<typename Server, typename Client> +class generic_connection: public Server, no_copy { + /*override*/ version_type version() const {return SERVER_VERSION;} + /*override*/ void yield() {thread_monitor::yield();} + /*override*/ void independent_thread_number_changed( int delta ) { my_thread_map.adjust_balance( -delta ); } + /*override*/ unsigned default_concurrency() const { return the_default_concurrency; } + friend void wakeup_some_tbb_threads(); + friend class connection_scavenger_thread; + +protected: + thread_map my_thread_map; + generic_connection* next_conn; + size_t my_ec; +#if RML_USE_WCRM + // FIXME: pad it? + tbb::spin_mutex map_mtx; + IScheduler* my_scheduler; + void do_open( IScheduler* s ) { + my_scheduler = s; + my_thread_map.bind( s ); + } + bool is_closing() { return my_thread_map.is_closing(); } + void request_close_connection( bool existing ); +#else + void do_open() {my_thread_map.bind();} + void request_close_connection( bool ); +#endif /* RML_USE_WCRM */ + //! Make destructor virtual + virtual ~generic_connection() {} +#if !RML_USE_WCRM + generic_connection( wait_counter& fc, Client& c ) : my_thread_map(fc,c), next_conn(NULL), my_ec(0) {} +#else + generic_connection( wait_counter& fc, Client& c ) : + my_thread_map(fc,c), next_conn(NULL), my_ec(0), map_mtx(), my_scheduler(NULL) {} + void add_virtual_processors( IVirtualProcessorRoot** vprocs, unsigned int count ); + void remove_virtual_processors( IVirtualProcessorRoot** vprocs, unsigned int count ); + void notify_resources_externally_busy( IVirtualProcessorRoot** vprocs, unsigned int count ) { my_thread_map.mark_virtual_processors_as_lent( vprocs, count, map_mtx ); } + void notify_resources_externally_idle( IVirtualProcessorRoot** vprocs, unsigned int count ) { + my_thread_map.mark_virtual_processors_as_returned( vprocs, count, map_mtx ); + } +#endif /* !RML_USE_WCRM */ + +public: + typedef Server server_type; + typedef Client client_type; + Client& client() const {return static_cast<Client&>(my_thread_map.client());} + void set_scratch_ptr( job& j, void* ptr ) { ::rml::server::scratch_ptr(j) = ptr; } +#if RML_USE_WCRM + template<typename Connection> + friend void make_job( Connection& c, server_thread& t ); + void add_server_ref () {my_thread_map.add_server_ref();} + void remove_server_ref() {if( my_thread_map.remove_server_ref()==0 ) delete this;} + void add_client_ref () {my_thread_map.add_client_ref();} + void remove_client_ref() {my_thread_map.remove_client_ref();} +#else /* !RML_USE_WCRM */ + int add_server_ref () {return my_thread_map.add_server_ref();} + void remove_server_ref() {if( my_thread_map.remove_server_ref()==0 ) delete this;} + void remove_client_ref() {my_thread_map.remove_client_ref();} + void make_job( server_thread& t, job_automaton& ja ); +#endif /* RML_USE_WCRM */ + static generic_connection* get_addr( uintptr_t addr_ex ) { + return reinterpret_cast<generic_connection*>( addr_ex&~(uintptr_t)3 ); + } +}; + +//------------------------------------------------------------------------ +// TBB server +//------------------------------------------------------------------------ + +template<> +struct connection_traits<tbb_server,tbb_client> { + static const bool assist_null_only = true; + static const bool is_tbb = true; +}; + +//! Represents a server/client binding. +/** The internal representation uses inheritance for the server part and a pointer for the client part. */ +class tbb_connection_v2: public generic_connection<tbb_server,tbb_client> { + /*override*/ void adjust_job_count_estimate( int delta ); +#if !RML_USE_WCRM +#if _WIN32||_WIN64 + /*override*/ void register_master ( rml::server::execution_resource_t& /*v*/ ) {} + /*override*/ void unregister_master ( rml::server::execution_resource_t /*v*/ ) {} +#endif +#else + /*override*/ void register_master ( rml::server::execution_resource_t& v ) { + my_thread_map.register_as_master(v); + if( v ) ++nesting; + } + /*override*/ void unregister_master ( rml::server::execution_resource_t v ) { + if( v ) { + __TBB_ASSERT( nesting>0, NULL ); + if( --nesting==0 ) { +#if !__RML_REMOVE_VIRTUAL_PROCESSORS_DISABLED + my_thread_map.allocate_thread_scavenger( (IExecutionResource*)v ); +#endif + } + } + my_thread_map.unregister(v); + } + IScheduler* create_scheduler() {return( scheduler<tbb_connection_v2>::create( *this ) );} + friend void free_all_connections( uintptr_t ); + friend class scheduler<tbb_connection_v2>; + friend class execution_context; + friend class connection_scavenger_thread; +#endif /* RML_USE_WCRM */ + friend void wakeup_some_tbb_threads(); + //! Estimate on number of jobs without threads working on them. + tbb::atomic<int> my_slack; + friend class dummy_class_to_shut_up_gratuitous_warning_from_gcc_3_2_3; +#if TBB_USE_ASSERT + tbb::atomic<int> my_job_count_estimate; +#endif /* TBB_USE_ASSERT */ + + tbb::atomic<int> n_adjust_job_count_requests; +#if RML_USE_WCRM + tbb::atomic<int> nesting; +#endif + + // dtor + ~tbb_connection_v2(); + +public: +#if RML_USE_WCRM + typedef tbb_server_thread server_thread_type; +#endif + //! True if there is slack that try_process can use. + bool has_slack() const {return my_slack>0;} + +#if RML_USE_WCRM + bool try_process( job& job ) +#else + bool try_process( server_thread& t, job& job ) +#endif + { + bool visited = false; + // No check for my_slack>0 here because caller is expected to do that check. + int k = --my_slack; + if( k>=0 ) { +#if !RML_USE_WCRM + t.my_extra_state = ts_visited; // remember the thread paid a trip to process() at least once +#endif + client().process(job); + visited = true; + } + ++my_slack; + return visited; + } + + tbb_connection_v2( wait_counter& fc, tbb_client& client ) : generic_connection<tbb_server,tbb_client>(fc,client) + { + my_slack = 0; +#if RML_USE_WCRM + nesting = 0; +#endif +#if TBB_USE_ASSERT + my_job_count_estimate = 0; +#endif /* TBB_USE_ASSERT */ + __TBB_ASSERT( !my_slack, NULL ); + +#if RML_USE_WCRM + do_open( client.max_job_count()>0 ? create_scheduler() : NULL ); +#else + do_open(); +#endif /* !RML_USE_WCRM */ + n_adjust_job_count_requests = 0; + + // Acquire head of active_tbb_connections & push the connection into the list + uintptr_t conn; + do { + for( ; (conn=active_tbb_connections)&1; ) + __TBB_Yield(); + } while( active_tbb_connections.compare_and_swap( conn|1, conn )!=conn ); + + this->next_conn = generic_connection<tbb_server,tbb_client>::get_addr(conn); + // Update and release head of active_tbb_connections + active_tbb_connections = (uintptr_t) this; // set and release + } + inline void wakeup_tbb_threads( unsigned n ) { + my_thread_map.wakeup_tbb_threads( n +#if RML_USE_WCRM + , map_mtx +#endif + ); + } +#if RML_USE_WCRM + inline int get_nesting_level() { return nesting; } +#else + inline bool wakeup_next_thread( thread_map::iterator i ) {return my_thread_map.wakeup_next_thread( i, *this );} + inline thread_map::size_type get_unrealized_threads () {return my_thread_map.get_unrealized_threads();} +#endif /* !RML_USE_WCRM */ +}; + +//------------------------------------------------------------------------ +// OpenMP server +//------------------------------------------------------------------------ + +template<> +struct connection_traits<omp_server,omp_client> { + static const bool assist_null_only = false; + static const bool is_tbb = false; +}; + +class omp_connection_v2: public generic_connection<omp_server,omp_client> { +#if !RML_USE_WCRM + /*override*/ int current_balance() const {return the_balance;} +#else + friend void free_all_connections( uintptr_t ); + friend class scheduler<omp_connection_v2>; + /*override*/ int current_balance() const {return my_thread_map.current_balance();} +#endif /* !RML_USE_WCRM */ + /*override*/ int try_increase_load( size_type n, bool strict ); + /*override*/ void decrease_load( size_type n ); + /*override*/ void get_threads( size_type request_size, void* cookie, job* array[] ); +#if !RML_USE_WCRM +#if _WIN32||_WIN64 + /*override*/ void register_master ( rml::server::execution_resource_t& /*v*/ ) {} + /*override*/ void unregister_master ( rml::server::execution_resource_t /*v*/ ) {} +#endif +#else + /*override*/ void register_master ( rml::server::execution_resource_t& v ) { + my_thread_map.register_as_master( v ); + my_thread_map.addto_original_exec_resources( (IExecutionResource*)v, map_mtx ); + } + /*override*/ void unregister_master ( rml::server::execution_resource_t v ) { my_thread_map.unregister(v); } +#endif /* !RML_USE_WCRM */ +#if _WIN32||_WIN64 + /*override*/ void deactivate( rml::job* j ); + /*override*/ void reactivate( rml::job* j ); +#endif /* _WIN32||_WIN64 */ +#if RML_USE_WCRM +public: + typedef omp_server_thread server_thread_type; +private: + IScheduler* create_scheduler() {return( scheduler<omp_connection_v2>::create( *this ) );} +#endif /* RML_USE_WCRM */ +public: +#if TBB_USE_ASSERT + //! Net change in delta caused by this connection. + /** Should be zero when connection is broken */ + tbb::atomic<int> net_delta; +#endif /* TBB_USE_ASSERT */ + + omp_connection_v2( wait_counter& fc, omp_client& client ) : generic_connection<omp_server,omp_client>(fc,client) { +#if TBB_USE_ASSERT + net_delta = 0; +#endif /* TBB_USE_ASSERT */ +#if RML_USE_WCRM + do_open( create_scheduler() ); +#else + do_open(); +#endif /* RML_USE_WCRM */ + } + ~omp_connection_v2() {__TBB_ASSERT( net_delta==0, "net increase/decrease of load is nonzero" );} +}; + +#if !RML_USE_WCRM +/* to deal with cases where the machine is oversubscribed; we want each thread to trip to try_process() at least once */ +/* this should not involve computing the_balance */ +bool thread_map::wakeup_next_thread( thread_map::iterator this_thr, tbb_connection_v2& conn ) { + if( all_visited_at_least_once ) + return false; + + iterator e = end(); +retry: + bool exist = false; + iterator k=this_thr; + for( ++k; k!=e; ++k ) { + // If another thread added *k, there is a tiny timing window where thread() is invalid. + server_thread& t = k->wait_for_thread(); + if( t.my_extra_state!=ts_visited ) + exist = true; + if( t.read_state()!=ts_tbb_busy && t.my_extra_state==ts_started ) + if( t.try_grab_for( ts_tbb_busy ) ) + return true; + } + for( k=begin(); k!=this_thr; ++k ) { + server_thread& t = k->wait_for_thread(); + if( t.my_extra_state!=ts_visited ) + exist = true; + if( t.read_state()!=ts_tbb_busy && t.my_extra_state==ts_started ) + if( t.try_grab_for( ts_tbb_busy ) ) + return true; + } + + if( exist ) + if( conn.has_slack() ) + goto retry; + else + all_visited_at_least_once = true; + return false; +} + +void thread_map::release_tbb_threads( server_thread* t ) { + for( ; t; t = t->link ) { + while( t->read_state()!=ts_asleep ) + __TBB_Yield(); + t->my_extra_state = ts_started; + } +} +#endif /* !RML_USE_WCRM */ + +void thread_map::adjust_balance( int delta ) { + int new_balance = the_balance += delta; + if( new_balance>0 && 0>=new_balance-delta /*== old the_balance*/ ) + wakeup_some_tbb_threads(); +} + +void thread_map::remove_client_ref() { + int k = my_client_ref_count.remove_ref(); + if( k==0 ) { + // Notify factory that thread has crossed back into RML. + --my_factory_counter; + // Notify client that RML is done with the client object. + my_client.acknowledge_close_connection(); + } +} + +#if RML_USE_WCRM +/** Not a member of generic_connection because we need Connection to be the derived class. */ +template<typename Connection> +void make_job( Connection& c, typename Connection::server_thread_type& t ) { + if( t.my_job_automaton.try_acquire() ) { + rml::job& j = *t.my_client.create_one_job(); + __TBB_ASSERT( &j!=NULL, "client:::create_one_job returned NULL" ); + __TBB_ASSERT( (intptr_t(&j)&1)==0, "client::create_one_job returned misaligned job" ); + t.my_job_automaton.set_and_release( j ); + c.set_scratch_ptr( j, (void*) &t ); + } +} +#endif /* RML_USE_WCRM */ + +#if _MSC_VER && !defined(__INTEL_COMPILER) +// Suppress "conditional expression is constant" warning. +#pragma warning( push ) +#pragma warning( disable: 4127 ) +#endif +#if RML_USE_WCRM +template<typename Server, typename Client> +void generic_connection<Server,Client>::request_close_connection( bool exiting ) { + // for TBB connections, exiting should always be false + if( connection_traits<Server,Client>::is_tbb ) + __TBB_ASSERT( !exiting, NULL); +#if TBB_USE_ASSERT + else if( exiting ) + reinterpret_cast<omp_connection_v2*>(this)->net_delta = 0; +#endif + if( exiting ) { + uintptr_t tail = connections_to_reclaim.tail; + while( connections_to_reclaim.tail.compare_and_swap( garbage_connection_queue::plugged, tail )!=tail ) + __TBB_Yield(); + my_thread_map.unbind( *this, map_mtx ); + my_thread_map.assist_cleanup( connection_traits<Server,Client>::assist_null_only ); + // It is assumed that the client waits for all other threads to terminate before + // calling request_close_connection with true. Thus, it is safe to return all + // outstanding connection objects that are reachable. It is possible that there may + // be some unreachable connection objects lying somewhere. + free_all_connections( connection_scavenger.grab_and_prepend( this ) ); + return; + } +#else /* !RML_USE_WCRM */ +template<typename Server, typename Client> +void generic_connection<Server,Client>::request_close_connection( bool ) { +#endif /* RML_USE_WCRM */ + if( connection_traits<Server,Client>::is_tbb ) { + // acquire the head of active tbb connections + uintptr_t conn; + do { + for( ; (conn=active_tbb_connections)&1; ) + __TBB_Yield(); + } while( active_tbb_connections.compare_and_swap( conn|1, conn )!=conn ); + + // Locate the current connection + generic_connection* pred_conn = NULL; + generic_connection* curr_conn = (generic_connection*) conn; + for( ; curr_conn && curr_conn!=this; curr_conn=curr_conn->next_conn ) + pred_conn = curr_conn; + __TBB_ASSERT( curr_conn==this, "the current connection is not in the list?" ); + + // Remove this from the list + if( pred_conn ) { + pred_conn->next_conn = curr_conn->next_conn; + active_tbb_connections = reinterpret_cast<uintptr_t>(generic_connection<tbb_server,tbb_client>::get_addr(active_tbb_connections)); // release it + } else + active_tbb_connections = (uintptr_t) curr_conn->next_conn; // update & release it + curr_conn->next_conn = NULL; + // Increment the tbb connection close event count + my_ec = ++close_tbb_connection_event_count; + // Wait happens in tbb_connection_v2::~tbb_connection_v2() + } +#if RML_USE_WCRM + my_thread_map.unbind( *this, map_mtx ); + my_thread_map.assist_cleanup( connection_traits<Server,Client>::assist_null_only ); + connection_scavenger.add_request( this ); +#else + my_thread_map.unbind(); + my_thread_map.assist_cleanup( connection_traits<Server,Client>::assist_null_only ); + // Remove extra reference + remove_server_ref(); +#endif +} +#if _MSC_VER && !defined(__INTEL_COMPILER) +#pragma warning( pop ) +#endif + +#if RML_USE_WCRM + +template<typename Server, typename Client> +void generic_connection<Server,Client>::add_virtual_processors( IVirtualProcessorRoot** vproots, unsigned int count ) +{} + +template<> +void generic_connection<tbb_server,tbb_client>::add_virtual_processors( IVirtualProcessorRoot** vproots, unsigned int count ) +{ + my_thread_map.add_virtual_processors( vproots, count, (tbb_connection_v2&)*this, map_mtx ); +} +template<> +void generic_connection<omp_server,omp_client>::add_virtual_processors( IVirtualProcessorRoot** vproots, unsigned int count ) +{ + // For OMP, since it uses ScheudlerPolicy of MinThreads==MaxThreads, this is called once when + // RequestInitialVirtualProcessors() is called. + my_thread_map.add_virtual_processors( vproots, count, (omp_connection_v2&)*this, map_mtx ); +} + +template<typename Server, typename Client> +void generic_connection<Server,Client>::remove_virtual_processors( IVirtualProcessorRoot** vproots, unsigned int count ) +{ + __TBB_ASSERT( false, "should not be called" ); +} +/* For OMP, RemoveVirtualProcessors() will never be called. */ + +template<> +void generic_connection<tbb_server,tbb_client>::remove_virtual_processors( IVirtualProcessorRoot** vproots, unsigned int count ) +{ + my_thread_map.remove_virtual_processors( vproots, count, map_mtx ); +} + +void tbb_connection_v2::adjust_job_count_estimate( int delta ) { +#if TBB_USE_ASSERT + my_job_count_estimate += delta; +#endif /* TBB_USE_ASSERT */ + // Atomically update slack. + int c = my_slack+=delta; + if( c>0 ) { + ++n_adjust_job_count_requests; + my_thread_map.wakeup_tbb_threads( c, map_mtx ); + --n_adjust_job_count_requests; + } +} +#endif /* RML_USE_WCRM */ + +tbb_connection_v2::~tbb_connection_v2() { +#if TBB_USE_ASSERT + if( my_job_count_estimate!=0 ) { + fprintf(stderr, "TBB client tried to disconnect with non-zero net job count estimate of %d\n", int(my_job_count_estimate )); + abort(); + } + __TBB_ASSERT( !my_slack, "attempt to destroy tbb_server with nonzero slack" ); + __TBB_ASSERT( this!=static_cast<tbb_connection_v2*>(generic_connection<tbb_server,tbb_client >::get_addr(active_tbb_connections)), "request_close_connection() must be called" ); +#endif /* TBB_USE_ASSERT */ +#if !RML_USE_WCRM + // If there are other threads ready for work, give them coins + if( the_balance>0 ) + wakeup_some_tbb_threads(); +#endif + // Someone might be accessing my data members + while( current_tbb_conn_readers>0 && (ptrdiff_t)(my_ec-current_tbb_conn_reader_epoch)>0 ) + __TBB_Yield(); +} + +#if !RML_USE_WCRM +template<typename Server, typename Client> +void generic_connection<Server,Client>::make_job( server_thread& t, job_automaton& ja ) { + if( ja.try_acquire() ) { + rml::job& j = *client().create_one_job(); + __TBB_ASSERT( &j!=NULL, "client:::create_one_job returned NULL" ); + __TBB_ASSERT( (intptr_t(&j)&1)==0, "client::create_one_job returned misaligned job" ); + ja.set_and_release( j ); + __TBB_ASSERT( t.my_conn && t.my_ja && t.my_job==NULL, NULL ); + t.my_job = &j; + set_scratch_ptr( j, (void*) &t ); + } +} + +void tbb_connection_v2::adjust_job_count_estimate( int delta ) { +#if TBB_USE_ASSERT + my_job_count_estimate += delta; +#endif /* TBB_USE_ASSERT */ + // Atomically update slack. + int c = my_slack+=delta; + if( c>0 ) { + ++n_adjust_job_count_requests; + // The client has work to do and there are threads available + thread_map::size_type n = my_thread_map.wakeup_tbb_threads(c); + + server_thread* new_threads_anchor = NULL; + thread_map::size_type i; + { + tbb::internal::affinity_helper fpa; + for( i=0; i<n; ++i ) { + // Obtain unrealized threads + thread_map::value_type* k = my_thread_map.add_one_thread( false ); + if( !k ) + // No unrealized threads left. + break; + // Eagerly start the thread off. + fpa.protect_affinity_mask(); + my_thread_map.bind_one_thread( *this, *k ); + server_thread& t = k->thread(); + __TBB_ASSERT( !t.link, NULL ); + t.link = new_threads_anchor; + new_threads_anchor = &t; + } + // Implicit destruction of fpa resets original affinity mask. + } + + thread_map::size_type j=0; + for( ; the_balance>0 && j<i; ++j ) { + if( --the_balance>=0 ) { + // Withdraw a coin from the bank + __TBB_ASSERT( new_threads_anchor, NULL ); + + server_thread* t = new_threads_anchor; + new_threads_anchor = t->link; + while( !t->try_grab_for( ts_tbb_busy ) ) + __TBB_Yield(); + t->my_extra_state = ts_started; + } else { + // Overdraft. return it to the bank + ++the_balance; + break; + } + } + __TBB_ASSERT( i-j!=0||new_threads_anchor==NULL, NULL ); + // Mark the ones that did not get started as eligible for being snatched. + if( new_threads_anchor ) + my_thread_map.release_tbb_threads( new_threads_anchor ); + + --n_adjust_job_count_requests; + } +} +#endif /* RML_USE_WCRM */ + +#if RML_USE_WCRM +int omp_connection_v2::try_increase_load( size_type n, bool strict ) { + __TBB_ASSERT(int(n)>=0,NULL); + if( strict ) { + the_balance -= int(n); + } else { + int avail, old; + do { + avail = the_balance; + if( avail<=0 ) { + // No atomic read-write-modify operation necessary. + return avail; + } + // Don't read the_system_balance; if it changes, compare_and_swap will fail anyway. + old = the_balance.compare_and_swap( int(n)<avail ? avail-n : 0, avail ); + } while( old!=avail ); + if( int(n)>avail ) + n=avail; + } +#if TBB_USE_ASSERT + net_delta += n; +#endif /* TBB_USE_ASSERT */ + return n; +} + +void omp_connection_v2::decrease_load( size_type /*n*/ ) {} + +void omp_connection_v2::get_threads( size_type request_size, void* cookie, job* array[] ) { + unsigned index = 0; + std::vector<omp_server_thread*> enlisted(request_size); + std::vector<thread_grab_t> to_activate(request_size); + + if( request_size==0 ) return; + + { + tbb::spin_mutex::scoped_lock lock(map_mtx); + + __TBB_ASSERT( !is_closing(), "try to get threads while connection is being shutdown?" ); + + for( int scan=0; scan<2; ++scan ) { + for( thread_map::iterator i=my_thread_map.begin(); i!=my_thread_map.end(); ++i ) { + omp_server_thread* thr = (omp_server_thread*) (*i).second; + // in the first scan, skip VPs that are lent + if( scan==0 && thr->is_lent() ) continue; + thread_grab_t res = thr->try_grab_for(); + if( res!=wk_failed ) {// && if is not busy by some other scheduler + to_activate[index] = res; + enlisted[index] = thr; + if( ++index==request_size ) + goto activate_threads; + } + } + } + } + +activate_threads: + + for( unsigned i=0; i<index; ++i ) { + omp_server_thread* thr = enlisted[i]; + if( to_activate[i]==wk_from_asleep ) + thr->get_virtual_processor()->Activate( thr ); + job* j = thr->wait_for_job(); + array[i] = j; + thr->omp_data.produce( client(), *j, cookie, i PRODUCE_ARG(*this) ); + } + + if( index==request_size ) + return; + + // If we come to this point, it must be becuase dynamic==false + // Create Oversubscribers.. + + // Note that our policy is such that MinConcurrency==MaxConcurrency. + // RM will deliver MaxConcurrency of VirtualProcessors and no more. + __TBB_ASSERT( request_size>index, NULL ); + unsigned n = request_size - index; + std::vector<server_thread*> thr_vec(n); + typedef std::vector<server_thread*>::iterator iterator_thr; + my_thread_map.create_oversubscribers( n, thr_vec, *this, map_mtx ); + for( iterator_thr ti=thr_vec.begin(); ti!=thr_vec.end(); ++ti ) { + omp_server_thread* thr = (omp_server_thread*) *ti; + __TBB_ASSERT( thr, "thread not created?" ); + // Thread is already grabbed; since it is nrewly created, we need to activate it. + thr->get_virtual_processor()->Activate( thr ); + job* j = thr->wait_for_job(); + array[index] = j; + thr->omp_data.produce( client(), *j, cookie, index PRODUCE_ARG(*this) ); + ++index; + } +} + +#if _WIN32||_WIN64 +void omp_connection_v2::deactivate( rml::job* j ) +{ + my_thread_map.adjust_balance(1); +#if TBB_USE_ASSERT + net_delta -= 1; +#endif + omp_server_thread* thr = (omp_server_thread*) scratch_ptr( *j ); + (thr->get_virtual_processor())->Deactivate( thr ); +} + +void omp_connection_v2::reactivate( rml::job* j ) +{ + // Should not adjust the_balance because OMP client is supposed to + // do try_increase_load() to reserve the threads to use. + omp_server_thread* thr = (omp_server_thread*) scratch_ptr( *j ); + (thr->get_virtual_processor())->Activate( thr ); +} +#endif /* !_WIN32||_WIN64 */ + +#endif /* RML_USE_WCRM */ + +//! Wake up some available tbb threads +void wakeup_some_tbb_threads() +{ + /* First, atomically grab the connection, then increase the server ref count to keep + it from being released prematurely. Second, check if the balance is available for TBB + and the tbb conneciton has slack to exploit. If the answer is true, go ahead and + try to wake some up. */ + if( generic_connection<tbb_server,tbb_client >::get_addr(active_tbb_connections)==0 ) + // the next connection will see the change; return. + return; + +start_it_over: + int n_curr_readers = ++current_tbb_conn_readers; + if( n_curr_readers>1 ) // I lost + return; + // if n_curr_readers==1, i am the first one, so I will take responsibility for waking tbb threads up. + + // update the current epoch + current_tbb_conn_reader_epoch = close_tbb_connection_event_count; + + // read and clear + // Newly added connection will not invalidate the pointer, and it will + // compete with the current one to claim coins. + // One that is about to close the connection increments the event count + // after it removes the connection from the list. But it will keep around + // the connection until all readers including this one catch up. So, reading + // the head and clearing the lock bit should be o.k. + generic_connection<tbb_server,tbb_client>* next_conn_wake_up = generic_connection<tbb_server,tbb_client>::get_addr( active_tbb_connections ); + + for( ; next_conn_wake_up; ) { + /* some threads are creating tbb server threads; they may not see my changes made to the_balance */ + /* When a thread is in adjust_job_count_estimate() to increase the slack + RML tries to activate worker threads on behalf of the requesting thread + by repeatedly drawing a coin from the bank optimistically and grabbing a + thread. If it finds the bank overdrafted, it returns the coin back to + the bank and returns the control to the thread (return from the method). + There lies a tiny timing hole. + + When the overdraft occurs (note that multiple masters may be in + adjust_job_count_estimate() so the_balance can be any negative value) and + a worker returns from the TBB work at that moment, its returning the coin + does not bump up the_balance over 0, so it happily returns from + wakeup_some_tbb_threads() without attempting to give coins to worker threads + that are ready. + */ + while( ((tbb_connection_v2*)next_conn_wake_up)->n_adjust_job_count_requests>0 ) + __TBB_Yield(); + + int bal = the_balance; + n_curr_readers = current_tbb_conn_readers; // get the snapshot + if( bal<=0 ) break; + // if the connection is deleted, the following will immediately return because its slack would be 0 or less. + + tbb_connection_v2* tbb_conn = (tbb_connection_v2*)next_conn_wake_up; + int my_slack = tbb_conn->my_slack; + if( my_slack>0 ) tbb_conn->wakeup_tbb_threads( my_slack ); + next_conn_wake_up = next_conn_wake_up->next_conn; + } + + int delta = current_tbb_conn_readers -= n_curr_readers; + //if delta>0, more threads entered the routine since this one took the snapshot + if( delta>0 ) { + current_tbb_conn_readers = 0; + if( the_balance>0 && generic_connection<tbb_server,tbb_client >::get_addr(active_tbb_connections)!=0 ) + goto start_it_over; + } + + // Signal any connection that is waiting for me to complete my access that I am done. + current_tbb_conn_reader_epoch = close_tbb_connection_event_count; +} + +#if !RML_USE_WCRM +int omp_connection_v2::try_increase_load( size_type n, bool strict ) { + __TBB_ASSERT(int(n)>=0,NULL); + if( strict ) { + the_balance -= int(n); + } else { + int avail, old; + do { + avail = the_balance; + if( avail<=0 ) { + // No atomic read-write-modify operation necessary. + return avail; + } + // don't read the_balance; if it changes, compare_and_swap will fail anyway. + old = the_balance.compare_and_swap( int(n)<avail ? avail-n : 0, avail ); + } while( old!=avail ); + if( int(n)>avail ) + n=avail; + } +#if TBB_USE_ASSERT + net_delta += n; +#endif /* TBB_USE_ASSERT */ + return n; +} + +void omp_connection_v2::decrease_load( size_type n ) { + __TBB_ASSERT(int(n)>=0,NULL); + my_thread_map.adjust_balance(int(n)); +#if TBB_USE_ASSERT + net_delta -= n; +#endif /* TBB_USE_ASSERT */ +} + +void omp_connection_v2::get_threads( size_type request_size, void* cookie, job* array[] ) { + + if( !request_size ) + return; + + unsigned index = 0; + for(;;) { // don't return until all request_size threads are grabbed. + // Need to grab some threads + thread_map::iterator k_end=my_thread_map.end(); + for( thread_map::iterator k=my_thread_map.begin(); k!=k_end; ++k ) { + // If another thread added *k, there is a tiny timing window where thread() is invalid. + server_thread& t = k->wait_for_thread(); + if( t.try_grab_for( ts_omp_busy ) ) { + // The preincrement instead of post-increment of index is deliberate. + job& j = k->wait_for_job(); + array[index] = &j; + t.omp_dispatch.produce( client(), j, cookie, index PRODUCE_ARG(*this) ); + if( ++index==request_size ) + return; + } + } + // Need to allocate more threads + for( unsigned i=index; i<request_size; ++i ) { + __TBB_ASSERT( index<request_size, NULL ); + thread_map::value_type* k = my_thread_map.add_one_thread( true ); +#if TBB_USE_ASSERT + if( !k ) { + // Client erred + __TBB_ASSERT(false, "server::get_threads: exceeded job_count\n"); + } +#endif + my_thread_map.bind_one_thread( *this, *k ); + server_thread& t = k->thread(); + if( t.try_grab_for( ts_omp_busy ) ) { + job& j = k->wait_for_job(); + array[index] = &j; + // The preincrement instead of post-increment of index is deliberate. + t.omp_dispatch.produce( client(), j, cookie, index PRODUCE_ARG(*this) ); + if( ++index==request_size ) + return; + } // else someone else snatched it. + } + } +} +#endif /* !RML_USE_WCRM */ + +//------------------------------------------------------------------------ +// Methods of omp_dispatch_type +//------------------------------------------------------------------------ +void omp_dispatch_type::consume() { + // Wait for short window between when master sets state of this thread to ts_omp_busy + // and master thread calls produce. + job_type* j = job; + if( !j ) { + tbb::internal::atomic_backoff bo; + do { + bo.pause(); + j = job; + } while( !j ); + } + job = static_cast<job_type*>(NULL); + client->process(*j,cookie,index); +#if TBB_USE_ASSERT + // Return of method process implies "decrease_load" from client's viewpoint, even though + // the actual adjustment of the_balance only happens when this thread really goes to sleep. + --server->net_delta; +#endif /* TBB_USE_ASSERT */ +} + +#if !RML_USE_WCRM +#if _WIN32||_WIN64 +void omp_connection_v2::deactivate( rml::job* j ) +{ +#if TBB_USE_ASSERT + net_delta -= 1; +#endif + __TBB_ASSERT( j, NULL ); + server_thread* thr = (server_thread*) scratch_ptr( *j ); + thr->deactivate(); +} + +void omp_connection_v2::reactivate( rml::job* j ) +{ + // Should not adjust the_balance because OMP client is supposed to + // do try_increase_load() to reserve the threads to use. + __TBB_ASSERT( j, NULL ); + server_thread* thr = (server_thread*) scratch_ptr( *j ); + thr->reactivate(); +} +#endif /* _WIN32||_WIN64 */ + +//------------------------------------------------------------------------ +// Methods of server_thread +//------------------------------------------------------------------------ + +server_thread::server_thread() : + ref_count(0), + link(NULL), + my_map_pos(), + my_conn(NULL), my_job(NULL), my_ja(NULL) +{ + state = ts_idle; + terminate = false; +#if TBB_USE_ASSERT + has_active_thread = false; +#endif /* TBB_USE_ASSERT */ +} + +server_thread::~server_thread() { + __TBB_ASSERT( !has_active_thread, NULL ); +} + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // Suppress overzealous compiler warnings about an initialized variable 'sink_for_alloca' not referenced + #pragma warning(push) + #pragma warning(disable:4189) +#endif +__RML_DECL_THREAD_ROUTINE server_thread::thread_routine( void* arg ) { + server_thread* self = static_cast<server_thread*>(arg); + AVOID_64K_ALIASING( self->my_index ); +#if TBB_USE_ASSERT + __TBB_ASSERT( !self->has_active_thread, NULL ); + self->has_active_thread = true; +#endif /* TBB_USE_ASSERT */ + self->loop(); + return 0; +} +#if _MSC_VER && !defined(__INTEL_COMPILER) + #pragma warning(pop) +#endif + +void server_thread::launch( size_t stack_size ) { +#if USE_WINTHREAD + thread_monitor::launch( thread_routine, this, stack_size, &this->my_index ); +#else + thread_monitor::launch( thread_routine, this, stack_size ); +#endif /* USE_PTHREAD */ +} + +void server_thread::sleep_perhaps( thread_state_t asleep ) { + if( terminate ) return; + __TBB_ASSERT( asleep==ts_asleep, NULL ); + thread_monitor::cookie c; + monitor.prepare_wait(c); + if( state.compare_and_swap( asleep, ts_idle )==ts_idle ) { + if( !terminate ) { + monitor.commit_wait(c); + // Someone else woke me up. The compare_and_swap further below deals with spurious wakeups. + } else { + monitor.cancel_wait(); + } + thread_state_t s = read_state(); + if( s==ts_asleep ) { + state.compare_and_swap( ts_idle, ts_asleep ); + // I woke myself up, either because I cancelled the wait or suffered a spurious wakeup. + } else { + // Someone else woke me up; there the_balance is decremented by 1. -- tbb only + if( !is_omp_thread ) { + __TBB_ASSERT( s==ts_tbb_busy||s==ts_idle, NULL ); + } + } + } else { + // someone else made it busy ; see try_grab_for when state==ts_idle. + __TBB_ASSERT( state==ts_omp_busy||state==ts_tbb_busy, NULL ); + monitor.cancel_wait(); + } + __TBB_ASSERT( read_state()!=asleep, "a thread can only put itself to sleep" ); +} + +bool server_thread::wakeup( thread_state_t to, thread_state_t from ) { + bool success = false; + __TBB_ASSERT( from==ts_asleep && (to==ts_idle||to==ts_omp_busy||to==ts_tbb_busy), NULL ); + if( state.compare_and_swap( to, from )==from ) { + if( !is_omp_thread ) __TBB_ASSERT( to==ts_idle||to==ts_tbb_busy, NULL ); + // There is a small timing window that permits balance to become negative, + // but such occurrences are probably rare enough to not worry about, since + // at worst the result is slight temporary oversubscription. + monitor.notify(); + success = true; + } + return success; +} + +//! Attempt to change a thread's state to ts_omp_busy, and waking it up if necessary. +bool server_thread::try_grab_for( thread_state_t target_state ) { + bool success = false; + switch( read_state() ) { + case ts_asleep: + success = wakeup( target_state, ts_asleep ); + break; + case ts_idle: + success = state.compare_and_swap( target_state, ts_idle )==ts_idle; + break; + default: + // Thread is not available to be part of an OpenMP thread team. + break; + } + return success; +} + +#if _WIN32||_WIN64 +void server_thread::deactivate() { + thread_state_t es = (thread_state_t) my_extra_state.fetch_and_store( ts_deactivated ); + __TBB_ASSERT( my_extra_state==ts_deactivated, "someone else tampered with my_extra_state?" ); + if( es==ts_none ) + state = ts_idle; + else + __TBB_ASSERT( es==ts_reactivated, "Cannot call deactivate() while in ts_deactivated" ); + // only the thread can transition itself from ts_deactivted to ts_none + __TBB_ASSERT( my_extra_state==ts_deactivated, "someone else tampered with my_extra_state?" ); + my_extra_state = ts_none; // release the critical section + int bal = ++the_balance; + if( bal>0 ) + wakeup_some_tbb_threads(); + if( es==ts_none ) + sleep_perhaps( ts_asleep ); +} + +void server_thread::reactivate() { + thread_state_t es; + do { + while( (es=read_extra_state())==ts_deactivated ) + __TBB_Yield(); + if( es==ts_reactivated ) { + __TBB_ASSERT( false, "two Reactivate() calls in a row. Should not happen" ); + return; + } + __TBB_ASSERT( es==ts_none, NULL ); + } while( (thread_state_t)my_extra_state.compare_and_swap( ts_reactivated, ts_none )!=ts_none ); + if( state!=ts_omp_busy ) { + my_extra_state = ts_none; + while( !try_grab_for( ts_omp_busy ) ) + __TBB_Yield(); + } +} +#endif /* _WIN32||_WIN64 */ + + +template<typename Connection> +bool server_thread::destroy_job( Connection& c ) { + __TBB_ASSERT( !is_omp_thread||(state==ts_idle||state==ts_omp_busy), NULL ); + __TBB_ASSERT( is_omp_thread||(state==ts_idle||state==ts_tbb_busy), NULL ); + if( !is_omp_thread ) { + __TBB_ASSERT( state==ts_idle||state==ts_tbb_busy, NULL ); + if( state==ts_idle ) + state.compare_and_swap( ts_done, ts_idle ); + // 'state' may be set to ts_tbb_busy by another thread. + + if( state==ts_tbb_busy ) { // return the coin to the deposit + // need to deposit first to let the next connection see the change + ++the_balance; + state = ts_done; // no other thread changes the state when it is ts_*_busy + } + } + if( job_automaton* ja = my_ja ) { + rml::job* j; + if( ja->try_plug(j) ) { + __TBB_ASSERT( j, NULL ); + c.client().cleanup(*j); + c.remove_client_ref(); + } else { + // Some other thread took responsibility for cleaning up the job. + } + } + // Must do remove client reference first, because execution of + // c.remove_ref() can cause *this to be destroyed. + int k = remove_ref(); + __TBB_ASSERT_EX( k==0, "more than one references?" ); +#if TBB_USE_ASSERT + has_active_thread = false; +#endif /* TBB_USE_ASSERT */ + c.remove_server_ref(); + return true; +} + +bool server_thread::do_termination() { + if( is_omp_thread ) + return destroy_job( *static_cast<omp_connection_v2*>(my_conn) ); + else + return destroy_job( *static_cast<tbb_connection_v2*>(my_conn) ); +} + +//! Loop that each thread executes +void server_thread::loop() { + if( is_omp_thread ) + static_cast<omp_connection_v2*>(my_conn)->make_job( *this, *my_ja ); + else + static_cast<tbb_connection_v2*>(my_conn)->make_job( *this, *my_ja ); + for(;;) { + __TBB_Yield(); + if( state==ts_idle ) + sleep_perhaps( ts_asleep ); + + // Check whether I should quit. + if( terminate ) + if( do_termination() ) + return; + + // read the state + thread_state_t s = read_state(); + __TBB_ASSERT( s==ts_idle||s==ts_omp_busy||s==ts_tbb_busy, NULL ); + + if( s==ts_omp_busy ) { + // Enslaved by OpenMP team. + omp_dispatch.consume(); + /* here wake tbb threads up if feasible */ + if( ++the_balance>0 ) + wakeup_some_tbb_threads(); + state = ts_idle; + } else if( s==ts_tbb_busy ) { + // do some TBB work. + __TBB_ASSERT( my_conn && my_job, NULL ); + tbb_connection_v2& conn = *static_cast<tbb_connection_v2*>(my_conn); + // give openmp higher priority + bool has_coin = true; + if( conn.has_slack() ) { + // it has the coin, it should trip to the scheduler at least once as long as its slack is positive + do { + if( conn.try_process( *this, *my_job ) ) + if( conn.has_slack() && the_balance>=0 ) + has_coin = !conn.wakeup_next_thread( my_map_pos ); + } while( has_coin && conn.has_slack() && the_balance>=0 ); + } + state = ts_idle; + if( has_coin ) { + ++the_balance; // return the coin back to the deposit + if( conn.has_slack() ) { // a new adjust_job_request_estimate() is in progress + // it may have missed my changes to state and/or the_balance + if( --the_balance>=0 ) { // try to grab the coin back + // I got the coin + if( state.compare_and_swap( ts_tbb_busy, ts_idle )!=ts_idle ) + ++the_balance; // someone else enlisted me. + } else { + // overdraft. return the coin + ++the_balance; + } + } // else the new request will see my changes to state & the_balance. + } + /* here wake tbb threads up if feasible */ + if( the_balance>0 ) + wakeup_some_tbb_threads(); + } + } +} +#endif /* !RML_USE_WCRM */ + +#if RML_USE_WCRM + +class tbb_connection_v2; +class omp_connection_v2; + +#define CREATE_SCHEDULER_POLICY(policy,min_thrs,max_thrs,stack_size) \ + try { \ + policy = new SchedulerPolicy (7, \ + SchedulerKind, RML_THREAD_KIND, /*defined in _rml_serer_msrt.h*/ \ + MinConcurrency, min_thrs, \ + MaxConcurrency, max_thrs, \ + TargetOversubscriptionFactor, 1, \ + ContextStackSize, stack_size/1000, /*ConcRT:kB, iRML:bytes*/ \ + ContextPriority, THREAD_PRIORITY_NORMAL, \ + DynamicProgressFeedback, ProgressFeedbackDisabled ); \ + } catch ( invalid_scheduler_policy_key & ) { \ + __TBB_ASSERT( false, "invalid scheduler policy key exception caught" );\ + } catch ( invalid_scheduler_policy_value & ) { \ + __TBB_ASSERT( false, "invalid scheduler policy value exception caught" );\ + } + +static unsigned int core_count; +static tbb::atomic<int> core_count_inited; + + +static unsigned int get_processor_count() +{ + if( core_count_inited!=2 ) { + if( core_count_inited.compare_and_swap( 1, 0 )==0 ) { + core_count = GetProcessorCount(); + core_count_inited = 2; + } else { + tbb::internal::spin_wait_until_eq( core_count_inited, 2 ); + } + } + return core_count; +} + +template<typename Connection> +scheduler<Connection>::scheduler( Connection& conn ) : uid(GetSchedulerId()), my_conn(conn) {} + +template<> +scheduler<tbb_connection_v2>::scheduler( tbb_connection_v2& conn ) : uid(GetSchedulerId()), my_conn(conn) +{ + rml::client& cl = my_conn.client(); + unsigned max_job_count = cl.max_job_count(); + unsigned count = get_processor_count(); + __TBB_ASSERT( max_job_count>0, "max job count must be positive" ); + __TBB_ASSERT( count>1, "The processor count must be greater than 1" ); + if( max_job_count>count-1) max_job_count = count-1; + CREATE_SCHEDULER_POLICY( my_policy, 0, max_job_count, cl.min_stack_size() ); +} + +#if __RML_REMOVE_VIRTUAL_PROCESSORS_DISABLED +template<> +void scheduler<tbb_connection_v2>::RemoveVirtualProcessors( IVirtualProcessorRoot**, unsigned int) +{ +} +#else +template<> +void scheduler<tbb_connection_v2>::RemoveVirtualProcessors( IVirtualProcessorRoot** vproots, unsigned int count ) +{ + if( !my_conn.is_closing() ) + my_conn.remove_virtual_processors( vproots, count ); +} +#endif + +template<> +void scheduler<tbb_connection_v2>::NotifyResourcesExternallyIdle( IVirtualProcessorRoot** /*vproots*/, unsigned int /*count*/) +{ + __TBB_ASSERT( false, "NotifyResourcesExternallyIdle() is not allowed for TBB" ); +} + +template<> +void scheduler<tbb_connection_v2>::NotifyResourcesExternallyBusy( IVirtualProcessorRoot** /*vproots*/, unsigned int /*count*/ ) +{ + __TBB_ASSERT( false, "NotifyResourcesExternallyBusy() is not allowed for TBB" ); +} + +template<> +scheduler<omp_connection_v2>::scheduler( omp_connection_v2& conn ) : uid(GetSchedulerId()), my_conn(conn) +{ + unsigned count = get_processor_count(); + rml::client& cl = my_conn.client(); + __TBB_ASSERT( count>1, "The processor count must be greater than 1" ); + CREATE_SCHEDULER_POLICY( my_policy, count-1, count-1, cl.min_stack_size() ); +} + +template<> +void scheduler<omp_connection_v2>::RemoveVirtualProcessors( IVirtualProcessorRoot** /*vproots*/, unsigned int /*count*/ ) { + __TBB_ASSERT( false, "RemoveVirtualProcessors() is not allowed for OMP" ); +} + +template<> +void scheduler<omp_connection_v2>::NotifyResourcesExternallyIdle( IVirtualProcessorRoot** vproots, unsigned int count ){ + if( !my_conn.is_closing() ) + my_conn.notify_resources_externally_idle( vproots, count ); +} + +template<> +void scheduler<omp_connection_v2>::NotifyResourcesExternallyBusy( IVirtualProcessorRoot** vproots, unsigned int count ){ + if( !my_conn.is_closing() ) + my_conn.notify_resources_externally_busy( vproots, count ); +} + +/* ts_idle, ts_asleep, ts_busy */ +void tbb_server_thread::Dispatch( DispatchState* ) { + // Activate() will resume a thread right after Deactivate() as if it returns from the call + tbb_connection_v2* tbb_conn = static_cast<tbb_connection_v2*>(my_conn); + make_job( *tbb_conn, *this ); + + for( ;; ) { + // Try to wake some tbb threads if the balance is positive. + // When a thread is added by ConcRT and enter here for the first time, + // the thread may wake itself up (i.e., atomically change its state to ts_busy. + if( the_balance>0 ) + wakeup_some_tbb_threads(); + if( read_state()!=ts_busy ) + if( sleep_perhaps() ) + return; + if( terminate ) + if( initiate_termination() ) + return; + if( read_state()==ts_busy ) { + // this thread has a coin (i.e., state=ts_busy; it should trip to the scheduler at least once + if ( tbb_conn->has_slack() ) { + do { + tbb_conn->try_process( *wait_for_job() ); + } while( tbb_conn->has_slack() && the_balance>=0 && !is_removed() ); + } + __TBB_ASSERT( read_state()==ts_busy, "thread is not in busy state after returning from process()" ); + // see remove_virtual_processors() + if( my_state.compare_and_swap( ts_idle, ts_busy )==ts_busy ) { + int bal = ++the_balance; + if( tbb_conn->has_slack() ) { + // slack is positive, volunteer to help + bal = --the_balance; // try to grab the coin back + if( bal>=0 ) { // got the coin back + if( my_state.compare_and_swap( ts_busy, ts_idle )!=ts_idle ) + ++the_balance; // someone else enlisted me. + // else my_state is ts_busy, I will come back to tbb_conn->try_process(). + } else { + // overdraft. return the coin + ++the_balance; + } + } // else the new request will see my changes to state & the_balance. + } else { + __TBB_ASSERT( false, "someone tampered with my state" ); + } + } // someone else might set the state to somthing other than ts_idle + } +} + +void omp_server_thread::Dispatch( DispatchState* ) { + // Activate() will resume a thread right after Deactivate() as if it returns from the call + make_job( *static_cast<omp_connection_v2*>(my_conn), *this ); + + for( ;; ) { + if( read_state()!=ts_busy ) + sleep_perhaps(); + if( terminate ) { + if( initiate_termination() ) + return; + } + if( read_state()==ts_busy ) { + omp_data.consume(); + __TBB_ASSERT( read_state()==ts_busy, "thread is not in busy state after returning from process()" ); + my_thread_map.adjust_balance( 1 ); + set_state( ts_idle ); + } + // someone else might set the state to somthing other than ts_idle + } +} + +//! Attempt to change a thread's state to ts_omp_busy, and waking it up if necessary. +thread_grab_t server_thread_rep::try_grab_for() { + thread_grab_t res = wk_failed; + thread_state_t s = read_state(); + switch( s ) { + case ts_asleep: + if( wakeup( ts_busy, ts_asleep ) ) + res = wk_from_asleep; + __TBB_ASSERT( res==wk_failed||read_state()==ts_busy, NULL ); + break; + case ts_idle: + if( my_state.compare_and_swap( ts_busy, ts_idle )==ts_idle ) + res = wk_from_idle; + // At this point a thread is grabbed (i.e., its state has changed to ts_busy. + // It is possible that the thread 1) processes the job, returns from process() and + // sets its state ts_idle again. In some cases, it even sets its state to ts_asleep. + break; + default: + break; + } + return res; +} + +bool tbb_server_thread::switch_out() { + thread_state_t s = read_state(); + __TBB_ASSERT( s==ts_asleep||s==ts_busy, NULL ); + // This thread comes back from the TBB scheduler, and changed its state to ts_asleep successfully. + // The master enlisted it and woke it up by Activate()'ing it; now it is emerging from Deactivated(). + // ConcRT requested for removal of the vp associated with the thread, and RML marks it removed. + // Now, it has ts_busy, and removed. -- we should remove it. + IExecutionResource* old_vp = my_execution_resource; + if( s==ts_busy ) { + ++the_balance; + my_state = ts_asleep; + } + IThreadProxy* proxy = my_proxy; + __TBB_ASSERT( proxy, NULL ); + my_execution_resource = (IExecutionResource*) c_remove_prepare; + old_vp->Remove( my_scheduler ); + my_execution_resource = (IExecutionResource*) c_remove_returned; + int cnt = --activation_count; + __TBB_ASSERT_EX( cnt==0||cnt==1, "too many activations?" ); + proxy->SwitchOut(); + if( terminate ) { + bool activated = activation_count==1; +#if TBB_USE_ASSERT + /* In a rare sequence of events, a thread comes out of SwitchOut with activation_count==1. + * 1) The thread is SwitchOut'ed. + * 2) AddVirtualProcessors() arrived and the thread is Activated. + * 3) The thread is coming out of SwitchOut(). + * 4) request_close_connection arrives and inform the thread that it is time to terminate. + * 5) The thread hits the check and falls into the path with 'activated==true'. + * In that case, do the clean-up but do not switch to the thread scavenger; rather simply return to RM. + */ + if( activated ) { + // thread is 'revived' in add_virtual_processors after being Activated(). + // so, if the thread extra state is still marked 'removed', it will shortly change to 'none' + // i.e., !is_remove(). The thread state is changed to ts_idle before the extra state, so + // the thread's state should be either ts_idle or ts_done. + while( is_removed() ) + __TBB_Yield(); + thread_state_t s = read_state(); + __TBB_ASSERT( s==ts_idle || s==ts_done, NULL ); + } +#endif + __TBB_ASSERT( my_state==ts_asleep||my_state==ts_idle, NULL ); + // it is possible that in make_job() the thread may not have a chance to create a job. + // my_job may not be set if the thread did not get a chance to process client's job (i.e., call try_process()) + rml::job* j; + if( my_job_automaton.try_plug(j) ) { + __TBB_ASSERT( j, NULL ); + my_client.cleanup(*j); + my_conn->remove_client_ref(); + } + // Must do remove client reference first, because execution of + // c.remove_ref() can cause *this to be destroyed. + if( !activated ) + proxy->SwitchTo( my_thread_map.get_thread_scavenger(), Idle ); + my_conn->remove_server_ref(); + return true; + } + // We revive a thread in add_virtual_processors() after we Activate the thread on a new virtual processor. + // So briefly wait until the thread's my_execution_resource gets set. + while( get_virtual_processor()==c_remove_returned ) + __TBB_Yield(); + return false; +} + +bool tbb_server_thread::sleep_perhaps () { + if( terminate ) return false; + thread_state_t s = read_state(); + if( s==ts_idle ) { + if( my_state.compare_and_swap( ts_asleep, ts_idle )==ts_idle ) { + // If a thread is between read_state() and compare_and_swap(), and the master tries to terminate, + // the master's compare_and_swap() will fail because the thread's state is ts_idle. + // We need to check if terminate is true or not before letting the thread go to sleep oetherwise + // we will miss the terminate signal. + if( !terminate ) { + if( !is_removed() ) { + --activation_count; + get_virtual_processor()->Deactivate( this ); + } + if( is_removed() ) { + if( switch_out() ) + return true; + __TBB_ASSERT( my_execution_resource>c_remove_returned, NULL ); + } + // in add_virtual_processors(), when we revive a thread, we change its state after Activate the thread + // in that case the state may be ts_asleep for a short period + while( read_state()==ts_asleep ) + __TBB_Yield(); + } else { + if( my_state.compare_and_swap( ts_done, ts_asleep )!=ts_asleep ) { + --activation_count; + // unbind() changed my state. It will call Activate(). So issue a matching Deactivate() + get_virtual_processor()->Deactivate( this ); + } + } + } + } else { + __TBB_ASSERT( s==ts_busy, NULL ); + } + return false; +} + +void omp_server_thread::sleep_perhaps () { + if( terminate ) return; + thread_state_t s = read_state(); + if( s==ts_idle ) { + if( my_state.compare_and_swap( ts_asleep, ts_idle )==ts_idle ) { + // If a thread is between read_state() and compare_and_swap(), and the master tries to terminate, + // the master's compare_and_swap() will fail because the thread's state is ts_idle. + // We need to check if terminate is true or not before letting the thread go to sleep oetherwise + // we will miss the terminate signal. + if( !terminate ) { + get_virtual_processor()->Deactivate( this ); + __TBB_ASSERT( !is_removed(), "OMP threads should not be deprived of a virtual processor" ); + __TBB_ASSERT( read_state()!=ts_asleep, NULL ); + } else { + if( my_state.compare_and_swap( ts_done, ts_asleep )!=ts_asleep ) + // unbind() changed my state. It will call Activate(). So issue a matching Deactivate() + get_virtual_processor()->Deactivate( this ); + } + } + } else { + __TBB_ASSERT( s==ts_busy, NULL ); + } +} + +bool tbb_server_thread::initiate_termination() { + if( read_state()==ts_busy ) { + int bal = ++the_balance; + if( bal>0 ) wakeup_some_tbb_threads(); + } + return destroy_job( (tbb_connection_v2*) my_conn ); +} + +template<typename Connection> +bool server_thread_rep::destroy_job( Connection* c ) { + __TBB_ASSERT( my_state!=ts_asleep, NULL ); + rml::job* j; + if( my_job_automaton.try_plug(j) ) { + __TBB_ASSERT( j, NULL ); + my_client.cleanup(*j); + c->remove_client_ref(); + } + // Must do remove client reference first, because execution of + // c.remove_ref() can cause *this to be destroyed. + c->remove_server_ref(); + return true; +} + +void thread_map::assist_cleanup( bool assist_null_only ) { + // To avoid deadlock, the current thread *must* help out with cleanups that have not started, + // becausd the thread that created the job may be busy for a long time. + for( iterator i = begin(); i!=end(); ++i ) { + rml::job* j=0; + server_thread* thr = (*i).second; + job_automaton& ja = thr->my_job_automaton; + if( assist_null_only ? ja.try_plug_null() : ja.try_plug(j) ) { + if( j ) { + my_client.cleanup(*j); + } else { + // server thread did not get a chance to create a job. + } + remove_client_ref(); + } + } +} + +void thread_map::add_virtual_processors( IVirtualProcessorRoot** vproots, unsigned int count, tbb_connection_v2& conn, ::tbb::spin_mutex& mtx ) +{ +#if TBB_USE_ASSERT + int req_cnt = ++n_add_vp_requests; + __TBB_ASSERT( req_cnt==1, NULL ); +#endif + std::vector<thread_map::iterator> vec(count); + std::vector<tbb_server_thread*> tvec(count); + iterator end; + + { + tbb::spin_mutex::scoped_lock lck( mtx ); + __TBB_ASSERT( my_map.size()==0||count==1, NULL ); + end = my_map.end(); //remember 'end' at the time of 'find' + // find entries in the map for those VPs that were previosly added and then removed. + for( size_t i=0; i<count; ++i ) { + vec[i] = my_map.find( (key_type) vproots[i] ); +#if TBB_USE_DEBUG + if( vec[i]!=end ) { + tbb_server_thread* t = (tbb_server_thread*) (*vec[i]).second; + IVirtualProcessorRoot* v = t->get_virtual_processor(); + __TBB_ASSERT( v==c_remove_prepare||v==c_remove_returned, NULL ); + } +#endif + } + + iterator nxt = my_map.begin(); + for( size_t i=0; i<count; ++i ) { + if( vec[i]!=end ) { +#if TBB_USE_ASSERT + tbb_server_thread* t = (tbb_server_thread*) (*vec[i]).second; + __TBB_ASSERT( t->read_state()==ts_asleep, NULL ); + IVirtualProcessorRoot* r = t->get_virtual_processor(); + __TBB_ASSERT( r==c_remove_prepare||r==c_remove_returned, NULL ); +#endif + continue; + } + + if( my_unrealized_threads>0 ) { + --my_unrealized_threads; + } else { + __TBB_ASSERT( nxt!=end, "nxt should not be thread_map::iterator::end" ); + // find a removed thread context for i + for( ; nxt!=end; ++nxt ) { + tbb_server_thread* t = (tbb_server_thread*) (*nxt).second; + if( t->is_removed() && t->read_state()==ts_asleep && t->get_virtual_processor()==c_remove_returned ) { + vec[i] = nxt++; + break; + } + } + // break target + if( vec[i]==end ) // ignore excessive VP. + vproots[i] = NULL; + } + } + } + + for( size_t i=0; i<count; ++i ) { + __TBB_ASSERT( !tvec[i], NULL ); + if( vec[i]==end ) { + if( vproots[i] ) { + tvec[i] = my_tbb_allocator.allocate(1); + new ( tvec[i] ) tbb_server_thread( false, my_scheduler, (IExecutionResource*)vproots[i], &conn, *this, my_client ); + } +#if TBB_USE_ASSERT + } else { + tbb_server_thread* t = (tbb_server_thread*) (*vec[i]).second; + __TBB_ASSERT( t->GetProxy(), "Proxy is cleared?" ); +#endif + } + } + + { + tbb::spin_mutex::scoped_lock lck( mtx ); + + bool closing = is_closing(); + + for( size_t i=0; i<count; ++i ) { + if( vec[i]==end ) { + if( vproots[i] ) { + thread_map::key_type key = (thread_map::key_type) vproots[i]; + vec[i] = insert( key, (server_thread*) tvec[i] ); + my_client_ref_count.add_ref(); + my_server_ref_count.add_ref(); + } + } else if( !closing ) { + tbb_server_thread* t = (tbb_server_thread*) (*vec[i]).second; + + if( (*vec[i]).first!=(thread_map::key_type)vproots[i] ) { + my_map.erase( vec[i] ); + thread_map::key_type key = (thread_map::key_type) vproots[i]; + __TBB_ASSERT( key, NULL ); + vec[i] = insert( key, t ); + } + __TBB_ASSERT( t->read_state()==ts_asleep, NULL ); + // We did not decrement server/client ref count when a thread is removed. + // So, don't increment server/client ref count here. + } + } + + // we could check is_closing() earlier. That requires marking the newly allocated server_thread objects + // that are not inserted into the thread_map, and deallocate them. Doing so seems more cumbersome + // than simply adding these to the thread_map and let thread_map's destructor take care of reclamation. + __TBB_ASSERT( closing==is_closing(), NULL ); + if( closing ) return; + } + + for( size_t i=0; i<count; ++i ) { + if( vproots[i] ) { + tbb_server_thread* t = (tbb_server_thread*) (*vec[i]).second; + __TBB_ASSERT( tvec[i]!=NULL||t->GetProxy(), "Proxy is cleared?" ); + if( t->is_removed() ) + __TBB_ASSERT( t->get_virtual_processor()==c_remove_returned, NULL ); + int cnt = ++t->activation_count; + __TBB_ASSERT_EX( cnt==0||cnt==1, NULL ); + vproots[i]->Activate( t ); + if( t->is_removed() ) + t->revive( my_scheduler, vproots[i], my_client ); + } + } +#if TBB_USE_ASSERT + req_cnt = --n_add_vp_requests; + __TBB_ASSERT( req_cnt==0, NULL ); +#endif +} + +void thread_map::remove_virtual_processors( IVirtualProcessorRoot** vproots, unsigned count, ::tbb::spin_mutex& mtx ) { + if( my_map.size()==0 ) + return; + tbb::spin_mutex::scoped_lock lck( mtx ); + + if( is_closing() ) return; + + for( unsigned int c=0; c<count; ++c ) { + iterator i = my_map.find( (key_type) vproots[c] ); + if( i==my_map.end() ) { + thread_scavenger_thread* tst = my_thread_scavenger_thread; + if( !tst ) { + // Remove unknown vp from my scheduler; + vproots[c]->Remove( my_scheduler ); + } else { + while( (tst=my_thread_scavenger_thread)==c_claimed ) + __TBB_Yield(); + if( vproots[c]!=tst->get_virtual_processor() ) + vproots[c]->Remove( my_scheduler ); + } + continue; + } + tbb_server_thread* thr = (tbb_server_thread*) (*i).second; + __TBB_ASSERT( thr->tbb_thread, "incorrect type of server_thread" ); + thr->set_removed(); + if( thr->read_state()==ts_asleep ) { + while( thr->activation_count>0 ) { + if( thr->get_virtual_processor()<=c_remove_returned ) + break; + __TBB_Yield(); + } + if( thr->get_virtual_processor()>c_remove_returned ) { + // the thread is in Deactivated state + ++thr->activation_count; + // wake the thread up so that it Switches Out itself. + thr->get_virtual_processor()->Activate( thr ); + } // else, it is Switched Out + } // else the thread will see that it is removed and proceed to switch itself out without Deactivation + } +} + +void thread_map::add_virtual_processors( IVirtualProcessorRoot** vproots, unsigned int count, omp_connection_v2& conn, ::tbb::spin_mutex& mtx ) +{ + std::vector<thread_map::iterator> vec(count); + std::vector<server_thread*> tvec(count); + iterator end; + + { + tbb::spin_mutex::scoped_lock lck( mtx ); + // read the map + end = my_map.end(); //remember 'end' at the time of 'find' + for( size_t i=0; i<count; ++i ) + vec[i] = my_map.find( (key_type) vproots[i] ); + } + + for( size_t i=0; i<count; ++i ) { + __TBB_ASSERT( !tvec[i], NULL ); + if( vec[i]==end ) { + tvec[i] = my_omp_allocator.allocate(1); + new ( tvec[i] ) omp_server_thread( false, my_scheduler, (IExecutionResource*)vproots[i], &conn, *this, my_client ); + } + } + + { + tbb::spin_mutex::scoped_lock lck( mtx ); + + for( size_t i=0; i<count; ++i ) { + if( vec[i]==my_map.end() ) { + thread_map::key_type key = (thread_map::key_type) vproots[i]; + vec[i] = insert( key, tvec[i] ); + my_client_ref_count.add_ref(); + my_server_ref_count.add_ref(); + } + } + + // we could check is_closing() earlier. That requires marking the newly allocated server_thread objects + // that are not inserted into the thread_map, and deallocate them. Doing so seems more cumbersome + // than simply adding these to the thread_map and let thread_map's destructor take care of reclamation. + if( is_closing() ) return; + } + + for( size_t i=0; i<count; ++i ) + vproots[i]->Activate( (*vec[i]).second ); + + { + tbb::spin_mutex::scoped_lock lck( mtx ); + for( size_t i=0; i<count; ++i ) + original_exec_resources.push_back( vproots[i] ); + } +} + +void thread_map::mark_virtual_processors_as_lent( IVirtualProcessorRoot** vproots, unsigned count, ::tbb::spin_mutex& mtx ) { + tbb::spin_mutex::scoped_lock lck( mtx ); + + if( is_closing() ) return; + + iterator end = my_map.end(); + for( unsigned int c=0; c<count; ++c ) { + iterator i = my_map.find( (key_type) vproots[c] ); + if( i==end ) { + // The vproc has not been added to the map in create_oversubscribers() + my_map.insert( hash_map_type::value_type( (key_type) vproots[c], (server_thread*)1 ) ); + } else { + server_thread* thr = (*i).second; + if( ((uintptr_t)thr)&~(uintptr_t)1 ) { + __TBB_ASSERT( !thr->is_removed(), "incorrectly removed" ); + ((omp_server_thread*)thr)->set_lent(); + } + } + } +} + +void thread_map::create_oversubscribers( unsigned n, std::vector<server_thread*>& thr_vec, omp_connection_v2& conn, ::tbb::spin_mutex& mtx ) { + std::vector<IExecutionResource*> curr_exec_rsc; + { + tbb::spin_mutex::scoped_lock lck( mtx ); + curr_exec_rsc = original_exec_resources; // copy construct + } + typedef std::vector<IExecutionResource*>::iterator iterator_er; + typedef ::std::vector<std::pair<hash_map_type::key_type, hash_map_type::mapped_type> > hash_val_vector_t; + hash_val_vector_t v_vec(n); + iterator_er begin = curr_exec_rsc.begin(); + iterator_er end = curr_exec_rsc.end(); + iterator_er i = begin; + for( unsigned c=0; c<n; ++c ) { + IVirtualProcessorRoot* vpr = my_scheduler_proxy->CreateOversubscriber( *i ); + omp_server_thread* t = new ( my_omp_allocator.allocate(1) ) omp_server_thread( true, my_scheduler, (IExecutionResource*)vpr, &conn, *this, my_client ); + thr_vec[c] = t; + v_vec[c] = hash_map_type::value_type( (key_type) vpr, t ); + if( ++i==end ) i = begin; + } + + { + tbb::spin_mutex::scoped_lock lck( mtx ); + + if( is_closing() ) return; + + iterator end = my_map.end(); + unsigned c = 0; + for( hash_val_vector_t::iterator vi=v_vec.begin(); vi!=v_vec.end(); ++vi, ++c ) { + iterator i = my_map.find( (key_type) (*vi).first ); + if( i==end ) { + my_map.insert( *vi ); + } else { + // the vproc has not been added to the map in mark_virtual_processors_as_returned(); + unsigned lent = (unsigned) (*i).second; + __TBB_ASSERT( lent<=1, "vproc map entry added incorrectly?"); + (*i).second = thr_vec[c]; + if( lent ) + ((omp_server_thread*)thr_vec[c])->set_lent(); + else + ((omp_server_thread*)thr_vec[c])->set_returned(); + } + my_client_ref_count.add_ref(); + my_server_ref_count.add_ref(); + } + } +} + +void thread_map::wakeup_tbb_threads( int c, ::tbb::spin_mutex& mtx ) { + std::vector<tbb_server_thread*> vec(c); + + size_t idx = 0; + { + tbb::spin_mutex::scoped_lock lck( mtx ); + + if( is_closing() ) return; + // only one RML thread is in here to wake worker threads up. + + int bal = the_balance; + int cnt = c<bal ? c : bal; + + if( cnt<=0 ) { return; } + + for( iterator i=begin(); i!=end(); ++i ) { + tbb_server_thread* thr = (tbb_server_thread*) (*i).second; + // ConcRT RM should take threads away from TBB scheduler instead of lending them to another scheduler + if( thr->is_removed() ) + continue; + + if( --the_balance>=0 ) { + thread_grab_t res; + while( (res=thr->try_grab_for())!=wk_from_idle ) { + if( res==wk_from_asleep ) { + vec[idx++] = thr; + break; + } else { + thread_state_t s = thr->read_state(); + if( s==ts_busy ) {// failed because already assigned. move on. + ++the_balance; + goto skip; + } + } + } + thread_state_t s = thr->read_state(); + __TBB_ASSERT_EX( s==ts_busy, "should have set the state to ts_busy" ); + if( --cnt==0 ) + break; + } else { + // overdraft + ++the_balance; + break; + } +skip: + ; + } + } + + for( size_t i=0; i<idx; ++i ) { + tbb_server_thread* thr = vec[i]; + __TBB_ASSERT( thr, NULL ); + thread_state_t s = thr->read_state(); + __TBB_ASSERT_EX( s==ts_busy, "should have set the state to ts_busy" ); + ++thr->activation_count; + thr->get_virtual_processor()->Activate( thr ); + } + +} + +void thread_map::mark_virtual_processors_as_returned( IVirtualProcessorRoot** vprocs, unsigned int count, tbb::spin_mutex& mtx ) { + { + tbb::spin_mutex::scoped_lock lck( mtx ); + + if( is_closing() ) return; + + iterator end = my_map.end(); + for(unsigned c=0; c<count; ++c ) { + iterator i = my_map.find( (key_type) vprocs[c] ); + if( i==end ) { + // the vproc has not been added to the map in create_oversubscribers() + my_map.insert( hash_map_type::value_type( (key_type) vprocs[c], static_cast<server_thread*>(0) ) ); + } else { + omp_server_thread* thr = (omp_server_thread*) (*i).second; + if( ((uintptr_t)thr)&~(uintptr_t)1 ) { + __TBB_ASSERT( !thr->is_removed(), "incorrectly removed" ); + // we shoud not make any assumption on the initial state of an added vproc. + thr->set_returned(); + } + } + } + } +} + + +void thread_map::unbind( rml::server& /*server*/, tbb::spin_mutex& mtx ) { + { + tbb::spin_mutex::scoped_lock lck( mtx ); + shutdown_in_progress = true; // ignore any callbacks from ConcRT RM + + // Ask each server_thread to cleanup its job for this server. + for( iterator i = begin(); i!=end(); ++i ) { + server_thread* t = (*i).second; + t->terminate = true; + if( t->is_removed() ) { + // This is for TBB only as ConcRT RM does not request OMP schedulers to remove virtual processors + if( t->read_state()==ts_asleep ) { + __TBB_ASSERT( my_thread_scavenger_thread, "this is TBB connection; thread_scavenger_thread must be allocated" ); + // thread is on its way to switch_out; see remove_virtual_processors() where + // the thread is Activated() to bring it back from 'Deactivated' in sleep_perhaps() + // now assume that the thread will go to SwitchOut() +#if TBB_USE_ASSERT + while( t->get_virtual_processor()>c_remove_returned ) + __TBB_Yield(); +#endif + // A removed thread is supposed to proceed to SwithcOut. + // There, we remove client&server references. + } + } else { + if( t->wakeup( ts_done, ts_asleep ) ) { + if( t->tbb_thread ) + ++((tbb_server_thread*)t)->activation_count; + t->get_virtual_processor()->Activate( t ); + // We mark in the thread_map such that when termination sequence started, we ignore + // all notification from ConcRT RM. + } + } + } + } + // Remove extra ref to client. + remove_client_ref(); + + if( my_thread_scavenger_thread ) { + thread_scavenger_thread* tst; + while( (tst=my_thread_scavenger_thread)==c_claimed ) + __TBB_Yield(); +#if TBB_USE_ASSERT + ++my_thread_scavenger_thread->activation_count; +#endif + tst->get_virtual_processor()->Activate( tst ); + } +} + +#if !__RML_REMOVE_VIRTUAL_PROCESSORS_DISABLED +void thread_map::allocate_thread_scavenger( IExecutionResource* v ) +{ + if( my_thread_scavenger_thread>c_claimed ) return; + thread_scavenger_thread* c = my_thread_scavenger_thread.fetch_and_store((thread_scavenger_thread*)c_claimed); + if( c==NULL ) { // successfully claimed + add_server_ref(); +#if TBB_USE_ASSERT + ++n_thread_scavengers_created; +#endif + __TBB_ASSERT( v, NULL ); + IVirtualProcessorRoot* vpr = my_scheduler_proxy->CreateOversubscriber( v ); + my_thread_scavenger_thread = c = new ( my_scavenger_allocator.allocate(1) ) thread_scavenger_thread( my_scheduler, vpr, *this ); +#if TBB_USE_ASSERT + ++c->activation_count; +#endif + vpr->Activate( c ); + } else if( c>c_claimed ) { + my_thread_scavenger_thread = c; + } +} +#endif + +void thread_scavenger_thread::Dispatch( DispatchState* ) +{ + __TBB_ASSERT( my_proxy, NULL ); +#if TBB_USE_ASSERT + --activation_count; +#endif + get_virtual_processor()->Deactivate( this ); + for( thread_map::iterator i=my_thread_map.begin(); i!=my_thread_map.end(); ++i ) { + tbb_server_thread* t = (tbb_server_thread*) (*i).second; + if( t->read_state()==ts_asleep && t->is_removed() ) { + while( t->get_execution_resource()!=c_remove_returned ) + __TBB_Yield(); + my_proxy->SwitchTo( t, Blocking ); + } + } + get_virtual_processor()->Remove( my_scheduler ); + my_thread_map.remove_server_ref(); + // signal to the connection scavenger that i am done with the map. + __TBB_ASSERT( activation_count==1, NULL ); + set_state( ts_done ); +} + +//! Windows "DllMain" that handles startup and shutdown of dynamic library. +extern "C" bool WINAPI DllMain( HINSTANCE /*hinstDLL*/, DWORD fwdReason, LPVOID lpvReserved ) { + void assist_cleanup_connections(); + if( fwdReason==DLL_PROCESS_DETACH ) { + // dll is being unloaded + if( !lpvReserved ) // if FreeLibrary has been called + assist_cleanup_connections(); + } + return true; +} + +void free_all_connections( uintptr_t conn_ex ) { + while( conn_ex ) { + bool is_tbb = (conn_ex&2)>0; + //clear extra bits + uintptr_t curr_conn = conn_ex & ~(uintptr_t)3; + __TBB_ASSERT( curr_conn, NULL ); + + // Wait for worker threads to return + if( is_tbb ) { + tbb_connection_v2* tbb_conn = reinterpret_cast<tbb_connection_v2*>(curr_conn); + conn_ex = reinterpret_cast<uintptr_t>(tbb_conn->next_conn); + while( tbb_conn->my_thread_map.remove_server_ref()>0 ) + __TBB_Yield(); + delete tbb_conn; + } else { + omp_connection_v2* omp_conn = reinterpret_cast<omp_connection_v2*>(curr_conn); + conn_ex = reinterpret_cast<uintptr_t>(omp_conn->next_conn); + while( omp_conn->my_thread_map.remove_server_ref()>0 ) + __TBB_Yield(); + delete omp_conn; + } + } +} + +void assist_cleanup_connections() +{ + //signal to connection_scavenger_thread to terminate + uintptr_t tail = connections_to_reclaim.tail; + while( connections_to_reclaim.tail.compare_and_swap( garbage_connection_queue::plugged, tail )!=tail ) { + __TBB_Yield(); + tail = connections_to_reclaim.tail; + } + + __TBB_ASSERT( connection_scavenger.state==ts_busy || connection_scavenger.state==ts_asleep, NULL ); + // Scavenger thread may be busy freeing connections + DWORD thr_exit_code = STILL_ACTIVE; + while( connection_scavenger.state==ts_busy ) { + if( GetExitCodeThread( connection_scavenger.thr_handle, &thr_exit_code )>0 ) + if( thr_exit_code!=STILL_ACTIVE ) + break; + __TBB_Yield(); + thr_exit_code = STILL_ACTIVE; + } + if( connection_scavenger.state==ts_asleep && thr_exit_code==STILL_ACTIVE ) + connection_scavenger.wakeup(); // wake the connection scavenger thread up + + // it is possible that the connection scavenger thread already exited. Take over its responsibility. + if( tail && connections_to_reclaim.tail!=garbage_connection_queue::plugged_acked ) { + // atomically claim the head of the list. + uintptr_t head = connections_to_reclaim.head.fetch_and_store( garbage_connection_queue::empty ); + if( head==garbage_connection_queue::empty ) + head = tail; + connection_scavenger.process_requests( head ); + } + __TBB_ASSERT( connections_to_reclaim.tail==garbage_connection_queue::plugged||connections_to_reclaim.tail==garbage_connection_queue::plugged_acked, "someone else added a request after termination has initiated" ); + __TBB_ASSERT( (unsigned)the_balance==the_default_concurrency, NULL ); +} + +void connection_scavenger_thread::sleep_perhaps() { + uintptr_t tail = connections_to_reclaim.tail; + // connections_to_reclaim.tail==garbage_connection_queue::plugged --> terminate, + // connections_to_reclaim.tail>garbage_connection_queue::plugged : we got work to do + if( tail>=garbage_connection_queue::plugged ) return; + __TBB_ASSERT( !tail, NULL ); + thread_monitor::cookie c; + monitor.prepare_wait(c); + if( state.compare_and_swap( ts_asleep, ts_busy )==ts_busy ) { + if( connections_to_reclaim.tail!=garbage_connection_queue::plugged ) { + monitor.commit_wait(c); + // Someone else woke me up. The compare_and_swap further below deals with spurious wakeups. + } else { + monitor.cancel_wait(); + } + thread_state_t s = state; + if( s==ts_asleep ) // if spurious wakeup. + state.compare_and_swap( ts_busy, ts_asleep ); + // I woke myself up, either because I cancelled the wait or suffered a spurious wakeup. + } else { + __TBB_ASSERT( false, "someone else tampered with my state" ); + } + __TBB_ASSERT( state==ts_busy, "a thread can only put itself to sleep" ); +} + +void connection_scavenger_thread::process_requests( uintptr_t conn_ex ) +{ + __TBB_ASSERT( conn_ex>1, NULL ); + __TBB_ASSERT( n_scavenger_threads==1||connections_to_reclaim.tail==garbage_connection_queue::plugged, "more than one connection_scavenger_thread being active?" ); + + bool done = false; + while( !done ) { + bool is_tbb = (conn_ex&2)>0; + //clear extra bits + uintptr_t curr_conn = conn_ex & ~(uintptr_t)3; + + // no contention. there is only one connection_scavenger_thread!! + uintptr_t next_conn; + tbb_connection_v2* tbb_conn = NULL; + omp_connection_v2* omp_conn = NULL; + // Wait for worker threads to return + if( is_tbb ) { + tbb_conn = reinterpret_cast<tbb_connection_v2*>(curr_conn); + next_conn = reinterpret_cast<uintptr_t>(tbb_conn->next_conn); + while( tbb_conn->my_thread_map.get_server_ref_count()>1 ) + __TBB_Yield(); + } else { + omp_conn = reinterpret_cast<omp_connection_v2*>(curr_conn); + next_conn = reinterpret_cast<uintptr_t>(omp_conn->next_conn); + while( omp_conn->my_thread_map.get_server_ref_count()>1 ) + __TBB_Yield(); + } + + //someone else may try to write into this connection object. + //So access next_conn field first before remove the extra server ref count. + + if( next_conn==0 ) { + uintptr_t tail = connections_to_reclaim.tail; + if( tail==garbage_connection_queue::plugged ) { + tail = garbage_connection_queue::plugged_acked; // connection scavenger saw the flag, and it freed all connections. + done = true; + } else if( tail==conn_ex ) { + if( connections_to_reclaim.tail.compare_and_swap( garbage_connection_queue::empty, tail )==tail ) { + __TBB_ASSERT( !connections_to_reclaim.head, NULL ); + done = true; + } + } + + if( !done ) { + // A new connection to close is added to connections_to_reclaim.tail; + // Wait for curr_conn->next_conn to be set. + if( is_tbb ) { + while( !tbb_conn->next_conn ) + __TBB_Yield(); + conn_ex = reinterpret_cast<uintptr_t>(tbb_conn->next_conn); + } else { + while( !omp_conn->next_conn ) + __TBB_Yield(); + conn_ex = reinterpret_cast<uintptr_t>(omp_conn->next_conn); + } + } + } else { + conn_ex = next_conn; + } + __TBB_ASSERT( conn_ex, NULL ); + if( is_tbb ) + // remove extra srever ref count; this will trigger Shutdown/Release of ConcRT RM + tbb_conn->remove_server_ref(); + else + // remove extra srever ref count; this will trigger Shutdown/Release of ConcRT RM + omp_conn->remove_server_ref(); + } +} + +__RML_DECL_THREAD_ROUTINE connection_scavenger_thread::thread_routine( void* arg ) { + connection_scavenger_thread* thr = (connection_scavenger_thread*) arg; + thr->state = ts_busy; + thr->thr_handle = GetCurrentThread(); +#if TBB_USE_ASSERT + ++thr->n_scavenger_threads; +#endif + for(;;) { + __TBB_Yield(); + thr->sleep_perhaps(); + if( connections_to_reclaim.tail==garbage_connection_queue::plugged || connections_to_reclaim.tail==garbage_connection_queue::plugged_acked ) { + thr->state = ts_asleep; + return 0; + } + + __TBB_ASSERT( connections_to_reclaim.tail!=garbage_connection_queue::plugged_acked, NULL ); + __TBB_ASSERT( connections_to_reclaim.tail>garbage_connection_queue::plugged && (connections_to_reclaim.tail&garbage_connection_queue::plugged)==0 , NULL ); + while( connections_to_reclaim.head==garbage_connection_queue::empty ) + __TBB_Yield(); + uintptr_t head = connections_to_reclaim.head.fetch_and_store( garbage_connection_queue::empty ); + thr->process_requests( head ); + wakeup_some_tbb_threads(); + } +} + +template<typename Server, typename Client> +void connection_scavenger_thread::add_request( generic_connection<Server,Client>* conn_to_close ) +{ + uintptr_t conn_ex = (uintptr_t)conn_to_close | (connection_traits<Server,Client>::is_tbb<<1); + __TBB_ASSERT( !conn_to_close->next_conn, NULL ); + uintptr_t old_tail_ex = connections_to_reclaim.tail; + __TBB_ASSERT( old_tail_ex==0||old_tail_ex>garbage_connection_queue::plugged_acked, "Unloading DLL called while this connection is being closed?" ); + tbb::internal::atomic_backoff backoff; + while( connections_to_reclaim.tail.compare_and_swap( conn_ex, old_tail_ex )!=old_tail_ex ) { + backoff.pause(); + old_tail_ex = connections_to_reclaim.tail; + } + + if( old_tail_ex==garbage_connection_queue::empty ) + connections_to_reclaim.head = conn_ex; + else { + bool is_tbb = (old_tail_ex&2)>0; + uintptr_t old_tail = old_tail_ex & ~(uintptr_t)3; + if( is_tbb ) + reinterpret_cast<tbb_connection_v2*>(old_tail)->next_conn = reinterpret_cast<tbb_connection_v2*>(conn_ex); + else + reinterpret_cast<omp_connection_v2*>(old_tail)->next_conn = reinterpret_cast<omp_connection_v2*>(conn_ex); + } + + if( state==ts_asleep ) + wakeup(); +} + +template<> +uintptr_t connection_scavenger_thread::grab_and_prepend( generic_connection<tbb_server,tbb_client>* /*last_conn_to_close*/ ) { return 0;} + +template<> +uintptr_t connection_scavenger_thread::grab_and_prepend( generic_connection<omp_server,omp_client>* last_conn_to_close ) +{ + uintptr_t conn_ex = (uintptr_t)last_conn_to_close; + uintptr_t head = connections_to_reclaim.head.fetch_and_store( garbage_connection_queue::empty ); + reinterpret_cast<omp_connection_v2*>(last_conn_to_close)->next_conn = reinterpret_cast<omp_connection_v2*>(head); + return conn_ex; +} + +extern "C" ULONGLONG NTAPI VerSetConditionMask( ULONGLONG, DWORD, BYTE); + +bool is_windows7_or_later () +{ + try { + return GetOSVersion()>=IResourceManager::Win7OrLater; + } catch( ... ) { + return false; + } +} + +#endif /* RML_USE_WCRM */ + +template<typename Connection, typename Server, typename Client> +static factory::status_type connect( factory& f, Server*& server, Client& client ) { + server = new Connection(*static_cast<wait_counter*>(f.scratch_ptr),client); + return factory::st_success; +} + +void init_rml_module () { + the_balance = the_default_concurrency = tbb::internal::AvailableHwConcurrency() - 1; +#if RML_USE_WCRM + connection_scavenger.launch(); +#endif +} + +extern "C" factory::status_type __RML_open_factory( factory& f, version_type& server_version, version_type client_version ) { + // Hack to keep this library from being closed by causing the first client's dlopen to not have a corresponding dlclose. + // This code will be removed once we figure out how to do shutdown of the RML perfectly. + static tbb::atomic<bool> one_time_flag; + if( one_time_flag.compare_and_swap(true,false)==false) { + __TBB_ASSERT( (size_t)f.library_handle!=factory::c_dont_unload, NULL ); +#if _WIN32||_WIN64 + f.library_handle = reinterpret_cast<HMODULE>(factory::c_dont_unload); +#else + f.library_handle = reinterpret_cast<void*>(factory::c_dont_unload); +#endif + } + // End of hack + + // Initialize the_balance only once + tbb::internal::atomic_do_once ( &init_rml_module, rml_module_state ); + + server_version = SERVER_VERSION; + f.scratch_ptr = 0; + if( client_version==0 ) { + return factory::st_incompatible; +#if RML_USE_WCRM + } else if ( !is_windows7_or_later() ) { +#if TBB_USE_DEBUG + fprintf(stderr, "This version of the RML library requires Windows 7 to run on.\nConnection request denied.\n"); +#endif + return factory::st_incompatible; +#endif + } else { +#if TBB_USE_DEBUG + if( client_version<EARLIEST_COMPATIBLE_CLIENT_VERSION ) + fprintf(stderr, "This client library is too old for the current RML server.\nThe connection request is granted but oversubscription/undersubscription may occur.\n"); +#endif + f.scratch_ptr = new wait_counter; + return factory::st_success; + } +} + +extern "C" void __RML_close_factory( factory& f ) { + if( wait_counter* fc = static_cast<wait_counter*>(f.scratch_ptr) ) { + f.scratch_ptr = 0; + fc->wait(); + size_t bal = the_balance; + f.scratch_ptr = (void*)bal; + delete fc; + } +} + +void call_with_build_date_str( ::rml::server_info_callback_t cb, void* arg ); + +}} // rml::internal + +namespace tbb { +namespace internal { +namespace rml { + +extern "C" tbb_factory::status_type __TBB_make_rml_server( tbb_factory& f, tbb_server*& server, tbb_client& client ) { + return ::rml::internal::connect< ::rml::internal::tbb_connection_v2>(f,server,client); +} + +extern "C" void __TBB_call_with_my_server_info( ::rml::server_info_callback_t cb, void* arg ) { + return ::rml::internal::call_with_build_date_str( cb, arg ); +} + +}}} + +namespace __kmp { +namespace rml { + +extern "C" omp_factory::status_type __KMP_make_rml_server( omp_factory& f, omp_server*& server, omp_client& client ) { + return ::rml::internal::connect< ::rml::internal::omp_connection_v2>(f,server,client); +} + +extern "C" void __KMP_call_with_my_server_info( ::rml::server_info_callback_t cb, void* arg ) { + return ::rml::internal::call_with_build_date_str( cb, arg ); +} + +}} + +/* + * RML server info + */ +#include "version_string.ver" + +#ifndef __TBB_VERSION_STRINGS +#pragma message("Warning: version_string.ver isn't generated properly by version_info.sh script!") +#endif + +// We use the build time as the RML server info. TBB is required to build RML, so we make it the same as the TBB build time. +#ifndef __TBB_DATETIME +#define __TBB_DATETIME __DATE__ " " __TIME__ +#endif + +#if !RML_USE_WCRM +#define RML_SERVER_BUILD_TIME "Intel(R) RML library built: " __TBB_DATETIME +#define RML_SERVER_VERSION_ST "Intel(R) RML library version: v" TOSTRING(SERVER_VERSION) +#else +#define RML_SERVER_BUILD_TIME "Intel(R) RML library built: " __TBB_DATETIME +#define RML_SERVER_VERSION_ST "Intel(R) RML library version: v" TOSTRING(SERVER_VERSION) " on ConcRT RM with " RML_THREAD_KIND_STRING +#endif + +namespace rml { +namespace internal { + +void call_with_build_date_str( ::rml::server_info_callback_t cb, void* arg ) +{ + (*cb)( arg, RML_SERVER_BUILD_TIME ); + (*cb)( arg, RML_SERVER_VERSION_ST ); +} +}} // rml::internal diff --git a/src/tbb/src/rml/server/thread_monitor.h b/src/tbb/src/rml/server/thread_monitor.h new file mode 100644 index 0000000..6e18885 --- /dev/null +++ b/src/tbb/src/rml/server/thread_monitor.h @@ -0,0 +1,220 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// All platform-specific threading support is encapsulated here. */ + +#ifndef __RML_thread_monitor_H +#define __RML_thread_monitor_H + +#if USE_WINTHREAD +#include <windows.h> +#include <process.h> +#include <malloc.h> //_alloca +#include "tbb/tbb_misc.h" // NumberOfProcessorGroups, MoveThreadIntoProcessorGroup, FindProcessorGroupIndex +#elif USE_PTHREAD +#include <pthread.h> +#include <string.h> +#include <stdlib.h> +#else +#error Unsupported platform +#endif +#include <stdio.h> +#include "tbb/itt_notify.h" +#include "tbb/atomic.h" +#include "tbb/semaphore.h" + +// All platform-specific threading support is in this header. + +#if (_WIN32||_WIN64)&&!__TBB_ipf +// Deal with 64K aliasing. The formula for "offset" is a Fibonacci hash function, +// which has the desirable feature of spreading out the offsets fairly evenly +// without knowing the total number of offsets, and furthermore unlikely to +// accidentally cancel out other 64K aliasing schemes that Microsoft might implement later. +// See Knuth Vol 3. "Theorem S" for details on Fibonacci hashing. +// The second statement is really does need "volatile", otherwise the compiler might remove the _alloca. +#define AVOID_64K_ALIASING(idx) \ + size_t offset = (idx+1) * 40503U % (1U<<16); \ + void* volatile sink_for_alloca = _alloca(offset); \ + __TBB_ASSERT_EX(sink_for_alloca, "_alloca failed"); +#else +// Linux thread allocators avoid 64K aliasing. +#define AVOID_64K_ALIASING(idx) +#endif /* _WIN32||_WIN64 */ + +namespace rml { + +namespace internal { + +#if DO_ITT_NOTIFY +static const ::tbb::tchar *SyncType_RML = _T("%Constant"); +static const ::tbb::tchar *SyncObj_ThreadMonitor = _T("RML Thr Monitor"); +#endif /* DO_ITT_NOTIFY */ + +//! Monitor with limited two-phase commit form of wait. +/** At most one thread should wait on an instance at a time. */ +class thread_monitor { +public: + class cookie { + friend class thread_monitor; + tbb::atomic<size_t> my_epoch; + }; + thread_monitor() : spurious(false) { + my_cookie.my_epoch = 0; + ITT_SYNC_CREATE(&my_sema, SyncType_RML, SyncObj_ThreadMonitor); + in_wait = false; + } + ~thread_monitor() {} + + //! If a thread is waiting or started a two-phase wait, notify it. + /** Can be called by any thread. */ + void notify(); + + //! Begin two-phase wait. + /** Should only be called by thread that owns the monitor. + The caller must either complete the wait or cancel it. */ + void prepare_wait( cookie& c ); + + //! Complete a two-phase wait and wait until notification occurs after the earlier prepare_wait. + void commit_wait( cookie& c ); + + //! Cancel a two-phase wait. + void cancel_wait(); + +#if USE_WINTHREAD + #define __RML_DECL_THREAD_ROUTINE unsigned WINAPI + typedef unsigned (WINAPI *thread_routine_type)(void*); + + //! Launch a thread + static void launch( thread_routine_type thread_routine, void* arg, size_t stack_size, const size_t* worker_index = NULL ); + +#elif USE_PTHREAD + #define __RML_DECL_THREAD_ROUTINE void* + typedef void*(*thread_routine_type)(void*); + + //! Launch a thread + static void launch( thread_routine_type thread_routine, void* arg, size_t stack_size ); +#endif /* USE_PTHREAD */ + + static void yield(); + +private: + cookie my_cookie; + tbb::atomic<bool> in_wait; + bool spurious; + tbb::internal::binary_semaphore my_sema; +#if USE_PTHREAD + static void check( int error_code, const char* routine ); +#endif +}; + +#if USE_WINTHREAD + +#ifndef STACK_SIZE_PARAM_IS_A_RESERVATION +#define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000 +#endif + +inline void thread_monitor::launch( thread_routine_type thread_routine, void* arg, size_t stack_size, const size_t* worker_index ) { + unsigned thread_id; + int number_of_processor_groups = ( worker_index ) ? tbb::internal::NumberOfProcessorGroups() : 0; + unsigned create_flags = ( number_of_processor_groups > 1 ) ? CREATE_SUSPENDED : 0; + uintptr_t status = _beginthreadex( NULL, unsigned(stack_size), thread_routine, arg, STACK_SIZE_PARAM_IS_A_RESERVATION | create_flags, &thread_id ); + if( status==0 ) { + fprintf(stderr,"thread_monitor::launch: _beginthreadex failed\n"); + exit(1); + } + if ( number_of_processor_groups > 1 ) { + tbb::internal::MoveThreadIntoProcessorGroup( (HANDLE)status, + tbb::internal::FindProcessorGroupIndex( static_cast<int>(*worker_index) ) ); + ResumeThread( (HANDLE)status ); + } + CloseHandle( (HANDLE)status ); +} + +inline void thread_monitor::yield() { + SwitchToThread(); +} +#endif /* USE_WINTHREAD */ + +#if USE_PTHREAD +inline void thread_monitor::check( int error_code, const char* routine ) { + if( error_code ) { + fprintf(stderr,"thread_monitor %s in %s\n", strerror(error_code), routine ); + exit(1); + } +} + +inline void thread_monitor::launch( void* (*thread_routine)(void*), void* arg, size_t stack_size ) { + // FIXME - consider more graceful recovery than just exiting if a thread cannot be launched. + // Note that there are some tricky situations to deal with, such that the thread is already + // grabbed as part of an OpenMP team. + pthread_attr_t s; + check(pthread_attr_init( &s ), "pthread_attr_init"); + if( stack_size>0 ) + check(pthread_attr_setstacksize( &s, stack_size ), "pthread_attr_setstack_size" ); + pthread_t handle; + check( pthread_create( &handle, &s, thread_routine, arg ), "pthread_create" ); + check( pthread_detach( handle ), "pthread_detach" ); +} + +inline void thread_monitor::yield() { + sched_yield(); +} +#endif /* USE_PTHREAD */ + +inline void thread_monitor::notify() { + my_cookie.my_epoch = my_cookie.my_epoch + 1; + bool do_signal = in_wait.fetch_and_store( false ); + if( do_signal ) + my_sema.V(); +} + +inline void thread_monitor::prepare_wait( cookie& c ) { + if( spurious ) { + spurious = false; + // consumes a spurious posted signal. don't wait on my_sema. + my_sema.P(); + } + c = my_cookie; + in_wait = true; + __TBB_full_memory_fence(); +} + +inline void thread_monitor::commit_wait( cookie& c ) { + bool do_it = ( c.my_epoch == my_cookie.my_epoch); + if( do_it ) my_sema.P(); + else cancel_wait(); +} + +inline void thread_monitor::cancel_wait() { + spurious = ! in_wait.fetch_and_store( false ); +} + +} // namespace internal +} // namespace rml + +#endif /* __RML_thread_monitor_H */ diff --git a/src/tbb/src/rml/server/wait_counter.h b/src/tbb/src/rml/server/wait_counter.h new file mode 100644 index 0000000..0f01b1f --- /dev/null +++ b/src/tbb/src/rml/server/wait_counter.h @@ -0,0 +1,81 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __RML_wait_counter_H +#define __RML_wait_counter_H + +#include "thread_monitor.h" +#include "tbb/atomic.h" + +namespace rml { +namespace internal { + +class wait_counter { + thread_monitor my_monitor; + tbb::atomic<int> my_count; + tbb::atomic<int> n_transients; +public: + wait_counter() { + // The "1" here is subtracted by the call to "wait". + my_count=1; + n_transients=0; + } + + //! Wait for number of operator-- invocations to match number of operator++ invocations. + /** Exactly one thread should call this method. */ + void wait() { + int k = --my_count; + __TBB_ASSERT( k>=0, "counter underflow" ); + if( k>0 ) { + thread_monitor::cookie c; + my_monitor.prepare_wait(c); + if( my_count ) + my_monitor.commit_wait(c); + else + my_monitor.cancel_wait(); + } + while( n_transients>0 ) + __TBB_Yield(); + } + void operator++() { + ++my_count; + } + void operator--() { + ++n_transients; + int k = --my_count; + __TBB_ASSERT( k>=0, "counter underflow" ); + if( k==0 ) + my_monitor.notify(); + --n_transients; + } +}; + +} // namespace internal +} // namespace rml + +#endif /* __RML_wait_counter_H */ diff --git a/src/tbb/src/rml/server/win32-rml-export.def b/src/tbb/src/rml/server/win32-rml-export.def new file mode 100644 index 0000000..10cdc9a --- /dev/null +++ b/src/tbb/src/rml/server/win32-rml-export.def @@ -0,0 +1,35 @@ +; Copyright 2005-2012 Intel Corporation. All Rights Reserved. +; +; This file is part of Threading Building Blocks. +; +; Threading Building Blocks is free software; you can redistribute it +; and/or modify it under the terms of the GNU General Public License +; version 2 as published by the Free Software Foundation. +; +; Threading Building Blocks is distributed in the hope that it will be +; useful, but WITHOUT ANY WARRANTY; without even the implied warranty +; of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with Threading Building Blocks; if not, write to the Free Software +; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +; +; As a special exception, you may use this file as part of a free software +; library without restriction. Specifically, if other files instantiate +; templates or use macros or inline functions from this file, or you compile +; this file and link it with other files to produce an executable, this +; file does not by itself cause the resulting executable to be covered by +; the GNU General Public License. This exception does not however +; invalidate any other reasons why the executable file might be covered by +; the GNU General Public License. + +EXPORTS + +__RML_open_factory +__RML_close_factory +__TBB_make_rml_server +__KMP_make_rml_server +__TBB_call_with_my_server_info +__KMP_call_with_my_server_info + diff --git a/src/tbb/src/rml/server/win64-rml-export.def b/src/tbb/src/rml/server/win64-rml-export.def new file mode 100644 index 0000000..10cdc9a --- /dev/null +++ b/src/tbb/src/rml/server/win64-rml-export.def @@ -0,0 +1,35 @@ +; Copyright 2005-2012 Intel Corporation. All Rights Reserved. +; +; This file is part of Threading Building Blocks. +; +; Threading Building Blocks is free software; you can redistribute it +; and/or modify it under the terms of the GNU General Public License +; version 2 as published by the Free Software Foundation. +; +; Threading Building Blocks is distributed in the hope that it will be +; useful, but WITHOUT ANY WARRANTY; without even the implied warranty +; of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with Threading Building Blocks; if not, write to the Free Software +; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +; +; As a special exception, you may use this file as part of a free software +; library without restriction. Specifically, if other files instantiate +; templates or use macros or inline functions from this file, or you compile +; this file and link it with other files to produce an executable, this +; file does not by itself cause the resulting executable to be covered by +; the GNU General Public License. This exception does not however +; invalidate any other reasons why the executable file might be covered by +; the GNU General Public License. + +EXPORTS + +__RML_open_factory +__RML_close_factory +__TBB_make_rml_server +__KMP_make_rml_server +__TBB_call_with_my_server_info +__KMP_call_with_my_server_info + diff --git a/src/tbb/src/rml/test/rml_omp_stub.cpp b/src/tbb/src/rml/test/rml_omp_stub.cpp new file mode 100644 index 0000000..59aab9a --- /dev/null +++ b/src/tbb/src/rml/test/rml_omp_stub.cpp @@ -0,0 +1,71 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// This file is compiled with C++, but linked with a program written in C. +// The intent is to find dependencies on the C++ run-time. + +#include <stdlib.h> +#define RML_PURE_VIRTUAL_HANDLER abort + +#if _MSC_VER==1500 && !defined(__INTEL_COMPILER) +// VS2008/VC9 seems to have an issue; +#pragma warning( push ) +#pragma warning( disable: 4100 ) +#endif +#include "rml_omp.h" +#if _MSC_VER==1500 && !defined(__INTEL_COMPILER) +#pragma warning( pop ) +#endif + +rml::versioned_object::version_type Version; + +class MyClient: public __kmp::rml::omp_client { +public: + /*override*/rml::versioned_object::version_type version() const {return 0;} + /*override*/size_type max_job_count() const {return 1024;} + /*override*/size_t min_stack_size() const {return 1<<20;} + /*override*/rml::job* create_one_job() {return NULL;} + /*override*/void acknowledge_close_connection() {} + /*override*/void cleanup(job&) {} + /*override*/policy_type policy() const {return throughput;} + /*override*/void process( job&, void*, __kmp::rml::omp_client::size_type ) {} + +}; + +//! Never actually set, because point of test is to find linkage issues. +__kmp::rml::omp_server* MyServerPtr; + +#define HARNESS_NO_PARSE_COMMAND_LINE 1 +#define HARNESS_CUSTOM_MAIN 1 +#include "harness.h" + +extern "C" void Cplusplus() { + MyClient client; + Version = client.version(); + REPORT("done\n"); +} diff --git a/src/tbb/src/rml/test/test_job_automaton.cpp b/src/tbb/src/rml/test/test_job_automaton.cpp new file mode 100644 index 0000000..5c76c99 --- /dev/null +++ b/src/tbb/src/rml/test/test_job_automaton.cpp @@ -0,0 +1,153 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "job_automaton.h" +#define HARNESS_NO_PARSE_COMMAND_LINE 1 +#include "harness.h" +#include "harness_barrier.h" + +class State { + Harness::SpinBarrier barrier; + rml::internal::job_automaton ja; + rml::job job; + tbb::atomic<int> job_created; + tbb::atomic<int> job_destroyed; + tbb::atomic<bool> job_received; +public: + State() : barrier(2) { + job_created = 0; + job_destroyed = 0; + job_received = false; + } + void exercise( bool is_owner ); + ~State() { + ASSERT( job_created==job_destroyed, "accounting error" ); + ASSERT( job_destroyed<=1, "destroyed job twice" ); + } +}; + +int DelayMask; +const int N = 14; +tbb::atomic<int> Coverage[N]; + +//! Mark kth interval as covered and insert delay if kth bit of DelayMask is set. +/** An interval is the code between two operations on the job_automaton that we are testing. */ +void Cover( int k ) { + ASSERT( k<N, NULL ); + ++Coverage[k]; + if( DelayMask>>k&1 ) { + // Introduce delay (and possibly a thread context switch) + __TBB_Yield(); + } +} + +void State::exercise( bool is_owner ) { + barrier.wait(); + if( is_owner ) { + Cover(0); + if( ja.try_acquire() ) { + Cover(1); + ++job_created; + ja.set_and_release(job); + Cover(2); + if( ja.try_acquire() ) { + Cover(3); + ja.release(); + Cover(4); + if( ja.try_acquire() ) { + Cover(5); + ja.release(); + } + } + Cover(6); + } else { + Cover(7); + } + if( DelayMask&1<<N ) { + while( !job_received ) + __TBB_Yield(); + } + } else { + // Using extra bit of DelayMask for choosing whether to run wait_for_job or not. + if( DelayMask&1<<N ) { + rml::job* j= &ja.wait_for_job(); + if( j!=&job ) REPORT("%p\n",j); + ASSERT( j==&job, NULL ); + job_received = true; + } + Cover(8); + } + rml::job* j; + if( ja.try_plug(j) ) { + ASSERT( j==&job || !j, NULL ); + if( j ) { + Cover(9+is_owner); + ++job_destroyed; + } else { + __TBB_ASSERT( !is_owner, "owner failed to create job but plugged self" ); + Cover(11); + } + } else { + Cover(12+is_owner); + } +} + +class Loop: NoAssign { + State& s; +public: + Loop(State& s_) : s(s_) {} + void operator()( int i ) const {s.exercise(i==0);} +}; + +/** Return true if coverage is acceptable. + If report==true, issue message if it is unacceptable. */ +bool CheckCoverage( bool report ) { + bool okay = true; + for( int i=0; i<N; ++i ) { + const int min_coverage = 4; + if( Coverage[i]<min_coverage ) { + okay = false; + if( report ) + REPORT("Warning: Coverage[%d]=%d is less than acceptable minimum of %d\n", i, int(Coverage[i]),min_coverage); + } + } + return okay; +} + +int TestMain () { + for( DelayMask=0; DelayMask<8<<N; ++DelayMask ) { + State s; + NativeParallelFor( 2, Loop(s) ); + if( CheckCoverage(false) ) { + // Reached acceptable code coverage level + break; + } + } + CheckCoverage(true); + return Harness::Done; +} diff --git a/src/tbb/src/rml/test/test_rml_mixed.cpp b/src/tbb/src/rml/test/test_rml_mixed.cpp new file mode 100644 index 0000000..fd46d3e --- /dev/null +++ b/src/tbb/src/rml/test/test_rml_mixed.cpp @@ -0,0 +1,302 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "rml_tbb.h" +#include "rml_omp.h" +#include "tbb/atomic.h" +#include "tbb/tick_count.h" + +#define HARNESS_DEFAULT_MIN_THREADS 4 +#include "harness.h" + +const int OMP_ParallelRegionSize = 16; +int TBB_MaxThread = 4; // Includes master +int OMP_MaxThread = int(~0u>>1); // Includes master + +template<typename Client> +class ClientBase: public Client { +protected: + typedef typename Client::version_type version_type; + typedef typename Client::job job; + typedef typename Client::policy_type policy_type; + +private: + /*override*/version_type version() const { + return 0; + } + /*override*/size_t min_stack_size() const { + return 1<<20; + } + /*override*/job* create_one_job() { + return new rml::job; + } + /*override*/policy_type policy() const { + return Client::turnaround; + } + /*override*/void acknowledge_close_connection() { + delete this; + } + /*override*/void cleanup( job& j ) {delete &j;} +}; + +#if _WIN32 +#include <direct.h> +#define PATH_LEN MAX_PATH+1 +#define SLASH '\\' +#define ROOT_DIR "\\" +// ROOT_DIR_REST means how many symbols before first slash in the path +#define ROOT_DIR_REST 2 +#else +#include <unistd.h> +#include <limits.h> +#define PATH_LEN PATH_MAX+1 +#define SLASH '/' +#define ROOT_DIR "/" +// ROOT_DIR_REST means how many symbols before first slash in the path +#define ROOT_DIR_REST 0 +#define _getcwd getcwd +#define _chdir chdir +#endif + +class ChangeCurrentDir { + char dir[PATH_LEN+1]; + char *last_slash; +public: + ChangeCurrentDir() { + if ( !_getcwd( dir, PATH_LEN ) ) { + REPORT_FATAL_ERROR("ERROR: Couldn't get current working directory\n"); + } + + last_slash = strrchr( dir, SLASH ); + ASSERT( last_slash, "The current directory doesn't contain slashes" ); + *last_slash = 0; + + if ( _chdir( last_slash-dir == ROOT_DIR_REST ? ROOT_DIR : dir ) ) { + REPORT_FATAL_ERROR("ERROR: Couldn't change current working directory (%s)\n", dir ); + } + } + + // Restore current dir + ~ChangeCurrentDir() { + *last_slash = SLASH; + if ( _chdir(dir) ) { + REPORT_FATAL_ERROR("ERROR: Couldn't change current working directory\n"); + } + } +}; + +//! Represents a TBB or OpenMP run-time that uses RML. +template<typename Factory, typename Client> +class RunTime { +public: + //! Factory that run-time uses to make servers. + Factory factory; + Client* client; + typename Factory::server_type* server; +#if _WIN32||_WIN64 + ::rml::server::execution_resource_t me; +#endif + RunTime() { + factory.open(); + } + ~RunTime() { + factory.close(); + } + //! Create server for this run-time + void create_connection(); + + //! Destroy server for this run-time + void destroy_connection(); +}; + +class ThreadLevelRecorder { + tbb::atomic<int> level; + struct record { + tbb::tick_count time; + int nthread; + }; + tbb::atomic<unsigned> next; + /** Must be power of two */ + static const unsigned max_record_count = 1<<20; + record array[max_record_count]; +public: + void change_level( int delta ); + void dump(); +}; + +void ThreadLevelRecorder::change_level( int delta ) { + int x = level+=delta; + tbb::tick_count t = tbb::tick_count::now(); + unsigned k = next++; + if( k<max_record_count ) { + record& r = array[k]; + r.time = t; + r.nthread = x; + } +} + +void ThreadLevelRecorder::dump() { + FILE* f = fopen("time.txt","w"); + if( !f ) { + perror("fopen(time.txt)\n"); + exit(1); + } + unsigned limit = next; + if( limit>max_record_count ) { + // Clip + limit = next; + } + for( unsigned i=0; i<limit; ++i ) { + fprintf(f,"%f\t%d\n",(array[i].time-array[0].time).seconds(),array[i].nthread); + } + fclose(f); +} + +ThreadLevelRecorder TotalThreadLevel; + +class TBB_Client: public ClientBase<tbb::internal::rml::tbb_client> { + /*override*/void process( job& j ); + /*override*/size_type max_job_count() const { + return TBB_MaxThread-1; + } +}; + +class OMP_Client: public ClientBase<__kmp::rml::omp_client> { + /*override*/void process( job&, void* cookie, omp_client::size_type ); + /*override*/size_type max_job_count() const { + return OMP_MaxThread-1; + } +}; + +// A global instance of ChangeCurrentDir should be declared before TBB_RunTime and OMP_RunTime +// since we want to change current directory before opening factory +ChangeCurrentDir Changer; +RunTime<tbb::internal::rml::tbb_factory, TBB_Client> TBB_RunTime; +RunTime<__kmp::rml::omp_factory, OMP_Client> OMP_RunTime; + +template<typename Factory, typename Client> +void RunTime<Factory,Client>::create_connection() { + client = new Client; + typename Factory::status_type status = factory.make_server( server, *client ); + ASSERT( status==Factory::st_success, NULL ); +#if _WIN32||_WIN64 + server->register_master( me ); +#endif /* _WIN32||_WIN64 */ +} + +template<typename Factory, typename Client> +void RunTime<Factory,Client>::destroy_connection() { +#if _WIN32||_WIN64 + server->unregister_master( me ); +#endif /* _WIN32||_WIN64 */ + server->request_close_connection(); + server = NULL; +} + +class OMP_Team { +public: + OMP_Team( __kmp::rml::omp_server& ) {} + tbb::atomic<unsigned> barrier; +}; + +tbb::atomic<int> AvailWork; +tbb::atomic<int> CompletionCount; + +void OMPWork() { + tbb::atomic<int> x; + for( x=0; x<2000000; ++x ) { + continue; + } +} + +void TBBWork() { + if( AvailWork>=0 ) { + int k = --AvailWork; + if( k==-1 ) { + TBB_RunTime.server->adjust_job_count_estimate(-(TBB_MaxThread-1)); + ++CompletionCount; + } else if( k>=0 ) { + for( int k=0; k<4; ++k ) { + OMP_Team team( *OMP_RunTime.server ); + int n = OMP_RunTime.server->try_increase_load( OMP_ParallelRegionSize-1, /*strict=*/false ); + team.barrier = 0; + ::rml::job* array[OMP_ParallelRegionSize-1]; + if( n>0) + OMP_RunTime.server->get_threads( n, &team, array ); + // Master does work inside parallel region too. + OMPWork(); + // Master waits for workers to finish + if( n>0 ) + while( team.barrier!=unsigned(n) ) { + __TBB_Yield(); + } + } + ++CompletionCount; + } + } +} + +/*override*/void TBB_Client::process( job& ) { + TotalThreadLevel.change_level(1); + TBBWork(); + TotalThreadLevel.change_level(-1); +} + +/*override*/void OMP_Client::process( job& /* j */, void* cookie, omp_client::size_type ) { + TotalThreadLevel.change_level(1); + ASSERT( OMP_RunTime.server, NULL ); + OMPWork(); + ASSERT( OMP_RunTime.server, NULL ); + static_cast<OMP_Team*>(cookie)->barrier+=1; + TotalThreadLevel.change_level(-1); +} + +void TBBOutSideOpenMPInside() { + TotalThreadLevel.change_level(1); + CompletionCount = 0; + int tbbtasks = 32; + AvailWork = tbbtasks; + TBB_RunTime.server->adjust_job_count_estimate(TBB_MaxThread-1); + while( CompletionCount!=tbbtasks+1 ) { + TBBWork(); + } + TotalThreadLevel.change_level(-1); +} + +int TestMain () { + for( int TBB_MaxThread=MinThread; TBB_MaxThread<=MaxThread; ++TBB_MaxThread ) { + REMARK("Testing with TBB_MaxThread=%d\n", TBB_MaxThread); + TBB_RunTime.create_connection(); + OMP_RunTime.create_connection(); + TBBOutSideOpenMPInside(); + OMP_RunTime.destroy_connection(); + TBB_RunTime.destroy_connection(); + } + TotalThreadLevel.dump(); + return Harness::Done; +} diff --git a/src/tbb/src/rml/test/test_rml_omp.cpp b/src/tbb/src/rml/test/test_rml_omp.cpp new file mode 100644 index 0000000..47364bc --- /dev/null +++ b/src/tbb/src/rml/test/test_rml_omp.cpp @@ -0,0 +1,196 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "rml_omp.h" + +typedef __kmp::rml::omp_server MyServer; +typedef __kmp::rml::omp_factory MyFactory; + +// Forward declaration for the function used in test_server.h +void DoClientSpecificVerification( MyServer& , int ); + +#define HARNESS_DEFAULT_MIN_THREADS 0 +#include "test_server.h" +#include "tbb/tbb_misc.h" + +static bool StrictTeam; + +class MyTeam { + MyTeam& operator=( const MyTeam& ) ; +public: + struct info_type { + rml::job* job; + bool ran; + info_type() : job(NULL), ran(false) {} + }; + MyTeam( MyServer& /* server */, size_t max_thread_ ) : + max_thread(max_thread_) + { + self_ptr = this; + info = new info_type[max_thread]; + } + ~MyTeam() { + delete[] info; + } + const size_t max_thread; + size_t n_thread; + tbb::atomic<int> barrier; + /** Indexed with 1-origin index */ + info_type* info; + int iteration; + MyTeam* self_ptr; +}; + +class MyClient: public ClientBase<__kmp::rml::omp_client> { +public: + MyServer* server; + /*override*/void process( job& j, void* cookie, size_type index ) { + MyTeam& t = *static_cast<MyTeam*>(cookie); + ASSERT( t.self_ptr==&t, "trashed cookie" ); + ASSERT( index<t.max_thread, NULL ); + ASSERT( !t.info[index].ran, "duplicate index?" ); + t.info[index].job = &j; + t.info[index].ran = true; + do_process(j); + if( index==1 && nesting.level<nesting.limit ) { + DoOneConnection<MyFactory,MyClient> doc(MaxThread,Nesting(nesting.level+1,nesting.limit),0,false); + doc(0); + } +#if _WIN32||_WIN64 + // test activate/deactivate + if( t.n_thread>1 && t.n_thread%2==0 ) { + if( nesting.level==0 ) { + if( index&1 ) { + size_type target = index-1; + ASSERT( target<t.max_thread, NULL ); + // wait until t.info[target].job is defined + tbb::internal::spin_wait_until_eq( t.info[target].ran, true ); + server->try_increase_load( 1, true ); + server->reactivate( t.info[target].job ); + } else { + server->deactivate( &j ); + } + } + } +#endif /* _WIN32||_WIN64 */ + ++t.barrier; + } + static const bool is_omp = true; + bool is_strict() const {return StrictTeam;} +}; + +void FireUpJobs( MyServer& server, MyClient& client, int max_thread, int n_extra, Checker* checker ) { + ASSERT( max_thread>=0, NULL ); +#if _WIN32||_WIN64 + ::rml::server::execution_resource_t me; + server.register_master( me ); +#endif /* _WIN32||_WIN64 */ + client.server = &server; + MyTeam team(server,size_t(max_thread)); + MyServer::size_type n_thread = 0; + for( int iteration=0; iteration<4; ++iteration ) { + for( size_t i=0; i<team.max_thread; ++i ) + team.info[i].ran = false; + switch( iteration ) { + default: + n_thread = int(max_thread); + break; + case 1: + // No change in number of threads + break; + case 2: + // Decrease number of threads. + n_thread = int(max_thread)/2; + break; + // Case 3 is same code as the default, but has effect of increasing the number of threads. + } + team.barrier = 0; + REMARK("client %d: server.run with n_thread=%d\n", client.client_id(), int(n_thread) ); + server.independent_thread_number_changed( n_extra ); + if( checker ) { + // Give RML time to respond to change in number of threads. + MilliSleep(1); + } + int n_delivered = server.try_increase_load( n_thread, StrictTeam ); + ASSERT( !StrictTeam || n_delivered==int(n_thread), "server failed to satisfy strict request" ); + if( n_delivered<0 ) { + REMARK( "client %d: oversubscription occurred (by %d)\n", client.client_id(), -n_delivered ); + server.independent_thread_number_changed( -n_extra ); + n_delivered = 0; + } else { + team.n_thread = n_delivered; + ::rml::job* job_array[JobArraySize]; + job_array[n_delivered] = (::rml::job*)intptr_t(-1); + server.get_threads( n_delivered, &team, job_array ); + __TBB_ASSERT( job_array[n_delivered]== (::rml::job*)intptr_t(-1), NULL ); + for( int i=0; i<n_delivered; ++i ) { + MyJob* j = static_cast<MyJob*>(job_array[i]); + int s = j->state; + ASSERT( s==MyJob::idle||s==MyJob::busy, NULL ); + } + server.independent_thread_number_changed( -n_extra ); + REMARK("client %d: team size is %d\n", client.client_id(), n_delivered); + if( checker ) { + checker->check_number_of_threads_delivered( n_delivered, n_thread, n_extra ); + } + // Protocol requires that master wait until workers have called "done_processing" + while( team.barrier!=n_delivered ) { + ASSERT( team.barrier>=0, NULL ); + ASSERT( team.barrier<=n_delivered, NULL ); + __TBB_Yield(); + } + REMARK("client %d: team completed\n", client.client_id() ); + for( int i=0; i<n_delivered; ++i ) { + ASSERT( team.info[i].ran, "thread on team allegedly delivered, but did not run?" ); + } + } + for( MyServer::size_type i=n_delivered; i<MyServer::size_type(max_thread); ++i ) { + ASSERT( !team.info[i].ran, "thread on team ran with illegal index" ); + } + } +#if _WIN32||_WIN64 + server.unregister_master( me ); +#endif +} + +void DoClientSpecificVerification( MyServer& server, int /*n_thread*/ ) +{ + ASSERT( server.current_balance()==int(tbb::internal::AvailableHwConcurrency())-1, NULL ); +} + +int TestMain () { + StrictTeam = true; + VerifyInitialization<MyFactory,MyClient>( MaxThread ); + SimpleTest<MyFactory,MyClient>(); + + StrictTeam = false; + VerifyInitialization<MyFactory,MyClient>( MaxThread ); + SimpleTest<MyFactory,MyClient>(); + + return Harness::Done; +} diff --git a/src/tbb/src/rml/test/test_rml_omp_c_linkage.c b/src/tbb/src/rml/test/test_rml_omp_c_linkage.c new file mode 100644 index 0000000..285001c --- /dev/null +++ b/src/tbb/src/rml/test/test_rml_omp_c_linkage.c @@ -0,0 +1,34 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +void Cplusplus(); + +int main() { + Cplusplus(); + return 0; +} diff --git a/src/tbb/src/rml/test/test_rml_tbb.cpp b/src/tbb/src/rml/test/test_rml_tbb.cpp new file mode 100644 index 0000000..cebd85d --- /dev/null +++ b/src/tbb/src/rml/test/test_rml_tbb.cpp @@ -0,0 +1,201 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "rml_tbb.h" + +typedef tbb::internal::rml::tbb_server MyServer; +typedef tbb::internal::rml::tbb_factory MyFactory; + +// Forward declaration of the function used in test_server.h +void DoClientSpecificVerification( MyServer&, int ); + +#define HARNESS_DEFAULT_MIN_THREADS 0 +#include "test_server.h" + +tbb::atomic<int> n_available_hw_threads; + +class MyClient: public ClientBase<tbb::internal::rml::tbb_client> { + tbb::atomic<int> counter; + tbb::atomic<int> gate; + /*override*/void process( job& j ) { + do_process(j); + //wait until the gate is open. + while( gate==0 ) + MilliSleep(1); + + __TBB_ASSERT( nesting.limit<=2, NULL ); + if( nesting.level>=nesting.limit ) + return; + + size_type max_outstanding_connections = max_job_count(); // if nesting.level==0 + if( nesting.level==1 ) + max_outstanding_connections *= (1+max_outstanding_connections); + + if( default_concurrency()<=max_outstanding_connections+2 ) + // i.e., if it is not guaranteed that at least two connections may be made without depleting the_balance + return; + + // at this point, ( nesting.level<nesting.limit ) && ( my_server->default_concurrency()-max_outstanding_connections>2 ) + for( ;; ) { + while( n_available_hw_threads<=1 ) + MilliSleep(1); + + int n = --n_available_hw_threads; + if( n>0 ) break; + // else I lost + ++n_available_hw_threads; + } + + DoOneConnection<MyFactory,MyClient> doc(max_job_count(),Nesting(nesting.level+1,nesting.limit),0,false); + doc(0); + + ++n_available_hw_threads; + } +public: + MyClient() {counter=1;} + static const bool is_omp = false; + bool is_strict() const {return false;} + void open_the_gate() { gate = 1; } + void close_the_gate() { gate = 0; } +}; + +void FireUpJobs( MyServer& server, MyClient& client, int n_thread, int n_extra, Checker* checker ) { + REMARK("client %d: calling adjust_job_count_estimate(%d)\n", client.client_id(),n_thread); + // Exercise independent_thread_number_changed, even for zero values. + server.independent_thread_number_changed( n_extra ); +#if _WIN32||_WIN64 + ::rml::server::execution_resource_t me; + server.register_master( me ); +#endif /* _WIN32||_WIN64 */ + // Experiments indicate that when oversubscribing, the main thread should wait a little + // while for the RML worker threads to do some work. + if( checker ) { + // Give RML time to respond to change in number of threads. + MilliSleep(1); + for( int k=0; k<n_thread; ++k ) + client.job_array[k].processing_count = 0; + } + //close the gate to keep worker threads from returning to RML until a snapshot is taken + client.close_the_gate(); + server.adjust_job_count_estimate( n_thread ); + int n_used = 0; + if( checker ) { + MilliSleep(100); + for( int k=0; k<n_thread; ++k ) + if( client.job_array[k].processing_count ) + ++n_used; + } + // open the gate + client.open_the_gate(); + // Logic further below presumes that jobs never starve, so undo previous call + // to independent_thread_number_changed before waiting on those jobs. + server.independent_thread_number_changed( -n_extra ); + REMARK("client %d: wait for each job to be processed at least once\n",client.client_id()); + // Calculate the number of jobs that are expected to get threads. + int expected = n_thread; + // Wait for expected number of jobs to be processed. +#if RML_USE_WCRM + int default_concurrency = server.default_concurrency(); + if( N_TestConnections>0 ) { + if( default_concurrency+1>=8 && n_thread<=3 && N_TestConnections<=3 && (default_concurrency/int(N_TestConnections)-1)>=n_thread ) { +#endif /* RML_USE_WCRM */ + for(;;) { + int n = 0; + for( int k=0; k<n_thread; ++k ) + if( client.job_array[k].processing_count!=0 ) + ++n; + if( n>=expected ) break; + server.yield(); + } +#if RML_USE_WCRM + } else if( n_thread>0 ) { + for( int m=0; m<20; ++m ) { + int n = 0; + for( int k=0; k<n_thread; ++k ) + if( client.job_array[k].processing_count!=0 ) + ++n; + if( n>=expected ) break; + MilliSleep(1); + } + } + } +#endif /* RML_USE_WCRM */ + server.adjust_job_count_estimate(-n_thread); +#if _WIN32||_WIN64 + server.unregister_master( me ); +#endif + // Give RML some time to respond + if( checker ) { + MilliSleep(1); + checker->check_number_of_threads_delivered( n_used, n_thread, n_extra ); + } +} + +void DoClientSpecificVerification( MyServer&, int n_thread ) +{ + MyClient* client = new MyClient; + client->initialize( n_thread, Nesting(), ClientStackSize[0] ); + MyFactory factory; + memset( &factory, 0, sizeof(factory) ); + MyFactory::status_type status = factory.open(); + ASSERT( status!=MyFactory::st_not_found, "could not find RML library" ); + ASSERT( status!=MyFactory::st_incompatible, NULL ); + ASSERT( status==MyFactory::st_success, NULL ); + MyFactory::server_type* server; + status = factory.make_server( server, *client ); + ASSERT( status==MyFactory::st_success, NULL ); + client->set_server( server ); + client->expect_close_connection = true; + server->request_close_connection(); + // Client deletes itself when it sees call to acknowledge_close_connection from server. + factory.close(); +} + +void Initialize() +{ + MyClient* client = new MyClient; + client->initialize( 1, Nesting(), ClientStackSize[0] ); + MyFactory factory; + memset( &factory, 0, sizeof(factory) ); + factory.open(); + MyFactory::server_type* server; + factory.make_server( server, *client ); + client->set_server( server ); + n_available_hw_threads = server->default_concurrency(); + client->expect_close_connection = true; + server->request_close_connection(); + // Client deletes itself when it sees call to acknowledge_close_connection from server. + factory.close(); +} + +int TestMain () { + VerifyInitialization<MyFactory,MyClient>( MaxThread ); + Initialize(); + SimpleTest<MyFactory,MyClient>(); + return Harness::Done; +} diff --git a/src/tbb/src/rml/test/test_server.h b/src/tbb/src/rml/test/test_server.h new file mode 100644 index 0000000..40afc77 --- /dev/null +++ b/src/tbb/src/rml/test/test_server.h @@ -0,0 +1,452 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* This header contains code shared by test_omp_server.cpp and test_tbb_server.cpp + There is no ifndef guard - test is supposed to include this file exactly once. + The test is also exected to have #include of rml_omp.h or rml_tbb.h before + including this header. + + This header should not use any parts of TBB that require linking in the TBB run-time. + It uses a few instances of tbb::atomic<T>, all of which are completely inlined. */ + +#include "tbb/atomic.h" +#include "tbb/tbb_thread.h" +#include "harness.h" +#include "harness_memory.h" +#include "harness_concurrency_tracker.h" + +//! Define TRIVIAL as 1 to test only a single client, no nesting, no extra threads. +#define TRIVIAL 0 + +//! Maximum number of clients +#if TRIVIAL +const size_t MaxClient = 1; +#else +const size_t MaxClient = 4; +#endif + +const size_t ClientStackSize[MaxClient] = { + 1000000 +#if !TRIVIAL + ,2000000 + ,1000000 + ,4000000 +#endif /* TRIVIAL */ +}; + +const size_t OverheadStackSize = 500000; + +const size_t JobArraySize = 1000; + +static bool TestSingleConnection; + +static size_t N_TestConnections; + +#if _WIN32||_WIN64 +#include <Windows.h> /* Need Sleep */ +#else +#include <unistd.h> /* Need usleep */ +#endif + +void MilliSleep( unsigned milliseconds ) { +#if _WIN32||_WIN64 + Sleep( milliseconds ); +#else + usleep( milliseconds*1000 ); +#endif /* _WIN32||_WIN64 */ +} + +class MyJob: public ::rml::job { +public: + //! Enumeration for tracking states of a job. + enum state_t { + //! Job has not yet been allocated. + unallocated, + //! Is idle. + idle, + //! Has a thread working on it. + busy, + //! After call to client::cleanup + clean + }; + tbb::atomic<int> state; + tbb::atomic<int> processing_count; + void update( state_t new_state, state_t old_state ) { + int o = state.compare_and_swap(new_state,old_state); + ASSERT( o==old_state, "illegal transition" ); + } + void update_from_either( state_t new_state, state_t old_state1, state_t old_state2 ) { + int snapshot; + do { + snapshot = state; + ASSERT( snapshot==old_state1||snapshot==old_state2, "illegal transition" ); + } while( state.compare_and_swap(new_state,snapshot)!=snapshot ); + } + MyJob() { + state=unallocated; + processing_count=0; + } + ~MyJob() { + // Overwrite so that accidental use after destruction can be detected. + memset(this,-1,sizeof(*this)); + } +}; + +static tbb::atomic<int> ClientConstructions; +static tbb::atomic<int> ClientDestructions; + +struct Nesting { + int level; + int limit; + Nesting() : level(0), limit(0) {} + Nesting( int level_, int limit_ ) : level(level_), limit(limit_) {} +}; + +template<typename Client> +class ClientBase: public Client { +protected: + typedef typename Client::size_type size_type; + typedef typename Client::version_type version_type; + typedef typename Client::policy_type policy_type; + typedef typename Client::job job; +private: + size_type my_max_job_count; + size_t my_stack_size; + tbb::atomic<size_t> next_job_index; + int my_client_id; + rml::server* my_server; + +public: + enum state_t { + //! Treat *this as constructed. + live=0x1, + //! Treat *this as destroyed. + destroyed=0xDEAD + }; + + tbb::atomic<int> state; + void update( state_t new_state, state_t old_state ) { + int o = state.compare_and_swap(new_state,old_state); + ASSERT( o==old_state, NULL ); + } + + tbb::atomic<bool> expect_close_connection; + + MyJob *job_array; + + /*override*/version_type version() const { + ASSERT( state==live, NULL ); + return 1; + } + + /*override*/size_type max_job_count() const { + ASSERT( state==live, NULL ); + return my_max_job_count; + } + + /*override*/size_t min_stack_size() const { + ASSERT( state==live, NULL ); + return my_stack_size; + } + + /*override*/policy_type policy() const {return Client::throughput;} + + /*override*/void acknowledge_close_connection() { + ASSERT( expect_close_connection, NULL ); + for( size_t k=next_job_index; k>0; ) { + --k; + ASSERT( job_array[k].state==MyJob::clean, NULL ); + } + delete[] job_array; + job_array = NULL; + ASSERT( my_server, NULL ); + update( destroyed, live ); + delete this; + } + + /*override*/void cleanup( job& j_ ) { + REMARK("client %d: cleanup(%p) called\n",client_id(),&j_); + ASSERT( state==live, NULL ); + MyJob& j = static_cast<MyJob&>(j_); + while( j.state==MyJob::busy ) + my_server->yield(); + j.update(MyJob::clean,MyJob::idle); + REMARK("client %d: cleanup(%p) returns\n",client_id(),&j_); + } + + job* create_one_job(); + +protected: + void do_process( job& j_ ) { + ASSERT( state==live, NULL ); + MyJob& j = static_cast<MyJob&>(j_); + ASSERT( &j, NULL ); + j.update(MyJob::busy,MyJob::idle); + // use of the plain addition (not the atomic increment) is intentonial + j.processing_count = j.processing_count + 1; + ASSERT( my_stack_size>OverheadStackSize, NULL ); +#ifdef __ia64__ + // Half of the stack is reserved for RSE, so test only remaining half. + UseStackSpace( (my_stack_size-OverheadStackSize)/2 ); +#else + UseStackSpace( my_stack_size-OverheadStackSize ); +#endif + j.update(MyJob::idle,MyJob::busy); + my_server->yield(); + } +public: + ClientBase() : my_server(NULL) { + my_client_id = ClientConstructions++; + next_job_index = 0; + } + int client_id() const {return my_client_id;} + + Nesting nesting; + + void initialize( size_type max_job_count, Nesting nesting_, size_t stack_size ) { + ASSERT( stack_size>0, NULL ); + my_max_job_count = max_job_count; + nesting = nesting_; + my_stack_size = stack_size; + job_array = new MyJob[JobArraySize]; + expect_close_connection = false; + state = live; + } + + void set_server( rml::server* s ) {my_server=s;} + + unsigned default_concurrency() const { ASSERT( my_server, NULL); return my_server->default_concurrency(); } + + virtual ~ClientBase() { + ASSERT( state==destroyed, NULL ); + ++ClientDestructions; + } +}; + +template<typename Client> +typename Client::job* ClientBase<Client>::create_one_job() { + REMARK("client %d: create_one_job() called\n",client_id()); + size_t k = next_job_index++; + ASSERT( state==live, NULL ); + // Following assertion depends on assumption that implementation does not destroy jobs until + // the connection is closed. If the implementation is changed to destroy jobs sooner, the + // test logic in this header will have to be reworked. + ASSERT( k<my_max_job_count, "RML allocated more than max_job_count jobs simultaneously" ); + ASSERT( k<JobArraySize, "JobArraySize not big enough (problem is in test, not RML)" ); + MyJob& j = job_array[k]; + j.update(MyJob::idle,MyJob::unallocated); + REMARK("client %d: create_one_job() for k=%d returns %p\n",client_id(),int(k),&j); + return &j; +} + +struct warning_tracker { + tbb::atomic<int> n_more_than_available; + tbb::atomic<int> n_too_many_threads; + tbb::atomic<int> n_system_overload; + warning_tracker() { + n_more_than_available = 0; + n_too_many_threads = 0; + n_system_overload = 0; + } + bool all_set() { return n_more_than_available>0 && n_too_many_threads>0 && n_system_overload>0; } +} tracker; + +class Checker { +public: + int default_concurrency; + void check_number_of_threads_delivered( int n_delivered, int n_requested, int n_extra ) const; + Checker( rml::server& server ) : default_concurrency(int(server.default_concurrency())) {} +}; + +void Checker::check_number_of_threads_delivered( int n_delivered, int n_requested, int n_extra ) const { + ASSERT( default_concurrency>=0, NULL ); + if( tracker.all_set() ) return; + // Check that number of threads delivered is reasonable. + int n_avail = default_concurrency; + if( n_extra>0 ) + n_avail-=n_extra; + if( n_avail<0 ) + n_avail=0; + if( n_requested>default_concurrency ) + n_avail += n_requested-default_concurrency; + int n_expected = n_requested; + if( n_expected>n_avail ) + n_expected=n_avail; + const char* msg = NULL; + if( n_delivered>n_avail ) { + if( ++tracker.n_more_than_available>1 ) + return; + msg = "server delivered more threads than were theoretically available"; + } else if( n_delivered>n_expected ) { + if( ++tracker.n_too_many_threads>1 ) + return; + msg = "server delivered more threads than expected"; + } else if( n_delivered<n_expected ) { + if( ++tracker.n_system_overload>1 ) + return; + msg = "server delivered fewer threads than ideal; or, the system is overloaded?"; + } + if( msg ) { + REPORT("Warning: %s (n_delivered=%d n_avail=%d n_requested=%d n_extra=%d default_concurrency=%d)\n", + msg, n_delivered, n_avail, n_requested, n_extra, default_concurrency ); + } +} + +template<typename Factory,typename Client> +class DoOneConnection: NoAssign { + //! Number of threads to request + const int n_thread; + //! Nesting + const Nesting nesting; + //! Number of extra threads to pretend having outside the RML + const int n_extra; + //! If true, check number of threads actually delivered. + const bool check_delivered; +public: + DoOneConnection( int n_thread_, Nesting nesting_, int n_extra_, bool check_delivered_ ) : + n_thread(n_thread_), + nesting(nesting_), + n_extra(n_extra_), + check_delivered(check_delivered_) + { + } + + //! Test ith connection + void operator()( size_t i ) const; +}; + +template<typename Factory,typename Client> +void DoOneConnection<Factory,Client>::operator()( size_t i ) const { + ASSERT( i<MaxClient, NULL ); + Client* client = new Client; + client->initialize( Client::is_omp ? JobArraySize : n_thread, nesting, ClientStackSize[i] ); + Factory factory; + memset( &factory, 0, sizeof(factory) ); + typename Factory::status_type status = factory.open(); + ASSERT( status==Factory::st_success, NULL ); + + typename Factory::server_type* server; + status = factory.make_server( server, *client ); + ASSERT( status==Factory::st_success, NULL ); + Harness::ConcurrencyTracker ct; + REMARK("client %d: opened server n_thread=%d nesting=(%d,%d)\n", + client->client_id(), n_thread, nesting.level, nesting.limit); + client->set_server( server ); + Checker checker( *server ); + + FireUpJobs( *server, *client, n_thread, n_extra, check_delivered && !client->is_strict() ? &checker : NULL ); + + // Close the connection + client->expect_close_connection = true; + REMARK("client %d: calling request_close_connection\n", client->client_id()); +#if !RML_USE_WCRM + int default_concurrency = server->default_concurrency(); +#endif + server->request_close_connection(); + // Client deletes itself when it sees call to acknowledge_close_connection from server. + factory.close(); +#if !RML_USE_WCRM + if( TestSingleConnection ) + __TBB_ASSERT_EX( uintptr_t(factory.scratch_ptr)==uintptr_t(default_concurrency), "under/over subscription?" ); +#endif +} + +//! Test with n_threads threads and n_client clients. +template<typename Factory, typename Client> +void SimpleTest() { + Harness::ConcurrencyTracker::Reset(); + TestSingleConnection = true; + N_TestConnections = 1; + for( int n_thread=MinThread; n_thread<=MaxThread; ++n_thread ) { + // Test a single connection, no nesting, no extra threads + DoOneConnection<Factory,Client> doc(n_thread,Nesting(0,0),0,false); + doc(0); + } +#if !TRIVIAL + TestSingleConnection = false; + for( int n_thread=MinThread; n_thread<=MaxThread; ++n_thread ) { + // Test parallel connections + for( int n_client=1; n_client<=int(MaxClient); ++n_client ) { + N_TestConnections = n_client; + REMARK("SimpleTest: n_thread=%d n_client=%d\n",n_thread,n_client); + NativeParallelFor( n_client, DoOneConnection<Factory,Client>(n_thread,Nesting(0,0),0,false) ); + } + // Test server::independent_thread_number_changed + N_TestConnections = 1; + for( int n_extra=-4; n_extra<=32; n_extra=n_extra+1+n_extra/5 ) { + DoOneConnection<Factory,Client> doc(n_thread,Nesting(0,0),n_extra,true); + doc(0); + } +#if !RML_USE_WCRM + // Test nested connections + DoOneConnection<Factory,Client> doc(n_thread,Nesting(0,2),0,false); + doc(0); +#endif + } + ASSERT( Harness::ConcurrencyTracker::PeakParallelism()>1, "No multiple connections exercised?" ); +#endif /* !TRIVIAL */ + // Let RML catch up. + while( ClientConstructions!=ClientDestructions ) + MilliSleep(1); +} + +static void check_server_info( void* arg, const char* server_info ) +{ + ASSERT( strstr(server_info, (char*)arg), NULL ); +} + +template<typename Factory, typename Client> +void VerifyInitialization( int n_thread ) { + Client* client = new Client; + client->initialize( Client::is_omp ? JobArraySize : n_thread, Nesting(), ClientStackSize[0] ); + Factory factory; + memset( &factory, 0, sizeof(factory) ); + typename Factory::status_type status = factory.open(); + ASSERT( status!=Factory::st_not_found, "could not find RML library" ); + ASSERT( status!=Factory::st_incompatible, NULL ); + ASSERT( status==Factory::st_success, NULL ); + factory.call_with_server_info( check_server_info, (void*)"Intel(R) RML library" ); + typename Factory::server_type* server; + status = factory.make_server( server, *client ); + ASSERT( status!=Factory::st_incompatible, NULL ); + ASSERT( status!=Factory::st_not_found, NULL ); + ASSERT( status==Factory::st_success, NULL ); + REMARK("client %d: opened server n_thread=%d nesting=(%d,%d)\n", + client->client_id(), n_thread, 0, 0); + ASSERT( server, NULL ); + client->set_server( server ); + + DoClientSpecificVerification( *server, n_thread ); + + // Close the connection + client->expect_close_connection = true; + REMARK("client %d: calling request_close_connection\n", client->client_id()); + server->request_close_connection(); + // Client deletes itself when it sees call to acknowledge_close_connection from server. + factory.close(); +} diff --git a/src/tbb/src/rml/test/test_thread_monitor.cpp b/src/tbb/src/rml/test/test_thread_monitor.cpp new file mode 100644 index 0000000..5b0453c --- /dev/null +++ b/src/tbb/src/rml/test/test_thread_monitor.cpp @@ -0,0 +1,119 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "thread_monitor.h" +#include "harness.h" +#include "harness_memory.h" +#include "tbb/semaphore.cpp" + +class ThreadState { + void loop(); +public: + static __RML_DECL_THREAD_ROUTINE routine( void* arg ) { + static_cast<ThreadState*>(arg)->loop(); + return 0; + } + typedef rml::internal::thread_monitor thread_monitor; + thread_monitor monitor; + volatile int request; + volatile int ack; + volatile unsigned clock; + volatile unsigned stamp; + ThreadState() : request(-1), ack(-1), clock(0) {} +}; + +void ThreadState::loop() { + for(;;) { + ++clock; + if( ack==request ) { + thread_monitor::cookie c; + monitor.prepare_wait(c); + if( ack==request ) { + REMARK("%p: request=%d ack=%d\n", this, request, ack ); + monitor.commit_wait(c); + } else + monitor.cancel_wait(); + } else { + // Throw in delay occasionally + switch( request%8 ) { + case 0: + case 1: + case 5: + rml::internal::thread_monitor::yield(); + } + int r = request; + ack = request; + if( !r ) return; + } + } +} + +// Linux on IA-64 seems to require at least 1<<18 bytes per stack. +const size_t MinStackSize = 1<<18; +const size_t MaxStackSize = 1<<22; + +int TestMain () { + for( int p=MinThread; p<=MaxThread; ++p ) { + ThreadState* t = new ThreadState[p]; + for( size_t stack_size = MinStackSize; stack_size<=MaxStackSize; stack_size*=2 ) { + REMARK("launching %d threads\n",p); + for( int i=0; i<p; ++i ) + rml::internal::thread_monitor::launch( ThreadState::routine, t+i, stack_size ); + for( int k=1000; k>=0; --k ) { + if( k%8==0 ) { + // Wait for threads to wait. + for( int i=0; i<p; ++i ) { + unsigned count = 0; + do { + t[i].stamp = t[i].clock; + rml::internal::thread_monitor::yield(); + if( ++count>=1000 ) { + REPORT("Warning: thread %d not waiting\n",i); + break; + } + } while( t[i].stamp!=t[i].clock ); + } + } + REMARK("notifying threads\n"); + for( int i=0; i<p; ++i ) { + // Change state visible to launched thread + t[i].request = k; + t[i].monitor.notify(); + } + REMARK("waiting for threads to respond\n"); + for( int i=0; i<p; ++i ) + // Wait for thread to respond + while( t[i].ack!=k ) + rml::internal::thread_monitor::yield(); + } + } + delete[] t; + } + + return Harness::Done; +} diff --git a/src/tbb/src/tbb/arena.cpp b/src/tbb/src/tbb/arena.cpp new file mode 100644 index 0000000..c516bcb --- /dev/null +++ b/src/tbb/src/tbb/arena.cpp @@ -0,0 +1,456 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "arena.h" +#include "governor.h" +#include "scheduler.h" +#include "itt_notify.h" + +#if !__TBB_CPU_CTL_ENV_PRESENT +inline void __TBB_get_cpu_ctl_env ( __TBB_cpu_ctl_env_t* ctl ) { fegetenv(ctl); } +inline void __TBB_set_cpu_ctl_env ( const __TBB_cpu_ctl_env_t* ctl ) { fesetenv(ctl); } +#endif /* !__TBB_CPU_CTL_ENV_PRESENT */ + +#include <functional> + +#if __TBB_STATISTICS_STDOUT +#include <cstdio> +#endif + +namespace tbb { +namespace internal { + +void arena::process( generic_scheduler& s ) { + __TBB_ASSERT( is_alive(my_guard), NULL ); + __TBB_ASSERT( governor::is_set(&s), NULL ); + __TBB_ASSERT( !s.my_innermost_running_task, NULL ); + __TBB_ASSERT( !s.my_dispatching_task, NULL ); + + __TBB_ASSERT( my_num_slots != 1, NULL ); + // Start search for an empty slot from the one we occupied the last time + unsigned index = s.my_arena_index < my_num_slots ? s.my_arena_index : s.my_random.get() % (my_num_slots - 1) + 1, + end = index; + __TBB_ASSERT( index != 0, "A worker cannot occupy slot 0" ); + __TBB_ASSERT( index < my_num_slots, NULL ); + + // Find a vacant slot + for ( ;; ) { + if ( !my_slots[index].my_scheduler && __TBB_CompareAndSwapW( &my_slots[index].my_scheduler, (intptr_t)&s, 0 ) == 0 ) + break; + if ( ++index == my_num_slots ) + index = 1; + if ( index == end ) { + // Likely this arena is already saturated + goto quit; + } + } + ITT_NOTIFY(sync_acquired, my_slots + index); + s.my_arena = this; + s.my_arena_index = index; +#if __TBB_TASK_PRIORITY + s.my_local_reload_epoch = my_reload_epoch; + __TBB_ASSERT( !s.my_offloaded_tasks, NULL ); +#endif /* __TBB_TASK_PRIORITY */ + s.attach_mailbox( affinity_id(index+1) ); + + my_slots[index].hint_for_push = index ^ unsigned(&s-(generic_scheduler*)NULL)>>16; // randomizer seed + my_slots[index].hint_for_pop = index; // initial value for round-robin + + __TBB_set_cpu_ctl_env(&my_cpu_ctl_env); + + atomic_update( my_limit, index + 1, std::less<unsigned>() ); + + for ( ;; ) { + // Try to steal a task. + // Passing reference count is technically unnecessary in this context, + // but omitting it here would add checks inside the function. + __TBB_ASSERT( is_alive(my_guard), NULL ); + task* t = s.receive_or_steal_task( s.my_dummy_task->prefix().ref_count, /*return_if_no_work=*/true ); + if (t) { + // A side effect of receive_or_steal_task is that my_innermost_running_task can be set. + // But for the outermost dispatch loop of a worker it has to be NULL. + s.my_innermost_running_task = NULL; + __TBB_ASSERT( !s.my_dispatching_task, NULL ); + s.local_wait_for_all(*s.my_dummy_task,t); + } + __TBB_ASSERT ( __TBB_load_relaxed(my_slots[index].head) == __TBB_load_relaxed(my_slots[index].tail), "Worker cannot leave arena while its task pool is not empty" ); + __TBB_ASSERT( my_slots[index].task_pool == EmptyTaskPool, "Empty task pool is not marked appropriately" ); + // Revalidate quitting condition + // This check prevents relinquishing more than necessary workers because + // of the non-atomicity of the decision making procedure + if ( num_workers_active() >= my_num_workers_allotted || !my_num_workers_requested ) + break; + } +#if __TBB_TASK_PRIORITY + if ( s.my_offloaded_tasks ) { + GATHER_STATISTIC( ++s.my_counters.prio_orphanings ); + ++my_abandonment_epoch; + __TBB_ASSERT( s.my_offloaded_task_list_tail_link && !*s.my_offloaded_task_list_tail_link, NULL ); + task* orphans; + do { + orphans = const_cast<task*>(my_orphaned_tasks); + *s.my_offloaded_task_list_tail_link = orphans; + } while ( __TBB_CompareAndSwapW(&my_orphaned_tasks, (ptrdiff_t)s.my_offloaded_tasks, (ptrdiff_t)orphans) != (ptrdiff_t)orphans ); + s.my_offloaded_tasks = NULL; +#if TBB_USE_ASSERT + s.my_offloaded_task_list_tail_link = NULL; +#endif /* TBB_USE_ASSERT */ + } +#endif /* __TBB_TASK_PRIORITY */ +#if __TBB_STATISTICS + ++s.my_counters.arena_roundtrips; + *my_slots[index].my_counters += s.my_counters; + s.my_counters.reset(); +#endif /* __TBB_STATISTICS */ + __TBB_store_with_release( my_slots[index].my_scheduler, (generic_scheduler*)NULL ); + s.my_inbox.detach(); + __TBB_ASSERT( s.my_inbox.is_idle_state(true), NULL ); + __TBB_ASSERT( !s.my_innermost_running_task, NULL ); + __TBB_ASSERT( !s.my_dispatching_task, NULL ); + __TBB_ASSERT( is_alive(my_guard), NULL ); +quit: + // In contrast to earlier versions of TBB (before 3.0 U5) now it is possible + // that arena may be temporarily left unpopulated by threads. See comments in + // arena::on_thread_leaving() for more details. +#if !__TBB_TRACK_PRIORITY_LEVEL_SATURATION + on_thread_leaving(); +#endif /* !__TBB_TRACK_PRIORITY_LEVEL_SATURATION */ +} + +arena::arena ( market& m, unsigned max_num_workers ) { + __TBB_ASSERT( !my_guard, "improperly allocated arena?" ); + __TBB_ASSERT( sizeof(my_slots[0]) % NFS_GetLineSize()==0, "arena::slot size not multiple of cache line size" ); + __TBB_ASSERT( (uintptr_t)this % NFS_GetLineSize()==0, "arena misaligned" ); +#if __TBB_TASK_PRIORITY + __TBB_ASSERT( !my_reload_epoch && !my_orphaned_tasks && !my_skipped_fifo_priority, "New arena object is not zeroed" ); +#endif /* __TBB_TASK_PRIORITY */ + my_market = &m; + my_limit = 1; + // Two slots are mandatory: for the master, and for 1 worker (required to support starvation resistant tasks). + my_num_slots = num_slots_to_reserve(max_num_workers); + my_max_num_workers = max_num_workers; + my_num_threads_active = 1; // accounts for the master + __TBB_get_cpu_ctl_env(&my_cpu_ctl_env); +#if __TBB_TASK_PRIORITY + my_bottom_priority = my_top_priority = normalized_normal_priority; +#endif /* __TBB_TASK_PRIORITY */ + my_aba_epoch = m.my_arenas_aba_epoch; + __TBB_ASSERT ( my_max_num_workers < my_num_slots, NULL ); + // Construct mailboxes. Mark internal synchronization elements for the tools. + for( unsigned i = 0; i < my_num_slots; ++i ) { + __TBB_ASSERT( !my_slots[i].my_scheduler && !my_slots[i].task_pool, NULL ); + ITT_SYNC_CREATE(my_slots + i, SyncType_Scheduler, SyncObj_WorkerTaskPool); + mailbox(i+1).construct(); + ITT_SYNC_CREATE(&mailbox(i+1), SyncType_Scheduler, SyncObj_Mailbox); +#if __TBB_STATISTICS + my_slots[i].my_counters = new ( NFS_Allocate(sizeof(statistics_counters), 1, NULL) ) statistics_counters; +#endif /* __TBB_STATISTICS */ + } +#if __TBB_TASK_PRIORITY + for ( intptr_t i = 0; i < num_priority_levels; ++i ) { + my_task_stream[i].initialize(my_num_slots); + ITT_SYNC_CREATE(my_task_stream + i, SyncType_Scheduler, SyncObj_TaskStream); + } +#else /* !__TBB_TASK_PRIORITY */ + my_task_stream.initialize(my_num_slots); + ITT_SYNC_CREATE(&my_task_stream, SyncType_Scheduler, SyncObj_TaskStream); +#endif /* !__TBB_TASK_PRIORITY */ + my_mandatory_concurrency = false; +#if __TBB_TASK_GROUP_CONTEXT + my_master_default_ctx = NULL; +#endif +} + +arena& arena::allocate_arena( market& m, unsigned max_num_workers ) { + __TBB_ASSERT( sizeof(base_type) + sizeof(arena_slot) == sizeof(arena), "All arena data fields must go to arena_base" ); + __TBB_ASSERT( sizeof(base_type) % NFS_GetLineSize() == 0, "arena slots area misaligned: wrong padding" ); + __TBB_ASSERT( sizeof(mail_outbox) == NFS_MaxLineSize, "Mailbox padding is wrong" ); + size_t n = allocation_size(max_num_workers); + unsigned char* storage = (unsigned char*)NFS_Allocate( n, 1, NULL ); + // Zero all slots to indicate that they are empty + memset( storage, 0, n ); + return *new( storage + num_slots_to_reserve(max_num_workers) * sizeof(mail_outbox) ) arena(m, max_num_workers); +} + +void arena::free_arena () { + __TBB_ASSERT( is_alive(my_guard), NULL ); + __TBB_ASSERT( !my_num_threads_active, "There are threads in the dying arena" ); + __TBB_ASSERT( !my_num_workers_requested && !my_num_workers_allotted, "Dying arena requests workers" ); + __TBB_ASSERT( my_pool_state == SNAPSHOT_EMPTY || !my_max_num_workers, "Inconsistent state of a dying arena" ); +#if !__TBB_STATISTICS_EARLY_DUMP + GATHER_STATISTIC( dump_arena_statistics() ); +#endif + poison_value( my_guard ); + intptr_t drained = 0; + for ( unsigned i = 1; i <= my_num_slots; ++i ) + drained += mailbox(i).drain(); +#if __TBB_TASK_PRIORITY && TBB_USE_ASSERT + for ( intptr_t i = 0; i < num_priority_levels; ++i ) + __TBB_ASSERT(my_task_stream[i].empty() && my_task_stream[i].drain()==0, "Not all enqueued tasks were executed"); +#elif !__TBB_TASK_PRIORITY + __TBB_ASSERT(my_task_stream.empty() && my_task_stream.drain()==0, "Not all enqueued tasks were executed"); +#endif /* !__TBB_TASK_PRIORITY */ +#if __TBB_COUNT_TASK_NODES + my_market->update_task_node_count( -drained ); +#endif /* __TBB_COUNT_TASK_NODES */ + my_market->release(); +#if __TBB_TASK_GROUP_CONTEXT + __TBB_ASSERT( my_master_default_ctx, "Master thread never entered the arena?" ); + my_master_default_ctx->~task_group_context(); + NFS_Free(my_master_default_ctx); +#endif /* __TBB_TASK_GROUP_CONTEXT */ +#if __TBB_STATISTICS + for( unsigned i = 0; i < my_num_slots; ++i ) + NFS_Free( my_slots[i].my_counters ); +#endif /* __TBB_STATISTICS */ + void* storage = &mailbox(my_num_slots); + __TBB_ASSERT( my_num_threads_active == 0, NULL ); + __TBB_ASSERT( my_pool_state == SNAPSHOT_EMPTY || !my_max_num_workers, NULL ); + this->~arena(); +#if TBB_USE_ASSERT > 1 + memset( storage, 0, allocation_size(my_max_num_workers) ); +#endif /* TBB_USE_ASSERT */ + NFS_Free( storage ); +} + +#if __TBB_STATISTICS +void arena::dump_arena_statistics () { + statistics_counters total; + for( unsigned i = 0; i < my_num_slots; ++i ) { +#if __TBB_STATISTICS_EARLY_DUMP + generic_scheduler* s = my_slots[i].my_scheduler; + if ( s ) + *my_slots[i].my_counters += s->my_counters; +#else + __TBB_ASSERT( !my_slots[i].my_scheduler, NULL ); +#endif + if ( i != 0 ) { + total += *my_slots[i].my_counters; + dump_statistics( *my_slots[i].my_counters, i ); + } + } + dump_statistics( *my_slots[0].my_counters, 0 ); +#if __TBB_STATISTICS_STDOUT +#if !__TBB_STATISTICS_TOTALS_ONLY + printf( "----------------------------------------------\n" ); +#endif + dump_statistics( total, workers_counters_total ); + total += *my_slots[0].my_counters; + dump_statistics( total, arena_counters_total ); +#if !__TBB_STATISTICS_TOTALS_ONLY + printf( "==============================================\n" ); +#endif +#endif /* __TBB_STATISTICS_STDOUT */ +} +#endif /* __TBB_STATISTICS */ + +#if __TBB_TASK_PRIORITY +// TODO: This function seems deserving refactoring +inline bool arena::may_have_tasks ( generic_scheduler* s, arena_slot& slot, bool& tasks_present, bool& dequeuing_possible ) { + suppress_unused_warning(slot); + if ( !s ) { + // This slot is vacant + __TBB_ASSERT( slot.task_pool == EmptyTaskPool, NULL ); + __TBB_ASSERT( slot.tail == slot.head, "Someone is tinkering with a vacant arena slot" ); + return false; + } + dequeuing_possible |= s->worker_outermost_level(); + if ( s->my_pool_reshuffling_pending ) { + // This primary task pool is nonempty and may contain tasks at the current + // priority level. Its owner is winnowing lower priority tasks at the moment. + tasks_present = true; + return true; + } + if ( s->my_offloaded_tasks ) { + tasks_present = true; + if ( s->my_local_reload_epoch < *s->my_ref_reload_epoch ) { + // This scheduler's offload area is nonempty and may contain tasks at the + // current priority level. + return true; + } + } + return false; +} +#endif /* __TBB_TASK_PRIORITY */ + +bool arena::is_out_of_work() { + // TODO: rework it to return at least a hint about where a task was found; better if the task itself. + for(;;) { + pool_state_t snapshot = my_pool_state; + switch( snapshot ) { + case SNAPSHOT_EMPTY: + return true; + case SNAPSHOT_FULL: { + // Use unique id for "busy" in order to avoid ABA problems. + const pool_state_t busy = pool_state_t(&busy); + // Request permission to take snapshot + if( my_pool_state.compare_and_swap( busy, SNAPSHOT_FULL )==SNAPSHOT_FULL ) { + // Got permission. Take the snapshot. + // NOTE: This is not a lock, as the state can be set to FULL at + // any moment by a thread that spawns/enqueues new task. + size_t n = my_limit; + // Make local copies of volatile parameters. Their change during + // snapshot taking procedure invalidates the attempt, and returns + // this thread into the dispatch loop. +#if __TBB_TASK_PRIORITY + intptr_t top_priority = my_top_priority; + uintptr_t reload_epoch = my_reload_epoch; + // Inspect primary task pools first +#endif /* __TBB_TASK_PRIORITY */ + size_t k; + for( k=0; k<n; ++k ) { + if( my_slots[k].task_pool != EmptyTaskPool && + __TBB_load_relaxed(my_slots[k].head) < __TBB_load_relaxed(my_slots[k].tail) ) + { + // k-th primary task pool is nonempty and does contain tasks. + break; + } + } + __TBB_ASSERT( k <= n, NULL ); + bool work_absent = k == n; +#if __TBB_TASK_PRIORITY + // Variable tasks_present indicates presence of tasks at any priority + // level, while work_absent refers only to the current priority. + bool tasks_present = !work_absent || my_orphaned_tasks; + bool dequeuing_possible = false; + if ( work_absent ) { + // Check for the possibility that recent priority changes + // brought some tasks to the current priority level + + uintptr_t abandonment_epoch = my_abandonment_epoch; + // Master thread's scheduler needs special handling as it + // may be destroyed at any moment (workers' schedulers are + // guaranteed to be alive while at least one thread is in arena). + // Have to exclude concurrency with task group state change propagation too. + my_market->my_arenas_list_mutex.lock(); + generic_scheduler *s = my_slots[0].my_scheduler; + if ( s && __TBB_CompareAndSwapW(&my_slots[0].my_scheduler, (intptr_t)LockedMaster, (intptr_t)s) == (intptr_t)s ) { + __TBB_ASSERT( my_slots[0].my_scheduler == LockedMaster && s != LockedMaster, NULL ); + work_absent = !may_have_tasks( s, my_slots[0], tasks_present, dequeuing_possible ); + __TBB_store_with_release( my_slots[0].my_scheduler, s ); + } + my_market->my_arenas_list_mutex.unlock(); + // The following loop is subject to data races. While k-th slot's + // scheduler is being examined, corresponding worker can either + // leave to RML or migrate to another arena. + // But the races are not prevented because all of them are benign. + // First, the code relies on the fact that worker thread's scheduler + // object persists until the whole library is deinitialized. + // Second, in the worst case the races can only cause another + // round of stealing attempts to be undertaken. Introducing complex + // synchronization into this coldest part of the scheduler's control + // flow does not seem to make sense because it both is unlikely to + // ever have any observable performance effect, and will require + // additional synchronization code on the hotter paths. + for( k = 1; work_absent && k < n; ++k ) + work_absent = !may_have_tasks( my_slots[k].my_scheduler, my_slots[k], tasks_present, dequeuing_possible ); + // Preclude premature switching arena off because of a race in the previous loop. + work_absent = work_absent + && !__TBB_load_with_acquire(my_orphaned_tasks) + && abandonment_epoch == my_abandonment_epoch; + } +#endif /* __TBB_TASK_PRIORITY */ + // Test and test-and-set. + if( my_pool_state==busy ) { +#if __TBB_TASK_PRIORITY + bool no_fifo_tasks = my_task_stream[top_priority].empty(); + work_absent = work_absent && (!dequeuing_possible || no_fifo_tasks) + && top_priority == my_top_priority && reload_epoch == my_reload_epoch; +#else + bool no_fifo_tasks = my_task_stream.empty(); + work_absent = work_absent && no_fifo_tasks; +#endif /* __TBB_TASK_PRIORITY */ + if( work_absent ) { +#if __TBB_TASK_PRIORITY + if ( top_priority > my_bottom_priority ) { + if ( my_market->lower_arena_priority(*this, top_priority - 1, top_priority) + && !my_task_stream[top_priority].empty() ) + { + atomic_update( my_skipped_fifo_priority, top_priority, std::less<intptr_t>()); + } + } + else if ( !tasks_present && !my_orphaned_tasks && no_fifo_tasks ) { +#endif /* __TBB_TASK_PRIORITY */ + // save current demand value before setting SNAPSHOT_EMPTY, + // to avoid race with advertise_new_work. + int current_demand = (int)my_max_num_workers; + if( my_pool_state.compare_and_swap( SNAPSHOT_EMPTY, busy )==busy ) { + // This thread transitioned pool to empty state, and thus is + // responsible for telling RML that there is no other work to do. + my_market->adjust_demand( *this, -current_demand ); +#if __TBB_TASK_PRIORITY + // Check for the presence of enqueued tasks "lost" on some of + // priority levels because updating arena priority and switching + // arena into "populated" (FULL) state happen non-atomically. + // Imposing atomicity would require task::enqueue() to use a lock, + // which is unacceptable. + bool switch_back = false; + for ( int p = 0; p < num_priority_levels; ++p ) { + if ( !my_task_stream[p].empty() ) { + switch_back = true; + if ( p < my_bottom_priority || p > my_top_priority ) + my_market->update_arena_priority(*this, p); + } + } + if ( switch_back ) + advertise_new_work</*Spawned*/false>(); +#endif /* __TBB_TASK_PRIORITY */ + return true; + } + return false; +#if __TBB_TASK_PRIORITY + } +#endif /* __TBB_TASK_PRIORITY */ + } + // Undo previous transition SNAPSHOT_FULL-->busy, unless another thread undid it. + my_pool_state.compare_and_swap( SNAPSHOT_FULL, busy ); + } + } + return false; + } + default: + // Another thread is taking a snapshot. + return false; + } + } +} + +#if __TBB_COUNT_TASK_NODES +intptr_t arena::workers_task_node_count() { + intptr_t result = 0; + for( unsigned i = 1; i < my_num_slots; ++i ) { + generic_scheduler* s = my_slots[i].my_scheduler; + if( s ) + result += s->my_task_node_count; + } + return result; +} +#endif /* __TBB_COUNT_TASK_NODES */ + +} // namespace internal +} // namespace tbb diff --git a/src/tbb/src/tbb/arena.h b/src/tbb/src/tbb/arena.h new file mode 100644 index 0000000..485b532 --- /dev/null +++ b/src/tbb/src/tbb/arena.h @@ -0,0 +1,389 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _TBB_arena_H +#define _TBB_arena_H + +#include "tbb/tbb_stddef.h" +#include "tbb/atomic.h" + +#include "tbb/tbb_machine.h" + +#if !__TBB_CPU_CTL_ENV_PRESENT + #include <fenv.h> + typedef fenv_t __TBB_cpu_ctl_env_t; +#endif /* !__TBB_CPU_CTL_ENV_PRESENT */ + +#include "scheduler_common.h" +#include "intrusive_list.h" +#include "task_stream.h" +#include "../rml/include/rml_tbb.h" +#include "mailbox.h" + +namespace tbb { + +class task_group_context; +class allocate_root_with_context_proxy; + +namespace internal { + +class governor; +class arena; +template<typename SchedulerTraits> class custom_scheduler; + +//------------------------------------------------------------------------ +// arena +//------------------------------------------------------------------------ + +class market; + +//! arena data except the array of slots +/** Separated in order to simplify padding. + Intrusive list node base class is used by market to form a list of arenas. **/ +struct arena_base : intrusive_list_node { + //! Market owning this arena + market* my_market; + + //! Maximal currently busy slot. + atomic<unsigned> my_limit; + + //! Number of slots in the arena + unsigned my_num_slots; + + //! Number of workers requested by the master thread owning the arena + unsigned my_max_num_workers; + + //! Number of workers that are currently requested from the resource manager + int my_num_workers_requested; + + //! Number of workers that have been marked out by the resource manager to service the arena + unsigned my_num_workers_allotted; + + //! Number of threads in the arena at the moment + /** Consists of the workers servicing the arena and one master until it starts + arena shutdown and detaches from it. Plays the role of the arena's ref count. **/ + atomic<unsigned> my_num_threads_active; + + //! ABA prevention marker + uintptr_t my_aba_epoch; + + //! FPU control settings of arena's master thread captured at the moment of arena instantiation. + __TBB_cpu_ctl_env_t my_cpu_ctl_env; + +#if __TBB_TRACK_PRIORITY_LEVEL_SATURATION + int my_num_workers_present; +#endif /* __TBB_TRACK_PRIORITY_LEVEL_SATURATION */ + + //! Current task pool state and estimate of available tasks amount. + /** The estimate is either 0 (SNAPSHOT_EMPTY) or infinity (SNAPSHOT_FULL). + Special state is "busy" (any other unsigned value). + Note that the implementation of arena::is_busy_or_empty() requires + my_pool_state to be unsigned. */ + tbb::atomic<uintptr_t> my_pool_state; + +#if __TBB_TASK_GROUP_CONTEXT + //! Default task group context. + /** Used by root tasks allocated directly by the master thread (not from inside + a TBB task) without explicit context specification. **/ + task_group_context* my_master_default_ctx; +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +#if __TBB_TASK_PRIORITY + //! Highest priority of recently spawned or enqueued tasks. + volatile intptr_t my_top_priority; + + //! Lowest normalized priority of available spawned or enqueued tasks. + intptr_t my_bottom_priority; + + //! Tracks events that may bring tasks in offload areas to the top priority level. + /** Incremented when arena top priority changes or a task group priority + is elevated to the current arena's top level. **/ + uintptr_t my_reload_epoch; + + //! List of offloaded tasks abandoned by workers revoked by the market + task* my_orphaned_tasks; + + //! Counter used to track the occurrence of recent orphaning and re-sharing operations. + tbb::atomic<uintptr_t> my_abandonment_epoch; + + //! Task pool for the tasks scheduled via task::enqueue() method + /** Such scheduling guarantees eventual execution even if + - new tasks are constantly coming (by extracting scheduled tasks in + relaxed FIFO order); + - the enqueuing thread does not call any of wait_for_all methods. **/ + task_stream my_task_stream[num_priority_levels]; + + //! Highest priority level containing enqueued tasks + /** It being greater than 0 means that high priority enqueued tasks had to be + bypassed because all workers were blocked in nested dispatch loops and + were unable to progress at then current priority level. **/ + tbb::atomic<intptr_t> my_skipped_fifo_priority; +#else /* !__TBB_TASK_PRIORITY */ + + //! Task pool for the tasks scheduled via task::enqueue() method + /** Such scheduling guarantees eventual execution even if + - new tasks are constantly coming (by extracting scheduled tasks in + relaxed FIFO order); + - the enqueuing thread does not call any of wait_for_all methods. **/ + task_stream my_task_stream; +#endif /* !__TBB_TASK_PRIORITY */ + + //! Indicates if there is an oversubscribing worker created to service enqueued tasks. + bool my_mandatory_concurrency; + +#if TBB_USE_ASSERT + //! Used to trap accesses to the object after its destruction. + uintptr_t my_guard; +#endif /* TBB_USE_ASSERT */ +}; // struct arena_base + +class arena +#if (__GNUC__<4 || __GNUC__==4 && __GNUC_MINOR__==0) && !__INTEL_COMPILER + : public padded<arena_base> +#else + : private padded<arena_base> +#endif +{ +private: + friend class generic_scheduler; + template<typename SchedulerTraits> friend class custom_scheduler; + friend class governor; + + friend class market; + friend class tbb::task_group_context; + friend class allocate_root_with_context_proxy; + friend class intrusive_list<arena>; + + typedef padded<arena_base> base_type; + + //! Constructor + arena ( market&, unsigned max_num_workers ); + + //! Allocate an instance of arena. + static arena& allocate_arena( market&, unsigned max_num_workers ); + + static int unsigned num_slots_to_reserve ( unsigned max_num_workers ) { + return max(2u, max_num_workers + 1); + } + + static int allocation_size ( unsigned max_num_workers ) { + return sizeof(base_type) + num_slots_to_reserve(max_num_workers) * (sizeof(mail_outbox) + sizeof(arena_slot)); + } + +#if __TBB_TASK_GROUP_CONTEXT + //! Finds all contexts affected by the state change and propagates the new state to them. + /** The propagation is relayed to the market because tasks created by one + master thread can be passed to and executed by other masters. This means + that context trees can span several arenas at once and thus state change + propagation cannot be generally localized to one arena only. **/ + template <typename T> + bool propagate_task_group_state ( T task_group_context::*mptr_state, task_group_context& src, T new_state ); +#endif /* __TBB_TASK_GROUP_CONTEXT */ + + //! Get reference to mailbox corresponding to given affinity_id. + mail_outbox& mailbox( affinity_id id ) { + __TBB_ASSERT( 0<id, "affinity id must be positive integer" ); + __TBB_ASSERT( id <= my_num_slots, "affinity id out of bounds" ); + + return ((mail_outbox*)this)[-(int)id]; + } + + //! Completes arena shutdown, destructs and deallocates it. + void free_arena (); + + typedef uintptr_t pool_state_t; + + //! No tasks to steal since last snapshot was taken + static const pool_state_t SNAPSHOT_EMPTY = 0; + + //! At least one task has been offered for stealing since the last snapshot started + static const pool_state_t SNAPSHOT_FULL = pool_state_t(-1); + + //! No tasks to steal or snapshot is being taken. + static bool is_busy_or_empty( pool_state_t s ) { return s < SNAPSHOT_FULL; } + + //! The number of workers active in the arena. + unsigned num_workers_active( ) { + return my_num_threads_active - (my_slots[0].my_scheduler? 1 : 0); + } + + //! If necessary, raise a flag that there is new job in arena. + template<bool Spawned> void advertise_new_work(); + + //! Check if there is job anywhere in arena. + /** Return true if no job or if arena is being cleaned up. */ + bool is_out_of_work(); + + //! Registers the worker with the arena and enters TBB scheduler dispatch loop + void process( generic_scheduler& ); + + //! Notification that worker or master leaves its arena + inline void on_thread_leaving ( bool master = false ); + +#if __TBB_STATISTICS + //! Outputs internal statistics accumulated by the arena + void dump_arena_statistics (); +#endif /* __TBB_STATISTICS */ + +#if __TBB_TASK_PRIORITY + //! Check if recent priority changes may bring some tasks to the current priority level soon + /** /param tasks_present indicates presence of tasks at any priority level. **/ + inline bool may_have_tasks ( generic_scheduler*, arena_slot&, bool& tasks_present, bool& dequeuing_possible ); +#endif /* __TBB_TASK_PRIORITY */ + +#if __TBB_COUNT_TASK_NODES + //! Returns the number of task objects "living" in worker threads + intptr_t workers_task_node_count(); +#endif + + /** Must be the last data field */ + arena_slot my_slots[1]; +}; // class arena + +} // namespace internal +} // namespace tbb + +#include "market.h" +#include "scheduler_common.h" + +namespace tbb { +namespace internal { + +inline void arena::on_thread_leaving ( bool master ) { + // + // Implementation of arena destruction synchronization logic contained various + // bugs/flaws at the different stages of its evolution, so below is a detailed + // description of the issues taken into consideration in the framework of the + // current design. + // + // In case of using fire-and-forget tasks (scheduled via task::enqueue()) + // master thread is allowed to leave its arena before all its work is executed, + // and market may temporarily revoke all workers from this arena. Since revoked + // workers never attempt to reset arena state to EMPTY and cancel its request + // to RML for threads, the arena object is destroyed only when both the last + // thread is leaving it and arena's state is EMPTY (that is its master thread + // left and it does not contain any work). + // + // A worker that checks for work presence and transitions arena to the EMPTY + // state (in snapshot taking procedure arena::is_out_of_work()) updates + // arena::my_pool_state first and only then arena::my_num_workers_requested. + // So the check for work absence must be done against the latter field. + // + // In a time window between decrementing the active threads count and checking + // if there is an outstanding request for workers. New worker thread may arrive, + // finish remaining work, set arena state to empty, and leave decrementing its + // refcount and destroying. Then the current thread will destroy the arena + // the second time. To preclude it a local copy of the outstanding request + // value can be stored before decrementing active threads count. + // + // But this technique may cause two other problem. When the stored request is + // zero, it is possible that arena still has threads and they can generate new + // tasks and thus re-establish non-zero requests. Then all the threads can be + // revoked (as described above) leaving this thread the last one, and causing + // it to destroy non-empty arena. + // + // The other problem takes place when the stored request is non-zero. Another + // thread may complete the work, set arena state to empty, and leave without + // arena destruction before this thread decrements the refcount. This thread + // cannot destroy the arena either. Thus the arena may be "orphaned". + // + // In both cases we cannot dereference arena pointer after the refcount is + // decremented, as our arena may already be destroyed. + // + // If this is the master thread, market can be concurrently destroyed. + // In case of workers market's liveness is ensured by the RML connection + // rundown protocol, according to which the client (i.e. the market) lives + // until RML server notifies it about connection termination, and this + // notification is fired only after all workers return into RML. + // + // Thus if we decremented refcount to zero we ask the market to check arena + // state (including the fact if it is alive) under the lock. + // + uintptr_t aba_epoch = my_aba_epoch; + market* m = my_market; + if ( !--my_num_threads_active ) + market::try_destroy_arena( m, this, aba_epoch, master ); +} + +template<bool Spawned> void arena::advertise_new_work() { + if( !Spawned ) { // i.e. the work was enqueued + if( my_max_num_workers==0 ) { + my_max_num_workers = 1; + my_mandatory_concurrency = true; + my_pool_state = SNAPSHOT_FULL; + my_market->adjust_demand( *this, 1 ); + return; + } + // Local memory fence is required to avoid missed wakeups; see the comment below. + // Starvation resistant tasks require mandatory concurrency, so missed wakeups are unacceptable. + atomic_fence(); + } + // Double-check idiom that, in case of spawning, is deliberately sloppy about memory fences. + // Technically, to avoid missed wakeups, there should be a full memory fence between the point we + // released the task pool (i.e. spawned task) and read the arena's state. However, adding such a + // fence might hurt overall performance more than it helps, because the fence would be executed + // on every task pool release, even when stealing does not occur. Since TBB allows parallelism, + // but never promises parallelism, the missed wakeup is not a correctness problem. + pool_state_t snapshot = my_pool_state; + if( is_busy_or_empty(snapshot) ) { + // Attempt to mark as full. The compare_and_swap below is a little unusual because the + // result is compared to a value that can be different than the comparand argument. + if( my_pool_state.compare_and_swap( SNAPSHOT_FULL, snapshot )==SNAPSHOT_EMPTY ) { + if( snapshot!=SNAPSHOT_EMPTY ) { + // This thread read "busy" into snapshot, and then another thread transitioned + // my_pool_state to "empty" in the meantime, which caused the compare_and_swap above + // to fail. Attempt to transition my_pool_state from "empty" to "full". + if( my_pool_state.compare_and_swap( SNAPSHOT_FULL, SNAPSHOT_EMPTY )!=SNAPSHOT_EMPTY ) { + // Some other thread transitioned my_pool_state from "empty", and hence became + // responsible for waking up workers. + return; + } + } + // This thread transitioned pool from empty to full state, and thus is responsible for + // telling RML that there is work to do. + if( Spawned ) { + if( my_mandatory_concurrency ) { + __TBB_ASSERT(my_max_num_workers==1, ""); + // There was deliberate oversubscription on 1 core for sake of starvation-resistant tasks. + // Now a single active thread (must be the master) supposedly starts a new parallel region + // with relaxed sequential semantics, and oversubscription should be avoided. + // Demand for workers has been decreased to 0 during SNAPSHOT_EMPTY, so just keep it. + my_max_num_workers = 0; + my_mandatory_concurrency = false; + return; + } + } + my_market->adjust_demand( *this, my_max_num_workers ); + } + } +} + +} // namespace internal +} // namespace tbb + +#endif /* _TBB_arena_H */ diff --git a/src/tbb/src/tbb/cache_aligned_allocator.cpp b/src/tbb/src/tbb/cache_aligned_allocator.cpp new file mode 100644 index 0000000..148abef --- /dev/null +++ b/src/tbb/src/tbb/cache_aligned_allocator.cpp @@ -0,0 +1,263 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/cache_aligned_allocator.h" +#include "tbb/tbb_allocator.h" +#include "tbb/tbb_exception.h" +#include "tbb_misc.h" +#include "dynamic_link.h" +#include <cstdlib> + +#if _WIN32||_WIN64 +#include "tbb/machine/windows_api.h" +#else +#include <dlfcn.h> +#endif /* _WIN32||_WIN64 */ + +using namespace std; + +#if __TBB_WEAK_SYMBOLS + +#pragma weak scalable_malloc +#pragma weak scalable_free +#pragma weak scalable_aligned_malloc +#pragma weak scalable_aligned_free + +extern "C" { + void* scalable_malloc( size_t ); + void scalable_free( void* ); + void* scalable_aligned_malloc( size_t, size_t ); + void scalable_aligned_free( void* ); +} + +#endif /* __TBB_WEAK_SYMBOLS */ + +namespace tbb { + +namespace internal { + +//! Dummy routine used for first indirect call via MallocHandler. +static void* DummyMalloc( size_t size ); + +//! Dummy routine used for first indirect call via FreeHandler. +static void DummyFree( void * ptr ); + +//! Handler for memory allocation +static void* (*MallocHandler)( size_t size ) = &DummyMalloc; + +//! Handler for memory deallocation +static void (*FreeHandler)( void* pointer ) = &DummyFree; + +//! Dummy routine used for first indirect call via padded_allocate_handler. +static void* dummy_padded_allocate( size_t bytes, size_t alignment ); + +//! Dummy routine used for first indirect call via padded_free_handler. +static void dummy_padded_free( void * ptr ); + +// ! Allocates memory using standard malloc. It is used when scalable_allocator is not available +static void* padded_allocate( size_t bytes, size_t alignment ); + +// ! Allocates memory using standard free. It is used when scalable_allocator is not available +static void padded_free( void* p ); + +//! Handler for padded memory allocation +static void* (*padded_allocate_handler)( size_t bytes, size_t alignment ) = &dummy_padded_allocate; + +//! Handler for padded memory deallocation +static void (*padded_free_handler)( void* p ) = &dummy_padded_free; + +//! Table describing how to link the handlers. +static const dynamic_link_descriptor MallocLinkTable[] = { + DLD(scalable_malloc, MallocHandler), + DLD(scalable_free, FreeHandler), + DLD(scalable_aligned_malloc, padded_allocate_handler), + DLD(scalable_aligned_free, padded_free_handler), +}; + + +#if TBB_USE_DEBUG +#define DEBUG_SUFFIX "_debug" +#else +#define DEBUG_SUFFIX +#endif /* TBB_USE_DEBUG */ + +// MALLOCLIB_NAME is the name of the TBB memory allocator library. +#if _WIN32||_WIN64 +#define MALLOCLIB_NAME "tbbmalloc" DEBUG_SUFFIX ".dll" +#elif __APPLE__ +#define MALLOCLIB_NAME "libtbbmalloc" DEBUG_SUFFIX ".dylib" +#elif __linux__ +#define MALLOCLIB_NAME "libtbbmalloc" DEBUG_SUFFIX __TBB_STRING(.so.TBB_COMPATIBLE_INTERFACE_VERSION) +#elif __FreeBSD__ || __NetBSD__ || __sun || _AIX +#define MALLOCLIB_NAME "libtbbmalloc" DEBUG_SUFFIX ".so" +#else +#error Unknown OS +#endif + +//! Initialize the allocation/free handler pointers. +/** Caller is responsible for ensuring this routine is called exactly once. + The routine attempts to dynamically link with the TBB memory allocator. + If that allocator is not found, it links to malloc and free. */ +void initialize_handler_pointers() { + __TBB_ASSERT( MallocHandler==&DummyMalloc, NULL ); + bool success = dynamic_link( MALLOCLIB_NAME, MallocLinkTable, 4 ); + if( !success ) { + // If unsuccessful, set the handlers to the default routines. + // This must be done now, and not before FillDynamicLinks runs, because if other + // threads call the handlers, we want them to go through the DoOneTimeInitializations logic, + // which forces them to wait. + FreeHandler = &free; + MallocHandler = &malloc; + padded_allocate_handler = &padded_allocate; + padded_free_handler = &padded_free; + } +#if !__TBB_RML_STATIC + PrintExtraVersionInfo( "ALLOCATOR", success?"scalable_malloc":"malloc" ); +#endif +} + +static tbb::atomic<do_once_state> initialization_state; +void initialize_cache_aligned_allocator() { + atomic_do_once( &initialize_handler_pointers, initialization_state ); +} + +//! Executed on very first call through MallocHandler +static void* DummyMalloc( size_t size ) { + initialize_cache_aligned_allocator(); + __TBB_ASSERT( MallocHandler!=&DummyMalloc, NULL ); + return (*MallocHandler)( size ); +} + +//! Executed on very first call throught FreeHandler +static void DummyFree( void * ptr ) { + initialize_cache_aligned_allocator(); + __TBB_ASSERT( FreeHandler!=&DummyFree, NULL ); + (*FreeHandler)( ptr ); +} + +//! Executed on very first call through padded_allocate_handler +static void* dummy_padded_allocate( size_t bytes, size_t alignment ) { + initialize_cache_aligned_allocator(); + __TBB_ASSERT( padded_allocate_handler!=&dummy_padded_allocate, NULL ); + return (*padded_allocate_handler)(bytes, alignment); +} + +//! Executed on very first call throught padded_free_handler +static void dummy_padded_free( void * ptr ) { + initialize_cache_aligned_allocator(); + __TBB_ASSERT( padded_free_handler!=&dummy_padded_free, NULL ); + (*padded_free_handler)( ptr ); +} + +static size_t NFS_LineSize = 128; + +size_t NFS_GetLineSize() { + return NFS_LineSize; +} + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // unary minus operator applied to unsigned type, result still unsigned + #pragma warning( disable: 4146 4706 ) +#endif + +void* NFS_Allocate( size_t n, size_t element_size, void* /*hint*/ ) { + size_t m = NFS_LineSize; + __TBB_ASSERT( m<=NFS_MaxLineSize, "illegal value for NFS_LineSize" ); + __TBB_ASSERT( (m & (m-1))==0, "must be power of two" ); + size_t bytes = n*element_size; + + if (bytes<n || bytes+m<bytes) { + // Overflow + throw_exception(eid_bad_alloc); + } + // scalable_aligned_malloc considers zero size request an error, and returns NULL + if (bytes==0) bytes = 1; + + void* result = (*padded_allocate_handler)( bytes, m ); + if (!result) + throw_exception(eid_bad_alloc); + + __TBB_ASSERT( ((size_t)result&(m-1)) == 0, "The address returned isn't aligned to cache line size" ); + return result; +} + +void NFS_Free( void* p ) { + (*padded_free_handler)( p ); +} + +static void* padded_allocate( size_t bytes, size_t alignment ) { + unsigned char* result = NULL; + unsigned char* base = (unsigned char*)malloc(alignment+bytes); + if( base ) { + // Round up to the next line + result = (unsigned char*)((uintptr_t)(base+alignment)&-alignment); + // Record where block actually starts. + ((uintptr_t*)result)[-1] = uintptr_t(base); + } + return result; +} + +static void padded_free( void* p ) { + if( p ) { + __TBB_ASSERT( (uintptr_t)p>=0x4096, "attempt to free block not obtained from cache_aligned_allocator" ); + // Recover where block actually starts + unsigned char* base = ((unsigned char**)p)[-1]; + __TBB_ASSERT( (void*)((uintptr_t)(base+NFS_LineSize)&-NFS_LineSize)==p, "not allocated by NFS_Allocate?" ); + free(base); + } +} + +void* __TBB_EXPORTED_FUNC allocate_via_handler_v3( size_t n ) { + void* result = (*MallocHandler) (n); + if (!result) { + throw_exception(eid_bad_alloc); + } + return result; +} + +void __TBB_EXPORTED_FUNC deallocate_via_handler_v3( void *p ) { + if( p ) { + (*FreeHandler)( p ); + } +} + +bool __TBB_EXPORTED_FUNC is_malloc_used_v3() { + if (MallocHandler == &DummyMalloc) { + void* void_ptr = (*MallocHandler)(1); + (*FreeHandler)(void_ptr); + } + __TBB_ASSERT( MallocHandler!=&DummyMalloc && FreeHandler!=&DummyFree, NULL ); + // Cast to void avoids type mismatch errors on some compilers (e.g. __IBMCPP__) + __TBB_ASSERT( !(((void*)MallocHandler==(void*)&malloc) ^ ((void*)FreeHandler==(void*)&free)), + "Both shim pointers must refer to routines from the same package (either TBB or CRT)" ); + return (void*)MallocHandler == (void*)&malloc; +} + +} // namespace internal + +} // namespace tbb diff --git a/src/tbb/src/tbb/cilk-tbb-interop.h b/src/tbb/src/tbb/cilk-tbb-interop.h new file mode 100644 index 0000000..43caf24 --- /dev/null +++ b/src/tbb/src/tbb/cilk-tbb-interop.h @@ -0,0 +1,122 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* The API to enable interoperability between Intel(R) Cilk(tm) Plus and TBB. */ + +#ifndef CILK_TBB_INTEROP_H +#define CILK_TBB_INTEROP_H + +#ifndef _WIN32 +#ifdef IN_CILK_RUNTIME +#define CILK_EXPORT __attribute__((visibility("protected"))) +#else +#define CILK_EXPORT /* nothing */ +#endif +#else +#ifdef IN_CILK_RUNTIME +#define CILK_EXPORT __declspec(dllexport) +#else +#define CILK_EXPORT __declspec(dllimport) +#endif // IN_CILK_RUNTIME +#endif // _WIN32 + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* A return code. 0 indicates success */ +typedef int __cilk_tbb_retcode; + +enum __cilk_tbb_stack_op { + CILK_TBB_STACK_ORPHAN, // disconnecting stack from a thread + CILK_TBB_STACK_ADOPT, // reconnecting orphaned stack to a trhead + CILK_TBB_STACK_RELEASE // releasing stack +}; + +typedef __cilk_tbb_retcode (*__cilk_tbb_pfn_stack_op)(enum __cilk_tbb_stack_op, void* data); + +typedef __cilk_tbb_retcode (*__cilk_tbb_pfn_unwatch_stacks)(void *data); + +/* Each thunk structure has two pointers: "routine" and "data". + The caller of the thunk invokes *routine, passing "data" as the void* parameter. */ + +/* Thunk invoked by Intel Cilk Plus runtime (cilkrts) when it changes the relationship + between a stack and a thread. It does not matter what stack the thunk runs on. + The thread (not fiber) on which the thunk runs is important. + + CILK_TBB_STACK_ORPHAN + The thunk must be invoked on the thread disconnecting itself from the stack. + Must "happen before" the stack is adopted elsewhere. + CILK_TBB_STACK_ADOPT + The thunk must be invoked on the thread adopting the stack. + CILK_TBB_STACK_RELEASE + The thunk must be invoked on the thread doing the releasing, + Must "happen before" the stack is used elsewhere. + + When a non-empty stack is transfered between threads, the first thread must orphan it + and the second thread must adopt it. + + An empty stack can be transfered similarly, or simply released by the first thread. + + Here is a summary of the actions as transitions on a state machine. + + watch ORPHAN + -->--> -->-- + / \ / \ + (freed empty stack) (TBB sees stack running on thread) (stack in limbo) + | \ / \ / | + | --<-- --<-- | + ^ RELEASE or ADOPT V + \ unwatch / + \ / + --------------------------<--------------------------- + RELEASE +*/ +struct __cilk_tbb_stack_op_thunk { + __cilk_tbb_pfn_stack_op routine; + void* data; /* Set by TBB */ +}; + +/* Thunk invoked by TBB when it is no longer interested in watching the stack bound to the current thread. */ +struct __cilk_tbb_unwatch_thunk { + __cilk_tbb_pfn_unwatch_stacks routine; + void* data; +}; + +/* Defined by cilkrts, called by TBB. + Requests that cilkrts invoke __cilk_tbb_stack_op_thunk when it orphans a stack. + cilkrts sets *u to a thunk that TBB should call when it is no longer interested in watching the stack. */ +CILK_EXPORT +__cilk_tbb_retcode __cilkrts_watch_stack(struct __cilk_tbb_unwatch_thunk* u, + struct __cilk_tbb_stack_op_thunk o); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // CILK_TBB_INTEROP_H diff --git a/src/tbb/src/tbb/concurrent_hash_map.cpp b/src/tbb/src/tbb/concurrent_hash_map.cpp new file mode 100644 index 0000000..571ad96 --- /dev/null +++ b/src/tbb/src/tbb/concurrent_hash_map.cpp @@ -0,0 +1,66 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/concurrent_hash_map.h" + +namespace tbb { + +namespace internal { +#if !TBB_NO_LEGACY +struct hash_map_segment_base { + typedef spin_rw_mutex segment_mutex_t; + //! Type of a hash code. + typedef size_t hashcode_t; + //! Log2 of n_segment + static const size_t n_segment_bits = 6; + //! Maximum size of array of chains + static const size_t max_physical_size = size_t(1)<<(8*sizeof(hashcode_t)-n_segment_bits); + //! Mutex that protects this segment + segment_mutex_t my_mutex; + // Number of nodes + atomic<size_t> my_logical_size; + // Size of chains + /** Always zero or a power of two */ + size_t my_physical_size; + //! True if my_logical_size>=my_physical_size. + /** Used to support Intel(R) Thread Checker. */ + bool __TBB_EXPORTED_METHOD internal_grow_predicate() const; +}; + +bool hash_map_segment_base::internal_grow_predicate() const { + // Intel(R) Thread Checker considers the following reads to be races, so we hide them in the + // library so that Intel(R) Thread Checker will ignore them. The reads are used in a double-check + // context, so the program is nonetheless correct despite the race. + return my_logical_size >= my_physical_size && my_physical_size < max_physical_size; +} +#endif//!TBB_NO_LEGACY + +} // namespace internal + +} // namespace tbb + diff --git a/src/tbb/src/tbb/concurrent_monitor.cpp b/src/tbb/src/tbb/concurrent_monitor.cpp new file mode 100644 index 0000000..829efdf --- /dev/null +++ b/src/tbb/src/tbb/concurrent_monitor.cpp @@ -0,0 +1,145 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "concurrent_monitor.h" + +namespace tbb { +namespace internal { + +void concurrent_monitor::thread_context::init() { + new (sema.begin()) binary_semaphore; + ready = true; +} + +concurrent_monitor::~concurrent_monitor() { + abort_all(); + __TBB_ASSERT( waitset_ec.empty(), "waitset not empty?" ); +} + +void concurrent_monitor::prepare_wait( thread_context& thr, uintptr_t ctx ) { + if( !thr.ready ) + thr.init(); + // this is good place to pump previous spurious wakeup + else if( thr.spurious ) { + thr.spurious = false; + thr.semaphore().P(); + } + thr.context = ctx; + thr.in_waitset = true; + { + tbb::spin_mutex::scoped_lock l( mutex_ec ); + __TBB_store_relaxed( thr.epoch, __TBB_load_relaxed(epoch) ); + waitset_ec.add( (waitset_t::node_t*)&thr ); + } + atomic_fence(); +} + +void concurrent_monitor::cancel_wait( thread_context& thr ) { + // spurious wakeup will be pumped in the following prepare_wait() + thr.spurious = true; + // try to remove node from waitset + bool th_in_waitset = thr.in_waitset; + if( th_in_waitset ) { + tbb::spin_mutex::scoped_lock l( mutex_ec ); + if (thr.in_waitset) { + // successfully removed from waitset, + // so there will be no spurious wakeup + thr.in_waitset = false; + thr.spurious = false; + waitset_ec.remove( (waitset_t::node_t&)thr ); + } + } +} + +void concurrent_monitor::notify_one_relaxed() { + if( waitset_ec.empty() ) + return; + waitset_node_t* n; + const waitset_node_t* end = waitset_ec.end(); + { + tbb::spin_mutex::scoped_lock l( mutex_ec ); + __TBB_store_relaxed( epoch, __TBB_load_relaxed(epoch) + 1 ); + n = waitset_ec.front(); + if( n!=end ) { + waitset_ec.remove( *n ); + to_thread_context(n)->in_waitset = false; + } + } + if( n!=end ) + to_thread_context(n)->semaphore().V(); +} + +void concurrent_monitor::notify_all_relaxed() { + if( waitset_ec.empty() ) + return; + dllist_t temp; + const waitset_node_t* end; + { + tbb::spin_mutex::scoped_lock l( mutex_ec ); + __TBB_store_relaxed( epoch, __TBB_load_relaxed(epoch) + 1 ); + waitset_ec.flush_to( temp ); + end = temp.end(); + for( waitset_node_t* n=temp.front(); n!=end; n=n->next ) + to_thread_context(n)->in_waitset = false; + } + waitset_node_t* nxt; + for( waitset_node_t* n=temp.front(); n!=end; n=nxt ) { + nxt = n->next; + to_thread_context(n)->semaphore().V(); + } +#if TBB_USE_ASSERT + temp.clear(); +#endif +} + +void concurrent_monitor::abort_all_relaxed() { + if( waitset_ec.empty() ) + return; + dllist_t temp; + const waitset_node_t* end; + { + tbb::spin_mutex::scoped_lock l( mutex_ec ); + __TBB_store_relaxed( epoch, __TBB_load_relaxed(epoch) + 1 ); + waitset_ec.flush_to( temp ); + end = temp.end(); + for( waitset_node_t* n=temp.front(); n!=end; n=n->next ) + to_thread_context(n)->in_waitset = false; + } + waitset_node_t* nxt; + for( waitset_node_t* n=temp.front(); n!=end; n=nxt ) { + nxt = n->next; + to_thread_context(n)->aborted = true; + to_thread_context(n)->semaphore().V(); + } +#if TBB_USE_ASSERT + temp.clear(); +#endif +} + +} // namespace internal +} // namespace tbb diff --git a/src/tbb/src/tbb/concurrent_monitor.h b/src/tbb/src/tbb/concurrent_monitor.h new file mode 100644 index 0000000..cf42742 --- /dev/null +++ b/src/tbb/src/tbb/concurrent_monitor.h @@ -0,0 +1,249 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_concurrent_monitor_H +#define __TBB_concurrent_monitor_H + +#include "tbb/tbb_stddef.h" +#include "tbb/atomic.h" +#include "tbb/spin_mutex.h" +#include "tbb/tbb_exception.h" +#include "tbb/aligned_space.h" + +#include "semaphore.h" + +namespace tbb { +namespace internal { + +//! Circular doubly-linked list with sentinel +/** head.next points to the front and head.prev points to the back */ +class circular_doubly_linked_list_with_sentinel : no_copy { +public: + struct node_t { + node_t* next; + node_t* prev; + explicit node_t() : next((node_t*)(uintptr_t)0xcdcdcdcd), prev((node_t*)(uintptr_t)0xcdcdcdcd) {} + }; + + // ctor + circular_doubly_linked_list_with_sentinel() {clear();} + // dtor + ~circular_doubly_linked_list_with_sentinel() {__TBB_ASSERT( head.next==&head && head.prev==&head, "the list is not empty" );} + + inline size_t size() const {return count;} + inline bool empty() const {return size()==0;} + inline node_t* front() const {return head.next;} + inline node_t* last() const {return head.prev;} + inline node_t* begin() const {return front();} + inline const node_t* end() const {return &head;} + + //! add to the back of the list + inline void add( node_t* n ) { + __TBB_store_relaxed(count, __TBB_load_relaxed(count) + 1); + n->prev = head.prev; + n->next = &head; + head.prev->next = n; + head.prev = n; + } + + //! remove node 'n' + inline void remove( node_t& n ) { + __TBB_store_relaxed(count, __TBB_load_relaxed(count) - 1); + n.prev->next = n.next; + n.next->prev = n.prev; + } + + //! move all elements to 'lst' and initialize the 'this' list + inline void flush_to( circular_doubly_linked_list_with_sentinel& lst ) { + if( const size_t l_count = __TBB_load_relaxed(count) ) { + __TBB_store_relaxed(lst.count, l_count); + lst.head.next = head.next; + lst.head.prev = head.prev; + head.next->prev = &lst.head; + head.prev->next = &lst.head; + clear(); + } + } + + void clear() {head.next = head.prev = &head; __TBB_store_relaxed(count, 0);} +private: + __TBB_atomic size_t count; + node_t head; +}; + +typedef circular_doubly_linked_list_with_sentinel waitset_t; +typedef circular_doubly_linked_list_with_sentinel dllist_t; +typedef circular_doubly_linked_list_with_sentinel::node_t waitset_node_t; + +//! concurrent_monitor +/** fine-grained concurrent_monitor implementation */ +class concurrent_monitor : no_copy { +public: + /** per-thread descriptor for concurrent_monitor */ + class thread_context : waitset_node_t, no_copy { + friend class concurrent_monitor; + public: + thread_context() : spurious(false), aborted(false), ready(false), context(0) { + epoch = 0; + in_waitset = false; + } + ~thread_context() { + if (ready) { + if( spurious ) semaphore().P(); + semaphore().~binary_semaphore(); + } + } + binary_semaphore& semaphore() { return *sema.begin(); } + private: + //! The method for lazy initialization of the thread_context's semaphore. + // Inlining of the method is undesirable, due to extra instructions for + // exception support added at caller side. + __TBB_NOINLINE( void init() ); + tbb::aligned_space<binary_semaphore, 1> sema; + __TBB_atomic unsigned epoch; + tbb::atomic<bool> in_waitset; + bool spurious; + bool aborted; + bool ready; + uintptr_t context; + }; + + //! ctor + concurrent_monitor() {__TBB_store_relaxed(epoch, 0);} + + //! dtor + ~concurrent_monitor() ; + + //! prepare wait by inserting 'thr' into the wailt queue + void prepare_wait( thread_context& thr, uintptr_t ctx = 0 ); + + //! Commit wait if event count has not changed; otherwise, cancel wait. + /** Returns true if committed, false if canceled. */ + inline bool commit_wait( thread_context& thr ) { + const bool do_it = thr.epoch == __TBB_load_relaxed(epoch); + // this check is just an optimization + if( do_it ) { + __TBB_ASSERT( thr.ready, "use of commit_wait() without prior prepare_wait()"); + thr.semaphore().P(); + __TBB_ASSERT( !thr.in_waitset, "still in the queue?" ); + if( thr.aborted ) + throw_exception( eid_user_abort ); + } else { + cancel_wait( thr ); + } + return do_it; + } + //! Cancel the wait. Removes the thread from the wait queue if not removed yet. + void cancel_wait( thread_context& thr ); + + //! Wait for a condition to be satisfied with waiting-on context + template<typename WaitUntil, typename Context> + void wait( WaitUntil until, Context on ); + + //! Notify one thread about the event + void notify_one() {atomic_fence(); notify_one_relaxed();} + + //! Notify one thread about the event. Relaxed version. + void notify_one_relaxed(); + + //! Notify all waiting threads of the event + void notify_all() {atomic_fence(); notify_all_relaxed();} + + //! Notify all waiting threads of the event; Relaxed version + void notify_all_relaxed(); + + //! Notify waiting threads of the event that satisfies the given predicate + template<typename P> void notify( const P& predicate ) {atomic_fence(); notify_relaxed( predicate );} + + //! Notify waiting threads of the event that satisfies the given predicate; Relaxed version + template<typename P> void notify_relaxed( const P& predicate ); + + //! Abort any sleeping threads at the time of the call + void abort_all() {atomic_fence(); abort_all_relaxed(); } + + //! Abort any sleeping threads at the time of the call; Relaxed version + void abort_all_relaxed(); + +private: + tbb::spin_mutex mutex_ec; + waitset_t waitset_ec; + __TBB_atomic unsigned epoch; + thread_context* to_thread_context( waitset_node_t* n ) { return static_cast<thread_context*>(n); } +}; + +template<typename WaitUntil, typename Context> +void concurrent_monitor::wait( WaitUntil until, Context on ) +{ + bool slept = false; + thread_context thr_ctx; + prepare_wait( thr_ctx, on() ); + while( !until() ) { + if( (slept = commit_wait( thr_ctx ) )==true ) + if( until() ) break; + slept = false; + prepare_wait( thr_ctx, on() ); + } + if( !slept ) + cancel_wait( thr_ctx ); +} + +template<typename P> +void concurrent_monitor::notify_relaxed( const P& predicate ) { + if( waitset_ec.empty() ) + return; + dllist_t temp; + waitset_node_t* nxt; + const waitset_node_t* end = waitset_ec.end(); + { + tbb::spin_mutex::scoped_lock l( mutex_ec ); + __TBB_store_relaxed(epoch, __TBB_load_relaxed(epoch) + 1); + for( waitset_node_t* n=waitset_ec.last(); n!=end; n=nxt ) { + nxt = n->prev; + thread_context* thr = to_thread_context( n ); + if( predicate( thr->context ) ) { + waitset_ec.remove( *n ); + thr->in_waitset = false; + temp.add( n ); + } + } + } + + end = temp.end(); + for( waitset_node_t* n=temp.front(); n!=end; n=nxt ) { + nxt = n->next; + to_thread_context(n)->semaphore().V(); + } +#if TBB_USE_ASSERT + temp.clear(); +#endif +} + +} // namespace internal +} // namespace tbb + +#endif /* __TBB_concurrent_monitor_H */ diff --git a/src/tbb/src/tbb/concurrent_queue.cpp b/src/tbb/src/tbb/concurrent_queue.cpp new file mode 100644 index 0000000..fcf6e16 --- /dev/null +++ b/src/tbb/src/tbb/concurrent_queue.cpp @@ -0,0 +1,639 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/tbb_stddef.h" +#include "tbb/tbb_machine.h" +#include "tbb/tbb_exception.h" +// Define required to satisfy test in internal file. +#define __TBB_concurrent_queue_H +#include "tbb/internal/_concurrent_queue_impl.h" +#include "concurrent_monitor.h" +#include "itt_notify.h" +#include <new> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include <cstring> // for memset() + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +using namespace std; + +#if defined(_MSC_VER) && defined(_Wp64) + // Workaround for overzealous compiler warnings in /Wp64 mode + #pragma warning (disable: 4267) +#endif + +#define RECORD_EVENTS 0 + + +namespace tbb { + +namespace internal { + +typedef concurrent_queue_base_v3 concurrent_queue_base; + +typedef size_t ticket; + +//! A queue using simple locking. +/** For efficiency, this class has no constructor. + The caller is expected to zero-initialize it. */ +struct micro_queue { + typedef concurrent_queue_base::page page; + + friend class micro_queue_pop_finalizer; + + atomic<page*> head_page; + atomic<ticket> head_counter; + + atomic<page*> tail_page; + atomic<ticket> tail_counter; + + spin_mutex page_mutex; + + void push( const void* item, ticket k, concurrent_queue_base& base ); + void abort_push( ticket k, concurrent_queue_base& base ); + + bool pop( void* dst, ticket k, concurrent_queue_base& base ); + + micro_queue& assign( const micro_queue& src, concurrent_queue_base& base ); + + page* make_copy ( concurrent_queue_base& base, const page* src_page, size_t begin_in_page, size_t end_in_page, ticket& g_index ) ; + + void make_invalid( ticket k ); +}; + +// we need to yank it out of micro_queue because of concurrent_queue_base::deallocate_page being virtual. +class micro_queue_pop_finalizer: no_copy { + typedef concurrent_queue_base::page page; + ticket my_ticket; + micro_queue& my_queue; + page* my_page; + concurrent_queue_base &base; +public: + micro_queue_pop_finalizer( micro_queue& queue, concurrent_queue_base& b, ticket k, page* p ) : + my_ticket(k), my_queue(queue), my_page(p), base(b) + {} + ~micro_queue_pop_finalizer() { + page* p = my_page; + if( p ) { + spin_mutex::scoped_lock lock( my_queue.page_mutex ); + page* q = p->next; + my_queue.head_page = q; + if( !q ) { + my_queue.tail_page = NULL; + } + } + my_queue.head_counter = my_ticket; + if( p ) + base.deallocate_page( p ); + } +}; + +struct predicate_leq { + ticket t; + predicate_leq( ticket t_ ) : t(t_) {} + bool operator() ( uintptr_t p ) const {return (ticket)p<=t;} +}; + +//! Internal representation of a ConcurrentQueue. +/** For efficiency, this class has no constructor. + The caller is expected to zero-initialize it. */ +class concurrent_queue_rep { +public: +private: + friend struct micro_queue; + + //! Approximately n_queue/golden ratio + static const size_t phi = 3; + +public: + //! Must be power of 2 + static const size_t n_queue = 8; + + //! Map ticket to an array index + static size_t index( ticket k ) { + return k*phi%n_queue; + } + + atomic<ticket> head_counter; + concurrent_monitor items_avail; + atomic<size_t> n_invalid_entries; + char pad1[NFS_MaxLineSize-((sizeof(atomic<ticket>)+sizeof(concurrent_monitor)+sizeof(atomic<size_t>))&(NFS_MaxLineSize-1))]; + + atomic<ticket> tail_counter; + concurrent_monitor slots_avail; + char pad2[NFS_MaxLineSize-((sizeof(atomic<ticket>)+sizeof(concurrent_monitor))&(NFS_MaxLineSize-1))]; + micro_queue array[n_queue]; + + micro_queue& choose( ticket k ) { + // The formula here approximates LRU in a cache-oblivious way. + return array[index(k)]; + } + + //! Value for effective_capacity that denotes unbounded queue. + static const ptrdiff_t infinite_capacity = ptrdiff_t(~size_t(0)/2); +}; + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // unary minus operator applied to unsigned type, result still unsigned + #pragma warning( push ) + #pragma warning( disable: 4146 ) +#endif + +static void* invalid_page; + +//------------------------------------------------------------------------ +// micro_queue +//------------------------------------------------------------------------ +void micro_queue::push( const void* item, ticket k, concurrent_queue_base& base ) { + k &= -concurrent_queue_rep::n_queue; + page* p = NULL; + // find index on page where we would put the data + size_t index = k/concurrent_queue_rep::n_queue & (base.items_per_page-1); + if( !index ) { // make a new page + __TBB_TRY { + p = base.allocate_page(); + } __TBB_CATCH(...) { + ++base.my_rep->n_invalid_entries; + make_invalid( k ); + } + p->mask = 0; + p->next = NULL; + } + + // wait for my turn + if( tail_counter!=k ) { + atomic_backoff backoff; + do { + backoff.pause(); + // no memory. throws an exception; assumes concurrent_queue_rep::n_queue>1 + if( tail_counter&0x1 ) { + ++base.my_rep->n_invalid_entries; + throw_exception( eid_bad_last_alloc ); + } + } while( tail_counter!=k ) ; + } + + if( p ) { // page is newly allocated; insert in micro_queue + spin_mutex::scoped_lock lock( page_mutex ); + if( page* q = tail_page ) + q->next = p; + else + head_page = p; + tail_page = p; + } + + if (item) { + p = tail_page; + ITT_NOTIFY( sync_acquired, p ); + __TBB_TRY { + base.copy_item( *p, index, item ); + } __TBB_CATCH(...) { + ++base.my_rep->n_invalid_entries; + tail_counter += concurrent_queue_rep::n_queue; + __TBB_RETHROW(); + } + ITT_NOTIFY( sync_releasing, p ); + // If no exception was thrown, mark item as present. + p->mask |= uintptr_t(1)<<index; + } + else // no item; this was called from abort_push + ++base.my_rep->n_invalid_entries; + + tail_counter += concurrent_queue_rep::n_queue; +} + + +void micro_queue::abort_push( ticket k, concurrent_queue_base& base ) { + push(NULL, k, base); +} + +bool micro_queue::pop( void* dst, ticket k, concurrent_queue_base& base ) { + k &= -concurrent_queue_rep::n_queue; + spin_wait_until_eq( head_counter, k ); + spin_wait_while_eq( tail_counter, k ); + page& p = *head_page; + __TBB_ASSERT( &p, NULL ); + size_t index = k/concurrent_queue_rep::n_queue & (base.items_per_page-1); + bool success = false; + { + micro_queue_pop_finalizer finalizer( *this, base, k+concurrent_queue_rep::n_queue, index==base.items_per_page-1 ? &p : NULL ); + if( p.mask & uintptr_t(1)<<index ) { + success = true; + ITT_NOTIFY( sync_acquired, dst ); + ITT_NOTIFY( sync_acquired, head_page ); + base.assign_and_destroy_item( dst, p, index ); + ITT_NOTIFY( sync_releasing, head_page ); + } else { + --base.my_rep->n_invalid_entries; + } + } + return success; +} + +micro_queue& micro_queue::assign( const micro_queue& src, concurrent_queue_base& base ) +{ + head_counter = src.head_counter; + tail_counter = src.tail_counter; + page_mutex = src.page_mutex; + + const page* srcp = src.head_page; + if( srcp ) { + ticket g_index = head_counter; + __TBB_TRY { + size_t n_items = (tail_counter-head_counter)/concurrent_queue_rep::n_queue; + size_t index = head_counter/concurrent_queue_rep::n_queue & (base.items_per_page-1); + size_t end_in_first_page = (index+n_items<base.items_per_page)?(index+n_items):base.items_per_page; + + head_page = make_copy( base, srcp, index, end_in_first_page, g_index ); + page* cur_page = head_page; + + if( srcp != src.tail_page ) { + for( srcp = srcp->next; srcp!=src.tail_page; srcp=srcp->next ) { + cur_page->next = make_copy( base, srcp, 0, base.items_per_page, g_index ); + cur_page = cur_page->next; + } + + __TBB_ASSERT( srcp==src.tail_page, NULL ); + + size_t last_index = tail_counter/concurrent_queue_rep::n_queue & (base.items_per_page-1); + if( last_index==0 ) last_index = base.items_per_page; + + cur_page->next = make_copy( base, srcp, 0, last_index, g_index ); + cur_page = cur_page->next; + } + tail_page = cur_page; + } __TBB_CATCH(...) { + make_invalid( g_index ); + } + } else { + head_page = tail_page = NULL; + } + return *this; +} + +concurrent_queue_base::page* micro_queue::make_copy( concurrent_queue_base& base, const concurrent_queue_base::page* src_page, size_t begin_in_page, size_t end_in_page, ticket& g_index ) +{ + page* new_page = base.allocate_page(); + new_page->next = NULL; + new_page->mask = src_page->mask; + for( ; begin_in_page!=end_in_page; ++begin_in_page, ++g_index ) + if( new_page->mask & uintptr_t(1)<<begin_in_page ) + base.copy_page_item( *new_page, begin_in_page, *src_page, begin_in_page ); + return new_page; +} + +void micro_queue::make_invalid( ticket k ) +{ + static concurrent_queue_base::page dummy = {static_cast<page*>((void*)1), 0}; + // mark it so that no more pushes are allowed. + invalid_page = &dummy; + { + spin_mutex::scoped_lock lock( page_mutex ); + tail_counter = k+concurrent_queue_rep::n_queue+1; + if( page* q = tail_page ) + q->next = static_cast<page*>(invalid_page); + else + head_page = static_cast<page*>(invalid_page); + tail_page = static_cast<page*>(invalid_page); + } + __TBB_RETHROW(); +} + +#if _MSC_VER && !defined(__INTEL_COMPILER) + #pragma warning( pop ) +#endif // warning 4146 is back + +//------------------------------------------------------------------------ +// concurrent_queue_base +//------------------------------------------------------------------------ +concurrent_queue_base_v3::concurrent_queue_base_v3( size_t item_sz ) { + items_per_page = item_sz<= 8 ? 32 : + item_sz<= 16 ? 16 : + item_sz<= 32 ? 8 : + item_sz<= 64 ? 4 : + item_sz<=128 ? 2 : + 1; + my_capacity = size_t(-1)/(item_sz>1 ? item_sz : 2); + my_rep = cache_aligned_allocator<concurrent_queue_rep>().allocate(1); + __TBB_ASSERT( (size_t)my_rep % NFS_GetLineSize()==0, "alignment error" ); + __TBB_ASSERT( (size_t)&my_rep->head_counter % NFS_GetLineSize()==0, "alignment error" ); + __TBB_ASSERT( (size_t)&my_rep->tail_counter % NFS_GetLineSize()==0, "alignment error" ); + __TBB_ASSERT( (size_t)&my_rep->array % NFS_GetLineSize()==0, "alignment error" ); + memset(my_rep,0,sizeof(concurrent_queue_rep)); + new ( &my_rep->items_avail ) concurrent_monitor(); + new ( &my_rep->slots_avail ) concurrent_monitor(); + this->item_size = item_sz; +} + +concurrent_queue_base_v3::~concurrent_queue_base_v3() { + size_t nq = my_rep->n_queue; + for( size_t i=0; i<nq; i++ ) + __TBB_ASSERT( my_rep->array[i].tail_page==NULL, "pages were not freed properly" ); + cache_aligned_allocator<concurrent_queue_rep>().deallocate(my_rep,1); +} + +void concurrent_queue_base_v3::internal_push( const void* src ) { + concurrent_queue_rep& r = *my_rep; + ticket k = r.tail_counter++; + ptrdiff_t e = my_capacity; +#if DO_ITT_NOTIFY + bool sync_prepare_done = false; +#endif + if( (ptrdiff_t)(k-r.head_counter)>=e ) { // queue is full +#if DO_ITT_NOTIFY + if( !sync_prepare_done ) { + ITT_NOTIFY( sync_prepare, &sync_prepare_done ); + sync_prepare_done = true; + } +#endif + bool slept = false; + concurrent_monitor::thread_context thr_ctx; + r.slots_avail.prepare_wait( thr_ctx, ((ptrdiff_t)(k-e)) ); + while( (ptrdiff_t)(k-r.head_counter)>=const_cast<volatile ptrdiff_t&>(e = my_capacity) ) { + __TBB_TRY { + slept = r.slots_avail.commit_wait( thr_ctx ); + } __TBB_CATCH( tbb::user_abort& ) { + r.choose(k).abort_push(k, *this); + __TBB_RETHROW(); + } __TBB_CATCH(...) { + __TBB_RETHROW(); + } + if (slept == true) break; + r.slots_avail.prepare_wait( thr_ctx, ((ptrdiff_t)(k-e)) ); + } + if( !slept ) + r.slots_avail.cancel_wait( thr_ctx ); + } + ITT_NOTIFY( sync_acquired, &sync_prepare_done ); + __TBB_ASSERT( (ptrdiff_t)(k-r.head_counter)<my_capacity, NULL); + r.choose( k ).push( src, k, *this ); + r.items_avail.notify( predicate_leq(k) ); +} + +void concurrent_queue_base_v3::internal_pop( void* dst ) { + concurrent_queue_rep& r = *my_rep; + ticket k; +#if DO_ITT_NOTIFY + bool sync_prepare_done = false; +#endif + do { + k=r.head_counter++; + if ( (ptrdiff_t)(r.tail_counter-k)<=0 ) { // queue is empty +#if DO_ITT_NOTIFY + if( !sync_prepare_done ) { + ITT_NOTIFY( sync_prepare, dst ); + sync_prepare_done = true; + } +#endif + bool slept = false; + concurrent_monitor::thread_context thr_ctx; + r.items_avail.prepare_wait( thr_ctx, k ); + while( (ptrdiff_t)(r.tail_counter-k)<=0 ) { + __TBB_TRY { + slept = r.items_avail.commit_wait( thr_ctx ); + } __TBB_CATCH( tbb::user_abort& ) { + r.head_counter--; + __TBB_RETHROW(); + } __TBB_CATCH(...) { + __TBB_RETHROW(); + } + if (slept == true) break; + r.items_avail.prepare_wait( thr_ctx, k ); + } + if( !slept ) + r.items_avail.cancel_wait( thr_ctx ); + } + __TBB_ASSERT((ptrdiff_t)(r.tail_counter-k)>0, NULL); + } while( !r.choose(k).pop(dst,k,*this) ); + + // wake up a producer.. + r.slots_avail.notify( predicate_leq(k) ); +} + +void concurrent_queue_base_v3::internal_abort() { + concurrent_queue_rep& r = *my_rep; + r.items_avail.abort_all(); + r.slots_avail.abort_all(); +} + +bool concurrent_queue_base_v3::internal_pop_if_present( void* dst ) { + concurrent_queue_rep& r = *my_rep; + ticket k; + do { + k = r.head_counter; + for(;;) { + if( (ptrdiff_t)(r.tail_counter-k)<=0 ) { + // Queue is empty + return false; + } + // Queue had item with ticket k when we looked. Attempt to get that item. + ticket tk=k; + k = r.head_counter.compare_and_swap( tk+1, tk ); + if( k==tk ) + break; + // Another thread snatched the item, retry. + } + } while( !r.choose( k ).pop( dst, k, *this ) ); + + r.slots_avail.notify( predicate_leq(k) ); + + return true; +} + +bool concurrent_queue_base_v3::internal_push_if_not_full( const void* src ) { + concurrent_queue_rep& r = *my_rep; + ticket k = r.tail_counter; + for(;;) { + if( (ptrdiff_t)(k-r.head_counter)>=my_capacity ) { + // Queue is full + return false; + } + // Queue had empty slot with ticket k when we looked. Attempt to claim that slot. + ticket tk=k; + k = r.tail_counter.compare_and_swap( tk+1, tk ); + if( k==tk ) + break; + // Another thread claimed the slot, so retry. + } + r.choose(k).push(src,k,*this); + + r.items_avail.notify( predicate_leq(k) ); + return true; +} + +ptrdiff_t concurrent_queue_base_v3::internal_size() const { + __TBB_ASSERT( sizeof(ptrdiff_t)<=sizeof(size_t), NULL ); + return ptrdiff_t(my_rep->tail_counter-my_rep->head_counter-my_rep->n_invalid_entries); +} + +bool concurrent_queue_base_v3::internal_empty() const { + ticket tc = my_rep->tail_counter; + ticket hc = my_rep->head_counter; + // if tc!=r.tail_counter, the queue was not empty at some point between the two reads. + return ( tc==my_rep->tail_counter && ptrdiff_t(tc-hc-my_rep->n_invalid_entries)<=0 ); +} + +void concurrent_queue_base_v3::internal_set_capacity( ptrdiff_t capacity, size_t /*item_sz*/ ) { + my_capacity = capacity<0 ? concurrent_queue_rep::infinite_capacity : capacity; +} + +void concurrent_queue_base_v3::internal_finish_clear() { + size_t nq = my_rep->n_queue; + for( size_t i=0; i<nq; ++i ) { + page* tp = my_rep->array[i].tail_page; + __TBB_ASSERT( my_rep->array[i].head_page==tp, "at most one page should remain" ); + if( tp!=NULL) { + if( tp!=invalid_page ) deallocate_page( tp ); + my_rep->array[i].tail_page = NULL; + } + } +} + +void concurrent_queue_base_v3::internal_throw_exception() const { + throw_exception( eid_bad_alloc ); +} + +void concurrent_queue_base_v3::assign( const concurrent_queue_base& src ) { + items_per_page = src.items_per_page; + my_capacity = src.my_capacity; + + // copy concurrent_queue_rep. + my_rep->head_counter = src.my_rep->head_counter; + my_rep->tail_counter = src.my_rep->tail_counter; + my_rep->n_invalid_entries = src.my_rep->n_invalid_entries; + + // copy micro_queues + for( size_t i = 0; i<my_rep->n_queue; ++i ) + my_rep->array[i].assign( src.my_rep->array[i], *this); + + __TBB_ASSERT( my_rep->head_counter==src.my_rep->head_counter && my_rep->tail_counter==src.my_rep->tail_counter, + "the source concurrent queue should not be concurrently modified." ); +} + +//------------------------------------------------------------------------ +// concurrent_queue_iterator_rep +//------------------------------------------------------------------------ +class concurrent_queue_iterator_rep: no_assign { +public: + ticket head_counter; + const concurrent_queue_base& my_queue; + const size_t offset_of_last; + concurrent_queue_base::page* array[concurrent_queue_rep::n_queue]; + concurrent_queue_iterator_rep( const concurrent_queue_base& queue, size_t offset_of_last_ ) : + head_counter(queue.my_rep->head_counter), + my_queue(queue), + offset_of_last(offset_of_last_) + { + const concurrent_queue_rep& rep = *queue.my_rep; + for( size_t k=0; k<concurrent_queue_rep::n_queue; ++k ) + array[k] = rep.array[k].head_page; + } + //! Set item to point to kth element. Return true if at end of queue or item is marked valid; false otherwise. + bool get_item( void*& item, size_t k ) { + if( k==my_queue.my_rep->tail_counter ) { + item = NULL; + return true; + } else { + concurrent_queue_base::page* p = array[concurrent_queue_rep::index(k)]; + __TBB_ASSERT(p,NULL); + size_t i = k/concurrent_queue_rep::n_queue & (my_queue.items_per_page-1); + item = static_cast<unsigned char*>(static_cast<void*>(p)) + offset_of_last + my_queue.item_size*i; + return (p->mask & uintptr_t(1)<<i)!=0; + } + } +}; + +//------------------------------------------------------------------------ +// concurrent_queue_iterator_base +//------------------------------------------------------------------------ + +void concurrent_queue_iterator_base_v3::initialize( const concurrent_queue_base& queue, size_t offset_of_last ) { + my_rep = cache_aligned_allocator<concurrent_queue_iterator_rep>().allocate(1); + new( my_rep ) concurrent_queue_iterator_rep(queue,offset_of_last); + size_t k = my_rep->head_counter; + if( !my_rep->get_item(my_item, k) ) advance(); +} + +concurrent_queue_iterator_base_v3::concurrent_queue_iterator_base_v3( const concurrent_queue_base& queue ) { + initialize(queue,0); +} + +concurrent_queue_iterator_base_v3::concurrent_queue_iterator_base_v3( const concurrent_queue_base& queue, size_t offset_of_last ) { + initialize(queue,offset_of_last); +} + +void concurrent_queue_iterator_base_v3::assign( const concurrent_queue_iterator_base& other ) { + if( my_rep!=other.my_rep ) { + if( my_rep ) { + cache_aligned_allocator<concurrent_queue_iterator_rep>().deallocate(my_rep, 1); + my_rep = NULL; + } + if( other.my_rep ) { + my_rep = cache_aligned_allocator<concurrent_queue_iterator_rep>().allocate(1); + new( my_rep ) concurrent_queue_iterator_rep( *other.my_rep ); + } + } + my_item = other.my_item; +} + +void concurrent_queue_iterator_base_v3::advance() { + __TBB_ASSERT( my_item, "attempt to increment iterator past end of queue" ); + size_t k = my_rep->head_counter; + const concurrent_queue_base& queue = my_rep->my_queue; +#if TBB_USE_ASSERT + void* tmp; + my_rep->get_item(tmp,k); + __TBB_ASSERT( my_item==tmp, NULL ); +#endif /* TBB_USE_ASSERT */ + size_t i = k/concurrent_queue_rep::n_queue & (queue.items_per_page-1); + if( i==queue.items_per_page-1 ) { + concurrent_queue_base::page*& root = my_rep->array[concurrent_queue_rep::index(k)]; + root = root->next; + } + // advance k + my_rep->head_counter = ++k; + if( !my_rep->get_item(my_item, k) ) advance(); +} + +concurrent_queue_iterator_base_v3::~concurrent_queue_iterator_base_v3() { + //delete my_rep; + cache_aligned_allocator<concurrent_queue_iterator_rep>().deallocate(my_rep, 1); + my_rep = NULL; +} + +} // namespace internal + +} // namespace tbb diff --git a/src/tbb/src/tbb/concurrent_vector.cpp b/src/tbb/src/tbb/concurrent_vector.cpp new file mode 100644 index 0000000..1c2d707 --- /dev/null +++ b/src/tbb/src/tbb/concurrent_vector.cpp @@ -0,0 +1,604 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/concurrent_vector.h" +#include "tbb/cache_aligned_allocator.h" +#include "tbb/tbb_exception.h" +#include "tbb_misc.h" +#include "itt_notify.h" + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include <cstring> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +#if defined(_MSC_VER) && defined(_Wp64) + // Workaround for overzealous compiler warnings in /Wp64 mode + #pragma warning (disable: 4267) +#endif + +using namespace std; + +namespace tbb { + +namespace internal { + class concurrent_vector_base_v3::helper :no_assign { +public: + //! memory page size + static const size_type page_size = 4096; + + inline static bool incompact_predicate(size_type size) { // assert size != 0, see source/test/test_vector_layout.cpp + return size < page_size || ((size-1)%page_size < page_size/2 && size < page_size * 128); // for more details + } + + inline static size_type find_segment_end(const concurrent_vector_base_v3 &v) { + segment_t *s = v.my_segment; + segment_index_t u = s==v.my_storage? pointers_per_short_table : pointers_per_long_table; + segment_index_t k = 0; + while( k < u && s[k].array > internal::vector_allocation_error_flag ) + ++k; + return k; + } + + // TODO: optimize accesses to my_first_block + //! assign first segment size. k - is index of last segment to be allocated, not a count of segments + inline static void assign_first_segment_if_neccessary(concurrent_vector_base_v3 &v, segment_index_t k) { + if( !v.my_first_block ) { + /* There was a suggestion to set first segment according to incompact_predicate: + while( k && !helper::incompact_predicate(segment_size( k ) * element_size) ) + --k; // while previous vector size is compact, decrement + // reasons to not do it: + // * constructor(n) is not ready to accept fragmented segments + // * backward compatibility due to that constructor + // * current version gives additional guarantee and faster init. + // * two calls to reserve() will give the same effect. + */ + v.my_first_block.compare_and_swap(k+1, 0); // store number of segments + } + } + + inline static void *allocate_segment(concurrent_vector_base_v3 &v, size_type n) { + void *ptr = v.vector_allocator_ptr(v, n); + if(!ptr) throw_exception(eid_bad_alloc); // check for bad allocation, throw exception + return ptr; + } + + //! Publish segment so other threads can see it. + inline static void publish_segment( segment_t& s, void* rhs ) { + // see also itt_store_pointer_with_release_v3() + ITT_NOTIFY( sync_releasing, &s.array ); + __TBB_store_with_release( s.array, rhs ); + } + + static size_type enable_segment(concurrent_vector_base_v3 &v, size_type k, size_type element_size); + + // TODO: rename as get_segments_table() and return segment pointer + inline static void extend_table_if_necessary(concurrent_vector_base_v3 &v, size_type k, size_type start ) { + if(k >= pointers_per_short_table && v.my_segment == v.my_storage) + extend_segment_table(v, start ); + } + + static void extend_segment_table(concurrent_vector_base_v3 &v, size_type start); + + inline static segment_t &acquire_segment(concurrent_vector_base_v3 &v, size_type index, size_type element_size, bool owner) { + segment_t &s = v.my_segment[index]; // TODO: pass v.my_segment as argument + if( !__TBB_load_with_acquire(s.array) ) { // do not check for internal::vector_allocation_error_flag + if( owner ) { + enable_segment( v, index, element_size ); + } else { + ITT_NOTIFY(sync_prepare, &s.array); + spin_wait_while_eq( s.array, (void*)0 ); + ITT_NOTIFY(sync_acquired, &s.array); + } + } else { + ITT_NOTIFY(sync_acquired, &s.array); + } + if( s.array <= internal::vector_allocation_error_flag ) // check for internal::vector_allocation_error_flag + throw_exception(eid_bad_last_alloc); // throw custom exception, because it's hard to recover after internal::vector_allocation_error_flag correctly + return s; + } + + ///// non-static fields of helper for exception-safe iteration across segments + segment_t *table;// TODO: review all segment_index_t as just short type + size_type first_block, k, sz, start, finish, element_size; + helper(segment_t *segments, size_type fb, size_type esize, size_type index, size_type s, size_type f) throw() + : table(segments), first_block(fb), k(index), sz(0), start(s), finish(f), element_size(esize) {} + inline void first_segment() throw() { + __TBB_ASSERT( start <= finish, NULL ); + __TBB_ASSERT( first_block || !finish, NULL ); + if( k < first_block ) k = 0; // process solid segment at a time + size_type base = segment_base( k ); + __TBB_ASSERT( base <= start, NULL ); + finish -= base; start -= base; // rebase as offsets from segment k + sz = k ? base : segment_size( first_block ); // sz==base for k>0 + } + inline void next_segment() throw() { + finish -= sz; start = 0; // offsets from next segment + if( !k ) k = first_block; + else { ++k; sz <<= 1; } + } + template<typename F> + inline size_type apply(const F &func) { + first_segment(); + while( sz < finish ) { // work for more than one segment + func( table[k], static_cast<char*>(table[k].array)+element_size*start, sz-start ); + next_segment(); + } + func( table[k], static_cast<char*>(table[k].array)+element_size*start, finish-start ); + return k; + } + inline void *get_segment_ptr(size_type index, bool wait) { + segment_t &s = table[index]; + if( !__TBB_load_with_acquire(s.array) && wait ) { + ITT_NOTIFY(sync_prepare, &s.array); + spin_wait_while_eq( s.array, (void*)0 ); + ITT_NOTIFY(sync_acquired, &s.array); + } + return s.array; + } + ~helper() { + if( sz >= finish ) return; // the work is done correctly + cleanup(); + } + + //! Out of line code to assists destructor in infrequent cases. + void cleanup(); + + /// TODO: turn into lambda functions when available + struct init_body { + internal_array_op2 func; + const void *arg; + init_body(internal_array_op2 init, const void *src) : func(init), arg(src) {} + void operator()(segment_t &, void *begin, size_type n) const { + func( begin, arg, n ); + } + }; + struct safe_init_body { + internal_array_op2 func; + const void *arg; + safe_init_body(internal_array_op2 init, const void *src) : func(init), arg(src) {} + void operator()(segment_t &s, void *begin, size_type n) const { + if( s.array <= internal::vector_allocation_error_flag ) + throw_exception(eid_bad_last_alloc); // throw custom exception + func( begin, arg, n ); + } + }; + struct destroy_body { + internal_array_op1 func; + destroy_body(internal_array_op1 destroy) : func(destroy) {} + void operator()(segment_t &s, void *begin, size_type n) const { + if( s.array > internal::vector_allocation_error_flag ) + func( begin, n ); + } + }; +}; + +void concurrent_vector_base_v3::helper::extend_segment_table(concurrent_vector_base_v3 &v, concurrent_vector_base_v3::size_type start) { + if( start > segment_size(pointers_per_short_table) ) start = segment_size(pointers_per_short_table); + // If other threads are trying to set pointers in the short segment, wait for them to finish their + // assignments before we copy the short segment to the long segment. Note: grow_to_at_least depends on it + for( segment_index_t i = 0; segment_base(i) < start && v.my_segment == v.my_storage; i++ ){ + if(!v.my_storage[i].array) { + ITT_NOTIFY(sync_prepare, &v.my_storage[i].array); + atomic_backoff backoff; + do backoff.pause(); while( v.my_segment == v.my_storage && !v.my_storage[i].array ); + ITT_NOTIFY(sync_acquired, &v.my_storage[i].array); + } + } + if( v.my_segment != v.my_storage ) return; + + segment_t* s = (segment_t*)NFS_Allocate( pointers_per_long_table, sizeof(segment_t), NULL ); + // No need to check !s here, because NFS_Allocate throws exception if it cannot allocate the requested storage. + std::memset( s, 0, pointers_per_long_table*sizeof(segment_t) ); + for( segment_index_t i = 0; i < pointers_per_short_table; i++) + s[i] = v.my_storage[i]; + if( v.my_segment.compare_and_swap( s, v.my_storage ) != v.my_storage ) + NFS_Free( s ); + // else TODO: add ITT_NOTIFY signals for v.my_segment? +} + +concurrent_vector_base_v3::size_type concurrent_vector_base_v3::helper::enable_segment(concurrent_vector_base_v3 &v, concurrent_vector_base_v3::size_type k, concurrent_vector_base_v3::size_type element_size) { + segment_t* s = v.my_segment; // TODO: optimize out as argument? Optimize accesses to my_first_block + __TBB_ASSERT( s[k].array <= internal::vector_allocation_error_flag, "concurrent operation during growth?" ); + if( !k ) { + assign_first_segment_if_neccessary(v, default_initial_segments-1); + __TBB_TRY { + publish_segment(s[0], allocate_segment(v, segment_size(v.my_first_block) ) ); + } __TBB_CATCH(...) { // intercept exception here, assign internal::vector_allocation_error_flag value, re-throw exception + publish_segment(s[0], internal::vector_allocation_error_flag); + __TBB_RETHROW(); + } + return 2; + } + size_type m = segment_size(k); + if( !v.my_first_block ) // push_back only + spin_wait_while_eq( v.my_first_block, segment_index_t(0) ); + if( k < v.my_first_block ) { + // s[0].array is changed only once ( 0 -> !0 ) and points to uninitialized memory + void *array0 = __TBB_load_with_acquire(s[0].array); + if( !array0 ) { + // sync_prepare called only if there is a wait + ITT_NOTIFY(sync_prepare, &s[0].array ); + spin_wait_while_eq( s[0].array, (void*)0 ); + array0 = __TBB_load_with_acquire(s[0].array); + } + ITT_NOTIFY(sync_acquired, &s[0].array); + if( array0 <= internal::vector_allocation_error_flag ) { // check for internal::vector_allocation_error_flag of initial segment + publish_segment(s[k], internal::vector_allocation_error_flag); // and assign internal::vector_allocation_error_flag here + throw_exception(eid_bad_last_alloc); // throw custom exception + } + publish_segment( s[k], + static_cast<void*>( static_cast<char*>(array0) + segment_base(k)*element_size ) + ); + } else { + __TBB_TRY { + publish_segment(s[k], allocate_segment(v, m)); + } __TBB_CATCH(...) { // intercept exception here, assign internal::vector_allocation_error_flag value, re-throw exception + publish_segment(s[k], internal::vector_allocation_error_flag); + __TBB_RETHROW(); + } + } + return m; +} + +void concurrent_vector_base_v3::helper::cleanup() { + if( !sz ) { // allocation failed, restore the table + segment_index_t k_start = k, k_end = segment_index_of(finish-1); + if( segment_base( k_start ) < start ) + get_segment_ptr(k_start++, true); // wait + if( k_start < first_block ) { + void *array0 = get_segment_ptr(0, start>0); // wait if necessary + if( array0 && !k_start ) ++k_start; + if( array0 <= internal::vector_allocation_error_flag ) + for(; k_start < first_block && k_start <= k_end; ++k_start ) + publish_segment(table[k_start], internal::vector_allocation_error_flag); + else for(; k_start < first_block && k_start <= k_end; ++k_start ) + publish_segment(table[k_start], static_cast<void*>( + static_cast<char*>(array0) + segment_base(k_start)*element_size) ); + } + for(; k_start <= k_end; ++k_start ) // not in first block + if( !__TBB_load_with_acquire(table[k_start].array) ) + publish_segment(table[k_start], internal::vector_allocation_error_flag); + // fill allocated items + first_segment(); + goto recover; + } + while( sz <= finish ) { // there is still work for at least one segment + next_segment(); +recover: + void *array = table[k].array; + if( array > internal::vector_allocation_error_flag ) + std::memset( static_cast<char*>(array)+element_size*start, 0, ((sz<finish?sz:finish) - start)*element_size ); + else __TBB_ASSERT( array == internal::vector_allocation_error_flag, NULL ); + } +} + +concurrent_vector_base_v3::~concurrent_vector_base_v3() { + segment_t* s = my_segment; + if( s != my_storage ) { + // Clear short segment. + for( segment_index_t i = 0; i < pointers_per_short_table; i++) + my_storage[i].array = NULL; +#if TBB_USE_DEBUG + for( segment_index_t i = 0; i < pointers_per_long_table; i++) + __TBB_ASSERT( my_segment[i].array <= internal::vector_allocation_error_flag, "Segment should have been freed. Please recompile with new TBB before using exceptions."); +#endif + my_segment = my_storage; + NFS_Free( s ); + } +} + +concurrent_vector_base_v3::size_type concurrent_vector_base_v3::internal_capacity() const { + return segment_base( helper::find_segment_end(*this) ); +} + +void concurrent_vector_base_v3::internal_throw_exception(size_type t) const { + switch(t) { + case 0: throw_exception(eid_out_of_range); + case 1: throw_exception(eid_segment_range_error); + case 2: throw_exception(eid_index_range_error); + } +} + +void concurrent_vector_base_v3::internal_reserve( size_type n, size_type element_size, size_type max_size ) { + if( n>max_size ) + throw_exception(eid_reservation_length_error); + __TBB_ASSERT( n, NULL ); + helper::assign_first_segment_if_neccessary(*this, segment_index_of(n-1)); + segment_index_t k = helper::find_segment_end(*this); + __TBB_TRY { + for( ; segment_base(k)<n; ++k ) { + helper::extend_table_if_necessary(*this, k, 0); + if(my_segment[k].array <= internal::vector_allocation_error_flag) + helper::enable_segment(*this, k, element_size); + } + } __TBB_CATCH(...) { + my_segment[k].array = NULL; + __TBB_RETHROW(); // repair and rethrow + } +} + +void concurrent_vector_base_v3::internal_copy( const concurrent_vector_base_v3& src, size_type element_size, internal_array_op2 copy ) { + size_type n = src.my_early_size; + __TBB_ASSERT( my_segment == my_storage, NULL); + if( n ) { + helper::assign_first_segment_if_neccessary(*this, segment_index_of(n-1)); + size_type b; + for( segment_index_t k=0; (b=segment_base(k))<n; ++k ) { + if( (src.my_segment == (segment_t*)src.my_storage && k >= pointers_per_short_table) + || src.my_segment[k].array <= internal::vector_allocation_error_flag ) { + my_early_size = b; break; + } + helper::extend_table_if_necessary(*this, k, 0); + size_type m = helper::enable_segment(*this, k, element_size); + if( m > n-b ) m = n-b; + my_early_size = b+m; + copy( my_segment[k].array, src.my_segment[k].array, m ); + } + } +} + +void concurrent_vector_base_v3::internal_assign( const concurrent_vector_base_v3& src, size_type element_size, internal_array_op1 destroy, internal_array_op2 assign, internal_array_op2 copy ) { + size_type n = src.my_early_size; + while( my_early_size>n ) { // TODO: improve + segment_index_t k = segment_index_of( my_early_size-1 ); + size_type b=segment_base(k); + size_type new_end = b>=n ? b : n; + __TBB_ASSERT( my_early_size>new_end, NULL ); + if( my_segment[k].array <= internal::vector_allocation_error_flag) // check vector was broken before + throw_exception(eid_bad_last_alloc); // throw custom exception + // destructors are supposed to not throw any exceptions + destroy( (char*)my_segment[k].array+element_size*(new_end-b), my_early_size-new_end ); + my_early_size = new_end; + } + size_type dst_initialized_size = my_early_size; + my_early_size = n; + helper::assign_first_segment_if_neccessary(*this, segment_index_of(n)); + size_type b; + for( segment_index_t k=0; (b=segment_base(k))<n; ++k ) { + if( (src.my_segment == (segment_t*)src.my_storage && k >= pointers_per_short_table) + || src.my_segment[k].array <= internal::vector_allocation_error_flag ) { // if source is damaged + my_early_size = b; break; // TODO: it may cause undestructed items + } + helper::extend_table_if_necessary(*this, k, 0); + if( !my_segment[k].array ) + helper::enable_segment(*this, k, element_size); + else if( my_segment[k].array <= internal::vector_allocation_error_flag ) + throw_exception(eid_bad_last_alloc); // throw custom exception + size_type m = k? segment_size(k) : 2; + if( m > n-b ) m = n-b; + size_type a = 0; + if( dst_initialized_size>b ) { + a = dst_initialized_size-b; + if( a>m ) a = m; + assign( my_segment[k].array, src.my_segment[k].array, a ); + m -= a; + a *= element_size; + } + if( m>0 ) + copy( (char*)my_segment[k].array+a, (char*)src.my_segment[k].array+a, m ); + } + __TBB_ASSERT( src.my_early_size==n, "detected use of concurrent_vector::operator= with right side that was concurrently modified" ); +} + +void* concurrent_vector_base_v3::internal_push_back( size_type element_size, size_type& index ) { + __TBB_ASSERT( sizeof(my_early_size)==sizeof(uintptr_t), NULL ); + size_type tmp = __TBB_FetchAndIncrementWacquire(&my_early_size); + index = tmp; + segment_index_t k_old = segment_index_of( tmp ); + size_type base = segment_base(k_old); + helper::extend_table_if_necessary(*this, k_old, tmp); + segment_t& s = helper::acquire_segment(*this, k_old, element_size, base==tmp); + size_type j_begin = tmp-base; + return (void*)((char*)s.array+element_size*j_begin); +} + +void concurrent_vector_base_v3::internal_grow_to_at_least( size_type new_size, size_type element_size, internal_array_op2 init, const void *src ) { + internal_grow_to_at_least_with_result( new_size, element_size, init, src ); +} + +concurrent_vector_base_v3::size_type concurrent_vector_base_v3::internal_grow_to_at_least_with_result( size_type new_size, size_type element_size, internal_array_op2 init, const void *src ) { + size_type e = my_early_size; + while( e<new_size ) { + size_type f = my_early_size.compare_and_swap(new_size,e); + if( f==e ) { + internal_grow( e, new_size, element_size, init, src ); + break; + } + e = f; + } + // Check/wait for segments allocation completes + segment_index_t i, k_old = segment_index_of( new_size-1 ); + if( k_old >= pointers_per_short_table && my_segment == my_storage ) { + spin_wait_while_eq( my_segment, my_storage ); + } + for( i = 0; i <= k_old; ++i ) { + segment_t &s = my_segment[i]; + if(!s.array) { + ITT_NOTIFY(sync_prepare, &s.array); + atomic_backoff backoff; + do backoff.pause(); + while( !__TBB_load_with_acquire(my_segment[i].array) ); // my_segment may change concurrently + ITT_NOTIFY(sync_acquired, &s.array); + } + if( my_segment[i].array <= internal::vector_allocation_error_flag ) + throw_exception(eid_bad_last_alloc); + } +#if TBB_USE_DEBUG + size_type capacity = internal_capacity(); + __TBB_ASSERT( capacity >= new_size, NULL); +#endif + return e; +} + +concurrent_vector_base_v3::size_type concurrent_vector_base_v3::internal_grow_by( size_type delta, size_type element_size, internal_array_op2 init, const void *src ) { + size_type result = my_early_size.fetch_and_add(delta); + internal_grow( result, result+delta, element_size, init, src ); + return result; +} + +void concurrent_vector_base_v3::internal_grow( const size_type start, size_type finish, size_type element_size, internal_array_op2 init, const void *src ) { + __TBB_ASSERT( start<finish, "start must be less than finish" ); + segment_index_t k_start = segment_index_of(start), k_end = segment_index_of(finish-1); + helper::assign_first_segment_if_neccessary(*this, k_end); + helper::extend_table_if_necessary(*this, k_end, start); + helper range(my_segment, my_first_block, element_size, k_start, start, finish); + for(; k_end > k_start && k_end >= range.first_block; --k_end ) // allocate segments in reverse order + helper::acquire_segment(*this, k_end, element_size, true/*for k_end>k_start*/); + for(; k_start <= k_end; ++k_start ) // but allocate first block in straight order + helper::acquire_segment(*this, k_start, element_size, segment_base( k_start ) >= start ); + range.apply( helper::init_body(init, src) ); +} + +void concurrent_vector_base_v3::internal_resize( size_type n, size_type element_size, size_type max_size, const void *src, + internal_array_op1 destroy, internal_array_op2 init ) { + size_type j = my_early_size; + if( n > j ) { // construct items + internal_reserve(n, element_size, max_size); + my_early_size = n; + helper for_each(my_segment, my_first_block, element_size, segment_index_of(j), j, n); + for_each.apply( helper::safe_init_body(init, src) ); + } else { + my_early_size = n; + helper for_each(my_segment, my_first_block, element_size, segment_index_of(n), n, j); + for_each.apply( helper::destroy_body(destroy) ); + } +} + +concurrent_vector_base_v3::segment_index_t concurrent_vector_base_v3::internal_clear( internal_array_op1 destroy ) { + __TBB_ASSERT( my_segment, NULL ); + size_type j = my_early_size; + my_early_size = 0; + helper for_each(my_segment, my_first_block, 0, 0, 0, j); // element_size is safe to be zero if 'start' is zero + j = for_each.apply( helper::destroy_body(destroy) ); + size_type i = helper::find_segment_end(*this); + return j < i? i : j+1; +} + +void *concurrent_vector_base_v3::internal_compact( size_type element_size, void *table, internal_array_op1 destroy, internal_array_op2 copy ) +{ + const size_type my_size = my_early_size; + const segment_index_t k_end = helper::find_segment_end(*this); // allocated segments + const segment_index_t k_stop = my_size? segment_index_of(my_size-1) + 1 : 0; // number of segments to store existing items: 0=>0; 1,2=>1; 3,4=>2; [5-8]=>3;.. + const segment_index_t first_block = my_first_block; // number of merged segments, getting values from atomics + + segment_index_t k = first_block; + if(k_stop < first_block) + k = k_stop; + else + while (k < k_stop && helper::incompact_predicate(segment_size( k ) * element_size) ) k++; + if(k_stop == k_end && k == first_block) + return NULL; + + segment_t *const segment_table = my_segment; + internal_segments_table &old = *static_cast<internal_segments_table*>( table ); + std::memset(&old, 0, sizeof(old)); + + if ( k != first_block && k ) // first segment optimization + { + // exception can occur here + void *seg = old.table[0] = helper::allocate_segment( *this, segment_size(k) ); + old.first_block = k; // fill info for freeing new segment if exception occurs + // copy items to the new segment + size_type my_segment_size = segment_size( first_block ); + for (segment_index_t i = 0, j = 0; i < k && j < my_size; j = my_segment_size) { + __TBB_ASSERT( segment_table[i].array > internal::vector_allocation_error_flag, NULL); + void *s = static_cast<void*>( + static_cast<char*>(seg) + segment_base(i)*element_size ); + if(j + my_segment_size >= my_size) my_segment_size = my_size - j; + __TBB_TRY { // exception can occur here + copy( s, segment_table[i].array, my_segment_size ); + } __TBB_CATCH(...) { // destroy all the already copied items + helper for_each(reinterpret_cast<segment_t*>(&old.table[0]), old.first_block, element_size, + 0, 0, segment_base(i)+my_segment_size); + for_each.apply( helper::destroy_body(destroy) ); + __TBB_RETHROW(); + } + my_segment_size = i? segment_size( ++i ) : segment_size( i = first_block ); + } + // commit the changes + memcpy(old.table, segment_table, k * sizeof(segment_t)); + for (segment_index_t i = 0; i < k; i++) { + segment_table[i].array = static_cast<void*>( + static_cast<char*>(seg) + segment_base(i)*element_size ); + } + old.first_block = first_block; my_first_block = k; // now, first_block != my_first_block + // destroy original copies + my_segment_size = segment_size( first_block ); // old.first_block actually + for (segment_index_t i = 0, j = 0; i < k && j < my_size; j = my_segment_size) { + if(j + my_segment_size >= my_size) my_segment_size = my_size - j; + // destructors are supposed to not throw any exceptions + destroy( old.table[i], my_segment_size ); + my_segment_size = i? segment_size( ++i ) : segment_size( i = first_block ); + } + } + // free unnecessary segments allocated by reserve() call + if ( k_stop < k_end ) { + old.first_block = first_block; + memcpy(old.table+k_stop, segment_table+k_stop, (k_end-k_stop) * sizeof(segment_t)); + std::memset(segment_table+k_stop, 0, (k_end-k_stop) * sizeof(segment_t)); + if( !k ) my_first_block = 0; + } + return table; +} + +void concurrent_vector_base_v3::internal_swap(concurrent_vector_base_v3& v) +{ + size_type my_sz = my_early_size, v_sz = v.my_early_size; + if(!my_sz && !v_sz) return; + size_type tmp = my_first_block; my_first_block = v.my_first_block; v.my_first_block = tmp; + bool my_short = (my_segment == my_storage), v_short = (v.my_segment == v.my_storage); + if ( my_short && v_short ) { // swap both tables + char tbl[pointers_per_short_table * sizeof(segment_t)]; + memcpy(tbl, my_storage, pointers_per_short_table * sizeof(segment_t)); + memcpy(my_storage, v.my_storage, pointers_per_short_table * sizeof(segment_t)); + memcpy(v.my_storage, tbl, pointers_per_short_table * sizeof(segment_t)); + } + else if ( my_short ) { // my -> v + memcpy(v.my_storage, my_storage, pointers_per_short_table * sizeof(segment_t)); + my_segment = v.my_segment; v.my_segment = v.my_storage; + } + else if ( v_short ) { // v -> my + memcpy(my_storage, v.my_storage, pointers_per_short_table * sizeof(segment_t)); + v.my_segment = my_segment; my_segment = my_storage; + } else { + segment_t *ptr = my_segment; my_segment = v.my_segment; v.my_segment = ptr; + } + my_early_size = v_sz; v.my_early_size = my_sz; +} + +} // namespace internal + +} // tbb diff --git a/src/tbb/src/tbb/condition_variable.cpp b/src/tbb/src/tbb/condition_variable.cpp new file mode 100644 index 0000000..e757a16 --- /dev/null +++ b/src/tbb/src/tbb/condition_variable.cpp @@ -0,0 +1,205 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/compat/condition_variable" +#include "tbb/atomic.h" +#include "tbb_misc.h" +#include "dynamic_link.h" +#include "itt_notify.h" + +namespace tbb { + +namespace internal { + +//condition_variable +#if _WIN32||_WIN64 +using tbb::interface5::internal::condition_variable_using_event; + +static atomic<do_once_state> condvar_api_state; + +void WINAPI init_condvar_using_event( condition_variable_using_event* cv_event ) +{ + cv_event->event = CreateEvent( NULL, TRUE/*manual reset*/, FALSE/*not signalled initially*/, NULL); + InitializeCriticalSection( &cv_event->mutex ); + cv_event->n_waiters = 0; + cv_event->release_count = 0; + cv_event->epoch = 0; +} + +BOOL WINAPI sleep_condition_variable_cs_using_event( condition_variable_using_event* cv_event, LPCRITICAL_SECTION cs, DWORD dwMilliseconds ) +{ + EnterCriticalSection( &cv_event->mutex ); + ++cv_event->n_waiters; + unsigned my_generation = cv_event->epoch; + LeaveCriticalSection( &cv_event->mutex ); + LeaveCriticalSection( cs ); + for (;;) { + // should come here at least once + DWORD rc = WaitForSingleObject( cv_event->event, dwMilliseconds ); + EnterCriticalSection( &cv_event->mutex ); + if( rc!=WAIT_OBJECT_0 ) { + --cv_event->n_waiters; + LeaveCriticalSection( &cv_event->mutex ); + if( rc==WAIT_TIMEOUT ) { + SetLastError( WAIT_TIMEOUT ); + EnterCriticalSection( cs ); + } + return false; + } + __TBB_ASSERT( rc==WAIT_OBJECT_0, NULL ); + if( cv_event->release_count>0 && cv_event->epoch!=my_generation ) + break; + LeaveCriticalSection( &cv_event->mutex ); + } + + // still in the critical section + --cv_event->n_waiters; + int count = --cv_event->release_count; + LeaveCriticalSection( &cv_event->mutex ); + + if( count==0 ) { + __TBB_ASSERT( cv_event->event, "Premature destruction of condition variable?" ); + ResetEvent( cv_event->event ); + } + EnterCriticalSection( cs ); + return true; +} + +void WINAPI wake_condition_variable_using_event( condition_variable_using_event* cv_event ) +{ + EnterCriticalSection( &cv_event->mutex ); + if( cv_event->n_waiters>cv_event->release_count ) { + SetEvent( cv_event->event ); // Signal the manual-reset event. + ++cv_event->release_count; + ++cv_event->epoch; + } + LeaveCriticalSection( &cv_event->mutex ); +} + +void WINAPI wake_all_condition_variable_using_event( condition_variable_using_event* cv_event ) +{ + EnterCriticalSection( &cv_event->mutex ); + if( cv_event->n_waiters>0 ) { + SetEvent( cv_event->event ); + cv_event->release_count = cv_event->n_waiters; + ++cv_event->epoch; + } + LeaveCriticalSection( &cv_event->mutex ); +} + +void WINAPI destroy_condvar_using_event( condition_variable_using_event* cv_event ) +{ + HANDLE my_event = cv_event->event; + EnterCriticalSection( &cv_event->mutex ); + // NULL is an invalid HANDLE value + cv_event->event = NULL; + if( cv_event->n_waiters>0 ) { + LeaveCriticalSection( &cv_event->mutex ); + spin_wait_until_eq( cv_event->n_waiters, 0 ); + // make sure the last thread completes its access to cv + EnterCriticalSection( &cv_event->mutex ); + } + LeaveCriticalSection( &cv_event->mutex ); + CloseHandle( my_event ); +} + +void WINAPI destroy_condvar_noop( CONDITION_VARIABLE* /*cv*/ ) { /*no op*/ } + +static void (WINAPI *__TBB_init_condvar)( PCONDITION_VARIABLE ) = (void (WINAPI *)(PCONDITION_VARIABLE))&init_condvar_using_event; +static BOOL (WINAPI *__TBB_condvar_wait)( PCONDITION_VARIABLE, LPCRITICAL_SECTION, DWORD ) = (BOOL (WINAPI *)(PCONDITION_VARIABLE,LPCRITICAL_SECTION, DWORD))&sleep_condition_variable_cs_using_event; +static void (WINAPI *__TBB_condvar_notify_one)( PCONDITION_VARIABLE ) = (void (WINAPI *)(PCONDITION_VARIABLE))&wake_condition_variable_using_event; +static void (WINAPI *__TBB_condvar_notify_all)( PCONDITION_VARIABLE ) = (void (WINAPI *)(PCONDITION_VARIABLE))&wake_all_condition_variable_using_event; +static void (WINAPI *__TBB_destroy_condvar)( PCONDITION_VARIABLE ) = (void (WINAPI *)(PCONDITION_VARIABLE))&destroy_condvar_using_event; + +//! Table describing how to link the handlers. +static const dynamic_link_descriptor CondVarLinkTable[] = { + DLD(InitializeConditionVariable, __TBB_init_condvar), + DLD(SleepConditionVariableCS, __TBB_condvar_wait), + DLD(WakeConditionVariable, __TBB_condvar_notify_one), + DLD(WakeAllConditionVariable, __TBB_condvar_notify_all) +}; + +void init_condvar_module() +{ + __TBB_ASSERT( (uintptr_t)__TBB_init_condvar==(uintptr_t)&init_condvar_using_event, NULL ); + if( dynamic_link( GetModuleHandle( "Kernel32.dll" ), CondVarLinkTable, 4 ) ) + __TBB_destroy_condvar = (void (WINAPI *)(PCONDITION_VARIABLE))&destroy_condvar_noop; +} +#endif /* _WIN32||_WIN64 */ + +} // namespace internal + +#if _WIN32||_WIN64 + +namespace interface5 { +namespace internal { + +using tbb::internal::condvar_api_state; +using tbb::internal::__TBB_init_condvar; +using tbb::internal::__TBB_condvar_wait; +using tbb::internal::__TBB_condvar_notify_one; +using tbb::internal::__TBB_condvar_notify_all; +using tbb::internal::__TBB_destroy_condvar; +using tbb::internal::init_condvar_module; + +void internal_initialize_condition_variable( condvar_impl_t& cv ) +{ + atomic_do_once( &init_condvar_module, condvar_api_state ); + __TBB_init_condvar( &cv.cv_native ); +} + +void internal_destroy_condition_variable( condvar_impl_t& cv ) +{ + __TBB_destroy_condvar( &cv.cv_native ); +} + +void internal_condition_variable_notify_one( condvar_impl_t& cv ) +{ + __TBB_condvar_notify_one ( &cv.cv_native ); +} + +void internal_condition_variable_notify_all( condvar_impl_t& cv ) +{ + __TBB_condvar_notify_all( &cv.cv_native ); +} + +bool internal_condition_variable_wait( condvar_impl_t& cv, mutex* mtx, const tick_count::interval_t* i ) +{ + DWORD duration = i ? DWORD((i->seconds()*1000)) : INFINITE; + mtx->set_state( mutex::INITIALIZED ); + BOOL res = __TBB_condvar_wait( &cv.cv_native, mtx->native_handle(), duration ); + mtx->set_state( mutex::HELD ); + return res?true:false; +} + +} // namespace internal +} // nameespace interface5 + +#endif /* _WIN32||_WIN64 */ + +} // namespace tbb diff --git a/src/tbb/src/tbb/critical_section.cpp b/src/tbb/src/tbb/critical_section.cpp new file mode 100644 index 0000000..83deebe --- /dev/null +++ b/src/tbb/src/tbb/critical_section.cpp @@ -0,0 +1,39 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/critical_section.h" +#include "itt_notify.h" + +namespace tbb { + namespace internal { + +void critical_section_v4::internal_construct() { + ITT_SYNC_CREATE(&my_impl, _T("ppl::critical_section"), _T("")); +} +} // namespace internal +} // namespace tbb diff --git a/src/tbb/src/tbb/custom_scheduler.h b/src/tbb/src/tbb/custom_scheduler.h new file mode 100644 index 0000000..b0ec8e8 --- /dev/null +++ b/src/tbb/src/tbb/custom_scheduler.h @@ -0,0 +1,618 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _TBB_custom_scheduler_H +#define _TBB_custom_scheduler_H + +#include "scheduler.h" +#include "observer_proxy.h" +#include "itt_notify.h" + +namespace tbb { +namespace internal { + +//! Amount of time to pause between steals. +/** The default values below were found to be best empirically for K-Means + on the 32-way Altix and 4-way (*2 for HT) fxqlin04. */ +#if __TBB_ipf +static const long PauseTime = 1500; +#else +static const long PauseTime = 80; +#endif + +//------------------------------------------------------------------------ +//! Traits classes for scheduler +//------------------------------------------------------------------------ + +struct DefaultSchedulerTraits { + static const bool itt_possible = true; + static const bool has_slow_atomic = false; +}; + +struct IntelSchedulerTraits { + static const bool itt_possible = false; +#if __TBB_x86_32||__TBB_x86_64 + static const bool has_slow_atomic = true; +#else + static const bool has_slow_atomic = false; +#endif /* __TBB_x86_32||__TBB_x86_64 */ +}; + +//------------------------------------------------------------------------ +// custom_scheduler +//------------------------------------------------------------------------ + +//! A scheduler with a customized evaluation loop. +/** The customization can use SchedulerTraits to make decisions without needing a run-time check. */ +template<typename SchedulerTraits> +class custom_scheduler: private generic_scheduler { + typedef custom_scheduler<SchedulerTraits> scheduler_type; + + //! Scheduler loop that dispatches tasks. + /** If child is non-NULL, it is dispatched first. + Then, until "parent" has a reference count of 1, other task are dispatched or stolen. */ + /*override*/ + void local_wait_for_all( task& parent, task* child ); + + //! Entry point from client code to the scheduler loop that dispatches tasks. + /** The method is virtual, but the *this object is used only for sake of dispatching on the correct vtable, + not necessarily the correct *this object. The correct *this object is looked up in TLS. */ + /*override*/ + void wait_for_all( task& parent, task* child ) { + static_cast<custom_scheduler*>(governor::local_scheduler())->scheduler_type::local_wait_for_all( parent, child ); + } + + //! Construct a custom_scheduler + custom_scheduler( arena* a, size_t index ) : generic_scheduler(a, index) {} + + //! Decrements ref_count of a predecessor. + /** If it achieves 0, the predecessor is scheduled for execution. + When changing, remember that this is a hot path function. */ + void tally_completion_of_predecessor( task& s, task*& bypass_slot ) { + task_prefix& p = s.prefix(); + if( SchedulerTraits::itt_possible ) + ITT_NOTIFY(sync_releasing, &p.ref_count); + if( SchedulerTraits::has_slow_atomic && p.ref_count==1 ) + p.ref_count=0; + else if( __TBB_FetchAndDecrementWrelease(&p.ref_count) > 1 ) // more references exist + return; + + // Ordering on p.ref_count (superfluous if SchedulerTraits::has_slow_atomic) + __TBB_control_consistency_helper(); + __TBB_ASSERT(p.ref_count==0, "completion of task caused predecessor's reference count to underflow"); + if( SchedulerTraits::itt_possible ) + ITT_NOTIFY(sync_acquired, &p.ref_count); +#if TBB_USE_ASSERT + p.extra_state &= ~es_ref_count_active; +#endif /* TBB_USE_ASSERT */ + + if( bypass_slot==NULL ) + bypass_slot = &s; + else + local_spawn( s, s.prefix().next ); + } + +public: + static generic_scheduler* allocate_scheduler( arena* a, size_t index ) { + scheduler_type* s = (scheduler_type*)NFS_Allocate(sizeof(scheduler_type),1,NULL); + new( s ) scheduler_type( a, index ); + s->assert_task_pool_valid(); + ITT_SYNC_CREATE(s, SyncType_Scheduler, SyncObj_TaskPoolSpinning); + return s; + } + + //! Try getting a task from the mailbox or stealing from another scheduler. + /** Returns the stolen task or NULL if all attempts fail. */ + /* override */ task* receive_or_steal_task( __TBB_atomic reference_count& completion_ref_count, bool return_if_no_work ); + +}; // class custom_scheduler<> + +//------------------------------------------------------------------------ +// custom_scheduler methods +//------------------------------------------------------------------------ + +template<typename SchedulerTraits> +task* custom_scheduler<SchedulerTraits>::receive_or_steal_task( __TBB_atomic reference_count& completion_ref_count, + bool return_if_no_work ) { + task* t = NULL; + bool outermost_dispatch_level = return_if_no_work || master_outermost_level(); + my_inbox.set_is_idle( true ); +#if __TBB_TASK_PRIORITY + if ( return_if_no_work && my_arena->my_skipped_fifo_priority ) { + // This thread can dequeue FIFO tasks, and some priority levels of + // FIFO tasks have been bypassed (to prevent deadlock caused by + // dynamic priority changes in nested task group hierarchy). + intptr_t skipped_priority = my_arena->my_skipped_fifo_priority; + if ( my_arena->my_skipped_fifo_priority.compare_and_swap(0, skipped_priority) == skipped_priority && + skipped_priority > my_arena->my_top_priority ) + { + my_market->update_arena_priority( *my_arena, skipped_priority ); + } + } +#endif /* __TBB_TASK_PRIORITY */ + // The state "failure_count==-1" is used only when itt_possible is true, + // and denotes that a sync_prepare has not yet been issued. + for( int failure_count = -static_cast<int>(SchedulerTraits::itt_possible);; ++failure_count) { + if( completion_ref_count==1 ) { + if( SchedulerTraits::itt_possible ) { + if( failure_count!=-1 ) { + ITT_NOTIFY(sync_prepare, &completion_ref_count); + // Notify Intel(R) Thread Profiler that thread has stopped spinning. + ITT_NOTIFY(sync_acquired, this); + } + ITT_NOTIFY(sync_acquired, &completion_ref_count); + } + __TBB_ASSERT( !t, NULL ); + __TBB_control_consistency_helper(); // on ref_count + break; // exit stealing loop and return; + } + __TBB_ASSERT( my_arena->my_limit > 0, NULL ); + size_t n = my_arena->my_limit; + __TBB_ASSERT( my_arena_index < n, NULL ); + if ( n > 1 ) { + // Check if the resource manager requires our arena to relinquish some threads + if ( return_if_no_work && my_arena->my_num_workers_allotted < my_arena->num_workers_active() ) { + __TBB_ASSERT( is_worker(), NULL ); + if( SchedulerTraits::itt_possible && failure_count != -1 ) + ITT_NOTIFY(sync_cancel, this); + return NULL; + } + // Check if there are tasks mailed to this thread via task-to-thread affinity mechanism. + if ( my_affinity_id && (t=get_mailbox_task()) ) { + GATHER_STATISTIC( ++my_counters.mails_received ); + } + // Check if there are tasks in starvation-resistant stream. + // Only allowed for workers with empty stack, which is identified by return_if_no_work. + else if ( outermost_dispatch_level && (t = dequeue_task()) ) { + // just proceed with the obtained task + } +#if __TBB_TASK_PRIORITY + // Check if any earlier offloaded non-top priority tasks become returned to the top level + else if ( my_offloaded_tasks && (t=reload_tasks()) ) { + // just proceed with the obtained task + } +#endif /* __TBB_TASK_PRIORITY */ + else if ( can_steal() && n > 1 ) { + // Try to steal a task from a random victim. + size_t k = my_random.get() % (n - 1); + arena_slot* victim = &my_arena->my_slots[k]; + // The following condition excludes the master that might have + // already taken our previous place in the arena from the list . + // of potential victims. But since such a situation can take + // place only in case of significant oversubscription, keeping + // the checks simple seems to be preferable to complicating the code. + if( k >= my_arena_index ) + ++victim; // Adjusts random distribution to exclude self + t = steal_task( *victim ); + if( !t ) goto fail; + if( is_proxy(*t) ) { + task_proxy &tp = *(task_proxy*)t; + t = tp.extract_task<task_proxy::pool_bit>(); + if ( !t ) { + // Proxy was empty, so it's our responsibility to free it + free_task<small_task>(tp); + goto fail; + } + GATHER_STATISTIC( ++my_counters.proxies_stolen ); + } + t->prefix().extra_state |= es_task_is_stolen; + if( is_version_3_task(*t) ) { + my_innermost_running_task = t; + t->prefix().owner = this; + t->note_affinity( my_affinity_id ); + } + GATHER_STATISTIC( ++my_counters.steals_committed ); + } // end of stealing branch + else + goto fail; + } // end of nonlocal retrieval branch + else { + // This is the only thread in this arena, so nowhere to steal +#if __TBB_TASK_PRIORITY + if ( !my_offloaded_tasks || !(t = reload_tasks()) ) +#endif /* __TBB_TASK_PRIORITY */ + goto fail; + } + // A task was successfully obtained somewhere + __TBB_ASSERT(t,NULL); +#if __TBB_SCHEDULER_OBSERVER + // No memory fence required for read of global_last_observer_proxy, because prior fence on steal/mailbox suffices. + if( my_local_last_observer_proxy!=global_last_observer_proxy ) { + notify_entry_observers(); + } +#endif /* __TBB_SCHEDULER_OBSERVER */ + if ( SchedulerTraits::itt_possible && failure_count != -1 ) { + // FIXME - might be victim, or might be selected from a mailbox + // Notify Intel(R) Thread Profiler that thread has stopped spinning. + ITT_NOTIFY(sync_acquired, this); + } + break; // exit stealing loop and return +fail: + GATHER_STATISTIC( ++my_counters.steals_failed ); + if( SchedulerTraits::itt_possible && failure_count==-1 ) { + // The first attempt to steal work failed, so notify Intel(R) Thread Profiler that + // the thread has started spinning. Ideally, we would do this notification + // *before* the first failed attempt to steal, but at that point we do not + // know that the steal will fail. + ITT_NOTIFY(sync_prepare, this); + failure_count = 0; + } + // Pause, even if we are going to yield, because the yield might return immediately. + __TBB_Pause(PauseTime); + int yield_threshold = 2*int(n); + if( failure_count>=yield_threshold ) { + __TBB_Yield(); +#if __TBB_TASK_PRIORITY + // Check if there are tasks abandoned by other workers + if ( my_arena->my_orphaned_tasks ) { + // Epoch must be advanced before seizing the list pointer + ++my_arena->my_abandonment_epoch; + task* orphans = (task*)__TBB_FetchAndStoreW( &my_arena->my_orphaned_tasks, 0 ); + if ( orphans ) { + task** link = NULL; + // Get local counter out of the way (we've just brought in external tasks) + my_local_reload_epoch = 0; + t = reload_tasks( orphans, link, effective_reference_priority() ); + if ( orphans ) { + *link = my_offloaded_tasks; + if ( !my_offloaded_tasks ) + my_offloaded_task_list_tail_link = link; + my_offloaded_tasks = orphans; + } + __TBB_ASSERT( !my_offloaded_tasks == !my_offloaded_task_list_tail_link, NULL ); + if ( t ) { + if( SchedulerTraits::itt_possible ) + ITT_NOTIFY(sync_cancel, this); + break; // exit stealing loop and return + } + } + } +#endif /* __TBB_TASK_PRIORITY */ + if( failure_count>=yield_threshold+100 ) { + // When a worker thread has nothing to do, return it to RML. + // For purposes of affinity support, the thread is considered idle while in RML. +#if __TBB_TASK_PRIORITY + if( return_if_no_work || my_arena->my_top_priority > my_arena->my_bottom_priority ) { + if ( my_arena->is_out_of_work() && return_if_no_work ) { +#else /* !__TBB_TASK_PRIORITY */ + if ( return_if_no_work && my_arena->is_out_of_work() ) { +#endif /* !__TBB_TASK_PRIORITY */ + if( SchedulerTraits::itt_possible ) + ITT_NOTIFY(sync_cancel, this); + return NULL; + } +#if __TBB_TASK_PRIORITY + } + if ( my_offloaded_tasks ) { + // Safeguard against any sloppiness in managing reload epoch + // counter (e.g. on the hot path bacause of performance reasons). + my_local_reload_epoch = 0; + // Break the deadlock caused by a higher priority dispatch loop + // stealing and offloading a lower priority task. Priority check + // at the stealing moment cannot completely preclude such cases + // because priorities can changes dynamically. + if ( !return_if_no_work && *my_ref_top_priority > my_arena->my_top_priority ) { + GATHER_STATISTIC( ++my_counters.prio_ref_fixups ); + my_ref_top_priority = &my_arena->my_top_priority; + my_ref_reload_epoch = &my_arena->my_reload_epoch; + } + } +#endif /* __TBB_TASK_PRIORITY */ + failure_count = yield_threshold; + } // end of arena snapshot branch + } // end of yielding branch + } // end of nonlocal task retrieval loop + my_inbox.set_is_idle( false ); + return t; +} + +template<typename SchedulerTraits> +void custom_scheduler<SchedulerTraits>::local_wait_for_all( task& parent, task* child ) { + __TBB_ASSERT( governor::is_set(this), NULL ); + __TBB_ASSERT( parent.ref_count() >= (child && child->parent() == &parent ? 2 : 1), "ref_count is too small" ); + assert_task_pool_valid(); + // Using parent's refcount in sync_prepare (in the stealing loop below) is + // a workaround for TP. We need to name it here to display correctly in Ampl. + if( SchedulerTraits::itt_possible ) + ITT_SYNC_CREATE(&parent.prefix().ref_count, SyncType_Scheduler, SyncObj_TaskStealingLoop); +#if __TBB_TASK_GROUP_CONTEXT + __TBB_ASSERT( parent.prefix().context || (is_worker() && &parent == my_dummy_task), "parent task does not have context" ); +#endif /* __TBB_TASK_GROUP_CONTEXT */ + task* t = child; + // Constant all_local_work_done is an unreacheable refcount value that prevents + // early quitting the dispatch loop. It is defined to be in the middle of the range + // of negative values representable by the reference_count type. + static const reference_count + // For normal dispatch loops + parents_work_done = 1, + // For termination dispatch loops in masters + all_local_work_done = (reference_count)3 << (sizeof(reference_count) * 8 - 2); + reference_count quit_point; +#if __TBB_TASK_PRIORITY + __TBB_ASSERT( (uintptr_t)*my_ref_top_priority < (uintptr_t)num_priority_levels, NULL ); + volatile intptr_t *old_ref_top_priority = my_ref_top_priority; + // When entering nested parallelism level market level counter + // must be replaced with the one local to this arena. + volatile uintptr_t *old_ref_reload_epoch = my_ref_reload_epoch; +#endif /* __TBB_TASK_PRIORITY */ + task* old_dispatching_task = my_dispatching_task; + my_dispatching_task = my_innermost_running_task; + if( master_outermost_level() ) { + // We are in the outermost task dispatch loop of a master thread, + __TBB_ASSERT( !is_worker(), NULL ); + quit_point = &parent == my_dummy_task ? all_local_work_done : parents_work_done; + } else { + quit_point = parents_work_done; +#if __TBB_TASK_PRIORITY + if ( &parent != my_dummy_task ) { + // We are in a nested dispatch loop. + // Market or arena priority must not prevent child tasks from being + // executed so that dynamic priority changes did not cause deadlock. + my_ref_top_priority = &parent.prefix().context->my_priority; + my_ref_reload_epoch = &my_arena->my_reload_epoch; + } +#endif /* __TBB_TASK_PRIORITY */ + } +#if __TBB_TASK_GROUP_CONTEXT && TBB_USE_EXCEPTIONS + // Infinite safeguard EH loop + for (;;) { + try { +#endif /* __TBB_TASK_GROUP_CONTEXT && TBB_USE_EXCEPTIONS */ + // Outer loop receives tasks from global environment (via mailbox, FIFO queue(s), + // and by stealing from other threads' task pools). + // All exit points from the dispatch loop are located in its immediate scope. + for(;;) { + // Middle loop retrieves tasks from the local task pool. + do { + // Inner loop evaluates tasks coming from nesting loops and those returned + // by just executed tasks (bypassing spawn or enqueue calls). + while(t) { + __TBB_ASSERT( my_inbox.is_idle_state(false), NULL ); + __TBB_ASSERT(!is_proxy(*t),"unexpected proxy"); + __TBB_ASSERT( t->prefix().owner, NULL ); + assert_task_valid(*t); +#if __TBB_TASK_GROUP_CONTEXT && TBB_USE_ASSERT + if ( !t->prefix().context->my_cancellation_requested ) +#endif + __TBB_ASSERT( 1L<<t->state() & (1L<<task::allocated|1L<<task::ready|1L<<task::reexecute), NULL ); + assert_task_pool_valid(); +#if __TBB_TASK_PRIORITY + intptr_t p = priority(*t); + if ( p != *my_ref_top_priority && (t->prefix().extra_state & es_task_enqueued) == 0) { + assert_priority_valid(p); + if ( p != my_arena->my_top_priority ) { + my_market->update_arena_priority( *my_arena, p ); + } + if ( p < effective_reference_priority() ) { + if ( !my_offloaded_tasks ) { + my_offloaded_task_list_tail_link = &t->prefix().next_offloaded; + // Erase possible reference to the owner scheduler (next_offloaded is a union member) + *my_offloaded_task_list_tail_link = NULL; + } + offload_task( *t, p ); + if ( in_arena() ) { + t = winnow_task_pool(); + if ( t ) + continue; + } + else { + // Mark arena as full to unlock arena priority level adjustment + // by arena::is_out_of_work(), and ensure worker's presence. + my_arena->advertise_new_work<false>(); + } + goto stealing_ground; + } + } +#endif /* __TBB_TASK_PRIORITY */ + task* t_next = NULL; + my_innermost_running_task = t; + t->prefix().owner = this; + t->prefix().state = task::executing; +#if __TBB_TASK_GROUP_CONTEXT + if ( !t->prefix().context->my_cancellation_requested ) +#endif + { + GATHER_STATISTIC( ++my_counters.tasks_executed ); + GATHER_STATISTIC( my_counters.avg_arena_concurrency += my_arena->my_num_threads_active ); + GATHER_STATISTIC( my_counters.avg_assigned_workers += my_arena->my_num_workers_allotted ); +#if __TBB_TASK_PRIORITY + GATHER_STATISTIC( my_counters.avg_arena_prio += p ); + GATHER_STATISTIC( my_counters.avg_market_prio += my_market->my_global_top_priority ); +#endif /* __TBB_TASK_PRIORITY */ + ITT_STACK(SchedulerTraits::itt_possible, callee_enter, t->prefix().context->itt_caller); + t_next = t->execute(); + ITT_STACK(SchedulerTraits::itt_possible, callee_leave, t->prefix().context->itt_caller); + if (t_next) { + __TBB_ASSERT( t_next->state()==task::allocated, + "if task::execute() returns task, it must be marked as allocated" ); + reset_extra_state(t_next); +#if TBB_USE_ASSERT + affinity_id next_affinity=t_next->prefix().affinity; + if (next_affinity != 0 && next_affinity != my_affinity_id) + GATHER_STATISTIC( ++my_counters.affinity_ignored ); +#endif + } + } + assert_task_pool_valid(); + switch( t->state() ) { + case task::executing: { + task* s = t->parent(); + __TBB_ASSERT( my_innermost_running_task==t, NULL ); + __TBB_ASSERT( t->prefix().ref_count==0, "Task still has children after it has been executed" ); + t->~task(); + if( s ) + tally_completion_of_predecessor(*s, t_next); + free_task<no_hint>( *t ); + assert_task_pool_valid(); + break; + } + + case task::recycle: // set by recycle_as_safe_continuation() + t->prefix().state = task::allocated; + __TBB_ASSERT( t_next != t, "a task returned from method execute() can not be recycled in another way" ); + reset_extra_state(t); + // for safe continuation, need atomically decrement ref_count; + tally_completion_of_predecessor(*t, t_next); + assert_task_pool_valid(); + break; + + case task::reexecute: // set by recycle_to_reexecute() + __TBB_ASSERT( t_next, "reexecution requires that method execute() return another task" ); + __TBB_ASSERT( t_next != t, "a task returned from method execute() can not be recycled in another way" ); + t->prefix().state = task::allocated; + reset_extra_state(t); + local_spawn( *t, t->prefix().next ); + assert_task_pool_valid(); + break; + case task::allocated: + reset_extra_state(t); + break; +#if TBB_USE_ASSERT + case task::ready: + __TBB_ASSERT( false, "task is in READY state upon return from method execute()" ); + break; + default: + __TBB_ASSERT( false, "illegal state" ); +#else + default: // just to shut up some compilation warnings + break; +#endif /* TBB_USE_ASSERT */ + } + GATHER_STATISTIC( t_next ? ++my_counters.spawns_bypassed : 0 ); + t = t_next; + } // end of scheduler bypass loop + + assert_task_pool_valid(); + if ( parent.prefix().ref_count == quit_point ) { + __TBB_ASSERT( quit_point != all_local_work_done, NULL ); + __TBB_control_consistency_helper(); // on ref_count + goto done; + } + if ( in_arena() ) { + t = get_task(); + } + else { + __TBB_ASSERT( is_quiescent_local_task_pool_reset(), NULL ); + break; + } + __TBB_ASSERT(!t || !is_proxy(*t),"unexpected proxy"); + assert_task_pool_valid(); + } while( t ); // end of local task pool retrieval loop + +#if __TBB_TASK_PRIORITY +stealing_ground: +#endif /* __TBB_TASK_PRIORITY */ + if ( quit_point == all_local_work_done ) { + __TBB_ASSERT( !in_arena() && is_quiescent_local_task_pool_reset(), NULL ); + my_innermost_running_task = my_dispatching_task; + my_dispatching_task = old_dispatching_task; +#if __TBB_TASK_PRIORITY + my_ref_top_priority = old_ref_top_priority; + my_ref_reload_epoch = old_ref_reload_epoch; +#endif /* __TBB_TASK_PRIORITY */ + return; + } + // The following assertion may be falsely triggered in the presence of enqueued tasks + //__TBB_ASSERT( my_arena->my_max_num_workers > 0 || my_market->my_ref_count > 1 + // || parent.prefix().ref_count == 1, "deadlock detected" ); + + // Dispatching task pointer is NULL *iff* this is a worker thread in its outermost + // dispatch loop (i.e. its execution stack is empty). In this case it should exit it + // either when there is no more work in the current arena, or when revoked by the market. + t = receive_or_steal_task( parent.prefix().ref_count, !my_dispatching_task ); + if ( !t ) + goto done; + __TBB_ASSERT(!is_proxy(*t),"unexpected proxy"); + } // end of infinite stealing loop +#if __TBB_TASK_GROUP_CONTEXT && TBB_USE_EXCEPTIONS + __TBB_ASSERT( false, "Must never get here" ); + } // end of try-block + TbbCatchAll( t->prefix().context ); + // Complete post-processing ... + if( t->state() == task::recycle ) { + // ... for tasks recycled with recycle_as_safe_continuation + t->prefix().state = task::allocated; + // for safe continuation, need to atomically decrement ref_count; + if( SchedulerTraits::itt_possible ) + ITT_NOTIFY(sync_releasing, &t->prefix().ref_count); + if( __TBB_FetchAndDecrementWrelease(&t->prefix().ref_count)==1 ) { + if( SchedulerTraits::itt_possible ) + ITT_NOTIFY(sync_acquired, &t->prefix().ref_count); + }else{ + t = NULL; + } + } + } // end of infinite EH loop + __TBB_ASSERT( false, "Must never get here too" ); +#endif /* __TBB_TASK_GROUP_CONTEXT && TBB_USE_EXCEPTIONS */ +done: + my_innermost_running_task = my_dispatching_task; + my_dispatching_task = old_dispatching_task; +#if __TBB_TASK_PRIORITY + my_ref_top_priority = old_ref_top_priority; + my_ref_reload_epoch = old_ref_reload_epoch; +#endif /* __TBB_TASK_PRIORITY */ + if ( !ConcurrentWaitsEnabled(parent) ) { + if ( parent.prefix().ref_count != parents_work_done ) { + // This is a worker that was revoked by the market. + __TBB_ASSERT( is_worker() && !my_dispatching_task, + "Worker thread exits nested dispatch loop prematurely" ); + return; + } + parent.prefix().ref_count = 0; + } +#if TBB_USE_ASSERT + parent.prefix().extra_state &= ~es_ref_count_active; +#endif /* TBB_USE_ASSERT */ +#if __TBB_TASK_GROUP_CONTEXT + __TBB_ASSERT(parent.prefix().context && default_context(), NULL); + task_group_context* parent_ctx = parent.prefix().context; + if ( parent_ctx->my_cancellation_requested ) { + task_group_context::exception_container_type *pe = parent_ctx->my_exception; + if ( master_outermost_level() && parent_ctx == default_context() ) { + // We are in the outermost task dispatch loop of a master thread, and + // the whole task tree has been collapsed. So we may clear cancellation data. + parent_ctx->my_cancellation_requested = 0; + // TODO: Add assertion that master's dummy task context does not have children + parent_ctx->my_state &= ~(uintptr_t)task_group_context::may_have_children; + } + if ( pe ) + pe->throw_self(); + } + __TBB_ASSERT(!is_worker() || !CancellationInfoPresent(*my_dummy_task), + "Worker's dummy task context modified"); + __TBB_ASSERT(!master_outermost_level() || !CancellationInfoPresent(*my_dummy_task), + "Unexpected exception or cancellation data in the master's dummy task"); +#endif /* __TBB_TASK_GROUP_CONTEXT */ + assert_task_pool_valid(); +} + +} // namespace internal +} // namespace tbb + +#endif /* _TBB_custom_scheduler_H */ diff --git a/src/tbb/src/tbb/dynamic_link.cpp b/src/tbb/src/tbb/dynamic_link.cpp new file mode 100644 index 0000000..25698fd --- /dev/null +++ b/src/tbb/src/tbb/dynamic_link.cpp @@ -0,0 +1,488 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "dynamic_link.h" + +/* + This file is used by both TBB and OpenMP RTL. Do not use __TBB_ASSERT() macro + and runtime_warning() function because they are not available in OpenMP. Use + LIBRARY_ASSERT and DYNAMIC_LINK_WARNING instead. +*/ + +#ifndef LIBRARY_ASSERT + #include "tbb/tbb_stddef.h" + #define LIBRARY_ASSERT(x,y) __TBB_ASSERT(x,y) +#endif /* !LIBRARY_ASSERT */ + +#include <cstdarg> // va_list etc. +#if _WIN32||_WIN64 + #include <malloc.h> /* alloca */ +#else + #include <dlfcn.h> + #include <string.h> + #include <unistd.h> + #include <limits.h> +#if __FreeBSD__ || __NetBSD__ + #include <stdlib.h> /* alloca */ +#else + #include <alloca.h> +#endif +#endif + +#ifdef __TBB_BUILD +#include "tbb/atomic.h" +#endif /* __TBB_BUILD */ + +OPEN_INTERNAL_NAMESPACE + +#if !defined(DYNAMIC_LINK_WARNING) && __TBB_DYNAMIC_LOAD_ENABLED + // Report runtime errors and continue. + #define DYNAMIC_LINK_WARNING dynamic_link_warning + static void dynamic_link_warning( dynamic_link_error_t code, ... ) { + (void) code; + } // library_warning +#endif /* DYNAMIC_LINK_WARNING */ + +#if __TBB_DYNAMIC_LOAD_ENABLED +#if _WIN32 || _WIN64 +/* + There is a security issue on Windows: LoadLibrary() may load and execute malicious code. + See http://www.microsoft.com/technet/security/advisory/2269637.mspx for details. + To avoid the issue, we have to pass full path (not just library name) to LoadLibrary. This + function constructs full path to the specified library (it is assumed the library located + side-by-side with the tbb.dll. + + The function constructs absolute path for given relative path. Important: Base directory is not + current one, it is the directory tbb.dll loaded from. + + Example: + Let us assume "tbb.dll" is located in "c:\program files\common\intel\" directory, e. g. + absolute path of tbb library is "c:\program files\common\intel\tbb.dll". Absolute path for + "tbbmalloc.dll" would be "c:\program files\common\intel\tbbmalloc.dll". Absolute path for + "malloc\tbbmalloc.dll" would be "c:\program files\common\intel\malloc\tbbmalloc.dll". + + Arguments: + in name -- Name of a file (may be with relative path; it must not be an absolute one). + out path -- Buffer to save result (absolute path) to. + in len -- Size of buffer. + ret -- 0 -- Error occurred. + > len -- Buffer too short, required size returned. + otherwise -- Ok, number of characters (not counting terminating null) written to + buffer. +*/ +static size_t abs_path( char const * name, char * path, size_t len ) { + // Get handle of our DLL first. + HMODULE handle; + BOOL brc = + GetModuleHandleEx( + GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + (LPCSTR)( & abs_path ), + & handle + ); + if ( ! brc ) { // Error occurred. + int err = GetLastError(); + DYNAMIC_LINK_WARNING( dl_sys_fail, "GetModuleHandleEx", err ); + return 0; + } // if + + // Now get path to our DLL. + DWORD drc = GetModuleFileName( handle, path, static_cast< DWORD >( len ) ); + if ( drc == 0 ) { // Error occurred. + int err = GetLastError(); + DYNAMIC_LINK_WARNING( dl_sys_fail, "GetModuleFileName", err ); + return drc; + } // if + if ( drc >= len ) { // Buffer too short. + DYNAMIC_LINK_WARNING( dl_buff_too_small ); + return drc; + } // if + + // Find the position of the last backslash. + char * backslash = path + drc; // backslash points behind the path. + LIBRARY_ASSERT( * backslash == 0, NULL ); + while ( backslash > path && * backslash != '\\' ) { + -- backslash; + } // while + if ( backslash <= path ) { // Backslash not found. + return 0; // Unbelievable. + } // if + + // Now append name to construct the full path. + LIBRARY_ASSERT( * backslash == '\\', NULL ); + size_t rc = ( backslash + 1 - path ) + strlen( name ); + if ( rc >= len ) { + DYNAMIC_LINK_WARNING( dl_buff_too_small ); + return rc + 1; + } // if + strcpy( backslash + 1, name ); + LIBRARY_ASSERT( rc == strlen( path ), NULL ); + return rc; +} // abs_path +#else /* WIN */ + class _abs_path { + char _path[PATH_MAX+1]; + size_t _len; + enum { + ap_invalid = 0, + ap_only_cwd, + ap_ready + } _state; + + bool prepare_full_path() { + LIBRARY_ASSERT( _state==ap_only_cwd, NULL ); + + Dl_info dlinfo; + int res = dladdr( (void*)&dynamic_unlink, &dlinfo ); + if ( !res ) { + char const * err = dlerror(); + DYNAMIC_LINK_WARNING( dl_sys_fail, "dladdr", err ); + return false; + } + + size_t fname_len = strlen( dlinfo.dli_fname ); + // Find the position of the last backslash. + while ( fname_len>0 && dlinfo.dli_fname[fname_len-1]!='/' ) fname_len-=1; + + size_t rc; + + if ( dlinfo.dli_fname[0]=='/' ) { + rc = 0; + _len = fname_len; + } else { + rc = _len; + _len += fname_len; + } + + if ( fname_len>0 ) { + if ( _len>PATH_MAX ) { + DYNAMIC_LINK_WARNING( dl_buff_too_small ); + return false; + } + memcpy( _path+rc, dlinfo.dli_fname, fname_len*sizeof(char) ); + _path[_len]=0; + } + + return true; + } + public: + _abs_path() { + if ( getcwd( _path, PATH_MAX+1 ) ) { + _state = ap_only_cwd; + _len = strlen( _path ); + _path[_len++]='/'; + } else { + DYNAMIC_LINK_WARNING( dl_buff_too_small ); + _state = ap_invalid; + } + } + + /* + The function constructs absolute path for given relative path. Important: Base directory is not + current one, it is the directory libtbb.so loaded from. + + Arguments: + in name -- Name of a file (may be with relative path; it must not be an absolute one). + out path -- Buffer to save result (absolute path) to. + in len -- Size of buffer. + ret -- 0 -- Error occured. + > len -- Buffer too short, required size returned. + otherwise -- Ok, number of characters (not counting terminating null) written to + buffer. + */ + size_t operator ()( char const * name, char * path, size_t len ) { + switch ( _state ) { + case ap_only_cwd: + if ( !prepare_full_path() ) { + _state = ap_invalid; + return 0; + } + _state = ap_ready; + // 'break' is missed since we really want to do next case. + case ap_ready: { + size_t name_len = strlen( name ); + size_t full_len = name_len+_len; + if ( full_len+_len < len ) { + memcpy( path, _path, _len ); + memcpy( path+_len, name, name_len ); + path[full_len] = 0; + } + return full_len; + } + default: + return 0; + } + } + + }; + +_abs_path abs_path; +#endif /* WIN */ +#endif /* __TBB_DYNAMIC_LOAD_ENABLED */ + +#if __TBB_WEAK_SYMBOLS + +bool dynamic_link( dynamic_link_handle, const dynamic_link_descriptor descriptors[], size_t n, size_t required ) +{ + if ( required == ~(size_t)0 ) + required = n; + LIBRARY_ASSERT( required<=n, "Number of required entry points exceeds their total number" ); + size_t k = 0; + // Check if the first required entries are present in what was loaded into our process + while ( k < required && descriptors[k].ptr ) + ++k; + if ( k < required ) + return false; + // Commit all the entry points. + for ( k = 0; k < n; ++k ) + *descriptors[k].handler = (pointer_to_handler) descriptors[k].ptr; + return true; +} + +#else /* !__TBB_WEAK_SYMBOLS */ + +bool dynamic_link( dynamic_link_handle module, const dynamic_link_descriptor descriptors[], size_t n, size_t required ) +{ + LIBRARY_ASSERT( module != NULL, "Module handle is NULL" ); + if ( module == NULL ) { + return false; + } // if + pointer_to_handler *h = (pointer_to_handler*)alloca(n * sizeof(pointer_to_handler)); + if ( required == ~(size_t)0 ) + required = n; + LIBRARY_ASSERT( required<=n, "Number of required entry points exceeds their total number" ); + size_t k = 0; + for ( ; k < n; ++k ) { + dynamic_link_descriptor const & desc = descriptors[k]; +#if _WIN32||_WIN64 + FARPROC addr = GetProcAddress( module, desc.name ); + if ( addr == NULL ) { + int err = GetLastError(); + DYNAMIC_LINK_WARNING( dl_sym_not_found, desc.name, err ); + } // if + h[k] = pointer_to_handler( addr ); +#else /* !WIN */ + void * addr = dlsym( module, desc.name ); + if ( addr == NULL ) { + char const * err = dlerror(); + DYNAMIC_LINK_WARNING( dl_sym_not_found, desc.name, err ); + } // if + // Lvalue casting is used; this way icc -strict-ansi does not warn about nonstandard pointer conversion + (void *&)h[k] = addr; +#endif /* !WIN */ + if ( !h[k] && k < required ) + return false; + } + LIBRARY_ASSERT( k == n, "if required entries are initialized, all entries are expected to be walked"); + // Commit the entry points. + // Cannot use memset here, because the writes must be atomic. + for( k = 0; k < n; ++k ) + *descriptors[k].handler = h[k]; + return true; +} + +#endif /* !__TBB_WEAK_SYMBOLS */ + +void dynamic_unlink( dynamic_link_handle handle ) { + if ( handle ) { +#if __TBB_DYNAMIC_LOAD_ENABLED +#if _WIN32||_WIN64 + FreeLibrary( handle ); +#else + dlclose( handle ); +#endif + (void)handle; +#endif /* __TBB_DYNAMIC_LOAD_ENABLED */ + } +} + +#if __TBB_BUILD + +// Class handle_storage is used by dynamic_link routine to store handles of +// all loaded or pinned dynamic libraries. When TBB is shut down, it calls +// dynamic_unlink_all() that unloads modules referenced by handle_storage. +// This functionality is only used by TBB. It should not be used by other +// libraries reusing this source file to avoid dependency on tbb::atomic<>. + +#define MAX_LOADED_MODULES 8 // The number of maximum possible modules which can be loaded + +class handle_storage { + tbb::atomic<size_t> my_size; + dynamic_link_handle my_handles[MAX_LOADED_MODULES]; +public: + + handle_storage() { + my_size = 0; + } + + void add_handle(dynamic_link_handle &handle) { + const size_t ind = my_size++; + LIBRARY_ASSERT( ind < MAX_LOADED_MODULES, "Too many modules are loaded" ); + my_handles[ind] = handle; + } + + void free_handles() { + const size_t size = my_size.fetch_and_store( 0 ); + for (size_t i=0; i<size; ++i) + dynamic_unlink( my_handles[i] ); + } + +} handles; +#endif /* __TBB_BUILD */ + +bool dynamic_link( const char* library, const dynamic_link_descriptor descriptors[], size_t n, size_t required, dynamic_link_handle *handle ) { + // Get library handle in case it is already loaded into the current process +#if ! __TBB_DYNAMIC_LOAD_ENABLED + dynamic_link_handle library_handle = NULL; + __TBB_ASSERT_EX( library, "library name must be provided"); +#elif _WIN32||_WIN64 + dynamic_link_handle library_handle = GetModuleHandle( library ); +#else + dynamic_link_handle library_handle = dlopen( NULL, RTLD_LAZY ); +#endif /* _WIN32||_WIN64 */ + + // Get descriptors from the library + if ( library_handle && dynamic_link( library_handle, descriptors, n, required ) ) { +#if !__TBB_DYNAMIC_LOAD_ENABLED + return true; +#else + // The library has been loaded by another module and contains requested symbols. + // But after we obtained the library's handle it can be unloaded by another thread + // invalidating our handle copy. Therefore we need to pin the library in memory. +#if _WIN32||_WIN64 + char library_full_name[ MAX_PATH+1 ]; + // Get library's name from earlier found handle + if ( GetModuleFileName( library_handle, library_full_name, MAX_PATH+1 ) ) { + // Pin the library + library_handle = LoadLibrary( library_full_name ); + if ( library_handle == NULL ) { + int err = GetLastError(); + DYNAMIC_LINK_WARNING( dl_lib_not_found, library_full_name, err ); + } // if + } // if +#else /* !WIN */ + Dl_info info; + // Get library's name from earlier found symbol + if ( dladdr( (void*)*descriptors[0].handler, &info ) ) { + // Pin the library + library_handle = dlopen( info.dli_fname, RTLD_LAZY ); + if ( library_handle == NULL ) { + char const * err = dlerror(); + DYNAMIC_LINK_WARNING( dl_lib_not_found, info.dli_fname, err ); + } // if + } // if +#endif /* !WIN */ + else { + // The library have been unloaded by another thread + library_handle = 0; + } + if ( library_handle ) { + // If original library was unloaded before we pinned it + // and then another module loaded in its place, the earlier + // found symbols would become invalid. So revalidate them. + if ( !dynamic_link( library_handle, descriptors, n, required ) ) { + // Wrong library. + dynamic_unlink(library_handle); + library_handle = 0; + } + } + if ( !library_handle ) { + // Failed to pin the library, so clear the descriptors too. + for( size_t i=0; i<n; ++i ) + *descriptors[i].handler = 0; + } +#endif /* __TBB_DYNAMIC_LOAD_ENABLED */ + } else { + library_handle = 0; + } + +#if __TBB_DYNAMIC_LOAD_ENABLED + if ( !library_handle ) { +#if _WIN32||_WIN64 +#if _XBOX + library_handle = LoadLibrary (library); +#else + library_handle = NULL; + // Construct absolute path to the library to avoid security issue. + size_t const len = MAX_PATH + 1; + char path[ len ]; + size_t rc = abs_path( library, path, len ); + if ( 0 < rc && rc < len ) { + // Prevent Windows from displaying silly message boxes if it fails to load library + // (e.g. because of MS runtime problems - one of those crazy manifest related ones) + UINT prev_mode = SetErrorMode (SEM_FAILCRITICALERRORS); + library_handle = LoadLibrary (path); + SetErrorMode (prev_mode); + if ( library_handle == NULL ) { + int err = GetLastError(); + DYNAMIC_LINK_WARNING( dl_lib_not_found, path, err ); + } // if + } // if +#endif /* !_XBOX */ +#else /* !WIN */ + library_handle = NULL; + // Construct absolute path to the library. + size_t const len = PATH_MAX + 1; + char path[ len ]; + size_t rc = abs_path( library, path, len ); + if ( 0 < rc && rc < len ) { + library_handle = dlopen( path, RTLD_LAZY ); + if ( library_handle == NULL ) { + char const * err = dlerror(); + DYNAMIC_LINK_WARNING( dl_lib_not_found, library, err ); + } // if + } // if +#endif /* !WIN */ + if( library_handle ) { + if( !dynamic_link( library_handle, descriptors, n, required ) ) { + // The loaded library does not contain all the expected entry points + dynamic_unlink( library_handle ); + library_handle = NULL; + } + } + } +#endif /* __TBB_DYNAMIC_LOAD_ENABLED */ + + if ( library_handle ) { + if ( handle ) + *handle = library_handle; +#if __TBB_BUILD + else + handles.add_handle( library_handle ); +#endif /* __TBB_BUILD */ + return true; + } + return false; +} + +#if __TBB_BUILD +void dynamic_unlink_all() { + handles.free_handles(); +} +#endif /* __TBB_BUILD */ + +CLOSE_INTERNAL_NAMESPACE diff --git a/src/tbb/src/tbb/dynamic_link.h b/src/tbb/src/tbb/dynamic_link.h new file mode 100644 index 0000000..fb69cd6 --- /dev/null +++ b/src/tbb/src/tbb/dynamic_link.h @@ -0,0 +1,123 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_dynamic_link +#define __TBB_dynamic_link + +// Support for dynamic loading entry points from other shared libraries. + +#ifndef LIBRARY_ASSERT + #include "tbb/tbb_config.h" +#endif /* !LIBRARY_ASSERT */ + +/** By default, symbols declared and defined here go into namespace tbb::internal. + To put them in other namespace, define macros OPEN_INTERNAL_NAMESPACE + and CLOSE_INTERNAL_NAMESPACE to override the following default definitions. **/ +#ifndef OPEN_INTERNAL_NAMESPACE +#define OPEN_INTERNAL_NAMESPACE namespace tbb { namespace internal { +#define CLOSE_INTERNAL_NAMESPACE }} +#endif /* OPEN_INTERNAL_NAMESPACE */ + +#include <stddef.h> +#if _WIN32||_WIN64 +#include "tbb/machine/windows_api.h" +#endif /* _WIN32||_WIN64 */ + +OPEN_INTERNAL_NAMESPACE + +//! Type definition for a pointer to a void somefunc(void) +typedef void (*pointer_to_handler)(); + +// Double cast through the void* from func_ptr in DLD macro is necessary to +// prevent warnings from some compilers (g++ 4.1) +#if __TBB_WEAK_SYMBOLS + +#define DLD(s,h) {(pointer_to_handler)&s, (pointer_to_handler*)(void*)(&h)} +//! Association between a handler name and location of pointer to it. +struct dynamic_link_descriptor { + //! pointer to the handler + pointer_to_handler ptr; + //! Pointer to the handler + pointer_to_handler* handler; +}; + +#else /* !__TBB_WEAK_SYMBOLS */ + +#define DLD(s,h) {#s, (pointer_to_handler*)(void*)(&h)} +//! Association between a handler name and location of pointer to it. +struct dynamic_link_descriptor { + //! Name of the handler + const char* name; + //! Pointer to the handler + pointer_to_handler* handler; +}; + +#endif /* !__TBB_WEAK_SYMBOLS */ + +#if _WIN32||_WIN64 +typedef HMODULE dynamic_link_handle; +#else +typedef void* dynamic_link_handle; +#endif /* _WIN32||_WIN64 */ + +//! Fill in dynamically linked handlers. +/** 'n' is the length of the array descriptors[]. + 'required' is the number of the initial entries in the array descriptors[] + that have to be found in order for the call to succeed. If the library and + all the required handlers are found, then the corresponding handler pointers + are set, and the return value is true. Otherwise the original array of + descriptors is left untouched and the return value is false. **/ +bool dynamic_link( const char* libraryname, + const dynamic_link_descriptor descriptors[], + size_t n, + size_t required = ~(size_t)0, + dynamic_link_handle* handle = 0 ); + +bool dynamic_link( dynamic_link_handle module, + const dynamic_link_descriptor descriptors[], + size_t n, + size_t required = ~(size_t)0 ); + +void dynamic_unlink( dynamic_link_handle handle ); + +#if __TBB_BUILD +void dynamic_unlink_all(); +#endif /* __TBB_BUILD */ + +enum dynamic_link_error_t { + dl_success = 0, + dl_lib_not_found, // char const * lib, dlerr_t err + dl_sym_not_found, // char const * sym, dlerr_t err + // Note: dlerr_t depends on OS: it is char const * on Linux and Mac, int on Windows. + dl_sys_fail, // char const * func, int err + dl_buff_too_small // none +}; // dynamic_link_error_t + +CLOSE_INTERNAL_NAMESPACE + +#endif /* __TBB_dynamic_link */ diff --git a/src/tbb/src/tbb/governor.cpp b/src/tbb/src/tbb/governor.cpp new file mode 100644 index 0000000..03b2e64 --- /dev/null +++ b/src/tbb/src/tbb/governor.cpp @@ -0,0 +1,322 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "governor.h" +#include "tbb_main.h" +#include "scheduler.h" +#include "market.h" +#include "arena.h" + +#include "tbb/task_scheduler_init.h" + +#include "dynamic_link.h" + +namespace tbb { +namespace internal { + +//------------------------------------------------------------------------ +// governor +//------------------------------------------------------------------------ + +#if __TBB_SURVIVE_THREAD_SWITCH +// Support for interoperability with Intel(R) Cilk(tm) Plus. + +#if _WIN32 +#define CILKLIB_NAME "cilkrts20.dll" +#else +#define CILKLIB_NAME "libcilkrts.so" +#endif + +//! Handler for memory allocation +static __cilk_tbb_retcode (*watch_stack_handler)(struct __cilk_tbb_unwatch_thunk* u, + struct __cilk_tbb_stack_op_thunk o); + +#if __TBB_WEAK_SYMBOLS + #pragma weak __cilkrts_watch_stack +#endif + +//! Table describing how to link the handlers. +static const dynamic_link_descriptor CilkLinkTable[] = { + DLD(__cilkrts_watch_stack, watch_stack_handler) +}; + +static atomic<do_once_state> cilkrts_load_state; + +bool initialize_cilk_interop() { + // Pinning can fail. This is a normal situation, and means that the current + // thread does not use cilkrts and consequently does not need interop. + return dynamic_link( CILKLIB_NAME, CilkLinkTable, 1 ); +} +#endif /* __TBB_SURVIVE_THREAD_SWITCH */ + +namespace rml { + tbb_server* make_private_server( tbb_client& client ); +} + +void governor::acquire_resources () { +#if USE_PTHREAD + int status = theTLS.create(auto_terminate); +#else + int status = theTLS.create(); +#endif + if( status ) + handle_perror(status, "TBB failed to initialize task scheduler TLS\n"); +} + +void governor::release_resources () { + theRMLServerFactory.close(); +#if TBB_USE_ASSERT + if( __TBB_InitOnce::initialization_done() && theTLS.get() ) + runtime_warning( "TBB is unloaded while tbb::task_scheduler_init object is alive?" ); +#endif + int status = theTLS.destroy(); + if( status ) + handle_perror(status, "TBB failed to destroy task scheduler TLS"); + dynamic_unlink_all(); +} + +rml::tbb_server* governor::create_rml_server ( rml::tbb_client& client ) { + rml::tbb_server* server = NULL; + if( !UsePrivateRML ) { + ::rml::factory::status_type status = theRMLServerFactory.make_server( server, client ); + if( status != ::rml::factory::st_success ) { + UsePrivateRML = true; + runtime_warning( "rml::tbb_factory::make_server failed with status %x, falling back on private rml", status ); + } + } + if ( !server ) { + __TBB_ASSERT( UsePrivateRML, NULL ); + server = rml::make_private_server( client ); + } + __TBB_ASSERT( server, "Failed to create RML server" ); + return server; +} + +void governor::sign_on(generic_scheduler* s) { + __TBB_ASSERT( !theTLS.get(), NULL ); + theTLS.set(s); +#if __TBB_SURVIVE_THREAD_SWITCH + if( watch_stack_handler ) { + __cilk_tbb_stack_op_thunk o; + o.routine = &stack_op_handler; + o.data = s; + if( (*watch_stack_handler)(&s->my_cilk_unwatch_thunk, o) ) { + // Failed to register with cilkrts, make sure we are clean + s->my_cilk_unwatch_thunk.routine = NULL; + } +#if TBB_USE_ASSERT + else + s->my_cilk_state = generic_scheduler::cs_running; +#endif /* TBB_USE_ASSERT */ + } +#endif /* __TBB_SURVIVE_THREAD_SWITCH */ +} + +void governor::sign_off(generic_scheduler* s) { + suppress_unused_warning(s); + __TBB_ASSERT( theTLS.get()==s, "attempt to unregister a wrong scheduler instance" ); + theTLS.set(NULL); +#if __TBB_SURVIVE_THREAD_SWITCH + __cilk_tbb_unwatch_thunk &ut = s->my_cilk_unwatch_thunk; + if ( ut.routine ) + (*ut.routine)(ut.data); +#endif /* __TBB_SURVIVE_THREAD_SWITCH */ +} + +generic_scheduler* governor::init_scheduler( unsigned num_threads, stack_size_type stack_size, bool auto_init ) { + if( !__TBB_InitOnce::initialization_done() ) + DoOneTimeInitializations(); + generic_scheduler* s = theTLS.get(); + if( s ) { + s->my_ref_count += 1; + return s; + } +#if __TBB_SURVIVE_THREAD_SWITCH + atomic_do_once( &initialize_cilk_interop, cilkrts_load_state ); +#endif /* __TBB_SURVIVE_THREAD_SWITCH */ + if( (int)num_threads == task_scheduler_init::automatic ) + num_threads = default_num_threads(); + s = generic_scheduler::create_master( + market::create_arena( num_threads - 1, stack_size ? stack_size : ThreadStackSize ) ); + __TBB_ASSERT(s, "Somehow a local scheduler creation for a master thread failed"); + s->my_auto_initialized = auto_init; + return s; +} + +void governor::terminate_scheduler( generic_scheduler* s ) { + __TBB_ASSERT( s == theTLS.get(), "Attempt to terminate non-local scheduler instance" ); + if( !--(s->my_ref_count) ) + s->cleanup_master(); +} + +void governor::auto_terminate(void* arg){ + generic_scheduler* s = static_cast<generic_scheduler*>(arg); + if( s && s->my_auto_initialized ) { + if( !--(s->my_ref_count) ) { + // If the TLS slot is already cleared by OS or underlying concurrency + // runtime, restore its value. + if ( !theTLS.get() ) + theTLS.set(s); + s->cleanup_master(); + __TBB_ASSERT( !theTLS.get(), "cleanup_master has not cleared its TLS slot" ); + } + } +} + +void governor::print_version_info () { + if ( UsePrivateRML ) + PrintExtraVersionInfo( "RML", "private" ); + else { + PrintExtraVersionInfo( "RML", "shared" ); + theRMLServerFactory.call_with_server_info( PrintRMLVersionInfo, (void*)"" ); + } +#if __TBB_SURVIVE_THREAD_SWITCH + if( watch_stack_handler ) + PrintExtraVersionInfo( "CILK", CILKLIB_NAME ); +#endif /* __TBB_SURVIVE_THREAD_SWITCH */ +} + +void governor::initialize_rml_factory () { + ::rml::factory::status_type res = theRMLServerFactory.open(); + UsePrivateRML = res != ::rml::factory::st_success; +} + +#if __TBB_SURVIVE_THREAD_SWITCH +__cilk_tbb_retcode governor::stack_op_handler( __cilk_tbb_stack_op op, void* data ) { + __TBB_ASSERT(data,NULL); + generic_scheduler* s = static_cast<generic_scheduler*>(data); +#if TBB_USE_ASSERT + void* current = theTLS.get(); +#if _WIN32||_WIN64 + uintptr_t thread_id = GetCurrentThreadId(); +#else + uintptr_t thread_id = uintptr_t(pthread_self()); +#endif + +#endif /* TBB_USE_ASSERT */ + switch( op ) { + default: + __TBB_ASSERT( 0, "invalid op" ); + case CILK_TBB_STACK_ADOPT: { + __TBB_ASSERT( !current && s->my_cilk_state==generic_scheduler::cs_limbo || + current==s && s->my_cilk_state==generic_scheduler::cs_running, "invalid adoption" ); +#if TBB_USE_ASSERT + if( current==s ) + runtime_warning( "redundant adoption of %p by thread %p\n", s, (void*)thread_id ); + s->my_cilk_state = generic_scheduler::cs_running; +#endif /* TBB_USE_ASSERT */ + theTLS.set(s); + break; + } + case CILK_TBB_STACK_ORPHAN: { + __TBB_ASSERT( current==s && s->my_cilk_state==generic_scheduler::cs_running, "invalid orphaning" ); +#if TBB_USE_ASSERT + s->my_cilk_state = generic_scheduler::cs_limbo; +#endif /* TBB_USE_ASSERT */ + theTLS.set(NULL); + break; + } + case CILK_TBB_STACK_RELEASE: { + __TBB_ASSERT( !current && s->my_cilk_state==generic_scheduler::cs_limbo || + current==s && s->my_cilk_state==generic_scheduler::cs_running, "invalid release" ); +#if TBB_USE_ASSERT + s->my_cilk_state = generic_scheduler::cs_freed; +#endif /* TBB_USE_ASSERT */ + s->my_cilk_unwatch_thunk.routine = NULL; + auto_terminate( s ); + } + } + return 0; +} +#endif /* __TBB_SURVIVE_THREAD_SWITCH */ + +} // namespace internal + +//------------------------------------------------------------------------ +// task_scheduler_init +//------------------------------------------------------------------------ + +using namespace internal; + +/** Left out-of-line for the sake of the backward binary compatibility **/ +void task_scheduler_init::initialize( int number_of_threads ) { + initialize( number_of_threads, 0 ); +} + +void task_scheduler_init::initialize( int number_of_threads, stack_size_type thread_stack_size ) { +#if __TBB_TASK_GROUP_CONTEXT && TBB_USE_EXCEPTIONS + uintptr_t new_mode = thread_stack_size & propagation_mode_mask; +#endif + thread_stack_size &= ~(stack_size_type)propagation_mode_mask; + if( number_of_threads!=deferred ) { + __TBB_ASSERT( !my_scheduler, "task_scheduler_init already initialized" ); + __TBB_ASSERT( number_of_threads==-1 || number_of_threads>=1, + "number_of_threads for task_scheduler_init must be -1 or positive" ); + internal::generic_scheduler *s = governor::init_scheduler( number_of_threads, thread_stack_size ); +#if __TBB_TASK_GROUP_CONTEXT && TBB_USE_EXCEPTIONS + if ( s->master_outermost_level() ) { + uintptr_t &vt = s->default_context()->my_version_and_traits; + uintptr_t prev_mode = vt & task_group_context::exact_exception ? propagation_mode_exact : 0; + vt = new_mode & propagation_mode_exact ? vt | task_group_context::exact_exception + : new_mode & propagation_mode_captured ? vt & ~task_group_context::exact_exception : vt; + // Use least significant bit of the scheduler pointer to store previous mode. + // This is necessary when components compiled with different compilers and/or + // TBB versions initialize the + my_scheduler = static_cast<scheduler*>((generic_scheduler*)((uintptr_t)s | prev_mode)); + } + else +#endif /* __TBB_TASK_GROUP_CONTEXT && TBB_USE_EXCEPTIONS */ + my_scheduler = s; + } else { + __TBB_ASSERT( !thread_stack_size, "deferred initialization ignores stack size setting" ); + } +} + +void task_scheduler_init::terminate() { +#if __TBB_TASK_GROUP_CONTEXT && TBB_USE_EXCEPTIONS + uintptr_t prev_mode = (uintptr_t)my_scheduler & propagation_mode_exact; + my_scheduler = (scheduler*)((uintptr_t)my_scheduler & ~(uintptr_t)propagation_mode_exact); +#endif /* __TBB_TASK_GROUP_CONTEXT && TBB_USE_EXCEPTIONS */ + generic_scheduler* s = static_cast<generic_scheduler*>(my_scheduler); + my_scheduler = NULL; + __TBB_ASSERT( s, "task_scheduler_init::terminate without corresponding task_scheduler_init::initialize()"); +#if __TBB_TASK_GROUP_CONTEXT && TBB_USE_EXCEPTIONS + if ( s->master_outermost_level() ) { + uintptr_t &vt = s->default_context()->my_version_and_traits; + vt = prev_mode & propagation_mode_exact ? vt | task_group_context::exact_exception + : vt & ~task_group_context::exact_exception; + } +#endif /* __TBB_TASK_GROUP_CONTEXT && TBB_USE_EXCEPTIONS */ + governor::terminate_scheduler(s); +} + +int task_scheduler_init::default_num_threads() { + return governor::default_num_threads(); +} + +} // namespace tbb diff --git a/src/tbb/src/tbb/governor.h b/src/tbb/src/tbb/governor.h new file mode 100644 index 0000000..b2a4cd2 --- /dev/null +++ b/src/tbb/src/tbb/governor.h @@ -0,0 +1,147 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _TBB_governor_H +#define _TBB_governor_H + +#include "tbb/task_scheduler_init.h" +#include "../rml/include/rml_tbb.h" + +#include "tbb_misc.h" // for AvailableHwConcurrency and ThreadStackSize +#include "tls.h" + +#if __TBB_SURVIVE_THREAD_SWITCH +#include "cilk-tbb-interop.h" +#endif /* __TBB_SURVIVE_THREAD_SWITCH */ + +namespace tbb { +namespace internal { + +class market; +class generic_scheduler; +class __TBB_InitOnce; + +//------------------------------------------------------------------------ +// Class governor +//------------------------------------------------------------------------ + +//! The class handles access to the single instance of market, and to TLS to keep scheduler instances. +/** It also supports automatic on-demand initialization of the TBB scheduler. + The class contains only static data members and methods.*/ +class governor { + friend class __TBB_InitOnce; + friend class market; + + //! TLS for scheduler instances associated with individual threads + static basic_tls<generic_scheduler*> theTLS; + + //! Caches the maximal level of paralellism supported by the hardware + static unsigned DefaultNumberOfThreads; + + static rml::tbb_factory theRMLServerFactory; + + static bool UsePrivateRML; + + //! Create key for thread-local storage and initialize RML. + static void acquire_resources (); + + //! Destroy the thread-local storage key and deinitialize RML. + static void release_resources (); + + static rml::tbb_server* create_rml_server ( rml::tbb_client& ); + + //! The internal routine to undo automatic initialization. + /** The signature is written with void* so that the routine + can be the destructor argument to pthread_key_create. */ + static void auto_terminate(void* scheduler); + +public: + static unsigned default_num_threads () { + // No memory fence required, because at worst each invoking thread calls AvailableHwConcurrency once. + return DefaultNumberOfThreads ? DefaultNumberOfThreads : + DefaultNumberOfThreads = AvailableHwConcurrency(); + } + //! Processes scheduler initialization request (possibly nested) in a master thread + /** If necessary creates new instance of arena and/or local scheduler. + The auto_init argument specifies if the call is due to automatic initialization. **/ + static generic_scheduler* init_scheduler( unsigned num_threads, stack_size_type stack_size, bool auto_init = false ); + + //! Processes scheduler termination request (possibly nested) in a master thread + static void terminate_scheduler( generic_scheduler* s ); + + //! Returns number of worker threads in the currently active arena. + inline static unsigned max_number_of_workers (); + + //! Register TBB scheduler instance in thread-local storage. + static void sign_on(generic_scheduler* s); + + //! Unregister TBB scheduler instance from thread-local storage. + static void sign_off(generic_scheduler* s); + + //! Used to check validity of the local scheduler TLS contents. + static bool is_set ( generic_scheduler* s ) { return theTLS.get() == s; } + + //! Temporarily set TLS slot to the given scheduler + static void assume_scheduler( generic_scheduler* s ) { theTLS.set( s ); } + + //! Obtain the thread-local instance of the TBB scheduler. + /** If the scheduler has not been initialized yet, initialization is done automatically. + Note that auto-initialized scheduler instance is destroyed only when its thread terminates. **/ + static generic_scheduler* local_scheduler () { + generic_scheduler* s = theTLS.get(); + return s ? s : init_scheduler( (unsigned)task_scheduler_init::automatic, 0, true ); + } + + static generic_scheduler* local_scheduler_if_initialized () { + return theTLS.get(); + } + + //! Undo automatic initialization if necessary; call when a thread exits. + static void terminate_auto_initialized_scheduler() { + auto_terminate( theTLS.get() ); + } + + static void print_version_info (); + + static void initialize_rml_factory (); + +#if __TBB_SURVIVE_THREAD_SWITCH + static __cilk_tbb_retcode stack_op_handler( __cilk_tbb_stack_op op, void* ); +#endif /* __TBB_SURVIVE_THREAD_SWITCH */ +}; // class governor + +} // namespace internal +} // namespace tbb + +#include "scheduler.h" + +inline unsigned tbb::internal::governor::max_number_of_workers () { + return local_scheduler()->number_of_workers_in_my_arena(); +} + +#endif /* _TBB_governor_H */ diff --git a/src/tbb/src/tbb/ia32-masm/atomic_support.asm b/src/tbb/src/tbb/ia32-masm/atomic_support.asm new file mode 100644 index 0000000..a87cf74 --- /dev/null +++ b/src/tbb/src/tbb/ia32-masm/atomic_support.asm @@ -0,0 +1,196 @@ +; Copyright 2005-2012 Intel Corporation. All Rights Reserved. +; +; This file is part of Threading Building Blocks. +; +; Threading Building Blocks is free software; you can redistribute it +; and/or modify it under the terms of the GNU General Public License +; version 2 as published by the Free Software Foundation. +; +; Threading Building Blocks is distributed in the hope that it will be +; useful, but WITHOUT ANY WARRANTY; without even the implied warranty +; of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with Threading Building Blocks; if not, write to the Free Software +; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +; +; As a special exception, you may use this file as part of a free software +; library without restriction. Specifically, if other files instantiate +; templates or use macros or inline functions from this file, or you compile +; this file and link it with other files to produce an executable, this +; file does not by itself cause the resulting executable to be covered by +; the GNU General Public License. This exception does not however +; invalidate any other reasons why the executable file might be covered by +; the GNU General Public License. + +.686 +.model flat,c +.code + ALIGN 4 + PUBLIC c __TBB_machine_fetchadd1 +__TBB_machine_fetchadd1: + mov edx,4[esp] + mov eax,8[esp] + lock xadd [edx],al + ret +.code + ALIGN 4 + PUBLIC c __TBB_machine_fetchstore1 +__TBB_machine_fetchstore1: + mov edx,4[esp] + mov eax,8[esp] + lock xchg [edx],al + ret +.code + ALIGN 4 + PUBLIC c __TBB_machine_cmpswp1 +__TBB_machine_cmpswp1: + mov edx,4[esp] + mov ecx,8[esp] + mov eax,12[esp] + lock cmpxchg [edx],cl + ret +.code + ALIGN 4 + PUBLIC c __TBB_machine_fetchadd2 +__TBB_machine_fetchadd2: + mov edx,4[esp] + mov eax,8[esp] + lock xadd [edx],ax + ret +.code + ALIGN 4 + PUBLIC c __TBB_machine_fetchstore2 +__TBB_machine_fetchstore2: + mov edx,4[esp] + mov eax,8[esp] + lock xchg [edx],ax + ret +.code + ALIGN 4 + PUBLIC c __TBB_machine_cmpswp2 +__TBB_machine_cmpswp2: + mov edx,4[esp] + mov ecx,8[esp] + mov eax,12[esp] + lock cmpxchg [edx],cx + ret +.code + ALIGN 4 + PUBLIC c __TBB_machine_fetchadd4 +__TBB_machine_fetchadd4: + mov edx,4[esp] + mov eax,8[esp] + lock xadd [edx],eax + ret +.code + ALIGN 4 + PUBLIC c __TBB_machine_fetchstore4 +__TBB_machine_fetchstore4: + mov edx,4[esp] + mov eax,8[esp] + lock xchg [edx],eax + ret +.code + ALIGN 4 + PUBLIC c __TBB_machine_cmpswp4 +__TBB_machine_cmpswp4: + mov edx,4[esp] + mov ecx,8[esp] + mov eax,12[esp] + lock cmpxchg [edx],ecx + ret +.code + ALIGN 4 + PUBLIC c __TBB_machine_fetchadd8 +__TBB_machine_fetchadd8: + push ebx + push edi + mov edi,12[esp] + mov eax,[edi] + mov edx,4[edi] +__TBB_machine_fetchadd8_loop: + mov ebx,16[esp] + mov ecx,20[esp] + add ebx,eax + adc ecx,edx + lock cmpxchg8b qword ptr [edi] + jnz __TBB_machine_fetchadd8_loop + pop edi + pop ebx + ret +.code + ALIGN 4 + PUBLIC c __TBB_machine_fetchstore8 +__TBB_machine_fetchstore8: + push ebx + push edi + mov edi,12[esp] + mov ebx,16[esp] + mov ecx,20[esp] + mov eax,[edi] + mov edx,4[edi] +__TBB_machine_fetchstore8_loop: + lock cmpxchg8b qword ptr [edi] + jnz __TBB_machine_fetchstore8_loop + pop edi + pop ebx + ret +.code + ALIGN 4 + PUBLIC c __TBB_machine_cmpswp8 +__TBB_machine_cmpswp8: + push ebx + push edi + mov edi,12[esp] + mov ebx,16[esp] + mov ecx,20[esp] + mov eax,24[esp] + mov edx,28[esp] + lock cmpxchg8b qword ptr [edi] + pop edi + pop ebx + ret +.code + ALIGN 4 + PUBLIC c __TBB_machine_load8 +__TBB_machine_Load8: + ; If location is on stack, compiler may have failed to align it correctly, so we do dynamic check. + mov ecx,4[esp] + test ecx,7 + jne load_slow + ; Load within a cache line + sub esp,12 + fild qword ptr [ecx] + fistp qword ptr [esp] + mov eax,[esp] + mov edx,4[esp] + add esp,12 + ret +load_slow: + ; Load is misaligned. Use cmpxchg8b. + push ebx + push edi + mov edi,ecx + xor eax,eax + xor ebx,ebx + xor ecx,ecx + xor edx,edx + lock cmpxchg8b qword ptr [edi] + pop edi + pop ebx + ret +EXTRN __TBB_machine_store8_slow:PROC +.code + ALIGN 4 + PUBLIC c __TBB_machine_store8 +__TBB_machine_Store8: + ; If location is on stack, compiler may have failed to align it correctly, so we do dynamic check. + mov ecx,4[esp] + test ecx,7 + jne __TBB_machine_store8_slow ;; tail call to tbb_misc.cpp + fild qword ptr 8[esp] + fistp qword ptr [ecx] + ret +end diff --git a/src/tbb/src/tbb/ia32-masm/lock_byte.asm b/src/tbb/src/tbb/ia32-masm/lock_byte.asm new file mode 100644 index 0000000..0e9a24a --- /dev/null +++ b/src/tbb/src/tbb/ia32-masm/lock_byte.asm @@ -0,0 +1,46 @@ +; Copyright 2005-2012 Intel Corporation. All Rights Reserved. +; +; This file is part of Threading Building Blocks. +; +; Threading Building Blocks is free software; you can redistribute it +; and/or modify it under the terms of the GNU General Public License +; version 2 as published by the Free Software Foundation. +; +; Threading Building Blocks is distributed in the hope that it will be +; useful, but WITHOUT ANY WARRANTY; without even the implied warranty +; of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with Threading Building Blocks; if not, write to the Free Software +; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +; +; As a special exception, you may use this file as part of a free software +; library without restriction. Specifically, if other files instantiate +; templates or use macros or inline functions from this file, or you compile +; this file and link it with other files to produce an executable, this +; file does not by itself cause the resulting executable to be covered by +; the GNU General Public License. This exception does not however +; invalidate any other reasons why the executable file might be covered by +; the GNU General Public License. + +; DO NOT EDIT - AUTOMATICALLY GENERATED FROM .s FILE +.686 +.model flat,c +.code + ALIGN 4 + PUBLIC c __TBB_machine_trylockbyte +__TBB_machine_trylockbyte: + mov edx,4[esp] + mov al,[edx] + mov cl,1 + test al,1 + jnz __TBB_machine_trylockbyte_contended + lock cmpxchg [edx],cl + jne __TBB_machine_trylockbyte_contended + mov eax,1 + ret +__TBB_machine_trylockbyte_contended: + xor eax,eax + ret +end diff --git a/src/tbb/src/tbb/ia64-gas/atomic_support.s b/src/tbb/src/tbb/ia64-gas/atomic_support.s new file mode 100644 index 0000000..5d0f943 --- /dev/null +++ b/src/tbb/src/tbb/ia64-gas/atomic_support.s @@ -0,0 +1,678 @@ +// Copyright 2005-2012 Intel Corporation. All Rights Reserved. +// +// This file is part of Threading Building Blocks. +// +// Threading Building Blocks is free software; you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// Threading Building Blocks is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Threading Building Blocks; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// DO NOT EDIT - AUTOMATICALLY GENERATED FROM tools/generate_atomic/ipf_generate.sh +# 1 "<stdin>" +# 1 "<built-in>" +# 1 "<command line>" +# 1 "<stdin>" + + + + + + .section .text + .align 16 + + + .proc __TBB_machine_fetchadd1__TBB_full_fence# + .global __TBB_machine_fetchadd1__TBB_full_fence# +__TBB_machine_fetchadd1__TBB_full_fence: +{ + mf + br __TBB_machine_fetchadd1acquire +} + .endp __TBB_machine_fetchadd1__TBB_full_fence# + + .proc __TBB_machine_fetchadd1acquire# + .global __TBB_machine_fetchadd1acquire# +__TBB_machine_fetchadd1acquire: + + + + + + + + ld1 r9=[r32] +;; +Retry_1acquire: + mov ar.ccv=r9 + mov r8=r9; + add r10=r9,r33 +;; + cmpxchg1.acq r9=[r32],r10,ar.ccv +;; + cmp.ne p7,p0=r8,r9 + (p7) br.cond.dpnt Retry_1acquire + br.ret.sptk.many b0 +# 49 "<stdin>" + .endp __TBB_machine_fetchadd1acquire# +# 62 "<stdin>" + .section .text + .align 16 + .proc __TBB_machine_fetchstore1__TBB_full_fence# + .global __TBB_machine_fetchstore1__TBB_full_fence# +__TBB_machine_fetchstore1__TBB_full_fence: + mf +;; + xchg1 r8=[r32],r33 + br.ret.sptk.many b0 + .endp __TBB_machine_fetchstore1__TBB_full_fence# + + + .proc __TBB_machine_fetchstore1acquire# + .global __TBB_machine_fetchstore1acquire# +__TBB_machine_fetchstore1acquire: + xchg1 r8=[r32],r33 + br.ret.sptk.many b0 + .endp __TBB_machine_fetchstore1acquire# +# 88 "<stdin>" + .section .text + .align 16 + + + .proc __TBB_machine_cmpswp1__TBB_full_fence# + .global __TBB_machine_cmpswp1__TBB_full_fence# +__TBB_machine_cmpswp1__TBB_full_fence: +{ + mf + br __TBB_machine_cmpswp1acquire +} + .endp __TBB_machine_cmpswp1__TBB_full_fence# + + .proc __TBB_machine_cmpswp1acquire# + .global __TBB_machine_cmpswp1acquire# +__TBB_machine_cmpswp1acquire: + + zxt1 r34=r34 +;; + + mov ar.ccv=r34 +;; + cmpxchg1.acq r8=[r32],r33,ar.ccv + br.ret.sptk.many b0 + .endp __TBB_machine_cmpswp1acquire# +// DO NOT EDIT - AUTOMATICALLY GENERATED FROM tools/generate_atomic/ipf_generate.sh +# 1 "<stdin>" +# 1 "<built-in>" +# 1 "<command line>" +# 1 "<stdin>" + + + + + + .section .text + .align 16 + + + .proc __TBB_machine_fetchadd2__TBB_full_fence# + .global __TBB_machine_fetchadd2__TBB_full_fence# +__TBB_machine_fetchadd2__TBB_full_fence: +{ + mf + br __TBB_machine_fetchadd2acquire +} + .endp __TBB_machine_fetchadd2__TBB_full_fence# + + .proc __TBB_machine_fetchadd2acquire# + .global __TBB_machine_fetchadd2acquire# +__TBB_machine_fetchadd2acquire: + + + + + + + + ld2 r9=[r32] +;; +Retry_2acquire: + mov ar.ccv=r9 + mov r8=r9; + add r10=r9,r33 +;; + cmpxchg2.acq r9=[r32],r10,ar.ccv +;; + cmp.ne p7,p0=r8,r9 + (p7) br.cond.dpnt Retry_2acquire + br.ret.sptk.many b0 +# 49 "<stdin>" + .endp __TBB_machine_fetchadd2acquire# +# 62 "<stdin>" + .section .text + .align 16 + .proc __TBB_machine_fetchstore2__TBB_full_fence# + .global __TBB_machine_fetchstore2__TBB_full_fence# +__TBB_machine_fetchstore2__TBB_full_fence: + mf +;; + xchg2 r8=[r32],r33 + br.ret.sptk.many b0 + .endp __TBB_machine_fetchstore2__TBB_full_fence# + + + .proc __TBB_machine_fetchstore2acquire# + .global __TBB_machine_fetchstore2acquire# +__TBB_machine_fetchstore2acquire: + xchg2 r8=[r32],r33 + br.ret.sptk.many b0 + .endp __TBB_machine_fetchstore2acquire# +# 88 "<stdin>" + .section .text + .align 16 + + + .proc __TBB_machine_cmpswp2__TBB_full_fence# + .global __TBB_machine_cmpswp2__TBB_full_fence# +__TBB_machine_cmpswp2__TBB_full_fence: +{ + mf + br __TBB_machine_cmpswp2acquire +} + .endp __TBB_machine_cmpswp2__TBB_full_fence# + + .proc __TBB_machine_cmpswp2acquire# + .global __TBB_machine_cmpswp2acquire# +__TBB_machine_cmpswp2acquire: + + zxt2 r34=r34 +;; + + mov ar.ccv=r34 +;; + cmpxchg2.acq r8=[r32],r33,ar.ccv + br.ret.sptk.many b0 + .endp __TBB_machine_cmpswp2acquire# +// DO NOT EDIT - AUTOMATICALLY GENERATED FROM tools/generate_atomic/ipf_generate.sh +# 1 "<stdin>" +# 1 "<built-in>" +# 1 "<command line>" +# 1 "<stdin>" + + + + + + .section .text + .align 16 + + + .proc __TBB_machine_fetchadd4__TBB_full_fence# + .global __TBB_machine_fetchadd4__TBB_full_fence# +__TBB_machine_fetchadd4__TBB_full_fence: +{ + mf + br __TBB_machine_fetchadd4acquire +} + .endp __TBB_machine_fetchadd4__TBB_full_fence# + + .proc __TBB_machine_fetchadd4acquire# + .global __TBB_machine_fetchadd4acquire# +__TBB_machine_fetchadd4acquire: + + cmp.eq p6,p0=1,r33 + cmp.eq p8,p0=-1,r33 + (p6) br.cond.dptk Inc_4acquire + (p8) br.cond.dpnt Dec_4acquire +;; + + ld4 r9=[r32] +;; +Retry_4acquire: + mov ar.ccv=r9 + mov r8=r9; + add r10=r9,r33 +;; + cmpxchg4.acq r9=[r32],r10,ar.ccv +;; + cmp.ne p7,p0=r8,r9 + (p7) br.cond.dpnt Retry_4acquire + br.ret.sptk.many b0 + +Inc_4acquire: + fetchadd4.acq r8=[r32],1 + br.ret.sptk.many b0 +Dec_4acquire: + fetchadd4.acq r8=[r32],-1 + br.ret.sptk.many b0 + + .endp __TBB_machine_fetchadd4acquire# +# 62 "<stdin>" + .section .text + .align 16 + .proc __TBB_machine_fetchstore4__TBB_full_fence# + .global __TBB_machine_fetchstore4__TBB_full_fence# +__TBB_machine_fetchstore4__TBB_full_fence: + mf +;; + xchg4 r8=[r32],r33 + br.ret.sptk.many b0 + .endp __TBB_machine_fetchstore4__TBB_full_fence# + + + .proc __TBB_machine_fetchstore4acquire# + .global __TBB_machine_fetchstore4acquire# +__TBB_machine_fetchstore4acquire: + xchg4 r8=[r32],r33 + br.ret.sptk.many b0 + .endp __TBB_machine_fetchstore4acquire# +# 88 "<stdin>" + .section .text + .align 16 + + + .proc __TBB_machine_cmpswp4__TBB_full_fence# + .global __TBB_machine_cmpswp4__TBB_full_fence# +__TBB_machine_cmpswp4__TBB_full_fence: +{ + mf + br __TBB_machine_cmpswp4acquire +} + .endp __TBB_machine_cmpswp4__TBB_full_fence# + + .proc __TBB_machine_cmpswp4acquire# + .global __TBB_machine_cmpswp4acquire# +__TBB_machine_cmpswp4acquire: + + zxt4 r34=r34 +;; + + mov ar.ccv=r34 +;; + cmpxchg4.acq r8=[r32],r33,ar.ccv + br.ret.sptk.many b0 + .endp __TBB_machine_cmpswp4acquire# +// DO NOT EDIT - AUTOMATICALLY GENERATED FROM tools/generate_atomic/ipf_generate.sh +# 1 "<stdin>" +# 1 "<built-in>" +# 1 "<command line>" +# 1 "<stdin>" + + + + + + .section .text + .align 16 + + + .proc __TBB_machine_fetchadd8__TBB_full_fence# + .global __TBB_machine_fetchadd8__TBB_full_fence# +__TBB_machine_fetchadd8__TBB_full_fence: +{ + mf + br __TBB_machine_fetchadd8acquire +} + .endp __TBB_machine_fetchadd8__TBB_full_fence# + + .proc __TBB_machine_fetchadd8acquire# + .global __TBB_machine_fetchadd8acquire# +__TBB_machine_fetchadd8acquire: + + cmp.eq p6,p0=1,r33 + cmp.eq p8,p0=-1,r33 + (p6) br.cond.dptk Inc_8acquire + (p8) br.cond.dpnt Dec_8acquire +;; + + ld8 r9=[r32] +;; +Retry_8acquire: + mov ar.ccv=r9 + mov r8=r9; + add r10=r9,r33 +;; + cmpxchg8.acq r9=[r32],r10,ar.ccv +;; + cmp.ne p7,p0=r8,r9 + (p7) br.cond.dpnt Retry_8acquire + br.ret.sptk.many b0 + +Inc_8acquire: + fetchadd8.acq r8=[r32],1 + br.ret.sptk.many b0 +Dec_8acquire: + fetchadd8.acq r8=[r32],-1 + br.ret.sptk.many b0 + + .endp __TBB_machine_fetchadd8acquire# +# 62 "<stdin>" + .section .text + .align 16 + .proc __TBB_machine_fetchstore8__TBB_full_fence# + .global __TBB_machine_fetchstore8__TBB_full_fence# +__TBB_machine_fetchstore8__TBB_full_fence: + mf +;; + xchg8 r8=[r32],r33 + br.ret.sptk.many b0 + .endp __TBB_machine_fetchstore8__TBB_full_fence# + + + .proc __TBB_machine_fetchstore8acquire# + .global __TBB_machine_fetchstore8acquire# +__TBB_machine_fetchstore8acquire: + xchg8 r8=[r32],r33 + br.ret.sptk.many b0 + .endp __TBB_machine_fetchstore8acquire# +# 88 "<stdin>" + .section .text + .align 16 + + + .proc __TBB_machine_cmpswp8__TBB_full_fence# + .global __TBB_machine_cmpswp8__TBB_full_fence# +__TBB_machine_cmpswp8__TBB_full_fence: +{ + mf + br __TBB_machine_cmpswp8acquire +} + .endp __TBB_machine_cmpswp8__TBB_full_fence# + + .proc __TBB_machine_cmpswp8acquire# + .global __TBB_machine_cmpswp8acquire# +__TBB_machine_cmpswp8acquire: + + + + + mov ar.ccv=r34 +;; + cmpxchg8.acq r8=[r32],r33,ar.ccv + br.ret.sptk.many b0 + .endp __TBB_machine_cmpswp8acquire# +// DO NOT EDIT - AUTOMATICALLY GENERATED FROM tools/generate_atomic/ipf_generate.sh +# 1 "<stdin>" +# 1 "<built-in>" +# 1 "<command line>" +# 1 "<stdin>" + + + + + + .section .text + .align 16 +# 19 "<stdin>" + .proc __TBB_machine_fetchadd1release# + .global __TBB_machine_fetchadd1release# +__TBB_machine_fetchadd1release: + + + + + + + + ld1 r9=[r32] +;; +Retry_1release: + mov ar.ccv=r9 + mov r8=r9; + add r10=r9,r33 +;; + cmpxchg1.rel r9=[r32],r10,ar.ccv +;; + cmp.ne p7,p0=r8,r9 + (p7) br.cond.dpnt Retry_1release + br.ret.sptk.many b0 +# 49 "<stdin>" + .endp __TBB_machine_fetchadd1release# +# 62 "<stdin>" + .section .text + .align 16 + .proc __TBB_machine_fetchstore1release# + .global __TBB_machine_fetchstore1release# +__TBB_machine_fetchstore1release: + mf +;; + xchg1 r8=[r32],r33 + br.ret.sptk.many b0 + .endp __TBB_machine_fetchstore1release# +# 88 "<stdin>" + .section .text + .align 16 +# 101 "<stdin>" + .proc __TBB_machine_cmpswp1release# + .global __TBB_machine_cmpswp1release# +__TBB_machine_cmpswp1release: + + zxt1 r34=r34 +;; + + mov ar.ccv=r34 +;; + cmpxchg1.rel r8=[r32],r33,ar.ccv + br.ret.sptk.many b0 + .endp __TBB_machine_cmpswp1release# +// DO NOT EDIT - AUTOMATICALLY GENERATED FROM tools/generate_atomic/ipf_generate.sh +# 1 "<stdin>" +# 1 "<built-in>" +# 1 "<command line>" +# 1 "<stdin>" + + + + + + .section .text + .align 16 +# 19 "<stdin>" + .proc __TBB_machine_fetchadd2release# + .global __TBB_machine_fetchadd2release# +__TBB_machine_fetchadd2release: + + + + + + + + ld2 r9=[r32] +;; +Retry_2release: + mov ar.ccv=r9 + mov r8=r9; + add r10=r9,r33 +;; + cmpxchg2.rel r9=[r32],r10,ar.ccv +;; + cmp.ne p7,p0=r8,r9 + (p7) br.cond.dpnt Retry_2release + br.ret.sptk.many b0 +# 49 "<stdin>" + .endp __TBB_machine_fetchadd2release# +# 62 "<stdin>" + .section .text + .align 16 + .proc __TBB_machine_fetchstore2release# + .global __TBB_machine_fetchstore2release# +__TBB_machine_fetchstore2release: + mf +;; + xchg2 r8=[r32],r33 + br.ret.sptk.many b0 + .endp __TBB_machine_fetchstore2release# +# 88 "<stdin>" + .section .text + .align 16 +# 101 "<stdin>" + .proc __TBB_machine_cmpswp2release# + .global __TBB_machine_cmpswp2release# +__TBB_machine_cmpswp2release: + + zxt2 r34=r34 +;; + + mov ar.ccv=r34 +;; + cmpxchg2.rel r8=[r32],r33,ar.ccv + br.ret.sptk.many b0 + .endp __TBB_machine_cmpswp2release# +// DO NOT EDIT - AUTOMATICALLY GENERATED FROM tools/generate_atomic/ipf_generate.sh +# 1 "<stdin>" +# 1 "<built-in>" +# 1 "<command line>" +# 1 "<stdin>" + + + + + + .section .text + .align 16 +# 19 "<stdin>" + .proc __TBB_machine_fetchadd4release# + .global __TBB_machine_fetchadd4release# +__TBB_machine_fetchadd4release: + + cmp.eq p6,p0=1,r33 + cmp.eq p8,p0=-1,r33 + (p6) br.cond.dptk Inc_4release + (p8) br.cond.dpnt Dec_4release +;; + + ld4 r9=[r32] +;; +Retry_4release: + mov ar.ccv=r9 + mov r8=r9; + add r10=r9,r33 +;; + cmpxchg4.rel r9=[r32],r10,ar.ccv +;; + cmp.ne p7,p0=r8,r9 + (p7) br.cond.dpnt Retry_4release + br.ret.sptk.many b0 + +Inc_4release: + fetchadd4.rel r8=[r32],1 + br.ret.sptk.many b0 +Dec_4release: + fetchadd4.rel r8=[r32],-1 + br.ret.sptk.many b0 + + .endp __TBB_machine_fetchadd4release# +# 62 "<stdin>" + .section .text + .align 16 + .proc __TBB_machine_fetchstore4release# + .global __TBB_machine_fetchstore4release# +__TBB_machine_fetchstore4release: + mf +;; + xchg4 r8=[r32],r33 + br.ret.sptk.many b0 + .endp __TBB_machine_fetchstore4release# +# 88 "<stdin>" + .section .text + .align 16 +# 101 "<stdin>" + .proc __TBB_machine_cmpswp4release# + .global __TBB_machine_cmpswp4release# +__TBB_machine_cmpswp4release: + + zxt4 r34=r34 +;; + + mov ar.ccv=r34 +;; + cmpxchg4.rel r8=[r32],r33,ar.ccv + br.ret.sptk.many b0 + .endp __TBB_machine_cmpswp4release# +// DO NOT EDIT - AUTOMATICALLY GENERATED FROM tools/generate_atomic/ipf_generate.sh +# 1 "<stdin>" +# 1 "<built-in>" +# 1 "<command line>" +# 1 "<stdin>" + + + + + + .section .text + .align 16 +# 19 "<stdin>" + .proc __TBB_machine_fetchadd8release# + .global __TBB_machine_fetchadd8release# +__TBB_machine_fetchadd8release: + + cmp.eq p6,p0=1,r33 + cmp.eq p8,p0=-1,r33 + (p6) br.cond.dptk Inc_8release + (p8) br.cond.dpnt Dec_8release +;; + + ld8 r9=[r32] +;; +Retry_8release: + mov ar.ccv=r9 + mov r8=r9; + add r10=r9,r33 +;; + cmpxchg8.rel r9=[r32],r10,ar.ccv +;; + cmp.ne p7,p0=r8,r9 + (p7) br.cond.dpnt Retry_8release + br.ret.sptk.many b0 + +Inc_8release: + fetchadd8.rel r8=[r32],1 + br.ret.sptk.many b0 +Dec_8release: + fetchadd8.rel r8=[r32],-1 + br.ret.sptk.many b0 + + .endp __TBB_machine_fetchadd8release# +# 62 "<stdin>" + .section .text + .align 16 + .proc __TBB_machine_fetchstore8release# + .global __TBB_machine_fetchstore8release# +__TBB_machine_fetchstore8release: + mf +;; + xchg8 r8=[r32],r33 + br.ret.sptk.many b0 + .endp __TBB_machine_fetchstore8release# +# 88 "<stdin>" + .section .text + .align 16 +# 101 "<stdin>" + .proc __TBB_machine_cmpswp8release# + .global __TBB_machine_cmpswp8release# +__TBB_machine_cmpswp8release: + + + + + mov ar.ccv=r34 +;; + cmpxchg8.rel r8=[r32],r33,ar.ccv + br.ret.sptk.many b0 + .endp __TBB_machine_cmpswp8release# diff --git a/src/tbb/src/tbb/ia64-gas/ia64_misc.s b/src/tbb/src/tbb/ia64-gas/ia64_misc.s new file mode 100644 index 0000000..2f5889a --- /dev/null +++ b/src/tbb/src/tbb/ia64-gas/ia64_misc.s @@ -0,0 +1,107 @@ +// Copyright 2005-2012 Intel Corporation. All Rights Reserved. +// +// This file is part of Threading Building Blocks. +// +// Threading Building Blocks is free software; you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// Threading Building Blocks is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Threading Building Blocks; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + + // RSE backing store pointer retrieval + .section .text + .align 16 + .proc __TBB_get_bsp# + .global __TBB_get_bsp# +__TBB_get_bsp: + mov r8=ar.bsp + br.ret.sptk.many b0 + .endp __TBB_get_bsp# + + .section .text + .align 16 + .proc __TBB_machine_load8_relaxed# + .global __TBB_machine_load8_relaxed# +__TBB_machine_load8_relaxed: + ld8 r8=[r32] + br.ret.sptk.many b0 + .endp __TBB_machine_load8_relaxed# + + .section .text + .align 16 + .proc __TBB_machine_store8_relaxed# + .global __TBB_machine_store8_relaxed# +__TBB_machine_store8_relaxed: + st8 [r32]=r33 + br.ret.sptk.many b0 + .endp __TBB_machine_store8_relaxed# + + .section .text + .align 16 + .proc __TBB_machine_load4_relaxed# + .global __TBB_machine_load4_relaxed# +__TBB_machine_load4_relaxed: + ld4 r8=[r32] + br.ret.sptk.many b0 + .endp __TBB_machine_load4_relaxed# + + .section .text + .align 16 + .proc __TBB_machine_store4_relaxed# + .global __TBB_machine_store4_relaxed# +__TBB_machine_store4_relaxed: + st4 [r32]=r33 + br.ret.sptk.many b0 + .endp __TBB_machine_store4_relaxed# + + .section .text + .align 16 + .proc __TBB_machine_load2_relaxed# + .global __TBB_machine_load2_relaxed# +__TBB_machine_load2_relaxed: + ld2 r8=[r32] + br.ret.sptk.many b0 + .endp __TBB_machine_load2_relaxed# + + .section .text + .align 16 + .proc __TBB_machine_store2_relaxed# + .global __TBB_machine_store2_relaxed# +__TBB_machine_store2_relaxed: + st2 [r32]=r33 + br.ret.sptk.many b0 + .endp __TBB_machine_store2_relaxed# + + .section .text + .align 16 + .proc __TBB_machine_load1_relaxed# + .global __TBB_machine_load1_relaxed# +__TBB_machine_load1_relaxed: + ld1 r8=[r32] + br.ret.sptk.many b0 + .endp __TBB_machine_load1_relaxed# + + .section .text + .align 16 + .proc __TBB_machine_store1_relaxed# + .global __TBB_machine_store1_relaxed# +__TBB_machine_store1_relaxed: + st1 [r32]=r33 + br.ret.sptk.many b0 + .endp __TBB_machine_store1_relaxed# diff --git a/src/tbb/src/tbb/ia64-gas/lock_byte.s b/src/tbb/src/tbb/ia64-gas/lock_byte.s new file mode 100644 index 0000000..377fc80 --- /dev/null +++ b/src/tbb/src/tbb/ia64-gas/lock_byte.s @@ -0,0 +1,54 @@ +// Copyright 2005-2012 Intel Corporation. All Rights Reserved. +// +// This file is part of Threading Building Blocks. +// +// Threading Building Blocks is free software; you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// Threading Building Blocks is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Threading Building Blocks; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + + // Support for class TinyLock + .section .text + .align 16 + // unsigned int __TBB_machine_trylockbyte( byte& flag ); + // r32 = address of flag + .proc __TBB_machine_trylockbyte# + .global __TBB_machine_trylockbyte# +ADDRESS_OF_FLAG=r32 +RETCODE=r8 +FLAG=r9 +BUSY=r10 +SCRATCH=r11 +__TBB_machine_trylockbyte: + ld1.acq FLAG=[ADDRESS_OF_FLAG] + mov BUSY=1 + mov RETCODE=0 +;; + cmp.ne p6,p0=0,FLAG + mov ar.ccv=r0 +(p6) br.ret.sptk.many b0 +;; + cmpxchg1.acq SCRATCH=[ADDRESS_OF_FLAG],BUSY,ar.ccv // Try to acquire lock +;; + cmp.eq p6,p0=0,SCRATCH +;; +(p6) mov RETCODE=1 + br.ret.sptk.many b0 + .endp __TBB_machine_trylockbyte# diff --git a/src/tbb/src/tbb/ia64-gas/log2.s b/src/tbb/src/tbb/ia64-gas/log2.s new file mode 100644 index 0000000..7cef1c5 --- /dev/null +++ b/src/tbb/src/tbb/ia64-gas/log2.s @@ -0,0 +1,66 @@ +// Copyright 2005-2012 Intel Corporation. All Rights Reserved. +// +// This file is part of Threading Building Blocks. +// +// Threading Building Blocks is free software; you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// Threading Building Blocks is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Threading Building Blocks; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + + .section .text + .align 16 + // unsigned long __TBB_machine_lg( unsigned long x ); + // r32 = x + .proc __TBB_machine_lg# + .global __TBB_machine_lg# +__TBB_machine_lg: + shr r16=r32,1 // .x +;; + shr r17=r32,2 // ..x + or r32=r32,r16 // xx +;; + shr r16=r32,3 // ...xx + or r32=r32,r17 // xxx +;; + shr r17=r32,5 // .....xxx + or r32=r32,r16 // xxxxx +;; + shr r16=r32,8 // ........xxxxx + or r32=r32,r17 // xxxxxxxx +;; + shr r17=r32,13 + or r32=r32,r16 // 13x +;; + shr r16=r32,21 + or r32=r32,r17 // 21x +;; + shr r17=r32,34 + or r32=r32,r16 // 34x +;; + shr r16=r32,55 + or r32=r32,r17 // 55x +;; + or r32=r32,r16 // 64x +;; + popcnt r8=r32 +;; + add r8=-1,r8 + br.ret.sptk.many b0 + .endp __TBB_machine_lg# diff --git a/src/tbb/src/tbb/ia64-gas/pause.s b/src/tbb/src/tbb/ia64-gas/pause.s new file mode 100644 index 0000000..97e1cc0 --- /dev/null +++ b/src/tbb/src/tbb/ia64-gas/pause.s @@ -0,0 +1,41 @@ +// Copyright 2005-2012 Intel Corporation. All Rights Reserved. +// +// This file is part of Threading Building Blocks. +// +// Threading Building Blocks is free software; you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// Threading Building Blocks is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Threading Building Blocks; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + + .section .text + .align 16 + // void __TBB_machine_pause( long count ); + // r32 = count + .proc __TBB_machine_pause# + .global __TBB_machine_pause# +count = r32 +__TBB_machine_pause: + hint.m 0 + add count=-1,count +;; + cmp.eq p6,p7=0,count +(p7) br.cond.dpnt __TBB_machine_pause +(p6) br.ret.sptk.many b0 + .endp __TBB_machine_pause# diff --git a/src/tbb/src/tbb/ibm_aix51/atomic_support.c b/src/tbb/src/tbb/ibm_aix51/atomic_support.c new file mode 100644 index 0000000..9001cd2 --- /dev/null +++ b/src/tbb/src/tbb/ibm_aix51/atomic_support.c @@ -0,0 +1,63 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include <stdint.h> +#include <sys/atomic_op.h> + +/* This file must be compiled with gcc. The IBM compiler doesn't seem to + support inline assembly statements (October 2007). */ + +#ifdef __GNUC__ + +int32_t __TBB_machine_cas_32 (volatile void* ptr, int32_t value, int32_t comparand) { + __asm__ __volatile__ ("sync\n"); /* memory release operation */ + compare_and_swap ((atomic_p) ptr, &comparand, value); + __asm__ __volatile__ ("isync\n"); /* memory acquire operation */ + return comparand; +} + +int64_t __TBB_machine_cas_64 (volatile void* ptr, int64_t value, int64_t comparand) { + __asm__ __volatile__ ("sync\n"); /* memory release operation */ + compare_and_swaplp ((atomic_l) ptr, &comparand, value); + __asm__ __volatile__ ("isync\n"); /* memory acquire operation */ + return comparand; +} + +void __TBB_machine_flush () { + __asm__ __volatile__ ("sync\n"); +} + +void __TBB_machine_lwsync () { + __asm__ __volatile__ ("lwsync\n"); +} + +void __TBB_machine_isync () { + __asm__ __volatile__ ("isync\n"); +} + +#endif /* __GNUC__ */ diff --git a/src/tbb/src/tbb/index.html b/src/tbb/src/tbb/index.html new file mode 100644 index 0000000..6da0f26 --- /dev/null +++ b/src/tbb/src/tbb/index.html @@ -0,0 +1,31 @@ +<HTML> +<BODY> + +<H2>Overview</H2> +This directory contains the source code of the TBB core components. + +<H2>Directories</H2> +<DL> +<DT><A HREF="tools_api">tools_api</A> +<DD>Source code of the interface components provided by the Intel® Parallel Studio tools. +<DT><A HREF="intel64-masm">intel64-masm</A> +<DD>Assembly code for the Intel® 64 architecture. +<DT><A HREF="ia32-masm">ia32-masm</A> +<DD>Assembly code for IA32 architecture. +<DT><A HREF="ia64-gas">ia64-gas</A> +<DD>Assembly code for IA64 architecture. +<DT><A HREF="ibm_aix51">ibm_aix51</A> +<DD>Assembly code for AIX 5.1 port. +</DL> + +<HR> +<A HREF="../index.html">Up to parent directory</A> +<p></p> +Copyright © 2005-2012 Intel Corporation. All Rights Reserved. +<P></P> +Intel is a registered trademark or trademark of Intel Corporation +or its subsidiaries in the United States and other countries. +<p></p> +* Other names and brands may be claimed as the property of others. +</BODY> +</HTML> diff --git a/src/tbb/src/tbb/intel64-masm/atomic_support.asm b/src/tbb/src/tbb/intel64-masm/atomic_support.asm new file mode 100644 index 0000000..b46af21 --- /dev/null +++ b/src/tbb/src/tbb/intel64-masm/atomic_support.asm @@ -0,0 +1,80 @@ +; Copyright 2005-2012 Intel Corporation. All Rights Reserved. +; +; This file is part of Threading Building Blocks. +; +; Threading Building Blocks is free software; you can redistribute it +; and/or modify it under the terms of the GNU General Public License +; version 2 as published by the Free Software Foundation. +; +; Threading Building Blocks is distributed in the hope that it will be +; useful, but WITHOUT ANY WARRANTY; without even the implied warranty +; of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with Threading Building Blocks; if not, write to the Free Software +; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +; +; As a special exception, you may use this file as part of a free software +; library without restriction. Specifically, if other files instantiate +; templates or use macros or inline functions from this file, or you compile +; this file and link it with other files to produce an executable, this +; file does not by itself cause the resulting executable to be covered by +; the GNU General Public License. This exception does not however +; invalidate any other reasons why the executable file might be covered by +; the GNU General Public License. + +; DO NOT EDIT - AUTOMATICALLY GENERATED FROM .s FILE +.code + ALIGN 8 + PUBLIC __TBB_machine_fetchadd1 +__TBB_machine_fetchadd1: + mov rax,rdx + lock xadd [rcx],al + ret +.code + ALIGN 8 + PUBLIC __TBB_machine_fetchstore1 +__TBB_machine_fetchstore1: + mov rax,rdx + lock xchg [rcx],al + ret +.code + ALIGN 8 + PUBLIC __TBB_machine_cmpswp1 +__TBB_machine_cmpswp1: + mov rax,r8 + lock cmpxchg [rcx],dl + ret +.code + ALIGN 8 + PUBLIC __TBB_machine_fetchadd2 +__TBB_machine_fetchadd2: + mov rax,rdx + lock xadd [rcx],ax + ret +.code + ALIGN 8 + PUBLIC __TBB_machine_fetchstore2 +__TBB_machine_fetchstore2: + mov rax,rdx + lock xchg [rcx],ax + ret +.code + ALIGN 8 + PUBLIC __TBB_machine_cmpswp2 +__TBB_machine_cmpswp2: + mov rax,r8 + lock cmpxchg [rcx],dx + ret +.code + ALIGN 8 + PUBLIC __TBB_machine_pause +__TBB_machine_pause: +L1: + dw 090f3H; pause + add ecx,-1 + jne L1 + ret +end + diff --git a/src/tbb/src/tbb/intel64-masm/intel64_misc.asm b/src/tbb/src/tbb/intel64-masm/intel64_misc.asm new file mode 100644 index 0000000..e9fb3d6 --- /dev/null +++ b/src/tbb/src/tbb/intel64-masm/intel64_misc.asm @@ -0,0 +1,41 @@ +; Copyright 2005-2012 Intel Corporation. All Rights Reserved. +; +; This file is part of Threading Building Blocks. +; +; Threading Building Blocks is free software; you can redistribute it +; and/or modify it under the terms of the GNU General Public License +; version 2 as published by the Free Software Foundation. +; +; Threading Building Blocks is distributed in the hope that it will be +; useful, but WITHOUT ANY WARRANTY; without even the implied warranty +; of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with Threading Building Blocks; if not, write to the Free Software +; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +; +; As a special exception, you may use this file as part of a free software +; library without restriction. Specifically, if other files instantiate +; templates or use macros or inline functions from this file, or you compile +; this file and link it with other files to produce an executable, this +; file does not by itself cause the resulting executable to be covered by +; the GNU General Public License. This exception does not however +; invalidate any other reasons why the executable file might be covered by +; the GNU General Public License. + +.code + ALIGN 8 + PUBLIC __TBB_get_cpu_ctl_env +__TBB_get_cpu_ctl_env: + stmxcsr [rcx] + fstcw [rcx+4] + ret +.code + ALIGN 8 + PUBLIC __TBB_set_cpu_ctl_env +__TBB_set_cpu_ctl_env: + ldmxcsr [rcx] + fldcw [rcx+4] + ret +end diff --git a/src/tbb/src/tbb/intrusive_list.h b/src/tbb/src/tbb/intrusive_list.h new file mode 100644 index 0000000..d9eb8bc --- /dev/null +++ b/src/tbb/src/tbb/intrusive_list.h @@ -0,0 +1,252 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _TBB_intrusive_list_H +#define _TBB_intrusive_list_H + +#include "tbb/tbb_stddef.h" + +namespace tbb { +namespace internal { + +//! Data structure to be inherited by the types that can form intrusive lists. +/** Intrusive list is formed by means of the member_intrusive_list<T> template class. + Note that type T must derive from intrusive_list_node either publicly or + declare instantiation member_intrusive_list<T> as a friend. + This class implements a limited subset of std::list interface. **/ +struct intrusive_list_node { + intrusive_list_node *my_prev_node, + *my_next_node; +#if TBB_USE_ASSERT + intrusive_list_node () { my_prev_node = my_next_node = this; } +#endif /* TBB_USE_ASSERT */ +}; + +//! List of element of type T, where T is derived from intrusive_list_node +/** The class is not thread safe. **/ +template <class List, class T> +class intrusive_list_base { + //! Pointer to the head node + intrusive_list_node my_head; + + //! Number of list elements + size_t my_size; + + static intrusive_list_node& node ( T& item ) { return List::node(item); } + + static T& item ( intrusive_list_node* node ) { return List::item(node); } + + template<class Iterator> + class iterator_impl { + Iterator& self () { return *static_cast<Iterator*>(this); } + + //! Pointer to the head of the list being iterated + intrusive_list_node *my_list_head; + + //! Node the iterator points to at the moment + intrusive_list_node *my_pos; + + protected: + iterator_impl ( intrusive_list_node* head, intrusive_list_node* pos ) + : my_list_head(head), my_pos(pos) + {} + + T& item () const { + //return *reinterpret_cast<T*>((char*)my_pos - ((ptrdiff_t)&(reinterpret_cast<T*>(0x1000)->*NodePtr) - 0x1000)); + return intrusive_list_base::item(my_pos); + } + + public: + iterator_impl () : my_list_head(NULL), my_pos(NULL) {} + + bool operator == ( const Iterator& it ) const { + return my_pos == it.my_pos; + } + + bool operator != ( const Iterator& it ) const { + return my_pos != it.my_pos; + } + + Iterator& operator++ () { + my_pos = my_pos->my_next_node; + return self(); + } + + Iterator& operator-- () { + my_pos = my_pos->my_prev_node; + return self(); + } + + Iterator operator++ ( int ) { + Iterator result = self(); + ++(*this); + return result; + } + + Iterator operator-- ( int ) { + Iterator result = self(); + --(*this); + return result; + } + }; // intrusive_list_base::iterator_impl + + void assert_ok () const { + __TBB_ASSERT( (my_head.my_prev_node == &my_head && !my_size) || + (my_head.my_next_node != &my_head && my_size >0), "intrusive_list_base corrupted" ); +#if TBB_USE_ASSERT >= 2 + size_t i = 0; + for ( intrusive_list_node *n = my_head.my_next_node; n != &my_head; n = n->my_next_node ) + ++i; + __TBB_ASSERT( my_size == i, "Wrong size" ); +#endif /* TBB_USE_ASSERT >= 2 */ + } + +public: + class iterator : public iterator_impl<iterator> { + template <class U, class V> friend class intrusive_list_base; + + iterator ( intrusive_list_node* head, intrusive_list_node* pos ) + : iterator_impl<iterator>( head, pos ) + {} + public: + iterator () {} + + T* operator-> () const { return &this->item(); } + + T& operator* () const { return this->item(); } + }; // class iterator + + class const_iterator : public iterator_impl<const_iterator> { + template <class U, class V> friend class intrusive_list_base; + + const_iterator ( const intrusive_list_node* head, const intrusive_list_node* pos ) + : iterator_impl<const_iterator>( const_cast<intrusive_list_node*>(head), const_cast<intrusive_list_node*>(pos) ) + {} + public: + const_iterator () {} + + const T* operator-> () const { return &this->item(); } + + const T& operator* () const { return this->item(); } + }; // class iterator + + intrusive_list_base () : my_size(0) { + my_head.my_prev_node = &my_head; + my_head.my_next_node = &my_head; + } + + bool empty () const { return my_head.my_next_node == &my_head; } + + size_t size () const { return my_size; } + + iterator begin () { return iterator(&my_head, my_head.my_next_node); } + + iterator end () { return iterator(&my_head, &my_head); } + + const_iterator begin () const { return const_iterator(&my_head, my_head.my_next_node); } + + const_iterator end () const { return const_iterator(&my_head, &my_head); } + + void push_front ( T& val ) { + __TBB_ASSERT( node(val).my_prev_node == &node(val) && node(val).my_next_node == &node(val), + "Object with intrusive list node can be part of only one intrusive list simultaneously" ); + // An object can be part of only one intrusive list at the given moment via the given node member + node(val).my_prev_node = &my_head; + node(val).my_next_node = my_head.my_next_node; + my_head.my_next_node->my_prev_node = &node(val); + my_head.my_next_node = &node(val); + ++my_size; + assert_ok(); + } + + void remove( T& val ) { + __TBB_ASSERT( node(val).my_prev_node != &node(val) && node(val).my_next_node != &node(val), "Element to remove is not in the list" ); + __TBB_ASSERT( node(val).my_prev_node->my_next_node == &node(val) && node(val).my_next_node->my_prev_node == &node(val), "Element to remove is not in the list" ); + --my_size; + node(val).my_next_node->my_prev_node = node(val).my_prev_node; + node(val).my_prev_node->my_next_node = node(val).my_next_node; +#if TBB_USE_ASSERT + node(val).my_prev_node = node(val).my_next_node = &node(val); +#endif + assert_ok(); + } + + iterator erase ( iterator it ) { + T& val = *it; + ++it; + remove( val ); + return it; + } + +}; // intrusive_list_base + + +//! Double linked list of items of type T containing a member of type intrusive_list_node. +/** NodePtr is a member pointer to the node data field. Class U is either T or + a base class of T containing the node member. Default values exist for the sake + of a partial specialization working with inheritance case. + + The list does not have ownership of its items. Its purpose is to avoid dynamic + memory allocation when forming lists of existing objects. + + The class is not thread safe. **/ +template <class T, class U, intrusive_list_node U::*NodePtr> +class memptr_intrusive_list : public intrusive_list_base<memptr_intrusive_list<T, U, NodePtr>, T> +{ + friend class intrusive_list_base<memptr_intrusive_list<T, U, NodePtr>, T>; + + static intrusive_list_node& node ( T& val ) { return val.*NodePtr; } + + static T& item ( intrusive_list_node* node ) { + // Cannot use __TBB_offestof (and consequently __TBB_get_object_ref) macro + // with *NodePtr argument because gcc refuses to interpret pasted "->" and "*" + // as member pointer dereferencing operator, and explicit usage of ## in + // __TBB_offestof implementation breaks operations with normal member names. + return *reinterpret_cast<T*>((char*)node - ((ptrdiff_t)&(reinterpret_cast<T*>(0x1000)->*NodePtr) - 0x1000)); + } +}; // intrusive_list<T, U, NodePtr> + +//! Double linked list of items of type T that is derived from intrusive_list_node class. +/** The list does not have ownership of its items. Its purpose is to avoid dynamic + memory allocation when forming lists of existing objects. + + The class is not thread safe. **/ +template <class T> +class intrusive_list : public intrusive_list_base<intrusive_list<T>, T> +{ + friend class intrusive_list_base<intrusive_list<T>, T>; + + static intrusive_list_node& node ( T& val ) { return val; } + + static T& item ( intrusive_list_node* node ) { return *static_cast<T*>(node); } +}; // intrusive_list<T> + +} // namespace internal +} // namespace tbb + +#endif /* _TBB_intrusive_list_H */ diff --git a/src/tbb/src/tbb/itt_notify.cpp b/src/tbb/src/tbb/itt_notify.cpp new file mode 100644 index 0000000..b8c31d9 --- /dev/null +++ b/src/tbb/src/tbb/itt_notify.cpp @@ -0,0 +1,97 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if DO_ITT_NOTIFY + +#if _WIN32||_WIN64 + #ifndef UNICODE + #define UNICODE + #endif +#else + #pragma weak dlopen + #pragma weak dlsym + #pragma weak dlerror +#endif /* WIN */ + +#if __TBB_BUILD + +extern "C" void ITT_DoOneTimeInitialization(); +#define __itt_init_ittlib_name(x,y) (ITT_DoOneTimeInitialization(), true) + +#elif __TBBMALLOC_BUILD + +extern "C" void MallocInitializeITT(); +#define __itt_init_ittlib_name(x,y) (MallocInitializeITT(), true) + +#else +#error This file is expected to be used for either TBB or TBB allocator build. +#endif // __TBB_BUILD + +#include "tools_api/ittnotify_static.c" + +namespace tbb { +namespace internal { +int __TBB_load_ittnotify() { + return __itt_init_ittlib(NULL, // groups for: + (__itt_group_id)(__itt_group_sync // prepare/cancel/acquired/releasing + | __itt_group_thread // name threads + | __itt_group_stitch // stack stitching + )); +} + +}} // namespaces + +#endif /* DO_ITT_NOTIFY */ + +#define __TBB_NO_IMPLICIT_LINKAGE 1 +#include "itt_notify.h" + +namespace tbb { + +#if DO_ITT_NOTIFY + const tchar + *SyncType_GlobalLock = _T("TbbGlobalLock"), + *SyncType_Scheduler = _T("%Constant") + ; + const tchar + *SyncObj_SchedulerInitialization = _T("TbbSchedulerInitialization"), + *SyncObj_SchedulersList = _T("TbbSchedulersList"), + *SyncObj_WorkerLifeCycleMgmt = _T("TBB Scheduler"), + *SyncObj_TaskStealingLoop = _T("TBB Scheduler"), + *SyncObj_WorkerTaskPool = _T("TBB Scheduler"), + *SyncObj_MasterTaskPool = _T("TBB Scheduler"), + *SyncObj_TaskPoolSpinning = _T("TBB Scheduler"), + *SyncObj_Mailbox = _T("TBB Scheduler"), + *SyncObj_TaskReturnList = _T("TBB Scheduler"), + *SyncObj_TaskStream = _T("TBB Scheduler"), + *SyncObj_ContextsList = _T("TBB Scheduler") + ; +#endif /* DO_ITT_NOTIFY */ + +} // namespace tbb + diff --git a/src/tbb/src/tbb/itt_notify.h b/src/tbb/src/tbb/itt_notify.h new file mode 100644 index 0000000..830cd14 --- /dev/null +++ b/src/tbb/src/tbb/itt_notify.h @@ -0,0 +1,133 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _TBB_ITT_NOTIFY +#define _TBB_ITT_NOTIFY + +#include "tbb/tbb_stddef.h" + +#if DO_ITT_NOTIFY + +#if _WIN32||_WIN64 + #ifndef UNICODE + #define UNICODE + #endif +#endif /* WIN */ + +#ifndef INTEL_ITTNOTIFY_API_PRIVATE +#define INTEL_ITTNOTIFY_API_PRIVATE +#endif + +#include "tools_api/ittnotify.h" +#include "tools_api/legacy/ittnotify.h" + +#if _WIN32||_WIN64 + #undef _T + #undef __itt_event_create + #define __itt_event_create __itt_event_createA +#endif /* WIN */ + + +#endif /* DO_ITT_NOTIFY */ + +#if !ITT_CALLER_NULL +#define ITT_CALLER_NULL ((__itt_caller)0) +#endif + +namespace tbb { +//! Unicode support +#if (_WIN32||_WIN64) && !__MINGW32__ + //! Unicode character type. Always wchar_t on Windows. + /** We do not use typedefs from Windows TCHAR family to keep consistence of TBB coding style. **/ + typedef wchar_t tchar; + //! Standard Windows macro to markup the string literals. + #define _T(string_literal) L ## string_literal +#else /* !WIN */ + typedef char tchar; + //! Standard Windows style macro to markup the string literals. + #define _T(string_literal) string_literal +#endif /* !WIN */ +} // namespace tbb + +#if DO_ITT_NOTIFY +namespace tbb { + //! Display names of internal synchronization types + extern const tchar + *SyncType_GlobalLock, + *SyncType_Scheduler; + //! Display names of internal synchronization components/scenarios + extern const tchar + *SyncObj_SchedulerInitialization, + *SyncObj_SchedulersList, + *SyncObj_WorkerLifeCycleMgmt, + *SyncObj_TaskStealingLoop, + *SyncObj_WorkerTaskPool, + *SyncObj_MasterTaskPool, + *SyncObj_TaskPoolSpinning, + *SyncObj_Mailbox, + *SyncObj_TaskReturnList, + *SyncObj_TaskStream, + *SyncObj_ContextsList + ; + + namespace internal { + void __TBB_EXPORTED_FUNC itt_set_sync_name_v3( void* obj, const tchar* name); + + } // namespace internal + +} // namespace tbb + +// const_cast<void*>() is necessary to cast off volatility +#define ITT_NOTIFY(name,obj) __itt_notify_##name(const_cast<void*>(static_cast<volatile void*>(obj))) +#define ITT_THREAD_SET_NAME(name) __itt_thread_set_name(name) +#define ITT_SYNC_CREATE(obj, type, name) __itt_sync_create((void*)(obj), type, name, 2) +#define ITT_SYNC_RENAME(obj, name) __itt_sync_rename(obj, name) +#define ITT_STACK_CREATE(obj) obj = __itt_stack_caller_create() +#if __TBB_TASK_GROUP_CONTEXT +#define ITT_STACK(precond, name, obj) (precond) ? __itt_stack_##name(obj) : ((void)0); +#else +#define ITT_STACK(precond, name, obj) ((void)0) +#endif /* !__TBB_TASK_GROUP_CONTEXT */ + +#else /* !DO_ITT_NOTIFY */ + +#define ITT_NOTIFY(name,obj) ((void)0) +#define ITT_THREAD_SET_NAME(name) ((void)0) +#define ITT_SYNC_CREATE(obj, type, name) ((void)0) +#define ITT_SYNC_RENAME(obj, name) ((void)0) +#define ITT_STACK_CREATE(obj) ((void)0) +#define ITT_STACK(precond, name, obj) ((void)0) + +#endif /* !DO_ITT_NOTIFY */ + +namespace tbb { +namespace internal { +int __TBB_load_ittnotify(); +}} + +#endif /* _TBB_ITT_NOTIFY */ diff --git a/src/tbb/src/tbb/lin32-tbb-export.def b/src/tbb/src/tbb/lin32-tbb-export.def new file mode 100644 index 0000000..6440ddc --- /dev/null +++ b/src/tbb/src/tbb/lin32-tbb-export.def @@ -0,0 +1,57 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +{ +global: + +#define __TBB_SYMBOL( sym ) sym; +#include "lin32-tbb-export.lst" + +local: + +/* TBB symbols */ +*3tbb*; +*__TBB*; + +/* ITT symbols */ +__itt_*; + +/* Intel Compiler (libirc) symbols */ +__intel_*; +_intel_*; +get_memcpy_largest_cachelinesize; +get_memcpy_largest_cache_size; +get_mem_ops_method; +init_mem_ops_method; +irc__get_msg; +irc__print; +override_mem_ops_method; +set_memcpy_largest_cachelinesize; +set_memcpy_largest_cache_size; + +}; diff --git a/src/tbb/src/tbb/lin32-tbb-export.lst b/src/tbb/src/tbb/lin32-tbb-export.lst new file mode 100644 index 0000000..15a5ff1 --- /dev/null +++ b/src/tbb/src/tbb/lin32-tbb-export.lst @@ -0,0 +1,365 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/tbb_config.h" + +/* cache_aligned_allocator.cpp */ +__TBB_SYMBOL( _ZN3tbb8internal12NFS_AllocateEjjPv ) +__TBB_SYMBOL( _ZN3tbb8internal15NFS_GetLineSizeEv ) +__TBB_SYMBOL( _ZN3tbb8internal8NFS_FreeEPv ) +__TBB_SYMBOL( _ZN3tbb8internal23allocate_via_handler_v3Ej ) +__TBB_SYMBOL( _ZN3tbb8internal25deallocate_via_handler_v3EPv ) +__TBB_SYMBOL( _ZN3tbb8internal17is_malloc_used_v3Ev ) + +/* task.cpp v3 */ +__TBB_SYMBOL( _ZN3tbb4task13note_affinityEt ) +__TBB_SYMBOL( _ZN3tbb4task22internal_set_ref_countEi ) +__TBB_SYMBOL( _ZN3tbb4task28internal_decrement_ref_countEv ) +__TBB_SYMBOL( _ZN3tbb4task22spawn_and_wait_for_allERNS_9task_listE ) +__TBB_SYMBOL( _ZN3tbb4task4selfEv ) +__TBB_SYMBOL( _ZN3tbb10interface58internal9task_base7destroyERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb4task26is_owned_by_current_threadEv ) +__TBB_SYMBOL( _ZN3tbb8internal19allocate_root_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZN3tbb8internal19allocate_root_proxy8allocateEj ) +__TBB_SYMBOL( _ZN3tbb8internal28affinity_partitioner_base_v36resizeEj ) +__TBB_SYMBOL( _ZNK3tbb8internal20allocate_child_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb8internal20allocate_child_proxy8allocateEj ) +__TBB_SYMBOL( _ZNK3tbb8internal27allocate_continuation_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb8internal27allocate_continuation_proxy8allocateEj ) +__TBB_SYMBOL( _ZNK3tbb8internal34allocate_additional_child_of_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb8internal34allocate_additional_child_of_proxy8allocateEj ) +__TBB_SYMBOL( _ZTIN3tbb4taskE ) +__TBB_SYMBOL( _ZTSN3tbb4taskE ) +__TBB_SYMBOL( _ZTVN3tbb4taskE ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init19default_num_threadsEv ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init10initializeEij ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init10initializeEi ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init9terminateEv ) +__TBB_SYMBOL( _ZN3tbb8internal26task_scheduler_observer_v37observeEb ) +__TBB_SYMBOL( _ZN3tbb10empty_task7executeEv ) +__TBB_SYMBOL( _ZN3tbb10empty_taskD0Ev ) +__TBB_SYMBOL( _ZN3tbb10empty_taskD1Ev ) +__TBB_SYMBOL( _ZTIN3tbb10empty_taskE ) +__TBB_SYMBOL( _ZTSN3tbb10empty_taskE ) +__TBB_SYMBOL( _ZTVN3tbb10empty_taskE ) + +#if !TBB_NO_LEGACY +/* task_v2.cpp */ +__TBB_SYMBOL( _ZN3tbb4task7destroyERS0_ ) +#endif /* !TBB_NO_LEGACY */ + +/* Exception handling in task scheduler */ +#if __TBB_TASK_GROUP_CONTEXT +__TBB_SYMBOL( _ZNK3tbb8internal32allocate_root_with_context_proxy8allocateEj ) +__TBB_SYMBOL( _ZNK3tbb8internal32allocate_root_with_context_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZN3tbb4task12change_groupERNS_18task_group_contextE ) +__TBB_SYMBOL( _ZNK3tbb18task_group_context28is_group_execution_cancelledEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context22cancel_group_executionEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context26register_pending_exceptionEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context5resetEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context4initEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_contextD1Ev ) +__TBB_SYMBOL( _ZN3tbb18task_group_contextD2Ev ) +#if __TBB_TASK_PRIORITY +__TBB_SYMBOL( _ZN3tbb18task_group_context12set_priorityENS_10priority_tE ) +__TBB_SYMBOL( _ZNK3tbb18task_group_context8priorityEv ) +#endif /* __TBB_TASK_PRIORITY */ +__TBB_SYMBOL( _ZNK3tbb18captured_exception4nameEv ) +__TBB_SYMBOL( _ZNK3tbb18captured_exception4whatEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception10throw_selfEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception3setEPKcS2_ ) +__TBB_SYMBOL( _ZN3tbb18captured_exception4moveEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception5clearEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception7destroyEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception8allocateEPKcS2_ ) +__TBB_SYMBOL( _ZN3tbb18captured_exceptionD0Ev ) +__TBB_SYMBOL( _ZN3tbb18captured_exceptionD1Ev ) +__TBB_SYMBOL( _ZN3tbb18captured_exceptionD2Ev ) +__TBB_SYMBOL( _ZTIN3tbb18captured_exceptionE ) +__TBB_SYMBOL( _ZTSN3tbb18captured_exceptionE ) +__TBB_SYMBOL( _ZTVN3tbb18captured_exceptionE ) +__TBB_SYMBOL( _ZN3tbb13tbb_exceptionD2Ev ) +__TBB_SYMBOL( _ZTIN3tbb13tbb_exceptionE ) +__TBB_SYMBOL( _ZTSN3tbb13tbb_exceptionE ) +__TBB_SYMBOL( _ZTVN3tbb13tbb_exceptionE ) +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +/* Symbols for exceptions thrown from TBB */ +__TBB_SYMBOL( _ZN3tbb8internal33throw_bad_last_alloc_exception_v4Ev ) +__TBB_SYMBOL( _ZN3tbb8internal18throw_exception_v4ENS0_12exception_idE ) +__TBB_SYMBOL( _ZN3tbb14bad_last_allocD0Ev ) +__TBB_SYMBOL( _ZN3tbb14bad_last_allocD1Ev ) +__TBB_SYMBOL( _ZNK3tbb14bad_last_alloc4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb14bad_last_allocE ) +__TBB_SYMBOL( _ZTSN3tbb14bad_last_allocE ) +__TBB_SYMBOL( _ZTVN3tbb14bad_last_allocE ) +__TBB_SYMBOL( _ZN3tbb12missing_waitD0Ev ) +__TBB_SYMBOL( _ZN3tbb12missing_waitD1Ev ) +__TBB_SYMBOL( _ZNK3tbb12missing_wait4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb12missing_waitE ) +__TBB_SYMBOL( _ZTSN3tbb12missing_waitE ) +__TBB_SYMBOL( _ZTVN3tbb12missing_waitE ) +__TBB_SYMBOL( _ZN3tbb27invalid_multiple_schedulingD0Ev ) +__TBB_SYMBOL( _ZN3tbb27invalid_multiple_schedulingD1Ev ) +__TBB_SYMBOL( _ZNK3tbb27invalid_multiple_scheduling4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb27invalid_multiple_schedulingE ) +__TBB_SYMBOL( _ZTSN3tbb27invalid_multiple_schedulingE ) +__TBB_SYMBOL( _ZTVN3tbb27invalid_multiple_schedulingE ) +__TBB_SYMBOL( _ZN3tbb13improper_lockD0Ev ) +__TBB_SYMBOL( _ZN3tbb13improper_lockD1Ev ) +__TBB_SYMBOL( _ZNK3tbb13improper_lock4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb13improper_lockE ) +__TBB_SYMBOL( _ZTSN3tbb13improper_lockE ) +__TBB_SYMBOL( _ZTVN3tbb13improper_lockE ) +__TBB_SYMBOL( _ZN3tbb10user_abortD0Ev ) +__TBB_SYMBOL( _ZN3tbb10user_abortD1Ev ) +__TBB_SYMBOL( _ZNK3tbb10user_abort4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb10user_abortE ) +__TBB_SYMBOL( _ZTSN3tbb10user_abortE ) +__TBB_SYMBOL( _ZTVN3tbb10user_abortE ) + +/* tbb_misc.cpp */ +__TBB_SYMBOL( _ZN3tbb17assertion_failureEPKciS1_S1_ ) +__TBB_SYMBOL( _ZN3tbb21set_assertion_handlerEPFvPKciS1_S1_E ) +__TBB_SYMBOL( _ZN3tbb8internal36get_initial_auto_partitioner_divisorEv ) +__TBB_SYMBOL( _ZN3tbb8internal13handle_perrorEiPKc ) +__TBB_SYMBOL( _ZN3tbb8internal15runtime_warningEPKcz ) +__TBB_SYMBOL( __TBB_machine_store8_slow_perf_warning ) +__TBB_SYMBOL( __TBB_machine_store8_slow ) +__TBB_SYMBOL( TBB_runtime_interface_version ) + +/* tbb_main.cpp */ +__TBB_SYMBOL( _ZN3tbb8internal32itt_load_pointer_with_acquire_v3EPKv ) +__TBB_SYMBOL( _ZN3tbb8internal33itt_store_pointer_with_release_v3EPvS1_ ) +__TBB_SYMBOL( _ZN3tbb8internal18call_itt_notify_v5EiPv ) +__TBB_SYMBOL( _ZN3tbb8internal20itt_set_sync_name_v3EPvPKc ) +__TBB_SYMBOL( _ZN3tbb8internal19itt_load_pointer_v3EPKv ) + +/* pipeline.cpp */ +__TBB_SYMBOL( _ZTIN3tbb6filterE ) +__TBB_SYMBOL( _ZTSN3tbb6filterE ) +__TBB_SYMBOL( _ZTVN3tbb6filterE ) +__TBB_SYMBOL( _ZN3tbb6filterD2Ev ) +__TBB_SYMBOL( _ZN3tbb8pipeline10add_filterERNS_6filterE ) +__TBB_SYMBOL( _ZN3tbb8pipeline12inject_tokenERNS_4taskE ) +__TBB_SYMBOL( _ZN3tbb8pipeline13remove_filterERNS_6filterE ) +__TBB_SYMBOL( _ZN3tbb8pipeline3runEj ) +#if __TBB_TASK_GROUP_CONTEXT +__TBB_SYMBOL( _ZN3tbb8pipeline3runEjRNS_18task_group_contextE ) +#endif +__TBB_SYMBOL( _ZN3tbb8pipeline5clearEv ) +__TBB_SYMBOL( _ZN3tbb19thread_bound_filter12process_itemEv ) +__TBB_SYMBOL( _ZN3tbb19thread_bound_filter16try_process_itemEv ) +__TBB_SYMBOL( _ZTIN3tbb8pipelineE ) +__TBB_SYMBOL( _ZTSN3tbb8pipelineE ) +__TBB_SYMBOL( _ZTVN3tbb8pipelineE ) +__TBB_SYMBOL( _ZN3tbb8pipelineC1Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineC2Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineD0Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineD1Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineD2Ev ) +__TBB_SYMBOL( _ZN3tbb6filter16set_end_of_inputEv ) + +/* queuing_rw_mutex.cpp */ +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex18internal_constructEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock17upgrade_to_writerEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock19downgrade_to_readerEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock7acquireERS0_b ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock7releaseEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock11try_acquireERS0_b ) + +/* reader_writer_lock.cpp */ +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock11scoped_lock16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock11scoped_lock18internal_constructERS1_ ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock13try_lock_readEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock16scoped_lock_read16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock16scoped_lock_read18internal_constructERS1_ ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock18internal_constructEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock4lockEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock6unlockEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock8try_lockEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock9lock_readEv ) + +#if !TBB_NO_LEGACY +/* spin_rw_mutex.cpp v2 */ +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex16internal_upgradeEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex22internal_itt_releasingEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_acquire_readerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_acquire_writerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex18internal_downgradeEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_release_readerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_release_writerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex27internal_try_acquire_readerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex27internal_try_acquire_writerEPS0_ ) +#endif + +/* spin_rw_mutex v3 */ +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v318internal_constructEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v316internal_upgradeEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v318internal_downgradeEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_acquire_readerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_acquire_writerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_release_readerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_release_writerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v327internal_try_acquire_readerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v327internal_try_acquire_writerEv ) + +/* spin_mutex.cpp */ +__TBB_SYMBOL( _ZN3tbb10spin_mutex18internal_constructEv ) +__TBB_SYMBOL( _ZN3tbb10spin_mutex11scoped_lock16internal_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb10spin_mutex11scoped_lock16internal_releaseEv ) +__TBB_SYMBOL( _ZN3tbb10spin_mutex11scoped_lock20internal_try_acquireERS0_ ) + +/* mutex.cpp */ +__TBB_SYMBOL( _ZN3tbb5mutex11scoped_lock16internal_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb5mutex11scoped_lock16internal_releaseEv ) +__TBB_SYMBOL( _ZN3tbb5mutex11scoped_lock20internal_try_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb5mutex16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb5mutex18internal_constructEv ) + +/* recursive_mutex.cpp */ +__TBB_SYMBOL( _ZN3tbb15recursive_mutex11scoped_lock16internal_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex11scoped_lock16internal_releaseEv ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex11scoped_lock20internal_try_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex18internal_constructEv ) + +/* QueuingMutex.cpp */ +__TBB_SYMBOL( _ZN3tbb13queuing_mutex18internal_constructEv ) +__TBB_SYMBOL( _ZN3tbb13queuing_mutex11scoped_lock7acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb13queuing_mutex11scoped_lock7releaseEv ) +__TBB_SYMBOL( _ZN3tbb13queuing_mutex11scoped_lock11try_acquireERS0_ ) + +/* critical_section.cpp */ +__TBB_SYMBOL( _ZN3tbb8internal19critical_section_v418internal_constructEv ) + +#if !TBB_NO_LEGACY +/* concurrent_hash_map */ +__TBB_SYMBOL( _ZNK3tbb8internal21hash_map_segment_base23internal_grow_predicateEv ) + +/* concurrent_queue.cpp v2 */ +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base12internal_popEPv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base13internal_pushEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base21internal_set_capacityEij ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base23internal_pop_if_presentEPv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base25internal_push_if_not_fullEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_baseC2Ej ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_baseD2Ev ) +__TBB_SYMBOL( _ZTIN3tbb8internal21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZTSN3tbb8internal21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZTVN3tbb8internal21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_base6assignERKS1_ ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_base7advanceEv ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_baseC2ERKNS0_21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_baseD2Ev ) +__TBB_SYMBOL( _ZNK3tbb8internal21concurrent_queue_base13internal_sizeEv ) +#endif + +/* concurrent_queue v3 */ +/* constructors */ +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v3C2Ej ) +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v3C2ERKNS0_24concurrent_queue_base_v3E ) +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v3C2ERKNS0_24concurrent_queue_base_v3Ej ) +/* destructors */ +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v3D2Ev ) +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v3D2Ev ) +/* typeinfo */ +__TBB_SYMBOL( _ZTIN3tbb8internal24concurrent_queue_base_v3E ) +__TBB_SYMBOL( _ZTSN3tbb8internal24concurrent_queue_base_v3E ) +/* vtable */ +__TBB_SYMBOL( _ZTVN3tbb8internal24concurrent_queue_base_v3E ) +/* methods */ +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v37advanceEv ) +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v36assignERKS1_ ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v313internal_pushEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v325internal_push_if_not_fullEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v312internal_popEPv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v323internal_pop_if_presentEPv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v314internal_abortEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v321internal_set_capacityEij ) +__TBB_SYMBOL( _ZNK3tbb8internal24concurrent_queue_base_v313internal_sizeEv ) +__TBB_SYMBOL( _ZNK3tbb8internal24concurrent_queue_base_v314internal_emptyEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v321internal_finish_clearEv ) +__TBB_SYMBOL( _ZNK3tbb8internal24concurrent_queue_base_v324internal_throw_exceptionEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v36assignERKS1_ ) + +#if !TBB_NO_LEGACY +/* concurrent_vector.cpp v2 */ +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base13internal_copyERKS1_jPFvPvPKvjE ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base14internal_clearEPFvPvjEb ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base15internal_assignERKS1_jPFvPvjEPFvS4_PKvjESA_ ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base16internal_grow_byEjjPFvPvjE ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base16internal_reserveEjjj ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base18internal_push_backEjRj ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base25internal_grow_to_at_leastEjjPFvPvjE ) +__TBB_SYMBOL( _ZNK3tbb8internal22concurrent_vector_base17internal_capacityEv ) +#endif + +/* concurrent_vector v3 */ +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v313internal_copyERKS1_jPFvPvPKvjE ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v314internal_clearEPFvPvjE ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v315internal_assignERKS1_jPFvPvjEPFvS4_PKvjESA_ ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v316internal_grow_byEjjPFvPvPKvjES4_ ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v316internal_reserveEjjj ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v318internal_push_backEjRj ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v325internal_grow_to_at_leastEjjPFvPvPKvjES4_ ) +__TBB_SYMBOL( _ZNK3tbb8internal25concurrent_vector_base_v317internal_capacityEv ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v316internal_compactEjPvPFvS2_jEPFvS2_PKvjE ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v313internal_swapERS1_ ) +__TBB_SYMBOL( _ZNK3tbb8internal25concurrent_vector_base_v324internal_throw_exceptionEj ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v3D2Ev ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v315internal_resizeEjjjPKvPFvPvjEPFvS4_S3_jE ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v337internal_grow_to_at_least_with_resultEjjPFvPvPKvjES4_ ) + +/* tbb_thread */ +#if __MINGW32__ +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v314internal_startEPFjPvES2_ ) +#else +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v314internal_startEPFPvS2_ES2_ ) +#endif +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v320hardware_concurrencyEv ) +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v34joinEv ) +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v36detachEv ) +__TBB_SYMBOL( _ZN3tbb8internal15free_closure_v3EPv ) +__TBB_SYMBOL( _ZN3tbb8internal15thread_sleep_v3ERKNS_10tick_count10interval_tE ) +__TBB_SYMBOL( _ZN3tbb8internal15thread_yield_v3Ev ) +__TBB_SYMBOL( _ZN3tbb8internal16thread_get_id_v3Ev ) +__TBB_SYMBOL( _ZN3tbb8internal19allocate_closure_v3Ej ) +__TBB_SYMBOL( _ZN3tbb8internal7move_v3ERNS0_13tbb_thread_v3ES2_ ) + +#if __MINGW32__ +/* condition_variable */ +__TBB_SYMBOL( _ZN3tbb10interface58internal32internal_condition_variable_waitERNS1_14condvar_impl_tEPNS_5mutexEPKNS_10tick_count10interval_tE ) +__TBB_SYMBOL( _ZN3tbb10interface58internal35internal_destroy_condition_variableERNS1_14condvar_impl_tE ) +__TBB_SYMBOL( _ZN3tbb10interface58internal38internal_condition_variable_notify_allERNS1_14condvar_impl_tE ) +__TBB_SYMBOL( _ZN3tbb10interface58internal38internal_condition_variable_notify_oneERNS1_14condvar_impl_tE ) +__TBB_SYMBOL( _ZN3tbb10interface58internal38internal_initialize_condition_variableERNS1_14condvar_impl_tE ) +#endif + +#undef __TBB_SYMBOL diff --git a/src/tbb/src/tbb/lin64-tbb-export.def b/src/tbb/src/tbb/lin64-tbb-export.def new file mode 100644 index 0000000..0c6e09a --- /dev/null +++ b/src/tbb/src/tbb/lin64-tbb-export.def @@ -0,0 +1,54 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +{ +global: + +#define __TBB_SYMBOL( sym ) sym; +#include "lin64-tbb-export.lst" + +local: + +/* TBB symbols */ +*3tbb*; +*__TBB*; + +/* ITT symbols */ +__itt_*; + +/* Intel Compiler (libirc) symbols */ +__intel_*; +_intel_*; +get_msg_buf; +get_text_buf; +message_catalog; +print_buf; +irc__get_msg; +irc__print; + +}; diff --git a/src/tbb/src/tbb/lin64-tbb-export.lst b/src/tbb/src/tbb/lin64-tbb-export.lst new file mode 100644 index 0000000..e35a655 --- /dev/null +++ b/src/tbb/src/tbb/lin64-tbb-export.lst @@ -0,0 +1,349 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/tbb_config.h" + +/* cache_aligned_allocator.cpp */ +__TBB_SYMBOL( _ZN3tbb8internal12NFS_AllocateEmmPv ) +__TBB_SYMBOL( _ZN3tbb8internal15NFS_GetLineSizeEv ) +__TBB_SYMBOL( _ZN3tbb8internal8NFS_FreeEPv ) +__TBB_SYMBOL( _ZN3tbb8internal23allocate_via_handler_v3Em ) +__TBB_SYMBOL( _ZN3tbb8internal25deallocate_via_handler_v3EPv ) +__TBB_SYMBOL( _ZN3tbb8internal17is_malloc_used_v3Ev ) + +/* task.cpp v3 */ +__TBB_SYMBOL( _ZN3tbb4task13note_affinityEt ) +__TBB_SYMBOL( _ZN3tbb4task22internal_set_ref_countEi ) +__TBB_SYMBOL( _ZN3tbb4task28internal_decrement_ref_countEv ) +__TBB_SYMBOL( _ZN3tbb4task22spawn_and_wait_for_allERNS_9task_listE ) +__TBB_SYMBOL( _ZN3tbb4task4selfEv ) +__TBB_SYMBOL( _ZN3tbb10interface58internal9task_base7destroyERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb4task26is_owned_by_current_threadEv ) +__TBB_SYMBOL( _ZN3tbb8internal19allocate_root_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZN3tbb8internal19allocate_root_proxy8allocateEm ) +__TBB_SYMBOL( _ZN3tbb8internal28affinity_partitioner_base_v36resizeEj ) +__TBB_SYMBOL( _ZNK3tbb8internal20allocate_child_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb8internal20allocate_child_proxy8allocateEm ) +__TBB_SYMBOL( _ZNK3tbb8internal27allocate_continuation_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb8internal27allocate_continuation_proxy8allocateEm ) +__TBB_SYMBOL( _ZNK3tbb8internal34allocate_additional_child_of_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb8internal34allocate_additional_child_of_proxy8allocateEm ) +__TBB_SYMBOL( _ZTIN3tbb4taskE ) +__TBB_SYMBOL( _ZTSN3tbb4taskE ) +__TBB_SYMBOL( _ZTVN3tbb4taskE ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init19default_num_threadsEv ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init10initializeEim ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init10initializeEi ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init9terminateEv ) +__TBB_SYMBOL( _ZN3tbb8internal26task_scheduler_observer_v37observeEb ) +__TBB_SYMBOL( _ZN3tbb10empty_task7executeEv ) +__TBB_SYMBOL( _ZN3tbb10empty_taskD0Ev ) +__TBB_SYMBOL( _ZN3tbb10empty_taskD1Ev ) +__TBB_SYMBOL( _ZTIN3tbb10empty_taskE ) +__TBB_SYMBOL( _ZTSN3tbb10empty_taskE ) +__TBB_SYMBOL( _ZTVN3tbb10empty_taskE ) + +#if !TBB_NO_LEGACY +/* task_v2.cpp */ +__TBB_SYMBOL( _ZN3tbb4task7destroyERS0_ ) +#endif /* !TBB_NO_LEGACY */ + +/* Exception handling in task scheduler */ +#if __TBB_TASK_GROUP_CONTEXT +__TBB_SYMBOL( _ZNK3tbb8internal32allocate_root_with_context_proxy8allocateEm ) +__TBB_SYMBOL( _ZNK3tbb8internal32allocate_root_with_context_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZN3tbb4task12change_groupERNS_18task_group_contextE ) +__TBB_SYMBOL( _ZNK3tbb18task_group_context28is_group_execution_cancelledEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context22cancel_group_executionEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context26register_pending_exceptionEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context5resetEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context4initEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_contextD1Ev ) +__TBB_SYMBOL( _ZN3tbb18task_group_contextD2Ev ) +#if __TBB_TASK_PRIORITY +__TBB_SYMBOL( _ZN3tbb18task_group_context12set_priorityENS_10priority_tE ) +__TBB_SYMBOL( _ZNK3tbb18task_group_context8priorityEv ) +#endif /* __TBB_TASK_PRIORITY */ +__TBB_SYMBOL( _ZNK3tbb18captured_exception4nameEv ) +__TBB_SYMBOL( _ZNK3tbb18captured_exception4whatEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception10throw_selfEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception3setEPKcS2_ ) +__TBB_SYMBOL( _ZN3tbb18captured_exception4moveEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception5clearEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception7destroyEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception8allocateEPKcS2_ ) +__TBB_SYMBOL( _ZN3tbb18captured_exceptionD0Ev ) +__TBB_SYMBOL( _ZN3tbb18captured_exceptionD1Ev ) +__TBB_SYMBOL( _ZN3tbb18captured_exceptionD2Ev ) +__TBB_SYMBOL( _ZTIN3tbb18captured_exceptionE ) +__TBB_SYMBOL( _ZTSN3tbb18captured_exceptionE ) +__TBB_SYMBOL( _ZTVN3tbb18captured_exceptionE ) +__TBB_SYMBOL( _ZN3tbb13tbb_exceptionD2Ev ) +__TBB_SYMBOL( _ZTIN3tbb13tbb_exceptionE ) +__TBB_SYMBOL( _ZTSN3tbb13tbb_exceptionE ) +__TBB_SYMBOL( _ZTVN3tbb13tbb_exceptionE ) +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +/* Symbols for exceptions thrown from TBB */ +__TBB_SYMBOL( _ZN3tbb8internal33throw_bad_last_alloc_exception_v4Ev ) +__TBB_SYMBOL( _ZN3tbb8internal18throw_exception_v4ENS0_12exception_idE ) +__TBB_SYMBOL( _ZN3tbb14bad_last_allocD0Ev ) +__TBB_SYMBOL( _ZN3tbb14bad_last_allocD1Ev ) +__TBB_SYMBOL( _ZNK3tbb14bad_last_alloc4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb14bad_last_allocE ) +__TBB_SYMBOL( _ZTSN3tbb14bad_last_allocE ) +__TBB_SYMBOL( _ZTVN3tbb14bad_last_allocE ) +__TBB_SYMBOL( _ZN3tbb12missing_waitD0Ev ) +__TBB_SYMBOL( _ZN3tbb12missing_waitD1Ev ) +__TBB_SYMBOL( _ZNK3tbb12missing_wait4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb12missing_waitE ) +__TBB_SYMBOL( _ZTSN3tbb12missing_waitE ) +__TBB_SYMBOL( _ZTVN3tbb12missing_waitE ) +__TBB_SYMBOL( _ZN3tbb27invalid_multiple_schedulingD0Ev ) +__TBB_SYMBOL( _ZN3tbb27invalid_multiple_schedulingD1Ev ) +__TBB_SYMBOL( _ZNK3tbb27invalid_multiple_scheduling4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb27invalid_multiple_schedulingE ) +__TBB_SYMBOL( _ZTSN3tbb27invalid_multiple_schedulingE ) +__TBB_SYMBOL( _ZTVN3tbb27invalid_multiple_schedulingE ) +__TBB_SYMBOL( _ZN3tbb13improper_lockD0Ev ) +__TBB_SYMBOL( _ZN3tbb13improper_lockD1Ev ) +__TBB_SYMBOL( _ZNK3tbb13improper_lock4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb13improper_lockE ) +__TBB_SYMBOL( _ZTSN3tbb13improper_lockE ) +__TBB_SYMBOL( _ZTVN3tbb13improper_lockE ) +__TBB_SYMBOL( _ZN3tbb10user_abortD0Ev ) +__TBB_SYMBOL( _ZN3tbb10user_abortD1Ev ) +__TBB_SYMBOL( _ZNK3tbb10user_abort4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb10user_abortE ) +__TBB_SYMBOL( _ZTSN3tbb10user_abortE ) +__TBB_SYMBOL( _ZTVN3tbb10user_abortE ) +/* tbb_misc.cpp */ +__TBB_SYMBOL( _ZN3tbb17assertion_failureEPKciS1_S1_ ) +__TBB_SYMBOL( _ZN3tbb21set_assertion_handlerEPFvPKciS1_S1_E ) +__TBB_SYMBOL( _ZN3tbb8internal36get_initial_auto_partitioner_divisorEv ) +__TBB_SYMBOL( _ZN3tbb8internal13handle_perrorEiPKc ) +__TBB_SYMBOL( _ZN3tbb8internal15runtime_warningEPKcz ) +__TBB_SYMBOL( TBB_runtime_interface_version ) + +/* tbb_main.cpp */ +__TBB_SYMBOL( _ZN3tbb8internal32itt_load_pointer_with_acquire_v3EPKv ) +__TBB_SYMBOL( _ZN3tbb8internal33itt_store_pointer_with_release_v3EPvS1_ ) +__TBB_SYMBOL( _ZN3tbb8internal18call_itt_notify_v5EiPv ) +__TBB_SYMBOL( _ZN3tbb8internal20itt_set_sync_name_v3EPvPKc ) +__TBB_SYMBOL( _ZN3tbb8internal19itt_load_pointer_v3EPKv ) + +/* pipeline.cpp */ +__TBB_SYMBOL( _ZTIN3tbb6filterE ) +__TBB_SYMBOL( _ZTSN3tbb6filterE ) +__TBB_SYMBOL( _ZTVN3tbb6filterE ) +__TBB_SYMBOL( _ZN3tbb6filterD2Ev ) +__TBB_SYMBOL( _ZN3tbb8pipeline10add_filterERNS_6filterE ) +__TBB_SYMBOL( _ZN3tbb8pipeline12inject_tokenERNS_4taskE ) +__TBB_SYMBOL( _ZN3tbb8pipeline13remove_filterERNS_6filterE ) +__TBB_SYMBOL( _ZN3tbb8pipeline3runEm ) +#if __TBB_TASK_GROUP_CONTEXT +__TBB_SYMBOL( _ZN3tbb8pipeline3runEmRNS_18task_group_contextE ) +#endif +__TBB_SYMBOL( _ZN3tbb8pipeline5clearEv ) +__TBB_SYMBOL( _ZN3tbb19thread_bound_filter12process_itemEv ) +__TBB_SYMBOL( _ZN3tbb19thread_bound_filter16try_process_itemEv ) +__TBB_SYMBOL( _ZTIN3tbb8pipelineE ) +__TBB_SYMBOL( _ZTSN3tbb8pipelineE ) +__TBB_SYMBOL( _ZTVN3tbb8pipelineE ) +__TBB_SYMBOL( _ZN3tbb8pipelineC1Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineC2Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineD0Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineD1Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineD2Ev ) +__TBB_SYMBOL( _ZN3tbb6filter16set_end_of_inputEv ) + +/* queuing_rw_mutex.cpp */ +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex18internal_constructEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock17upgrade_to_writerEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock19downgrade_to_readerEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock7acquireERS0_b ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock7releaseEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock11try_acquireERS0_b ) + +/* reader_writer_lock.cpp */ +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock11scoped_lock16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock11scoped_lock18internal_constructERS1_ ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock13try_lock_readEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock16scoped_lock_read16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock16scoped_lock_read18internal_constructERS1_ ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock18internal_constructEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock4lockEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock6unlockEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock8try_lockEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock9lock_readEv ) + +#if !TBB_NO_LEGACY +/* spin_rw_mutex.cpp v2 */ +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex16internal_upgradeEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex22internal_itt_releasingEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_acquire_readerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_acquire_writerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex18internal_downgradeEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_release_readerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_release_writerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex27internal_try_acquire_readerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex27internal_try_acquire_writerEPS0_ ) +#endif + +/* spin_rw_mutex v3 */ +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v318internal_constructEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v316internal_upgradeEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v318internal_downgradeEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_acquire_readerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_acquire_writerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_release_readerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_release_writerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v327internal_try_acquire_readerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v327internal_try_acquire_writerEv ) + +/* spin_mutex.cpp */ +__TBB_SYMBOL( _ZN3tbb10spin_mutex11scoped_lock16internal_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb10spin_mutex11scoped_lock16internal_releaseEv ) +__TBB_SYMBOL( _ZN3tbb10spin_mutex11scoped_lock20internal_try_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb10spin_mutex18internal_constructEv ) + +/* mutex.cpp */ +__TBB_SYMBOL( _ZN3tbb5mutex11scoped_lock16internal_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb5mutex11scoped_lock16internal_releaseEv ) +__TBB_SYMBOL( _ZN3tbb5mutex11scoped_lock20internal_try_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb5mutex16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb5mutex18internal_constructEv ) + +/* recursive_mutex.cpp */ +__TBB_SYMBOL( _ZN3tbb15recursive_mutex11scoped_lock16internal_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex11scoped_lock16internal_releaseEv ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex11scoped_lock20internal_try_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex18internal_constructEv ) + +/* QueuingMutex.cpp */ +__TBB_SYMBOL( _ZN3tbb13queuing_mutex18internal_constructEv ) +__TBB_SYMBOL( _ZN3tbb13queuing_mutex11scoped_lock7acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb13queuing_mutex11scoped_lock7releaseEv ) +__TBB_SYMBOL( _ZN3tbb13queuing_mutex11scoped_lock11try_acquireERS0_ ) + +/* critical_section.cpp */ +__TBB_SYMBOL( _ZN3tbb8internal19critical_section_v418internal_constructEv ) + +#if !TBB_NO_LEGACY +/* concurrent_hash_map */ +__TBB_SYMBOL( _ZNK3tbb8internal21hash_map_segment_base23internal_grow_predicateEv ) + +/* concurrent_queue.cpp v2 */ +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base12internal_popEPv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base13internal_pushEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base21internal_set_capacityElm ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base23internal_pop_if_presentEPv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base25internal_push_if_not_fullEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_baseC2Em ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_baseD2Ev ) +__TBB_SYMBOL( _ZTIN3tbb8internal21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZTSN3tbb8internal21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZTVN3tbb8internal21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_base6assignERKS1_ ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_base7advanceEv ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_baseC2ERKNS0_21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_baseD2Ev ) +__TBB_SYMBOL( _ZNK3tbb8internal21concurrent_queue_base13internal_sizeEv ) +#endif + +/* concurrent_queue v3 */ +/* constructors */ +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v3C2Em ) +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v3C2ERKNS0_24concurrent_queue_base_v3E ) +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v3C2ERKNS0_24concurrent_queue_base_v3Em ) +/* destructors */ +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v3D2Ev ) +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v3D2Ev ) +/* typeinfo */ +__TBB_SYMBOL( _ZTIN3tbb8internal24concurrent_queue_base_v3E ) +__TBB_SYMBOL( _ZTSN3tbb8internal24concurrent_queue_base_v3E ) +/* vtable */ +__TBB_SYMBOL( _ZTVN3tbb8internal24concurrent_queue_base_v3E ) +/* methods */ +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v36assignERKS1_ ) +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v37advanceEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v313internal_pushEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v325internal_push_if_not_fullEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v312internal_popEPv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v323internal_pop_if_presentEPv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v314internal_abortEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v321internal_finish_clearEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v321internal_set_capacityElm ) +__TBB_SYMBOL( _ZNK3tbb8internal24concurrent_queue_base_v313internal_sizeEv ) +__TBB_SYMBOL( _ZNK3tbb8internal24concurrent_queue_base_v314internal_emptyEv ) +__TBB_SYMBOL( _ZNK3tbb8internal24concurrent_queue_base_v324internal_throw_exceptionEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v36assignERKS1_ ) + +#if !TBB_NO_LEGACY +/* concurrent_vector.cpp v2 */ +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base13internal_copyERKS1_mPFvPvPKvmE ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base14internal_clearEPFvPvmEb ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base15internal_assignERKS1_mPFvPvmEPFvS4_PKvmESA_ ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base16internal_grow_byEmmPFvPvmE ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base16internal_reserveEmmm ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base18internal_push_backEmRm ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base25internal_grow_to_at_leastEmmPFvPvmE ) +__TBB_SYMBOL( _ZNK3tbb8internal22concurrent_vector_base17internal_capacityEv ) +#endif + +/* concurrent_vector v3 */ +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v313internal_copyERKS1_mPFvPvPKvmE ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v314internal_clearEPFvPvmE ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v315internal_assignERKS1_mPFvPvmEPFvS4_PKvmESA_ ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v316internal_grow_byEmmPFvPvPKvmES4_ ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v316internal_reserveEmmm ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v318internal_push_backEmRm ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v325internal_grow_to_at_leastEmmPFvPvPKvmES4_ ) +__TBB_SYMBOL( _ZNK3tbb8internal25concurrent_vector_base_v317internal_capacityEv ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v316internal_compactEmPvPFvS2_mEPFvS2_PKvmE ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v313internal_swapERS1_ ) +__TBB_SYMBOL( _ZNK3tbb8internal25concurrent_vector_base_v324internal_throw_exceptionEm ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v3D2Ev ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v315internal_resizeEmmmPKvPFvPvmEPFvS4_S3_mE ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v337internal_grow_to_at_least_with_resultEmmPFvPvPKvmES4_ ) + +/* tbb_thread */ +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v320hardware_concurrencyEv ) +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v36detachEv ) +__TBB_SYMBOL( _ZN3tbb8internal16thread_get_id_v3Ev ) +__TBB_SYMBOL( _ZN3tbb8internal15free_closure_v3EPv ) +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v34joinEv ) +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v314internal_startEPFPvS2_ES2_ ) +__TBB_SYMBOL( _ZN3tbb8internal19allocate_closure_v3Em ) +__TBB_SYMBOL( _ZN3tbb8internal7move_v3ERNS0_13tbb_thread_v3ES2_ ) +__TBB_SYMBOL( _ZN3tbb8internal15thread_yield_v3Ev ) +__TBB_SYMBOL( _ZN3tbb8internal15thread_sleep_v3ERKNS_10tick_count10interval_tE ) + +#undef __TBB_SYMBOL diff --git a/src/tbb/src/tbb/lin64ipf-tbb-export.def b/src/tbb/src/tbb/lin64ipf-tbb-export.def new file mode 100644 index 0000000..7629551 --- /dev/null +++ b/src/tbb/src/tbb/lin64ipf-tbb-export.def @@ -0,0 +1,56 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +{ +global: + +#define __TBB_SYMBOL( sym ) sym; +#include "lin64ipf-tbb-export.lst" + +local: + +/* TBB symbols */ +*3tbb*; +*__TBB*; + +/* ITT symbols */ +__itt_*; + +/* Intel Compiler (libirc) symbols */ +__intel_*; +_intel_*; +?0_memcopyA; +?0_memcopyDu; +?0_memcpyD; +?1__memcpy; +?1__memmove; +?1__serial_memmove; +memcpy; +memset; + +}; diff --git a/src/tbb/src/tbb/lin64ipf-tbb-export.lst b/src/tbb/src/tbb/lin64ipf-tbb-export.lst new file mode 100644 index 0000000..694235b --- /dev/null +++ b/src/tbb/src/tbb/lin64ipf-tbb-export.lst @@ -0,0 +1,400 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/tbb_config.h" + +/* cache_aligned_allocator.cpp */ +__TBB_SYMBOL( _ZN3tbb8internal12NFS_AllocateEmmPv ) +__TBB_SYMBOL( _ZN3tbb8internal15NFS_GetLineSizeEv ) +__TBB_SYMBOL( _ZN3tbb8internal8NFS_FreeEPv ) +__TBB_SYMBOL( _ZN3tbb8internal23allocate_via_handler_v3Em ) +__TBB_SYMBOL( _ZN3tbb8internal25deallocate_via_handler_v3EPv ) +__TBB_SYMBOL( _ZN3tbb8internal17is_malloc_used_v3Ev ) + +/* task.cpp v3 */ +__TBB_SYMBOL( _ZN3tbb4task13note_affinityEt ) +__TBB_SYMBOL( _ZN3tbb4task22internal_set_ref_countEi ) +__TBB_SYMBOL( _ZN3tbb4task28internal_decrement_ref_countEv ) +__TBB_SYMBOL( _ZN3tbb4task22spawn_and_wait_for_allERNS_9task_listE ) +__TBB_SYMBOL( _ZN3tbb4task4selfEv ) +__TBB_SYMBOL( _ZN3tbb10interface58internal9task_base7destroyERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb4task26is_owned_by_current_threadEv ) +__TBB_SYMBOL( _ZN3tbb8internal19allocate_root_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZN3tbb8internal19allocate_root_proxy8allocateEm ) +__TBB_SYMBOL( _ZN3tbb8internal28affinity_partitioner_base_v36resizeEj ) +__TBB_SYMBOL( _ZNK3tbb8internal20allocate_child_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb8internal20allocate_child_proxy8allocateEm ) +__TBB_SYMBOL( _ZNK3tbb8internal27allocate_continuation_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb8internal27allocate_continuation_proxy8allocateEm ) +__TBB_SYMBOL( _ZNK3tbb8internal34allocate_additional_child_of_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb8internal34allocate_additional_child_of_proxy8allocateEm ) +__TBB_SYMBOL( _ZTIN3tbb4taskE ) +__TBB_SYMBOL( _ZTSN3tbb4taskE ) +__TBB_SYMBOL( _ZTVN3tbb4taskE ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init19default_num_threadsEv ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init10initializeEim ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init10initializeEi ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init9terminateEv ) +__TBB_SYMBOL( _ZN3tbb8internal26task_scheduler_observer_v37observeEb ) +__TBB_SYMBOL( _ZN3tbb10empty_task7executeEv ) +__TBB_SYMBOL( _ZN3tbb10empty_taskD0Ev ) +__TBB_SYMBOL( _ZN3tbb10empty_taskD1Ev ) +__TBB_SYMBOL( _ZTIN3tbb10empty_taskE ) +__TBB_SYMBOL( _ZTSN3tbb10empty_taskE ) +__TBB_SYMBOL( _ZTVN3tbb10empty_taskE ) + +#if !TBB_NO_LEGACY +/* task_v2.cpp */ +__TBB_SYMBOL( _ZN3tbb4task7destroyERS0_ ) +#endif /* !TBB_NO_LEGACY */ + +/* Exception handling in task scheduler */ +#if __TBB_TASK_GROUP_CONTEXT +__TBB_SYMBOL( _ZNK3tbb8internal32allocate_root_with_context_proxy8allocateEm ) +__TBB_SYMBOL( _ZNK3tbb8internal32allocate_root_with_context_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZN3tbb4task12change_groupERNS_18task_group_contextE ) +__TBB_SYMBOL( _ZNK3tbb18task_group_context28is_group_execution_cancelledEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context22cancel_group_executionEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context26register_pending_exceptionEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context5resetEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context4initEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_contextD1Ev ) +__TBB_SYMBOL( _ZN3tbb18task_group_contextD2Ev ) +#if __TBB_TASK_PRIORITY +__TBB_SYMBOL( _ZN3tbb18task_group_context12set_priorityENS_10priority_tE ) +__TBB_SYMBOL( _ZNK3tbb18task_group_context8priorityEv ) +#endif /* __TBB_TASK_PRIORITY */ +__TBB_SYMBOL( _ZNK3tbb18captured_exception4nameEv ) +__TBB_SYMBOL( _ZNK3tbb18captured_exception4whatEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception10throw_selfEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception3setEPKcS2_ ) +__TBB_SYMBOL( _ZN3tbb18captured_exception4moveEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception5clearEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception7destroyEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception8allocateEPKcS2_ ) +__TBB_SYMBOL( _ZN3tbb18captured_exceptionD0Ev ) +__TBB_SYMBOL( _ZN3tbb18captured_exceptionD1Ev ) +__TBB_SYMBOL( _ZN3tbb18captured_exceptionD2Ev ) +__TBB_SYMBOL( _ZTIN3tbb18captured_exceptionE ) +__TBB_SYMBOL( _ZTSN3tbb18captured_exceptionE ) +__TBB_SYMBOL( _ZTVN3tbb18captured_exceptionE ) +__TBB_SYMBOL( _ZN3tbb13tbb_exceptionD2Ev ) +__TBB_SYMBOL( _ZTIN3tbb13tbb_exceptionE ) +__TBB_SYMBOL( _ZTSN3tbb13tbb_exceptionE ) +__TBB_SYMBOL( _ZTVN3tbb13tbb_exceptionE ) +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +/* Symbols for exceptions thrown from TBB */ +__TBB_SYMBOL( _ZN3tbb8internal33throw_bad_last_alloc_exception_v4Ev ) +__TBB_SYMBOL( _ZN3tbb8internal18throw_exception_v4ENS0_12exception_idE ) +__TBB_SYMBOL( _ZN3tbb14bad_last_allocD0Ev ) +__TBB_SYMBOL( _ZN3tbb14bad_last_allocD1Ev ) +__TBB_SYMBOL( _ZNK3tbb14bad_last_alloc4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb14bad_last_allocE ) +__TBB_SYMBOL( _ZTSN3tbb14bad_last_allocE ) +__TBB_SYMBOL( _ZTVN3tbb14bad_last_allocE ) +__TBB_SYMBOL( _ZN3tbb12missing_waitD0Ev ) +__TBB_SYMBOL( _ZN3tbb12missing_waitD1Ev ) +__TBB_SYMBOL( _ZNK3tbb12missing_wait4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb12missing_waitE ) +__TBB_SYMBOL( _ZTSN3tbb12missing_waitE ) +__TBB_SYMBOL( _ZTVN3tbb12missing_waitE ) +__TBB_SYMBOL( _ZN3tbb27invalid_multiple_schedulingD0Ev ) +__TBB_SYMBOL( _ZN3tbb27invalid_multiple_schedulingD1Ev ) +__TBB_SYMBOL( _ZNK3tbb27invalid_multiple_scheduling4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb27invalid_multiple_schedulingE ) +__TBB_SYMBOL( _ZTSN3tbb27invalid_multiple_schedulingE ) +__TBB_SYMBOL( _ZTVN3tbb27invalid_multiple_schedulingE ) +__TBB_SYMBOL( _ZN3tbb13improper_lockD0Ev ) +__TBB_SYMBOL( _ZN3tbb13improper_lockD1Ev ) +__TBB_SYMBOL( _ZNK3tbb13improper_lock4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb13improper_lockE ) +__TBB_SYMBOL( _ZTSN3tbb13improper_lockE ) +__TBB_SYMBOL( _ZTVN3tbb13improper_lockE ) +__TBB_SYMBOL( _ZN3tbb10user_abortD0Ev ) +__TBB_SYMBOL( _ZN3tbb10user_abortD1Ev ) +__TBB_SYMBOL( _ZNK3tbb10user_abort4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb10user_abortE ) +__TBB_SYMBOL( _ZTSN3tbb10user_abortE ) +__TBB_SYMBOL( _ZTVN3tbb10user_abortE ) + +/* tbb_misc.cpp */ +__TBB_SYMBOL( _ZN3tbb17assertion_failureEPKciS1_S1_ ) +__TBB_SYMBOL( _ZN3tbb21set_assertion_handlerEPFvPKciS1_S1_E ) +__TBB_SYMBOL( _ZN3tbb8internal36get_initial_auto_partitioner_divisorEv ) +__TBB_SYMBOL( _ZN3tbb8internal13handle_perrorEiPKc ) +__TBB_SYMBOL( _ZN3tbb8internal15runtime_warningEPKcz ) +__TBB_SYMBOL( TBB_runtime_interface_version ) + +/* tbb_main.cpp */ +__TBB_SYMBOL( _ZN3tbb8internal32itt_load_pointer_with_acquire_v3EPKv ) +__TBB_SYMBOL( _ZN3tbb8internal33itt_store_pointer_with_release_v3EPvS1_ ) +__TBB_SYMBOL( _ZN3tbb8internal18call_itt_notify_v5EiPv ) +__TBB_SYMBOL( _ZN3tbb8internal20itt_set_sync_name_v3EPvPKc ) +__TBB_SYMBOL( _ZN3tbb8internal19itt_load_pointer_v3EPKv ) + +/* pipeline.cpp */ +__TBB_SYMBOL( _ZTIN3tbb6filterE ) +__TBB_SYMBOL( _ZTSN3tbb6filterE ) +__TBB_SYMBOL( _ZTVN3tbb6filterE ) +__TBB_SYMBOL( _ZN3tbb6filterD2Ev ) +__TBB_SYMBOL( _ZN3tbb8pipeline10add_filterERNS_6filterE ) +__TBB_SYMBOL( _ZN3tbb8pipeline12inject_tokenERNS_4taskE ) +__TBB_SYMBOL( _ZN3tbb8pipeline13remove_filterERNS_6filterE ) +__TBB_SYMBOL( _ZN3tbb8pipeline3runEm ) +#if __TBB_TASK_GROUP_CONTEXT +__TBB_SYMBOL( _ZN3tbb8pipeline3runEmRNS_18task_group_contextE ) +#endif +__TBB_SYMBOL( _ZN3tbb8pipeline5clearEv ) +__TBB_SYMBOL( _ZN3tbb19thread_bound_filter12process_itemEv ) +__TBB_SYMBOL( _ZN3tbb19thread_bound_filter16try_process_itemEv ) +__TBB_SYMBOL( _ZTIN3tbb8pipelineE ) +__TBB_SYMBOL( _ZTSN3tbb8pipelineE ) +__TBB_SYMBOL( _ZTVN3tbb8pipelineE ) +__TBB_SYMBOL( _ZN3tbb8pipelineC1Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineC2Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineD0Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineD1Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineD2Ev ) +__TBB_SYMBOL( _ZN3tbb6filter16set_end_of_inputEv ) + +/* queuing_rw_mutex.cpp */ +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex18internal_constructEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock17upgrade_to_writerEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock19downgrade_to_readerEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock7acquireERS0_b ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock7releaseEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock11try_acquireERS0_b ) + +/* reader_writer_lock.cpp */ +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock11scoped_lock16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock11scoped_lock18internal_constructERS1_ ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock13try_lock_readEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock16scoped_lock_read16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock16scoped_lock_read18internal_constructERS1_ ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock18internal_constructEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock4lockEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock6unlockEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock8try_lockEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock9lock_readEv ) + +#if !TBB_NO_LEGACY +/* spin_rw_mutex.cpp v2 */ +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex16internal_upgradeEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex22internal_itt_releasingEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_acquire_readerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_acquire_writerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex18internal_downgradeEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_release_readerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_release_writerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex27internal_try_acquire_readerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex27internal_try_acquire_writerEPS0_ ) +#endif + +/* spin_rw_mutex v3 */ +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v318internal_constructEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v316internal_upgradeEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v318internal_downgradeEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_acquire_readerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_acquire_writerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_release_readerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_release_writerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v327internal_try_acquire_readerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v327internal_try_acquire_writerEv ) + +/* spin_mutex.cpp */ +__TBB_SYMBOL( _ZN3tbb10spin_mutex18internal_constructEv ) +__TBB_SYMBOL( _ZN3tbb10spin_mutex11scoped_lock16internal_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb10spin_mutex11scoped_lock16internal_releaseEv ) +__TBB_SYMBOL( _ZN3tbb10spin_mutex11scoped_lock20internal_try_acquireERS0_ ) + +/* mutex.cpp */ +__TBB_SYMBOL( _ZN3tbb5mutex11scoped_lock16internal_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb5mutex11scoped_lock16internal_releaseEv ) +__TBB_SYMBOL( _ZN3tbb5mutex11scoped_lock20internal_try_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb5mutex16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb5mutex18internal_constructEv ) + +/* recursive_mutex.cpp */ +__TBB_SYMBOL( _ZN3tbb15recursive_mutex11scoped_lock16internal_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex11scoped_lock16internal_releaseEv ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex11scoped_lock20internal_try_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex18internal_constructEv ) + +/* QueuingMutex.cpp */ +__TBB_SYMBOL( _ZN3tbb13queuing_mutex18internal_constructEv ) +__TBB_SYMBOL( _ZN3tbb13queuing_mutex11scoped_lock7acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb13queuing_mutex11scoped_lock7releaseEv ) +__TBB_SYMBOL( _ZN3tbb13queuing_mutex11scoped_lock11try_acquireERS0_ ) + +/* critical_section.cpp */ +__TBB_SYMBOL( _ZN3tbb8internal19critical_section_v418internal_constructEv ) + +#if !TBB_NO_LEGACY +/* concurrent_hash_map */ +__TBB_SYMBOL( _ZNK3tbb8internal21hash_map_segment_base23internal_grow_predicateEv ) + +/* concurrent_queue.cpp v2 */ +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base12internal_popEPv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base13internal_pushEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base21internal_set_capacityElm ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base23internal_pop_if_presentEPv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base25internal_push_if_not_fullEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_baseC2Em ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_baseD2Ev ) +__TBB_SYMBOL( _ZTIN3tbb8internal21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZTSN3tbb8internal21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZTVN3tbb8internal21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_base6assignERKS1_ ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_base7advanceEv ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_baseC2ERKNS0_21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_baseD2Ev ) +__TBB_SYMBOL( _ZNK3tbb8internal21concurrent_queue_base13internal_sizeEv ) +#endif + +/* concurrent_queue v3 */ +/* constructors */ +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v3C2Em ) +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v3C2ERKNS0_24concurrent_queue_base_v3E ) +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v3C2ERKNS0_24concurrent_queue_base_v3Em ) +/* destructors */ +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v3D2Ev ) +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v3D2Ev ) +/* typeinfo */ +__TBB_SYMBOL( _ZTIN3tbb8internal24concurrent_queue_base_v3E ) +__TBB_SYMBOL( _ZTSN3tbb8internal24concurrent_queue_base_v3E ) +/* vtable */ +__TBB_SYMBOL( _ZTVN3tbb8internal24concurrent_queue_base_v3E ) +/* methods */ +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v36assignERKS1_ ) +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v37advanceEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v313internal_pushEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v325internal_push_if_not_fullEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v312internal_popEPv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v323internal_pop_if_presentEPv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v314internal_abortEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v321internal_finish_clearEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v321internal_set_capacityElm ) +__TBB_SYMBOL( _ZNK3tbb8internal24concurrent_queue_base_v313internal_sizeEv ) +__TBB_SYMBOL( _ZNK3tbb8internal24concurrent_queue_base_v314internal_emptyEv ) +__TBB_SYMBOL( _ZNK3tbb8internal24concurrent_queue_base_v324internal_throw_exceptionEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v36assignERKS1_ ) + +#if !TBB_NO_LEGACY +/* concurrent_vector.cpp v2 */ +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base13internal_copyERKS1_mPFvPvPKvmE ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base14internal_clearEPFvPvmEb ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base15internal_assignERKS1_mPFvPvmEPFvS4_PKvmESA_ ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base16internal_grow_byEmmPFvPvmE ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base16internal_reserveEmmm ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base18internal_push_backEmRm ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base25internal_grow_to_at_leastEmmPFvPvmE ) +__TBB_SYMBOL( _ZNK3tbb8internal22concurrent_vector_base17internal_capacityEv ) +#endif + +/* concurrent_vector v3 */ +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v313internal_copyERKS1_mPFvPvPKvmE ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v314internal_clearEPFvPvmE ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v315internal_assignERKS1_mPFvPvmEPFvS4_PKvmESA_ ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v316internal_grow_byEmmPFvPvPKvmES4_ ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v316internal_reserveEmmm ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v318internal_push_backEmRm ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v325internal_grow_to_at_leastEmmPFvPvPKvmES4_ ) +__TBB_SYMBOL( _ZNK3tbb8internal25concurrent_vector_base_v317internal_capacityEv ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v316internal_compactEmPvPFvS2_mEPFvS2_PKvmE ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v313internal_swapERS1_ ) +__TBB_SYMBOL( _ZNK3tbb8internal25concurrent_vector_base_v324internal_throw_exceptionEm ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v3D2Ev ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v315internal_resizeEmmmPKvPFvPvmEPFvS4_S3_mE ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v337internal_grow_to_at_least_with_resultEmmPFvPvPKvmES4_ ) + +/* tbb_thread */ +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v320hardware_concurrencyEv ) +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v36detachEv ) +__TBB_SYMBOL( _ZN3tbb8internal16thread_get_id_v3Ev ) +__TBB_SYMBOL( _ZN3tbb8internal15free_closure_v3EPv ) +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v34joinEv ) +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v314internal_startEPFPvS2_ES2_ ) +__TBB_SYMBOL( _ZN3tbb8internal19allocate_closure_v3Em ) +__TBB_SYMBOL( _ZN3tbb8internal7move_v3ERNS0_13tbb_thread_v3ES2_ ) +__TBB_SYMBOL( _ZN3tbb8internal15thread_yield_v3Ev ) +__TBB_SYMBOL( _ZN3tbb8internal15thread_sleep_v3ERKNS_10tick_count10interval_tE ) + +/* asm functions */ +__TBB_SYMBOL( __TBB_machine_fetchadd1__TBB_full_fence ) +__TBB_SYMBOL( __TBB_machine_fetchadd2__TBB_full_fence ) +__TBB_SYMBOL( __TBB_machine_fetchadd4__TBB_full_fence ) +__TBB_SYMBOL( __TBB_machine_fetchadd8__TBB_full_fence ) +__TBB_SYMBOL( __TBB_machine_fetchstore1__TBB_full_fence ) +__TBB_SYMBOL( __TBB_machine_fetchstore2__TBB_full_fence ) +__TBB_SYMBOL( __TBB_machine_fetchstore4__TBB_full_fence ) +__TBB_SYMBOL( __TBB_machine_fetchstore8__TBB_full_fence ) +__TBB_SYMBOL( __TBB_machine_fetchadd1acquire ) +__TBB_SYMBOL( __TBB_machine_fetchadd1release ) +__TBB_SYMBOL( __TBB_machine_fetchadd2acquire ) +__TBB_SYMBOL( __TBB_machine_fetchadd2release ) +__TBB_SYMBOL( __TBB_machine_fetchadd4acquire ) +__TBB_SYMBOL( __TBB_machine_fetchadd4release ) +__TBB_SYMBOL( __TBB_machine_fetchadd8acquire ) +__TBB_SYMBOL( __TBB_machine_fetchadd8release ) +__TBB_SYMBOL( __TBB_machine_fetchstore1acquire ) +__TBB_SYMBOL( __TBB_machine_fetchstore1release ) +__TBB_SYMBOL( __TBB_machine_fetchstore2acquire ) +__TBB_SYMBOL( __TBB_machine_fetchstore2release ) +__TBB_SYMBOL( __TBB_machine_fetchstore4acquire ) +__TBB_SYMBOL( __TBB_machine_fetchstore4release ) +__TBB_SYMBOL( __TBB_machine_fetchstore8acquire ) +__TBB_SYMBOL( __TBB_machine_fetchstore8release ) +__TBB_SYMBOL( __TBB_machine_cmpswp1acquire ) +__TBB_SYMBOL( __TBB_machine_cmpswp1release ) +__TBB_SYMBOL( __TBB_machine_cmpswp1__TBB_full_fence ) +__TBB_SYMBOL( __TBB_machine_cmpswp2acquire ) +__TBB_SYMBOL( __TBB_machine_cmpswp2release ) +__TBB_SYMBOL( __TBB_machine_cmpswp2__TBB_full_fence ) +__TBB_SYMBOL( __TBB_machine_cmpswp4acquire ) +__TBB_SYMBOL( __TBB_machine_cmpswp4release ) +__TBB_SYMBOL( __TBB_machine_cmpswp4__TBB_full_fence ) +__TBB_SYMBOL( __TBB_machine_cmpswp8acquire ) +__TBB_SYMBOL( __TBB_machine_cmpswp8release ) +__TBB_SYMBOL( __TBB_machine_cmpswp8__TBB_full_fence ) +__TBB_SYMBOL( __TBB_machine_lg ) +__TBB_SYMBOL( __TBB_machine_lockbyte ) +__TBB_SYMBOL( __TBB_machine_pause ) +__TBB_SYMBOL( __TBB_machine_trylockbyte ) +__TBB_SYMBOL( __TBB_machine_load8_relaxed ) +__TBB_SYMBOL( __TBB_machine_store8_relaxed ) +__TBB_SYMBOL( __TBB_machine_load4_relaxed ) +__TBB_SYMBOL( __TBB_machine_store4_relaxed ) +__TBB_SYMBOL( __TBB_machine_load2_relaxed ) +__TBB_SYMBOL( __TBB_machine_store2_relaxed ) +__TBB_SYMBOL( __TBB_machine_load1_relaxed ) +__TBB_SYMBOL( __TBB_machine_store1_relaxed ) + +#undef __TBB_SYMBOL diff --git a/src/tbb/src/tbb/mac32-tbb-export.def b/src/tbb/src/tbb/mac32-tbb-export.def new file mode 100644 index 0000000..33b5c4c --- /dev/null +++ b/src/tbb/src/tbb/mac32-tbb-export.def @@ -0,0 +1,23 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + The source code contained or described herein and all documents related + to the source code ("Material") are owned by Intel Corporation or its + suppliers or licensors. Title to the Material remains with Intel + Corporation or its suppliers and licensors. The Material is protected + by worldwide copyright laws and treaty provisions. No part of the + Material may be used, copied, reproduced, modified, published, uploaded, + posted, transmitted, distributed, or disclosed in any way without + Intel's prior express written permission. + + No license under any patent, copyright, trade secret or other + intellectual property right is granted to or conferred upon you by + disclosure or delivery of the Materials, either expressly, by + implication, inducement, estoppel or otherwise. Any license under such + intellectual property rights must be express and approved by Intel in + writing. +*/ + +#define __TBB_SYMBOL( sym ) _##sym +#include "mac32-tbb-export.lst" + diff --git a/src/tbb/src/tbb/mac32-tbb-export.lst b/src/tbb/src/tbb/mac32-tbb-export.lst new file mode 100644 index 0000000..c459860 --- /dev/null +++ b/src/tbb/src/tbb/mac32-tbb-export.lst @@ -0,0 +1,367 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + The source code contained or described herein and all documents related + to the source code ("Material") are owned by Intel Corporation or its + suppliers or licensors. Title to the Material remains with Intel + Corporation or its suppliers and licensors. The Material is protected + by worldwide copyright laws and treaty provisions. No part of the + Material may be used, copied, reproduced, modified, published, uploaded, + posted, transmitted, distributed, or disclosed in any way without + Intel's prior express written permission. + + No license under any patent, copyright, trade secret or other + intellectual property right is granted to or conferred upon you by + disclosure or delivery of the Materials, either expressly, by + implication, inducement, estoppel or otherwise. Any license under such + intellectual property rights must be express and approved by Intel in + writing. +*/ + +#include "tbb/tbb_config.h" + +/* + Sometimes Mac OS X requires leading underscore (e. g. in export list file), but sometimes not + (e. g. when searching symbol in a dynamic library via dlsym()). Symbols in this file SHOULD + be listed WITHOUT one leading underscore. __TBB_SYMBOL macro should add underscore when + necessary, depending on the indended usage. +*/ + +// cache_aligned_allocator.cpp +__TBB_SYMBOL( _ZN3tbb8internal12NFS_AllocateEmmPv ) +__TBB_SYMBOL( _ZN3tbb8internal15NFS_GetLineSizeEv ) +__TBB_SYMBOL( _ZN3tbb8internal8NFS_FreeEPv ) +__TBB_SYMBOL( _ZN3tbb8internal23allocate_via_handler_v3Em ) +__TBB_SYMBOL( _ZN3tbb8internal25deallocate_via_handler_v3EPv ) +__TBB_SYMBOL( _ZN3tbb8internal17is_malloc_used_v3Ev ) + +// task.cpp v3 +__TBB_SYMBOL( _ZN3tbb4task13note_affinityEt ) +__TBB_SYMBOL( _ZN3tbb4task22internal_set_ref_countEi ) +__TBB_SYMBOL( _ZN3tbb4task28internal_decrement_ref_countEv ) +__TBB_SYMBOL( _ZN3tbb4task22spawn_and_wait_for_allERNS_9task_listE ) +__TBB_SYMBOL( _ZN3tbb4task4selfEv ) +__TBB_SYMBOL( _ZN3tbb10interface58internal9task_base7destroyERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb4task26is_owned_by_current_threadEv ) +__TBB_SYMBOL( _ZN3tbb8internal19allocate_root_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZN3tbb8internal19allocate_root_proxy8allocateEm ) +__TBB_SYMBOL( _ZN3tbb8internal28affinity_partitioner_base_v36resizeEj ) +__TBB_SYMBOL( _ZN3tbb8internal36get_initial_auto_partitioner_divisorEv ) +__TBB_SYMBOL( _ZNK3tbb8internal20allocate_child_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb8internal20allocate_child_proxy8allocateEm ) +__TBB_SYMBOL( _ZNK3tbb8internal27allocate_continuation_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb8internal27allocate_continuation_proxy8allocateEm ) +__TBB_SYMBOL( _ZNK3tbb8internal34allocate_additional_child_of_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb8internal34allocate_additional_child_of_proxy8allocateEm ) +__TBB_SYMBOL( _ZTIN3tbb4taskE ) +__TBB_SYMBOL( _ZTSN3tbb4taskE ) +__TBB_SYMBOL( _ZTVN3tbb4taskE ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init19default_num_threadsEv ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init10initializeEim ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init10initializeEi ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init9terminateEv ) +__TBB_SYMBOL( _ZN3tbb8internal26task_scheduler_observer_v37observeEb ) +__TBB_SYMBOL( _ZN3tbb10empty_task7executeEv ) +__TBB_SYMBOL( _ZN3tbb10empty_taskD0Ev ) +__TBB_SYMBOL( _ZN3tbb10empty_taskD1Ev ) +__TBB_SYMBOL( _ZTIN3tbb10empty_taskE ) +__TBB_SYMBOL( _ZTSN3tbb10empty_taskE ) +__TBB_SYMBOL( _ZTVN3tbb10empty_taskE ) + +#if !TBB_NO_LEGACY +// task_v2.cpp +__TBB_SYMBOL( _ZN3tbb4task7destroyERS0_ ) +#endif + +// Exception handling in task scheduler +#if __TBB_TASK_GROUP_CONTEXT +__TBB_SYMBOL( _ZNK3tbb8internal32allocate_root_with_context_proxy8allocateEm ) +__TBB_SYMBOL( _ZNK3tbb8internal32allocate_root_with_context_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZN3tbb4task12change_groupERNS_18task_group_contextE ) +__TBB_SYMBOL( _ZNK3tbb18task_group_context28is_group_execution_cancelledEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context22cancel_group_executionEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context26register_pending_exceptionEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context5resetEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context4initEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_contextD1Ev ) +__TBB_SYMBOL( _ZN3tbb18task_group_contextD2Ev ) +#if __TBB_TASK_PRIORITY +__TBB_SYMBOL( _ZN3tbb18task_group_context12set_priorityENS_10priority_tE ) +__TBB_SYMBOL( _ZNK3tbb18task_group_context8priorityEv ) +#endif /* __TBB_TASK_PRIORITY */ +__TBB_SYMBOL( _ZNK3tbb18captured_exception4nameEv ) +__TBB_SYMBOL( _ZNK3tbb18captured_exception4whatEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception10throw_selfEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception3setEPKcS2_ ) +__TBB_SYMBOL( _ZN3tbb18captured_exception4moveEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception5clearEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception7destroyEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception8allocateEPKcS2_ ) +__TBB_SYMBOL( _ZN3tbb18captured_exceptionD0Ev ) +__TBB_SYMBOL( _ZN3tbb18captured_exceptionD1Ev ) +__TBB_SYMBOL( _ZN3tbb18captured_exceptionD2Ev ) +__TBB_SYMBOL( _ZTIN3tbb18captured_exceptionE ) +__TBB_SYMBOL( _ZTSN3tbb18captured_exceptionE ) +__TBB_SYMBOL( _ZTVN3tbb18captured_exceptionE ) +__TBB_SYMBOL( _ZTIN3tbb13tbb_exceptionE ) +__TBB_SYMBOL( _ZTSN3tbb13tbb_exceptionE ) +__TBB_SYMBOL( _ZTVN3tbb13tbb_exceptionE ) +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +// Symbols for exceptions thrown from TBB +__TBB_SYMBOL( _ZN3tbb8internal33throw_bad_last_alloc_exception_v4Ev ) +__TBB_SYMBOL( _ZN3tbb8internal18throw_exception_v4ENS0_12exception_idE ) +__TBB_SYMBOL( _ZNSt13runtime_errorD1Ev ) +__TBB_SYMBOL( _ZTISt13runtime_error ) +__TBB_SYMBOL( _ZTSSt13runtime_error ) +__TBB_SYMBOL( _ZNSt16invalid_argumentD1Ev ) +__TBB_SYMBOL( _ZTISt16invalid_argument ) +__TBB_SYMBOL( _ZTSSt16invalid_argument ) +__TBB_SYMBOL( _ZNSt11range_errorD1Ev ) +__TBB_SYMBOL( _ZTISt11range_error ) +__TBB_SYMBOL( _ZTSSt11range_error ) +__TBB_SYMBOL( _ZNSt12length_errorD1Ev ) +__TBB_SYMBOL( _ZTISt12length_error ) +__TBB_SYMBOL( _ZTSSt12length_error ) +__TBB_SYMBOL( _ZNSt12out_of_rangeD1Ev ) +__TBB_SYMBOL( _ZTISt12out_of_range ) +__TBB_SYMBOL( _ZTSSt12out_of_range ) +__TBB_SYMBOL( _ZN3tbb14bad_last_allocD0Ev ) +__TBB_SYMBOL( _ZN3tbb14bad_last_allocD1Ev ) +__TBB_SYMBOL( _ZNK3tbb14bad_last_alloc4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb14bad_last_allocE ) +__TBB_SYMBOL( _ZTSN3tbb14bad_last_allocE ) +__TBB_SYMBOL( _ZTVN3tbb14bad_last_allocE ) +__TBB_SYMBOL( _ZN3tbb12missing_waitD0Ev ) +__TBB_SYMBOL( _ZN3tbb12missing_waitD1Ev ) +__TBB_SYMBOL( _ZNK3tbb12missing_wait4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb12missing_waitE ) +__TBB_SYMBOL( _ZTSN3tbb12missing_waitE ) +__TBB_SYMBOL( _ZTVN3tbb12missing_waitE ) +__TBB_SYMBOL( _ZN3tbb27invalid_multiple_schedulingD0Ev ) +__TBB_SYMBOL( _ZN3tbb27invalid_multiple_schedulingD1Ev ) +__TBB_SYMBOL( _ZNK3tbb27invalid_multiple_scheduling4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb27invalid_multiple_schedulingE ) +__TBB_SYMBOL( _ZTSN3tbb27invalid_multiple_schedulingE ) +__TBB_SYMBOL( _ZTVN3tbb27invalid_multiple_schedulingE ) +__TBB_SYMBOL( _ZN3tbb13improper_lockD0Ev ) +__TBB_SYMBOL( _ZN3tbb13improper_lockD1Ev ) +__TBB_SYMBOL( _ZNK3tbb13improper_lock4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb13improper_lockE ) +__TBB_SYMBOL( _ZTSN3tbb13improper_lockE ) +__TBB_SYMBOL( _ZTVN3tbb13improper_lockE ) +__TBB_SYMBOL( _ZN3tbb10user_abortD0Ev ) +__TBB_SYMBOL( _ZN3tbb10user_abortD1Ev ) +__TBB_SYMBOL( _ZNK3tbb10user_abort4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb10user_abortE ) +__TBB_SYMBOL( _ZTSN3tbb10user_abortE ) +__TBB_SYMBOL( _ZTVN3tbb10user_abortE ) + +// tbb_misc.cpp +__TBB_SYMBOL( _ZN3tbb17assertion_failureEPKciS1_S1_ ) +__TBB_SYMBOL( _ZN3tbb21set_assertion_handlerEPFvPKciS1_S1_E ) +__TBB_SYMBOL( _ZN3tbb8internal13handle_perrorEiPKc ) +__TBB_SYMBOL( _ZN3tbb8internal15runtime_warningEPKcz ) +#ifndef __POWERPC__ +__TBB_SYMBOL( __TBB_machine_store8_slow_perf_warning ) +__TBB_SYMBOL( __TBB_machine_store8_slow ) +#endif +__TBB_SYMBOL( TBB_runtime_interface_version ) + +// tbb_main.cpp +__TBB_SYMBOL( _ZN3tbb8internal32itt_load_pointer_with_acquire_v3EPKv ) +__TBB_SYMBOL( _ZN3tbb8internal33itt_store_pointer_with_release_v3EPvS1_ ) +__TBB_SYMBOL( _ZN3tbb8internal18call_itt_notify_v5EiPv ) +__TBB_SYMBOL( _ZN3tbb8internal19itt_load_pointer_v3EPKv ) +__TBB_SYMBOL( _ZN3tbb8internal20itt_set_sync_name_v3EPvPKc ) + +// pipeline.cpp +__TBB_SYMBOL( _ZTIN3tbb6filterE ) +__TBB_SYMBOL( _ZTSN3tbb6filterE ) +__TBB_SYMBOL( _ZTVN3tbb6filterE ) +__TBB_SYMBOL( _ZN3tbb6filterD2Ev ) +__TBB_SYMBOL( _ZN3tbb8pipeline10add_filterERNS_6filterE ) +__TBB_SYMBOL( _ZN3tbb8pipeline12inject_tokenERNS_4taskE ) +__TBB_SYMBOL( _ZN3tbb8pipeline13remove_filterERNS_6filterE ) +__TBB_SYMBOL( _ZN3tbb8pipeline3runEm ) +#if __TBB_TASK_GROUP_CONTEXT +__TBB_SYMBOL( _ZN3tbb8pipeline3runEmRNS_18task_group_contextE ) +#endif +__TBB_SYMBOL( _ZN3tbb8pipeline5clearEv ) +__TBB_SYMBOL( _ZN3tbb19thread_bound_filter12process_itemEv ) +__TBB_SYMBOL( _ZN3tbb19thread_bound_filter16try_process_itemEv ) +__TBB_SYMBOL( _ZN3tbb8pipelineC1Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineC2Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineD0Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineD1Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineD2Ev ) +__TBB_SYMBOL( _ZTIN3tbb8pipelineE ) +__TBB_SYMBOL( _ZTSN3tbb8pipelineE ) +__TBB_SYMBOL( _ZTVN3tbb8pipelineE ) +__TBB_SYMBOL( _ZN3tbb6filter16set_end_of_inputEv ) + +// queuing_rw_mutex.cpp +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock17upgrade_to_writerEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock19downgrade_to_readerEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock7acquireERS0_b ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock7releaseEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock11try_acquireERS0_b ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex18internal_constructEv ) + +// reader_writer_lock.cpp +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock11scoped_lock16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock11scoped_lock18internal_constructERS1_ ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock13try_lock_readEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock16scoped_lock_read16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock16scoped_lock_read18internal_constructERS1_ ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock18internal_constructEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock4lockEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock6unlockEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock8try_lockEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock9lock_readEv ) + +#if !TBB_NO_LEGACY +// spin_rw_mutex.cpp v2 +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex16internal_upgradeEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex22internal_itt_releasingEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_acquire_readerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_acquire_writerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex18internal_downgradeEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_release_readerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_release_writerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex27internal_try_acquire_readerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex27internal_try_acquire_writerEPS0_ ) +#endif + +// spin_rw_mutex v3 +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v316internal_upgradeEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v318internal_downgradeEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_acquire_readerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_acquire_writerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_release_readerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_release_writerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v327internal_try_acquire_readerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v327internal_try_acquire_writerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v318internal_constructEv ) + +// spin_mutex.cpp +__TBB_SYMBOL( _ZN3tbb10spin_mutex11scoped_lock16internal_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb10spin_mutex11scoped_lock16internal_releaseEv ) +__TBB_SYMBOL( _ZN3tbb10spin_mutex11scoped_lock20internal_try_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb10spin_mutex18internal_constructEv ) + +// mutex.cpp +__TBB_SYMBOL( _ZN3tbb5mutex11scoped_lock16internal_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb5mutex11scoped_lock16internal_releaseEv ) +__TBB_SYMBOL( _ZN3tbb5mutex11scoped_lock20internal_try_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb5mutex16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb5mutex18internal_constructEv ) + +// recursive_mutex.cpp +__TBB_SYMBOL( _ZN3tbb15recursive_mutex11scoped_lock16internal_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex11scoped_lock16internal_releaseEv ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex11scoped_lock20internal_try_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex18internal_constructEv ) + +// queuing_mutex.cpp +__TBB_SYMBOL( _ZN3tbb13queuing_mutex11scoped_lock7acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb13queuing_mutex11scoped_lock7releaseEv ) +__TBB_SYMBOL( _ZN3tbb13queuing_mutex11scoped_lock11try_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb13queuing_mutex18internal_constructEv ) + +// critical_section.cpp +__TBB_SYMBOL( _ZN3tbb8internal19critical_section_v418internal_constructEv ) + +#if !TBB_NO_LEGACY +// concurrent_hash_map +__TBB_SYMBOL( _ZNK3tbb8internal21hash_map_segment_base23internal_grow_predicateEv ) + +// concurrent_queue.cpp v2 +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base12internal_popEPv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base13internal_pushEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base21internal_set_capacityEim ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base23internal_pop_if_presentEPv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base25internal_push_if_not_fullEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_baseC2Em ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_baseD2Ev ) +__TBB_SYMBOL( _ZTIN3tbb8internal21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZTSN3tbb8internal21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZTVN3tbb8internal21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_base6assignERKS1_ ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_base7advanceEv ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_baseC2ERKNS0_21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_baseD2Ev ) +__TBB_SYMBOL( _ZNK3tbb8internal21concurrent_queue_base13internal_sizeEv ) +#endif + +// concurrent_queue v3 +// constructors +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v3C2ERKNS0_24concurrent_queue_base_v3E ) +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v3C2ERKNS0_24concurrent_queue_base_v3Em ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v3C2Em ) +// destructors +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v3D2Ev ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v3D2Ev ) +// typeinfo +__TBB_SYMBOL( _ZTIN3tbb8internal24concurrent_queue_base_v3E ) +__TBB_SYMBOL( _ZTSN3tbb8internal24concurrent_queue_base_v3E ) +// vtable +__TBB_SYMBOL( _ZTVN3tbb8internal24concurrent_queue_base_v3E ) +// methods +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v37advanceEv ) +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v36assignERKS1_ ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v313internal_pushEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v325internal_push_if_not_fullEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v312internal_popEPv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v323internal_pop_if_presentEPv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v314internal_abortEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v321internal_set_capacityEim ) +__TBB_SYMBOL( _ZNK3tbb8internal24concurrent_queue_base_v313internal_sizeEv ) +__TBB_SYMBOL( _ZNK3tbb8internal24concurrent_queue_base_v314internal_emptyEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v321internal_finish_clearEv ) +__TBB_SYMBOL( _ZNK3tbb8internal24concurrent_queue_base_v324internal_throw_exceptionEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v36assignERKS1_ ) + +#if !TBB_NO_LEGACY +// concurrent_vector.cpp v2 +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base13internal_copyERKS1_mPFvPvPKvmE ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base14internal_clearEPFvPvmEb ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base15internal_assignERKS1_mPFvPvmEPFvS4_PKvmESA_ ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base16internal_grow_byEmmPFvPvmE ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base16internal_reserveEmmm ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base18internal_push_backEmRm ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base25internal_grow_to_at_leastEmmPFvPvmE ) +__TBB_SYMBOL( _ZNK3tbb8internal22concurrent_vector_base17internal_capacityEv ) +#endif + +// concurrent_vector v3 +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v313internal_copyERKS1_mPFvPvPKvmE ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v314internal_clearEPFvPvmE ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v315internal_assignERKS1_mPFvPvmEPFvS4_PKvmESA_ ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v316internal_grow_byEmmPFvPvPKvmES4_ ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v316internal_reserveEmmm ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v318internal_push_backEmRm ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v325internal_grow_to_at_leastEmmPFvPvPKvmES4_ ) +__TBB_SYMBOL( _ZNK3tbb8internal25concurrent_vector_base_v317internal_capacityEv ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v316internal_compactEmPvPFvS2_mEPFvS2_PKvmE ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v313internal_swapERS1_ ) +__TBB_SYMBOL( _ZNK3tbb8internal25concurrent_vector_base_v324internal_throw_exceptionEm ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v3D2Ev ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v315internal_resizeEmmmPKvPFvPvmEPFvS4_S3_mE ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v337internal_grow_to_at_least_with_resultEmmPFvPvPKvmES4_ ) + +// tbb_thread +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v314internal_startEPFPvS2_ES2_ ) +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v320hardware_concurrencyEv ) +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v34joinEv ) +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v36detachEv ) +__TBB_SYMBOL( _ZN3tbb8internal15free_closure_v3EPv ) +__TBB_SYMBOL( _ZN3tbb8internal15thread_sleep_v3ERKNS_10tick_count10interval_tE ) +__TBB_SYMBOL( _ZN3tbb8internal15thread_yield_v3Ev ) +__TBB_SYMBOL( _ZN3tbb8internal16thread_get_id_v3Ev ) +__TBB_SYMBOL( _ZN3tbb8internal19allocate_closure_v3Em ) +__TBB_SYMBOL( _ZN3tbb8internal7move_v3ERNS0_13tbb_thread_v3ES2_ ) + +#undef __TBB_SYMBOL diff --git a/src/tbb/src/tbb/mac64-tbb-export.def b/src/tbb/src/tbb/mac64-tbb-export.def new file mode 100644 index 0000000..6bef209 --- /dev/null +++ b/src/tbb/src/tbb/mac64-tbb-export.def @@ -0,0 +1,23 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + The source code contained or described herein and all documents related + to the source code ("Material") are owned by Intel Corporation or its + suppliers or licensors. Title to the Material remains with Intel + Corporation or its suppliers and licensors. The Material is protected + by worldwide copyright laws and treaty provisions. No part of the + Material may be used, copied, reproduced, modified, published, uploaded, + posted, transmitted, distributed, or disclosed in any way without + Intel's prior express written permission. + + No license under any patent, copyright, trade secret or other + intellectual property right is granted to or conferred upon you by + disclosure or delivery of the Materials, either expressly, by + implication, inducement, estoppel or otherwise. Any license under such + intellectual property rights must be express and approved by Intel in + writing. +*/ + +#define __TBB_SYMBOL( sym ) _##sym +#include "mac64-tbb-export.lst" + diff --git a/src/tbb/src/tbb/mac64-tbb-export.lst b/src/tbb/src/tbb/mac64-tbb-export.lst new file mode 100644 index 0000000..7c573e5 --- /dev/null +++ b/src/tbb/src/tbb/mac64-tbb-export.lst @@ -0,0 +1,364 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + The source code contained or described herein and all documents related + to the source code ("Material") are owned by Intel Corporation or its + suppliers or licensors. Title to the Material remains with Intel + Corporation or its suppliers and licensors. The Material is protected + by worldwide copyright laws and treaty provisions. No part of the + Material may be used, copied, reproduced, modified, published, uploaded, + posted, transmitted, distributed, or disclosed in any way without + Intel's prior express written permission. + + No license under any patent, copyright, trade secret or other + intellectual property right is granted to or conferred upon you by + disclosure or delivery of the Materials, either expressly, by + implication, inducement, estoppel or otherwise. Any license under such + intellectual property rights must be express and approved by Intel in + writing. +*/ + +#include "tbb/tbb_config.h" + +/* + Sometimes Mac OS X requires leading underscore (e. g. in export list file), but sometimes not + (e. g. when searching symbol in a dynamic library via dlsym()). Symbols in this file SHOULD + be listed WITHOUT one leading underscore. __TBB_SYMBOL macro should add underscore when + necessary, depending on the indended usage. +*/ + +// cache_aligned_allocator.cpp +__TBB_SYMBOL( _ZN3tbb8internal12NFS_AllocateEmmPv ) +__TBB_SYMBOL( _ZN3tbb8internal15NFS_GetLineSizeEv ) +__TBB_SYMBOL( _ZN3tbb8internal8NFS_FreeEPv ) +__TBB_SYMBOL( _ZN3tbb8internal23allocate_via_handler_v3Em ) +__TBB_SYMBOL( _ZN3tbb8internal25deallocate_via_handler_v3EPv ) +__TBB_SYMBOL( _ZN3tbb8internal17is_malloc_used_v3Ev ) + +// task.cpp v3 +__TBB_SYMBOL( _ZN3tbb4task13note_affinityEt ) +__TBB_SYMBOL( _ZN3tbb4task22internal_set_ref_countEi ) +__TBB_SYMBOL( _ZN3tbb4task28internal_decrement_ref_countEv ) +__TBB_SYMBOL( _ZN3tbb4task22spawn_and_wait_for_allERNS_9task_listE ) +__TBB_SYMBOL( _ZN3tbb4task4selfEv ) +__TBB_SYMBOL( _ZN3tbb10interface58internal9task_base7destroyERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb4task26is_owned_by_current_threadEv ) +__TBB_SYMBOL( _ZN3tbb8internal19allocate_root_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZN3tbb8internal19allocate_root_proxy8allocateEm ) +__TBB_SYMBOL( _ZN3tbb8internal28affinity_partitioner_base_v36resizeEj ) +__TBB_SYMBOL( _ZN3tbb8internal36get_initial_auto_partitioner_divisorEv ) +__TBB_SYMBOL( _ZNK3tbb8internal20allocate_child_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb8internal20allocate_child_proxy8allocateEm ) +__TBB_SYMBOL( _ZNK3tbb8internal27allocate_continuation_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb8internal27allocate_continuation_proxy8allocateEm ) +__TBB_SYMBOL( _ZNK3tbb8internal34allocate_additional_child_of_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb8internal34allocate_additional_child_of_proxy8allocateEm ) +__TBB_SYMBOL( _ZTIN3tbb4taskE ) +__TBB_SYMBOL( _ZTSN3tbb4taskE ) +__TBB_SYMBOL( _ZTVN3tbb4taskE ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init19default_num_threadsEv ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init10initializeEim ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init10initializeEi ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init9terminateEv ) +__TBB_SYMBOL( _ZN3tbb8internal26task_scheduler_observer_v37observeEb ) +__TBB_SYMBOL( _ZN3tbb10empty_task7executeEv ) +__TBB_SYMBOL( _ZN3tbb10empty_taskD0Ev ) +__TBB_SYMBOL( _ZN3tbb10empty_taskD1Ev ) +__TBB_SYMBOL( _ZTIN3tbb10empty_taskE ) +__TBB_SYMBOL( _ZTSN3tbb10empty_taskE ) +__TBB_SYMBOL( _ZTVN3tbb10empty_taskE ) + +#if !TBB_NO_LEGACY +// task_v2.cpp +__TBB_SYMBOL( _ZN3tbb4task7destroyERS0_ ) +#endif + +// Exception handling in task scheduler +#if __TBB_TASK_GROUP_CONTEXT +__TBB_SYMBOL( _ZNK3tbb8internal32allocate_root_with_context_proxy8allocateEm ) +__TBB_SYMBOL( _ZNK3tbb8internal32allocate_root_with_context_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZN3tbb4task12change_groupERNS_18task_group_contextE ) +__TBB_SYMBOL( _ZNK3tbb18task_group_context28is_group_execution_cancelledEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context22cancel_group_executionEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context26register_pending_exceptionEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context5resetEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context4initEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_contextD1Ev ) +__TBB_SYMBOL( _ZN3tbb18task_group_contextD2Ev ) +#if __TBB_TASK_PRIORITY +__TBB_SYMBOL( _ZN3tbb18task_group_context12set_priorityENS_10priority_tE ) +__TBB_SYMBOL( _ZNK3tbb18task_group_context8priorityEv ) +#endif /* __TBB_TASK_PRIORITY */ +__TBB_SYMBOL( _ZNK3tbb18captured_exception4nameEv ) +__TBB_SYMBOL( _ZNK3tbb18captured_exception4whatEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception10throw_selfEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception3setEPKcS2_ ) +__TBB_SYMBOL( _ZN3tbb18captured_exception4moveEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception5clearEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception7destroyEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception8allocateEPKcS2_ ) +__TBB_SYMBOL( _ZN3tbb18captured_exceptionD0Ev ) +__TBB_SYMBOL( _ZN3tbb18captured_exceptionD1Ev ) +__TBB_SYMBOL( _ZN3tbb18captured_exceptionD2Ev ) +__TBB_SYMBOL( _ZTIN3tbb18captured_exceptionE ) +__TBB_SYMBOL( _ZTSN3tbb18captured_exceptionE ) +__TBB_SYMBOL( _ZTVN3tbb18captured_exceptionE ) +__TBB_SYMBOL( _ZTIN3tbb13tbb_exceptionE ) +__TBB_SYMBOL( _ZTSN3tbb13tbb_exceptionE ) +__TBB_SYMBOL( _ZTVN3tbb13tbb_exceptionE ) +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +// Symbols for exceptions thrown from TBB +__TBB_SYMBOL( _ZN3tbb8internal33throw_bad_last_alloc_exception_v4Ev ) +__TBB_SYMBOL( _ZN3tbb8internal18throw_exception_v4ENS0_12exception_idE ) +__TBB_SYMBOL( _ZNSt13runtime_errorD1Ev ) +__TBB_SYMBOL( _ZTISt13runtime_error ) +__TBB_SYMBOL( _ZTSSt13runtime_error ) +__TBB_SYMBOL( _ZNSt16invalid_argumentD1Ev ) +__TBB_SYMBOL( _ZTISt16invalid_argument ) +__TBB_SYMBOL( _ZTSSt16invalid_argument ) +__TBB_SYMBOL( _ZNSt11range_errorD1Ev ) +__TBB_SYMBOL( _ZTISt11range_error ) +__TBB_SYMBOL( _ZTSSt11range_error ) +__TBB_SYMBOL( _ZNSt12length_errorD1Ev ) +__TBB_SYMBOL( _ZTISt12length_error ) +__TBB_SYMBOL( _ZTSSt12length_error ) +__TBB_SYMBOL( _ZNSt12out_of_rangeD1Ev ) +__TBB_SYMBOL( _ZTISt12out_of_range ) +__TBB_SYMBOL( _ZTSSt12out_of_range ) +__TBB_SYMBOL( _ZN3tbb14bad_last_allocD0Ev ) +__TBB_SYMBOL( _ZN3tbb14bad_last_allocD1Ev ) +__TBB_SYMBOL( _ZNK3tbb14bad_last_alloc4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb14bad_last_allocE ) +__TBB_SYMBOL( _ZTSN3tbb14bad_last_allocE ) +__TBB_SYMBOL( _ZTVN3tbb14bad_last_allocE ) +__TBB_SYMBOL( _ZN3tbb12missing_waitD0Ev ) +__TBB_SYMBOL( _ZN3tbb12missing_waitD1Ev ) +__TBB_SYMBOL( _ZNK3tbb12missing_wait4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb12missing_waitE ) +__TBB_SYMBOL( _ZTSN3tbb12missing_waitE ) +__TBB_SYMBOL( _ZTVN3tbb12missing_waitE ) +__TBB_SYMBOL( _ZN3tbb27invalid_multiple_schedulingD0Ev ) +__TBB_SYMBOL( _ZN3tbb27invalid_multiple_schedulingD1Ev ) +__TBB_SYMBOL( _ZNK3tbb27invalid_multiple_scheduling4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb27invalid_multiple_schedulingE ) +__TBB_SYMBOL( _ZTSN3tbb27invalid_multiple_schedulingE ) +__TBB_SYMBOL( _ZTVN3tbb27invalid_multiple_schedulingE ) +__TBB_SYMBOL( _ZN3tbb13improper_lockD0Ev ) +__TBB_SYMBOL( _ZN3tbb13improper_lockD1Ev ) +__TBB_SYMBOL( _ZNK3tbb13improper_lock4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb13improper_lockE ) +__TBB_SYMBOL( _ZTSN3tbb13improper_lockE ) +__TBB_SYMBOL( _ZTVN3tbb13improper_lockE ) +__TBB_SYMBOL( _ZN3tbb10user_abortD0Ev ) +__TBB_SYMBOL( _ZN3tbb10user_abortD1Ev ) +__TBB_SYMBOL( _ZNK3tbb10user_abort4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb10user_abortE ) +__TBB_SYMBOL( _ZTSN3tbb10user_abortE ) +__TBB_SYMBOL( _ZTVN3tbb10user_abortE ) + + +// tbb_misc.cpp +__TBB_SYMBOL( _ZN3tbb17assertion_failureEPKciS1_S1_ ) +__TBB_SYMBOL( _ZN3tbb21set_assertion_handlerEPFvPKciS1_S1_E ) +__TBB_SYMBOL( _ZN3tbb8internal13handle_perrorEiPKc ) +__TBB_SYMBOL( _ZN3tbb8internal15runtime_warningEPKcz ) +__TBB_SYMBOL( TBB_runtime_interface_version ) + +// tbb_main.cpp +__TBB_SYMBOL( _ZN3tbb8internal32itt_load_pointer_with_acquire_v3EPKv ) +__TBB_SYMBOL( _ZN3tbb8internal33itt_store_pointer_with_release_v3EPvS1_ ) +__TBB_SYMBOL( _ZN3tbb8internal18call_itt_notify_v5EiPv ) +__TBB_SYMBOL( _ZN3tbb8internal19itt_load_pointer_v3EPKv ) +__TBB_SYMBOL( _ZN3tbb8internal20itt_set_sync_name_v3EPvPKc ) + +// pipeline.cpp +__TBB_SYMBOL( _ZTIN3tbb6filterE ) +__TBB_SYMBOL( _ZTSN3tbb6filterE ) +__TBB_SYMBOL( _ZTVN3tbb6filterE ) +__TBB_SYMBOL( _ZN3tbb6filterD2Ev ) +__TBB_SYMBOL( _ZN3tbb8pipeline10add_filterERNS_6filterE ) +__TBB_SYMBOL( _ZN3tbb8pipeline12inject_tokenERNS_4taskE ) +__TBB_SYMBOL( _ZN3tbb8pipeline13remove_filterERNS_6filterE ) +__TBB_SYMBOL( _ZN3tbb8pipeline3runEm ) +#if __TBB_TASK_GROUP_CONTEXT +__TBB_SYMBOL( _ZN3tbb8pipeline3runEmRNS_18task_group_contextE ) +#endif +__TBB_SYMBOL( _ZN3tbb8pipeline5clearEv ) +__TBB_SYMBOL( _ZN3tbb19thread_bound_filter12process_itemEv ) +__TBB_SYMBOL( _ZN3tbb19thread_bound_filter16try_process_itemEv ) +__TBB_SYMBOL( _ZN3tbb8pipelineC1Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineC2Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineD0Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineD1Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineD2Ev ) +__TBB_SYMBOL( _ZTIN3tbb8pipelineE ) +__TBB_SYMBOL( _ZTSN3tbb8pipelineE ) +__TBB_SYMBOL( _ZTVN3tbb8pipelineE ) +__TBB_SYMBOL( _ZN3tbb6filter16set_end_of_inputEv ) + +// queuing_rw_mutex.cpp +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock17upgrade_to_writerEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock19downgrade_to_readerEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock7acquireERS0_b ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock7releaseEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock11try_acquireERS0_b ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex18internal_constructEv ) + +// reader_writer_lock.cpp +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock11scoped_lock16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock11scoped_lock18internal_constructERS1_ ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock13try_lock_readEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock16scoped_lock_read16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock16scoped_lock_read18internal_constructERS1_ ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock18internal_constructEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock4lockEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock6unlockEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock8try_lockEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock9lock_readEv ) + +#if !TBB_NO_LEGACY +// spin_rw_mutex.cpp v2 +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex16internal_upgradeEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex22internal_itt_releasingEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_acquire_readerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_acquire_writerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex18internal_downgradeEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_release_readerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_release_writerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex27internal_try_acquire_readerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex27internal_try_acquire_writerEPS0_ ) +#endif + +// spin_rw_mutex v3 +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v316internal_upgradeEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v318internal_downgradeEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_acquire_readerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_acquire_writerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_release_readerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_release_writerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v327internal_try_acquire_readerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v327internal_try_acquire_writerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v318internal_constructEv ) + +// spin_mutex.cpp +__TBB_SYMBOL( _ZN3tbb10spin_mutex11scoped_lock16internal_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb10spin_mutex11scoped_lock16internal_releaseEv ) +__TBB_SYMBOL( _ZN3tbb10spin_mutex11scoped_lock20internal_try_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb10spin_mutex18internal_constructEv ) + +// mutex.cpp +__TBB_SYMBOL( _ZN3tbb5mutex11scoped_lock16internal_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb5mutex11scoped_lock16internal_releaseEv ) +__TBB_SYMBOL( _ZN3tbb5mutex11scoped_lock20internal_try_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb5mutex16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb5mutex18internal_constructEv ) + +// recursive_mutex.cpp +__TBB_SYMBOL( _ZN3tbb15recursive_mutex11scoped_lock16internal_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex11scoped_lock16internal_releaseEv ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex11scoped_lock20internal_try_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex18internal_constructEv ) + +// queuing_mutex.cpp +__TBB_SYMBOL( _ZN3tbb13queuing_mutex11scoped_lock7acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb13queuing_mutex11scoped_lock7releaseEv ) +__TBB_SYMBOL( _ZN3tbb13queuing_mutex11scoped_lock11try_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb13queuing_mutex18internal_constructEv ) + +// critical_section.cpp +__TBB_SYMBOL( _ZN3tbb8internal19critical_section_v418internal_constructEv ) + +#if !TBB_NO_LEGACY +// concurrent_hash_map +__TBB_SYMBOL( _ZNK3tbb8internal21hash_map_segment_base23internal_grow_predicateEv ) + +// concurrent_queue.cpp v2 +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base12internal_popEPv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base13internal_pushEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base21internal_set_capacityElm ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base23internal_pop_if_presentEPv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base25internal_push_if_not_fullEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_baseC2Em ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_baseD2Ev ) +__TBB_SYMBOL( _ZTIN3tbb8internal21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZTSN3tbb8internal21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZTVN3tbb8internal21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_base6assignERKS1_ ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_base7advanceEv ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_baseC2ERKNS0_21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_baseD2Ev ) +__TBB_SYMBOL( _ZNK3tbb8internal21concurrent_queue_base13internal_sizeEv ) +#endif + +// concurrent_queue v3 +// constructors +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v3C2ERKNS0_24concurrent_queue_base_v3E ) +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v3C2ERKNS0_24concurrent_queue_base_v3Em ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v3C2Em ) +// destructors +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v3D2Ev ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v3D2Ev ) +// typeinfo +__TBB_SYMBOL( _ZTIN3tbb8internal24concurrent_queue_base_v3E ) +__TBB_SYMBOL( _ZTSN3tbb8internal24concurrent_queue_base_v3E ) +// vtable +__TBB_SYMBOL( _ZTVN3tbb8internal24concurrent_queue_base_v3E ) +// methods +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v36assignERKS1_ ) +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v37advanceEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v313internal_pushEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v325internal_push_if_not_fullEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v312internal_popEPv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v323internal_pop_if_presentEPv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v314internal_abortEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v321internal_finish_clearEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v321internal_set_capacityElm ) +__TBB_SYMBOL( _ZNK3tbb8internal24concurrent_queue_base_v313internal_sizeEv ) +__TBB_SYMBOL( _ZNK3tbb8internal24concurrent_queue_base_v314internal_emptyEv ) +__TBB_SYMBOL( _ZNK3tbb8internal24concurrent_queue_base_v324internal_throw_exceptionEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v36assignERKS1_ ) + +#if !TBB_NO_LEGACY +// concurrent_vector.cpp v2 +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base13internal_copyERKS1_mPFvPvPKvmE ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base14internal_clearEPFvPvmEb ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base15internal_assignERKS1_mPFvPvmEPFvS4_PKvmESA_ ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base16internal_grow_byEmmPFvPvmE ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base16internal_reserveEmmm ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base18internal_push_backEmRm ) +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base25internal_grow_to_at_leastEmmPFvPvmE ) +__TBB_SYMBOL( _ZNK3tbb8internal22concurrent_vector_base17internal_capacityEv ) +#endif + +// concurrent_vector v3 +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v313internal_copyERKS1_mPFvPvPKvmE ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v314internal_clearEPFvPvmE ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v315internal_assignERKS1_mPFvPvmEPFvS4_PKvmESA_ ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v316internal_grow_byEmmPFvPvPKvmES4_ ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v316internal_reserveEmmm ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v318internal_push_backEmRm ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v325internal_grow_to_at_leastEmmPFvPvPKvmES4_ ) +__TBB_SYMBOL( _ZNK3tbb8internal25concurrent_vector_base_v317internal_capacityEv ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v316internal_compactEmPvPFvS2_mEPFvS2_PKvmE ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v313internal_swapERS1_ ) +__TBB_SYMBOL( _ZNK3tbb8internal25concurrent_vector_base_v324internal_throw_exceptionEm ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v3D2Ev ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v315internal_resizeEmmmPKvPFvPvmEPFvS4_S3_mE ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v337internal_grow_to_at_least_with_resultEmmPFvPvPKvmES4_ ) + +// tbb_thread +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v320hardware_concurrencyEv ) +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v36detachEv ) +__TBB_SYMBOL( _ZN3tbb8internal16thread_get_id_v3Ev ) +__TBB_SYMBOL( _ZN3tbb8internal15free_closure_v3EPv ) +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v34joinEv ) +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v314internal_startEPFPvS2_ES2_ ) +__TBB_SYMBOL( _ZN3tbb8internal19allocate_closure_v3Em ) +__TBB_SYMBOL( _ZN3tbb8internal7move_v3ERNS0_13tbb_thread_v3ES2_ ) +__TBB_SYMBOL( _ZN3tbb8internal15thread_yield_v3Ev ) +__TBB_SYMBOL( _ZN3tbb8internal15thread_sleep_v3ERKNS_10tick_count10interval_tE ) + +#undef __TBB_SYMBOL diff --git a/src/tbb/src/tbb/mailbox.h b/src/tbb/src/tbb/mailbox.h new file mode 100644 index 0000000..00e1785 --- /dev/null +++ b/src/tbb/src/tbb/mailbox.h @@ -0,0 +1,229 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _TBB_mailbox_H +#define _TBB_mailbox_H + +#include "tbb/tbb_stddef.h" +#include "tbb/cache_aligned_allocator.h" + +#include "scheduler_common.h" + +namespace tbb { +namespace internal { + +class generic_scheduler; +class mail_outbox; + +struct task_proxy : public task { + static const intptr_t pool_bit = 1<<0; + static const intptr_t mailbox_bit = 1<<1; + static const intptr_t location_mask = pool_bit | mailbox_bit; + /* All but two low-order bits represent a (task*). + Two low-order bits mean: + 1 = proxy is/was/will be in task pool + 2 = proxy is/was/will be in mailbox */ + intptr_t task_and_tag; + + //! Pointer to next task_proxy in a mailbox + task_proxy *__TBB_atomic next_in_mailbox; + + //! Mailbox to which this was mailed. + mail_outbox* outbox; + + //! True if the proxy is stored both in its sender's pool and in the destination mailbox. + static bool is_shared ( intptr_t tat ) { + return (tat & location_mask) == location_mask; + } + + //! Returns a pointer to the encapsulated task or NULL. + static task* task_ptr ( intptr_t tat ) { + return (task*)(tat & ~location_mask); + } + + //! Returns a pointer to the encapsulated task or NULL, and frees proxy if necessary. + template<intptr_t from_bit> + inline task* extract_task () { + __TBB_ASSERT( prefix().extra_state == es_task_proxy, "Normal task misinterpreted as a proxy?" ); + intptr_t tat = __TBB_load_with_acquire(task_and_tag); + __TBB_ASSERT( tat == from_bit || (is_shared(tat) && task_ptr(tat)), + "Proxy's tag cannot specify both locations if the proxy " + "was retrieved from one of its original locations" ); + if ( tat != from_bit ) { + const intptr_t cleaner_bit = location_mask & ~from_bit; + // Attempt to transition the proxy to the "empty" state with + // cleaner_bit specifying entity responsible for its eventual freeing. + // Explicit cast to void* is to work around a seeming ICC 11.1 bug. + if ( __TBB_CompareAndSwapW( (void*)&task_and_tag, cleaner_bit, tat ) == tat ) { + // Successfully grabbed the task, and left new owner with the job of freeing the proxy + return task_ptr(tat); + } + } + // Proxied task has already been claimed from another proxy location. + __TBB_ASSERT( task_and_tag == from_bit, "Empty proxy cannot contain non-zero task pointer" ); + poison_pointer(outbox); + poison_pointer(next_in_mailbox); + poison_value(task_and_tag); + return NULL; + } +}; // struct task_proxy + +//! Internal representation of mail_outbox, without padding. +class unpadded_mail_outbox { +protected: + typedef task_proxy*__TBB_atomic proxy_ptr; + + //! Pointer to first task_proxy in mailbox, or NULL if box is empty. + proxy_ptr my_first; + + //! Pointer to pointer that will point to next item in the queue. Never NULL. + proxy_ptr* __TBB_atomic my_last; + + //! Owner of mailbox is not executing a task, and has drained its own task pool. + bool my_is_idle; +}; + +//! Class representing where mail is put. +/** Padded to occupy a cache line. */ +class mail_outbox : unpadded_mail_outbox { + char pad[NFS_MaxLineSize-sizeof(unpadded_mail_outbox)]; + + task_proxy* internal_pop() { + task_proxy* const first = __TBB_load_relaxed(my_first); + if( !first ) + return NULL; + __TBB_control_consistency_helper(); // on my_first + // There is a first item in the mailbox. See if there is a second. + if( task_proxy* second = first->next_in_mailbox ) { + // There are at least two items, so first item can be popped easily. + my_first = second; + } else { + // There is only one item. Some care is required to pop it. + my_first = NULL; + if( (proxy_ptr*)__TBB_CompareAndSwapW(&my_last, (intptr_t)&my_first, + (intptr_t)&first->next_in_mailbox) == &first->next_in_mailbox ) + { + // Successfully transitioned mailbox from having one item to having none. + __TBB_ASSERT(!first->next_in_mailbox,NULL); + } else { + // Some other thread updated my_last but has not filled in first->next_in_mailbox + // Wait until first item points to second item. + for( atomic_backoff backoff; !(second = first->next_in_mailbox); backoff.pause() ) {} + my_first = second; + } + } + return first; + } +public: + friend class mail_inbox; + + //! Push task_proxy onto the mailbox queue of another thread. + /** Implementation is wait-free. */ + void push( task_proxy& t ) { + __TBB_ASSERT(&t, NULL); + t.next_in_mailbox = NULL; + proxy_ptr * const link = (proxy_ptr *)__TBB_FetchAndStoreW(&my_last,(intptr_t)&t.next_in_mailbox); + // No release fence required for the next store, because there are no memory operations + // between the previous fully fenced atomic operation and the store. + __TBB_store_relaxed(*link, &t); + } + + //! Construct *this as a mailbox from zeroed memory. + /** Raise assertion if *this is not previously zeroed, or sizeof(this) is wrong. + This method is provided instead of a full constructor since we know the object + will be constructed in zeroed memory. */ + void construct() { + __TBB_ASSERT( sizeof(*this)==NFS_MaxLineSize, NULL ); + __TBB_ASSERT( !my_first, NULL ); + __TBB_ASSERT( !my_last, NULL ); + __TBB_ASSERT( !my_is_idle, NULL ); + my_last=&my_first; + } + + //! Drain the mailbox + intptr_t drain() { + intptr_t k = 0; + // No fences here because other threads have already quit. + for( ; task_proxy* t = my_first; ++k ) { + my_first = t->next_in_mailbox; + NFS_Free((char*)t - task_prefix_reservation_size); + } + return k; + } + + //! True if thread that owns this mailbox is looking for work. + bool recipient_is_idle() { + return my_is_idle; + } +}; // class mail_outbox + +//! Class representing source of mail. +class mail_inbox { + //! Corresponding sink where mail that we receive will be put. + mail_outbox* my_putter; +public: + //! Construct unattached inbox + mail_inbox() : my_putter(NULL) {} + + //! Attach inbox to a corresponding outbox. + void attach( mail_outbox& putter ) { + __TBB_ASSERT(!my_putter,"already attached"); + my_putter = &putter; + } + //! Detach inbox from its outbox + void detach() { + __TBB_ASSERT(my_putter,"not attached"); + my_putter = NULL; + } + //! Get next piece of mail, or NULL if mailbox is empty. + task_proxy* pop() { + return my_putter->internal_pop(); + } + //! Indicate whether thread that reads this mailbox is idle. + /** Raises assertion failure if mailbox is redundantly marked as not idle. */ + void set_is_idle( bool value ) { + if( my_putter ) { + __TBB_ASSERT( my_putter->my_is_idle || value, "attempt to redundantly mark mailbox as not idle" ); + my_putter->my_is_idle = value; + } + } + //! Indicate whether thread that reads this mailbox is idle. + bool is_idle_state ( bool value ) const { + return !my_putter || my_putter->my_is_idle == value; + } + +#if DO_ITT_NOTIFY + //! Get pointer to corresponding outbox used for ITT_NOTIFY calls. + void* outbox() const {return my_putter;} +#endif /* DO_ITT_NOTIFY */ +}; // class mail_inbox + +} // namespace internal +} // namespace tbb + +#endif /* _TBB_mailbox_H */ diff --git a/src/tbb/src/tbb/market.cpp b/src/tbb/src/tbb/market.cpp new file mode 100644 index 0000000..aaec6a5 --- /dev/null +++ b/src/tbb/src/tbb/market.cpp @@ -0,0 +1,594 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/tbb_stddef.h" + +#include "market.h" +#include "tbb_main.h" +#include "governor.h" +#include "scheduler.h" +#include "itt_notify.h" + +namespace tbb { +namespace internal { + +void market::insert_arena_into_list ( arena& a ) { +#if __TBB_TASK_PRIORITY + arena_list_type &arenas = my_priority_levels[a.my_top_priority].arenas; + arena_list_type::iterator &next = my_priority_levels[a.my_top_priority].next_arena; +#else /* !__TBB_TASK_PRIORITY */ + arena_list_type &arenas = my_arenas; + arena_list_type::iterator &next = my_next_arena; +#endif /* !__TBB_TASK_PRIORITY */ + arenas.push_front( a ); + if ( arenas.size() == 1 ) + next = arenas.begin(); +} + +void market::remove_arena_from_list ( arena& a ) { +#if __TBB_TASK_PRIORITY + arena_list_type &arenas = my_priority_levels[a.my_top_priority].arenas; + arena_list_type::iterator &next = my_priority_levels[a.my_top_priority].next_arena; +#else /* !__TBB_TASK_PRIORITY */ + arena_list_type &arenas = my_arenas; + arena_list_type::iterator &next = my_next_arena; +#endif /* !__TBB_TASK_PRIORITY */ + __TBB_ASSERT( next != arenas.end(), NULL ); + if ( &*next == &a ) + if ( ++next == arenas.end() && arenas.size() > 1 ) + next = arenas.begin(); + arenas.remove( a ); +} + +//------------------------------------------------------------------------ +// market +//------------------------------------------------------------------------ + +market::market ( unsigned max_num_workers, size_t stack_size ) + : my_ref_count(1) + , my_stack_size(stack_size) + , my_max_num_workers(max_num_workers) +#if __TBB_TASK_PRIORITY + , my_global_top_priority(normalized_normal_priority) + , my_global_bottom_priority(normalized_normal_priority) +#if __TBB_TRACK_PRIORITY_LEVEL_SATURATION + , my_lowest_populated_level(normalized_normal_priority) +#endif /* __TBB_TRACK_PRIORITY_LEVEL_SATURATION */ +#endif /* __TBB_TASK_PRIORITY */ +{ +#if __TBB_TASK_PRIORITY + __TBB_ASSERT( my_global_reload_epoch == 0, NULL ); + my_priority_levels[normalized_normal_priority].workers_available = max_num_workers; +#endif /* __TBB_TASK_PRIORITY */ + + // Once created RML server will start initializing workers that will need + // global market instance to get worker stack size + my_server = governor::create_rml_server( *this ); + __TBB_ASSERT( my_server, "Failed to create RML server" ); +} + + +market& market::global_market ( unsigned max_num_workers, size_t stack_size ) { + global_market_mutex_type::scoped_lock lock( theMarketMutex ); + market *m = theMarket; + if ( m ) { + ++m->my_ref_count; + if ( m->my_stack_size < stack_size ) + runtime_warning( "Newer master request for larger stack cannot be satisfied\n" ); + } + else { + max_num_workers = max( governor::default_num_threads() - 1, max_num_workers ); + // at least 1 worker is required to support starvation resistant tasks + if( max_num_workers==0 ) max_num_workers = 1; + // Create the global market instance + size_t size = sizeof(market); +#if __TBB_TASK_GROUP_CONTEXT + __TBB_ASSERT( __TBB_offsetof(market, my_workers) + sizeof(generic_scheduler*) == sizeof(market), + "my_workers must be the last data field of the market class"); + size += sizeof(generic_scheduler*) * (max_num_workers - 1); +#endif /* __TBB_TASK_GROUP_CONTEXT */ + __TBB_InitOnce::add_ref(); + void* storage = NFS_Allocate(size, 1, NULL); + memset( storage, 0, size ); + // Initialize and publish global market + m = new (storage) market( max_num_workers, stack_size ); + theMarket = m; + } + return *m; +} + +void market::destroy () { +#if __TBB_COUNT_TASK_NODES + if ( my_task_node_count ) + runtime_warning( "Leaked %ld task objects\n", (long)my_task_node_count ); +#endif /* __TBB_COUNT_TASK_NODES */ + this->~market(); + NFS_Free( this ); + __TBB_InitOnce::remove_ref(); +} + +void market::release () { + __TBB_ASSERT( theMarket == this, "Global market instance was destroyed prematurely?" ); + bool do_release = false; + { + global_market_mutex_type::scoped_lock lock(theMarketMutex); + if ( --my_ref_count == 0 ) { + do_release = true; + theMarket = NULL; + } + } + if( do_release ) + my_server->request_close_connection(); +} + +arena& market::create_arena ( unsigned max_num_workers, size_t stack_size ) { + market &m = global_market( max_num_workers, stack_size ); // increases market's ref count + arena& a = arena::allocate_arena( m, min(max_num_workers, m.my_max_num_workers) ); + // Add newly created arena into the existing market's list. + spin_mutex::scoped_lock lock(m.my_arenas_list_mutex); + m.insert_arena_into_list(a); + return a; +} + +/** This method must be invoked under my_arenas_list_mutex. **/ +void market::detach_arena ( arena& a ) { + __TBB_ASSERT( theMarket == this, "Global market instance was destroyed prematurely?" ); +#if __TBB_TRACK_PRIORITY_LEVEL_SATURATION + __TBB_ASSERT( !a.my_num_workers_present, NULL ); +#endif /* __TBB_TRACK_PRIORITY_LEVEL_SATURATION */ + __TBB_ASSERT( !a.my_slots[0].my_scheduler, NULL ); + remove_arena_from_list(a); + if ( a.my_aba_epoch == my_arenas_aba_epoch ) + ++my_arenas_aba_epoch; +} + +void market::try_destroy_arena ( arena* a, uintptr_t aba_epoch ) { + __TBB_ASSERT ( a, NULL ); + spin_mutex::scoped_lock lock(my_arenas_list_mutex); + assert_market_valid(); +#if __TBB_TASK_PRIORITY + for ( int p = my_global_top_priority; p >= my_global_bottom_priority; --p ) { + priority_level_info &pl = my_priority_levels[p]; + arena_list_type &my_arenas = pl.arenas; +#endif /* __TBB_TASK_PRIORITY */ + arena_list_type::iterator it = my_arenas.begin(); + for ( ; it != my_arenas.end(); ++it ) { + if ( a == &*it ) { + if ( it->my_aba_epoch == aba_epoch ) { + // Arena is alive + if ( !a->my_num_workers_requested && !a->my_num_threads_active ) { + __TBB_ASSERT( !a->my_num_workers_allotted && (a->my_pool_state == arena::SNAPSHOT_EMPTY || !a->my_max_num_workers), "Inconsistent arena state" ); + // Arena is abandoned. Destroy it. + detach_arena( *a ); + lock.release(); + a->free_arena(); + } + } + return; + } + } +#if __TBB_TASK_PRIORITY + } +#endif /* __TBB_TASK_PRIORITY */ +} + +void market::try_destroy_arena ( market* m, arena* a, uintptr_t aba_epoch, bool master ) { + // Arena may have been orphaned. Or it may have been destroyed. + // Thus we cannot dereference the pointer to it until its liveness is verified. + // Arena is alive if it is found in the market's list. + + if ( m != theMarket ) { + // The market has already been emptied. + return; + } + else if ( master ) { + // If this is a master thread, market can be destroyed at any moment. + // So protect it with an extra refcount. + global_market_mutex_type::scoped_lock lock(theMarketMutex); + if ( m != theMarket ) + return; + ++m->my_ref_count; + } + m->try_destroy_arena( a, aba_epoch ); + if ( master ) + m->release(); +} + +/** This method must be invoked under my_arenas_list_mutex. **/ +arena* market::arena_in_need ( arena_list_type &arenas, arena_list_type::iterator& next ) { + if ( arenas.empty() ) + return NULL; + __TBB_ASSERT( next != arenas.end(), NULL ); + arena_list_type::iterator it = next; + do { + arena& a = *it; + if ( ++it == arenas.end() ) + it = arenas.begin(); + if ( a.num_workers_active() < a.my_num_workers_allotted ) { + ++a.my_num_threads_active; +#if __TBB_TRACK_PRIORITY_LEVEL_SATURATION + ++a.my_num_workers_present; + ++my_priority_levels[a.my_top_priority].workers_present; +#endif /* __TBB_TRACK_PRIORITY_LEVEL_SATURATION */ + next = it; + return &a; + } + } while ( it != next ); + return NULL; +} + +void market::update_allotment ( arena_list_type& arenas, int workers_demand, int max_workers ) { + __TBB_ASSERT( workers_demand, NULL ); + max_workers = min(workers_demand, max_workers); + int carry = 0; +#if TBB_USE_ASSERT + int assigned = 0; +#endif /* TBB_USE_ASSERT */ + arena_list_type::iterator it = arenas.begin(); + for ( ; it != arenas.end(); ++it ) { + arena& a = *it; + if ( a.my_num_workers_requested <= 0 ) { + __TBB_ASSERT( !a.my_num_workers_allotted, NULL ); + continue; + } + int tmp = a.my_num_workers_requested * max_workers + carry; + int allotted = tmp / workers_demand; + carry = tmp % workers_demand; + // a.my_num_workers_requested may temporarily exceed a.my_max_num_workers + a.my_num_workers_allotted = min( allotted, (int)a.my_max_num_workers ); +#if TBB_USE_ASSERT + assigned += a.my_num_workers_allotted; +#endif /* TBB_USE_ASSERT */ + } + __TBB_ASSERT( assigned <= workers_demand, NULL ); +} + +#if __TBB_TASK_PRIORITY +inline void market::update_global_top_priority ( intptr_t newPriority ) { + GATHER_STATISTIC( ++governor::local_scheduler_if_initialized()->my_counters.market_prio_switches ); + my_global_top_priority = newPriority; + my_priority_levels[newPriority].workers_available = my_max_num_workers; + advance_global_reload_epoch(); +} + +inline void market::reset_global_priority () { + my_global_bottom_priority = normalized_normal_priority; + update_global_top_priority(normalized_normal_priority); +#if __TBB_TRACK_PRIORITY_LEVEL_SATURATION + my_lowest_populated_level = normalized_normal_priority; +#endif /* __TBB_TRACK_PRIORITY_LEVEL_SATURATION */ +} + +arena* market::arena_in_need ( +#if __TBB_TRACK_PRIORITY_LEVEL_SATURATION + arena* prev_arena +#endif /* __TBB_TRACK_PRIORITY_LEVEL_SATURATION */ + ) +{ + spin_mutex::scoped_lock lock(my_arenas_list_mutex); + assert_market_valid(); +#if __TBB_TRACK_PRIORITY_LEVEL_SATURATION + if ( prev_arena ) { + priority_level_info &pl = my_priority_levels[prev_arena->my_top_priority]; + --prev_arena->my_num_workers_present; + --pl.workers_present; + if ( !--prev_arena->my_num_threads_active && !prev_arena->my_num_workers_requested ) { + detach_arena( *a ); + lock.release(); + a->free_arena(); + lock.acquire(); + } + } +#endif /* __TBB_TRACK_PRIORITY_LEVEL_SATURATION */ + int p = my_global_top_priority; + arena *a = NULL; + do { + priority_level_info &pl = my_priority_levels[p]; +#if __TBB_TRACK_PRIORITY_LEVEL_SATURATION + __TBB_ASSERT( p >= my_lowest_populated_level, NULL ); + if ( pl.workers_present >= pl.workers_requested ) + continue; +#endif /* __TBB_TRACK_PRIORITY_LEVEL_SATURATION */ + a = arena_in_need( pl.arenas, pl.next_arena ); + } while ( !a && --p >= my_global_bottom_priority ); + return a; +} + +void market::update_allotment ( intptr_t highest_affected_priority ) { + intptr_t i = highest_affected_priority; + int available = my_priority_levels[i].workers_available; +#if __TBB_TRACK_PRIORITY_LEVEL_SATURATION + my_lowest_populated_level = my_global_bottom_priority; +#endif /* __TBB_TRACK_PRIORITY_LEVEL_SATURATION */ + for ( ; i >= my_global_bottom_priority; --i ) { + priority_level_info &pl = my_priority_levels[i]; + pl.workers_available = available; + if ( pl.workers_requested ) { + update_allotment( pl.arenas, pl.workers_requested, available ); + available -= pl.workers_requested; + if ( available < 0 ) { + available = 0; +#if __TBB_TRACK_PRIORITY_LEVEL_SATURATION + my_lowest_populated_level = i; +#endif /* __TBB_TRACK_PRIORITY_LEVEL_SATURATION */ + break; + } + } + } + __TBB_ASSERT( i <= my_global_bottom_priority || !available, NULL ); + for ( --i; i >= my_global_bottom_priority; --i ) { + priority_level_info &pl = my_priority_levels[i]; + pl.workers_available = 0; + arena_list_type::iterator it = pl.arenas.begin(); + for ( ; it != pl.arenas.end(); ++it ) { + __TBB_ASSERT( it->my_num_workers_requested || !it->my_num_workers_allotted, NULL ); + it->my_num_workers_allotted = 0; + } + } +} +#endif /* __TBB_TASK_PRIORITY */ + +void market::adjust_demand ( arena& a, int delta ) { + __TBB_ASSERT( theMarket, "market instance was destroyed prematurely?" ); + if ( !delta ) + return; + my_arenas_list_mutex.lock(); + int prev_req = a.my_num_workers_requested; + a.my_num_workers_requested += delta; + if ( a.my_num_workers_requested <= 0 ) { + a.my_num_workers_allotted = 0; + if ( prev_req <= 0 ) { + my_arenas_list_mutex.unlock(); + return; + } + delta = -prev_req; + } + __TBB_ASSERT( prev_req >= 0, "Part-size request to RML?" ); +#if __TBB_TASK_PRIORITY + intptr_t p = a.my_top_priority; + priority_level_info &pl = my_priority_levels[p]; + pl.workers_requested += delta; + __TBB_ASSERT( pl.workers_requested >= 0, NULL ); + __TBB_ASSERT( a.my_num_workers_requested >= 0, NULL ); + if ( a.my_num_workers_requested <= 0 ) { + if ( a.my_top_priority != normalized_normal_priority ) { + GATHER_STATISTIC( ++governor::local_scheduler_if_initialized()->my_counters.arena_prio_resets ); + update_arena_top_priority( a, normalized_normal_priority ); + } + a.my_bottom_priority = normalized_normal_priority; + } + if ( p == my_global_top_priority ) { + if ( !pl.workers_requested ) { + while ( --p >= my_global_bottom_priority && !my_priority_levels[p].workers_requested ) + continue; + if ( p < my_global_bottom_priority ) + reset_global_priority(); + else + update_global_top_priority(p); + } + update_allotment( my_global_top_priority ); + } + else if ( p > my_global_top_priority ) { + __TBB_ASSERT( pl.workers_requested > 0, NULL ); + update_global_top_priority(p); + a.my_num_workers_allotted = min( (int)my_max_num_workers, a.my_num_workers_requested ); + my_priority_levels[p - 1].workers_available = my_max_num_workers - a.my_num_workers_allotted; + update_allotment( p - 1 ); + } + else if ( p == my_global_bottom_priority ) { + if ( !pl.workers_requested ) { + while ( ++p <= my_global_top_priority && !my_priority_levels[p].workers_requested ) + continue; + if ( p > my_global_top_priority ) + reset_global_priority(); + else { + my_global_bottom_priority = p; +#if __TBB_TRACK_PRIORITY_LEVEL_SATURATION + my_lowest_populated_level = max( my_lowest_populated_level, p ); +#endif /* __TBB_TRACK_PRIORITY_LEVEL_SATURATION */ + } + } + else + update_allotment( p ); + } + else if ( p < my_global_bottom_priority ) { + __TBB_ASSERT( a.my_num_workers_requested > 0, NULL ); + int prev_bottom = my_global_bottom_priority; + my_global_bottom_priority = p; + update_allotment( prev_bottom ); + } + else { + __TBB_ASSERT( my_global_bottom_priority < p && p < my_global_top_priority, NULL ); + update_allotment( p ); + } + assert_market_valid(); +#else /* !__TBB_TASK_PRIORITY */ + my_total_demand += delta; + update_allotment(); +#endif /* !__TBB_TASK_PRIORITY */ + my_arenas_list_mutex.unlock(); + // Must be called outside of any locks + my_server->adjust_job_count_estimate( delta ); + GATHER_STATISTIC( governor::local_scheduler_if_initialized() ? ++governor::local_scheduler_if_initialized()->my_counters.gate_switches : 0 ); +} + +void market::process( job& j ) { + generic_scheduler& s = static_cast<generic_scheduler&>(j); + __TBB_ASSERT( governor::is_set(&s), NULL ); +#if __TBB_TRACK_PRIORITY_LEVEL_SATURATION + arena *a = NULL; + while ( (a = arena_in_need(a)) ) +#else + while ( arena *a = arena_in_need() ) +#endif + a->process(s); + GATHER_STATISTIC( ++s.my_counters.market_roundtrips ); +} + +void market::cleanup( job& j ) { + __TBB_ASSERT( theMarket != this, NULL ); + generic_scheduler& s = static_cast<generic_scheduler&>(j); + generic_scheduler* mine = governor::local_scheduler_if_initialized(); + __TBB_ASSERT( !mine || mine->my_arena_index!=0, NULL ); + if( mine!=&s ) { + governor::assume_scheduler( &s ); + generic_scheduler::cleanup_worker( &s, mine!=NULL ); + governor::assume_scheduler( mine ); + } else { + generic_scheduler::cleanup_worker( &s, true ); + } +} + +void market::acknowledge_close_connection() { + destroy(); +} + +::rml::job* market::create_one_job() { + unsigned index = ++my_num_workers; + __TBB_ASSERT( index > 0, NULL ); + ITT_THREAD_SET_NAME(_T("TBB Worker Thread")); + // index serves as a hint decreasing conflicts between workers when they migrate between arenas + generic_scheduler* s = generic_scheduler::create_worker( *this, index ); +#if __TBB_TASK_GROUP_CONTEXT + __TBB_ASSERT( !my_workers[index - 1], NULL ); + my_workers[index - 1] = s; +#endif /* __TBB_TASK_GROUP_CONTEXT */ + governor::sign_on(s); + return s; +} + +#if __TBB_TASK_PRIORITY +void market::update_arena_top_priority ( arena& a, intptr_t new_priority ) { + GATHER_STATISTIC( ++governor::local_scheduler_if_initialized()->my_counters.arena_prio_switches ); + __TBB_ASSERT( a.my_top_priority != new_priority, NULL ); + priority_level_info &prev_level = my_priority_levels[a.my_top_priority], + &new_level = my_priority_levels[new_priority]; + remove_arena_from_list(a); + a.my_top_priority = new_priority; + insert_arena_into_list(a); + ++a.my_reload_epoch; +#if __TBB_TRACK_PRIORITY_LEVEL_SATURATION + // Arena's my_num_workers_present may remain positive for some time after its + // my_num_workers_requested becomes zero. Thus the following two lines are + // executed unconditionally. + prev_level.workers_present -= a.my_num_workers_present; + new_level.workers_present += a.my_num_workers_present; +#endif /* __TBB_TRACK_PRIORITY_LEVEL_SATURATION */ + prev_level.workers_requested -= a.my_num_workers_requested; + new_level.workers_requested += a.my_num_workers_requested; + __TBB_ASSERT( prev_level.workers_requested >= 0 && new_level.workers_requested >= 0, NULL ); +} + +bool market::lower_arena_priority ( arena& a, intptr_t new_priority, intptr_t old_priority ) { + spin_mutex::scoped_lock lock(my_arenas_list_mutex); + if ( a.my_top_priority != old_priority ) { + assert_market_valid(); + return false; + } + __TBB_ASSERT( a.my_top_priority > new_priority, NULL ); + __TBB_ASSERT( my_global_top_priority >= a.my_top_priority, NULL ); + intptr_t p = a.my_top_priority; + update_arena_top_priority( a, new_priority ); + if ( a.my_num_workers_requested > 0 ) { + if ( my_global_bottom_priority > new_priority ) { + my_global_bottom_priority = new_priority; + } + if ( p == my_global_top_priority && !my_priority_levels[p].workers_requested ) { + // Global top level became empty + for ( --p; !my_priority_levels[p].workers_requested; --p ) continue; + __TBB_ASSERT( p >= my_global_bottom_priority, NULL ); + update_global_top_priority(p); + } + update_allotment( p ); + } + assert_market_valid(); + return true; +} + +bool market::update_arena_priority ( arena& a, intptr_t new_priority ) { + spin_mutex::scoped_lock lock(my_arenas_list_mutex); + if ( a.my_top_priority == new_priority ) { + assert_market_valid(); + return false; + } + else if ( a.my_top_priority > new_priority ) { + if ( a.my_bottom_priority > new_priority ) + a.my_bottom_priority = new_priority; + assert_market_valid(); + return false; + } + intptr_t p = a.my_top_priority; + intptr_t highest_affected_level = max(p, new_priority); + update_arena_top_priority( a, new_priority ); + if ( a.my_num_workers_requested > 0 ) { + if ( my_global_top_priority < new_priority ) { + update_global_top_priority(new_priority); + } + else if ( my_global_top_priority == new_priority ) { + advance_global_reload_epoch(); + } + else { + __TBB_ASSERT( new_priority < my_global_top_priority, NULL ); + __TBB_ASSERT( new_priority > my_global_bottom_priority, NULL ); + if ( p == my_global_top_priority && !my_priority_levels[p].workers_requested ) { + // Global top level became empty + __TBB_ASSERT( my_global_bottom_priority < p, NULL ); + for ( --p; !my_priority_levels[p].workers_requested; --p ) continue; + __TBB_ASSERT( p >= new_priority, NULL ); + update_global_top_priority(p); + highest_affected_level = p; + } + } + if ( p == my_global_bottom_priority ) { + // Arena priority was increased from the global bottom level. + __TBB_ASSERT( p < new_priority, NULL ); // n + __TBB_ASSERT( new_priority <= my_global_top_priority, NULL ); + while ( !my_priority_levels[my_global_bottom_priority].workers_requested ) + ++my_global_bottom_priority; + __TBB_ASSERT( my_global_bottom_priority <= new_priority, NULL ); + __TBB_ASSERT( my_priority_levels[my_global_bottom_priority].workers_requested > 0, NULL ); + } + update_allotment( highest_affected_level ); + } + assert_market_valid(); + return true; +} +#endif /* __TBB_TASK_PRIORITY */ + +#if __TBB_COUNT_TASK_NODES +intptr_t market::workers_task_node_count() { + intptr_t result = 0; + ForEachArena(a) { + result += a.workers_task_node_count(); + } EndForEach(); + return result; +} +#endif /* __TBB_COUNT_TASK_NODES */ + +} // namespace internal +} // namespace tbb diff --git a/src/tbb/src/tbb/market.h b/src/tbb/src/tbb/market.h new file mode 100644 index 0000000..5873e44 --- /dev/null +++ b/src/tbb/src/tbb/market.h @@ -0,0 +1,367 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _TBB_market_H +#define _TBB_market_H + +#include "tbb/tbb_stddef.h" + +#include "scheduler_common.h" +#include "tbb/atomic.h" +#include "tbb/spin_mutex.h" +#include "../rml/include/rml_tbb.h" + +#include "intrusive_list.h" + +#if defined(_MSC_VER) && defined(_Wp64) + // Workaround for overzealous compiler warnings in /Wp64 mode + #pragma warning (push) + #pragma warning (disable: 4244) +#endif + +namespace tbb { + +class task_group_context; + +namespace internal { + +class arena; +class generic_scheduler; +template<typename SchedulerTraits> class custom_scheduler; + +//------------------------------------------------------------------------ +// Class market +//------------------------------------------------------------------------ + +class market : no_copy, rml::tbb_client { + friend class generic_scheduler; + friend class arena; + template<typename SchedulerTraits> friend class custom_scheduler; + friend class tbb::task_group_context; +private: + friend void ITT_DoUnsafeOneTimeInitialization (); + + typedef intrusive_list<arena> arena_list_type; + + //! Currently active global market + static market* theMarket; + + typedef spin_mutex global_market_mutex_type; + + //! Mutex guarding creation/destruction of theMarket, insertions/deletions in my_arenas, and cancellation propagation + static global_market_mutex_type theMarketMutex; + + //! Reference count controlling market object lifetime + intptr_t my_ref_count; + + //! Lightweight mutex guarding accounting operations with arenas list + spin_mutex my_arenas_list_mutex; + + //! Pointer to the RML server object that services this TBB instance. + rml::tbb_server* my_server; + + //! Stack size of worker threads + size_t my_stack_size; + + //! Number of workers requested from the underlying resource manager + unsigned my_max_num_workers; + + //! Number of workers that have been delivered by RML + /** Used to assign indices to the new workers coming from RML, and busy part + of my_workers array. **/ + atomic<unsigned> my_num_workers; + +#if __TBB_TASK_PRIORITY + //! Highest priority among active arenas in the market. + /** Arena priority level is its tasks highest priority (specified by arena's + my_top_priority member). + Arena is active when it has outstanding request for workers. Note that + inactive arena may have workers lingering there for some time. **/ + intptr_t my_global_top_priority; + + //! Lowest priority among active arenas in the market. + /** See also my_global_top_priority **/ + intptr_t my_global_bottom_priority; + + //! Tracks events that may bring tasks in offload areas to the top priority level. + /** Incremented when global top priority is decremented or a task group priority + is elevated to the current top level. **/ + uintptr_t my_global_reload_epoch; + + //! Information about arenas at a particular priority level + struct priority_level_info { + //! List of arenas at this priority level + arena_list_type arenas; + + //! The first arena to be checked when idle worker seeks for an arena to enter + /** The check happens in round-robin fashion. **/ + arena_list_type::iterator next_arena; + + //! Total amount of workers requested by arenas at this priority level. + int workers_requested; + + //! Maximal amount of workers the market can tell off to this priority level. + int workers_available; + +#if __TBB_TRACK_PRIORITY_LEVEL_SATURATION + //! Total amount of workers that are in arenas at this priority level. + int workers_present; +#endif /* __TBB_TRACK_PRIORITY_LEVEL_SATURATION */ + }; // struct priority_level_info + + //! Information about arenas at different priority levels + priority_level_info my_priority_levels[num_priority_levels]; + +#if __TBB_TRACK_PRIORITY_LEVEL_SATURATION + //! Lowest priority level having workers available. + intptr_t my_lowest_populated_level; +#endif /* __TBB_TRACK_PRIORITY_LEVEL_SATURATION */ + +#else /* !__TBB_TASK_PRIORITY */ + + //! List of registered arenas + arena_list_type my_arenas; + + //! The first arena to be checked when idle worker seeks for an arena to enter + /** The check happens in round-robin fashion. **/ + arena_list_type::iterator my_next_arena; + + //! Number of workers that were requested by all arenas + int my_total_demand; +#endif /* !__TBB_TASK_PRIORITY */ + + //! ABA prevention marker to assign to newly created arenas + uintptr_t my_arenas_aba_epoch; + +#if __TBB_COUNT_TASK_NODES + //! Net number of nodes that have been allocated from heap. + /** Updated each time a scheduler or arena is destroyed. */ + atomic<intptr_t> my_task_node_count; +#endif /* __TBB_COUNT_TASK_NODES */ + + //! Constructor + market ( unsigned max_num_workers, size_t stack_size ); + + //! Factory method creating new market object + static market& global_market ( unsigned max_num_workers, size_t stack_size ); + + //! Destroys and deallocates market object created by market::create() + void destroy (); + + void try_destroy_arena ( arena*, uintptr_t aba_epoch ); + +#if __TBB_TASK_PRIORITY + //! Returns next arena that needs more workers, or NULL. + arena* arena_in_need ( +#if __TBB_TRACK_PRIORITY_LEVEL_SATURATION + arena* prev_arena +#endif /* __TBB_TRACK_PRIORITY_LEVEL_SATURATION */ + ); + + //! Recalculates the number of workers assigned to each arena at and below the specified priority. + /** The actual number of workers servicing a particular arena may temporarily + deviate from the calculated value. **/ + void update_allotment ( intptr_t highest_affected_priority ); + + //! Changes arena's top priority and updates affected priority levels info in the market. + void update_arena_top_priority ( arena& a, intptr_t newPriority ); + + //! Changes market's global top priority and related settings. + inline void update_global_top_priority ( intptr_t newPriority ); + + //! Resets empty market's global top and bottom priority to the normal level. + inline void reset_global_priority (); + + inline void advance_global_reload_epoch () { + __TBB_store_with_release( my_global_reload_epoch, my_global_reload_epoch + 1 ); + } + + void assert_market_valid () const { + __TBB_ASSERT( (my_priority_levels[my_global_top_priority].workers_requested > 0 + && !my_priority_levels[my_global_top_priority].arenas.empty()) + || (my_global_top_priority == my_global_bottom_priority && + my_global_top_priority == normalized_normal_priority), NULL ); + } + +#else /* !__TBB_TASK_PRIORITY */ + + //! Recalculates the number of workers assigned to each arena in the list. + /** The actual number of workers servicing a particular arena may temporarily + deviate from the calculated value. **/ + void update_allotment () { + if ( my_total_demand ) + update_allotment( my_arenas, my_total_demand, (int)my_max_num_workers ); + } + + //! Returns next arena that needs more workers, or NULL. + arena* arena_in_need () { + spin_mutex::scoped_lock lock(my_arenas_list_mutex); + return arena_in_need(my_arenas, my_next_arena); + } + void assert_market_valid () const {} +#endif /* !__TBB_TASK_PRIORITY */ + + //! Returns number of masters doing computational (CPU-intensive) work + int num_active_masters () { return 1; } // APM TODO: replace with a real mechanism + + + //////////////////////////////////////////////////////////////////////////////// + // Helpers to unify code branches dependent on priority feature presence + + void insert_arena_into_list ( arena& a ); + + void remove_arena_from_list ( arena& a ); + + arena* arena_in_need ( arena_list_type &arenas, arena_list_type::iterator& next ); + + static void update_allotment ( arena_list_type& arenas, int total_demand, int max_workers ); + + + //////////////////////////////////////////////////////////////////////////////// + // Implementation of rml::tbb_client interface methods + + /*override*/ version_type version () const { return 0; } + + /*override*/ unsigned max_job_count () const { return my_max_num_workers; } + + /*override*/ size_t min_stack_size () const { return worker_stack_size(); } + + /*override*/ policy_type policy () const { return throughput; } + + /*override*/ job* create_one_job (); + + /*override*/ void cleanup( job& j ); + + /*override*/ void acknowledge_close_connection (); + + /*override*/ void process( job& j ); + +public: + //! Creates an arena object + /** If necessary, also creates global market instance, and boosts its ref count. + Each call to create_arena() must be matched by the call to arena::free_arena(). **/ + static arena& create_arena ( unsigned max_num_workers, size_t stack_size ); + + //! Removes the arena from the market's list + static void try_destroy_arena ( market*, arena*, uintptr_t aba_epoch, bool master ); + + //! Removes the arena from the market's list + void detach_arena ( arena& ); + + //! Decrements market's refcount and destroys it in the end + void release (); + + //! Request that arena's need in workers should be adjusted. + /** Concurrent invocations are possible only on behalf of different arenas. **/ + void adjust_demand ( arena&, int delta ); + + //! Returns the requested stack size of worker threads. + size_t worker_stack_size () const { return my_stack_size; } + +#if _WIN32||_WIN64 + //! register master with the resource manager + void register_master( ::rml::server::execution_resource_t& rsc_handle ) { + __TBB_ASSERT( my_server, "RML server not defined?" ); + // the server may ignore registration and set master_exec_resource to NULL. + my_server->register_master( rsc_handle ); + } + + //! unregister master with the resource manager + void unregister_master( ::rml::server::execution_resource_t& rsc_handle ) const { + my_server->unregister_master( rsc_handle ); + } +#endif /* WIN */ + +#if __TBB_TASK_GROUP_CONTEXT + //! Finds all contexts affected by the state change and propagates the new state to them. + template <typename T> + bool propagate_task_group_state ( T task_group_context::*mptr_state, task_group_context& src, T new_state ); +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +#if __TBB_TASK_PRIORITY + //! Lowers arena's priority is not higher than newPriority + /** Returns true if arena priority was actually elevated. **/ + bool lower_arena_priority ( arena& a, intptr_t new_priority, intptr_t old_priority ); + + //! Makes sure arena's priority is not lower than newPriority + /** Returns true if arena priority was elevated. Also updates arena's bottom + priority boundary if necessary. + + This method is called whenever a user changes priority, because whether + it was hiked or sunk can be determined for sure only under the lock used + by this function. **/ + bool update_arena_priority ( arena& a, intptr_t new_priority ); +#endif /* __TBB_TASK_PRIORITY */ + +#if __TBB_COUNT_TASK_NODES + //! Returns the number of task objects "living" in worker threads + intptr_t workers_task_node_count(); + + //! Net number of nodes that have been allocated from heap. + /** Updated each time a scheduler or arena is destroyed. */ + void update_task_node_count( intptr_t delta ) { my_task_node_count += delta; } +#endif /* __TBB_COUNT_TASK_NODES */ + +#if __TBB_TASK_GROUP_CONTEXT + //! Array of pointers to the registered workers + /** Used by cancellation propagation mechanism. + Must be the last data member of the class market. **/ + generic_scheduler* my_workers[1]; +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +}; // class market + +#if __TBB_TASK_PRIORITY + #define BeginForEachArena(a) \ + spin_mutex::scoped_lock arena_list_lock(my_arenas_list_mutex); \ + for ( intptr_t i = my_global_top_priority; i >= my_global_bottom_priority; --i ) { \ + /*spin_mutex::scoped_lock arena_list_lock(my_priority_levels[i].my_arenas_list_mutex);*/ \ + arena_list_type &arenas = my_priority_levels[i].arenas; +#else /* !__TBB_TASK_PRIORITY */ + #define BeginForEachArena(a) \ + arena_list_type &arenas = my_arenas; { +#endif /* !__TBB_TASK_PRIORITY */ + +#define ForEachArena(a) \ + BeginForEachArena(a) \ + arena_list_type::iterator it = arenas.begin(); \ + for ( ; it != arenas.end(); ++it ) { \ + arena &a = *it; + +#define EndForEach() }} + + +} // namespace internal +} // namespace tbb + +#if defined(_MSC_VER) && defined(_Wp64) + // Workaround for overzealous compiler warnings in /Wp64 mode + #pragma warning (pop) +#endif // warning 4244 is back + +#endif /* _TBB_market_H */ diff --git a/src/tbb/src/tbb/mutex.cpp b/src/tbb/src/tbb/mutex.cpp new file mode 100644 index 0000000..139163c --- /dev/null +++ b/src/tbb/src/tbb/mutex.cpp @@ -0,0 +1,148 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/mutex.h" +#include "itt_notify.h" + +namespace tbb { + void mutex::scoped_lock::internal_acquire( mutex& m ) { + +#if _WIN32||_WIN64 + switch( m.state ) { + case INITIALIZED: + case HELD: + EnterCriticalSection( &m.impl ); + // If a thread comes here, and another thread holds the lock, it will block + // in EnterCriticalSection. When it returns from EnterCriticalSection, + // m.state must be set to INITIALIZED. If the same thread tries to acquire a lock it + // aleady holds, the the lock is in HELD state, thus will cause the assertion to fail. + __TBB_ASSERT(m.state!=HELD, "mutex::scoped_lock: deadlock caused by attempt to reacquire held mutex"); + m.state = HELD; + break; + case DESTROYED: + __TBB_ASSERT(false,"mutex::scoped_lock: mutex already destroyed"); + break; + default: + __TBB_ASSERT(false,"mutex::scoped_lock: illegal mutex state"); + break; + } +#else + int error_code = pthread_mutex_lock(&m.impl); + __TBB_ASSERT_EX(!error_code,"mutex::scoped_lock: pthread_mutex_lock failed"); +#endif /* _WIN32||_WIN64 */ + my_mutex = &m; + } + +void mutex::scoped_lock::internal_release() { + __TBB_ASSERT( my_mutex, "mutex::scoped_lock: not holding a mutex" ); +#if _WIN32||_WIN64 + switch( my_mutex->state ) { + case INITIALIZED: + __TBB_ASSERT(false,"mutex::scoped_lock: try to release the lock without acquisition"); + break; + case HELD: + my_mutex->state = INITIALIZED; + LeaveCriticalSection(&my_mutex->impl); + break; + case DESTROYED: + __TBB_ASSERT(false,"mutex::scoped_lock: mutex already destroyed"); + break; + default: + __TBB_ASSERT(false,"mutex::scoped_lock: illegal mutex state"); + break; + } +#else + int error_code = pthread_mutex_unlock(&my_mutex->impl); + __TBB_ASSERT_EX(!error_code, "mutex::scoped_lock: pthread_mutex_unlock failed"); +#endif /* _WIN32||_WIN64 */ + my_mutex = NULL; +} + +bool mutex::scoped_lock::internal_try_acquire( mutex& m ) { +#if _WIN32||_WIN64 + switch( m.state ) { + case INITIALIZED: + case HELD: + break; + case DESTROYED: + __TBB_ASSERT(false,"mutex::scoped_lock: mutex already destroyed"); + break; + default: + __TBB_ASSERT(false,"mutex::scoped_lock: illegal mutex state"); + break; + } +#endif /* _WIN32||_WIN64 */ + + bool result; +#if _WIN32||_WIN64 + result = TryEnterCriticalSection(&m.impl)!=0; + if( result ) { + __TBB_ASSERT(m.state!=HELD, "mutex::scoped_lock: deadlock caused by attempt to reacquire held mutex"); + m.state = HELD; + } +#else + result = pthread_mutex_trylock(&m.impl)==0; +#endif /* _WIN32||_WIN64 */ + if( result ) + my_mutex = &m; + return result; +} + +void mutex::internal_construct() { +#if _WIN32||_WIN64 + InitializeCriticalSection(&impl); + state = INITIALIZED; +#else + int error_code = pthread_mutex_init(&impl,NULL); + if( error_code ) + tbb::internal::handle_perror(error_code,"mutex: pthread_mutex_init failed"); +#endif /* _WIN32||_WIN64*/ + ITT_SYNC_CREATE(&impl, _T("tbb::mutex"), _T("")); +} + +void mutex::internal_destroy() { +#if _WIN32||_WIN64 + switch( state ) { + case INITIALIZED: + DeleteCriticalSection(&impl); + break; + case DESTROYED: + __TBB_ASSERT(false,"mutex: already destroyed"); + break; + default: + __TBB_ASSERT(false,"mutex: illegal state for destruction"); + break; + } + state = DESTROYED; +#else + int error_code = pthread_mutex_destroy(&impl); + __TBB_ASSERT_EX(!error_code,"mutex: pthread_mutex_destroy failed"); +#endif /* _WIN32||_WIN64 */ +} + +} // namespace tbb diff --git a/src/tbb/src/tbb/observer_proxy.cpp b/src/tbb/src/tbb/observer_proxy.cpp new file mode 100644 index 0000000..a08e347 --- /dev/null +++ b/src/tbb/src/tbb/observer_proxy.cpp @@ -0,0 +1,237 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/tbb_config.h" + +#if __TBB_SCHEDULER_OBSERVER + +#include "tbb/spin_rw_mutex.h" +#include "tbb/aligned_space.h" + +#include "observer_proxy.h" +#include "tbb_main.h" +#include "governor.h" +#include "scheduler.h" + +namespace tbb { +namespace internal { + +typedef spin_rw_mutex::scoped_lock task_scheduler_observer_mutex_scoped_lock; + +/** aligned_space used here to shut up warnings when mutex destructor is called while threads are still using it. */ +static aligned_space<spin_rw_mutex,1> the_task_scheduler_observer_mutex; +static observer_proxy* global_first_observer_proxy; +observer_proxy* global_last_observer_proxy; + + +#if TBB_USE_ASSERT +static atomic<int> observer_proxy_count; + +struct check_observer_proxy_count { + ~check_observer_proxy_count() { + if( observer_proxy_count!=0 ) { + runtime_warning( "Leaked %ld observer_proxy objects\n", long(observer_proxy_count) ); + } + } +}; + +static check_observer_proxy_count the_check_observer_proxy_count; +#endif /* TBB_USE_ASSERT */ + +observer_proxy::observer_proxy( task_scheduler_observer_v3& tso ) : next(NULL), observer(&tso) { +#if TBB_USE_ASSERT + ++observer_proxy_count; +#endif /* TBB_USE_ASSERT */ + // 1 for observer + gc_ref_count = 1; + { + // Append to the global list + task_scheduler_observer_mutex_scoped_lock lock(the_task_scheduler_observer_mutex.begin()[0],/*is_writer=*/true); + observer_proxy* p = global_last_observer_proxy; + prev = p; + if( p ) + p->next=this; + else + global_first_observer_proxy = this; + global_last_observer_proxy = this; + } +} + +void observer_proxy::remove_from_list() { + // Take myself off the global list. + if( next ) + next->prev = prev; + else + global_last_observer_proxy = prev; + if( prev ) + prev->next = next; + else + global_first_observer_proxy = next; +#if TBB_USE_ASSERT + poison_pointer(prev); + poison_pointer(next); + gc_ref_count = -666; +#endif /* TBB_USE_ASSERT */ +} + +void observer_proxy::remove_ref_slow() { + int r = gc_ref_count; + while(r>1) { + __TBB_ASSERT( r!=0, NULL ); + int r_old = gc_ref_count.compare_and_swap(r-1,r); + if( r_old==r ) { + // Successfully decremented count. + return; + } + r = r_old; + } + __TBB_ASSERT( r==1, NULL ); + // Reference count might go to zero + { + task_scheduler_observer_mutex_scoped_lock lock(the_task_scheduler_observer_mutex.begin()[0],/*is_writer=*/true); + r = --gc_ref_count; + if( !r ) { + remove_from_list(); + } + } + if( !r ) { + __TBB_ASSERT( gc_ref_count == -666, NULL ); +#if TBB_USE_ASSERT + --observer_proxy_count; +#endif /* TBB_USE_ASSERT */ + delete this; + } +} + +observer_proxy* observer_proxy::process_list( observer_proxy* local_last, bool is_worker, bool is_entry ) { + // Pointer p marches though the list. + // If is_entry, start with our previous list position, otherwise start at beginning of list. + observer_proxy* p = is_entry ? local_last : NULL; + for(;;) { + task_scheduler_observer* tso=NULL; + // Hold lock on list only long enough to advance to next proxy in list. + { + task_scheduler_observer_mutex_scoped_lock lock(the_task_scheduler_observer_mutex.begin()[0],/*is_writer=*/false); + do { + if( local_last && local_last->observer ) { + // 2 = 1 for observer and 1 for local_last + __TBB_ASSERT( local_last->gc_ref_count>=2, NULL ); + // Can decrement count quickly, because it cannot become zero here. + --local_last->gc_ref_count; + local_last = NULL; + } else { + // Use slow form of decrementing the reference count, after lock is released. + } + if( p ) { + // We were already processing the list. + if( observer_proxy* q = p->next ) { + // Step to next item in list. + p=q; + } else { + // At end of list. + if( is_entry ) { + // Remember current position in the list, so we can start at on the next call. + ++p->gc_ref_count; + } else { + // Finishin running off the end of the list + p=NULL; + } + goto done; + } + } else { + // Starting pass through the list + p = global_first_observer_proxy; + if( !p ) + goto done; + } + tso = p->observer; + } while( !tso ); + ++p->gc_ref_count; + ++tso->my_busy_count; + } + __TBB_ASSERT( !local_last || p!=local_last, NULL ); + if( local_last ) + local_last->remove_ref_slow(); + // Do not hold any locks on the list while calling user's code. + __TBB_TRY { + if( is_entry ) + tso->on_scheduler_entry( is_worker ); + else + tso->on_scheduler_exit( is_worker ); + } __TBB_CATCH(...) { + // Suppress exception, because user routines are supposed to be observing, not changing + // behavior of a master or worker thread. +#if TBB_USE_ASSERT + runtime_warning( "%s threw exception\n", is_entry ? "on_scheduler_entry" : "on_scheduler_exit"); +#endif /* TBB_USE_ASSERT */ + } + intptr_t bc = --tso->my_busy_count; + __TBB_ASSERT_EX( bc>=0, "my_busy_count underflowed" ); + local_last = p; + } +done: + // Return new value to be used as local_last next time. + if( local_last ) + local_last->remove_ref_slow(); + __TBB_ASSERT( !p || is_entry, NULL ); + return p; +} + +void task_scheduler_observer_v3::observe( bool state ) { + if( state ) { + if( !my_proxy ) { + if( !__TBB_InitOnce::initialization_done() ) + DoOneTimeInitializations(); + my_busy_count = 0; + my_proxy = new observer_proxy(*this); + if( generic_scheduler* s = governor::local_scheduler_if_initialized() ) { + // Notify newly created observer of its own thread. + // Any other pending observers are notified too. + s->notify_entry_observers(); + } + } + } else { + if( observer_proxy* proxy = my_proxy ) { + my_proxy = NULL; + __TBB_ASSERT( proxy->gc_ref_count>=1, "reference for observer missing" ); + { + task_scheduler_observer_mutex_scoped_lock lock(the_task_scheduler_observer_mutex.begin()[0],/*is_writer=*/true); + proxy->observer = NULL; + } + proxy->remove_ref_slow(); + while( my_busy_count ) { + __TBB_Yield(); + } + } + } +} + +} // namespace internal +} // namespace tbb + +#endif /* __TBB_SCHEDULER_OBSERVER */ diff --git a/src/tbb/src/tbb/observer_proxy.h b/src/tbb/src/tbb/observer_proxy.h new file mode 100644 index 0000000..0b8fe8e --- /dev/null +++ b/src/tbb/src/tbb/observer_proxy.h @@ -0,0 +1,69 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _TBB_observer_proxy_H +#define _TBB_observer_proxy_H + +#if __TBB_SCHEDULER_OBSERVER + +#include "tbb/task_scheduler_observer.h" + +namespace tbb { +namespace internal { + +class observer_proxy { + friend class task_scheduler_observer_v3; + //! Reference count used for garbage collection. + /** 1 for reference from my task_scheduler_observer. + 1 for each my_local_last_observer_proxy that points to me. + No accounting for predecessor in the global list. + No accounting for global_last_observer_proxy that points to me. */ + atomic<int> gc_ref_count; + //! Pointer to next task_scheduler_observer + /** Valid even when *this has been removed from the global list. */ + observer_proxy* next; + //! Pointer to previous task_scheduler_observer in global list. + observer_proxy* prev; + //! Associated observer + task_scheduler_observer* observer; + //! Account for removing reference from p. No effect if p is NULL. + void remove_ref_slow(); + void remove_from_list(); + observer_proxy( task_scheduler_observer_v3& wo ); +public: + static observer_proxy* process_list( observer_proxy* local_last, bool is_worker, bool is_entry ); +}; + +extern observer_proxy* global_last_observer_proxy; + +} // namespace internal +} // namespace tbb + +#endif /* __TBB_SCHEDULER_OBSERVER */ + +#endif /* _TBB_observer_proxy_H */ diff --git a/src/tbb/src/tbb/pipeline.cpp b/src/tbb/src/tbb/pipeline.cpp new file mode 100644 index 0000000..2cb0629 --- /dev/null +++ b/src/tbb/src/tbb/pipeline.cpp @@ -0,0 +1,790 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/pipeline.h" +#include "tbb/spin_mutex.h" +#include "tbb/cache_aligned_allocator.h" +#include "itt_notify.h" +#include "semaphore.h" +#include "tls.h" // for parallel filters that do not use NULL as end_of_input + + +namespace tbb { + +namespace internal { + +//! This structure is used to store task information in a input buffer +struct task_info { + void* my_object; + //! Invalid unless a task went through an ordered stage. + Token my_token; + //! False until my_token is set. + bool my_token_ready; + //! True if my_object is valid. + bool is_valid; + //! Set to initial state (no object, no token) + void reset() { + my_object = NULL; + my_token = 0; + my_token_ready = false; + is_valid = false; + } +}; +//! A buffer of input items for a filter. +/** Each item is a task_info, inserted into a position in the buffer corresponding to a Token. */ +class input_buffer { + friend class tbb::internal::pipeline_root_task; + friend class tbb::filter; + friend class tbb::thread_bound_filter; + friend class tbb::internal::stage_task; + friend class tbb::pipeline; + + typedef Token size_type; + + //! Array of deferred tasks that cannot yet start executing. + task_info* array; + + //! for thread-bound filter, semaphore for waiting, NULL otherwise. + semaphore* my_sem; + + //! Size of array + /** Always 0 or a power of 2 */ + size_type array_size; + + //! Lowest token that can start executing. + /** All prior Token have already been seen. */ + Token low_token; + + //! Serializes updates. + spin_mutex array_mutex; + + //! Resize "array". + /** Caller is responsible to acquiring a lock on "array_mutex". */ + void grow( size_type minimum_size ); + + //! Initial size for "array" + /** Must be a power of 2 */ + static const size_type initial_buffer_size = 4; + + //! Used for out of order buffer, and for assigning my_token if is_ordered and my_token not already assigned + Token high_token; + + //! True for ordered filter, false otherwise. + bool is_ordered; + + //! True for thread-bound filter, false otherwise. + bool is_bound; + + //! for parallel filters that accepts NULLs, thread-local flag for reaching end_of_input + typedef basic_tls<intptr_t> end_of_input_tls_t; + end_of_input_tls_t end_of_input_tls; + bool end_of_input_tls_allocated; // no way to test pthread creation of TLS + + void create_sema(size_t initial_tokens) { __TBB_ASSERT(!my_sem,NULL); my_sem = new internal::semaphore(initial_tokens); } + void free_sema() { __TBB_ASSERT(my_sem,NULL); delete my_sem; } + void sema_P() { __TBB_ASSERT(my_sem,NULL); my_sem->P(); } + void sema_V() { __TBB_ASSERT(my_sem,NULL); my_sem->V(); } + +public: + //! Construct empty buffer. + input_buffer( bool is_ordered_, bool is_bound_ ) : + array(NULL), my_sem(NULL), array_size(0), + low_token(0), high_token(0), + is_ordered(is_ordered_), is_bound(is_bound_), + end_of_input_tls_allocated(false) { + grow(initial_buffer_size); + __TBB_ASSERT( array, NULL ); + if(is_bound) create_sema(0); + } + + //! Destroy the buffer. + ~input_buffer() { + __TBB_ASSERT( array, NULL ); + cache_aligned_allocator<task_info>().deallocate(array,array_size); + poison_pointer( array ); + if(my_sem) { + free_sema(); + } + if(end_of_input_tls_allocated) { + destroy_my_tls(); + } + } + + //! Put a token into the buffer. + /** If task information was placed into buffer, returns true; + otherwise returns false, informing the caller to create and spawn a task. + If input buffer owned by thread-bound filter and the item at + low_token was not valid, issue a V() + If the input_buffer is owned by a successor to a thread-bound filter, + the force_put parameter should be true to ensure the token is inserted + in the buffer. + */ + bool put_token( task_info& info_, bool force_put = false ) { + { + info_.is_valid = true; + spin_mutex::scoped_lock lock( array_mutex ); + Token token; + bool was_empty = !array[low_token&(array_size-1)].is_valid; + if( is_ordered ) { + if( !info_.my_token_ready ) { + info_.my_token = high_token++; + info_.my_token_ready = true; + } + token = info_.my_token; + } else + token = high_token++; + __TBB_ASSERT( (tokendiff_t)(token-low_token)>=0, NULL ); + if( token!=low_token || is_bound || force_put ) { + // Trying to put token that is beyond low_token. + // Need to wait until low_token catches up before dispatching. + if( token-low_token>=array_size ) + grow( token-low_token+1 ); + ITT_NOTIFY( sync_releasing, this ); + array[token&(array_size-1)] = info_; + if(was_empty && is_bound) { + sema_V(); + } + return true; + } + } + return false; + } + + //! Note that processing of a token is finished. + /** Fires up processing of the next token, if processing was deferred. */ + // Using template to avoid explicit dependency on stage_task + // this is only called for serial filters, and is the reason for the + // advance parameter in return_item (we're incrementing low_token here.) + // Non-TBF serial stages don't advance the token at the start because the presence + // of the current token in the buffer keeps another stage from being spawned. + template<typename StageTask> + void note_done( Token token, StageTask& spawner ) { + task_info wakee; + wakee.reset(); + { + spin_mutex::scoped_lock lock( array_mutex ); + if( !is_ordered || token==low_token ) { + // Wake the next task + task_info& item = array[++low_token & (array_size-1)]; + ITT_NOTIFY( sync_acquired, this ); + wakee = item; + item.is_valid = false; + } + } + if( wakee.is_valid ) + spawner.spawn_stage_task(wakee); + } + +#if __TBB_TASK_GROUP_CONTEXT + //! The method destroys all data in filters to prevent memory leaks + void clear( filter* my_filter ) { + long t=low_token; + for( size_type i=0; i<array_size; ++i, ++t ){ + task_info& temp = array[t&(array_size-1)]; + if (temp.is_valid ) { + my_filter->finalize(temp.my_object); + temp.is_valid = false; + } + } + } +#endif + + //! return an item, invalidate the queued item, but only advance if advance + // advance == true for parallel filters. If the filter is serial, leave the + // item in the buffer to keep another stage from being spawned. + bool return_item(task_info& info, bool advance) { + spin_mutex::scoped_lock lock( array_mutex ); + task_info& item = array[low_token&(array_size-1)]; + ITT_NOTIFY( sync_acquired, this ); + if( item.is_valid ) { + info = item; + item.is_valid = false; + if (advance) low_token++; + return true; + } + return false; + } + + //! true if the current low_token is valid. + bool has_item() { spin_mutex::scoped_lock lock(array_mutex); return array[low_token&(array_size -1)].is_valid; } + + // end_of_input signal for parallel_pipeline, parallel input filters with 0 tokens allowed. + void create_my_tls() { int status = end_of_input_tls.create(); if(status) handle_perror(status, "TLS not allocated for filter"); end_of_input_tls_allocated = true; } + void destroy_my_tls() { int status = end_of_input_tls.destroy(); if(status) handle_perror(status, "Failed to destroy filter TLS"); } + bool my_tls_end_of_input() { return end_of_input_tls.get() != 0; } + void set_my_tls_end_of_input() { end_of_input_tls.set(1); } +}; + +void input_buffer::grow( size_type minimum_size ) { + size_type old_size = array_size; + size_type new_size = old_size ? 2*old_size : initial_buffer_size; + while( new_size<minimum_size ) + new_size*=2; + task_info* new_array = cache_aligned_allocator<task_info>().allocate(new_size); + task_info* old_array = array; + for( size_type i=0; i<new_size; ++i ) + new_array[i].is_valid = false; + long t=low_token; + for( size_type i=0; i<old_size; ++i, ++t ) + new_array[t&(new_size-1)] = old_array[t&(old_size-1)]; + array = new_array; + array_size = new_size; + if( old_array ) + cache_aligned_allocator<task_info>().deallocate(old_array,old_size); +} + +class stage_task: public task, public task_info { +private: + friend class tbb::pipeline; + pipeline& my_pipeline; + filter* my_filter; + //! True if this task has not yet read the input. + bool my_at_start; + +public: + //! Construct stage_task for first stage in a pipeline. + /** Such a stage has not read any input yet. */ + stage_task( pipeline& pipeline ) : + my_pipeline(pipeline), + my_filter(pipeline.filter_list), + my_at_start(true) + { + task_info::reset(); + } + //! Construct stage_task for a subsequent stage in a pipeline. + stage_task( pipeline& pipeline, filter* filter_, const task_info& info ) : + task_info(info), + my_pipeline(pipeline), + my_filter(filter_), + my_at_start(false) + {} + //! Roughly equivalent to the constructor of input stage task + void reset() { + task_info::reset(); + my_filter = my_pipeline.filter_list; + my_at_start = true; + } + //! The virtual task execution method + /*override*/ task* execute(); +#if __TBB_TASK_GROUP_CONTEXT + ~stage_task() + { + if (my_filter && my_object && (my_filter->my_filter_mode & filter::version_mask) >= __TBB_PIPELINE_VERSION(4)) { + __TBB_ASSERT(is_cancelled(), "Trying to finalize the task that wasn't cancelled"); + my_filter->finalize(my_object); + my_object = NULL; + } + } +#endif // __TBB_TASK_GROUP_CONTEXT + //! Creates and spawns stage_task from task_info + void spawn_stage_task(const task_info& info) + { + stage_task* clone = new (allocate_additional_child_of(*parent())) + stage_task( my_pipeline, my_filter, info ); + spawn(*clone); + } +}; + +task* stage_task::execute() { + __TBB_ASSERT( !my_at_start || !my_object, NULL ); + __TBB_ASSERT( !my_filter->is_bound(), NULL ); + if( my_at_start ) { + if( my_filter->is_serial() ) { + my_object = (*my_filter)(my_object); + if( my_object || ( my_filter->object_may_be_null() && !my_pipeline.end_of_input) ) + { + if( my_filter->is_ordered() ) { + my_token = my_pipeline.token_counter++; // ideally, with relaxed semantics + my_token_ready = true; + } else if( (my_filter->my_filter_mode & my_filter->version_mask) >= __TBB_PIPELINE_VERSION(5) ) { + if( my_pipeline.has_thread_bound_filters ) + my_pipeline.token_counter++; // ideally, with relaxed semantics + } + if( !my_filter->next_filter_in_pipeline ) { // we're only filter in pipeline + reset(); + goto process_another_stage; + } else { + ITT_NOTIFY( sync_releasing, &my_pipeline.input_tokens ); + if( --my_pipeline.input_tokens>0 ) + spawn( *new( allocate_additional_child_of(*parent()) ) stage_task( my_pipeline ) ); + } + } else { + my_pipeline.end_of_input = true; + return NULL; + } + } else /*not is_serial*/ { + if( my_pipeline.end_of_input ) + return NULL; + if( (my_filter->my_filter_mode & my_filter->version_mask) >= __TBB_PIPELINE_VERSION(5) ) { + if( my_pipeline.has_thread_bound_filters ) + my_pipeline.token_counter++; + } + ITT_NOTIFY( sync_releasing, &my_pipeline.input_tokens ); + if( --my_pipeline.input_tokens>0 ) + spawn( *new( allocate_additional_child_of(*parent()) ) stage_task( my_pipeline ) ); + my_object = (*my_filter)(my_object); + if( !my_object && (!my_filter->object_may_be_null() || my_filter->my_input_buffer->my_tls_end_of_input()) ) + { + my_pipeline.end_of_input = true; + if( (my_filter->my_filter_mode & my_filter->version_mask) >= __TBB_PIPELINE_VERSION(5) ) { + if( my_pipeline.has_thread_bound_filters ) + my_pipeline.token_counter--; // fix token_counter + } + return NULL; + } + } + my_at_start = false; + } else { + my_object = (*my_filter)(my_object); + if( my_filter->is_serial() ) + my_filter->my_input_buffer->note_done(my_token, *this); + } + my_filter = my_filter->next_filter_in_pipeline; + if( my_filter ) { + // There is another filter to execute. + // Crank up priority a notch. + add_to_depth(1); + if( my_filter->is_serial() ) { + // The next filter must execute tokens in order + if( my_filter->my_input_buffer->put_token(*this) ){ + // Can't proceed with the same item + if( my_filter->is_bound() ) { + // Find the next non-thread-bound filter + do { + my_filter = my_filter->next_filter_in_pipeline; + } while( my_filter && my_filter->is_bound() ); + // Check if there is an item ready to process + if( my_filter && my_filter->my_input_buffer->return_item(*this, !my_filter->is_serial())) + goto process_another_stage; + } + my_filter = NULL; // To prevent deleting my_object twice if exception occurs + return NULL; + } + } + } else { + // Reached end of the pipe. + size_t ntokens_avail = ++my_pipeline.input_tokens; + if(my_pipeline.filter_list->is_bound() ) { + if(ntokens_avail == 1) { + my_pipeline.filter_list->my_input_buffer->sema_V(); + } + return NULL; + } + if( ntokens_avail>1 // Only recycle if there is one available token + || my_pipeline.end_of_input ) { + return NULL; // No need to recycle for new input + } + ITT_NOTIFY( sync_acquired, &my_pipeline.input_tokens ); + // Recycle as an input stage task. + reset(); + } +process_another_stage: + /* A semi-hackish way to reexecute the same task object immediately without spawning. + recycle_as_continuation marks the task for future execution, + and then 'this' pointer is returned to bypass spawning. */ + recycle_as_continuation(); + return this; +} + +class pipeline_root_task: public task { + pipeline& my_pipeline; + bool do_segment_scanning; + + /*override*/ task* execute() { + if( !my_pipeline.end_of_input ) + if( !my_pipeline.filter_list->is_bound() ) + if( my_pipeline.input_tokens > 0 ) { + recycle_as_continuation(); + set_ref_count(1); + return new( allocate_child() ) stage_task( my_pipeline ); + } + if( do_segment_scanning ) { + filter* current_filter = my_pipeline.filter_list->next_segment; + /* first non-thread-bound filter that follows thread-bound one + and may have valid items to process */ + filter* first_suitable_filter = current_filter; + while( current_filter ) { + __TBB_ASSERT( !current_filter->is_bound(), "filter is thread-bound?" ); + __TBB_ASSERT( current_filter->prev_filter_in_pipeline->is_bound(), "previous filter is not thread-bound?" ); + if( !my_pipeline.end_of_input || current_filter->has_more_work()) + { + task_info info; + info.reset(); + if( current_filter->my_input_buffer->return_item(info, !current_filter->is_serial()) ) { + set_ref_count(1); + recycle_as_continuation(); + return new( allocate_child() ) stage_task( my_pipeline, current_filter, info); + } + current_filter = current_filter->next_segment; + if( !current_filter ) { + if( !my_pipeline.end_of_input ) { + recycle_as_continuation(); + return this; + } + current_filter = first_suitable_filter; + __TBB_Yield(); + } + } else { + /* The preceding pipeline segment is empty. + Fast-forward to the next post-TBF segment. */ + first_suitable_filter = first_suitable_filter->next_segment; + current_filter = first_suitable_filter; + } + } /* while( current_filter ) */ + return NULL; + } else { + if( !my_pipeline.end_of_input ) { + recycle_as_continuation(); + return this; + } + return NULL; + } + } +public: + pipeline_root_task( pipeline& pipeline ): my_pipeline(pipeline), do_segment_scanning(false) + { + __TBB_ASSERT( my_pipeline.filter_list, NULL ); + filter* first = my_pipeline.filter_list; + if( (first->my_filter_mode & first->version_mask) >= __TBB_PIPELINE_VERSION(5) ) { + // Scanning the pipeline for segments + filter* head_of_previous_segment = first; + for( filter* subfilter=first->next_filter_in_pipeline; + subfilter!=NULL; + subfilter=subfilter->next_filter_in_pipeline ) + { + if( subfilter->prev_filter_in_pipeline->is_bound() && !subfilter->is_bound() ) { + do_segment_scanning = true; + head_of_previous_segment->next_segment = subfilter; + head_of_previous_segment = subfilter; + } + } + } + } +}; + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // Workaround for overzealous compiler warnings + // Suppress compiler warning about constant conditional expression + #pragma warning (disable: 4127) +#endif + +// The class destroys end_counter and clears all input buffers if pipeline was cancelled. +class pipeline_cleaner: internal::no_copy { + pipeline& my_pipeline; +public: + pipeline_cleaner(pipeline& _pipeline) : + my_pipeline(_pipeline) + {} + ~pipeline_cleaner(){ +#if __TBB_TASK_GROUP_CONTEXT + if (my_pipeline.end_counter->is_cancelled()) // Pipeline was cancelled + my_pipeline.clear_filters(); +#endif + my_pipeline.end_counter = NULL; + } +}; + +} // namespace internal + +void pipeline::inject_token( task& ) { + __TBB_ASSERT(0,"illegal call to inject_token"); +} + +#if __TBB_TASK_GROUP_CONTEXT +void pipeline::clear_filters() { + for( filter* f = filter_list; f; f = f->next_filter_in_pipeline ) { + if ((f->my_filter_mode & filter::version_mask) >= __TBB_PIPELINE_VERSION(4)) + if( internal::input_buffer* b = f->my_input_buffer ) + b->clear(f); + } +} +#endif + +pipeline::pipeline() : + filter_list(NULL), + filter_end(NULL), + end_counter(NULL), + end_of_input(false), + has_thread_bound_filters(false) +{ + token_counter = 0; + input_tokens = 0; +} + +pipeline::~pipeline() { + clear(); +} + +void pipeline::clear() { + filter* next; + for( filter* f = filter_list; f; f=next ) { + if( internal::input_buffer* b = f->my_input_buffer ) { + delete b; + f->my_input_buffer = NULL; + } + next=f->next_filter_in_pipeline; + f->next_filter_in_pipeline = filter::not_in_pipeline(); + if ( (f->my_filter_mode & filter::version_mask) >= __TBB_PIPELINE_VERSION(3) ) { + f->prev_filter_in_pipeline = filter::not_in_pipeline(); + f->my_pipeline = NULL; + } + if ( (f->my_filter_mode & filter::version_mask) >= __TBB_PIPELINE_VERSION(5) ) + f->next_segment = NULL; + } + filter_list = filter_end = NULL; +} + +void pipeline::add_filter( filter& filter_ ) { +#if TBB_USE_ASSERT + if ( (filter_.my_filter_mode & filter::version_mask) >= __TBB_PIPELINE_VERSION(3) ) + __TBB_ASSERT( filter_.prev_filter_in_pipeline==filter::not_in_pipeline(), "filter already part of pipeline?" ); + __TBB_ASSERT( filter_.next_filter_in_pipeline==filter::not_in_pipeline(), "filter already part of pipeline?" ); + __TBB_ASSERT( !end_counter, "invocation of add_filter on running pipeline" ); +#endif + if ( (filter_.my_filter_mode & filter::version_mask) >= __TBB_PIPELINE_VERSION(3) ) { + filter_.my_pipeline = this; + filter_.prev_filter_in_pipeline = filter_end; + if ( filter_list == NULL) + filter_list = &filter_; + else + filter_end->next_filter_in_pipeline = &filter_; + filter_.next_filter_in_pipeline = NULL; + filter_end = &filter_; + } + else + { + if( !filter_end ) + filter_end = reinterpret_cast<filter*>(&filter_list); + + *reinterpret_cast<filter**>(filter_end) = &filter_; + filter_end = reinterpret_cast<filter*>(&filter_.next_filter_in_pipeline); + *reinterpret_cast<filter**>(filter_end) = NULL; + } + if( (filter_.my_filter_mode & filter_.version_mask) >= __TBB_PIPELINE_VERSION(5) ) { + if( filter_.is_serial() ) { + if( filter_.is_bound() ) + has_thread_bound_filters = true; + filter_.my_input_buffer = new internal::input_buffer( filter_.is_ordered(), filter_.is_bound() ); + } + else { + if(filter_.prev_filter_in_pipeline) { + if(filter_.prev_filter_in_pipeline->is_bound()) { + // successors to bound filters must have an input_buffer + filter_.my_input_buffer = new internal::input_buffer( /*is_ordered*/false, false ); + } + } + else { // input filter + if(filter_.object_may_be_null() ) { + //TODO: buffer only needed to hold TLS; could improve + filter_.my_input_buffer = new internal::input_buffer( /*is_ordered*/false, false ); + filter_.my_input_buffer->create_my_tls(); + } + } + } + } else { + if( filter_.is_serial() ) { + filter_.my_input_buffer = new internal::input_buffer( filter_.is_ordered(), false ); + } + } + +} + +void pipeline::remove_filter( filter& filter_ ) { + __TBB_ASSERT( filter_.prev_filter_in_pipeline!=filter::not_in_pipeline(), "filter not part of pipeline" ); + __TBB_ASSERT( filter_.next_filter_in_pipeline!=filter::not_in_pipeline(), "filter not part of pipeline" ); + __TBB_ASSERT( !end_counter, "invocation of remove_filter on running pipeline" ); + if (&filter_ == filter_list) + filter_list = filter_.next_filter_in_pipeline; + else { + __TBB_ASSERT( filter_.prev_filter_in_pipeline, "filter list broken?" ); + filter_.prev_filter_in_pipeline->next_filter_in_pipeline = filter_.next_filter_in_pipeline; + } + if (&filter_ == filter_end) + filter_end = filter_.prev_filter_in_pipeline; + else { + __TBB_ASSERT( filter_.next_filter_in_pipeline, "filter list broken?" ); + filter_.next_filter_in_pipeline->prev_filter_in_pipeline = filter_.prev_filter_in_pipeline; + } + if( internal::input_buffer* b = filter_.my_input_buffer ) { + delete b; + filter_.my_input_buffer = NULL; + } + filter_.next_filter_in_pipeline = filter_.prev_filter_in_pipeline = filter::not_in_pipeline(); + if ( (filter_.my_filter_mode & filter::version_mask) >= __TBB_PIPELINE_VERSION(5) ) + filter_.next_segment = NULL; + filter_.my_pipeline = NULL; +} + +void pipeline::run( size_t max_number_of_live_tokens +#if __TBB_TASK_GROUP_CONTEXT + , tbb::task_group_context& context +#endif + ) { + __TBB_ASSERT( max_number_of_live_tokens>0, "pipeline::run must have at least one token" ); + __TBB_ASSERT( !end_counter, "pipeline already running?" ); + if( filter_list ) { + internal::pipeline_cleaner my_pipeline_cleaner(*this); + end_of_input = false; + input_tokens = internal::Token(max_number_of_live_tokens); + if(has_thread_bound_filters) { + // release input filter if thread-bound + if(filter_list->is_bound()) { + filter_list->my_input_buffer->sema_V(); + } + } +#if __TBB_TASK_GROUP_CONTEXT + end_counter = new( task::allocate_root(context) ) internal::pipeline_root_task( *this ); +#else + end_counter = new( task::allocate_root() ) internal::pipeline_root_task( *this ); +#endif + // Start execution of tasks + task::spawn_root_and_wait( *end_counter ); + + if(has_thread_bound_filters) { + for(filter* f = filter_list->next_filter_in_pipeline; f; f=f->next_filter_in_pipeline) { + if(f->is_bound()) { + f->my_input_buffer->sema_V(); // wake to end + } + } + } + } +} + +#if __TBB_TASK_GROUP_CONTEXT +void pipeline::run( size_t max_number_of_live_tokens ) { + if( filter_list ) { + // Construct task group context with the exception propagation mode expected + // by the pipeline caller. + uintptr_t ctx_traits = filter_list->my_filter_mode & filter::exact_exception_propagation ? + task_group_context::default_traits : + task_group_context::default_traits & ~task_group_context::exact_exception; + task_group_context context(task_group_context::bound, ctx_traits); + run(max_number_of_live_tokens, context); + } +} +#endif // __TBB_TASK_GROUP_CONTEXT + +bool filter::has_more_work() { + __TBB_ASSERT(my_pipeline, NULL); + __TBB_ASSERT(my_input_buffer, "has_more_work() called for filter with no input buffer"); + return (internal::tokendiff_t)(my_pipeline->token_counter - my_input_buffer->low_token) != 0; +} + +filter::~filter() { + if ( (my_filter_mode & version_mask) >= __TBB_PIPELINE_VERSION(3) ) { + if ( next_filter_in_pipeline != filter::not_in_pipeline() ) + my_pipeline->remove_filter(*this); + else + __TBB_ASSERT( prev_filter_in_pipeline == filter::not_in_pipeline(), "probably filter list is broken" ); + } else { + __TBB_ASSERT( next_filter_in_pipeline==filter::not_in_pipeline(), "cannot destroy filter that is part of pipeline" ); + } +} + +void +filter::set_end_of_input() { + __TBB_ASSERT(my_input_buffer, NULL); + __TBB_ASSERT(object_may_be_null(), NULL); + if(is_serial()) { + my_pipeline->end_of_input = true; + } + else { + __TBB_ASSERT(my_input_buffer->end_of_input_tls_allocated, NULL); + my_input_buffer->set_my_tls_end_of_input(); + } +} + +thread_bound_filter::result_type thread_bound_filter::process_item() { + return internal_process_item(true); +} + +thread_bound_filter::result_type thread_bound_filter::try_process_item() { + return internal_process_item(false); +} + +thread_bound_filter::result_type thread_bound_filter::internal_process_item(bool is_blocking) { + internal::task_info info; + info.reset(); + + if(my_pipeline && my_pipeline->end_of_input && !has_more_work()) + return end_of_stream; + + if( !prev_filter_in_pipeline ) { + if( my_pipeline->end_of_input ) + return end_of_stream; + while(my_pipeline->input_tokens == 0) { + if( !is_blocking ) + return item_not_available; + my_input_buffer->sema_P(); + } + info.my_object = (*this)(info.my_object); + if( info.my_object ) { + __TBB_ASSERT(my_pipeline->input_tokens > 0, "Token failed in thread-bound filter"); + my_pipeline->input_tokens--; + if( is_ordered() ) { + info.my_token = my_pipeline->token_counter; + info.my_token_ready = true; + } + my_pipeline->token_counter++; // ideally, with relaxed semantics + } else { + my_pipeline->end_of_input = true; + return end_of_stream; + } + } else { /* this is not an input filter */ + while(!my_input_buffer->has_item()) { + if(!is_blocking) { + return item_not_available; + } + my_input_buffer->sema_P(); + if( my_pipeline->end_of_input && !has_more_work()) { + return end_of_stream; + } + } + if(!my_input_buffer->return_item(info, /*advance*/true)) { + __TBB_ASSERT(0,"return_item failed"); + } + info.my_object = (*this)(info.my_object); + } + if( next_filter_in_pipeline ) { + if (!next_filter_in_pipeline->my_input_buffer->put_token(info,/*force_put=*/true) ) { + __TBB_ASSERT(0, "Couldn't put token after thread-bound buffer"); + } + } else { + size_t ntokens_avail = ++(my_pipeline->input_tokens); + if(my_pipeline->filter_list->is_bound()) { + if(ntokens_avail == 1) { + my_pipeline->filter_list->my_input_buffer->sema_V(); + } + } + } + + return success; +} + +} // tbb + diff --git a/src/tbb/src/tbb/private_server.cpp b/src/tbb/src/tbb/private_server.cpp new file mode 100644 index 0000000..dce544f --- /dev/null +++ b/src/tbb/src/tbb/private_server.cpp @@ -0,0 +1,401 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "rml_tbb.h" +#include "../server/thread_monitor.h" +#include "tbb/atomic.h" +#include "tbb/cache_aligned_allocator.h" +#include "tbb/spin_mutex.h" +#include "governor.h" +#include "tbb_misc.h" + +using rml::internal::thread_monitor; + +namespace tbb { +namespace internal { +namespace rml { + +class private_server; + +class private_worker: no_copy { + //! State in finite-state machine that controls the worker. + /** State diagram: + init --------------------\ + | | + V V + starting --> normal --> quit + | + V + plugged + */ + enum state_t { + //! *this is initialized + st_init, + //! *this has associated thread that is starting up. + st_starting, + //! Associated thread is doing normal life sequence. + st_normal, + //! Associated thread has ended normal life sequence and promises to never touch *this again. + st_quit, + //! Associated thread should skip normal life sequence, because private_server is shutting down. + st_plugged + }; + atomic<state_t> my_state; + + //! Associated server + private_server& my_server; + + //! Associated client + tbb_client& my_client; + + //! index used for avoiding the 64K aliasing problem + const size_t my_index; + + //! Monitor for sleeping when there is no work to do. + /** The invariant that holds for sleeping workers is: + "my_slack<=0 && my_state==st_normal && I am on server's list of asleep threads" */ + thread_monitor my_thread_monitor; + + //! Link for list of workers that are sleeping or have no associated thread. + private_worker* my_next; + + friend class private_server; + + //! Actions executed by the associated thread + void run(); + + //! Wake up associated thread (or launch a thread if there is none) + void wake_or_launch(); + + //! Called by a thread (usually not the associated thread) to commence termination. + void start_shutdown(); + + static __RML_DECL_THREAD_ROUTINE thread_routine( void* arg ); + +protected: + private_worker( private_server& server, tbb_client& client, const size_t i ) : + my_server(server), + my_client(client), + my_index(i) + { + my_state = st_init; + } + +}; + +static const size_t cache_line_size = tbb::internal::NFS_MaxLineSize; + + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // Suppress overzealous compiler warnings about uninstantiatble class + #pragma warning(push) + #pragma warning(disable:4510 4610) +#endif +class padded_private_worker: public private_worker { + char pad[cache_line_size - sizeof(private_worker)%cache_line_size]; +public: + padded_private_worker( private_server& server, tbb_client& client, const size_t i ) : private_worker(server,client,i) {} +}; +#if _MSC_VER && !defined(__INTEL_COMPILER) + #pragma warning(pop) +#endif + +class private_server: public tbb_server, no_copy { + tbb_client& my_client; + //! Maximum number of threads to be created. + /** Threads are created lazily, so maximum might not actually be reached. */ + const tbb_client::size_type my_n_thread; + + //! Stack size for each thread. */ + const size_t my_stack_size; + + //! Number of jobs that could use their associated thread minus number of active threads. + /** If negative, indicates oversubscription. + If positive, indicates that more threads should run. + Can be lowered asynchronously, but must be raised only while holding my_asleep_list_mutex, + because raising it impacts the invariant for sleeping threads. */ + atomic<int> my_slack; + + //! Counter used to determine when to delete this. + atomic<int> my_ref_count; + + padded_private_worker* my_thread_array; + + //! List of workers that are asleep or committed to sleeping until notified by another thread. + tbb::atomic<private_worker*> my_asleep_list_root; + + //! Protects my_asleep_list_root + tbb::spin_mutex my_asleep_list_mutex; + +#if TBB_USE_ASSERT + atomic<int> my_net_slack_requests; +#endif /* TBB_USE_ASSERT */ + + //! Wake up to two sleeping workers, if there are any sleeping. + /** The call is used to propagate a chain reaction where each thread wakes up two threads, + which in turn each wake up two threads, etc. */ + void propagate_chain_reaction() { + // First test of a double-check idiom. Second test is inside wake_some(0). + if( my_asleep_list_root ) + wake_some(0); + } + + //! Try to add t to list of sleeping workers + bool try_insert_in_asleep_list( private_worker& t ); + + //! Equivalent of adding additional_slack to my_slack and waking up to 2 threads if my_slack permits. + void wake_some( int additional_slack ); + + virtual ~private_server(); + + void remove_server_ref() { + if( --my_ref_count==0 ) { + my_client.acknowledge_close_connection(); + this->~private_server(); + tbb::cache_aligned_allocator<private_server>().deallocate( this, 1 ); + } + } + + friend class private_worker; +public: + private_server( tbb_client& client ); + + /*override*/ version_type version() const { + return 0; + } + + /*override*/ void request_close_connection( bool /*exiting*/ ) { + for( size_t i=0; i<my_n_thread; ++i ) + my_thread_array[i].start_shutdown(); + remove_server_ref(); + } + + /*override*/ void yield() {__TBB_Yield();} + + /*override*/ void independent_thread_number_changed( int ) {__TBB_ASSERT(false,NULL);} + + /*override*/ unsigned default_concurrency() const { return governor::default_num_threads() - 1; } + + /*override*/ void adjust_job_count_estimate( int delta ); + +#if _WIN32||_WIN64 + /*override*/ void register_master ( ::rml::server::execution_resource_t& ) {} + /*override*/ void unregister_master ( ::rml::server::execution_resource_t ) {} +#endif /* _WIN32||_WIN64 */ +}; + +//------------------------------------------------------------------------ +// Methods of private_worker +//------------------------------------------------------------------------ +#if _MSC_VER && !defined(__INTEL_COMPILER) + // Suppress overzealous compiler warnings about an initialized variable 'sink_for_alloca' not referenced + #pragma warning(push) + #pragma warning(disable:4189) +#endif +#if __MINGW32__ && __GNUC__==4 &&__GNUC_MINOR__>=2 && !__MINGW64__ +// ensure that stack is properly aligned for TBB threads +__attribute__((force_align_arg_pointer)) +#endif +__RML_DECL_THREAD_ROUTINE private_worker::thread_routine( void* arg ) { + private_worker* self = static_cast<private_worker*>(arg); + AVOID_64K_ALIASING( self->my_index ); +#if _XBOX + int HWThreadIndex = __TBB_XBOX360_GetHardwareThreadIndex(i); + XSetThreadProcessor(GetCurrentThread(), HWThreadIndex); +#endif + self->run(); + return 0; +} +#if _MSC_VER && !defined(__INTEL_COMPILER) + #pragma warning(pop) +#endif + +void private_worker::start_shutdown() { + state_t s; + // Transition from st_starting or st_normal to st_plugged or st_quit + do { + s = my_state; + __TBB_ASSERT( s==st_init||s==st_starting||s==st_normal, NULL ); + } while( my_state.compare_and_swap( s==st_starting? st_plugged : st_quit, s )!=s ); + if( s==st_normal ) { + // May have invalidated invariant for sleeping, so wake up the thread. + // Note that the notify() here occurs without maintaining invariants for my_slack. + // It does not matter, because my_state==st_quit overrides checking of my_slack. + my_thread_monitor.notify(); + } else if( s==st_init ) { + // Perform action that otherwise would be performed by associated thread when it quits. + my_server.remove_server_ref(); + } +} + +void private_worker::run() { + my_server.propagate_chain_reaction(); + state_t s = my_state.compare_and_swap( st_normal, st_starting ); + if( s==st_starting ) { + ::rml::job& j = *my_client.create_one_job(); + while( my_state==st_normal ) { + if( my_server.my_slack>=0 ) { + my_client.process(j); + } else { + thread_monitor::cookie c; + // Prepare to wait + my_thread_monitor.prepare_wait(c); + // Check/set the invariant for sleeping + if( my_state==st_normal && my_server.try_insert_in_asleep_list(*this) ) { + my_thread_monitor.commit_wait(c); + my_server.propagate_chain_reaction(); + } else { + // Invariant broken + my_thread_monitor.cancel_wait(); + } + } + } + my_client.cleanup(j); + } else { + // Server is already shutting down. + __TBB_ASSERT( s==st_plugged, NULL ); + } + ++my_server.my_slack; + my_server.remove_server_ref(); +} + +inline void private_worker::wake_or_launch() { + if( my_state==st_init && my_state.compare_and_swap( st_starting, st_init )==st_init ) { +#if USE_WINTHREAD + thread_monitor::launch( thread_routine, this, my_server.my_stack_size, &this->my_index ); +#elif USE_PTHREAD + { + affinity_helper fpa; + fpa.protect_affinity_mask(); + thread_monitor::launch( thread_routine, this, my_server.my_stack_size ); + // Implicit destruction of fpa resets original affinity mask. + } +#endif /* USE_PTHREAD */ + } + else + my_thread_monitor.notify(); +} + +//------------------------------------------------------------------------ +// Methods of private_server +//------------------------------------------------------------------------ +private_server::private_server( tbb_client& client ) : + my_client(client), + my_n_thread(client.max_job_count()), + my_stack_size(client.min_stack_size()), + my_thread_array(NULL) +{ + my_ref_count = my_n_thread+1; + my_slack = 0; +#if TBB_USE_ASSERT + my_net_slack_requests = 0; +#endif /* TBB_USE_ASSERT */ + my_asleep_list_root = NULL; + my_thread_array = tbb::cache_aligned_allocator<padded_private_worker>().allocate( my_n_thread ); + memset( my_thread_array, 0, sizeof(private_worker)*my_n_thread ); + for( size_t i=0; i<my_n_thread; ++i ) { + private_worker* t = new( &my_thread_array[i] ) padded_private_worker( *this, client, i ); + t->my_next = my_asleep_list_root; + my_asleep_list_root = t; + } +} + +private_server::~private_server() { + __TBB_ASSERT( my_net_slack_requests==0, NULL ); + for( size_t i=my_n_thread; i--; ) + my_thread_array[i].~padded_private_worker(); + tbb::cache_aligned_allocator<padded_private_worker>().deallocate( my_thread_array, my_n_thread ); + tbb::internal::poison_pointer( my_thread_array ); +} + +inline bool private_server::try_insert_in_asleep_list( private_worker& t ) { + tbb::spin_mutex::scoped_lock lock(my_asleep_list_mutex); + // Contribute to slack under lock so that if another takes that unit of slack, + // it sees us sleeping on the list and wakes us up. + int k = ++my_slack; + if( k<=0 ) { + t.my_next = my_asleep_list_root; + my_asleep_list_root = &t; + return true; + } else { + --my_slack; + return false; + } +} + +void private_server::wake_some( int additional_slack ) { + __TBB_ASSERT( additional_slack>=0, NULL ); + private_worker* wakee[2]; + private_worker**w = wakee; + { + tbb::spin_mutex::scoped_lock lock(my_asleep_list_mutex); + while( my_asleep_list_root && w<wakee+2 ) { + if( additional_slack>0 ) { + if (additional_slack+my_slack<=0) // additional demand does not exceed surplus supply + break; + --additional_slack; + } else { + // Chain reaction; Try to claim unit of slack + int old; + do { + old = my_slack; + if( old<=0 ) goto done; + } while( my_slack.compare_and_swap(old-1,old)!=old ); + } + // Pop sleeping worker to combine with claimed unit of slack + my_asleep_list_root = (*w++ = my_asleep_list_root)->my_next; + } + if( additional_slack ) { + // Contribute our unused slack to my_slack. + my_slack += additional_slack; + } + } +done: + while( w>wakee ) + (*--w)->wake_or_launch(); +} + +void private_server::adjust_job_count_estimate( int delta ) { +#if TBB_USE_ASSERT + my_net_slack_requests+=delta; +#endif /* TBB_USE_ASSERT */ + if( delta<0 ) { + my_slack+=delta; + } else if( delta>0 ) { + wake_some( delta ); + } +} + +//! Factory method called from task.cpp to create a private_server. +tbb_server* make_private_server( tbb_client& client ) { + return new( tbb::cache_aligned_allocator<private_server>().allocate(1) ) private_server(client); +} + +} // namespace rml +} // namespace internal +} // namespace tbb diff --git a/src/tbb/src/tbb/queuing_mutex.cpp b/src/tbb/src/tbb/queuing_mutex.cpp new file mode 100644 index 0000000..0d4f578 --- /dev/null +++ b/src/tbb/src/tbb/queuing_mutex.cpp @@ -0,0 +1,117 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/queuing_mutex.h" +#include "tbb/tbb_machine.h" +#include "tbb/tbb_stddef.h" +#include "tbb_misc.h" +#include "itt_notify.h" + +namespace tbb { + +using namespace internal; + +//! A method to acquire queuing_mutex lock +void queuing_mutex::scoped_lock::acquire( queuing_mutex& m ) +{ + __TBB_ASSERT( !this->mutex, "scoped_lock is already holding a mutex"); + + // Must set all fields before the fetch_and_store, because once the + // fetch_and_store executes, *this becomes accessible to other threads. + mutex = &m; + next = NULL; + going = 0; + + // The fetch_and_store must have release semantics, because we are + // "sending" the fields initialized above to other processors. + scoped_lock* pred = m.q_tail.fetch_and_store<tbb::release>(this); + if( pred ) { + ITT_NOTIFY(sync_prepare, mutex); +#if TBB_USE_ASSERT + __TBB_control_consistency_helper(); // on "m.q_tail" + __TBB_ASSERT( !pred->next, "the predecessor has another successor!"); +#endif + pred->next = this; + spin_wait_while_eq( going, 0ul ); + } + ITT_NOTIFY(sync_acquired, mutex); + + // Force acquire so that user's critical section receives correct values + // from processor that was previously in the user's critical section. + __TBB_load_with_acquire(going); +} + +//! A method to acquire queuing_mutex if it is free +bool queuing_mutex::scoped_lock::try_acquire( queuing_mutex& m ) +{ + __TBB_ASSERT( !this->mutex, "scoped_lock is already holding a mutex"); + + // Must set all fields before the fetch_and_store, because once the + // fetch_and_store executes, *this becomes accessible to other threads. + next = NULL; + going = 0; + + // The CAS must have release semantics, because we are + // "sending" the fields initialized above to other processors. + if( m.q_tail.compare_and_swap<tbb::release>(this, NULL) ) + return false; + + // Force acquire so that user's critical section receives correct values + // from processor that was previously in the user's critical section. + // try_acquire should always have acquire semantic, even if failed. + __TBB_load_with_acquire(going); + mutex = &m; + ITT_NOTIFY(sync_acquired, mutex); + return true; +} + +//! A method to release queuing_mutex lock +void queuing_mutex::scoped_lock::release( ) +{ + __TBB_ASSERT(this->mutex!=NULL, "no lock acquired"); + + ITT_NOTIFY(sync_releasing, mutex); + if( !next ) { + if( this == mutex->q_tail.compare_and_swap<tbb::release>(NULL, this) ) { + // this was the only item in the queue, and the queue is now empty. + goto done; + } + // Someone in the queue + spin_wait_while_eq( next, (scoped_lock*)0 ); + } + __TBB_ASSERT(next,NULL); + __TBB_store_with_release(next->going, 1); +done: + initialize(); +} + +void queuing_mutex::internal_construct() { + ITT_SYNC_CREATE(this, _T("tbb::queuing_mutex"), _T("")); +} + +} // namespace tbb diff --git a/src/tbb/src/tbb/queuing_rw_mutex.cpp b/src/tbb/src/tbb/queuing_rw_mutex.cpp new file mode 100644 index 0000000..25eabfa --- /dev/null +++ b/src/tbb/src/tbb/queuing_rw_mutex.cpp @@ -0,0 +1,505 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/** Before making any changes in the implementation, please emulate algorithmic changes + with SPIN tool using <TBB directory>/tools/spin_models/ReaderWriterMutex.pml. + There could be some code looking as "can be restructured" but its structure does matter! */ + +#include "tbb/queuing_rw_mutex.h" +#include "tbb/tbb_machine.h" +#include "tbb/tbb_stddef.h" +#include "tbb/tbb_machine.h" +#include "itt_notify.h" + + +namespace tbb { + +using namespace internal; + +//! Flag bits in a state_t that specify information about a locking request. +enum state_t_flags { + STATE_NONE = 0, + STATE_WRITER = 1<<0, + STATE_READER = 1<<1, + STATE_READER_UNBLOCKNEXT = 1<<2, + STATE_ACTIVEREADER = 1<<3, + STATE_UPGRADE_REQUESTED = 1<<4, + STATE_UPGRADE_WAITING = 1<<5, + STATE_UPGRADE_LOSER = 1<<6, + STATE_COMBINED_WAITINGREADER = STATE_READER | STATE_READER_UNBLOCKNEXT, + STATE_COMBINED_READER = STATE_COMBINED_WAITINGREADER | STATE_ACTIVEREADER, + STATE_COMBINED_UPGRADING = STATE_UPGRADE_WAITING | STATE_UPGRADE_LOSER +}; + +const unsigned char RELEASED = 0; +const unsigned char ACQUIRED = 1; + +inline bool queuing_rw_mutex::scoped_lock::try_acquire_internal_lock() +{ + return as_atomic(my_internal_lock).compare_and_swap<tbb::acquire>(ACQUIRED,RELEASED) == RELEASED; +} + +inline void queuing_rw_mutex::scoped_lock::acquire_internal_lock() +{ + // Usually, we would use the test-test-and-set idiom here, with exponential backoff. + // But so far, experiments indicate there is no value in doing so here. + while( !try_acquire_internal_lock() ) { + __TBB_Pause(1); + } +} + +inline void queuing_rw_mutex::scoped_lock::release_internal_lock() +{ + __TBB_store_with_release(my_internal_lock,RELEASED); +} + +inline void queuing_rw_mutex::scoped_lock::wait_for_release_of_internal_lock() +{ + spin_wait_until_eq(my_internal_lock, RELEASED); +} + +inline void queuing_rw_mutex::scoped_lock::unblock_or_wait_on_internal_lock( uintptr_t flag ) { + if( flag ) + wait_for_release_of_internal_lock(); + else + release_internal_lock(); +} + +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) + // Workaround for overzealous compiler warnings + #pragma warning (push) + #pragma warning (disable: 4311 4312) +#endif + +//! A view of a T* with additional functionality for twiddling low-order bits. +template<typename T> +class tricky_atomic_pointer: no_copy { +public: + typedef typename atomic_selector<sizeof(T*)>::word word; + + template<memory_semantics M> + static T* fetch_and_add( T* volatile * location, word addend ) { + return reinterpret_cast<T*>( atomic_traits<sizeof(T*),M>::fetch_and_add(location, addend) ); + } + template<memory_semantics M> + static T* fetch_and_store( T* volatile * location, T* value ) { + return reinterpret_cast<T*>( atomic_traits<sizeof(T*),M>::fetch_and_store(location, reinterpret_cast<word>(value)) ); + } + template<memory_semantics M> + static T* compare_and_swap( T* volatile * location, T* value, T* comparand ) { + return reinterpret_cast<T*>( + atomic_traits<sizeof(T*),M>::compare_and_swap(location, reinterpret_cast<word>(value), + reinterpret_cast<word>(comparand)) + ); + } + + T* & ref; + tricky_atomic_pointer( T*& original ) : ref(original) {}; + tricky_atomic_pointer( T* volatile & original ) : ref(original) {}; + T* operator&( word operand2 ) const { + return reinterpret_cast<T*>( reinterpret_cast<word>(ref) & operand2 ); + } + T* operator|( word operand2 ) const { + return reinterpret_cast<T*>( reinterpret_cast<word>(ref) | operand2 ); + } +}; + +typedef tricky_atomic_pointer<queuing_rw_mutex::scoped_lock> tricky_pointer; + +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) + // Workaround for overzealous compiler warnings + #pragma warning (pop) +#endif + +//! Mask for low order bit of a pointer. +static const tricky_pointer::word FLAG = 0x1; + +inline +uintptr_t get_flag( queuing_rw_mutex::scoped_lock* ptr ) { + return uintptr_t(ptr) & FLAG; +} + +//------------------------------------------------------------------------ +// Methods of queuing_rw_mutex::scoped_lock +//------------------------------------------------------------------------ + +//! A method to acquire queuing_rw_mutex lock +void queuing_rw_mutex::scoped_lock::acquire( queuing_rw_mutex& m, bool write ) +{ + __TBB_ASSERT( !my_mutex, "scoped_lock is already holding a mutex"); + + // Must set all fields before the fetch_and_store, because once the + // fetch_and_store executes, *this becomes accessible to other threads. + my_mutex = &m; + __TBB_store_relaxed(my_prev , (scoped_lock*)0); + __TBB_store_relaxed(my_next , (scoped_lock*)0); + __TBB_store_relaxed(my_going, 0); + my_state = state_t(write ? STATE_WRITER : STATE_READER); + my_internal_lock = RELEASED; + + queuing_rw_mutex::scoped_lock* pred = m.q_tail.fetch_and_store<tbb::release>(this); + + if( write ) { // Acquiring for write + + if( pred ) { + ITT_NOTIFY(sync_prepare, my_mutex); + pred = tricky_pointer(pred) & ~FLAG; + __TBB_ASSERT( !( uintptr_t(pred) & FLAG ), "use of corrupted pointer!" ); +#if TBB_USE_ASSERT + __TBB_control_consistency_helper(); // on "m.q_tail" + __TBB_ASSERT( !__TBB_load_relaxed(pred->my_next), "the predecessor has another successor!"); +#endif + __TBB_store_with_release(pred->my_next,this); + spin_wait_until_eq(my_going, 1); + } + + } else { // Acquiring for read +#if DO_ITT_NOTIFY + bool sync_prepare_done = false; +#endif + if( pred ) { + unsigned short pred_state; + __TBB_ASSERT( !__TBB_load_relaxed(my_prev), "the predecessor is already set" ); + if( uintptr_t(pred) & FLAG ) { + /* this is only possible if pred is an upgrading reader and it signals us to wait */ + pred_state = STATE_UPGRADE_WAITING; + pred = tricky_pointer(pred) & ~FLAG; + } else { + // Load pred->my_state now, because once pred->my_next becomes + // non-NULL, we must assume that *pred might be destroyed. + pred_state = pred->my_state.compare_and_swap<tbb::acquire>(STATE_READER_UNBLOCKNEXT, STATE_READER); + } + __TBB_store_relaxed(my_prev, pred); + __TBB_ASSERT( !( uintptr_t(pred) & FLAG ), "use of corrupted pointer!" ); +#if TBB_USE_ASSERT + __TBB_control_consistency_helper(); // on "m.q_tail" + __TBB_ASSERT( !__TBB_load_relaxed(pred->my_next), "the predecessor has another successor!"); +#endif + __TBB_store_with_release(pred->my_next,this); + if( pred_state != STATE_ACTIVEREADER ) { +#if DO_ITT_NOTIFY + sync_prepare_done = true; + ITT_NOTIFY(sync_prepare, my_mutex); +#endif + spin_wait_until_eq(my_going, 1); + } + } + + // The protected state must have been acquired here before it can be further released to any other reader(s): + unsigned short old_state = my_state.compare_and_swap<tbb::acquire>(STATE_ACTIVEREADER, STATE_READER); + if( old_state!=STATE_READER ) { +#if DO_ITT_NOTIFY + if( !sync_prepare_done ) + ITT_NOTIFY(sync_prepare, my_mutex); +#endif + // Failed to become active reader -> need to unblock the next waiting reader first + __TBB_ASSERT( my_state==STATE_READER_UNBLOCKNEXT, "unexpected state" ); + spin_wait_while_eq(my_next, (scoped_lock*)NULL); + /* my_state should be changed before unblocking the next otherwise it might finish + and another thread can get our old state and left blocked */ + my_state = STATE_ACTIVEREADER; + __TBB_store_with_release(my_next->my_going,1); + } + } + + ITT_NOTIFY(sync_acquired, my_mutex); + + // Force acquire so that user's critical section receives correct values + // from processor that was previously in the user's critical section. + __TBB_load_with_acquire(my_going); +} + +//! A method to acquire queuing_rw_mutex if it is free +bool queuing_rw_mutex::scoped_lock::try_acquire( queuing_rw_mutex& m, bool write ) +{ + __TBB_ASSERT( !my_mutex, "scoped_lock is already holding a mutex"); + + if( load<relaxed>(m.q_tail) ) + return false; // Someone already took the lock + + // Must set all fields before the fetch_and_store, because once the + // fetch_and_store executes, *this becomes accessible to other threads. + __TBB_store_relaxed(my_prev, (scoped_lock*)0); + __TBB_store_relaxed(my_next, (scoped_lock*)0); + __TBB_store_relaxed(my_going, 0); // TODO: remove dead assignment? + my_state = state_t(write ? STATE_WRITER : STATE_ACTIVEREADER); + my_internal_lock = RELEASED; + + // The CAS must have release semantics, because we are + // "sending" the fields initialized above to other processors. + if( m.q_tail.compare_and_swap<tbb::release>(this, NULL) ) + return false; // Someone already took the lock + // Force acquire so that user's critical section receives correct values + // from processor that was previously in the user's critical section. + // try_acquire should always have acquire semantic, even if failed. + __TBB_load_with_acquire(my_going); + my_mutex = &m; + ITT_NOTIFY(sync_acquired, my_mutex); + return true; +} + +//! A method to release queuing_rw_mutex lock +void queuing_rw_mutex::scoped_lock::release( ) +{ + __TBB_ASSERT(my_mutex!=NULL, "no lock acquired"); + + ITT_NOTIFY(sync_releasing, my_mutex); + + if( my_state == STATE_WRITER ) { // Acquired for write + + // The logic below is the same as "writerUnlock", but elides + // "return" from the middle of the routine. + // In the statement below, acquire semantics of reading my_next is required + // so that following operations with fields of my_next are safe. + scoped_lock* n = __TBB_load_with_acquire(my_next); + if( !n ) { + if( this == my_mutex->q_tail.compare_and_swap<tbb::release>(NULL, this) ) { + // this was the only item in the queue, and the queue is now empty. + goto done; + } + spin_wait_while_eq( my_next, (scoped_lock*)NULL ); + n = __TBB_load_with_acquire(my_next); + } + __TBB_store_relaxed(n->my_going, 2); // protect next queue node from being destroyed too early + if( n->my_state==STATE_UPGRADE_WAITING ) { + // the next waiting for upgrade means this writer was upgraded before. + acquire_internal_lock(); + queuing_rw_mutex::scoped_lock* tmp = tricky_pointer::fetch_and_store<tbb::release>(&(n->my_prev), NULL); + n->my_state = STATE_UPGRADE_LOSER; + __TBB_store_with_release(n->my_going,1); + unblock_or_wait_on_internal_lock(get_flag(tmp)); + } else { + __TBB_ASSERT( my_state & (STATE_COMBINED_WAITINGREADER | STATE_WRITER), "unexpected state" ); + __TBB_ASSERT( !( uintptr_t(__TBB_load_relaxed(n->my_prev)) & FLAG ), "use of corrupted pointer!" ); + __TBB_store_relaxed(n->my_prev, (scoped_lock*)0); + __TBB_store_with_release(n->my_going,1); + } + + } else { // Acquired for read + + queuing_rw_mutex::scoped_lock *tmp = NULL; +retry: + // Addition to the original paper: Mark my_prev as in use + queuing_rw_mutex::scoped_lock *pred = tricky_pointer::fetch_and_add<tbb::acquire>(&my_prev, FLAG); + + if( pred ) { + if( !(pred->try_acquire_internal_lock()) ) + { + // Failed to acquire the lock on pred. The predecessor either unlinks or upgrades. + // In the second case, it could or could not know my "in use" flag - need to check + tmp = tricky_pointer::compare_and_swap<tbb::release>(&my_prev, pred, tricky_pointer(pred) | FLAG ); + if( !(uintptr_t(tmp) & FLAG) ) { + // Wait for the predecessor to change my_prev (e.g. during unlink) + spin_wait_while_eq( my_prev, tricky_pointer(pred)|FLAG ); + // Now owner of pred is waiting for _us_ to release its lock + pred->release_internal_lock(); + } + // else the "in use" flag is back -> the predecessor didn't get it and will release itself; nothing to do + + tmp = NULL; + goto retry; + } + __TBB_ASSERT(pred && pred->my_internal_lock==ACQUIRED, "predecessor's lock is not acquired"); + __TBB_store_relaxed(my_prev, pred); + acquire_internal_lock(); + + __TBB_store_with_release(pred->my_next,reinterpret_cast<scoped_lock *>(NULL)); + + if( !__TBB_load_relaxed(my_next) && this != my_mutex->q_tail.compare_and_swap<tbb::release>(pred, this) ) { + spin_wait_while_eq( my_next, (void*)NULL ); + } + __TBB_ASSERT( !get_flag(__TBB_load_relaxed(my_next)), "use of corrupted pointer" ); + + // ensure acquire semantics of reading 'my_next' + if( scoped_lock *const l_next = __TBB_load_with_acquire(my_next) ) { // I->next != nil, TODO: rename to n after clearing up and adapting the n in the comment two lines below + // Equivalent to I->next->prev = I->prev but protected against (prev[n]&FLAG)!=0 + tmp = tricky_pointer::fetch_and_store<tbb::release>(&(l_next->my_prev), pred); + // I->prev->next = I->next; + __TBB_ASSERT(__TBB_load_relaxed(my_prev)==pred, NULL); + __TBB_store_with_release(pred->my_next, my_next); + } + // Safe to release in the order opposite to acquiring which makes the code simplier + pred->release_internal_lock(); + + } else { // No predecessor when we looked + acquire_internal_lock(); // "exclusiveLock(&I->EL)" + scoped_lock* n = __TBB_load_with_acquire(my_next); + if( !n ) { + if( this != my_mutex->q_tail.compare_and_swap<tbb::release>(NULL, this) ) { + spin_wait_while_eq( my_next, (scoped_lock*)NULL ); + n = __TBB_load_relaxed(my_next); + } else { + goto unlock_self; + } + } + __TBB_store_relaxed(n->my_going, 2); // protect next queue node from being destroyed too early + tmp = tricky_pointer::fetch_and_store<tbb::release>(&(n->my_prev), NULL); + __TBB_store_with_release(n->my_going,1); + } +unlock_self: + unblock_or_wait_on_internal_lock(get_flag(tmp)); + } +done: + spin_wait_while_eq( my_going, 2 ); + + initialize(); +} + +bool queuing_rw_mutex::scoped_lock::downgrade_to_reader() +{ + __TBB_ASSERT( my_state==STATE_WRITER, "no sense to downgrade a reader" ); + + ITT_NOTIFY(sync_releasing, my_mutex); + + if( ! __TBB_load_with_acquire(my_next) ) { + my_state = STATE_READER; + if( this==my_mutex->q_tail ) { + unsigned short old_state = my_state.compare_and_swap<tbb::release>(STATE_ACTIVEREADER, STATE_READER); + if( old_state==STATE_READER ) { + // Downgrade completed + return true; + } + } + /* wait for the next to register */ + spin_wait_while_eq( my_next, (void*)NULL ); + } + scoped_lock *const n = __TBB_load_relaxed(my_next); + __TBB_ASSERT( n, "still no successor at this point!" ); + if( n->my_state & STATE_COMBINED_WAITINGREADER ) + __TBB_store_with_release(n->my_going,1); + else if( n->my_state==STATE_UPGRADE_WAITING ) + // the next waiting for upgrade means this writer was upgraded before. + n->my_state = STATE_UPGRADE_LOSER; + my_state = STATE_ACTIVEREADER; + return true; +} + +bool queuing_rw_mutex::scoped_lock::upgrade_to_writer() +{ + __TBB_ASSERT( my_state==STATE_ACTIVEREADER, "only active reader can be upgraded" ); + + queuing_rw_mutex::scoped_lock * tmp; + queuing_rw_mutex::scoped_lock * me = this; + + ITT_NOTIFY(sync_releasing, my_mutex); + my_state = STATE_UPGRADE_REQUESTED; +requested: + __TBB_ASSERT( !(uintptr_t(__TBB_load_relaxed(my_next)) & FLAG), "use of corrupted pointer!" ); + acquire_internal_lock(); + if( this != my_mutex->q_tail.compare_and_swap<tbb::release>(tricky_pointer(me)|FLAG, this) ) { + spin_wait_while_eq( my_next, (void*)NULL ); + queuing_rw_mutex::scoped_lock * n; + n = tricky_pointer::fetch_and_add<tbb::acquire>(&my_next, FLAG); + unsigned short n_state = n->my_state; + /* the next reader can be blocked by our state. the best thing to do is to unblock it */ + if( n_state & STATE_COMBINED_WAITINGREADER ) + __TBB_store_with_release(n->my_going,1); + tmp = tricky_pointer::fetch_and_store<tbb::release>(&(n->my_prev), this); + unblock_or_wait_on_internal_lock(get_flag(tmp)); + if( n_state & (STATE_COMBINED_READER | STATE_UPGRADE_REQUESTED) ) { + // save n|FLAG for simplicity of following comparisons + tmp = tricky_pointer(n)|FLAG; + atomic_backoff backoff; + while(__TBB_load_relaxed(my_next)==tmp) { + if( my_state & STATE_COMBINED_UPGRADING ) { + if( __TBB_load_with_acquire(my_next)==tmp ) + __TBB_store_relaxed(my_next, n); + goto waiting; + } + backoff.pause(); + } + __TBB_ASSERT(__TBB_load_relaxed(my_next) != (tricky_pointer(n)|FLAG), NULL); + goto requested; + } else { + __TBB_ASSERT( n_state & (STATE_WRITER | STATE_UPGRADE_WAITING), "unexpected state"); + __TBB_ASSERT( (tricky_pointer(n)|FLAG) == __TBB_load_relaxed(my_next), NULL); + __TBB_store_relaxed(my_next, n); + } + } else { + /* We are in the tail; whoever comes next is blocked by q_tail&FLAG */ + release_internal_lock(); + } // if( this != my_mutex->q_tail... ) + my_state.compare_and_swap<tbb::acquire>(STATE_UPGRADE_WAITING, STATE_UPGRADE_REQUESTED); + +waiting: + __TBB_ASSERT( !( intptr_t(__TBB_load_relaxed(my_next)) & FLAG ), "use of corrupted pointer!" ); + __TBB_ASSERT( my_state & STATE_COMBINED_UPGRADING, "wrong state at upgrade waiting_retry" ); + __TBB_ASSERT( me==this, NULL ); + ITT_NOTIFY(sync_prepare, my_mutex); + /* if no one was blocked by the "corrupted" q_tail, turn it back */ + my_mutex->q_tail.compare_and_swap<tbb::release>( this, tricky_pointer(me)|FLAG ); + queuing_rw_mutex::scoped_lock * pred; + pred = tricky_pointer::fetch_and_add<tbb::acquire>(&my_prev, FLAG); + if( pred ) { + bool success = pred->try_acquire_internal_lock(); + pred->my_state.compare_and_swap<tbb::release>(STATE_UPGRADE_WAITING, STATE_UPGRADE_REQUESTED); + if( !success ) { + tmp = tricky_pointer::compare_and_swap<tbb::release>(&my_prev, pred, tricky_pointer(pred)|FLAG ); + if( uintptr_t(tmp) & FLAG ) { + spin_wait_while_eq(my_prev, pred); + pred = __TBB_load_relaxed(my_prev); + } else { + spin_wait_while_eq( my_prev, tricky_pointer(pred)|FLAG ); + pred->release_internal_lock(); + } + } else { + __TBB_store_relaxed(my_prev, pred); + pred->release_internal_lock(); + spin_wait_while_eq(my_prev, pred); + pred = __TBB_load_relaxed(my_prev); + } + if( pred ) + goto waiting; + } else { + // restore the corrupted my_prev field for possible further use (e.g. if downgrade back to reader) + __TBB_store_relaxed(my_prev, pred); + } + __TBB_ASSERT( !pred && !__TBB_load_relaxed(my_prev), NULL ); + + // additional lifetime issue prevention checks + // wait for the successor to finish working with my fields + wait_for_release_of_internal_lock(); + // now wait for the predecessor to finish working with my fields + spin_wait_while_eq( my_going, 2 ); + + // Acquire critical section indirectly from previous owner or directly from predecessor (TODO: not clear). + __TBB_control_consistency_helper(); // on either "my_mutex->q_tail" or "my_going" (TODO: not clear) + + bool result = ( my_state != STATE_UPGRADE_LOSER ); + my_state = STATE_WRITER; + __TBB_store_relaxed(my_going, 1); + + ITT_NOTIFY(sync_acquired, my_mutex); + return result; +} + +void queuing_rw_mutex::internal_construct() { + ITT_SYNC_CREATE(this, _T("tbb::queuing_rw_mutex"), _T("")); +} + +} // namespace tbb diff --git a/src/tbb/src/tbb/reader_writer_lock.cpp b/src/tbb/src/tbb/reader_writer_lock.cpp new file mode 100644 index 0000000..78c6177 --- /dev/null +++ b/src/tbb/src/tbb/reader_writer_lock.cpp @@ -0,0 +1,355 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/reader_writer_lock.h" +#include "tbb/tbb_machine.h" +#include "tbb/tbb_exception.h" +#include "itt_notify.h" + +#if defined(_MSC_VER) && defined(_Wp64) + // Workaround for overzealous compiler warnings in /Wp64 mode + #pragma warning (disable: 4244) +#endif + +namespace tbb { +namespace interface5 { + +const uintptr_t WFLAG1 = 0x1; // writer interested or active +const uintptr_t WFLAG2 = 0x2; // writers interested, no entering readers +const uintptr_t RFLAG = 0x4; // reader interested but not active +const uintptr_t RC_INCR = 0x8; // to adjust reader count + + +// Perform an atomic bitwise-OR on the operand, and return its previous value. +inline uintptr_t fetch_and_or(atomic<uintptr_t>& operand, uintptr_t value) { + for (tbb::internal::atomic_backoff b;;b.pause()) { + uintptr_t old = operand; + uintptr_t result = operand.compare_and_swap(old|value, old); + if (result==old) return result; + } +} + +// Perform an atomic bitwise-AND on the operand, and return its previous value. +inline uintptr_t fetch_and_and(atomic<uintptr_t>& operand, uintptr_t value) { + for (tbb::internal::atomic_backoff b;;b.pause()) { + uintptr_t old = operand; + uintptr_t result = operand.compare_and_swap(old&value, old); + if (result==old) return result; + } +} + +//! Spin WHILE the value at the location is greater than or equal to a given value +/** T and U should be comparable types. */ +template<typename T, typename U> +void spin_wait_while_geq( const volatile T& location, U value ) { + tbb::internal::atomic_backoff backoff; + while( location>=value ) backoff.pause(); +} + +//! Spin UNTIL (location & value) is true. +/** T and U should be comparable types. */ +template<typename T, typename U> +void spin_wait_until_and( const volatile T& location, U value ) { + tbb::internal::atomic_backoff backoff; + while( !(location & value) ) backoff.pause(); +} + + +void reader_writer_lock::internal_construct() { + reader_head = NULL; + writer_head = NULL; + writer_tail = NULL; + rdr_count_and_flags = 0; + my_current_writer = tbb_thread::id(); +#if TBB_USE_THREADING_TOOLS + ITT_SYNC_CREATE(this, _T("tbb::reader_writer_lock"), _T("")); +#endif /* TBB_USE_THREADING_TOOLS */ +} + +void reader_writer_lock::internal_destroy() { + __TBB_ASSERT(rdr_count_and_flags==0, "reader_writer_lock destroyed with pending readers/writers."); + __TBB_ASSERT(reader_head==NULL, "reader_writer_lock destroyed with pending readers."); + __TBB_ASSERT(writer_tail==NULL, "reader_writer_lock destroyed with pending writers."); + __TBB_ASSERT(writer_head==NULL, "reader_writer_lock destroyed with pending/active writers."); +} + +// Acquires the reader_writer_lock for write. If the lock is currently held in write +// mode by another context, the writer will block by spinning on a local variable. +// Throws exception improper_lock if the context tries to acquire a +// reader_writer_lock that it already has write ownership of. +void reader_writer_lock::lock() { + if (is_current_writer()) { // recursive lock attempt + // we don't support recursive writer locks; throw exception + tbb::internal::throw_exception(tbb::internal::eid_improper_lock); + } + else { + scoped_lock *a_writer_lock = new scoped_lock(); + (void) start_write(a_writer_lock); + } +} + +// Tries to acquire the reader_writer_lock for write. This function does not block. +// Return Value: True or false, depending on whether the lock is acquired or not. +// If the lock is already held by this acquiring context, try_lock() returns false. +bool reader_writer_lock::try_lock() { + if (is_current_writer()) { // recursive lock attempt + return false; + } + else { + scoped_lock *a_writer_lock = new scoped_lock(); + a_writer_lock->status = waiting_nonblocking; + return start_write(a_writer_lock); + } +} + +bool reader_writer_lock::start_write(scoped_lock *I) { + tbb_thread::id id = this_tbb_thread::get_id(); + scoped_lock *pred = NULL; + if (I->status == waiting_nonblocking) { + if ((pred = writer_tail.compare_and_swap(I, NULL)) != NULL) { + delete I; + return false; + } + } + else { + ITT_NOTIFY(sync_prepare, this); + pred = writer_tail.fetch_and_store(I); + } + if (pred) + pred->next = I; + else { + set_next_writer(I); + if (I->status == waiting_nonblocking) { + if (I->next) { // potentially more writers + set_next_writer(I->next); + } + else { // no more writers + writer_head.fetch_and_store(NULL); + if (I != writer_tail.compare_and_swap(NULL, I)) { // an incoming writer is in the process of being added + spin_wait_while_eq(I->next, (scoped_lock *)NULL); // wait for new writer to be added + __TBB_ASSERT(I->next, "There should be a node following the last writer."); + set_next_writer(I->next); + } + } + delete I; + return false; + } + } + spin_wait_while_eq(I->status, waiting); + ITT_NOTIFY(sync_acquired, this); + my_current_writer = id; + return true; +} + +void reader_writer_lock::set_next_writer(scoped_lock *W) { + writer_head = W; + if (W->status == waiting_nonblocking) { + if (rdr_count_and_flags.compare_and_swap(WFLAG1+WFLAG2, 0) == 0) { + W->status = active; + } + } + else { + if (fetch_and_or(rdr_count_and_flags, WFLAG1) & RFLAG) { // reader present + spin_wait_until_and(rdr_count_and_flags, WFLAG2); // block until readers set WFLAG2 + } + else { // no reader in timing window + __TBB_AtomicOR(&rdr_count_and_flags, WFLAG2); + } + spin_wait_while_geq(rdr_count_and_flags, RC_INCR); // block until readers finish + W->status = active; + } +} + +// Acquires the reader_writer_lock for read. If the lock is currently held by a writer, +// this reader will block and wait until the writers are done. +// Throws exception improper_lock when the context tries to acquire a reader_writer_lock +// that it already has write ownership of. +void reader_writer_lock::lock_read() { + if (is_current_writer()) { // recursive lock attempt + // we don't support writer->reader downgrade; throw exception + tbb::internal::throw_exception(tbb::internal::eid_improper_lock); + } + else { + scoped_lock_read a_reader_lock; + start_read(&a_reader_lock); + } +} + +// Tries to acquire the reader_writer_lock for read. This function does not block. +// Return Value: True or false, depending on whether the lock is acquired or not. +bool reader_writer_lock::try_lock_read() { + if (is_current_writer()) { // recursive lock attempt + return false; + } + else { + if (rdr_count_and_flags.fetch_and_add(RC_INCR) & (WFLAG1+WFLAG2)) { // writers present + rdr_count_and_flags -= RC_INCR; + return false; + } + else { // no writers + ITT_NOTIFY(sync_acquired, this); + return true; + } + } +} + +void reader_writer_lock::start_read(scoped_lock_read *I) { + ITT_NOTIFY(sync_prepare, this); + I->next = reader_head.fetch_and_store(I); + if (!I->next) { // first arriving reader in my group; set RFLAG, test writer flags + // unblock and/or update statuses of non-blocking readers + if (!(fetch_and_or(rdr_count_and_flags, RFLAG) & (WFLAG1+WFLAG2))) { // no writers + unblock_readers(); + } + } + __TBB_ASSERT(I->status == waiting || I->status == active, "Lock requests should be waiting or active before blocking."); + spin_wait_while_eq(I->status, waiting); // block + if (I->next) { + __TBB_ASSERT(I->next->status == waiting, NULL); + rdr_count_and_flags += RC_INCR; + I->next->status = active; // wake successor + } + ITT_NOTIFY(sync_acquired, this); +} + +void reader_writer_lock::unblock_readers() { + // clear rdr interest flag, increment rdr count + __TBB_ASSERT(rdr_count_and_flags&RFLAG, NULL); + rdr_count_and_flags += RC_INCR-RFLAG; + __TBB_ASSERT(rdr_count_and_flags >= RC_INCR, NULL); + // indicate clear of window + if (rdr_count_and_flags & WFLAG1 && !(rdr_count_and_flags & WFLAG2)) { + __TBB_AtomicOR(&rdr_count_and_flags, WFLAG2); + } + // unblock waiting readers + scoped_lock_read *head = reader_head.fetch_and_store(NULL); + __TBB_ASSERT(head, NULL); + __TBB_ASSERT(head->status == waiting, NULL); + head->status = active; +} + +// Releases the reader_writer_lock +void reader_writer_lock::unlock() { + if( my_current_writer!=tbb_thread::id() ) { + // A writer owns the lock + __TBB_ASSERT(is_current_writer(), "caller of reader_writer_lock::unlock() does not own the lock."); + __TBB_ASSERT(writer_head, NULL); + __TBB_ASSERT(writer_head->status==active, NULL); + scoped_lock *a_writer_lock = writer_head; + end_write(a_writer_lock); + __TBB_ASSERT(a_writer_lock != writer_head, "Internal error: About to turn writer_head into dangling reference."); + delete a_writer_lock; + } else { + end_read(); + } +} + +void reader_writer_lock::end_write(scoped_lock *I) { + __TBB_ASSERT(I==writer_head, "Internal error: can't unlock a thread that is not holding the lock."); + my_current_writer = tbb_thread::id(); + ITT_NOTIFY(sync_releasing, this); + if (I->next) { // potentially more writers + writer_head = I->next; + writer_head->status = active; + } + else { // No more writers; clear writer flag, test reader interest flag + __TBB_ASSERT(writer_head, NULL); + if (fetch_and_and(rdr_count_and_flags, ~(WFLAG1+WFLAG2)) & RFLAG) { + unblock_readers(); + } + writer_head.fetch_and_store(NULL); + if (I != writer_tail.compare_and_swap(NULL, I)) { // an incoming writer is in the process of being added + spin_wait_while_eq(I->next, (scoped_lock *)NULL); // wait for new writer to be added + __TBB_ASSERT(I->next, "There should be a node following the last writer."); + set_next_writer(I->next); + } + } +} + +void reader_writer_lock::end_read() { + ITT_NOTIFY(sync_releasing, this); + __TBB_ASSERT(rdr_count_and_flags >= RC_INCR, "unlock() called but no readers hold the lock."); + rdr_count_and_flags -= RC_INCR; +} + +inline bool reader_writer_lock::is_current_writer() { + return my_current_writer==this_tbb_thread::get_id(); +} + +// Construct with a blocking attempt to acquire a write lock on the passed reader_writer_lock +void reader_writer_lock::scoped_lock::internal_construct (reader_writer_lock& lock) { + mutex = &lock; + next = NULL; + status = waiting; + if (mutex->is_current_writer()) { // recursive lock attempt + // we don't support recursive writer locks; throw exception + tbb::internal::throw_exception(tbb::internal::eid_improper_lock); + } + else { // this thread holds no locks + (void) mutex->start_write(this); + } +} + +inline reader_writer_lock::scoped_lock::scoped_lock() : mutex(NULL), next(NULL) { + status = waiting; +} + +// Construct with a blocking attempt to acquire a write lock on the passed reader_writer_lock +void reader_writer_lock::scoped_lock_read::internal_construct (reader_writer_lock& lock) { + mutex = &lock; + next = NULL; + status = waiting; + if (mutex->is_current_writer()) { // recursive lock attempt + // we don't support writer->reader downgrade; throw exception + tbb::internal::throw_exception(tbb::internal::eid_improper_lock); + } + else { // this thread holds no locks + mutex->start_read(this); + } +} + +inline reader_writer_lock::scoped_lock_read::scoped_lock_read() : mutex(NULL), next(NULL) { + status = waiting; +} + +void reader_writer_lock::scoped_lock::internal_destroy() { + if (mutex) { + __TBB_ASSERT(mutex->is_current_writer(), "~scoped_lock() destroyed by thread different than thread that holds lock."); + mutex->end_write(this); + } + status = invalid; +} + +void reader_writer_lock::scoped_lock_read::internal_destroy() { + if (mutex) + mutex->end_read(); + status = invalid; +} + +} // namespace interface5 +} // namespace tbb diff --git a/src/tbb/src/tbb/recursive_mutex.cpp b/src/tbb/src/tbb/recursive_mutex.cpp new file mode 100644 index 0000000..2c848b6 --- /dev/null +++ b/src/tbb/src/tbb/recursive_mutex.cpp @@ -0,0 +1,143 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/recursive_mutex.h" +#include "itt_notify.h" + +namespace tbb { + +void recursive_mutex::scoped_lock::internal_acquire( recursive_mutex& m ) { +#if _WIN32||_WIN64 + switch( m.state ) { + case INITIALIZED: + // since we cannot look into the internal of the CriticalSection object + // we won't know how many times the lock has been acquired, and thus + // we won't know when we may safely set the state back to INITIALIZED + // if we change the state to HELD as in mutex.cpp. thus, we won't change + // the state for recursive_mutex + EnterCriticalSection( &m.impl ); + break; + case DESTROYED: + __TBB_ASSERT(false,"recursive_mutex::scoped_lock: mutex already destroyed"); + break; + default: + __TBB_ASSERT(false,"recursive_mutex::scoped_lock: illegal mutex state"); + break; + } +#else + int error_code = pthread_mutex_lock(&m.impl); + __TBB_ASSERT_EX(!error_code,"recursive_mutex::scoped_lock: pthread_mutex_lock failed"); +#endif /* _WIN32||_WIN64 */ + my_mutex = &m; +} + +void recursive_mutex::scoped_lock::internal_release() { + __TBB_ASSERT( my_mutex, "recursive_mutex::scoped_lock: not holding a mutex" ); +#if _WIN32||_WIN64 + switch( my_mutex->state ) { + case INITIALIZED: + LeaveCriticalSection( &my_mutex->impl ); + break; + case DESTROYED: + __TBB_ASSERT(false,"recursive_mutex::scoped_lock: mutex already destroyed"); + break; + default: + __TBB_ASSERT(false,"recursive_mutex::scoped_lock: illegal mutex state"); + break; + } +#else + int error_code = pthread_mutex_unlock(&my_mutex->impl); + __TBB_ASSERT_EX(!error_code, "recursive_mutex::scoped_lock: pthread_mutex_unlock failed"); +#endif /* _WIN32||_WIN64 */ + my_mutex = NULL; +} + +bool recursive_mutex::scoped_lock::internal_try_acquire( recursive_mutex& m ) { +#if _WIN32||_WIN64 + switch( m.state ) { + case INITIALIZED: + break; + case DESTROYED: + __TBB_ASSERT(false,"recursive_mutex::scoped_lock: mutex already destroyed"); + break; + default: + __TBB_ASSERT(false,"recursive_mutex::scoped_lock: illegal mutex state"); + break; + } +#endif /* _WIN32||_WIN64 */ + bool result; +#if _WIN32||_WIN64 + result = TryEnterCriticalSection(&m.impl)!=0; +#else + result = pthread_mutex_trylock(&m.impl)==0; +#endif /* _WIN32||_WIN64 */ + if( result ) + my_mutex = &m; + return result; +} + +void recursive_mutex::internal_construct() { +#if _WIN32||_WIN64 + InitializeCriticalSection(&impl); + state = INITIALIZED; +#else + pthread_mutexattr_t mtx_attr; + int error_code = pthread_mutexattr_init( &mtx_attr ); + if( error_code ) + tbb::internal::handle_perror(error_code,"recursive_mutex: pthread_mutexattr_init failed"); + + pthread_mutexattr_settype( &mtx_attr, PTHREAD_MUTEX_RECURSIVE ); + error_code = pthread_mutex_init( &impl, &mtx_attr ); + if( error_code ) + tbb::internal::handle_perror(error_code,"recursive_mutex: pthread_mutex_init failed"); + pthread_mutexattr_destroy( &mtx_attr ); +#endif /* _WIN32||_WIN64*/ + ITT_SYNC_CREATE(&impl, _T("tbb::recursive_mutex"), _T("")); +} + +void recursive_mutex::internal_destroy() { +#if _WIN32||_WIN64 + switch( state ) { + case INITIALIZED: + DeleteCriticalSection(&impl); + break; + case DESTROYED: + __TBB_ASSERT(false,"recursive_mutex: already destroyed"); + break; + default: + __TBB_ASSERT(false,"recursive_mutex: illegal state for destruction"); + break; + } + state = DESTROYED; +#else + int error_code = pthread_mutex_destroy(&impl); + __TBB_ASSERT_EX(!error_code,"recursive_mutex: pthread_mutex_destroy failed"); +#endif /* _WIN32||_WIN64 */ +} + +} // namespace tbb diff --git a/src/tbb/src/tbb/scheduler.cpp b/src/tbb/src/tbb/scheduler.cpp new file mode 100644 index 0000000..bea35a0 --- /dev/null +++ b/src/tbb/src/tbb/scheduler.cpp @@ -0,0 +1,1248 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/tbb_machine.h" + +#include "custom_scheduler.h" +#include "scheduler_utility.h" +#include "governor.h" +#include "market.h" +#include "arena.h" +#include "mailbox.h" +#include "observer_proxy.h" + +namespace tbb { +namespace internal { + +//------------------------------------------------------------------------ +// Library initialization +//------------------------------------------------------------------------ + +/** Defined in tbb_main.cpp **/ +extern generic_scheduler* (*AllocateSchedulerPtr)( arena*, size_t index ); + +inline generic_scheduler* allocate_scheduler ( arena* a, size_t index ) { + return AllocateSchedulerPtr(a, index); +} + +#if __TBB_TASK_GROUP_CONTEXT +spin_mutex the_context_state_propagation_mutex; + +uintptr_t the_context_state_propagation_epoch = 0; + +//! Context to be associated with dummy tasks of worker threads schedulers. +/** It is never used for its direct purpose, and is introduced solely for the sake + of avoiding one extra conditional branch in the end of wait_for_all method. **/ +static task_group_context the_dummy_context(task_group_context::isolated); +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +void Scheduler_OneTimeInitialization ( bool itt_present ) { + AllocateSchedulerPtr = itt_present ? &custom_scheduler<DefaultSchedulerTraits>::allocate_scheduler : + &custom_scheduler<IntelSchedulerTraits>::allocate_scheduler; +#if __TBB_TASK_GROUP_CONTEXT && __TBB_TASK_PRIORITY + // There are no tasks belonging to this fake task group. So it should never + // prevent tasks from being passed to execution. + the_dummy_context.my_priority = num_priority_levels - 1; +#endif /* __TBB_TASK_GROUP_CONTEXT && __TBB_TASK_PRIORITY */ +} + +//------------------------------------------------------------------------ +// scheduler interface +//------------------------------------------------------------------------ + +// A pure virtual destructor should still have a body +// so the one for tbb::internal::scheduler::~scheduler() is provided here +scheduler::~scheduler( ) {} + +//------------------------------------------------------------------------ +// generic_scheduler +//------------------------------------------------------------------------ + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // Suppress overzealous compiler warning about using 'this' in base initializer list. + #pragma warning(push) + #pragma warning(disable:4355) +#endif + +generic_scheduler::generic_scheduler( arena* a, size_t index ) + : my_stealing_threshold(0) + , my_arena_index(index) + , my_task_pool_size(0) + , my_arena_slot(&my_dummy_slot) + , my_market(NULL) + , my_arena(a) + , my_random( unsigned(this-(generic_scheduler*)NULL) ) + , my_free_list(NULL) + , my_innermost_running_task(NULL) + , my_dummy_task(NULL) + , my_ref_count(1) + , my_affinity_id(0) + , my_auto_initialized(false) +#if __TBB_SCHEDULER_OBSERVER + , my_local_last_observer_proxy(NULL) +#endif /* __TBB_SCHEDULER_OBSERVER */ +#if __TBB_COUNT_TASK_NODES + , my_task_node_count(0) +#endif /* __TBB_COUNT_TASK_NODES */ + , my_small_task_count(1) // Extra 1 is a guard reference + , my_return_list(NULL) +#if __TBB_TASK_GROUP_CONTEXT + , my_local_ctx_list_update(make_atomic(uintptr_t(0))) +#endif /* __TBB_TASK_GROUP_CONTEXT */ + , my_dispatching_task(NULL) +#if __TBB_TASK_PRIORITY + , my_ref_top_priority(NULL) + , my_offloaded_tasks(NULL) + , my_offloaded_task_list_tail_link(NULL) + , my_ref_reload_epoch(NULL) + , my_local_reload_epoch(0) + , my_pool_reshuffling_pending(false) +#endif /* __TBB_TASK_PRIORITY */ +#if __TBB_TASK_GROUP_CONTEXT + , my_nonlocal_ctx_list_update(make_atomic(uintptr_t(0))) +#endif /* __TBB_TASK_GROUP_CONTEXT */ +#if __TBB_SURVIVE_THREAD_SWITCH && TBB_USE_ASSERT + , my_cilk_state(cs_none) +#endif /* __TBB_SURVIVE_THREAD_SWITCH && TBB_USE_ASSERT */ +{ + my_dummy_slot.task_pool = allocate_task_pool(min_task_pool_size); + my_dummy_slot.hint_for_push = index ^ unsigned(this-(generic_scheduler*)NULL)>>16; // randomizer seed + my_dummy_slot.hint_for_pop = index; // initial value for round-robin + __TBB_ASSERT( my_task_pool_size == min_task_pool_size, NULL ); + __TBB_store_relaxed(my_dummy_slot.head, 0); + __TBB_store_relaxed(my_dummy_slot.tail, 0); + my_dummy_task = &allocate_task( sizeof(task), __TBB_CONTEXT_ARG(NULL, NULL) ); +#if __TBB_TASK_GROUP_CONTEXT + my_context_list_head.my_prev = &my_context_list_head; + my_context_list_head.my_next = &my_context_list_head; + ITT_SYNC_CREATE(&my_context_list_mutex, SyncType_Scheduler, SyncObj_ContextsList); +#endif /* __TBB_TASK_GROUP_CONTEXT */ + my_dummy_task->prefix().ref_count = 2; + ITT_SYNC_CREATE(&my_dummy_task->prefix().ref_count, SyncType_Scheduler, SyncObj_WorkerLifeCycleMgmt); + ITT_SYNC_CREATE(&my_return_list, SyncType_Scheduler, SyncObj_TaskReturnList); + assert_task_pool_valid(); +#if __TBB_SURVIVE_THREAD_SWITCH + my_cilk_unwatch_thunk.routine = NULL; +#endif /* __TBB_SURVIVE_THREAD_SWITCH */ +} + +#if _MSC_VER && !defined(__INTEL_COMPILER) + #pragma warning(pop) +#endif // warning 4355 is back + +#if TBB_USE_ASSERT > 1 +void generic_scheduler::assert_task_pool_valid() const { + acquire_task_pool(); + task** tp = my_dummy_slot.task_pool; + __TBB_ASSERT( my_task_pool_size >= min_task_pool_size, NULL ); + const size_t H = __TBB_load_relaxed(my_arena_slot->head); // mirror + const size_t T = __TBB_load_relaxed(my_arena_slot->tail); // mirror + __TBB_ASSERT( H <= T, NULL ); + for ( size_t i = 0; i < H; ++i ) + __TBB_ASSERT( tp[i] == poisoned_ptr, "Task pool corrupted" ); + for ( size_t i = H; i < T; ++i ) { + __TBB_ASSERT( (uintptr_t)tp[i] + 1 > 1u, "nil or invalid task pointer in the deque" ); + __TBB_ASSERT( tp[i]->prefix().state == task::ready || + tp[i]->prefix().extra_state == es_task_proxy, "task in the deque has invalid state" ); + } + for ( size_t i = T; i < my_task_pool_size; ++i ) + __TBB_ASSERT( tp[i] == poisoned_ptr, "Task pool corrupted" ); + release_task_pool(); +} +#endif /* TBB_USE_ASSERT > 1 */ + +#if TBB_USE_ASSERT +void generic_scheduler::fill_with_canary_pattern ( task** task_pool, size_t first, size_t last ) { + for ( size_t i = first; i < last; ++i ) + poison_pointer(task_pool[i]); +} +#endif /* TBB_USE_ASSERT */ + +void generic_scheduler::init_stack_info () { + // Stacks are growing top-down. Highest address is called "stack base", + // and the lowest is "stack limit". + __TBB_ASSERT( !my_stealing_threshold, "Stealing threshold has already been calculated" ); + size_t stack_size = my_market->worker_stack_size(); +#if USE_WINTHREAD +#if defined(_MSC_VER)&&_MSC_VER<1400 && !_WIN64 + NT_TIB *pteb = (NT_TIB*)__TBB_machine_get_current_teb(); +#else + NT_TIB *pteb = (NT_TIB*)NtCurrentTeb(); +#endif + __TBB_ASSERT( &pteb < pteb->StackBase && &pteb > pteb->StackLimit, "invalid stack info in TEB" ); + __TBB_ASSERT( stack_size >0, "stack_size not initialized?" ); + // When a thread is created with the attribute STACK_SIZE_PARAM_IS_A_RESERVATION, stack limit + // in the TIB points to the committed part of the stack only. This renders the expression + // "(uintptr_t)pteb->StackBase / 2 + (uintptr_t)pteb->StackLimit / 2" virtually useless. + // Thus for worker threads we use the explicit stack size we used while creating them. + // And for master threads we rely on the following fact and assumption: + // - the default stack size of a master thread on Windows is 1M; + // - if it was explicitly set by the application it is at least as large as the size of a worker stack. + if ( is_worker() || stack_size < MByte ) + my_stealing_threshold = (uintptr_t)pteb->StackBase - stack_size / 2; + else + my_stealing_threshold = (uintptr_t)pteb->StackBase - MByte / 2; +#else /* USE_PTHREAD */ + // There is no portable way to get stack base address in Posix, so we use + // non-portable method (on all modern Linux) or the simplified approach + // based on the common sense assumptions. The most important assumption + // is that the main thread's stack size is not less than that of other threads. + // See also comment 3 at the end of this file + void *stack_base = &stack_size; +#if __TBB_ipf + void *rsb_base = __TBB_get_bsp(); +#endif +#if __linux__ + size_t np_stack_size = 0; + void *stack_limit = NULL; + pthread_attr_t np_attr_stack; +#if __bgp__ + // Workaround pthread_attr_init() before pthread_getattr_np() prevents subsequent abort() in pthread_attr_destroy() when + // freeing an erroneously invalid pointer value for cpuset (refers to the implementation of opaque type pthread_attr_t). + if( 0 == pthread_attr_init(&np_attr_stack) ) +#endif + if( 0 == pthread_getattr_np(pthread_self(), &np_attr_stack) ) { + if ( 0 == pthread_attr_getstack(&np_attr_stack, &stack_limit, &np_stack_size) ) { +#if __TBB_ipf + pthread_attr_t attr_stack; + if ( 0 == pthread_attr_init(&attr_stack) ) { + if ( 0 == pthread_attr_getstacksize(&attr_stack, &stack_size) ) { + if ( np_stack_size < stack_size ) { + // We are in a secondary thread. Use reliable data. + // IA64 stack is split into RSE backup and memory parts + rsb_base = stack_limit; + stack_size = np_stack_size/2; + // Limit of the memory part of the stack + stack_limit = (char*)stack_limit + stack_size; + } + // We are either in the main thread or this thread stack + // is bigger that that of the main one. As we cannot discern + // these cases we fall back to the default (heuristic) values. + } + pthread_attr_destroy(&attr_stack); + } + // IA64 stack is split into RSE backup and memory parts + my_rsb_stealing_threshold = (uintptr_t)((char*)rsb_base + stack_size/2); +#endif /* __TBB_ipf */ + // Size of the stack free part + stack_size = size_t((char*)stack_base - (char*)stack_limit); + } + pthread_attr_destroy(&np_attr_stack); + } +#endif /* __linux__ */ + __TBB_ASSERT( stack_size>0, "stack size must be positive" ); + my_stealing_threshold = (uintptr_t)((char*)stack_base - stack_size/2); +#endif /* USE_PTHREAD */ +} + +#if __TBB_TASK_GROUP_CONTEXT +/** The function uses synchronization scheme similar to the one in the destructor + of task_group_context augmented with interlocked state change of each context + object. The purpose of this algo is to prevent threads doing nonlocal context + destruction from accessing destroyed owner-scheduler instance still pointed to + by the context object. **/ +void generic_scheduler::cleanup_local_context_list () { + // Detach contexts remaining in the local list + bool wait_for_concurrent_destroyers_to_leave = false; + uintptr_t local_count_snapshot = my_context_state_propagation_epoch; + my_local_ctx_list_update.store<relaxed>(1); + { + // This is just a definition. Actual lock is acquired only in case of conflict. + spin_mutex::scoped_lock lock; + // Full fence prevents reordering of store to my_local_ctx_list_update with + // load from my_nonlocal_ctx_list_update. + atomic_fence(); + // Check for the conflict with concurrent destroyer or cancelation propagator + if ( my_nonlocal_ctx_list_update.load<relaxed>() || local_count_snapshot != the_context_state_propagation_epoch ) + lock.acquire(my_context_list_mutex); + // No acquire fence is necessary for loading my_context_list_head.my_next, + // as the list can be updated by this thread only. + context_list_node_t *node = my_context_list_head.my_next; + while ( node != &my_context_list_head ) { + task_group_context &ctx = __TBB_get_object_ref(task_group_context, my_node, node); + __TBB_ASSERT( ctx.my_kind != task_group_context::binding_required, "Only a context bound to a root task can be detached" ); + node = node->my_next; + __TBB_ASSERT( is_alive(ctx.my_version_and_traits), "Walked into a destroyed context while detaching contexts from the local list" ); + // On 64-bit systems my_kind can be a 32-bit value padded with 32 uninitialized bits. + // So the cast below is necessary to throw off the higher bytes containing garbage + if ( (task_group_context::kind_type)(uintptr_t)__TBB_FetchAndStoreW(&ctx.my_kind, task_group_context::detached) == task_group_context::dying ) + wait_for_concurrent_destroyers_to_leave = true; + } + } + my_local_ctx_list_update.store<release>(0); + // Wait until other threads referencing this scheduler object finish with it + if ( wait_for_concurrent_destroyers_to_leave ) + spin_wait_until_eq( my_nonlocal_ctx_list_update, 0u ); +} +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +void generic_scheduler::free_scheduler() { + __TBB_ASSERT( !in_arena(), NULL ); +#if __TBB_TASK_GROUP_CONTEXT + cleanup_local_context_list(); +#endif /* __TBB_TASK_GROUP_CONTEXT */ + free_task<small_local_task>( *my_dummy_task ); + + // k accounts for a guard reference and each task that we deallocate. + intptr_t k = 1; + for(;;) { + while( task* t = my_free_list ) { + my_free_list = t->prefix().next; + deallocate_task(*t); + ++k; + } + if( my_return_list==plugged_return_list() ) + break; + my_free_list = (task*)__TBB_FetchAndStoreW( &my_return_list, (intptr_t)plugged_return_list() ); + } +#if __TBB_COUNT_TASK_NODES + my_market->update_task_node_count( my_task_node_count ); +#endif /* __TBB_COUNT_TASK_NODES */ + free_task_pool( my_dummy_slot.task_pool ); + my_dummy_slot.task_pool = NULL; + // Update my_small_task_count last. Doing so sooner might cause another thread to free *this. + __TBB_ASSERT( my_small_task_count>=k, "my_small_task_count corrupted" ); + governor::sign_off(this); + if( __TBB_FetchAndAddW( &my_small_task_count, -k )==k ) + NFS_Free( this ); +} + +task& generic_scheduler::allocate_task( size_t number_of_bytes, + __TBB_CONTEXT_ARG(task* parent, task_group_context* context) ) { + GATHER_STATISTIC(++my_counters.active_tasks); + task* t = my_free_list; + if( number_of_bytes<=quick_task_size ) { + if( t ) { + GATHER_STATISTIC(--my_counters.free_list_length); + __TBB_ASSERT( t->state()==task::freed, "free list of tasks is corrupted" ); + my_free_list = t->prefix().next; + } else if( my_return_list ) { + // No fence required for read of my_return_list above, because __TBB_FetchAndStoreW has a fence. + t = (task*)__TBB_FetchAndStoreW( &my_return_list, 0 ); // with acquire + __TBB_ASSERT( t, "another thread emptied the my_return_list" ); + __TBB_ASSERT( t->prefix().origin==this, "task returned to wrong my_return_list" ); + ITT_NOTIFY( sync_acquired, &my_return_list ); + my_free_list = t->prefix().next; + } else { + t = (task*)((char*)NFS_Allocate( task_prefix_reservation_size+quick_task_size, 1, NULL ) + task_prefix_reservation_size ); +#if __TBB_COUNT_TASK_NODES + ++my_task_node_count; +#endif /* __TBB_COUNT_TASK_NODES */ + t->prefix().origin = this; + ++my_small_task_count; + } + } else { + GATHER_STATISTIC(++my_counters.big_tasks); + t = (task*)((char*)NFS_Allocate( task_prefix_reservation_size+number_of_bytes, 1, NULL ) + task_prefix_reservation_size ); +#if __TBB_COUNT_TASK_NODES + ++my_task_node_count; +#endif /* __TBB_COUNT_TASK_NODES */ + t->prefix().origin = NULL; + } + task_prefix& p = t->prefix(); +#if __TBB_TASK_GROUP_CONTEXT + p.context = context; +#endif /* __TBB_TASK_GROUP_CONTEXT */ + // Obsolete. But still in use, so has to be assigned correct value here. + p.owner = this; + p.ref_count = 0; + // Obsolete. Assign some not outrageously out-of-place value for a while. + p.depth = 0; + p.parent = parent; + // In TBB 2.1 and later, the constructor for task sets extra_state to indicate the version of the tbb/task.h header. + // In TBB 2.0 and earlier, the constructor leaves extra_state as zero. + p.extra_state = 0; + p.affinity = 0; + p.state = task::allocated; + return *t; +} + +void generic_scheduler::free_nonlocal_small_task( task& t ) { + __TBB_ASSERT( t.state()==task::freed, NULL ); + generic_scheduler& s = *static_cast<generic_scheduler*>(t.prefix().origin); + __TBB_ASSERT( &s!=this, NULL ); + for(;;) { + task* old = s.my_return_list; + if( old==plugged_return_list() ) + break; + // Atomically insert t at head of s.my_return_list + t.prefix().next = old; + ITT_NOTIFY( sync_releasing, &s.my_return_list ); + if( __TBB_CompareAndSwapW( &s.my_return_list, (intptr_t)&t, (intptr_t)old )==(intptr_t)old ) { + GATHER_STATISTIC(++my_counters.free_list_length); + return; + } + } + deallocate_task(t); + if( __TBB_FetchAndDecrementWrelease( &s.my_small_task_count )==1 ) { + // We freed the last task allocated by scheduler s, so it's our responsibility + // to free the scheduler. + NFS_Free( &s ); + } +} + +size_t generic_scheduler::prepare_task_pool ( size_t num_tasks ) { + size_t T = __TBB_load_relaxed(my_arena_slot->tail); // mirror + if ( T + num_tasks <= my_task_pool_size ) + return T; + acquire_task_pool(); + // Below my_dummy_slot.task_pool is used as the lock on the task pool munges + // my_arena_slot->task_pool pointer + size_t H = __TBB_load_relaxed(my_arena_slot->head); // mirror + T -= H; + size_t new_size = T + num_tasks; + // If the free space at the beginning of the task pool is too short, we + // are likely facing a pathological single-producer-multiple-consumers + // scenario, and thus it's better to expand the task pool + if ( new_size <= my_task_pool_size - min_task_pool_size/4 ) { + // Relocate the busy part to the beginning of the deque + memmove( my_dummy_slot.task_pool, my_dummy_slot.task_pool + H, T * sizeof(task*) ); + fill_with_canary_pattern( my_dummy_slot.task_pool, T, my_arena_slot->tail ); + commit_relocated_tasks(T); + } + else { + // Grow task pool. As this operation is rare, and its cost is asymptotically + // amortizable, we can tolerate new task pool allocation done under the lock. + if ( new_size < 2 * my_task_pool_size ) + new_size = 2 * my_task_pool_size; + task** old_pool = my_dummy_slot.task_pool; + my_dummy_slot.task_pool = allocate_task_pool( new_size ); // updates my_task_pool_size + __TBB_ASSERT( T <= my_task_pool_size, "new task pool is too short" ); + memcpy( my_dummy_slot.task_pool, old_pool + H, T * sizeof(task*) ); + commit_relocated_tasks(T); + free_task_pool( old_pool ); + } + assert_task_pool_valid(); + return T; +} + +/** ATTENTION: + This method is mostly the same as generic_scheduler::lock_task_pool(), with + a little different logic of slot state checks (slot is either locked or points + to our task pool). + Thus if either of them is changed, consider changing the counterpart as well. **/ +inline void generic_scheduler::acquire_task_pool() const { + if ( !in_arena() ) + return; // we are not in arena - nothing to lock + atomic_backoff backoff; + bool sync_prepare_done = false; + for(;;) { +#if TBB_USE_ASSERT + __TBB_ASSERT( my_arena_slot == my_arena->my_slots + my_arena_index, "invalid arena slot index" ); + // Local copy of the arena slot task pool pointer is necessary for the next + // assertion to work correctly to exclude asynchronous state transition effect. + task** tp = my_arena_slot->task_pool; + __TBB_ASSERT( tp == LockedTaskPool || tp == my_dummy_slot.task_pool, "slot ownership corrupt?" ); +#endif + if( my_arena_slot->task_pool != LockedTaskPool && + __TBB_CompareAndSwapW( &my_arena_slot->task_pool, (intptr_t)LockedTaskPool, + (intptr_t)my_dummy_slot.task_pool ) == (intptr_t)my_dummy_slot.task_pool ) + { + // We acquired our own slot + ITT_NOTIFY(sync_acquired, my_arena_slot); + break; + } + else if( !sync_prepare_done ) { + // Start waiting + ITT_NOTIFY(sync_prepare, my_arena_slot); + sync_prepare_done = true; + } + // Someone else acquired a lock, so pause and do exponential backoff. + backoff.pause(); + } + __TBB_ASSERT( my_arena_slot->task_pool == LockedTaskPool, "not really acquired task pool" ); +} // generic_scheduler::acquire_task_pool + +inline void generic_scheduler::release_task_pool() const { + if ( !in_arena() ) + return; // we are not in arena - nothing to unlock + __TBB_ASSERT( my_arena_slot, "we are not in arena" ); + __TBB_ASSERT( my_arena_slot->task_pool == LockedTaskPool, "arena slot is not locked" ); + ITT_NOTIFY(sync_releasing, my_arena_slot); + __TBB_store_with_release( my_arena_slot->task_pool, my_dummy_slot.task_pool ); +} + +/** ATTENTION: + This method is mostly the same as generic_scheduler::acquire_task_pool(), + with a little different logic of slot state checks (slot can be empty, locked + or point to any task pool other than ours, and asynchronous transitions between + all these states are possible). + Thus if any of them is changed, consider changing the counterpart as well **/ +inline task** generic_scheduler::lock_task_pool( arena_slot* victim_arena_slot ) const { + task** victim_task_pool; + atomic_backoff backoff; + bool sync_prepare_done = false; + for(;;) { + victim_task_pool = victim_arena_slot->task_pool; + // NOTE: Do not use comparison of head and tail indices to check for + // the presence of work in the victim's task pool, as they may give + // incorrect indication because of task pool relocations and resizes. + if ( victim_task_pool == EmptyTaskPool ) { + // The victim thread emptied its task pool - nothing to lock + if( sync_prepare_done ) + ITT_NOTIFY(sync_cancel, victim_arena_slot); + break; + } + if( victim_task_pool != LockedTaskPool && + __TBB_CompareAndSwapW( &victim_arena_slot->task_pool, + (intptr_t)LockedTaskPool, (intptr_t)victim_task_pool ) == (intptr_t)victim_task_pool ) + { + // We've locked victim's task pool + ITT_NOTIFY(sync_acquired, victim_arena_slot); + break; + } + else if( !sync_prepare_done ) { + // Start waiting + ITT_NOTIFY(sync_prepare, victim_arena_slot); + sync_prepare_done = true; + } + GATHER_STATISTIC( ++my_counters.thieves_conflicts ); + // Someone else acquired a lock, so pause and do exponential backoff. + backoff.pause(); + } + __TBB_ASSERT( victim_task_pool == EmptyTaskPool || + (victim_arena_slot->task_pool == LockedTaskPool && victim_task_pool != LockedTaskPool), + "not really locked victim's task pool?" ); + return victim_task_pool; +} // generic_scheduler::lock_task_pool + +inline void generic_scheduler::unlock_task_pool( arena_slot* victim_arena_slot, + task** victim_task_pool ) const { + __TBB_ASSERT( victim_arena_slot, "empty victim arena slot pointer" ); + __TBB_ASSERT( victim_arena_slot->task_pool == LockedTaskPool, "victim arena slot is not locked" ); + ITT_NOTIFY(sync_releasing, victim_arena_slot); + __TBB_store_with_release( victim_arena_slot->task_pool, victim_task_pool ); +} + + +inline task* generic_scheduler::prepare_for_spawning( task* t ) { + __TBB_ASSERT( t->state()==task::allocated, "attempt to spawn task that is not in 'allocated' state" ); + t->prefix().state = task::ready; +#if TBB_USE_ASSERT + if( task* parent = t->parent() ) { + internal::reference_count ref_count = parent->prefix().ref_count; + __TBB_ASSERT( ref_count>=0, "attempt to spawn task whose parent has a ref_count<0" ); + __TBB_ASSERT( ref_count!=0, "attempt to spawn task whose parent has a ref_count==0 (forgot to set_ref_count?)" ); + parent->prefix().extra_state |= es_ref_count_active; + } +#endif /* TBB_USE_ASSERT */ + affinity_id dst_thread = t->prefix().affinity; + __TBB_ASSERT( dst_thread == 0 || is_version_3_task(*t), + "backwards compatibility to TBB 2.0 tasks is broken" ); + if( dst_thread != 0 && dst_thread != my_affinity_id ) { + task_proxy& proxy = (task_proxy&)allocate_task( sizeof(task_proxy), + __TBB_CONTEXT_ARG(NULL, NULL) ); + // Mark as a proxy + proxy.prefix().extra_state = es_task_proxy; + proxy.outbox = &my_arena->mailbox(dst_thread); + // Mark proxy as present in both locations (sender's task pool and destination mailbox) + proxy.task_and_tag = intptr_t(t) | task_proxy::location_mask; +#if __TBB_TASK_PRIORITY + proxy.prefix().context = t->prefix().context; +#endif /* __TBB_TASK_PRIORITY */ + ITT_NOTIFY( sync_releasing, proxy.outbox ); + // Mail the proxy - after this point t may be destroyed by another thread at any moment. + proxy.outbox->push(proxy); + return &proxy; + } + return t; +} + +/** Conceptually, this method should be a member of class scheduler. + But doing so would force us to publish class scheduler in the headers. */ +void generic_scheduler::local_spawn( task& first, task*& next ) { + __TBB_ASSERT( governor::is_set(this), NULL ); + if ( &first.prefix().next == &next ) { + // Single task is being spawned + size_t T = prepare_task_pool( 1 ); + my_dummy_slot.task_pool[T] = prepare_for_spawning( &first ); + commit_spawned_tasks( T + 1 ); + } + else { + // Task list is being spawned + task *arr[min_task_pool_size]; + fast_reverse_vector<task*> tasks(arr, min_task_pool_size); + task *t_next = NULL; + for( task* t = &first; ; t = t_next ) { + // If t is affinitized to another thread, it may already be executed + // and destroyed by the time prepare_for_spawning returns. + // So milk it while it is alive. + bool end = &t->prefix().next == &next; + t_next = t->prefix().next; + tasks.push_back( prepare_for_spawning(t) ); + if( end ) + break; + } + size_t num_tasks = tasks.size(); + size_t T = prepare_task_pool( num_tasks ); + tasks.copy_memory( my_dummy_slot.task_pool + T ); + commit_spawned_tasks( T + num_tasks ); + } + if ( !in_arena() ) + enter_arena(); + my_arena->advertise_new_work</*Spawned=*/true>(); + assert_task_pool_valid(); +} + +void generic_scheduler::local_spawn_root_and_wait( task& first, task*& next ) { + __TBB_ASSERT( governor::is_set(this), NULL ); + __TBB_ASSERT( &first, NULL ); + auto_empty_task dummy( __TBB_CONTEXT_ARG(this, first.prefix().context) ); + internal::reference_count n = 0; + for( task* t=&first; ; t=t->prefix().next ) { + ++n; + __TBB_ASSERT( !t->prefix().parent, "not a root task, or already running" ); + t->prefix().parent = &dummy; + if( &t->prefix().next==&next ) break; +#if __TBB_TASK_GROUP_CONTEXT + __TBB_ASSERT( t->prefix().context == t->prefix().next->prefix().context, + "all the root tasks in list must share the same context"); +#endif /* __TBB_TASK_GROUP_CONTEXT */ + } + dummy.prefix().ref_count = n+1; + if( n>1 ) + local_spawn( *first.prefix().next, next ); + local_wait_for_all( dummy, &first ); +} + +inline task* generic_scheduler::get_mailbox_task() { + __TBB_ASSERT( my_affinity_id>0, "not in arena" ); + while ( task_proxy* const tp = my_inbox.pop() ) { + if ( task* result = tp->extract_task<task_proxy::mailbox_bit>() ) { + ITT_NOTIFY( sync_acquired, my_inbox.outbox() ); + result->prefix().extra_state |= es_task_is_stolen; + return result; + } + // We have exclusive access to the proxy, and can destroy it. + free_task<small_task>(*tp); + } + return NULL; +} + +void generic_scheduler::local_enqueue( task& t +#if __TBB_TASK_PRIORITY + , priority_t prio +#endif /* __TBB_TASK_PRIORITY */ + ) +{ + __TBB_ASSERT( governor::is_set(this), NULL ); + __TBB_ASSERT( t.state()==task::allocated, "attempt to enqueue task that is not in 'allocated' state" ); + t.prefix().state = task::ready; + t.prefix().extra_state |= es_task_enqueued; // enqueued task marker + +#if TBB_USE_ASSERT + if( task* parent = t.parent() ) { + internal::reference_count ref_count = parent->prefix().ref_count; + __TBB_ASSERT( ref_count>=0, "attempt to enqueue task whose parent has a ref_count<0" ); + __TBB_ASSERT( ref_count!=0, "attempt to enqueue task whose parent has a ref_count==0 (forgot to set_ref_count?)" ); + parent->prefix().extra_state |= es_ref_count_active; + } + __TBB_ASSERT(t.prefix().affinity==affinity_id(0), "affinity is ignored for enqueued tasks"); +#endif /* TBB_USE_ASSERT */ + + __TBB_ASSERT( my_arena, "thread is not in any arena" ); +#if __TBB_TASK_PRIORITY + intptr_t p = prio ? normalize_priority(prio) : normalized_normal_priority; + assert_priority_valid(p); + task_stream &ts = my_arena->my_task_stream[p]; +#else /* !__TBB_TASK_PRIORITY */ + task_stream &ts = my_arena->my_task_stream; +#endif /* !__TBB_TASK_PRIORITY */ + ITT_NOTIFY(sync_releasing, &ts); + ts.push( &t, my_arena_slot->hint_for_push ); +#if __TBB_TASK_PRIORITY + if ( p != my_arena->my_top_priority ) + my_market->update_arena_priority( *my_arena, p ); +#endif /* __TBB_TASK_PRIORITY */ + my_arena->advertise_new_work< /*Spawned=*/ false >(); +#if __TBB_TASK_PRIORITY + if ( p != my_arena->my_top_priority ) + my_market->update_arena_priority( *my_arena, p ); +#endif /* __TBB_TASK_PRIORITY */ +} + +inline task* generic_scheduler::dequeue_task() { + task* result = NULL; +#if __TBB_TASK_PRIORITY + task_stream &ts = my_arena->my_task_stream[my_arena->my_top_priority]; +#else /* !__TBB_TASK_PRIORITY */ + task_stream &ts = my_arena->my_task_stream; +#endif /* !__TBB_TASK_PRIORITY */ + ts.pop(result, my_arena_slot->hint_for_pop); + if (result) + ITT_NOTIFY(sync_acquired, &ts); + return result; +} + +#if __TBB_TASK_PRIORITY +class auto_indicator : no_copy { + volatile bool& my_indicator; +public: + auto_indicator ( volatile bool& indicator ) : my_indicator(indicator) { my_indicator = true ;} + ~auto_indicator () { my_indicator = false; } +}; + +task* generic_scheduler::winnow_task_pool () { + GATHER_STATISTIC( ++my_counters.prio_winnowings ); + __TBB_ASSERT( in_arena(), NULL ); + __TBB_ASSERT( my_offloaded_tasks, "At least one task is expected to be already offloaded" ); + // To eliminate possible sinking of the store to the indicator below the subsequent + // store to my_arena_slot->tail, the stores should've either been separated + // by full fence or both use release fences. And resetting indicator should've + // been done with release fence. But since this is just an optimization, and + // the corresponding checking sequence in arena::is_out_of_work() is not atomic + // anyway, fences aren't used, so that not to penalize warmer path. + auto_indicator indicator(my_pool_reshuffling_pending); + // The purpose of the synchronization algorithm here is for the owner thread + // to avoid locking task pool most of the time. + size_t T0 = __TBB_load_relaxed(my_arena_slot->tail); + __TBB_store_relaxed( my_arena_slot->tail, __TBB_load_relaxed(my_arena_slot->head) - 1 ); + atomic_fence(); + size_t H = __TBB_load_relaxed(my_arena_slot->head); + size_t T = __TBB_load_relaxed(my_arena_slot->tail); + __TBB_ASSERT( (intptr_t)T <= (intptr_t)T0, NULL); + __TBB_ASSERT( (intptr_t)H >= (intptr_t)T || (H == T0 && T == T0), NULL ); + bool acquired = false; + if ( H == T ) { + // Either no contention with thieves during arbitration protocol execution or ... + if ( H >= T0 ) { + // ... the task pool got empty + reset_deque_and_leave_arena( /*locked=*/false ); + return NULL; + } + } + else { + // Contention with thieves detected. Now without taking lock it is impossible + // to define the current head value because of its jitter caused by continuing + // stealing attempts (the pool is not locked so far). + acquired = true; + acquire_task_pool(); + H = __TBB_load_relaxed(my_arena_slot->head); + if ( H >= T0 ) { + reset_deque_and_leave_arena( /*locked=*/true ); + return NULL; + } + } + size_t src, + dst = T0; + // Find the first task to offload. + for ( src = H; src < T0; ++src ) { + task &t = *my_dummy_slot.task_pool[src]; + intptr_t p = priority(t); + if ( p < *my_ref_top_priority ) { + // Position of the first offloaded task will be the starting point + // for relocation of subsequent tasks that survive winnowing. + dst = src; + offload_task( t, p ); + break; + } + } + for ( ++src; src < T0; ++src ) { + task &t = *my_dummy_slot.task_pool[src]; + intptr_t p = priority(t); + if ( p < *my_ref_top_priority ) + offload_task( t, p ); + else + my_dummy_slot.task_pool[dst++] = &t; + } + __TBB_ASSERT( T0 >= dst, NULL ); + task *t = H < dst ? my_dummy_slot.task_pool[--dst] : NULL; + if ( H == dst ) { + // No tasks remain the primary pool + reset_deque_and_leave_arena( acquired ); + } + else if ( acquired ) { + __TBB_ASSERT( !is_poisoned(my_dummy_slot.task_pool[H]), NULL ); + __TBB_store_relaxed( my_arena_slot->tail, dst ); + release_task_pool(); + } + else { + __TBB_ASSERT( !is_poisoned(my_dummy_slot.task_pool[H]), NULL ); + // Release fence is necessary to make sure possibly relocated task pointers + // become visible to potential thieves + __TBB_store_with_release( my_arena_slot->tail, dst ); + } + fill_with_canary_pattern( my_dummy_slot.task_pool, dst, T0 ); + assert_task_pool_valid(); + return t; +} + +task* generic_scheduler::reload_tasks ( task*& offloaded_tasks, task**& offloaded_task_list_link, intptr_t top_priority ) { + GATHER_STATISTIC( ++my_counters.prio_reloads ); + __TBB_ASSERT( !in_arena(), NULL ); + task *arr[min_task_pool_size]; + fast_reverse_vector<task*> tasks(arr, min_task_pool_size); + task **link = &offloaded_tasks; + task *t; + while ( (t = *link) ) { + task** next_ptr = &t->prefix().next_offloaded; + if ( priority(*t) >= top_priority ) { + tasks.push_back( t ); + // Note that owner is an alias of next_offloaded. Thus the following + // assignment overwrites *next_ptr + task* next = *next_ptr; + t->prefix().owner = this; + __TBB_ASSERT( t->prefix().state == task::ready || t->prefix().extra_state == es_task_proxy, NULL ); + *link = next; + } + else { + link = next_ptr; + } + } + if ( link == &offloaded_tasks ) { + offloaded_tasks = NULL; +#if TBB_USE_ASSERT + offloaded_task_list_link = NULL; +#endif /* TBB_USE_ASSERT */ + } + else { + __TBB_ASSERT( link, NULL ); + // Mark end of list + *link = NULL; + offloaded_task_list_link = link; + } + __TBB_ASSERT( link, NULL ); + size_t num_tasks = tasks.size(); + if ( num_tasks ) { + GATHER_STATISTIC( ++my_counters.prio_tasks_reloaded ); + size_t T = prepare_task_pool( num_tasks ); + tasks.copy_memory( my_dummy_slot.task_pool + T ); + if ( --num_tasks ) { + commit_spawned_tasks( T += num_tasks ); + enter_arena(); + my_arena->advertise_new_work</*Spawned=*/true>(); + } + __TBB_ASSERT( T == __TBB_load_relaxed(my_arena_slot->tail), NULL ); + __TBB_ASSERT( T < my_task_pool_size, NULL ); + t = my_dummy_slot.task_pool[T]; + poison_pointer(my_dummy_slot.task_pool[T]); + assert_task_pool_valid(); + } + return t; +} + +task* generic_scheduler::reload_tasks () { + uintptr_t reload_epoch = *my_ref_reload_epoch; + __TBB_ASSERT( my_offloaded_tasks, NULL ); + if ( my_local_reload_epoch == reload_epoch ) + return NULL; + __TBB_ASSERT( my_offloaded_tasks, NULL ); + intptr_t top_priority = effective_reference_priority(); + __TBB_ASSERT( (uintptr_t)top_priority < (uintptr_t)num_priority_levels, NULL ); + task *t = reload_tasks( my_offloaded_tasks, my_offloaded_task_list_tail_link, top_priority ); + if ( my_offloaded_tasks && (my_arena->my_bottom_priority >= top_priority || !my_arena->my_num_workers_requested) ) { + // Safeguard against deliberately relaxed synchronization while checking + // for the presence of work in arena (so that not to impact hot paths). + // Arena may be reset to empty state when offloaded low priority tasks + // are still present. This results in both bottom and top priority bounds + // becoming 'normal', which makes offloaded low priority tasks unreachable. + // Update arena's bottom priority to accommodate them. + + // First indicate the presence of lower-priority tasks + my_market->update_arena_priority( *my_arena, priority(*my_offloaded_tasks) ); + // Then mark arena as full to unlock arena priority level adjustment + // by arena::is_out_of_work(), and ensure worker's presence + my_arena->advertise_new_work</*Spawned=*/false>(); + } + my_local_reload_epoch = reload_epoch; + return t; +} +#endif /* __TBB_TASK_PRIORITY */ + +inline task* generic_scheduler::get_task() { + __TBB_ASSERT( in_arena(), NULL ); + task* result = NULL; + size_t T = __TBB_load_relaxed(my_arena_slot->tail); // mirror +retry: + __TBB_store_relaxed(my_arena_slot->tail, --T); + atomic_fence(); + if ( (intptr_t)__TBB_load_relaxed(my_arena_slot->head) > (intptr_t)T ) { + acquire_task_pool(); + size_t H = __TBB_load_relaxed(my_arena_slot->head); // mirror + if ( (intptr_t)H <= (intptr_t)T ) { + // The thief backed off - grab the task + // Task pool pointer from our arena slot is garbled by above taken lock. + result = my_dummy_slot.task_pool[T]; + __TBB_ASSERT( !is_poisoned(result), NULL ); + poison_pointer( my_dummy_slot.task_pool[T] ); + } + else { + __TBB_ASSERT ( H == __TBB_load_relaxed(my_arena_slot->head) + && T == __TBB_load_relaxed(my_arena_slot->tail) + && H == T + 1, "victim/thief arbitration algorithm failure" ); + } + if ( (intptr_t)H < (intptr_t)T ) + release_task_pool(); + else + reset_deque_and_leave_arena( /*locked=*/true ); + } + else { + __TBB_control_consistency_helper(); // on my_arena_slot->head + result = my_dummy_slot.task_pool[T]; + __TBB_ASSERT( !is_poisoned(result), NULL ); + poison_pointer( my_dummy_slot.task_pool[T] ); + } + if( result && is_proxy(*result) ) { + task_proxy &tp = *(task_proxy*)result; + result = tp.extract_task<task_proxy::pool_bit>(); + if( !result ) { + // Proxy was empty, so it's our responsibility to free it + free_task<small_task>(tp); + if ( in_arena() ) + goto retry; + __TBB_ASSERT( is_quiescent_local_task_pool_reset(), NULL ); + return NULL; + } + GATHER_STATISTIC( ++my_counters.proxies_executed ); + // Following assertion should be true because TBB 2.0 tasks never specify affinity, and hence are not proxied. + __TBB_ASSERT( is_version_3_task(*result), "backwards compatibility with TBB 2.0 broken" ); + // Task affinity has changed. + my_innermost_running_task = result; + result->note_affinity(my_affinity_id); + } + __TBB_ASSERT( result || is_quiescent_local_task_pool_reset(), NULL ); + return result; +} // generic_scheduler::get_task + +task* generic_scheduler::steal_task( arena_slot& victim_slot ) { + task** victim_pool = lock_task_pool( &victim_slot ); + if ( !victim_pool ) + return NULL; + task* result = NULL; + size_t H = __TBB_load_relaxed(victim_slot.head); // mirror + const size_t H0 = H; + int skip_and_bump = 0; // +1 for skipped task and +1 for bumped head&tail +retry: + __TBB_store_relaxed( victim_slot.head, ++H ); + atomic_fence(); + if ( (intptr_t)H > (intptr_t)__TBB_load_relaxed(victim_slot.tail) ) { + // Stealing attempt failed, deque contents has not been changed by us + GATHER_STATISTIC( ++my_counters.thief_backoffs ); + __TBB_store_relaxed( victim_slot.head, /*dead: H = */ H0 ); + skip_and_bump++; // trigger that we bumped head and tail + __TBB_ASSERT ( !result, NULL ); + } + else { + __TBB_control_consistency_helper(); // on victim_slot.tail + result = victim_pool[H-1]; + __TBB_ASSERT( !is_poisoned(result), NULL ); + if( is_proxy(*result) ) { + task_proxy& tp = *static_cast<task_proxy*>(result); + // If mailed task is likely to be grabbed by its destination thread, skip it. + if ( task_proxy::is_shared(tp.task_and_tag) && tp.outbox->recipient_is_idle() ) + { + GATHER_STATISTIC( ++my_counters.proxies_bypassed ); + result = NULL; + __TBB_ASSERT( skip_and_bump < 2, NULL ); + skip_and_bump = 1; // note we skipped a task + goto retry; + } + } + __TBB_ASSERT( result, NULL ); + const size_t H1 = H0 + 1; + if ( H1 < H ) { + // Some proxies in the task pool have been bypassed. Need to close + // the hole left by the stolen task. The following variant: + // victim_pool[H-1] = victim_pool[H0]; + // is of constant time, but creates a potential for degrading stealing + // mechanism efficiency and growing owner's stack size too much because + // of moving earlier split off (and thus larger) chunks closer to owner's + // end of the deque (tail). + // So we use linear time variant that is likely to be amortized to be + // near-constant time, though, and preserves stealing efficiency premises. + // These changes in the deque must be released to the owner. + memmove( victim_pool + H1, victim_pool + H0, (H - H1) * sizeof(task*) ); + __TBB_store_with_release( victim_slot.head, /*dead: H = */ H1 ); + if ( (intptr_t)H >= (intptr_t)__TBB_load_relaxed(victim_slot.tail) ) + skip_and_bump++; // trigger that we bumped head and tail + } + poison_pointer( victim_pool[H0] ); + } + unlock_task_pool( &victim_slot, victim_pool ); + __TBB_ASSERT( skip_and_bump <= 2, NULL ); + if( --skip_and_bump > 0 ) { // if both: task skipped and head&tail bumped + // Synchronize with snapshot as we bumped head and tail which can falsely trigger EMPTY state + atomic_fence(); + my_arena->advertise_new_work</*Spawned=*/true>(); + } + return result; +} + +inline void generic_scheduler::do_enter_arena() { + my_arena_slot = &my_arena->my_slots[my_arena_index]; + __TBB_ASSERT ( is_quiescent_local_task_pool_empty(), "task deque of a free slot must be empty" ); + const size_t H = __TBB_load_relaxed(my_dummy_slot.head); // mirror + const size_t T = __TBB_load_relaxed(my_dummy_slot.tail); // mirror + __TBB_ASSERT ( H < T, "entering arena without tasks to share" ); + __TBB_store_relaxed(my_arena_slot->head, H); + __TBB_store_relaxed(my_arena_slot->tail, T); + // Release signal on behalf of previously spawned tasks (when this thread was not in arena yet) + ITT_NOTIFY(sync_releasing, my_arena_slot); + __TBB_store_with_release( my_arena_slot->task_pool, my_dummy_slot.task_pool ); + // We'll leave arena only when it's empty, so clean up local instances of indices. + __TBB_store_relaxed(my_dummy_slot.head, /*dead: H =*/ 0); + __TBB_store_relaxed(my_dummy_slot.tail, /*dead: T =*/ 0); +} + +void generic_scheduler::enter_arena() { + __TBB_ASSERT ( my_arena, "no arena: initialization not completed?" ); + __TBB_ASSERT ( !in_arena(), "Repeated entry into arena attempted" ); + __TBB_ASSERT ( my_arena_index < my_arena->my_num_slots, "arena slot index is out-of-bound" ); + __TBB_ASSERT ( my_arena->my_slots[my_arena_index].task_pool == EmptyTaskPool, "someone else grabbed my arena slot?" ); + do_enter_arena(); +} + +void generic_scheduler::leave_arena() { + __TBB_ASSERT( in_arena(), "Not in arena" ); + // Do not reset my_arena_index. It will be used to (attempt to) re-acquire the slot next time + __TBB_ASSERT( &my_arena->my_slots[my_arena_index] == my_arena_slot, "arena slot and slot index mismatch" ); + __TBB_ASSERT ( my_arena_slot->task_pool == LockedTaskPool, "Task pool must be locked when leaving arena" ); + __TBB_ASSERT ( is_quiescent_local_task_pool_empty(), "Cannot leave arena when the task pool is not empty" ); + ITT_NOTIFY(sync_releasing, &my_arena->my_slots[my_arena_index]); + // No release fence is necessary here as this assignment precludes external + // accesses to the local task pool when becomes visible. Thus it is harmless + // if it gets hoisted above preceding local bookkeeping manipulations. + __TBB_store_relaxed( my_arena_slot->task_pool, EmptyTaskPool ); + my_arena_slot = &my_dummy_slot; +} + +generic_scheduler* generic_scheduler::create_worker( market& m, size_t index ) { + generic_scheduler* s = allocate_scheduler( NULL, index ); +#if __TBB_TASK_GROUP_CONTEXT + s->my_dummy_task->prefix().context = &the_dummy_context; + // Sync up the local cancellation state with the global one. No need for fence here. + s->my_context_state_propagation_epoch = the_context_state_propagation_epoch; +#endif /* __TBB_TASK_GROUP_CONTEXT */ + s->my_market = &m; + s->init_stack_info(); +#if __TBB_TASK_PRIORITY + s->my_ref_top_priority = &s->my_market->my_global_top_priority; + s->my_ref_reload_epoch = &s->my_market->my_global_reload_epoch; +#endif /* __TBB_TASK_PRIORITY */ + return s; +} + +generic_scheduler* generic_scheduler::create_master( arena& a ) { + generic_scheduler* s = allocate_scheduler( &a, 0 /*Master thread always occupies the first slot*/ ); + task& t = *s->my_dummy_task; + s->my_innermost_running_task = &t; + s->my_dispatching_task = &t; + t.prefix().ref_count = 1; + governor::sign_on(s); + __TBB_ASSERT( &task::self()==&t, "governor::sign_on failed?" ); +#if __TBB_TASK_GROUP_CONTEXT + // Context to be used by root tasks by default (if the user has not specified one). + // Allocation is done by NFS allocator because we cannot reuse memory allocated + // for task objects since the free list is empty at the moment. + t.prefix().context = a.my_master_default_ctx = + new ( NFS_Allocate(sizeof(task_group_context), 1, NULL) ) task_group_context(task_group_context::isolated); +#endif /* __TBB_TASK_GROUP_CONTEXT */ + s->my_market = a.my_market; + __TBB_ASSERT( s->my_arena_index == 0, "Master thread must occupy the first slot in its arena" ); + s->attach_mailbox(1); + a.my_slots[0].my_scheduler = s; +#if _WIN32|_WIN64 + __TBB_ASSERT( s->my_market, NULL ); + s->my_market->register_master( s->master_exec_resource ); +#endif /* _WIN32|_WIN64 */ + s->init_stack_info(); +#if __TBB_TASK_GROUP_CONTEXT + // Sync up the local cancellation state with the global one. No need for fence here. + s->my_context_state_propagation_epoch = the_context_state_propagation_epoch; +#endif +#if __TBB_TASK_PRIORITY + // In the current implementation master threads continue processing even when + // there are other masters with higher priority. Only TBB worker threads are + // redistributed between arenas based on the latters' priority. Thus master + // threads use arena's top priority as a reference point (in contrast to workers + // that use my_market->my_global_top_priority). + s->my_ref_top_priority = &s->my_arena->my_top_priority; + s->my_ref_reload_epoch = &s->my_arena->my_reload_epoch; +#endif /* __TBB_TASK_PRIORITY */ +#if __TBB_SCHEDULER_OBSERVER + // Process any existing observers. + s->notify_entry_observers(); +#endif /* __TBB_SCHEDULER_OBSERVER */ + return s; +} + +void generic_scheduler::cleanup_worker( void* arg, bool worker ) { + generic_scheduler& s = *(generic_scheduler*)arg; + __TBB_ASSERT( s.my_dummy_slot.task_pool, "cleaning up worker with missing task pool" ); +#if __TBB_SCHEDULER_OBSERVER + s.notify_exit_observers( worker ); +#endif /* __TBB_SCHEDULER_OBSERVER */ + // When comparing "head" and "tail" indices ">=" is used because this worker's + // task pool may still be published in the arena, and thieves can optimistically + // bump "head" (and then roll back). + __TBB_ASSERT( s.my_arena_slot->task_pool == EmptyTaskPool + || __TBB_load_relaxed(s.my_arena_slot->head) >= __TBB_load_relaxed(s.my_arena_slot->tail), + "worker has unfinished work at run down" ); + s.free_scheduler(); +} + +void generic_scheduler::cleanup_master() { + generic_scheduler& s = *this; // for similarity with cleanup_worker + __TBB_ASSERT( s.my_dummy_slot.task_pool, "cleaning up master with missing task pool" ); +#if __TBB_SCHEDULER_OBSERVER + s.notify_exit_observers(/*worker=*/false); +#endif /* __TBB_SCHEDULER_OBSERVER */ + if( in_arena() ) { + acquire_task_pool(); + if ( my_arena_slot->task_pool == EmptyTaskPool || + __TBB_load_relaxed(my_arena_slot->head) >= __TBB_load_relaxed(my_arena_slot->tail) ) + { + // Local task pool is empty + leave_arena(); + } + else { + // Master's local task pool may e.g. contain proxies of affinitized tasks. + release_task_pool(); + __TBB_ASSERT ( governor::is_set(this), "TLS slot is cleared before the task pool cleanup" ); + s.local_wait_for_all( *s.my_dummy_task, NULL ); + __TBB_ASSERT( !in_arena(), NULL ); + __TBB_ASSERT ( governor::is_set(this), "Other thread reused our TLS key during the task pool cleanup" ); + } + } +#if _WIN32|_WIN64 + __TBB_ASSERT( s.my_market, NULL ); + s.my_market->unregister_master( s.master_exec_resource ); +#endif /* _WIN32|_WIN64 */ + arena* a = s.my_arena; +#if __TBB_STATISTICS + *a->my_slots[0].my_counters += s.my_counters; +#endif /* __TBB_STATISTICS */ +#if __TBB_TASK_PRIORITY + __TBB_ASSERT( a->my_slots[0].my_scheduler, NULL ); + // Master's scheduler may be locked by a worker taking arena snapshot or by + // a thread propagating task group state change across the context tree. + while ( __TBB_CompareAndSwapW(&a->my_slots[0].my_scheduler, 0, (intptr_t)this) != (intptr_t)this ) + __TBB_Yield(); + __TBB_ASSERT( !a->my_slots[0].my_scheduler, NULL ); +#else /* !__TBB_TASK_PRIORITY */ + a->my_slots[0].my_scheduler = NULL; +#endif /* __TBB_TASK_PRIORITY */ + s.free_scheduler(); + // Resetting arena to EMPTY state (as earlier TBB versions did) should not be + // done here (or anywhere else in the master thread to that matter) because + // after introducing arena-per-master logic and fire-and-forget tasks doing + // so can result either in arena's premature destruction (at least without + // additional costly checks in workers) or in unnecessary arena state changes + // (and ensuing workers migration). +#if __TBB_STATISTICS_EARLY_DUMP + GATHER_STATISTIC( a->dump_arena_statistics() ); +#endif + a->on_thread_leaving( /*is_master*/ true ); +} + +#if __TBB_SCHEDULER_OBSERVER + void generic_scheduler::notify_entry_observers() { + my_local_last_observer_proxy = observer_proxy::process_list(my_local_last_observer_proxy,is_worker(),/*is_entry=*/true); + } + + void generic_scheduler::notify_exit_observers( bool worker ) { + observer_proxy::process_list(my_local_last_observer_proxy,worker,/*is_entry=*/false); + } +#endif /* __TBB_SCHEDULER_OBSERVER */ + +} // namespace internal +} // namespace tbb + +/* + Comments: + +1. The premise of the cancellation support implementation is that cancellations are + not part of the hot path of the program execution. Therefore all changes in its + implementation in order to reduce the overhead of the cancellation control flow + should be done only in ways that do not increase overhead of the normal execution. + + In general contexts are used by all threads and their descendants are created in + different threads as well. In order to minimize impact of the cross-thread tree + maintenance (first of all because of the synchronization), the tree of contexts + is split into pieces, each of which is handled by the only thread. Such pieces + are represented as lists of contexts, members of which are contexts that were + bound to their parents in the given thread. + + The context tree maintenance and cancellation propagation algorithms is designed + in such a manner that cross-thread access to a context list will take place only + when cancellation signal is sent (by user or when an exception happens), and + synchronization is necessary only then. Thus the normal execution flow (without + exceptions and cancellation) remains free from any synchronization done on + behalf of exception handling and cancellation support. + +2. Consider parallel cancellations at the different levels of the context tree: + + Ctx1 <- Cancelled by Thread1 |- Thread2 started processing + | | + Ctx2 |- Thread1 started processing + | T1 |- Thread2 finishes and syncs up local counters + Ctx3 <- Cancelled by Thread2 | + | |- Ctx5 is bound to Ctx2 + Ctx4 | + T2 |- Thread1 reaches Ctx2 + + Thread-propagator of each cancellation increments global counter. However the thread + propagating the cancellation from the outermost context (Thread1) may be the last + to finish. Which means that the local counters may be synchronized earlier (by Thread2, + at Time1) than it propagated cancellation into Ctx2 (at time Time2). If a new context + (Ctx5) is created and bound to Ctx2 between Time1 and Time2, checking its parent only + (Ctx2) may result in cancellation request being lost. + + This issue is solved by doing the whole propagation under the lock. + + If we need more concurrency while processing parallel cancellations, we could try + the following modification of the propagation algorithm: + + advance global counter and remember it + for each thread: + scan thread's list of contexts + for each thread: + sync up its local counter only if the global counter has not been changed + + However this version of the algorithm requires more analysis and verification. + +3. There is no portable way to get stack base address in Posix, however + the modern Linux versions provide pthread_attr_np API that can be used + to obtain thread's stack size and base address. Unfortunately even this + function does not provide enough information for the main thread on IA64 + (RSE spill area and memory stack are allocated as two separate discontinuous + chunks of memory), and there is no portable way to discern the main and + the secondary threads. + Thus for MacOS and IA64 Linux we use the TBB worker stack size for all + threads and use the current stack top as the stack base. This simplified + approach is based on the following assumptions: + 1) If the default stack size is insufficient for the user app needs, + the required amount will be explicitly specified by the user at + the point of the TBB scheduler initialization (as an argument to + tbb::task_scheduler_init constructor). + 2) When a master thread initializes the scheduler, it has enough space + on its stack. Here "enough" means "at least as much as worker threads + have". + 3) If the user app strives to conserve the memory by cutting stack size, + it should do this for TBB workers too (as in the #1). +*/ diff --git a/src/tbb/src/tbb/scheduler.h b/src/tbb/src/tbb/scheduler.h new file mode 100644 index 0000000..9260cff --- /dev/null +++ b/src/tbb/src/tbb/scheduler.h @@ -0,0 +1,700 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _TBB_scheduler_H +#define _TBB_scheduler_H + +#include "scheduler_common.h" +#include "mailbox.h" +#include "tbb_misc.h" // for FastRandom +#include "itt_notify.h" +#include "../rml/include/rml_tbb.h" + +#if __TBB_SURVIVE_THREAD_SWITCH +#include "cilk-tbb-interop.h" +#endif /* __TBB_SURVIVE_THREAD_SWITCH */ + +namespace tbb { +namespace internal { + +template<typename SchedulerTraits> class custom_scheduler; + +//------------------------------------------------------------------------ +// generic_scheduler +//------------------------------------------------------------------------ + +#if __TBB_TASK_GROUP_CONTEXT +struct scheduler_list_node_t { + scheduler_list_node_t *my_prev, + *my_next; +}; +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +#define EmptyTaskPool ((task**)0) +#define LockedTaskPool ((task**)~(intptr_t)0) + +#define LockedMaster ((generic_scheduler*)~(intptr_t)0) + +class governor; +class market; +class arena; + +#if __TBB_SCHEDULER_OBSERVER +class task_scheduler_observer_v3; +class observer_proxy; +#endif /* __TBB_SCHEDULER_OBSERVER */ + +//! Work stealing task scheduler. +/** None of the fields here are ever read or written by threads other than + the thread that creates the instance. + + Class generic_scheduler is an abstract base class that contains most of the scheduler, + except for tweaks specific to processors and tools (e.g. VTune). + The derived template class custom_scheduler<SchedulerTraits> fills in the tweaks. */ +class generic_scheduler: public scheduler, public ::rml::job { + friend class tbb::task; + friend class market; + friend class arena; + friend class allocate_root_proxy; + friend class governor; +#if __TBB_TASK_GROUP_CONTEXT + friend class allocate_root_with_context_proxy; + friend class tbb::task_group_context; +#endif /* __TBB_TASK_GROUP_CONTEXT */ +#if __TBB_SCHEDULER_OBSERVER + friend class task_scheduler_observer_v3; +#endif /* __TBB_SCHEDULER_OBSERVER */ + friend class scheduler; + template<typename SchedulerTraits> friend class custom_scheduler; + + //! If sizeof(task) is <=quick_task_size, it is handled on a free list instead of malloc'd. + static const size_t quick_task_size = 256-task_prefix_reservation_size; + + static bool is_version_3_task( task& t ) { + return (t.prefix().extra_state & 0x0F)>=0x1; + } + + //! Position in the call stack specifying its maximal filling when stealing is still allowed + uintptr_t my_stealing_threshold; +#if __TBB_ipf + //! Position in the RSE backup area specifying its maximal filling when stealing is still allowed + uintptr_t my_rsb_stealing_threshold; +#endif + + static const size_t null_arena_index = ~size_t(0); + + //! Index of the arena slot the scheduler occupies now, or occupied last time. + size_t my_arena_index; + + //! Capacity of the primary task pool (number of elements - pointers to task). + size_t my_task_pool_size; + + //! Pointer to the slot in the arena we own at the moment. + /** When out of arena it points to this scheduler's my_dummy_slot. **/ + arena_slot* my_arena_slot; + + inline bool in_arena () const; + + inline bool is_local_task_pool_quiescent () const; + + inline bool is_quiescent_local_task_pool_empty () const; + + inline bool is_quiescent_local_task_pool_reset () const; + + //! The market I am in + market* my_market; + + //! The arena that I own (if master) or am servicing at the moment (if worker) + arena* my_arena; + + //! Random number generator used for picking a random victim from which to steal. + FastRandom my_random; + + //! Free list of small tasks that can be reused. + task* my_free_list; + + //! Innermost task whose task::execute() is running. + task* my_innermost_running_task; + + //! Fake root task created by slave threads. + /** The task is used as the "parent" argument to method wait_for_all. */ + task* my_dummy_task; + + //! Reference count for scheduler + /** Number of task_scheduler_init objects that point to this scheduler */ + long my_ref_count; + + mail_inbox my_inbox; + + inline void attach_mailbox( affinity_id id ); + + //! The mailbox id assigned to this scheduler. + /** The id is assigned upon first entry into the arena. + TODO: how are id's being garbage collected? + TODO: master thread may enter arena and leave and then reenter. + We want to give it the same affinity_id upon reentry, if practical. + */ + affinity_id my_affinity_id; + + /* A couple of bools can be located here because space is otherwise just padding after my_affinity_id. */ + + //! True if *this was created by automatic TBB initialization + bool my_auto_initialized; + +#if __TBB_SCHEDULER_OBSERVER + //! Last observer_proxy processed by this scheduler + observer_proxy* my_local_last_observer_proxy; + + //! Notify any entry observers that have been created since the last call by this thread. + void notify_entry_observers(); + + //! Notify all exit observers that this thread is no longer participating in task scheduling. + void notify_exit_observers( bool is_worker ); +#endif /* __TBB_SCHEDULER_OBSERVER */ + +#if __TBB_COUNT_TASK_NODES + //! Net number of big task objects that have been allocated but not yet freed. + intptr_t my_task_node_count; +#endif /* __TBB_COUNT_TASK_NODES */ + + //! Sets up the data necessary for the stealing limiting heuristics + void init_stack_info (); + + //! Returns true if stealing is allowed + bool can_steal () { + int anchor; +#if __TBB_ipf + return my_stealing_threshold < (uintptr_t)&anchor && (uintptr_t)__TBB_get_bsp() < my_rsb_stealing_threshold; +#else + return my_stealing_threshold < (uintptr_t)&anchor; +#endif + } + + //! Actions common to enter_arena and try_enter_arena + void do_enter_arena(); + + //! Used by workers to enter the arena + /** Does not lock the task pool in case if arena slot has been successfully grabbed. **/ + void enter_arena(); + + //! Leave the arena + /** Leaving arena automatically releases the task pool if it is locked. **/ + void leave_arena(); + + //! Resets head and tail indices to 0, and leaves arena + /** Argument specifies whether the task pool is currently locked by the owner + (via acquire_task_pool).**/ + inline void reset_deque_and_leave_arena ( bool locked ); + + //! Locks victim's task pool, and returns pointer to it. The pointer can be NULL. + /** Garbles victim_arena_slot->task_pool for the duration of the lock. **/ + task** lock_task_pool( arena_slot* victim_arena_slot ) const; + + //! Unlocks victim's task pool + /** Restores victim_arena_slot->task_pool munged by lock_task_pool. **/ + void unlock_task_pool( arena_slot* victim_arena_slot, task** victim_task_pool ) const; + + //! Locks the local task pool + /** Garbles my_arena_slot->task_pool for the duration of the lock. Requires + correctly set my_dummy_slot.task_pool. **/ + void acquire_task_pool() const; + + //! Unlocks the local task pool + /** Restores my_arena_slot->task_pool munged by acquire_task_pool. Requires + correctly set my_dummy_slot.task_pool. **/ + void release_task_pool() const; + + //! Checks if t is affinitized to another thread, and if so, bundles it as proxy. + /** Returns either t or proxy containing t. **/ + task* prepare_for_spawning( task* t ); + + //! Makes newly spawned tasks visible to thieves + inline void commit_spawned_tasks( size_t new_tail ); + + //! Makes relocated tasks visible to thieves and releases the local task pool. + /** Obviously, the task pool must be locked when caaling this method. **/ + inline void commit_relocated_tasks( size_t new_tail ); + + //! Get a task from the local pool. + /** Called only by the pool owner. + Returns the pointer to the task or NULL if the pool is empty. + In the latter case compacts the pool. **/ + task* get_task(); + + //! Attempt to get a task from the mailbox. + /** Gets a task only if it has not been executed by its sender or a thief + that has stolen it from the sender's task pool. Otherwise returns NULL. + + This method is intended to be used only by the thread extracting the proxy + from its mailbox. (In contrast to local task pool, mailbox can be read only + by its owner). **/ + task* get_mailbox_task(); + + //! True if t is a task_proxy + static bool is_proxy( const task& t ) { + return t.prefix().extra_state==es_task_proxy; + } + + //! Get a task from the starvation-resistant task stream of the current arena. + /** Returns the pointer to the task, or NULL if the attempt was unsuccessful. + The latter case does not mean that the stream is drained, however. **/ + task* dequeue_task(); + + //! Steal task from another scheduler's ready pool. + task* steal_task( arena_slot& victim_arena_slot ); + + /** Initial size of the task deque sufficient to serve without reallocation + 4 nested parallel_for calls with iteration space of 65535 grains each. **/ + static const size_t min_task_pool_size = 64; + + //! Allocate task pool containing at least n elements. + inline task** allocate_task_pool( size_t n ); + + //! Deallocate task pool that was allocated by means of allocate_task_pool. + static void free_task_pool( task** pool ) { + __TBB_ASSERT( pool, "attempt to free NULL TaskPool" ); + NFS_Free( pool ); + } + + //! Makes sure that the task pool can accommodate at least n more elements + /** If necessary relocates existing task pointers or grows the ready task deque. + Returns (possible updated) tail index (not accounting for n). **/ + size_t prepare_task_pool( size_t n ); + + //! Initialize a scheduler for a master thread. + static generic_scheduler* create_master( arena& a ); + + //! Perform necessary cleanup when a master thread stops using TBB. + void cleanup_master(); + + //! Initialize a scheduler for a worker thread. + static generic_scheduler* create_worker( market& m, size_t index ); + + //! Perform necessary cleanup when a worker thread finishes. + static void cleanup_worker( void* arg, bool worker ); + +protected: + generic_scheduler( arena*, size_t index ); + +#if TBB_USE_ASSERT > 1 + //! Check that internal data structures are in consistent state. + /** Raises __TBB_ASSERT failure if inconsistency is found. */ + void assert_task_pool_valid () const; +#else + void assert_task_pool_valid() const {} +#endif /* TBB_USE_ASSERT <= 1 */ + +#if TBB_USE_ASSERT + static void fill_with_canary_pattern ( task** task_pool, size_t first, size_t last ); +#else + static void fill_with_canary_pattern ( task**, size_t, size_t ) {} +#endif /* !TBB_USE_ASSERT */ + +public: + /*override*/ + inline void spawn( task& first, task*& next ); + + /*override*/ + inline void spawn_root_and_wait( task& first, task*& next ); + + /*override*/ + inline void enqueue( task&, void* reserved ); + +#if __TBB_TASK_PRIORITY + void local_enqueue( task&, priority_t prio ); +#else /* !__TBB_TASK_PRIORITY */ + void local_enqueue( task& ); +#endif /* !__TBB_TASK_PRIORITY */ + + void local_spawn( task& first, task*& next ); + void local_spawn_root_and_wait( task& first, task*& next ); + virtual void local_wait_for_all( task& parent, task* child ) = 0; + + //! Destroy and deallocate this scheduler object + void free_scheduler(); + + //! Allocate task object, either from the heap or a free list. + /** Returns uninitialized task object with initialized prefix. */ + task& allocate_task( size_t number_of_bytes, + __TBB_CONTEXT_ARG(task* parent, task_group_context* context) ); + + //! Put task on free list. + /** Does not call destructor. */ + template<free_task_hint h> + void free_task( task& t ); + + //! Return task object to the memory allocator. + inline void deallocate_task( task& t ); + + //! True if running on a worker thread, false otherwise. + inline bool is_worker(); + + //! True if the scheduler is on the outermost dispatch level in a master thread. + /** Returns true when this scheduler instance is associated with an application + thread, and is not executing any TBB task. This includes being in a TBB + dispatch loop (one of wait_for_all methods) invoked directly from that thread. **/ + inline bool master_outermost_level () const; + +#if __TBB_TASK_GROUP_CONTEXT + //! Returns task group context used by this scheduler instance. + /** This context is associated with root tasks created by a master thread + without explicitly specified context object outside of any running task. + + Note that the default context of a worker thread is never accessed by + user code (directly or indirectly). **/ + inline task_group_context* default_context (); +#endif /* __TBB_TASK_GROUP_CONTEXT */ + + //! Returns number of worker threads in the arena this thread belongs to. + unsigned number_of_workers_in_my_arena(); + +#if __TBB_COUNT_TASK_NODES + intptr_t get_task_node_count( bool count_arena_workers = false ); +#endif /* __TBB_COUNT_TASK_NODES */ + + //! Special value used to mark my_return_list as not taking any more entries. + static task* plugged_return_list() {return (task*)(intptr_t)(-1);} + + //! Number of small tasks that have been allocated by this scheduler. + intptr_t my_small_task_count; + + //! List of small tasks that have been returned to this scheduler by other schedulers. + task* my_return_list; + + //! Try getting a task from other threads (via mailbox, stealing, FIFO queue, orphans adoption). + /** Returns obtained task or NULL if all attempts fail. */ + virtual task* receive_or_steal_task( __TBB_atomic reference_count& completion_ref_count, + bool return_if_no_work ) = 0; + + //! Free a small task t that that was allocated by a different scheduler + void free_nonlocal_small_task( task& t ); + +#if __TBB_TASK_GROUP_CONTEXT + //! Padding isolating thread-local members from members that can be written to by other threads. + char _padding1[NFS_MaxLineSize - sizeof(context_list_node_t)]; + + //! Head of the thread specific list of task group contexts. + context_list_node_t my_context_list_head; + + //! Mutex protecting access to the list of task group contexts. + spin_mutex my_context_list_mutex; + + //! Last state propagation epoch known to this thread + /** Together with the_context_state_propagation_epoch constitute synchronization protocol + that keeps hot path of task group context construction destruction mostly + lock-free. + When local epoch equals the global one, the state of task group contexts + registered with this thread is consistent with that of the task group trees + they belong to. **/ + uintptr_t my_context_state_propagation_epoch; + + //! Flag indicating that a context is being destructed by its owner thread + /** Together with my_nonlocal_ctx_list_update constitute synchronization protocol + that keeps hot path of context destruction (by the owner thread) mostly + lock-free. **/ + tbb::atomic<uintptr_t> my_local_ctx_list_update; + + //! Task, in the context of which the current TBB dispatch loop is running. + /** Outside of or in the outermost dispatch loop (not in a nested call to + wait_for_all) it is my_dummy_task for master threads, and NULL for workers. **/ + task* my_dispatching_task; + +#if __TBB_TASK_PRIORITY + //! True if the scheduler is on the outermost dispatch level in a worker thread. + inline bool worker_outermost_level () const; + + //! Returns reference priority used to decide whether a task should be offloaded. + inline intptr_t effective_reference_priority () const; + + //! Latest known highest priority of tasks in the market or arena. + /** Master threads currently tracks only tasks in their arenas, while workers + take into account global top priority (among all arenas in the market). **/ + volatile intptr_t *my_ref_top_priority; + + //! Task pool for offloading tasks with priorities lower than the current top priority. + task* my_offloaded_tasks; + + //! Points to the last offloaded task in the my_offloaded_tasks list. + task** my_offloaded_task_list_tail_link; + + //! Pointer to market's (for workers) or current arena's (for the master) reload epoch counter. + volatile uintptr_t *my_ref_reload_epoch; + + //! Indicator of how recently the offload area was checked for the presence of top priority tasks. + uintptr_t my_local_reload_epoch; + + //! Indicates that the pool is likely non-empty even if appears so from outside + volatile bool my_pool_reshuffling_pending; + + //! Searches offload area for top priority tasks and reloads found ones into primary task pool. + /** Returns one of the found tasks or NULL. **/ + task* reload_tasks (); + + task* reload_tasks ( task*& offloaded_tasks, task**& offloaded_task_list_link, intptr_t top_priority ); + + //! Moves tasks with priority below the top one from primary task pool into offload area. + /** Returns the next execution candidate task or NULL. **/ + task* winnow_task_pool (); + + //! Unconditionally moves the task into offload area. + inline void offload_task ( task& t, intptr_t task_priority ); +#endif /* __TBB_TASK_PRIORITY */ + + //! Detaches abandoned contexts + /** These contexts must be destroyed by other threads. **/ + void cleanup_local_context_list (); + + //! Finds all contexts registered by this scheduler affected by the state change + //! and propagates the new state to them. + template <typename T> + void propagate_task_group_state ( T task_group_context::*mptr_state, T new_state ); +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +#if _WIN32||_WIN64 +private: + //! Handle returned by RML when registering a master with RML + ::rml::server::execution_resource_t master_exec_resource; +#endif /* _WIN32||_WIN64 */ + + //! Dummy slot used when scheduler is not in arena + /** The data structure is heavily padded, therefore it should be placed after + other data fields used by the owner thread only to allow compiler using + instructions with short offsets when accessing the majority of data members. **/ + arena_slot my_dummy_slot; + +#if __TBB_TASK_GROUP_CONTEXT + //! Flag indicating that a context is being destructed by non-owner thread. + /** See also my_local_ctx_list_update. **/ + tbb::atomic<uintptr_t> my_nonlocal_ctx_list_update; +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +#if __TBB_SURVIVE_THREAD_SWITCH + __cilk_tbb_unwatch_thunk my_cilk_unwatch_thunk; +#if TBB_USE_ASSERT + //! State values used to check interface contract with cilkrts. + /** Names of cs_running...cs_freed derived from state machine diagram in cilk-tbb-interop.h */ + enum cilk_state_t { + cs_none=0xF000, // Start at nonzero value so that we can detect use of zeroed memory. + cs_running, + cs_limbo, + cs_freed + }; + cilk_state_t my_cilk_state; +#endif /* TBB_USE_ASSERT */ +#endif /* __TBB_SURVIVE_THREAD_SWITCH */ + +#if __TBB_STATISTICS + //! Set of counters to track internal statistics on per thread basis + /** Placed at the end of the class definition to minimize the disturbance of + the core logic memory operations. **/ + mutable statistics_counters my_counters; +#endif /* __TBB_STATISTICS */ + +}; // class generic_scheduler + + +} // namespace internal +} // namespace tbb + +#include "arena.h" +#include "governor.h" + +namespace tbb { +namespace internal { + +inline void tbb::internal::generic_scheduler::spawn( task& first, task*& next ) { + governor::local_scheduler()->local_spawn( first, next ); +} + +inline void tbb::internal::generic_scheduler::spawn_root_and_wait( task& first, task*& next ) { + governor::local_scheduler()->local_spawn_root_and_wait( first, next ); +} + +inline void tbb::internal::generic_scheduler::enqueue( task& t, void* prio ) { + governor::local_scheduler()->local_enqueue( t +#if __TBB_TASK_PRIORITY + , (priority_t)(intptr_t)prio +#endif /* __TBB_TASK_PRIORITY */ + ); +} + +inline bool generic_scheduler::in_arena () const { + return my_arena_slot != &my_dummy_slot; +} + +inline bool generic_scheduler::is_local_task_pool_quiescent () const { + return !in_arena() || my_arena_slot->task_pool == EmptyTaskPool || my_arena_slot->task_pool == LockedTaskPool; +} + +inline bool generic_scheduler::is_quiescent_local_task_pool_empty () const { + __TBB_ASSERT( is_local_task_pool_quiescent(), "Task pool is not quiescent" ); + return __TBB_load_relaxed(my_arena_slot->head) == __TBB_load_relaxed(my_arena_slot->tail); +} + +inline bool generic_scheduler::is_quiescent_local_task_pool_reset () const { + __TBB_ASSERT( is_local_task_pool_quiescent(), "Task pool is not quiescent" ); + return __TBB_load_relaxed(my_arena_slot->head) == 0 && __TBB_load_relaxed(my_arena_slot->tail) == 0; +} + + +inline bool generic_scheduler::master_outermost_level () const { + return my_dispatching_task == my_dummy_task; +} + +#if __TBB_TASK_GROUP_CONTEXT +inline task_group_context* generic_scheduler::default_context () { + return my_dummy_task->prefix().context; +} +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +inline void generic_scheduler::attach_mailbox( affinity_id id ) { + __TBB_ASSERT(id>0,NULL); + my_inbox.attach( my_arena->mailbox(id) ); + my_affinity_id = id; +} + +inline bool generic_scheduler::is_worker() { + return my_arena_index != 0; +} + +inline unsigned generic_scheduler::number_of_workers_in_my_arena() { + return my_arena->my_max_num_workers; +} + +//! Return task object to the memory allocator. +inline void generic_scheduler::deallocate_task( task& t ) { +#if TBB_USE_ASSERT + task_prefix& p = t.prefix(); + p.state = 0xFF; + p.extra_state = 0xFF; + poison_pointer(p.next); +#endif /* TBB_USE_ASSERT */ + NFS_Free((char*)&t-task_prefix_reservation_size); +#if __TBB_COUNT_TASK_NODES + --my_task_node_count; +#endif /* __TBB_COUNT_TASK_NODES */ +} + +#if __TBB_COUNT_TASK_NODES +inline intptr_t generic_scheduler::get_task_node_count( bool count_arena_workers ) { + return my_task_node_count + (count_arena_workers? my_arena->workers_task_node_count(): 0); +} +#endif /* __TBB_COUNT_TASK_NODES */ + +inline void generic_scheduler::reset_deque_and_leave_arena ( bool locked ) { + if ( !locked ) + acquire_task_pool(); + __TBB_store_relaxed( my_arena_slot->tail, 0 ); + __TBB_store_relaxed( my_arena_slot->head, 0 ); + leave_arena(); +} + +inline task** generic_scheduler::allocate_task_pool( size_t n ) { + size_t byte_size = ((n * sizeof(task*) + NFS_MaxLineSize - 1) / NFS_MaxLineSize) * NFS_MaxLineSize; + my_task_pool_size = byte_size / sizeof(task*); + task** new_pool = (task**)NFS_Allocate( byte_size, 1, NULL ); + // No need to clear the fresh deque since valid items are designated by the head and tail members. + // But fill it with a canary pattern in the high vigilance debug mode. + fill_with_canary_pattern( new_pool, 0, my_task_pool_size ); + return new_pool; +} + +inline void generic_scheduler::commit_spawned_tasks( size_t new_tail ) { + __TBB_ASSERT ( new_tail <= my_task_pool_size, "task deque end was overwritten" ); + ITT_NOTIFY(sync_releasing, my_arena_slot); + // Release fence is necessary to make sure that previously stored task pointers + // are visible to thieves. + __TBB_store_with_release( my_arena_slot->tail, new_tail ); +} + +void generic_scheduler::commit_relocated_tasks ( size_t new_tail ) { + __TBB_ASSERT( my_arena_slot == &my_dummy_slot || my_arena_slot->task_pool == LockedTaskPool, + "Task pool must be locked when calling commit_relocated_tasks()" ); + __TBB_store_relaxed( my_arena_slot->head, 0 ); + // Tail is updated last to minimize probability of a thread making arena + // snapshot being misguided into thinking that this task pool is empty. + __TBB_store_relaxed( my_arena_slot->tail, new_tail ); + release_task_pool(); +} + +template<free_task_hint h> +void generic_scheduler::free_task( task& t ) { + GATHER_STATISTIC(--my_counters.active_tasks); + task_prefix& p = t.prefix(); + // Verify that optimization hints are correct. + __TBB_ASSERT( h!=small_local_task || p.origin==this, NULL ); + __TBB_ASSERT( !(h&small_task) || p.origin, NULL ); + poison_value(p.depth); + poison_value(p.ref_count); + poison_pointer(p.owner); + __TBB_ASSERT( 1L<<t.state() & (1L<<task::executing|1L<<task::allocated), NULL ); + p.state = task::freed; + if( h==small_local_task || p.origin==this ) { + GATHER_STATISTIC(++my_counters.free_list_length); + p.next = my_free_list; + my_free_list = &t; + } else if( !(h&local_task) && p.origin ) { + free_nonlocal_small_task(t); + } else { + GATHER_STATISTIC(--my_counters.big_tasks); + deallocate_task(t); + } +} + +#if __TBB_TASK_PRIORITY +inline bool generic_scheduler::worker_outermost_level () const { + return !my_dispatching_task; +} + +inline intptr_t generic_scheduler::effective_reference_priority () const { + // Workers on the outermost dispatch level (i.e. with empty stack) use market's + // priority as a reference point (to speedup discovering process level priority + // changes). But when there are enough workers to service (even if only partially) + // a lower priority arena, they should use arena's priority as a reference, lest + // be trapped in a futile spinning (because market's priority would prohibit + // executing ANY tasks in this arena). + return !worker_outermost_level() || + my_arena->my_num_workers_allotted < my_arena->num_workers_active() + ? *my_ref_top_priority : my_arena->my_top_priority; +} + +inline void generic_scheduler::offload_task ( task& t, intptr_t /*priority*/ ) { + GATHER_STATISTIC( ++my_counters.prio_tasks_offloaded ); + __TBB_ASSERT( my_offloaded_task_list_tail_link && !*my_offloaded_task_list_tail_link, NULL ); +#if TBB_USE_ASSERT + t.prefix().state = task::ready; +#endif /* TBB_USE_ASSERT */ + t.prefix().next_offloaded = my_offloaded_tasks; + my_offloaded_tasks = &t; +} +#endif /* __TBB_TASK_PRIORITY */ + +} // namespace internal +} // namespace tbb + +#endif /* _TBB_scheduler_H */ diff --git a/src/tbb/src/tbb/scheduler_common.h b/src/tbb/src/tbb/scheduler_common.h new file mode 100644 index 0000000..aab2cf1 --- /dev/null +++ b/src/tbb/src/tbb/scheduler_common.h @@ -0,0 +1,293 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _TBB_scheduler_common_H +#define _TBB_scheduler_common_H + +#include "tbb/tbb_stddef.h" + +#include <string.h> // for memset, memcpy, memmove + +#include "tbb_statistics.h" + +#if TBB_USE_ASSERT > 1 +#include <stdio.h> +#endif /* TBB_USE_ASSERT > 1 */ + +/* Temporarily change "private" to "public" while including "tbb/task.h". + This hack allows us to avoid publishing internal types and methods + in the public header files just for sake of friend declarations. */ +#ifndef private + #define private public + #define undef_private +#endif + +#include "tbb/task.h" +#include "tbb/tbb_exception.h" + +#ifdef undef_private + #undef private +#endif + +#if __TBB_TASK_GROUP_CONTEXT +#include "tbb/spin_mutex.h" +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +// This macro is an attempt to get rid of ugly ifdefs in the shared parts of the code. +// It drops the second argument depending on whether the controlling macro is defined. +// The first argument is just a convenience allowing to keep comma before the macro usage. +#if __TBB_TASK_GROUP_CONTEXT + #define __TBB_CONTEXT_ARG(arg1, context) arg1, context +#else /* !__TBB_TASK_GROUP_CONTEXT */ + #define __TBB_CONTEXT_ARG(arg1, context) arg1 +#endif /* !__TBB_TASK_GROUP_CONTEXT */ + +#if DO_TBB_TRACE +#include <cstdio> +#define TBB_TRACE(x) ((void)std::printf x) +#else +#define TBB_TRACE(x) ((void)(0)) +#endif /* DO_TBB_TRACE */ + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // Workaround for overzealous compiler warnings + // These particular warnings are so ubiquitous that no attempt is made to narrow + // the scope of the warnings. + #pragma warning (disable: 4100 4127 4312 4244 4267 4706) +#endif + +namespace tbb { +namespace internal { + +class generic_scheduler; + +#if __TBB_TASK_PRIORITY +static const intptr_t num_priority_levels = 3; +static const intptr_t normalized_normal_priority = (num_priority_levels - 1) / 2; + +inline intptr_t normalize_priority ( priority_t p ) { + return intptr_t(p - priority_low) / priority_stride_v4; +} + +static const priority_t priority_from_normalized_rep[num_priority_levels] = { + priority_low, priority_normal, priority_high +}; + +inline void assert_priority_valid ( intptr_t& p ) { + __TBB_ASSERT_EX( p >= 0 && p < num_priority_levels, NULL ); +} + +inline intptr_t& priority ( task& t ) { + return t.prefix().context->my_priority; +} +#endif /* __TBB_TASK_PRIORITY */ + +#if __TBB_TASK_GROUP_CONTEXT +//! Task group state change propagation global epoch +/** Together with generic_scheduler::my_context_state_propagation_epoch forms + cross-thread signaling mechanism that allows to avoid locking at the hot path + of normal execution flow. + + When a descendant task group context is registered or unregistered, the global + and local epochs are compared. If they differ, a state change is being propagated, + and thus registration/deregistration routines take slower branch that may block + (at most one thread of the pool can be blocked at any moment). Otherwise the + control path is lock-free and fast. **/ +extern uintptr_t the_context_state_propagation_epoch; + +//! Mutex guarding state change propagation across task groups forest. +/** Also protects modification of related data structures. **/ +extern spin_mutex the_context_state_propagation_mutex; +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +//! Alignment for a task object +const size_t task_alignment = 32; + +//! Number of bytes reserved for a task prefix +/** If not exactly sizeof(task_prefix), the extra bytes *precede* the task_prefix. */ +const size_t task_prefix_reservation_size = ((sizeof(internal::task_prefix)-1)/task_alignment+1)*task_alignment; + +//! Definitions for bits in task_prefix::extra_state +enum task_extra_state { + //! Tag for v1 tasks (i.e. tasks in TBB 1.0 and 2.0) + es_version_1_task = 0, + //! Tag for v3 tasks (i.e. tasks in TBB 2.1-2.2) + es_version_3_task = 1, + //! Tag for enqueued tasks + es_task_enqueued = 0x10, + //! Tag for v3 task_proxy. + es_task_proxy = 0x20, + //! Set if ref_count might be changed by another thread. Used for debugging. + es_ref_count_active = 0x40, + //! Set if the task has been stolen + es_task_is_stolen = 0x80 +}; + +inline void reset_extra_state ( task *t ) { + t->prefix().extra_state &= ~(es_task_is_stolen | es_task_enqueued); +} + +//! Optimization hint to free_task that enables it omit unnecessary tests and code. +enum free_task_hint { + //! No hint + no_hint=0, + //! Task is known to have been allocated by this scheduler + local_task=1, + //! Task is known to be a small task. + /** Task should be returned to the free list of *some* scheduler, possibly not this scheduler. */ + small_task=2, + //! Bitwise-OR of local_task and small_task. + /** Task should be returned to free list of this scheduler. */ + small_local_task=3 +}; + +//------------------------------------------------------------------------ +// Debugging support +//------------------------------------------------------------------------ + +#if TBB_USE_ASSERT + +static const uintptr_t venom = tbb::internal::size_t_select(0xDEADBEEFU,0xDDEEAADDDEADBEEFULL); + +template <typename T> +void poison_value ( T& val ) { val = * punned_cast<T*>(&venom); } + +/** Expected to be used in assertions only, thus no empty form is defined. **/ +inline bool is_alive( uintptr_t v ) { return v != venom; } + +/** Logically, this method should be a member of class task. + But we do not want to publish it, so it is here instead. */ +inline void assert_task_valid( const task& task ) { + __TBB_ASSERT( &task!=NULL, NULL ); + __TBB_ASSERT( !is_poisoned(&task), NULL ); + __TBB_ASSERT( (uintptr_t)&task % task_alignment == 0, "misaligned task" ); + __TBB_ASSERT( (unsigned)task.state()<=(unsigned)task::recycle, "corrupt task (invalid state)" ); +} + +#else /* !TBB_USE_ASSERT */ + +/** In contrast to debug version poison_value() is a macro here because + the variable used as its argument may be undefined in release builds. **/ +#define poison_value(g) ((void)0) + +inline void assert_task_valid( const task& ) {} + +#endif /* !TBB_USE_ASSERT */ + +//------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------ + +#if __TBB_TASK_GROUP_CONTEXT +inline bool ConcurrentWaitsEnabled ( task& t ) { + return (t.prefix().context->my_version_and_traits & task_group_context::concurrent_wait) != 0; +} + +inline bool CancellationInfoPresent ( task& t ) { + return t.prefix().context->my_cancellation_requested != 0; +} + +#if TBB_USE_CAPTURED_EXCEPTION + inline tbb_exception* TbbCurrentException( task_group_context*, tbb_exception* src) { return src->move(); } + inline tbb_exception* TbbCurrentException( task_group_context*, captured_exception* src) { return src; } +#else + // Using macro instead of an inline function here allows to avoid evaluation of the + // TbbCapturedException expression when exact propagation is enabled for the context. + #define TbbCurrentException(context, TbbCapturedException) \ + context->my_version_and_traits & task_group_context::exact_exception \ + ? tbb_exception_ptr::allocate() \ + : tbb_exception_ptr::allocate( *(TbbCapturedException) ); +#endif /* !TBB_USE_CAPTURED_EXCEPTION */ + +#define TbbRegisterCurrentException(context, TbbCapturedException) \ + if ( context->cancel_group_execution() ) { \ + /* We are the first to signal cancellation, so store the exception that caused it. */ \ + context->my_exception = TbbCurrentException( context, TbbCapturedException ); \ + } + +#define TbbCatchAll(context) \ + catch ( tbb_exception& exc ) { \ + TbbRegisterCurrentException( context, &exc ); \ + } catch ( std::exception& exc ) { \ + TbbRegisterCurrentException( context, captured_exception::allocate(typeid(exc).name(), exc.what()) ); \ + } catch ( ... ) { \ + TbbRegisterCurrentException( context, captured_exception::allocate("...", "Unidentified exception") );\ + } + +#else /* !__TBB_TASK_GROUP_CONTEXT */ + +inline bool ConcurrentWaitsEnabled ( task& t ) { return false; } + +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +//------------------------------------------------------------------------ +// arena_slot +//------------------------------------------------------------------------ + +struct arena_slot { + //! Scheduler of the thread attached to the slot + /** Marks the slot as busy, and is used to iterate through the schedulers belonging to this arena **/ + generic_scheduler* my_scheduler; + + // Task pool (the deque of task pointers) of the scheduler that owns this slot + /** Also is used to specify if the slot is empty or locked: + 0 - empty + -1 - locked **/ + task* *__TBB_atomic task_pool; + + //! Index of the first ready task in the deque. + /** Modified by thieves, and by the owner during compaction/reallocation **/ + __TBB_atomic size_t head; + + //! Padding to avoid false sharing caused by the thieves accessing this slot + char pad1[NFS_MaxLineSize - sizeof(size_t) - sizeof(task**) - sizeof(generic_scheduler*)]; + + //! Index of the element following the last ready task in the deque. + /** Modified by the owner thread. **/ + __TBB_atomic size_t tail; + + //! Hints provided for operations with the container of starvation-resistant tasks. + /** Modified by the owner thread (during these operations). **/ + unsigned hint_for_push, hint_for_pop; + +#if __TBB_STATISTICS + //! Set of counters to accumulate internal statistics related to this arena + statistics_counters *my_counters; +#endif /* __TBB_STATISTICS */ + //! Padding to avoid false sharing caused by the thieves accessing the next slot + char pad2[NFS_MaxLineSize - sizeof(size_t) - 2*sizeof(unsigned) +#if __TBB_STATISTICS + - sizeof(statistics_counters*) +#endif /* __TBB_STATISTICS */ + ]; +}; // class arena_slot + +} // namespace internal +} // namespace tbb + +#endif /* _TBB_scheduler_common_H */ diff --git a/src/tbb/src/tbb/scheduler_utility.h b/src/tbb/src/tbb/scheduler_utility.h new file mode 100644 index 0000000..debba23 --- /dev/null +++ b/src/tbb/src/tbb/scheduler_utility.h @@ -0,0 +1,141 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _TBB_scheduler_utility_H +#define _TBB_scheduler_utility_H + +#include "scheduler.h" + +namespace tbb { +namespace internal { + +//------------------------------------------------------------------------ +// auto_empty_task +//------------------------------------------------------------------------ + +//! Smart holder for the empty task class with automatic destruction +class auto_empty_task { + task* my_task; + generic_scheduler* my_scheduler; +public: + auto_empty_task ( __TBB_CONTEXT_ARG(generic_scheduler *s, task_group_context* context) ) + : my_task( new(&s->allocate_task(sizeof(empty_task), __TBB_CONTEXT_ARG(NULL, context))) empty_task ) + , my_scheduler(s) + {} + // empty_task has trivial destructor, so there's no need to call it. + ~auto_empty_task () { my_scheduler->free_task<small_local_task>(*my_task); } + + operator task& () { return *my_task; } + task* operator & () { return my_task; } + task_prefix& prefix () { return my_task->prefix(); } +}; // class auto_empty_task + +//------------------------------------------------------------------------ +// fast_reverse_vector +//------------------------------------------------------------------------ + +//! Vector that grows without reallocations, and stores items in the reverse order. +/** Requires to initialize its first segment with a preallocated memory chunk + (usually it is static array or an array allocated on the stack). + The second template parameter specifies maximal number of segments. Each next + segment is twice as large as the previous one. **/ +template<typename T, size_t max_segments = 16> +class fast_reverse_vector +{ +public: + fast_reverse_vector ( T* initial_segment, size_t segment_size ) + : m_cur_segment(initial_segment) + , m_cur_segment_size(segment_size) + , m_pos(segment_size) + , m_num_segments(0) + , m_size(0) + { + __TBB_ASSERT ( initial_segment && segment_size, "Nonempty initial segment must be supplied"); + } + + ~fast_reverse_vector () + { + for ( size_t i = 1; i < m_num_segments; ++i ) + NFS_Free( m_segments[i] ); + } + + size_t size () const { return m_size + m_cur_segment_size - m_pos; } + + void push_back ( const T& val ) + { + if ( !m_pos ) { + if ( !m_num_segments ) m_segments[m_num_segments++] = m_cur_segment; + m_size += m_cur_segment_size; + m_cur_segment_size *= 2; + m_pos = m_cur_segment_size; + m_segments[m_num_segments++] = m_cur_segment = (T*)NFS_Allocate( m_cur_segment_size * sizeof(T), 1, NULL ); + __TBB_ASSERT ( m_num_segments < max_segments, "Maximal capacity exceeded" ); + } + m_cur_segment[--m_pos] = val; + } + + //! Copies the contents of the vector into the dst array. + /** Can only be used when T is a POD type, as copying does not invoke copy constructors. **/ + void copy_memory ( T* dst ) const + { + size_t sz = m_cur_segment_size - m_pos; + memcpy( dst, m_cur_segment + m_pos, sz * sizeof(T) ); + dst += sz; + sz = m_cur_segment_size / 2; + for ( long i = (long)m_num_segments - 2; i >= 0; --i ) { + memcpy( dst, m_segments[i], sz * sizeof(T) ); + dst += sz; + sz /= 2; + } + } + +protected: + //! The current (not completely filled) segment + T *m_cur_segment; + + //! Capacity of m_cur_segment + size_t m_cur_segment_size; + + //! Insertion position in m_cur_segment + size_t m_pos; + + //! Array of segments (has fixed size specified by the second template parameter) + T *m_segments[max_segments]; + + //! Number of segments (the size of m_segments) + size_t m_num_segments; + + //! Number of items in the segments in m_segments + size_t m_size; + +}; // class fast_reverse_vector + +} // namespace internal +} // namespace tbb + +#endif /* _TBB_scheduler_utility_H */ diff --git a/src/tbb/src/tbb/semaphore.cpp b/src/tbb/src/tbb/semaphore.cpp new file mode 100644 index 0000000..ba931af --- /dev/null +++ b/src/tbb/src/tbb/semaphore.cpp @@ -0,0 +1,101 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "semaphore.h" +#if _WIN32||_WIN64 +#if defined(RTL_SRWLOCK_INIT) +#include "dynamic_link.h" // Refers to src/tbb, not include/tbb +#include "tbb_misc.h" +#endif +#endif + +namespace tbb { +namespace internal { + +#if _WIN32||_WIN64 +#if defined(RTL_SRWLOCK_INIT) + +static atomic<do_once_state> concmon_module_inited; + +void WINAPI init_binsem_using_event( SRWLOCK* h_ ) +{ + srwl_or_handle* shptr = (srwl_or_handle*) h_; + shptr->h = CreateEvent( NULL, FALSE/*manual reset*/, FALSE/*not signalled initially*/, NULL); +} + +void WINAPI acquire_binsem_using_event( SRWLOCK* h_ ) +{ + srwl_or_handle* shptr = (srwl_or_handle*) h_; + WaitForSingleObject( shptr->h, INFINITE ); +} + +void WINAPI release_binsem_using_event( SRWLOCK* h_ ) +{ + srwl_or_handle* shptr = (srwl_or_handle*) h_; + SetEvent( shptr->h ); +} + +static void (WINAPI *__TBB_init_binsem)( SRWLOCK* ) = (void (WINAPI *)(SRWLOCK*))&init_binsem_using_event; +static void (WINAPI *__TBB_acquire_binsem)( SRWLOCK* ) = (void (WINAPI *)(SRWLOCK*))&acquire_binsem_using_event; +static void (WINAPI *__TBB_release_binsem)( SRWLOCK* ) = (void (WINAPI *)(SRWLOCK*))&release_binsem_using_event; + +//! Table describing the how to link the handlers. +static const dynamic_link_descriptor SRWLLinkTable[] = { + DLD(InitializeSRWLock, __TBB_init_binsem), + DLD(AcquireSRWLockExclusive, __TBB_acquire_binsem), + DLD(ReleaseRWLockExclusive, __TBB_release_binsem) +}; + +inline void init_concmon_module() +{ + __TBB_ASSERT( (uintptr_t)__TBB_init_binsem==(uintptr_t)&init_binsem_using_event, NULL ); + dynamic_link( "Kernel32.dll", SRWLLinkTable, 3 ); +} + +binary_semaphore::binary_semaphore() { + atomic_do_once( &init_concmon_module, concmon_module_inited ); + + __TBB_init_binsem( &my_sem.lock ); + if( (uintptr_t)__TBB_init_binsem!=(uintptr_t)&init_binsem_using_event ) + P(); +} + +binary_semaphore::~binary_semaphore() { + if( (uintptr_t)__TBB_init_binsem==(uintptr_t)&init_binsem_using_event ) + CloseHandle( my_sem.h ); +} + +void binary_semaphore::P() { __TBB_acquire_binsem( &my_sem.lock ); } + +void binary_semaphore::V() { __TBB_release_binsem( &my_sem.lock ); } + +#endif /* defined(RTL_SRWLOCK_INIT) */ +#endif /* _WIN32||_WIN64 */ + +} // namespace internal +} // namespace tbb diff --git a/src/tbb/src/tbb/semaphore.h b/src/tbb/src/tbb/semaphore.h new file mode 100644 index 0000000..3148361 --- /dev/null +++ b/src/tbb/src/tbb/semaphore.h @@ -0,0 +1,260 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_tbb_semaphore_H +#define __TBB_tbb_semaphore_H + +#include "tbb/tbb_stddef.h" + +#if _WIN32||_WIN64 +#include "tbb/machine/windows_api.h" + +#elif __APPLE__ +#include <mach/semaphore.h> +#include <mach/task.h> +#include <mach/mach_init.h> +#include <mach/error.h> + +#else +#include <semaphore.h> +#ifdef TBB_USE_DEBUG +#include <errno.h> +#endif +#endif /*_WIN32||_WIN64*/ + +namespace tbb { +namespace internal { + + +#if _WIN32||_WIN64 +typedef LONG sem_count_t; +//! Edsger Dijkstra's counting semaphore +class semaphore : no_copy { + static const int max_semaphore_cnt = MAXLONG; +public: + //! ctor + semaphore(size_t start_cnt_ = 0) {init_semaphore(start_cnt_);} + //! dtor + ~semaphore() {CloseHandle( sem );} + //! wait/acquire + void P() {WaitForSingleObject( sem, INFINITE );} + //! post/release + void V() {ReleaseSemaphore( sem, 1, NULL );} +private: + HANDLE sem; + void init_semaphore(size_t start_cnt_) {sem = CreateSemaphore( NULL, LONG(start_cnt_), max_semaphore_cnt, NULL );} +}; +#elif __APPLE__ +//! Edsger Dijkstra's counting semaphore +class semaphore : no_copy { +public: + //! ctor + semaphore(int start_cnt_ = 0) : sem(start_cnt_) { init_semaphore(start_cnt_); } + //! dtor + ~semaphore() { + kern_return_t ret = semaphore_destroy( mach_task_self(), sem ); + __TBB_ASSERT_EX( ret==err_none, NULL ); + } + //! wait/acquire + void P() { + int ret; + do { + ret = semaphore_wait( sem ); + } while( ret==KERN_ABORTED ); + __TBB_ASSERT( ret==KERN_SUCCESS, "semaphore_wait() failed" ); + } + //! post/release + void V() { semaphore_signal( sem ); } +private: + semaphore_t sem; + void init_semaphore(int start_cnt_) { + kern_return_t ret = semaphore_create( mach_task_self(), &sem, SYNC_POLICY_FIFO, start_cnt_ ); + __TBB_ASSERT_EX( ret==err_none, "failed to create a semaphore" ); + } +}; +#else /* Linux/Unix */ +typedef uint32_t sem_count_t; +//! Edsger Dijkstra's counting semaphore +class semaphore : no_copy { +public: + //! ctor + semaphore(int start_cnt_ = 0 ) { init_semaphore( start_cnt_ ); } + + //! dtor + ~semaphore() { + int ret = sem_destroy( &sem ); + __TBB_ASSERT_EX( !ret, NULL ); + } + //! wait/acquire + void P() { + while( sem_wait( &sem )!=0 ) + __TBB_ASSERT( errno==EINTR, NULL ); + } + //! post/release + void V() { sem_post( &sem ); } +private: + sem_t sem; + void init_semaphore(int start_cnt_) { + int ret = sem_init( &sem, /*shared among threads*/ 0, start_cnt_ ); + __TBB_ASSERT_EX( !ret, NULL ); + } +}; +#endif /* _WIN32||_WIN64 */ + + +//! for performance reasons, we want specialied binary_semaphore +#if _WIN32||_WIN64 +#if !defined(RTL_SRWLOCK_INIT) +//! binary_semaphore for concurrent_monitor +class binary_semaphore : no_copy { +public: + //! ctor + binary_semaphore() { my_sem = CreateEvent( NULL, FALSE/*manual reset*/, FALSE/*not signalled initially*/, NULL); } + //! dtor + ~binary_semaphore() { CloseHandle( my_sem ); } + //! wait/acquire + void P() {WaitForSingleObject( my_sem, INFINITE ); } + //! post/release + void V() {SetEvent( my_sem );} +private: + HANDLE my_sem; +}; +#else /* defined(RTL_SRWLOCK_INIT) */ + +union srwl_or_handle { + SRWLOCK lock; + HANDLE h; +}; + +//! binary_semaphore for concurrent_monitor +class binary_semaphore : no_copy { +public: + //! ctor + binary_semaphore(); + //! dtor + ~binary_semaphore(); + //! wait/acquire + void P(); + //! post/release + void V(); +private: + srwl_or_handle my_sem; +}; +#endif /* !defined(RTL_SRWLOCK_INIT) */ +#elif __APPLE__ +//! binary_semaphore for concurrent monitor +class binary_semaphore : no_copy { +public: + //! ctor + binary_semaphore() : my_sem(0) { + kern_return_t ret = semaphore_create( mach_task_self(), &my_sem, SYNC_POLICY_FIFO, 0 ); + __TBB_ASSERT_EX( ret==err_none, "failed to create a semaphore" ); + } + //! dtor + ~binary_semaphore() { + kern_return_t ret = semaphore_destroy( mach_task_self(), my_sem ); + __TBB_ASSERT_EX( ret==err_none, NULL ); + } + //! wait/acquire + void P() { + int ret; + do { + ret = semaphore_wait( my_sem ); + } while( ret==KERN_ABORTED ); + __TBB_ASSERT( ret==KERN_SUCCESS, "semaphore_wait() failed" ); + } + //! post/release + void V() { semaphore_signal( my_sem ); } +private: + semaphore_t my_sem; +}; +#else /* Linux/Unix */ + +#if __TBB_USE_FUTEX +class binary_semaphore : no_copy { +public: + //! ctor + binary_semaphore() { my_sem = 1; } + //! dtor + ~binary_semaphore() {} + //! wait/acquire + void P() { + int s; + if( (s = my_sem.compare_and_swap( 1, 0 ))!=0 ) { + if( s!=2 ) + s = my_sem.fetch_and_store( 2 ); + while( s!=0 ) { + futex_wait( &my_sem, 2 ); + s = my_sem.fetch_and_store( 2 ); + } + } + } + //! post/release + void V() { + __TBB_ASSERT( my_sem>=1, "multiple V()'s in a row?" ); + if( my_sem--!=1 ) { + //if old value was 2 + my_sem = 0; + futex_wakeup_one( &my_sem ); + } + } +private: + atomic<int> my_sem; +}; +#else +typedef uint32_t sem_count_t; +//! binary_semaphore for concurrent monitor +class binary_semaphore : no_copy { +public: + //! ctor + binary_semaphore() { + int ret = sem_init( &my_sem, /*shared among threads*/ 0, 0 ); + __TBB_ASSERT_EX( !ret, NULL ); + } + //! dtor + ~binary_semaphore() { + int ret = sem_destroy( &my_sem ); + __TBB_ASSERT_EX( !ret, NULL ); + } + //! wait/acquire + void P() { + while( sem_wait( &my_sem )!=0 ) + __TBB_ASSERT( errno==EINTR, NULL ); + } + //! post/release + void V() { sem_post( &my_sem ); } +private: + sem_t my_sem; +}; +#endif /* __TBB_USE_FUTEX */ +#endif /* _WIN32||_WIN64 */ + +} // namespace internal +} // namespace tbb + +#endif /* __TBB_tbb_semaphore_H */ diff --git a/src/tbb/src/tbb/spin_mutex.cpp b/src/tbb/src/tbb/spin_mutex.cpp new file mode 100644 index 0000000..ab09c73 --- /dev/null +++ b/src/tbb/src/tbb/spin_mutex.cpp @@ -0,0 +1,68 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/tbb_machine.h" +#include "tbb/spin_mutex.h" +#include "itt_notify.h" +#include "tbb_misc.h" + +namespace tbb { + +void spin_mutex::scoped_lock::internal_acquire( spin_mutex& m ) { + __TBB_ASSERT( !my_mutex, "already holding a lock on a spin_mutex" ); + ITT_NOTIFY(sync_prepare, &m); + my_unlock_value = __TBB_LockByte(m.flag); + my_mutex = &m; + ITT_NOTIFY(sync_acquired, &m); +} + +void spin_mutex::scoped_lock::internal_release() { + __TBB_ASSERT( my_mutex, "release on spin_mutex::scoped_lock that is not holding a lock" ); + __TBB_ASSERT( !(my_unlock_value&1), "corrupted scoped_lock?" ); + + ITT_NOTIFY(sync_releasing, my_mutex); + __TBB_UnlockByte(my_mutex->flag, my_unlock_value); + my_mutex = NULL; +} + +bool spin_mutex::scoped_lock::internal_try_acquire( spin_mutex& m ) { + __TBB_ASSERT( !my_mutex, "already holding a lock on a spin_mutex" ); + bool result = bool( __TBB_TryLockByte(m.flag) ); + if( result ) { + my_unlock_value = 0; + my_mutex = &m; + ITT_NOTIFY(sync_acquired, &m); + } + return result; +} + +void spin_mutex::internal_construct() { + ITT_SYNC_CREATE(this, _T("tbb::spin_mutex"), _T("")); +} + +} // namespace tbb diff --git a/src/tbb/src/tbb/spin_rw_mutex.cpp b/src/tbb/src/tbb/spin_rw_mutex.cpp new file mode 100644 index 0000000..4323487 --- /dev/null +++ b/src/tbb/src/tbb/spin_rw_mutex.cpp @@ -0,0 +1,166 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/spin_rw_mutex.h" +#include "tbb/tbb_machine.h" +#include "itt_notify.h" + +#if defined(_MSC_VER) && defined(_Wp64) + // Workaround for overzealous compiler warnings in /Wp64 mode + #pragma warning (disable: 4244) +#endif + +namespace tbb { + +template<typename T> // a template can work with private spin_rw_mutex::state_t +static inline T CAS(volatile T &addr, T newv, T oldv) { + // ICC (9.1 and 10.1 tried) unable to do implicit conversion + // from "volatile T*" to "volatile void*", so explicit cast added. + return T(__TBB_CompareAndSwapW((volatile void *)&addr, (intptr_t)newv, (intptr_t)oldv)); +} + +//! Acquire write lock on the given mutex. +bool spin_rw_mutex_v3::internal_acquire_writer() +{ + ITT_NOTIFY(sync_prepare, this); + for( internal::atomic_backoff backoff;;backoff.pause() ){ + state_t s = const_cast<volatile state_t&>(state); // ensure reloading + if( !(s & BUSY) ) { // no readers, no writers + if( CAS(state, WRITER, s)==s ) + break; // successfully stored writer flag + backoff.reset(); // we could be very close to complete op. + } else if( !(s & WRITER_PENDING) ) { // no pending writers + __TBB_AtomicOR(&state, WRITER_PENDING); + } + } + ITT_NOTIFY(sync_acquired, this); + return false; +} + +//! Release writer lock on the given mutex +void spin_rw_mutex_v3::internal_release_writer() +{ + ITT_NOTIFY(sync_releasing, this); + __TBB_AtomicAND( &state, READERS ); +} + +//! Acquire read lock on given mutex. +void spin_rw_mutex_v3::internal_acquire_reader() +{ + ITT_NOTIFY(sync_prepare, this); + for( internal::atomic_backoff backoff;;backoff.pause() ){ + state_t s = const_cast<volatile state_t&>(state); // ensure reloading + if( !(s & (WRITER|WRITER_PENDING)) ) { // no writer or write requests + state_t t = (state_t)__TBB_FetchAndAddW( &state, (intptr_t) ONE_READER ); + if( !( t&WRITER )) + break; // successfully stored increased number of readers + // writer got there first, undo the increment + __TBB_FetchAndAddW( &state, -(intptr_t)ONE_READER ); + } + } + + ITT_NOTIFY(sync_acquired, this); + __TBB_ASSERT( state & READERS, "invalid state of a read lock: no readers" ); +} + +//! Upgrade reader to become a writer. +/** Returns whether the upgrade happened without releasing and re-acquiring the lock */ +bool spin_rw_mutex_v3::internal_upgrade() +{ + state_t s = state; + __TBB_ASSERT( s & READERS, "invalid state before upgrade: no readers " ); + // check and set writer-pending flag + // required conditions: either no pending writers, or we are the only reader + // (with multiple readers and pending writer, another upgrade could have been requested) + while( (s & READERS)==ONE_READER || !(s & WRITER_PENDING) ) { + state_t old_s = s; + if( (s=CAS(state, s | WRITER | WRITER_PENDING, s))==old_s ) { + ITT_NOTIFY(sync_prepare, this); + for( internal::atomic_backoff backoff; (state & READERS) != ONE_READER; ) + backoff.pause(); // while more than 1 reader + __TBB_ASSERT((state&(WRITER_PENDING|WRITER))==(WRITER_PENDING|WRITER),"invalid state when upgrading to writer"); + // both new readers and writers are blocked at this time + __TBB_FetchAndAddW( &state, - (intptr_t)(ONE_READER+WRITER_PENDING)); + ITT_NOTIFY(sync_acquired, this); + return true; // successfully upgraded + } + } + // slow reacquire + internal_release_reader(); + return internal_acquire_writer(); // always returns false +} + +//! Downgrade writer to a reader +void spin_rw_mutex_v3::internal_downgrade() { + ITT_NOTIFY(sync_releasing, this); + __TBB_FetchAndAddW( &state, (intptr_t)(ONE_READER-WRITER)); + __TBB_ASSERT( state & READERS, "invalid state after downgrade: no readers" ); +} + +//! Release read lock on the given mutex +void spin_rw_mutex_v3::internal_release_reader() +{ + __TBB_ASSERT( state & READERS, "invalid state of a read lock: no readers" ); + ITT_NOTIFY(sync_releasing, this); // release reader + __TBB_FetchAndAddWrelease( &state,-(intptr_t)ONE_READER); +} + +//! Try to acquire write lock on the given mutex +bool spin_rw_mutex_v3::internal_try_acquire_writer() +{ + // for a writer: only possible to acquire if no active readers or writers + state_t s = state; + if( !(s & BUSY) ) // no readers, no writers; mask is 1..1101 + if( CAS(state, WRITER, s)==s ) { + ITT_NOTIFY(sync_acquired, this); + return true; // successfully stored writer flag + } + return false; +} + +//! Try to acquire read lock on the given mutex +bool spin_rw_mutex_v3::internal_try_acquire_reader() +{ + // for a reader: acquire if no active or waiting writers + state_t s = state; + if( !(s & (WRITER|WRITER_PENDING)) ) { // no writers + state_t t = (state_t)__TBB_FetchAndAddW( &state, (intptr_t) ONE_READER ); + if( !( t&WRITER )) { // got the lock + ITT_NOTIFY(sync_acquired, this); + return true; // successfully stored increased number of readers + } + // writer got there first, undo the increment + __TBB_FetchAndAddW( &state, -(intptr_t)ONE_READER ); + } + return false; +} + +void spin_rw_mutex_v3::internal_construct() { + ITT_SYNC_CREATE(this, _T("tbb::spin_rw_mutex"), _T("")); +} +} // namespace tbb diff --git a/src/tbb/src/tbb/task.cpp b/src/tbb/src/tbb/task.cpp new file mode 100644 index 0000000..6b0faa4 --- /dev/null +++ b/src/tbb/src/tbb/task.cpp @@ -0,0 +1,271 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include <new> + +// Do not include task.h directly. Use scheduler_common.h instead +#include "scheduler_common.h" +#include "governor.h" +#include "scheduler.h" +#include "itt_notify.h" + +#include "tbb/cache_aligned_allocator.h" +#include "tbb/partitioner.h" + +namespace tbb { + +using namespace std; + +namespace internal { + +//------------------------------------------------------------------------ +// Methods of allocate_root_proxy +//------------------------------------------------------------------------ +task& allocate_root_proxy::allocate( size_t size ) { + internal::generic_scheduler* v = governor::local_scheduler(); + __TBB_ASSERT( v, "thread did not activate a task_scheduler_init object?" ); +#if __TBB_TASK_GROUP_CONTEXT + task_prefix& p = v->my_innermost_running_task->prefix(); + + ITT_STACK_CREATE(p.context->itt_caller); +#endif + // New root task becomes part of the currently running task's cancellation context + return v->allocate_task( size, __TBB_CONTEXT_ARG(NULL, p.context) ); +} + +void allocate_root_proxy::free( task& task ) { + internal::generic_scheduler* v = governor::local_scheduler(); + __TBB_ASSERT( v, "thread does not have initialized task_scheduler_init object?" ); +#if __TBB_TASK_GROUP_CONTEXT + // No need to do anything here as long as there is no context -> task connection +#endif /* __TBB_TASK_GROUP_CONTEXT */ + v->free_task<local_task>( task ); +} + +#if __TBB_TASK_GROUP_CONTEXT +//------------------------------------------------------------------------ +// Methods of allocate_root_with_context_proxy +//------------------------------------------------------------------------ +task& allocate_root_with_context_proxy::allocate( size_t size ) const { + internal::generic_scheduler* s = governor::local_scheduler(); + __TBB_ASSERT( s, "Scheduler auto-initialization failed?" ); + task& t = s->allocate_task( size, __TBB_CONTEXT_ARG(NULL, &my_context) ); + // Supported usage model prohibits concurrent initial binding. Thus we do not + // need interlocked operations or fences to manipulate with my_context.my_kind + if ( my_context.my_kind == task_group_context::binding_required ) { + // If we are in the outermost task dispatch loop of a master thread, then + // there is nothing to bind this context to, and we skip the binding part + // treating the context as isolated. + if ( s->my_innermost_running_task == s->my_dummy_task ) + my_context.my_kind = task_group_context::isolated; + else + my_context.bind_to( s ); + } + ITT_STACK_CREATE(my_context.itt_caller); + return t; +} + +void allocate_root_with_context_proxy::free( task& task ) const { + internal::generic_scheduler* v = governor::local_scheduler(); + __TBB_ASSERT( v, "thread does not have initialized task_scheduler_init object?" ); + // No need to do anything here as long as unbinding is performed by context destructor only. + v->free_task<local_task>( task ); +} +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +//------------------------------------------------------------------------ +// Methods of allocate_continuation_proxy +//------------------------------------------------------------------------ +task& allocate_continuation_proxy::allocate( size_t size ) const { + task& t = *((task*)this); + assert_task_valid(t); + generic_scheduler* s = governor::local_scheduler(); + task* parent = t.parent(); + t.prefix().parent = NULL; + return s->allocate_task( size, __TBB_CONTEXT_ARG(parent, t.prefix().context) ); +} + +void allocate_continuation_proxy::free( task& mytask ) const { + // Restore the parent as it was before the corresponding allocate was called. + ((task*)this)->prefix().parent = mytask.parent(); + governor::local_scheduler()->free_task<local_task>(mytask); +} + +//------------------------------------------------------------------------ +// Methods of allocate_child_proxy +//------------------------------------------------------------------------ +task& allocate_child_proxy::allocate( size_t size ) const { + task& t = *((task*)this); + assert_task_valid(t); + generic_scheduler* s = governor::local_scheduler(); + return s->allocate_task( size, __TBB_CONTEXT_ARG(&t, t.prefix().context) ); +} + +void allocate_child_proxy::free( task& mytask ) const { + governor::local_scheduler()->free_task<local_task>(mytask); +} + +//------------------------------------------------------------------------ +// Methods of allocate_additional_child_of_proxy +//------------------------------------------------------------------------ +task& allocate_additional_child_of_proxy::allocate( size_t size ) const { + parent.increment_ref_count(); + generic_scheduler* s = governor::local_scheduler(); + return s->allocate_task( size, __TBB_CONTEXT_ARG(&parent, parent.prefix().context) ); +} + +void allocate_additional_child_of_proxy::free( task& task ) const { + // Undo the increment. We do not check the result of the fetch-and-decrement. + // We could consider be spawning the task if the fetch-and-decrement returns 1. + // But we do not know that was the programmer's intention. + // Furthermore, if it was the programmer's intention, the program has a fundamental + // race condition (that we warn about in Reference manual), because the + // reference count might have become zero before the corresponding call to + // allocate_additional_child_of_proxy::allocate. + parent.internal_decrement_ref_count(); + governor::local_scheduler()->free_task<local_task>(task); +} + +//------------------------------------------------------------------------ +// Support for auto_partitioner +//------------------------------------------------------------------------ +size_t get_initial_auto_partitioner_divisor() { + const size_t X_FACTOR = 4; + return X_FACTOR * (governor::max_number_of_workers()+1); +} + +//------------------------------------------------------------------------ +// Methods of affinity_partitioner_base_v3 +//------------------------------------------------------------------------ +void affinity_partitioner_base_v3::resize( unsigned factor ) { + // Check factor to avoid asking for number of workers while there might be no arena. + size_t new_size = factor ? factor*(governor::max_number_of_workers()+1) : 0; + if( new_size!=my_size ) { + if( my_array ) { + NFS_Free( my_array ); + // Following two assignments must be done here for sake of exception safety. + my_array = NULL; + my_size = 0; + } + if( new_size ) { + my_array = static_cast<affinity_id*>(NFS_Allocate(new_size,sizeof(affinity_id), NULL )); + memset( my_array, 0, sizeof(affinity_id)*new_size ); + my_size = new_size; + } + } +} + +} // namespace internal + +using namespace tbb::internal; + +//------------------------------------------------------------------------ +// task +//------------------------------------------------------------------------ + +void task::internal_set_ref_count( int count ) { + __TBB_ASSERT( count>=0, "count must not be negative" ); + task_prefix &p = prefix(); + __TBB_ASSERT(p.ref_count==1 && p.state==allocated && self().parent()==this + || !(p.extra_state & es_ref_count_active), "ref_count race detected"); + ITT_NOTIFY(sync_releasing, &p.ref_count); + p.ref_count = count; +} + +internal::reference_count task::internal_decrement_ref_count() { + ITT_NOTIFY( sync_releasing, &prefix().ref_count ); + internal::reference_count k = __TBB_FetchAndDecrementWrelease( &prefix().ref_count ); + __TBB_ASSERT( k>=1, "task's reference count underflowed" ); + if( k==1 ) + ITT_NOTIFY( sync_acquired, &prefix().ref_count ); + return k-1; +} + +task& task::self() { + generic_scheduler *v = governor::local_scheduler(); + v->assert_task_pool_valid(); + __TBB_ASSERT( v->my_innermost_running_task, NULL ); + return *v->my_innermost_running_task; +} + +bool task::is_owned_by_current_thread() const { + return true; +} + +void interface5::internal::task_base::destroy( task& victim ) { + // 1 may be a guard reference for wait_for_all, which was not reset because + // of concurrent_wait mode or because prepared root task was not actually used + // for spawning tasks (as in structured_task_group). + __TBB_ASSERT( (intptr_t)victim.prefix().ref_count <= 1, "Task being destroyed must not have children" ); + __TBB_ASSERT( victim.state()==task::allocated, "illegal state for victim task" ); + task* parent = victim.parent(); + victim.~task(); + if( parent ) { + __TBB_ASSERT( parent->state()==task::allocated, "attempt to destroy child of running or corrupted parent?" ); + parent->internal_decrement_ref_count(); + // Even if the last reference to *parent is removed, it should not be spawned (documented behavior). + } + governor::local_scheduler()->free_task<no_hint>( victim ); +} + +void task::spawn_and_wait_for_all( task_list& list ) { + generic_scheduler* s = governor::local_scheduler(); + task* t = list.first; + if( t ) { + if( &t->prefix().next!=list.next_ptr ) + s->local_spawn( *t->prefix().next, *list.next_ptr ); + list.clear(); + } + s->local_wait_for_all( *this, t ); +} + +/** Defined out of line so that compiler does not replicate task's vtable. + It's pointless to define it inline anyway, because all call sites to it are virtual calls + that the compiler is unlikely to optimize. */ +void task::note_affinity( affinity_id ) { +} + +#if __TBB_TASK_GROUP_CONTEXT +void task::change_group ( task_group_context& ctx ) { + prefix().context = &ctx; + if ( ctx.my_kind == task_group_context::binding_required ) { + internal::generic_scheduler* s = governor::local_scheduler(); + // If we are in the outermost task dispatch loop of a master thread, then + // there is nothing to bind this context to, and we skip the binding part + // treating the context as isolated. + if ( s->my_innermost_running_task == s->my_dummy_task ) + ctx.my_kind = task_group_context::isolated; + else + ctx.bind_to( s ); + } + ITT_STACK_CREATE(ctx.itt_caller); +} +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +} // namespace tbb + diff --git a/src/tbb/src/tbb/task_group_context.cpp b/src/tbb/src/tbb/task_group_context.cpp new file mode 100644 index 0000000..f2c18cb --- /dev/null +++ b/src/tbb/src/tbb/task_group_context.cpp @@ -0,0 +1,452 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "scheduler.h" + +#include "tbb/task.h" +#include "tbb/tbb_exception.h" +#include "tbb/cache_aligned_allocator.h" +#include "itt_notify.h" + +namespace tbb { + +#if __TBB_TASK_GROUP_CONTEXT + +using namespace internal; + +//------------------------------------------------------------------------ +// captured_exception +//------------------------------------------------------------------------ + +inline char* duplicate_string ( const char* src ) { + char* dst = NULL; + if ( src ) { + size_t len = strlen(src) + 1; + dst = (char*)allocate_via_handler_v3(len); + strncpy (dst, src, len); + } + return dst; +} + +captured_exception::~captured_exception () throw() { + clear(); +} + +void captured_exception::set ( const char* a_name, const char* info ) throw() { + my_exception_name = duplicate_string( a_name ); + my_exception_info = duplicate_string( info ); +} + +void captured_exception::clear () throw() { + deallocate_via_handler_v3 (const_cast<char*>(my_exception_name)); + deallocate_via_handler_v3 (const_cast<char*>(my_exception_info)); +} + +captured_exception* captured_exception::move () throw() { + captured_exception *e = (captured_exception*)allocate_via_handler_v3(sizeof(captured_exception)); + if ( e ) { + ::new (e) captured_exception(); + e->my_exception_name = my_exception_name; + e->my_exception_info = my_exception_info; + e->my_dynamic = true; + my_exception_name = my_exception_info = NULL; + } + return e; +} + +void captured_exception::destroy () throw() { + __TBB_ASSERT ( my_dynamic, "Method destroy can be used only on objects created by clone or allocate" ); + if ( my_dynamic ) { + this->captured_exception::~captured_exception(); + deallocate_via_handler_v3 (this); + } +} + +captured_exception* captured_exception::allocate ( const char* a_name, const char* info ) { + captured_exception *e = (captured_exception*)allocate_via_handler_v3( sizeof(captured_exception) ); + if ( e ) { + ::new (e) captured_exception(a_name, info); + e->my_dynamic = true; + } + return e; +} + +const char* captured_exception::name() const throw() { + return my_exception_name; +} + +const char* captured_exception::what() const throw() { + return my_exception_info; +} + + +//------------------------------------------------------------------------ +// tbb_exception_ptr +//------------------------------------------------------------------------ + +#if !TBB_USE_CAPTURED_EXCEPTION + +namespace internal { + +template<typename T> +tbb_exception_ptr* AllocateExceptionContainer( const T& src ) { + tbb_exception_ptr *eptr = (tbb_exception_ptr*)allocate_via_handler_v3( sizeof(tbb_exception_ptr) ); + if ( eptr ) + new (eptr) tbb_exception_ptr(src); + return eptr; +} + +tbb_exception_ptr* tbb_exception_ptr::allocate () { + return AllocateExceptionContainer( std::current_exception() ); +} + +tbb_exception_ptr* tbb_exception_ptr::allocate ( const tbb_exception& ) { + return AllocateExceptionContainer( std::current_exception() ); +} + +tbb_exception_ptr* tbb_exception_ptr::allocate ( captured_exception& src ) { + tbb_exception_ptr *res = AllocateExceptionContainer( src ); + src.destroy(); + return res; +} + +void tbb_exception_ptr::destroy () throw() { + this->tbb_exception_ptr::~tbb_exception_ptr(); + deallocate_via_handler_v3 (this); +} + +} // namespace internal +#endif /* !TBB_USE_CAPTURED_EXCEPTION */ + + +//------------------------------------------------------------------------ +// task_group_context +//------------------------------------------------------------------------ + +task_group_context::~task_group_context () { + if ( my_kind == binding_completed ) { + if ( governor::is_set(my_owner) ) { + // Local update of the context list + uintptr_t local_count_snapshot = my_owner->my_context_state_propagation_epoch; + my_owner->my_local_ctx_list_update.store<relaxed>(1); + // Prevent load of nonlocal update flag from being hoisted before the + // store to local update flag. + atomic_fence(); + if ( my_owner->my_nonlocal_ctx_list_update.load<relaxed>() ) { + spin_mutex::scoped_lock lock(my_owner->my_context_list_mutex); + my_node.my_prev->my_next = my_node.my_next; + my_node.my_next->my_prev = my_node.my_prev; + my_owner->my_local_ctx_list_update.store<relaxed>(0); + } + else { + my_node.my_prev->my_next = my_node.my_next; + my_node.my_next->my_prev = my_node.my_prev; + // Release fence is necessary so that update of our neighbors in + // the context list was committed when possible concurrent destroyer + // proceeds after local update flag is reset by the following store. + my_owner->my_local_ctx_list_update.store<release>(0); + if ( local_count_snapshot != the_context_state_propagation_epoch ) { + // Another thread was propagating cancellation request when we removed + // ourselves from the list. We must ensure that it is not accessing us + // when this destructor finishes. We'll be able to acquire the lock + // below only after the other thread finishes with us. + spin_mutex::scoped_lock lock(my_owner->my_context_list_mutex); + } + } + } + else { + // Nonlocal update of the context list + // Synchronizes with generic_scheduler::free_scheduler() + if ( __TBB_FetchAndStoreW(&my_kind, dying) == detached ) { + my_node.my_prev->my_next = my_node.my_next; + my_node.my_next->my_prev = my_node.my_prev; + } + else { + //TODO: evaluate and perhaps relax + my_owner->my_nonlocal_ctx_list_update.fetch_and_increment<full_fence>(); + //TODO: evaluate and perhaps remove + spin_wait_until_eq( my_owner->my_local_ctx_list_update, 0u ); + my_owner->my_context_list_mutex.lock(); + my_node.my_prev->my_next = my_node.my_next; + my_node.my_next->my_prev = my_node.my_prev; + my_owner->my_context_list_mutex.unlock(); + //TODO: evaluate and perhaps relax + my_owner->my_nonlocal_ctx_list_update.fetch_and_decrement<full_fence>(); + } + } + } + poison_value(my_version_and_traits); + if ( my_exception ) + my_exception->destroy(); + ITT_STACK(itt_caller != ITT_CALLER_NULL, caller_destroy, itt_caller); +} + +void task_group_context::init () { + __TBB_ASSERT ( sizeof(uintptr_t) < 32, "Layout of my_version_and_traits must be reconsidered on this platform" ); + __TBB_ASSERT ( sizeof(task_group_context) == 2 * NFS_MaxLineSize, "Context class has wrong size - check padding and members alignment" ); + __TBB_ASSERT ( (uintptr_t(this) & (sizeof(my_cancellation_requested) - 1)) == 0, "Context is improperly aligned" ); + __TBB_ASSERT ( my_kind == isolated || my_kind == bound, "Context can be created only as isolated or bound" ); + my_parent = NULL; + my_cancellation_requested = 0; + my_exception = NULL; + my_owner = NULL; + my_state = 0; + itt_caller = ITT_CALLER_NULL; +#if __TBB_TASK_PRIORITY + my_priority = normalized_normal_priority; +#endif /* __TBB_TASK_PRIORITY */ +} + +void task_group_context::register_with ( generic_scheduler *local_sched ) { + __TBB_ASSERT( local_sched, NULL ); + my_owner = local_sched; + my_node.my_prev = &local_sched->my_context_list_head; + // Notify threads that may be concurrently destroying contexts registered + // in this scheduler's list that local list update is underway. + local_sched->my_local_ctx_list_update.store<relaxed>(1); + // Prevent load of global propagation epoch counter from being hoisted before + // speculative stores above, as well as load of nonlocal update flag from + // being hoisted before the store to local update flag. + atomic_fence(); + // Finalize local context list update + if ( local_sched->my_nonlocal_ctx_list_update.load<relaxed>() ) { + spin_mutex::scoped_lock lock(my_owner->my_context_list_mutex); + local_sched->my_context_list_head.my_next->my_prev = &my_node; + my_node.my_next = local_sched->my_context_list_head.my_next; + my_owner->my_local_ctx_list_update.store<relaxed>(0); + local_sched->my_context_list_head.my_next = &my_node; + } + else { + local_sched->my_context_list_head.my_next->my_prev = &my_node; + my_node.my_next = local_sched->my_context_list_head.my_next; + my_owner->my_local_ctx_list_update.store<release>(0); + // Thread-local list of contexts allows concurrent traversal by another thread + // while propagating state change. To ensure visibility of my_node's members + // to the concurrently traversing thread, the list's head is updated by means + // of store-with-release. + __TBB_store_with_release(local_sched->my_context_list_head.my_next, &my_node); + } +} + +void task_group_context::bind_to ( generic_scheduler *local_sched ) { + __TBB_ASSERT ( my_kind == binding_required, "Already bound or isolated?" ); + __TBB_ASSERT ( !my_parent, "Parent is set before initial binding" ); + my_parent = local_sched->my_innermost_running_task->prefix().context; + + // Condition below prevents unnecessary thrashing parent context's cache line + if ( !(my_parent->my_state & may_have_children) ) + my_parent->my_state |= may_have_children; + if ( my_parent->my_parent ) { + // Even if this context were made accessible for state change propagation + // (by placing __TBB_store_with_release(s->my_context_list_head.my_next, &my_node) + // above), it still could be missed if state propagation from a grand-ancestor + // was underway concurrently with binding. + // Speculative propagation from the parent together with epoch counters + // detecting possibility of such a race allow to avoid taking locks when + // there is no contention. + + // Acquire fence is necessary to prevent reordering subsequent speculative + // loads of parent state data out of the scope where epoch counters comparison + // can reliably validate it. + uintptr_t local_count_snapshot = __TBB_load_with_acquire( my_parent->my_owner->my_context_state_propagation_epoch ); + // Speculative propagation of parent's state. The speculation will be + // validated by the epoch counters check further on. + my_cancellation_requested = my_parent->my_cancellation_requested; +#if __TBB_TASK_PRIORITY + my_priority = my_parent->my_priority; +#endif /* __TBB_TASK_PRIORITY */ + register_with( local_sched ); // Issues full fence + + // If no state propagation was detected by the following condition, the above + // full fence guarantees that the parent had correct state during speculative + // propagation before the fence. Otherwise the propagation from parent is + // repeated under the lock. + if ( local_count_snapshot != the_context_state_propagation_epoch ) { + // Another thread may be propagating state change right now. So resort to lock. + spin_mutex::scoped_lock lock(the_context_state_propagation_mutex); + my_cancellation_requested = my_parent->my_cancellation_requested; +#if __TBB_TASK_PRIORITY + my_priority = my_parent->my_priority; +#endif /* __TBB_TASK_PRIORITY */ + } + } + else { + register_with( local_sched ); // Issues full fence + // As we do not have grand-ancestors, concurrent state propagation (if any) + // may originate only from the parent context, and thus it is safe to directly + // copy the state from it. + my_cancellation_requested = my_parent->my_cancellation_requested; +#if __TBB_TASK_PRIORITY + my_priority = my_parent->my_priority; +#endif /* __TBB_TASK_PRIORITY */ + } + my_kind = binding_completed; +} + +#if __TBB_TASK_GROUP_CONTEXT +template <typename T> +void task_group_context::propagate_state_from_ancestors ( T task_group_context::*mptr_state, T new_state ) { + task_group_context *ancestor = my_parent; + while ( ancestor && ancestor->*mptr_state != new_state ) + ancestor = ancestor->my_parent; + if ( ancestor ) { + task_group_context *ctx = this; + do { + ctx->*mptr_state = new_state; + ctx = ctx->my_parent; + } while ( ctx != ancestor ); + } +} + +template <typename T> +void generic_scheduler::propagate_task_group_state ( T task_group_context::*mptr_state, T new_state ) { + spin_mutex::scoped_lock lock(my_context_list_mutex); + // Acquire fence is necessary to ensure that the subsequent node->my_next load + // returned the correct value in case it was just inserted in another thread. + // The fence also ensures visibility of the correct my_parent value. + context_list_node_t *node = __TBB_load_with_acquire(my_context_list_head.my_next); + while ( node != &my_context_list_head ) { + task_group_context &ctx = __TBB_get_object_ref(task_group_context, my_node, node); + if ( ctx.*mptr_state != new_state ) + ctx.propagate_state_from_ancestors( mptr_state, new_state ); + node = node->my_next; + __TBB_ASSERT( is_alive(ctx.my_version_and_traits), "Local context list contains destroyed object" ); + } + // Sync up local propagation epoch with the global one. Release fence prevents + // reordering of possible store to *mptr_state after the sync point. + __TBB_store_with_release(my_context_state_propagation_epoch, the_context_state_propagation_epoch); +} + +template <typename T> +bool market::propagate_task_group_state ( T task_group_context::*mptr_state, task_group_context& src, T new_state ) { + if ( !(src.my_state & task_group_context::may_have_children) ) + return true; + // The whole propagation algorithm is under the lock in order to ensure correctness + // in case of concurrent state changes at the different levels of the context tree. + // See the note 3 at the bottom of scheduler.cpp + spin_mutex::scoped_lock lock(the_context_state_propagation_mutex); + if ( src.*mptr_state != new_state ) + // Another thread has concurrently changed the state. Back off. + return false; + src.*mptr_state = new_state; + // Advance global state propagation epoch + __TBB_FetchAndAddWrelease(&the_context_state_propagation_epoch, 1); + // Propagate to all workers and masters and sync up their local epochs with the global one + unsigned num_workers = my_num_workers; + for ( unsigned i = 0; i < num_workers; ++i ) { + generic_scheduler *s = my_workers[i]; + // If the worker is only about to be registered, skip it. + if ( s ) + s->propagate_task_group_state( mptr_state, new_state ); + } + // Propagate to all master threads (under my_arenas_list_mutex lock) + ForEachArena(a) { + arena_slot &slot = a.my_slots[0]; + generic_scheduler *s = slot.my_scheduler; + // If the master is under construction, skip it. Otherwise make sure that it does not + // leave its arena and its scheduler get destroyed while we accessing its data. + if ( s && __TBB_CompareAndSwapW(&slot.my_scheduler, (intptr_t)LockedMaster, (intptr_t)s) == (intptr_t)s ) { + __TBB_ASSERT( slot.my_scheduler == LockedMaster, NULL ); + // The whole propagation sequence is locked, thus no contention is expected + __TBB_ASSERT( s != LockedMaster, NULL ); + s->propagate_task_group_state( mptr_state, new_state ); + __TBB_store_with_release( slot.my_scheduler, s ); + } + } EndForEach(); + return true; +} + +template <typename T> +bool arena::propagate_task_group_state ( T task_group_context::*mptr_state, task_group_context& src, T new_state ) { + return my_market->propagate_task_group_state( mptr_state, src, new_state ); +} +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +bool task_group_context::cancel_group_execution () { + __TBB_ASSERT ( my_cancellation_requested == 0 || my_cancellation_requested == 1, "Invalid cancellation state"); + if ( my_cancellation_requested || __TBB_CompareAndSwapW(&my_cancellation_requested, 1, 0) ) { + // This task group has already been canceled + return false; + } + governor::local_scheduler()->my_arena->propagate_task_group_state( &task_group_context::my_cancellation_requested, *this, (uintptr_t)1 ); + return true; +} + +bool task_group_context::is_group_execution_cancelled () const { + return my_cancellation_requested != 0; +} + +// IMPORTANT: It is assumed that this method is not used concurrently! +void task_group_context::reset () { + //! \todo Add assertion that this context does not have children + // No fences are necessary since this context can be accessed from another thread + // only after stealing happened (which means necessary fences were used). + if ( my_exception ) { + my_exception->destroy(); + my_exception = NULL; + } + my_cancellation_requested = 0; +} + +void task_group_context::register_pending_exception () { + if ( my_cancellation_requested ) + return; +#if TBB_USE_EXCEPTIONS + try { + throw; + } TbbCatchAll( this ); +#endif /* TBB_USE_EXCEPTIONS */ +} + +#if __TBB_TASK_PRIORITY +void task_group_context::set_priority ( priority_t prio ) { + __TBB_ASSERT( prio == priority_low || prio == priority_normal || prio == priority_high, "Invalid priority level value" ); + intptr_t p = normalize_priority(prio); + if ( my_priority == p ) + return; + my_priority = p; + internal::generic_scheduler* s = governor::local_scheduler_if_initialized(); + if ( !s || !s->my_arena->propagate_task_group_state(&task_group_context::my_priority, *this, p) ) + return; + // Updating arena priority here does not eliminate necessity of checking each + // task priority and updating arena priority if necessary before the task execution. + // These checks will be necessary because: + // a) set_priority() may be invoked before any tasks from this task group are spawned; + // b) all spawned tasks from this task group are retrieved from the task pools. + // These cases create a time window when arena priority may be lowered. + s->my_market->update_arena_priority( *s->my_arena, p ); +} + +priority_t task_group_context::priority () const { + return static_cast<priority_t>(priority_from_normalized_rep[my_priority]); +} +#endif /* __TBB_TASK_PRIORITY */ + +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +} // namespace tbb diff --git a/src/tbb/src/tbb/task_stream.h b/src/tbb/src/tbb/task_stream.h new file mode 100644 index 0000000..bba51c9 --- /dev/null +++ b/src/tbb/src/tbb/task_stream.h @@ -0,0 +1,165 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _TBB_task_stream_H +#define _TBB_task_stream_H + +#include "tbb/tbb_stddef.h" +#include <deque> +#include <climits> +#include "tbb/atomic.h" // for __TBB_Atomic* +#include "tbb/spin_mutex.h" +#include "tbb/tbb_allocator.h" +#include "scheduler_common.h" +#include "tbb_misc.h" // for FastRandom + +namespace tbb { +namespace internal { + +//! Essentially, this is just a pair of a queue and a mutex to protect the queue. +/** The reason std::pair is not used is that the code would look less clean + if field names were replaced with 'first' and 'second'. **/ +template< typename T, typename mutex_t > +struct queue_and_mutex { + typedef std::deque< T, tbb_allocator<T> > queue_base_t; + + queue_base_t my_queue; + mutex_t my_mutex; + + queue_and_mutex () : my_queue(), my_mutex() {} + ~queue_and_mutex () {} +}; + +const uintptr_t one = 1; + +inline void set_one_bit( uintptr_t& dest, int pos ) { + __TBB_ASSERT( pos>=0, NULL ); + __TBB_ASSERT( pos<32, NULL ); + __TBB_AtomicOR( &dest, one<<pos ); +} + +inline void clear_one_bit( uintptr_t& dest, int pos ) { + __TBB_ASSERT( pos>=0, NULL ); + __TBB_ASSERT( pos<32, NULL ); + __TBB_AtomicAND( &dest, ~(one<<pos) ); +} + +inline bool is_bit_set( uintptr_t val, int pos ) { + __TBB_ASSERT( pos>=0, NULL ); + __TBB_ASSERT( pos<32, NULL ); + return (val & (one<<pos)) != 0; +} + +//! The container for "fairness-oriented" aka "enqueued" tasks. +class task_stream { + typedef queue_and_mutex <task*, spin_mutex> lane_t; + unsigned N; + uintptr_t population; + FastRandom random; + padded<lane_t>* lanes; + +public: + task_stream() : N(), population(), random(unsigned(&N-(unsigned*)NULL)), lanes() + { + __TBB_ASSERT( sizeof(population) * CHAR_BIT >= 32, NULL ); + } + + void initialize( unsigned n_lanes ) { + N = n_lanes>=32 ? 32 : n_lanes>2 ? 1<<(__TBB_Log2(n_lanes-1)+1) : 2; + __TBB_ASSERT( N==32 || N>=n_lanes && ((N-1)&N)==0, "number of lanes miscalculated"); + lanes = new padded<lane_t>[N]; + __TBB_ASSERT( !population, NULL ); + } + + ~task_stream() { if (lanes) delete[] lanes; } + + //! Push a task into a lane. + void push( task* source, unsigned& last_random ) { + // Lane selection is random. Each thread should keep a separate seed value. + unsigned idx; + for( ; ; ) { + idx = random.get(last_random) & (N-1); + spin_mutex::scoped_lock lock; + if( lock.try_acquire(lanes[idx].my_mutex) ) { + lanes[idx].my_queue.push_back(source); + set_one_bit( population, idx ); //TODO: avoid atomic op if the bit is already set + break; + } + } + } + //! Try finding and popping a task. + /** Does not change destination if unsuccessful. */ + void pop( task*& dest, unsigned& last_used_lane ) { + if( !population ) return; // keeps the hot path shorter + // Lane selection is round-robin. Each thread should keep its last used lane. + unsigned idx = (last_used_lane+1)&(N-1); + for( ; population; idx=(idx+1)&(N-1) ) { + if( is_bit_set( population, idx ) ) { + lane_t& lane = lanes[idx]; + spin_mutex::scoped_lock lock; + if( lock.try_acquire(lane.my_mutex) && !lane.my_queue.empty() ) { + dest = lane.my_queue.front(); + lane.my_queue.pop_front(); + if( lane.my_queue.empty() ) + clear_one_bit( population, idx ); + break; + } + } + } + last_used_lane = idx; + } + + //! Checks existence of a task. + bool empty() { + return !population; + } + //! Destroys all remaining tasks in every lane. Returns the number of destroyed tasks. + /** Tasks are not executed, because it would potentially create more tasks at a late stage. + The scheduler is really expected to execute all tasks before task_stream destruction. */ + intptr_t drain() { + intptr_t result = 0; + for(unsigned i=0; i<N; ++i) { + lane_t& lane = lanes[i]; + spin_mutex::scoped_lock lock(lane.my_mutex); + for(lane_t::queue_base_t::iterator it=lane.my_queue.begin(); + it!=lane.my_queue.end(); ++it, ++result) + { + task* t = *it; + tbb::task::destroy(*t); + } + lane.my_queue.clear(); + clear_one_bit( population, i ); + } + return result; + } +}; // task_stream + +} // namespace internal +} // namespace tbb + +#endif /* _TBB_task_stream_H */ diff --git a/src/tbb/src/tbb/tbb_assert_impl.h b/src/tbb/src/tbb/tbb_assert_impl.h new file mode 100644 index 0000000..700023d --- /dev/null +++ b/src/tbb/src/tbb/tbb_assert_impl.h @@ -0,0 +1,112 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// IMPORTANT: To use assertion handling in TBB, exactly one of the TBB source files +// should #include tbb_assert_impl.h thus instantiating assertion handling routines. +// The intent of putting it to a separate file is to allow some tests to use it +// as well in order to avoid dependency on the library. + +// include headers for required function declarations +#include <cstdlib> +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#if _MSC_VER +#include <crtdbg.h> +#define __TBB_USE_DBGBREAK_DLG TBB_USE_DEBUG +#endif + +#if _MSC_VER >= 1400 +#define __TBB_EXPORTED_FUNC __cdecl +#else +#define __TBB_EXPORTED_FUNC +#endif + +using namespace std; + +#if __TBBMALLOC_BUILD +namespace rml { namespace internal { +#else +namespace tbb { +#endif + //! Type for an assertion handler + typedef void(*assertion_handler_type)( const char* filename, int line, const char* expression, const char * comment ); + + static assertion_handler_type assertion_handler; + + assertion_handler_type __TBB_EXPORTED_FUNC set_assertion_handler( assertion_handler_type new_handler ) { + assertion_handler_type old_handler = assertion_handler; + assertion_handler = new_handler; + return old_handler; + } + + void __TBB_EXPORTED_FUNC assertion_failure( const char* filename, int line, const char* expression, const char* comment ) { + if( assertion_handler_type a = assertion_handler ) { + (*a)(filename,line,expression,comment); + } else { + static bool already_failed; + if( !already_failed ) { + already_failed = true; + fprintf( stderr, "Assertion %s failed on line %d of file %s\n", + expression, line, filename ); + if( comment ) + fprintf( stderr, "Detailed description: %s\n", comment ); +#if __TBB_USE_DBGBREAK_DLG + if(1 == _CrtDbgReport(_CRT_ASSERT, filename, line, "tbb_debug.dll", "%s\r\n%s", expression, comment?comment:"")) + _CrtDbgBreak(); +#else + fflush(stderr); + abort(); +#endif + } + } + } + +#if defined(_MSC_VER)&&_MSC_VER<1400 +# define vsnprintf _vsnprintf +#endif + +#if !__TBBMALLOC_BUILD + namespace internal { + //! Report a runtime warning. + void __TBB_EXPORTED_FUNC runtime_warning( const char* format, ... ) + { + char str[1024]; memset(str, 0, 1024); + va_list args; va_start(args, format); + vsnprintf( str, 1024-1, format, args); + va_end(args); + fprintf( stderr, "TBB Warning: %s\n", str); + } + } // namespace internal +#endif + +#if __TBBMALLOC_BUILD +}} // namespaces rml::internal +#else +} // namespace tbb +#endif diff --git a/src/tbb/src/tbb/tbb_main.cpp b/src/tbb/src/tbb/tbb_main.cpp new file mode 100644 index 0000000..800ce07 --- /dev/null +++ b/src/tbb/src/tbb/tbb_main.cpp @@ -0,0 +1,251 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb_main.h" +#include "governor.h" +#include "tbb_misc.h" +#include "itt_notify.h" + +namespace tbb { +namespace internal { + +//------------------------------------------------------------------------ +// Begin shared data layout. +// The following global data items are mostly read-only after initialization. +//------------------------------------------------------------------------ + +//! Padding in order to prevent false sharing. +static const char _pad[NFS_MaxLineSize - sizeof(int)] = {}; + +//------------------------------------------------------------------------ +// governor data +basic_tls<generic_scheduler*> governor::theTLS; +unsigned governor::DefaultNumberOfThreads; +rml::tbb_factory governor::theRMLServerFactory; +bool governor::UsePrivateRML; + +//------------------------------------------------------------------------ +// market data +market* market::theMarket; +market::global_market_mutex_type market::theMarketMutex; + +//------------------------------------------------------------------------ +// One time initialization data + +//! Counter of references to global shared resources such as TLS. +atomic<int> __TBB_InitOnce::count; + +__TBB_atomic_flag __TBB_InitOnce::InitializationLock; + +//! Flag that is set to true after one-time initializations are done. +bool __TBB_InitOnce::InitializationDone; + +#if DO_ITT_NOTIFY + static bool ITT_Present; + static bool ITT_InitializationDone; +#endif + +#if !(_WIN32||_WIN64) || __TBB_SOURCE_DIRECTLY_INCLUDED + static __TBB_InitOnce __TBB_InitOnceHiddenInstance; +#endif + +//------------------------------------------------------------------------ +// generic_scheduler data + +//! Pointer to the scheduler factory function +generic_scheduler* (*AllocateSchedulerPtr)( arena*, size_t index ); + +//! Table of primes used by fast random-number generator (FastRandom). +/** Also serves to keep anything else from being placed in the same + cache line as the global data items preceding it. */ +static const unsigned Primes[] = { + 0x9e3779b1, 0xffe6cc59, 0x2109f6dd, 0x43977ab5, + 0xba5703f5, 0xb495a877, 0xe1626741, 0x79695e6b, + 0xbc98c09f, 0xd5bee2b3, 0x287488f9, 0x3af18231, + 0x9677cd4d, 0xbe3a6929, 0xadc6a877, 0xdcf0674b, + 0xbe4d6fe9, 0x5f15e201, 0x99afc3fd, 0xf3f16801, + 0xe222cfff, 0x24ba5fdb, 0x0620452d, 0x79f149e3, + 0xc8b93f49, 0x972702cd, 0xb07dd827, 0x6c97d5ed, + 0x085a3d61, 0x46eb5ea7, 0x3d9910ed, 0x2e687b5b, + 0x29609227, 0x6eb081f1, 0x0954c4e1, 0x9d114db9, + 0x542acfa9, 0xb3e6bd7b, 0x0742d917, 0xe9f3ffa7, + 0x54581edb, 0xf2480f45, 0x0bb9288f, 0xef1affc7, + 0x85fa0ca7, 0x3ccc14db, 0xe6baf34b, 0x343377f7, + 0x5ca19031, 0xe6d9293b, 0xf0a9f391, 0x5d2e980b, + 0xfc411073, 0xc3749363, 0xb892d829, 0x3549366b, + 0x629750ad, 0xb98294e5, 0x892d9483, 0xc235baf3, + 0x3d2402a3, 0x6bdef3c9, 0xbec333cd, 0x40c9520f +}; + +//------------------------------------------------------------------------ +// End of shared data layout +//------------------------------------------------------------------------ + +//------------------------------------------------------------------------ +// Shared data accessors +//------------------------------------------------------------------------ + +unsigned GetPrime ( unsigned seed ) { + return Primes[seed%(sizeof(Primes)/sizeof(Primes[0]))]; +} + +//------------------------------------------------------------------------ +// __TBB_InitOnce +//------------------------------------------------------------------------ + +void __TBB_InitOnce::add_ref() { + if( ++count==1 ) + governor::acquire_resources(); +} + +void __TBB_InitOnce::remove_ref() { + int k = --count; + __TBB_ASSERT(k>=0,"removed __TBB_InitOnce ref that was not added?"); + if( k==0 ) + governor::release_resources(); +} + +//------------------------------------------------------------------------ +// One-time Initializations +//------------------------------------------------------------------------ + +//! Defined in cache_aligned_allocator.cpp +void initialize_cache_aligned_allocator(); + +//! Defined in scheduler.cpp +void Scheduler_OneTimeInitialization ( bool itt_present ); + +#if DO_ITT_NOTIFY + +/** Thread-unsafe lazy one-time initialization of tools interop. + Used by both dummy handlers and general TBB one-time initialization routine. **/ +void ITT_DoUnsafeOneTimeInitialization () { + if ( !ITT_InitializationDone ) { + ITT_Present = (__TBB_load_ittnotify()!=0); + ITT_InitializationDone = true; + ITT_SYNC_CREATE(&market::theMarketMutex, SyncType_GlobalLock, SyncObj_SchedulerInitialization); + } +} + +/** Thread-safe lazy one-time initialization of tools interop. + Used by dummy handlers only. **/ +extern "C" +void ITT_DoOneTimeInitialization() { + __TBB_InitOnce::lock(); + ITT_DoUnsafeOneTimeInitialization(); + __TBB_InitOnce::unlock(); +} +#endif /* DO_ITT_NOTIFY */ + +//! Performs thread-safe lazy one-time general TBB initialization. +void DoOneTimeInitializations() { + __TBB_InitOnce::lock(); + // No fence required for load of InitializationDone, because we are inside a critical section. + if( !__TBB_InitOnce::InitializationDone ) { + __TBB_InitOnce::add_ref(); + if( GetBoolEnvironmentVariable("TBB_VERSION") ) + PrintVersion(); + bool itt_present = false; +#if DO_ITT_NOTIFY + ITT_DoUnsafeOneTimeInitialization(); + itt_present = ITT_Present; +#endif /* DO_ITT_NOTIFY */ + initialize_cache_aligned_allocator(); + governor::initialize_rml_factory(); + Scheduler_OneTimeInitialization( itt_present ); + // Force processor groups support detection + governor::default_num_threads(); + // Dump version data + governor::print_version_info(); + PrintExtraVersionInfo( "Tools support", itt_present ? "enabled" : "disabled" ); + __TBB_InitOnce::InitializationDone = true; + } + __TBB_InitOnce::unlock(); +} + +#if (_WIN32||_WIN64) && !__TBB_SOURCE_DIRECTLY_INCLUDED +//! Windows "DllMain" that handles startup and shutdown of dynamic library. +extern "C" bool WINAPI DllMain( HANDLE /*hinstDLL*/, DWORD reason, LPVOID /*lpvReserved*/ ) { + switch( reason ) { + case DLL_PROCESS_ATTACH: + __TBB_InitOnce::add_ref(); + break; + case DLL_PROCESS_DETACH: + __TBB_InitOnce::remove_ref(); + // It is assumed that InitializationDone is not set after DLL_PROCESS_DETACH, + // and thus no race on InitializationDone is possible. + if( __TBB_InitOnce::initialization_done() ) { + // Remove reference that we added in DoOneTimeInitializations. + __TBB_InitOnce::remove_ref(); + } + break; + case DLL_THREAD_DETACH: + governor::terminate_auto_initialized_scheduler(); + break; + } + return true; +} +#endif /* (_WIN32||_WIN64) && !__TBB_SOURCE_DIRECTLY_INCLUDED */ + +void itt_store_pointer_with_release_v3( void* dst, void* src ) { + ITT_NOTIFY(sync_releasing, dst); + __TBB_store_with_release(*static_cast<void**>(dst),src); +} + +void* itt_load_pointer_with_acquire_v3( const void* src ) { + void* result = __TBB_load_with_acquire(*static_cast<void*const*>(src)); + ITT_NOTIFY(sync_acquired, const_cast<void*>(src)); + return result; +} + +#if DO_ITT_NOTIFY +void call_itt_notify_v5(int t, void *ptr) { + switch (t) { + case 0: ITT_NOTIFY(sync_prepare, ptr); break; + case 1: ITT_NOTIFY(sync_cancel, ptr); break; + case 2: ITT_NOTIFY(sync_acquired, ptr); break; + case 3: ITT_NOTIFY(sync_releasing, ptr); break; + } +} +#else +void call_itt_notify_v5(int /*t*/, void* /*ptr*/) {} +#endif + +void* itt_load_pointer_v3( const void* src ) { + void* result = *static_cast<void*const*>(src); + return result; +} + +void itt_set_sync_name_v3( void* obj, const tchar* name) { + ITT_SYNC_RENAME(obj, name); + suppress_unused_warning(obj && name); +} + + +} // namespace internal +} // namespace tbb diff --git a/src/tbb/src/tbb/tbb_main.h b/src/tbb/src/tbb/tbb_main.h new file mode 100644 index 0000000..14afbed --- /dev/null +++ b/src/tbb/src/tbb/tbb_main.h @@ -0,0 +1,104 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _TBB_tbb_main_H +#define _TBB_tbb_main_H + +#include "tbb/atomic.h" + +namespace tbb { + +namespace internal { + +void DoOneTimeInitializations (); + +//------------------------------------------------------------------------ +// __TBB_InitOnce +//------------------------------------------------------------------------ + +//! Class that supports TBB initialization. +/** It handles acquisition and release of global resources (e.g. TLS) during startup and shutdown, + as well as synchronization for DoOneTimeInitializations. */ +class __TBB_InitOnce { + friend void DoOneTimeInitializations(); + friend void ITT_DoUnsafeOneTimeInitialization (); + + static atomic<int> count; + + //! Platform specific code to acquire resources. + static void acquire_resources(); + + //! Platform specific code to release resources. + static void release_resources(); + + //! Specifies if the one-time initializations has been done. + static bool InitializationDone; + + //! Global initialization lock + /** Scenarios are possible when tools interop has to be initialized before the + TBB itself. This imposes a requirement that the global initialization lock + has to support valid static initialization, and does not issue any tool + notifications in any build mode. **/ + static __TBB_atomic_flag InitializationLock; + +public: + static void lock() { __TBB_LockByte( InitializationLock ); } + + static void unlock() { __TBB_UnlockByte( InitializationLock, 0 ); } + + static bool initialization_done() { return __TBB_load_with_acquire(InitializationDone); } + + //! Add initial reference to resources. + /** We assume that dynamic loading of the library prevents any other threads + from entering the library until this constructor has finished running. **/ + __TBB_InitOnce() { add_ref(); } + + //! Remove the initial reference to resources. + /** This is not necessarily the last reference if other threads are still running. **/ + ~__TBB_InitOnce() { + remove_ref(); + // We assume that InitializationDone is not set after file-scope destructors + // start running, and thus no race on InitializationDone is possible. + if( initialization_done() ) { + // Remove an extra reference that was added in DoOneTimeInitializations. + remove_ref(); + } + } + //! Add reference to resources. If first reference added, acquire the resources. + static void add_ref(); + + //! Remove reference to resources. If last reference removed, release the resources. + static void remove_ref(); +}; // class __TBB_InitOnce + + +} // namespace internal + +} // namespace tbb + +#endif /* _TBB_tbb_main_H */ diff --git a/src/tbb/src/tbb/tbb_misc.cpp b/src/tbb/src/tbb/tbb_misc.cpp new file mode 100644 index 0000000..2999f75 --- /dev/null +++ b/src/tbb/src/tbb/tbb_misc.cpp @@ -0,0 +1,245 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Source file for miscellaneous entities that are infrequently referenced by +// an executing program. + +#include "tbb/tbb_stddef.h" +#include "tbb_assert_impl.h" // Out-of-line TBB assertion handling routines are instantiated here. +#include "tbb/tbb_exception.h" +#include "tbb/tbb_machine.h" +#include "tbb_misc.h" +#include <cstdio> +#include <cstdlib> + +#if _WIN32||_WIN64 +#include "tbb/machine/windows_api.h" +#endif + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include <cstring> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +using namespace std; + +namespace tbb { + +const char* bad_last_alloc::what() const throw() { return "bad allocation in previous or concurrent attempt"; } +const char* improper_lock::what() const throw() { return "attempted recursive lock on critical section or non-recursive mutex"; } +const char* user_abort::what() const throw() { return "User-initiated abort has terminated this operation"; } +const char* invalid_multiple_scheduling::what() const throw() { return "The same task_handle object cannot be executed more than once"; } +const char* missing_wait::what() const throw() { return "wait() was not called on the structured_task_group"; } + +namespace internal { + +#if TBB_USE_EXCEPTIONS + #define DO_THROW(exc, init_args) throw exc init_args; +#else /* !TBB_USE_EXCEPTIONS */ + #define PRINT_ERROR_AND_ABORT(exc_name, msg) \ + fprintf (stderr, "Exception %s with message %s would've been thrown, " \ + "if exception handling were not disabled. Aborting.\n", exc_name, msg); \ + fflush(stderr); \ + abort(); + #define DO_THROW(exc, init_args) PRINT_ERROR_AND_ABORT(#exc, #init_args) +#endif /* !TBB_USE_EXCEPTIONS */ + + +/* The "what" should be fairly short, not more than about 128 characters. + Because we control all the call sites to handle_perror, it is pointless + to bullet-proof it for very long strings. + + Design note: ADR put this routine off to the side in tbb_misc.cpp instead of + Task.cpp because the throw generates a pathetic lot of code, and ADR wanted + this large chunk of code to be placed on a cold page. */ +void handle_perror( int error_code, const char* what ) { + char buf[256]; + __TBB_ASSERT( strlen(what) < sizeof(buf) - 64, "Error description is too long" ); + sprintf(buf,"%s: ",what); + char* end = strchr(buf,0); + size_t n = buf+sizeof(buf)-end; + strncpy( end, strerror( error_code ), n ); + // Ensure that buffer ends in terminator. + buf[sizeof(buf)-1] = 0; +#if TBB_USE_EXCEPTIONS + throw runtime_error(buf); +#else + PRINT_ERROR_AND_ABORT( "runtime_error", buf); +#endif /* !TBB_USE_EXCEPTIONS */ +} + +#if _WIN32||_WIN64 +void handle_win_error( int error_code ) { + char buf[512]; + FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, error_code, 0, buf, sizeof(buf), NULL ); +#if TBB_USE_EXCEPTIONS + throw runtime_error(buf); +#else + PRINT_ERROR_AND_ABORT( "runtime_error", buf); +#endif /* !TBB_USE_EXCEPTIONS */ +} +#endif // _WIN32||_WIN64 + +void throw_bad_last_alloc_exception_v4() { + throw_exception_v4(eid_bad_last_alloc); +} + +void throw_exception_v4 ( exception_id eid ) { + __TBB_ASSERT ( eid > 0 && eid < eid_max, "Unknown exception ID" ); + switch ( eid ) { + case eid_bad_alloc: DO_THROW( bad_alloc, () ); + case eid_bad_last_alloc: DO_THROW( bad_last_alloc, () ); + case eid_nonpositive_step: DO_THROW( invalid_argument, ("Step must be positive") ); + case eid_out_of_range: DO_THROW( out_of_range, ("Index out of requested size range") ); + case eid_segment_range_error: DO_THROW( range_error, ("Index out of allocated segment slots") ); + case eid_index_range_error: DO_THROW( range_error, ("Index is not allocated") ); + case eid_missing_wait: DO_THROW( missing_wait, () ); + case eid_invalid_multiple_scheduling: DO_THROW( invalid_multiple_scheduling, () ); + case eid_improper_lock: DO_THROW( improper_lock, () ); + case eid_possible_deadlock: DO_THROW( runtime_error, ("Resource deadlock would occur") ); + case eid_operation_not_permitted: DO_THROW( runtime_error, ("Operation not permitted") ); + case eid_condvar_wait_failed: DO_THROW( runtime_error, ("Wait on condition variable failed") ); + case eid_invalid_load_factor: DO_THROW( out_of_range, ("Invalid hash load factor") ); + case eid_reserved: DO_THROW( out_of_range, ("[backward compatibility] Invalid number of buckets") ); + case eid_invalid_swap: DO_THROW( invalid_argument, ("swap() is invalid on non-equal allocators") ); + case eid_reservation_length_error: DO_THROW( length_error, ("reservation size exceeds permitted max size") ); + case eid_invalid_key: DO_THROW( out_of_range, ("invalid key") ); + case eid_user_abort: DO_THROW( user_abort, () ); + default: break; + } +#if !TBB_USE_EXCEPTIONS && __APPLE__ + out_of_range e1(""); + length_error e2(""); + range_error e3(""); + invalid_argument e4(""); +#endif /* !TBB_USE_EXCEPTIONS && __APPLE__ */ +} + +#if _XBOX +bool GetBoolEnvironmentVariable( const char * name ) { return false;} +#else +bool GetBoolEnvironmentVariable( const char * name ) { + if( const char* s = getenv(name) ) + return strcmp(s,"0") != 0; + return false; +} +#endif /* !_XBOX */ + +#include "tbb_version.h" + +/** The leading "\0" is here so that applying "strings" to the binary delivers a clean result. */ +static const char VersionString[] = "\0" TBB_VERSION_STRINGS; + +static bool PrintVersionFlag = false; + +void PrintVersion() { + PrintVersionFlag = true; + fputs(VersionString+1,stderr); +} + +void PrintExtraVersionInfo( const char* category, const char* format, ... ) { + if( PrintVersionFlag ) { + char str[1024]; memset(str, 0, 1024); + va_list args; va_start(args, format); + // Note: correct vsnprintf definition obtained from tbb_assert_impl.h + vsnprintf( str, 1024-1, format, args); + va_end(args); + fprintf(stderr, "TBB: %s\t%s\n", category, str ); + } +} + +void PrintRMLVersionInfo( void* arg, const char* server_info ) { + PrintExtraVersionInfo( server_info, (const char *)arg ); +} + +} // namespace internal + +extern "C" int TBB_runtime_interface_version() { + return TBB_INTERFACE_VERSION; +} + +} // namespace tbb + +#if !__TBB_RML_STATIC +#if __TBB_x86_32 + +#include "tbb/atomic.h" + +// in MSVC environment, int64_t defined in tbb::internal namespace only (see tbb_stddef.h) +#if _MSC_VER +using tbb::internal::int64_t; +#endif + +//! Warn about 8-byte store that crosses a cache line. +extern "C" void __TBB_machine_store8_slow_perf_warning( volatile void *ptr ) { + // Report run-time warning unless we have already recently reported warning for that address. + const unsigned n = 4; + static tbb::atomic<void*> cache[n]; + static tbb::atomic<unsigned> k; + for( unsigned i=0; i<n; ++i ) + if( ptr==cache[i] ) + goto done; + cache[(k++)%n] = const_cast<void*>(ptr); + tbb::internal::runtime_warning( "atomic store on misaligned 8-byte location %p is slow", ptr ); +done:; +} + +//! Handle 8-byte store that crosses a cache line. +extern "C" void __TBB_machine_store8_slow( volatile void *ptr, int64_t value ) { + for( tbb::internal::atomic_backoff b;; b.pause() ) { + int64_t tmp = *(int64_t*)ptr; + if( __TBB_machine_cmpswp8(ptr,value,tmp)==tmp ) + break; + } +} + +#endif /* __TBB_x86_32 */ +#endif /* !__TBB_RML_STATIC */ + +#if __TBB_ipf +/* It was found that on IPF inlining of __TBB_machine_lockbyte leads + to serious performance regression with ICC 10.0. So keep it out-of-line. + */ +extern "C" intptr_t __TBB_machine_lockbyte( volatile unsigned char& flag ) { + if ( !__TBB_TryLockByte(flag) ) { + tbb::internal::atomic_backoff b; + do { + b.pause(); + } while ( !__TBB_TryLockByte(flag) ); + } + return 0; +} +#endif diff --git a/src/tbb/src/tbb/tbb_misc.h b/src/tbb/src/tbb/tbb_misc.h new file mode 100644 index 0000000..9af65f4 --- /dev/null +++ b/src/tbb/src/tbb/tbb_misc.h @@ -0,0 +1,251 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _TBB_tbb_misc_H +#define _TBB_tbb_misc_H + +#include "tbb/tbb_stddef.h" +#include "tbb/tbb_machine.h" +#include "tbb/atomic.h" // For atomic_xxx definitions + +#if __linux__ || __FreeBSD__ +#include <sys/param.h> // __FreeBSD_version +#if __FreeBSD_version >= 701000 +#include <sys/cpuset.h> +#endif +#endif + +namespace tbb { +namespace internal { + +const size_t MByte = 1024*1024; + +const size_t ThreadStackSize = (sizeof(uintptr_t) <= 4 ? 2 : 4 )*MByte; + +#ifndef __TBB_HardwareConcurrency + +//! Returns maximal parallelism level supported by the current OS configuration. +int AvailableHwConcurrency(); + +#else + +inline int AvailableHwConcurrency() { + int n = __TBB_HardwareConcurrency(); + return n > 0 ? n : 1; // Fail safety strap +} +#endif /* __TBB_HardwareConcurrency */ + + +#if _WIN32||_WIN64 + +//! Returns number of processor groups in the current OS configuration. +/** AvailableHwConcurrency must be called at least once before calling this method. **/ +int NumberOfProcessorGroups(); + +//! Retrieves index of processor group containing processor with the given index +int FindProcessorGroupIndex ( int processorIndex ); + +//! Affinitizes the thread to the specified processor group +void MoveThreadIntoProcessorGroup( void* hThread, int groupIndex ); + +#endif /* _WIN32||_WIN64 */ + +//! Throws std::runtime_error with what() returning error_code description prefixed with aux_info +void handle_win_error( int error_code ); + +//! True if environment variable with given name is set and not 0; otherwise false. +bool GetBoolEnvironmentVariable( const char * name ); + +//! Prints TBB version information on stderr +void PrintVersion(); + +//! Prints arbitrary extra TBB version information on stderr +void PrintExtraVersionInfo( const char* category, const char* format, ... ); + +//! A callback routine to print RML version information on stderr +void PrintRMLVersionInfo( void* arg, const char* server_info ); + +// For TBB compilation only; not to be used in public headers +#if defined(min) || defined(max) +#undef min +#undef max +#endif + +//! Utility template function returning lesser of the two values. +/** Provided here to avoid including not strict safe <algorithm>.\n + In case operands cause signed/unsigned or size mismatch warnings it is caller's + responsibility to do the appropriate cast before calling the function. **/ +template<typename T1, typename T2> +T1 min ( const T1& val1, const T2& val2 ) { + return val1 < val2 ? val1 : val2; +} + +//! Utility template function returning greater of the two values. +/** Provided here to avoid including not strict safe <algorithm>.\n + In case operands cause signed/unsigned or size mismatch warnings it is caller's + responsibility to do the appropriate cast before calling the function. **/ +template<typename T1, typename T2> +T1 max ( const T1& val1, const T2& val2 ) { + return val1 < val2 ? val2 : val1; +} + +//! Utility template function to prevent "unused" warnings by various compilers. +template<typename T> +void suppress_unused_warning( const T& ) {} + +//------------------------------------------------------------------------ +// FastRandom +//------------------------------------------------------------------------ + +/** Defined in tbb_main.cpp **/ +unsigned GetPrime ( unsigned seed ); + +//! A fast random number generator. +/** Uses linear congruential method. */ +class FastRandom { + unsigned x, a; +public: + //! Get a random number. + unsigned short get() { + return get(x); + } + //! Get a random number for the given seed; update the seed for next use. + unsigned short get( unsigned& seed ) { + unsigned short r = (unsigned short)(seed>>16); + seed = seed*a+1; + return r; + } + //! Construct a random number generator. + FastRandom( unsigned seed ) { + x = seed; + a = GetPrime( seed ); + } +}; + +//------------------------------------------------------------------------ +// Atomic extensions +//------------------------------------------------------------------------ + +//! Atomically replaces value of dst with newValue if they satisfy condition of compare predicate +/** Return value semantics is the same as for CAS. **/ +template<typename T1, typename T2, class Pred> +T1 atomic_update ( tbb::atomic<T1>& dst, T2 newValue, Pred compare ) { + T1 oldValue = dst; + while ( compare(oldValue, newValue) ) { + if ( dst.compare_and_swap((T1)newValue, oldValue) == oldValue ) + break; + oldValue = dst; + } + return oldValue; +} + +//! One-time initialization states +enum do_once_state { + do_once_uninitialized = 0, ///< No execution attempts have been undertaken yet + do_once_pending, ///< A thread is executing associated do-once routine + do_once_executed, ///< Do-once routine has been executed + initialization_complete = do_once_executed ///< Convenience alias +}; + +//! One-time initialization function +/** /param initializer Pointer to function without arguments + The variant that returns bool is used for cases when initialization can fail + and it is OK to continue execution, but the state should be reset so that + the initialization attempt was repeated the next time. + /param state Shared state associated with initializer that specifies its + initialization state. Must be initially set to #uninitialized value + (e.g. by means of default static zero initialization). **/ +template <typename F> +void atomic_do_once ( const F& initializer, atomic<do_once_state>& state ) { + // tbb::atomic provides necessary acquire and release fences. + // The loop in the implementation is necessary to avoid race when thread T2 + // that arrived in the middle of initialization attempt by another thread T1 + // has just made initialization possible. + // In such a case T2 has to rely on T1 to initialize, but T1 may already be past + // the point where it can recognize the changed conditions. + while ( state != do_once_executed ) { + if( state == do_once_uninitialized ) { + if( state.compare_and_swap( do_once_pending, do_once_uninitialized ) == do_once_uninitialized ) { + run_initializer( initializer, state ); + break; + } + } + spin_wait_while_eq( state, do_once_pending ); + } +} + +// Run the initializer which can not fail +inline void run_initializer( void (*f)(), atomic<do_once_state>& state ) { + f(); + state = do_once_executed; +} + +// Run the initializer which can require repeated call +inline void run_initializer( bool (*f)(), atomic<do_once_state>& state ) { + state = f() ? do_once_executed : do_once_uninitialized; +} + +#ifdef __TBB_HardwareConcurrency + class affinity_helper { + public: + void protect_affinity_mask() {} + }; +#elif __linux__ || __FreeBSD_version >= 701000 + #if __linux__ + typedef cpu_set_t basic_mask_t; + #elif __FreeBSD_version >= 701000 + typedef cpuset_t basic_mask_t; + #else + #error affinity_helper is not implemented in this OS + #endif + class affinity_helper { + basic_mask_t* threadMask; + int is_changed; + public: + affinity_helper() : threadMask(NULL), is_changed(0) {} + ~affinity_helper(); + void protect_affinity_mask(); + }; +#elif defined(_SC_NPROCESSORS_ONLN) + class affinity_helper { + public: + void protect_affinity_mask() {} + }; +#elif _WIN32||_WIN64 + class affinity_helper { + public: + void protect_affinity_mask() {} + }; +#else + #error affinity_helper is not implemented in this OS +#endif /* __TBB_HardwareConcurrency */ + +} // namespace internal +} // namespace tbb + +#endif /* _TBB_tbb_misc_H */ diff --git a/src/tbb/src/tbb/tbb_misc_ex.cpp b/src/tbb/src/tbb/tbb_misc_ex.cpp new file mode 100644 index 0000000..b328195 --- /dev/null +++ b/src/tbb/src/tbb/tbb_misc_ex.cpp @@ -0,0 +1,352 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Source file for miscellaneous entities that are infrequently referenced by +// an executing program, and implementation of which requires dynamic linking. + +#include "tbb_misc.h" + +#if !defined(__TBB_HardwareConcurrency) + +#include "dynamic_link.h" +#include <stdio.h> +#include <limits.h> + +#if _WIN32||_WIN64 +#include "tbb/machine/windows_api.h" +#elif __linux__ +#include <sys/sysinfo.h> +#include <string.h> +#include <sched.h> +#include <errno.h> +#elif __sun +#include <sys/sysinfo.h> +#include <unistd.h> +#elif __FreeBSD__ +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <sys/param.h> // Required by <sys/cpuset.h> +#include <sys/cpuset.h> +#elif _AIX +#include <unistd.h> +#endif + +namespace tbb { +namespace internal { + +#if __linux__ || __FreeBSD_version >= 701000 + +static void set_affinity_mask( size_t maskSize, const basic_mask_t* threadMask ) { +#if __linux__ + if( sched_setaffinity( 0, maskSize, threadMask ) ) +#else /* FreeBSD */ + if( cpuset_setaffinity( CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, maskSize, threadMask ) ) +#endif + runtime_warning( "setaffinity syscall failed" ); +} + +static void get_affinity_mask( size_t maskSize, basic_mask_t* threadMask ) { +#if __linux__ + if( sched_getaffinity( 0, maskSize, threadMask ) ) +#else /* FreeBSD */ + if( cpuset_getaffinity( CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, maskSize, threadMask ) ) +#endif + runtime_warning( "getaffinity syscall failed" ); +} + +static basic_mask_t* process_mask; +static int num_masks; +struct process_mask_cleanup_helper { + ~process_mask_cleanup_helper() { + if( process_mask ) { + delete [] process_mask; + } + } +}; +static process_mask_cleanup_helper process_mask_cleanup; + +#define curMaskSize sizeof(basic_mask_t) * num_masks +affinity_helper::~affinity_helper() { + if( threadMask ) { + if( is_changed ) { + set_affinity_mask( curMaskSize, threadMask ); + } + delete [] threadMask; + } +} +void affinity_helper::protect_affinity_mask() { + if( threadMask == NULL && num_masks && process_mask ) { + threadMask = new basic_mask_t [num_masks]; + memset( threadMask, 0, curMaskSize ); + get_affinity_mask( curMaskSize, threadMask ); + is_changed = memcmp( process_mask, threadMask, curMaskSize ); + if( is_changed ) { + set_affinity_mask( curMaskSize, process_mask ); + } + } +} +#undef curMaskSize + +static atomic<do_once_state> hardware_concurrency_info; + +static int theNumProcs; + +static void initialize_hardware_concurrency_info () { + int err; + int availableProcs = 0; + int numMasks = 1; +#if __linux__ +#if __TBB_MAIN_THREAD_AFFINITY_BROKEN + int maxProcs = INT_MAX; // To check the entire mask. + int pid = 0; // Get the mask of the calling thread. +#else + int maxProcs = sysconf(_SC_NPROCESSORS_ONLN); + int pid = getpid(); +#endif + cpu_set_t *processMask; + const size_t BasicMaskSize = sizeof(cpu_set_t); + for (;;) { + int curMaskSize = BasicMaskSize * numMasks; + processMask = new cpu_set_t[numMasks]; + memset( processMask, 0, curMaskSize ); + err = sched_getaffinity( pid, curMaskSize, processMask ); + if ( !err || errno != EINVAL || curMaskSize * CHAR_BIT >= 256 * 1024 ) + break; + delete[] processMask; + numMasks <<= 1; + } +#else /* FreeBSD >= 7.1 */ + int maxProcs = sysconf(_SC_NPROCESSORS_ONLN); + cpuset_t *processMask; + const size_t BasicMaskSize = sizeof(cpuset_t); + for (;;) { + int curMaskSize = BasicMaskSize * numMasks; + processMask = new cpuset_t[numMasks]; + memset( processMask, 0, curMaskSize ); + // CPU_LEVEL_WHICH - anonymous (current) mask, CPU_LEVEL_CPUSET - assigned mask +#if __TBB_MAIN_THREAD_AFFINITY_BROKEN + err = cpuset_getaffinity( CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, curMaskSize, processMask ); +#else + err = cpuset_getaffinity( CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, curMaskSize, processMask ); +#endif + if ( !err || errno != ERANGE || curMaskSize * CHAR_BIT >= 16 * 1024 ) + break; + delete[] processMask; + numMasks <<= 1; + } +#endif /* FreeBSD >= 7.1 */ + if ( !err ) { + for ( int m = 0; availableProcs < maxProcs && m < numMasks; ++m ) { + for ( size_t i = 0; (availableProcs < maxProcs) && (i < BasicMaskSize * CHAR_BIT); ++i ) { + if ( CPU_ISSET( i, processMask + m ) ) + ++availableProcs; + } + } + num_masks = numMasks; + process_mask = processMask; + } + else { + availableProcs = (maxProcs == INT_MAX) ? sysconf(_SC_NPROCESSORS_ONLN) : maxProcs; + delete[] processMask; + } + theNumProcs = availableProcs > 0 ? availableProcs : 1; // Fail safety strap + __TBB_ASSERT( theNumProcs <= sysconf(_SC_NPROCESSORS_ONLN), NULL ); +} + +int AvailableHwConcurrency() { + atomic_do_once( &initialize_hardware_concurrency_info, hardware_concurrency_info ); + return theNumProcs; +} + +#elif defined(_SC_NPROCESSORS_ONLN) + +int AvailableHwConcurrency() { + int n = sysconf(_SC_NPROCESSORS_ONLN); + return n > 0 ? n : 1; +} + +#elif _WIN32||_WIN64 + +static atomic<do_once_state> hardware_concurrency_info; + +static const WORD TBB_ALL_PROCESSOR_GROUPS = 0xffff; + +// Statically allocate an array for processor group information. +// Windows 7 supports maximum 4 groups, but let's look ahead a little. +static const WORD MaxProcessorGroups = 64; + +struct ProcessorGroupInfo { + DWORD_PTR mask; ///< Affinity mask covering the whole group + int numProcs; ///< Number of processors in the group + int numProcsRunningTotal; ///< Subtotal of processors in this and preceding groups + + //! Total number of processor groups in the system + static int NumGroups; + + //! Index of the group with a slot reserved for the first master thread + /** In the context of multiple processor groups support current implementation + defines "the first master thread" as the first thread to invoke + AvailableHwConcurrency(). + + TODO: Implement a dynamic scheme remapping workers depending on the pending + master threads affinity. **/ + static int HoleIndex; +}; + +int ProcessorGroupInfo::NumGroups = 1; +int ProcessorGroupInfo::HoleIndex = 0; + + +ProcessorGroupInfo theProcessorGroups[MaxProcessorGroups]; + +struct TBB_GROUP_AFFINITY { + DWORD_PTR Mask; + WORD Group; + WORD Reserved[3]; +}; + +static DWORD (WINAPI *TBB_GetMaximumProcessorCount)( WORD groupIndex ) = NULL; +static WORD (WINAPI *TBB_GetMaximumProcessorGroupCount)() = NULL; +static BOOL (WINAPI *TBB_SetThreadGroupAffinity)( HANDLE hThread, + const TBB_GROUP_AFFINITY* newAff, TBB_GROUP_AFFINITY *prevAff ); +static BOOL (WINAPI *TBB_GetThreadGroupAffinity)( HANDLE hThread, TBB_GROUP_AFFINITY* ); + +static const dynamic_link_descriptor ProcessorGroupsApiLinkTable[] = { + DLD(GetMaximumProcessorCount, TBB_GetMaximumProcessorCount) + , DLD(GetMaximumProcessorGroupCount, TBB_GetMaximumProcessorGroupCount) + , DLD(SetThreadGroupAffinity, TBB_SetThreadGroupAffinity) + , DLD(GetThreadGroupAffinity, TBB_GetThreadGroupAffinity) +}; + +static void initialize_hardware_concurrency_info () { + dynamic_link( GetModuleHandleA( "Kernel32.dll" ), ProcessorGroupsApiLinkTable, + sizeof(ProcessorGroupsApiLinkTable)/sizeof(dynamic_link_descriptor) ); + SYSTEM_INFO si; + GetSystemInfo(&si); + DWORD_PTR pam, sam, m = 1; + GetProcessAffinityMask( GetCurrentProcess(), &pam, &sam ); + int nproc = 0; + for ( size_t i = 0; i < sizeof(DWORD_PTR) * CHAR_BIT; ++i, m <<= 1 ) { + if ( pam & m ) + ++nproc; + } + __TBB_ASSERT( nproc <= (int)si.dwNumberOfProcessors, NULL ); + if ( nproc == (int)si.dwNumberOfProcessors && TBB_GetMaximumProcessorCount ) { + // The process does not have restricting affinity mask and multiple processor groups are possible + ProcessorGroupInfo::NumGroups = (int)TBB_GetMaximumProcessorGroupCount(); + __TBB_ASSERT( ProcessorGroupInfo::NumGroups <= MaxProcessorGroups, NULL ); + // Fail safety bootstrap. Release versions will limit available concurrency + // level, while debug ones would assert. + if ( ProcessorGroupInfo::NumGroups > MaxProcessorGroups ) + ProcessorGroupInfo::NumGroups = MaxProcessorGroups; + if ( ProcessorGroupInfo::NumGroups > 1 ) { + TBB_GROUP_AFFINITY ga; + if ( TBB_GetThreadGroupAffinity( GetCurrentThread(), &ga ) ) + ProcessorGroupInfo::HoleIndex = ga.Group; + int nprocs = 0; + for ( WORD i = 0; i < ProcessorGroupInfo::NumGroups; ++i ) { + ProcessorGroupInfo &pgi = theProcessorGroups[i]; + pgi.numProcs = (int)TBB_GetMaximumProcessorCount(i); + __TBB_ASSERT( pgi.numProcs <= (int)sizeof(DWORD_PTR) * CHAR_BIT, NULL ); + pgi.mask = pgi.numProcs == sizeof(DWORD_PTR) * CHAR_BIT ? ~(DWORD_PTR)0 : (DWORD_PTR(1) << pgi.numProcs) - 1; + pgi.numProcsRunningTotal = nprocs += pgi.numProcs; + } + __TBB_ASSERT( nprocs == (int)TBB_GetMaximumProcessorCount( TBB_ALL_PROCESSOR_GROUPS ), NULL ); + return; + } + } + // Either the process has restricting affinity mask or only a single processor groups is present + theProcessorGroups[0].numProcs = theProcessorGroups[0].numProcsRunningTotal = nproc; + + PrintExtraVersionInfo("Processor groups", "%d", ProcessorGroupInfo::NumGroups); + if (ProcessorGroupInfo::NumGroups>1) + for (int i=0; i<ProcessorGroupInfo::NumGroups; ++i) + PrintExtraVersionInfo( "----- Group", "%d: size %d", i, theProcessorGroups[i].numProcs); +} + +int AvailableHwConcurrency() { + atomic_do_once( &initialize_hardware_concurrency_info, hardware_concurrency_info ); + return theProcessorGroups[ProcessorGroupInfo::NumGroups - 1].numProcsRunningTotal; +} + +int NumberOfProcessorGroups() { + __TBB_ASSERT( hardware_concurrency_info == initialization_complete, "NumberOfProcessorGroups is used before AvailableHwConcurrency" ); + return ProcessorGroupInfo::NumGroups; +} + +// Offset for the slot reserved for the first master thread +#define HoleAdjusted(procIdx, grpIdx) (procIdx + (holeIdx <= grpIdx)) + +int FindProcessorGroupIndex ( int procIdx ) { + // In case of oversubscription spread extra workers in a round robin manner + int holeIdx; + const int numProcs = theProcessorGroups[ProcessorGroupInfo::NumGroups - 1].numProcsRunningTotal; + if ( procIdx >= numProcs - 1 ) { + holeIdx = INT_MAX; + procIdx = (procIdx - numProcs + 1) % numProcs; + } + else + holeIdx = ProcessorGroupInfo::HoleIndex; + __TBB_ASSERT( hardware_concurrency_info == initialization_complete, "FindProcessorGroupIndex is used before AvailableHwConcurrency" ); + // Approximate the likely group index assuming all groups are of the same size + int i = procIdx / theProcessorGroups[0].numProcs; + // Make sure the approximation is a valid group index + if (i >= ProcessorGroupInfo::NumGroups) i = ProcessorGroupInfo::NumGroups-1; + // Now adjust the approximation up or down + if ( theProcessorGroups[i].numProcsRunningTotal > HoleAdjusted(procIdx, i) ) { + while ( theProcessorGroups[i].numProcsRunningTotal - theProcessorGroups[i].numProcs > HoleAdjusted(procIdx, i) ) { + __TBB_ASSERT( i > 0, NULL ); + --i; + } + } + else { + do { + ++i; + } while ( theProcessorGroups[i].numProcsRunningTotal <= HoleAdjusted(procIdx, i) ); + } + __TBB_ASSERT( i < ProcessorGroupInfo::NumGroups, NULL ); + return i; +} + +void MoveThreadIntoProcessorGroup( void* hThread, int groupIndex ) { + __TBB_ASSERT( hardware_concurrency_info == initialization_complete, "MoveThreadIntoProcessorGroup is used before AvailableHwConcurrency" ); + if ( !TBB_SetThreadGroupAffinity ) + return; + TBB_GROUP_AFFINITY ga = { theProcessorGroups[groupIndex].mask, (WORD)groupIndex, {0,0,0} }; + TBB_SetThreadGroupAffinity( hThread, &ga, NULL ); +} + +#else + #error AvailableHwConcurrency is not implemented in this OS +#endif /* OS */ + +} // namespace internal +} // namespace tbb + +#endif /* !__TBB_HardwareConcurrency */ diff --git a/src/tbb/src/tbb/tbb_resource.rc b/src/tbb/src/tbb/tbb_resource.rc new file mode 100644 index 0000000..3ba56f0 --- /dev/null +++ b/src/tbb/src/tbb/tbb_resource.rc @@ -0,0 +1,126 @@ +// Copyright 2005-2012 Intel Corporation. All Rights Reserved. +// +// This file is part of Threading Building Blocks. +// +// Threading Building Blocks is free software; you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// Threading Building Blocks is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Threading Building Blocks; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// Microsoft Visual C++ generated resource script. +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include <winresrc.h> +#define ENDL "\r\n" +#include "tbb_version.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Neutral resources + +//#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// manifest integration +#ifdef TBB_MANIFEST +#include "winuser.h" +2 RT_MANIFEST tbbmanifest.exe.manifest +#endif + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION TBB_VERNUMBERS + PRODUCTVERSION TBB_VERNUMBERS + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "CompanyName", "Intel Corporation\0" + VALUE "FileDescription", "Threading Building Blocks library\0" + VALUE "FileVersion", TBB_VERSION "\0" +//what is it? VALUE "InternalName", "tbb\0" + VALUE "LegalCopyright", "Copyright 2005-2012 Intel Corporation. All Rights Reserved.\0" + VALUE "LegalTrademarks", "\0" +#ifndef TBB_USE_DEBUG + VALUE "OriginalFilename", "tbb.dll\0" +#else + VALUE "OriginalFilename", "tbb_debug.dll\0" +#endif + VALUE "ProductName", "Intel(R) Threading Building Blocks for Windows\0" + VALUE "ProductVersion", TBB_VERSION "\0" + VALUE "Comments", TBB_VERSION_STRINGS "\0" + VALUE "PrivateBuild", "\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END + +//#endif // Neutral resources +///////////////////////////////////////////////////////////////////////////// + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/tbb/src/tbb/tbb_statistics.cpp b/src/tbb/src/tbb/tbb_statistics.cpp new file mode 100644 index 0000000..be8f9e2 --- /dev/null +++ b/src/tbb/src/tbb/tbb_statistics.cpp @@ -0,0 +1,195 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb_statistics.h" + +#if __TBB_STATISTICS + +#include <climits> +#include <cstdarg> +#if __TBB_STATISTICS_STDOUT +#include <cstdio> +#endif + +#include "tbb/spin_mutex.h" + +namespace tbb { +namespace internal { + +//! Human readable titles of statistics groups defined by statistics_groups enum. +/** The order of this vector elements must correspond to the statistics_counters + structure layout. **/ +const char* StatGroupTitles[] = { + "task objects", "tasks executed", "stealing attempts", "task proxies", "arena", "market", "priority ops", "prio ops details" +}; + +//! Human readable titles of statistics elements defined by statistics_counters struct. +/** The order of this vector elements must correspond to the statistics_counters + structure layout (with NULLs interspersed to separate groups). **/ +const char* StatFieldTitles[] = { + /*task objects*/ "active", "freed", "big", NULL, + /*tasks executed*/ "total", "w/o spawn", NULL, + /*stealing attempts*/ "succeeded", "failed", "conflicts", "backoffs", NULL, + /*task proxies*/ "mailed", "revoked", "stolen", "bypassed", "ignored", NULL, + /*arena*/ "switches", "roundtrips", "avg.conc", "avg.allot", NULL, + /*market*/ "roundtrips", NULL, + /*priority ops*/ "ar.switch", "mkt.switch", "ar.reset", "ref.fixup", "avg.ar.pr", "avg.mkt.pr", NULL, + /*prio ops details*/ "winnows", "reloads", "orphaned", "winnowed", "reloaded", NULL +}; + +//! Class for logging statistics +/** There should be only one instance of this class. + Results are written to a file "statistics.txt" in tab-separated format. */ +class statistics_logger { +public: + statistics_logger () { + __TBB_ASSERT( sg_end - 1 == 1 << (sizeof(StatGroupTitles)/sizeof(*StatGroupTitles) - 1), NULL ); + + my_file = fopen("statistics.txt","w"); + if( !my_file ) + perror("fopen(\"statistics.txt\"\")"); + // Initialize groups dump layout info + group_start_field[0] = 0; + for ( size_t i = 0, j = 0; i < NumGroups; ++i, ++j ) { + __TBB_ASSERT( StatFieldTitles[j], "Empty group occurred" ); + while ( StatFieldTitles[j] ) + ++j; + group_start_field[i + 1] = j - i; // -i accounts for preceding NULL separators + } + __TBB_ASSERT( group_start_field[NumGroups] == statistics_counters::size(), + "Wrong number of elements in StatFieldTitles" ); + dump( "%-*s", IDColumnWidth, ""); + process_groups( &statistics_logger::print_group_title ); + dump( "%-*s", IDColumnWidth, "ID"); + process_groups( &statistics_logger::print_field_titles ); + } + + ~statistics_logger () { fclose(my_file); } + + void record( const statistics_counters& c, size_t id ) { + spin_mutex::scoped_lock lock(my_mutex); + counters_to_dump = &c; +#if __TBB_STATISTICS_TOTALS_ONLY + if ( id == arena_counters_total ) { + dump( "%-*s", IDColumnWidth, "Tot" ); + process_groups( &statistics_logger::print_field_values ); + } +#else /* !__TBB_STATISTICS_TOTALS_ONLY */ + const char* idString = NULL; + switch ( id ) { + case 0: + idString = "M"; break; + case workers_counters_total: + idString = "Wtot"; break; + case arena_counters_total: + idString = "Tot"; break; + default: + dump( "W%-*u", IDColumnWidth - 1, id ); + } + if ( idString ) + dump( "%-*s", IDColumnWidth, idString ); + process_groups( &statistics_logger::print_field_values ); +#endif /* !__TBB_STATISTICS_TOTALS_ONLY */ + } +private: + static const size_t IDColumnWidth = 5; + static const size_t StatisticsColumnWidth = 10; + static const size_t NumGroups = sizeof(StatGroupTitles)/sizeof(char*); + + //! File into which statistics are written. + FILE* my_file; + //! Mutex that serializes accesses to my_file + spin_mutex my_mutex; + //! Indices of the each group's first field in statistics_counters struct. + /** An extra element is used to track the total number of statistics fields. **/ + size_t group_start_field[NumGroups + 1]; + //! Currently processed set of counters. + const statistics_counters* counters_to_dump; + + static const size_t NumFields = sizeof(StatFieldTitles)/sizeof(*StatFieldTitles) - NumGroups; + bool averages_fields[NumFields]; + + void dump ( char const* fmt, ... ) { + va_list args; + if ( my_file ) { + va_start( args, fmt ); + vfprintf( my_file, fmt, args ); + va_end( args ); + } +#if __TBB_STATISTICS_STDOUT + va_start( args, fmt ); + vprintf( fmt, args ); + va_end( args ); +#endif + } + + void process_groups ( void (statistics_logger::*per_group_action)(size_t group_idx) ) { + for ( size_t i = 0, group_flag = 1; i < NumGroups; ++i, group_flag <<= 1 ) { + __TBB_ASSERT( group_flag < sg_end, "StatGroupTitles contents is incompatible with statistics_groups definition" ); + if ( __TBB_ActiveStatisticsGroups & group_flag ) + (this->*per_group_action)( i ); + } + dump( "\n" ); + } + + void print_group_title ( size_t group_idx ) { + dump( "%-*s", (group_start_field[group_idx + 1] - group_start_field[group_idx]) * (StatisticsColumnWidth + 1), + StatGroupTitles[group_idx] ); + } + + void print_field_titles ( size_t group_idx ) { + // +group_idx accounts for preceding NULL separators + size_t i = group_start_field[group_idx] + group_idx; + while ( StatFieldTitles[i] ) { + averages_fields[i - group_idx] = strncmp(StatFieldTitles[i], "avg.", 4) == 0; + dump( "%-*s ", StatisticsColumnWidth, StatFieldTitles[i++] ); + } + } + + void print_field_values ( size_t group_idx ) { + size_t begin = group_start_field[group_idx], + end = group_start_field[group_idx + 1]; + for ( size_t i = begin; i < end; ++i ) { + if ( averages_fields[i] ) + dump( "%-*.2f ", StatisticsColumnWidth, (double)counters_to_dump->field(i)/counters_to_dump->tasks_executed ); + else + dump( "%-*ld ", StatisticsColumnWidth, counters_to_dump->field(i) ); + } + } +}; // class statistics_logger + +static statistics_logger the_statistics; + +void dump_statistics ( const statistics_counters& c, size_t id ) { + the_statistics.record(c, id); +} + +} // namespace internal +} // namespace tbb + +#endif /* __TBB_STATISTICS */ diff --git a/src/tbb/src/tbb/tbb_statistics.h b/src/tbb/src/tbb/tbb_statistics.h new file mode 100644 index 0000000..f5e222d --- /dev/null +++ b/src/tbb/src/tbb/tbb_statistics.h @@ -0,0 +1,248 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _TBB_tbb_statistics_H +#define _TBB_tbb_statistics_H + +/** + This file defines parameters of the internal statistics collected by the TBB + library (currently by the task scheduler only). + + Statistics is accumulated separately in each thread and is dumped when + the scheduler instance associated with the given thread is destroyed. + For apps with multiple master threads or with the same master repeatedly + initializing and then deinitializing task scheduler this results in TBB + workers statistics getting inseparably mixed. + + Therefore statistics is accumulated in arena slots, and should be dumped + when arena is destroyed. This separates statistics collected for each + scheduler activity region in each master thread. + + With the current RML implementation (TBB 2.2, 3.0) to avoid complete loss of + statistics data during app shutdown (because of lazy workers deinitialization + logic) set __TBB_STATISTICS_EARLY_DUMP macro to write the statistics at the + moment a master thread deinitializes its scheduler. This may happen a little + earlier than the moment of arena destruction resulting in the following undesired + (though usually tolerable) effects: + - a few events related to unsuccessful stealing or thread pool activity may be lost, + - statistics may be substantially incomplete in case of FIFO tasks used in + the FAF mode. + + Macro __TBB_STATISTICS_STDOUT and global variable __TBB_ActiveStatisticsGroups + defined below can be used to configure the statistics output. + + To add new counter: + 1) Insert it into the appropriate group range in statistics_counters; + 2) Insert the corresponding field title into StatFieldTitles (preserving + relative order of the fields). + + To add new counters group: + 1) Insert new group bit flag into statistics_groups; + 2) Insert the new group title into StatGroupTitles (preserving + relative order of the groups). + 3) Add counter belonging to the new group as described above +**/ + +#include "tbb/tbb_stddef.h" + +#ifndef __TBB_STATISTICS +#define __TBB_STATISTICS 0 +#endif /* __TBB_STATISTICS */ + +#if __TBB_STATISTICS + +#include <string.h> // for memset + +//! Dump counters into stdout as well. +/** By default statistics counters are written to the file "statistics.txt" only. **/ +#define __TBB_STATISTICS_STDOUT 1 + +//! Dump only totals for all threads in the given arena +/** By default statistics counters for each arena slot are dumped separately, as + well as the subtotal for workers. **/ +#define __TBB_STATISTICS_TOTALS_ONLY 1 + +//! Dump statistics for an arena when its master completes +/** By default (when this macro is not set) the statistics is sent to output when + arena object is destroyed. But with the current lazy workers termination + logic default behavior may result in loosing all statistics output. **/ +#define __TBB_STATISTICS_EARLY_DUMP 1 + +#define GATHER_STATISTIC(x) (x) + +namespace tbb { +namespace internal { + +//! Groups of statistics counters. +/** The order of enumerators must be the same as the order of the corresponding + field groups in the statistics_counters structure. **/ +enum statistics_groups { + sg_task_allocation = 0x01, + sg_task_execution = 0x02, + sg_stealing = 0x04, + sg_affinity = 0x08, + sg_arena = 0x10, + sg_market = 0x20, + sg_prio = 0x40, + sg_prio_ex = 0x80, + // List end marker. Insert new groups only before it. + sg_end +}; + +//! Groups of counters to output +const uintptr_t __TBB_ActiveStatisticsGroups = sg_task_execution | sg_stealing | sg_arena | sg_market; + +//! A set of various statistics counters that are updated by the library on per thread basis. +/** All the fields must be of the same type (statistics_counters::counter_type). + This is necessary to allow reinterpreting this structure as an array. **/ +struct statistics_counters { + typedef long counter_type; + + // Group: sg_task_allocation + // Counters in this group can have negative values as the tasks migrate across + // threads while the associated counters are updated in the current thread only + // to avoid data races + + //! Number of tasks allocated and not yet destroyed + counter_type active_tasks; + //! Number of task corpses stored for future reuse + counter_type free_list_length; + //! Number of big tasks allocated during the run + /** To find total number of tasks malloc'd, compute (big_tasks+my_small_task_count) */ + counter_type big_tasks; + + // Group: sg_task_execution + + //! Number of tasks executed + counter_type tasks_executed; + //! Number of elided spawns + counter_type spawns_bypassed; + + // Group: sg_stealing + + //! Number of tasks successfully stolen + counter_type steals_committed; + //! Number of failed stealing attempts + counter_type steals_failed; + //! Number of failed attempts to lock victim's task pool + counter_type thieves_conflicts; + //! Number of times thief backed off because of the collision with the owner + counter_type thief_backoffs; + + // Group: sg_affinity + + //! Number of tasks received from mailbox + counter_type mails_received; + //! Number of affinitized tasks executed by the owner + /** Goes as "revoked" in statistics printout. **/ + counter_type proxies_executed; + //! Number of affinitized tasks intercepted by thieves + counter_type proxies_stolen; + //! Number of proxy bypasses by thieves during stealing + counter_type proxies_bypassed; + //! Number of affinitized tasks executed by the owner via scheduler bypass mechanism + counter_type affinity_ignored; + + // Group: sg_arena + + //! Number of times the state of arena switched between "full" and "empty" + counter_type gate_switches; + //! Number of times workers left an arena and returned into the market + counter_type arena_roundtrips; + // !Average concurrency level of this arena + counter_type avg_arena_concurrency; + //! Average assigned priority + counter_type avg_assigned_workers; + + // Group: sg_market + + //! Number of times workers left the market and returned into RML + counter_type market_roundtrips; + + // Group; sg_prio + + //! Number of arena priority switches + counter_type arena_prio_switches; + //! Number of market priority switches + counter_type market_prio_switches; + //! Number of arena priority switches + counter_type arena_prio_resets; + //! Number of reference priority source fixups to avoid deadlock + counter_type prio_ref_fixups; + //! Average arena priority + counter_type avg_arena_prio; + //! Average market priority + counter_type avg_market_prio; + + // Group; sg_prio_ex + + //! Number of times local task pools were winnowed + counter_type prio_winnowings; + //! Number of times secondary task pools were searched for top priority tasks + counter_type prio_reloads; + //! Number of times secondary task pools were abandoned by quitting workers + counter_type prio_orphanings; + //! Number of tasks offloaded into secondary task pools + counter_type prio_tasks_offloaded; + //! Number of tasks reloaded from secondary task pools + counter_type prio_tasks_reloaded; + + // Constructor and helpers + + statistics_counters() { reset(); } + + void reset () { memset( this, 0, sizeof(statistics_counters) ); } + + counter_type& field ( size_t index ) { return reinterpret_cast<counter_type*>(this)[index]; } + + const counter_type& field ( size_t index ) const { return reinterpret_cast<const counter_type*>(this)[index]; } + + static size_t size () { return sizeof(statistics_counters) / sizeof(counter_type); } + + const statistics_counters& operator += ( const statistics_counters& rhs ) { + for ( size_t i = 0; i < size(); ++i ) + field(i) += rhs.field(i); + return *this; + } +}; // statistics_counters + +static const size_t workers_counters_total = (size_t)-1; +static const size_t arena_counters_total = (size_t)-2; + +void dump_statistics ( const statistics_counters& c, size_t id ); + +} // namespace internal +} // namespace tbb + +#else /* !__TBB_STATISTICS */ + +#define GATHER_STATISTIC(x) ((void)0) + +#endif /* !__TBB_STATISTICS */ + +#endif /* _TBB_tbb_statistics_H */ diff --git a/src/tbb/src/tbb/tbb_thread.cpp b/src/tbb/src/tbb/tbb_thread.cpp new file mode 100644 index 0000000..b677f15 --- /dev/null +++ b/src/tbb/src/tbb/tbb_thread.cpp @@ -0,0 +1,172 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if _WIN32||_WIN64 +#include <process.h> // _beginthreadex() +#endif +#include "tbb_misc.h" // handle_win_error(), ThreadStackSize +#include "tbb/tbb_stddef.h" +#include "tbb/tbb_thread.h" +#include "tbb/tbb_allocator.h" +#include "governor.h" // default_num_threads() + +namespace tbb { +namespace internal { + +//! Allocate a closure +void* allocate_closure_v3( size_t size ) +{ + return allocate_via_handler_v3( size ); +} + +//! Free a closure allocated by allocate_closure_v3 +void free_closure_v3( void *ptr ) +{ + deallocate_via_handler_v3( ptr ); +} + +void tbb_thread_v3::join() +{ + __TBB_ASSERT( joinable(), "thread should be joinable when join called" ); +#if _WIN32||_WIN64 + DWORD status = WaitForSingleObject( my_handle, INFINITE ); + if ( status == WAIT_FAILED ) + handle_win_error( GetLastError() ); + BOOL close_stat = CloseHandle( my_handle ); + if ( close_stat == 0 ) + handle_win_error( GetLastError() ); + my_thread_id = 0; +#else + int status = pthread_join( my_handle, NULL ); + if( status ) + handle_perror( status, "pthread_join" ); +#endif // _WIN32||_WIN64 + my_handle = 0; +} + +void tbb_thread_v3::detach() { + __TBB_ASSERT( joinable(), "only joinable thread can be detached" ); +#if _WIN32||_WIN64 + BOOL status = CloseHandle( my_handle ); + if ( status == 0 ) + handle_win_error( GetLastError() ); + my_thread_id = 0; +#else + int status = pthread_detach( my_handle ); + if( status ) + handle_perror( status, "pthread_detach" ); +#endif // _WIN32||_WIN64 + my_handle = 0; +} + +void tbb_thread_v3::internal_start( __TBB_NATIVE_THREAD_ROUTINE_PTR(start_routine), + void* closure ) { +#if _WIN32||_WIN64 + unsigned thread_id; + // The return type of _beginthreadex is "uintptr_t" on new MS compilers, + // and 'unsigned long' on old MS compilers. uintptr_t works for both. + uintptr_t status = _beginthreadex( NULL, ThreadStackSize, start_routine, + closure, 0, &thread_id ); + if( status==0 ) + handle_perror(errno,"__beginthreadex"); + else { + my_handle = (HANDLE)status; + my_thread_id = thread_id; + } +#else + pthread_t thread_handle; + int status; + pthread_attr_t stack_size; + status = pthread_attr_init( &stack_size ); + if( status ) + handle_perror( status, "pthread_attr_init" ); + status = pthread_attr_setstacksize( &stack_size, ThreadStackSize ); + if( status ) + handle_perror( status, "pthread_attr_setstacksize" ); + + status = pthread_create( &thread_handle, &stack_size, start_routine, closure ); + if( status ) + handle_perror( status, "pthread_create" ); + + my_handle = thread_handle; +#endif // _WIN32||_WIN64 +} + +unsigned tbb_thread_v3::hardware_concurrency() { + return governor::default_num_threads(); +} + +tbb_thread_v3::id thread_get_id_v3() { +#if _WIN32||_WIN64 + return tbb_thread_v3::id( GetCurrentThreadId() ); +#else + return tbb_thread_v3::id( pthread_self() ); +#endif // _WIN32||_WIN64 +} + +void move_v3( tbb_thread_v3& t1, tbb_thread_v3& t2 ) +{ + if (t1.joinable()) + t1.detach(); + t1.my_handle = t2.my_handle; + t2.my_handle = 0; +#if _WIN32||_WIN64 + t1.my_thread_id = t2.my_thread_id; + t2.my_thread_id = 0; +#endif // _WIN32||_WIN64 +} + +void thread_yield_v3() +{ + __TBB_Yield(); +} + +void thread_sleep_v3(const tick_count::interval_t &i) +{ +#if _WIN32||_WIN64 + tick_count t0 = tick_count::now(); + tick_count t1 = t0; + for(;;) { + double remainder = (i-(t1-t0)).seconds()*1e3; // milliseconds remaining to sleep + if( remainder<=0 ) break; + DWORD t = remainder>=INFINITE ? INFINITE-1 : DWORD(remainder); + Sleep( t ); + t1 = tick_count::now(); + } +#else + struct timespec req; + double sec = i.seconds(); + + req.tv_sec = static_cast<long>(sec); + req.tv_nsec = static_cast<long>( (sec - req.tv_sec)*1e9 ); + nanosleep(&req, NULL); +#endif // _WIN32||_WIN64 +} + +} // internal +} // tbb diff --git a/src/tbb/src/tbb/tbb_version.h b/src/tbb/src/tbb/tbb_version.h new file mode 100644 index 0000000..d5edae2 --- /dev/null +++ b/src/tbb/src/tbb/tbb_version.h @@ -0,0 +1,127 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Please define version number in the file: +#include "tbb/tbb_stddef.h" + +// And don't touch anything below +#ifndef ENDL +#define ENDL "\n" +#endif +#include "version_string.ver" + +#ifndef __TBB_VERSION_STRINGS +#pragma message("Warning: version_string.ver isn't generated properly by version_info.sh script!") +// here is an example of macros value: +#define __TBB_VERSION_STRINGS \ +"TBB: BUILD_HOST\tUnknown\n" \ +"TBB: BUILD_ARCH\tUnknown\n" \ +"TBB: BUILD_OS\t\tUnknown\n" \ +"TBB: BUILD_CL\t\tUnknown\n" \ +"TBB: BUILD_COMPILER\tUnknown\n" \ +"TBB: BUILD_COMMAND\tUnknown\n" +#endif +#ifndef __TBB_DATETIME +#ifdef RC_INVOKED +#define __TBB_DATETIME "Unknown" +#else +#define __TBB_DATETIME __DATE__ __TIME__ +#endif +#endif + +#define __TBB_VERSION_NUMBER(N) #N ": VERSION\t\t" __TBB_STRING(TBB_VERSION_MAJOR.TBB_VERSION_MINOR) ENDL +#define __TBB_INTERFACE_VERSION_NUMBER(N) #N ": INTERFACE VERSION\t" __TBB_STRING(TBB_INTERFACE_VERSION) ENDL + +#define __TBB_VERSION_DATETIME(N) #N ": BUILD_DATE\t\t" __TBB_DATETIME ENDL +#ifndef TBB_USE_DEBUG + #define __TBB_VERSION_USE_DEBUG(N) #N ": TBB_USE_DEBUG\tundefined" ENDL +#elif TBB_USE_DEBUG==0 + #define __TBB_VERSION_USE_DEBUG(N) #N ": TBB_USE_DEBUG\t0" ENDL +#elif TBB_USE_DEBUG==1 + #define __TBB_VERSION_USE_DEBUG(N) #N ": TBB_USE_DEBUG\t1" ENDL +#elif TBB_USE_DEBUG==2 + #define __TBB_VERSION_USE_DEBUG(N) #N ": TBB_USE_DEBUG\t2" ENDL +#else + #error Unexpected value for TBB_USE_DEBUG +#endif + +/* Make __TBB_VERSION_USE_ASSERT and __TBB_VERSION_DO_NOTIFY empty for rc + * because rc from VS2005 crashed with fatal error RC10056 for too complex + * macros (for example, when __TBB_CPF_BUILD is enabled). + * All information is available in BUILD_COMMAND anyway. + */ + +#ifdef RC_INVOKED + #define __TBB_VERSION_USE_ASSERT(N) +#else // RC_INVOKED +#ifndef TBB_USE_ASSERT + #define __TBB_VERSION_USE_ASSERT(N) #N ": TBB_USE_ASSERT\tundefined" ENDL +#elif TBB_USE_ASSERT==0 + #define __TBB_VERSION_USE_ASSERT(N) #N ": TBB_USE_ASSERT\t0" ENDL +#elif TBB_USE_ASSERT==1 + #define __TBB_VERSION_USE_ASSERT(N) #N ": TBB_USE_ASSERT\t1" ENDL +#elif TBB_USE_ASSERT==2 + #define __TBB_VERSION_USE_ASSERT(N) #N ": TBB_USE_ASSERT\t2" ENDL +#else + #error Unexpected value for TBB_USE_ASSERT +#endif +#endif // RC_INVOKED + +#ifndef __TBB_CPF_BUILD + #define __TBB_VERSION_TBB_PREVIEW_BINARY(N) +#else + #define __TBB_VERSION_TBB_PREVIEW_BINARY(N) #N ": TBB_PREVIEW_BINARY\t1" ENDL +#endif + +#ifdef RC_INVOKED + #define __TBB_VERSION_DO_NOTIFY(N) +#else +#ifndef DO_ITT_NOTIFY + #define __TBB_VERSION_DO_NOTIFY(N) #N ": DO_ITT_NOTIFY\tundefined" ENDL +#elif DO_ITT_NOTIFY==1 + #define __TBB_VERSION_DO_NOTIFY(N) #N ": DO_ITT_NOTIFY\t1" ENDL +#elif DO_ITT_NOTIFY==0 + #define __TBB_VERSION_DO_NOTIFY(N) +#else + #error Unexpected value for DO_ITT_NOTIFY +#endif +#endif // RC_INVOKED + +#define TBB_VERSION_STRINGS_P(N) __TBB_VERSION_NUMBER(N) __TBB_INTERFACE_VERSION_NUMBER(N) __TBB_VERSION_DATETIME(N) __TBB_VERSION_STRINGS(N) __TBB_VERSION_USE_DEBUG(N) __TBB_VERSION_USE_ASSERT(N) __TBB_VERSION_TBB_PREVIEW_BINARY(N) __TBB_VERSION_DO_NOTIFY(N) + +#define TBB_VERSION_STRINGS TBB_VERSION_STRINGS_P(TBB) +#define TBBMALLOC_VERSION_STRINGS TBB_VERSION_STRINGS_P(TBBmalloc) + +// numbers +#ifndef __TBB_VERSION_YMD +#define __TBB_VERSION_YMD 0, 0 +#endif + +#define TBB_VERNUMBERS TBB_VERSION_MAJOR, TBB_VERSION_MINOR, __TBB_VERSION_YMD + +#define TBB_VERSION __TBB_STRING(TBB_VERNUMBERS) diff --git a/src/tbb/src/tbb/tls.h b/src/tbb/src/tbb/tls.h new file mode 100644 index 0000000..97294d2 --- /dev/null +++ b/src/tbb/src/tbb/tls.h @@ -0,0 +1,119 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _TBB_tls_H +#define _TBB_tls_H + +#if USE_PTHREAD +#include <pthread.h> +#else /* assume USE_WINTHREAD */ +#include "tbb/machine/windows_api.h" +#endif + +namespace tbb { + +namespace internal { + +typedef void (*tls_dtor_t)(void*); + +//! Basic cross-platform wrapper class for TLS operations. +template <typename T> +class basic_tls { +#if USE_PTHREAD + typedef pthread_key_t tls_key_t; +public: + int create( tls_dtor_t dtor = NULL ) { + return pthread_key_create(&my_key, dtor); + } + int destroy() { return pthread_key_delete(my_key); } + void set( T value ) { pthread_setspecific(my_key, (void*)value); } + T get() { return (T)pthread_getspecific(my_key); } +#else /* USE_WINTHREAD */ + typedef DWORD tls_key_t; +public: + int create() { + tls_key_t tmp = TlsAlloc(); + if( tmp==TLS_OUT_OF_INDEXES ) + return TLS_OUT_OF_INDEXES; + my_key = tmp; + return 0; + } + int destroy() { TlsFree(my_key); my_key=0; return 0; } + void set( T value ) { TlsSetValue(my_key, (LPVOID)value); } + T get() { return (T)TlsGetValue(my_key); } +#endif +private: + tls_key_t my_key; +}; + +//! More advanced TLS support template class. +/** It supports RAII and to some extent mimic __declspec(thread) variables. */ +template <typename T> +class tls : public basic_tls<T> { + typedef basic_tls<T> base; +public: + tls() { base::create(); } + ~tls() { base::destroy(); } + T operator=(T value) { base::set(value); return value; } + operator T() { return base::get(); } +}; + +template <typename T> +class tls<T*> : basic_tls<T*> { + typedef basic_tls<T*> base; + static void internal_dtor(void* ptr) { + if (ptr) delete (T*)ptr; + } + T* internal_get() { + T* result = base::get(); + if (!result) { + result = new T; + base::set(result); + } + return result; + } +public: + tls() { +#if USE_PTHREAD + base::create( internal_dtor ); +#else + base::create(); +#endif + } + ~tls() { base::destroy(); } + T* operator=(T* value) { base::set(value); return value; } + operator T*() { return internal_get(); } + T* operator->() { return internal_get(); } + T& operator*() { return *internal_get(); } +}; + +} // namespace internal + +} // namespace tbb + +#endif /* _TBB_tls_H */ diff --git a/src/tbb/src/tbb/tools_api/disable_warnings.h b/src/tbb/src/tbb/tools_api/disable_warnings.h new file mode 100644 index 0000000..7ce1ff1 --- /dev/null +++ b/src/tbb/src/tbb/tools_api/disable_warnings.h @@ -0,0 +1,47 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "ittnotify_config.h" + +#if ITT_PLATFORM==ITT_PLATFORM_WIN + +#pragma warning (disable: 593) /* parameter "XXXX" was set but never used */ +#pragma warning (disable: 344) /* typedef name has already been declared (with same type) */ +#pragma warning (disable: 174) /* expression has no effect */ +#pragma warning (disable: 4127) /* conditional expression is constant */ +#pragma warning (disable: 4306) /* conversion from '?' to '?' of greater size */ + +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +#if defined __INTEL_COMPILER + +#pragma warning (disable: 869) /* parameter "XXXXX" was never referenced */ +#pragma warning (disable: 1418) /* external function definition with no prior declaration */ +#pragma warning (disable: 1419) /* external declaration in primary source file */ + +#endif /* __INTEL_COMPILER */ diff --git a/src/tbb/src/tbb/tools_api/internal/ittnotify.h b/src/tbb/src/tbb/tools_api/internal/ittnotify.h new file mode 100644 index 0000000..339a98f --- /dev/null +++ b/src/tbb/src/tbb/tools_api/internal/ittnotify.h @@ -0,0 +1,661 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _INTERNAL_ITTNOTIFY_H_ +#define _INTERNAL_ITTNOTIFY_H_ +/** + * @file + * @brief Internal User API functions and types + */ + +/** @cond exclude_from_documentation */ +#ifndef ITT_OS_WIN +# define ITT_OS_WIN 1 +#endif /* ITT_OS_WIN */ + +#ifndef ITT_OS_LINUX +# define ITT_OS_LINUX 2 +#endif /* ITT_OS_LINUX */ + +#ifndef ITT_OS_MAC +# define ITT_OS_MAC 3 +#endif /* ITT_OS_MAC */ + +#ifndef ITT_OS +# if defined WIN32 || defined _WIN32 +# define ITT_OS ITT_OS_WIN +# elif defined( __APPLE__ ) && defined( __MACH__ ) +# define ITT_OS ITT_OS_MAC +# else +# define ITT_OS ITT_OS_LINUX +# endif +#endif /* ITT_OS */ + +#ifndef ITT_PLATFORM_WIN +# define ITT_PLATFORM_WIN 1 +#endif /* ITT_PLATFORM_WIN */ + +#ifndef ITT_PLATFORM_POSIX +# define ITT_PLATFORM_POSIX 2 +#endif /* ITT_PLATFORM_POSIX */ + +#ifndef ITT_PLATFORM +# if ITT_OS==ITT_OS_WIN +# define ITT_PLATFORM ITT_PLATFORM_WIN +# else +# define ITT_PLATFORM ITT_PLATFORM_POSIX +# endif /* _WIN32 */ +#endif /* ITT_PLATFORM */ + +#include <stddef.h> +#include <stdarg.h> +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#include <tchar.h> +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +#ifndef CDECL +# if ITT_PLATFORM==ITT_PLATFORM_WIN +# define CDECL __cdecl +# else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +# define CDECL /* nothing */ +# endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* CDECL */ + +#ifndef STDCALL +# if ITT_PLATFORM==ITT_PLATFORM_WIN +# define STDCALL __stdcall +# else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +# define STDCALL /* nothing */ +# endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* STDCALL */ + +#define ITTAPI CDECL +#define LIBITTAPI /* nothing */ + +#define ITT_JOIN_AUX(p,n) p##n +#define ITT_JOIN(p,n) ITT_JOIN_AUX(p,n) + +#ifndef INTEL_ITTNOTIFY_PREFIX +# define INTEL_ITTNOTIFY_PREFIX __itt_ +#endif /* INTEL_ITTNOTIFY_PREFIX */ +#ifndef INTEL_ITTNOTIFY_POSTFIX +# define INTEL_ITTNOTIFY_POSTFIX _ptr_ +#endif /* INTEL_ITTNOTIFY_POSTFIX */ + +#define ITTNOTIFY_NAME_AUX(n) ITT_JOIN(INTEL_ITTNOTIFY_PREFIX,n) +#define ITTNOTIFY_NAME(n) ITTNOTIFY_NAME_AUX(ITT_JOIN(n,INTEL_ITTNOTIFY_POSTFIX)) + +#define ITTNOTIFY_VOID(n) (!ITTNOTIFY_NAME(n)) ? (void)0 : ITTNOTIFY_NAME(n) +#define ITTNOTIFY_DATA(n) (!ITTNOTIFY_NAME(n)) ? 0 : ITTNOTIFY_NAME(n) + +#ifdef ITT_STUB +#undef ITT_STUB +#endif +#ifdef ITT_STUBV +#undef ITT_STUBV +#endif +#define ITT_STUBV(api,type,name,args,params) \ + typedef type (api* ITT_JOIN(ITTNOTIFY_NAME(name),_t)) args; \ + extern ITT_JOIN(ITTNOTIFY_NAME(name),_t) ITTNOTIFY_NAME(name); +#define ITT_STUB ITT_STUBV + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ +/** @endcond */ + +/** + * @defgroup internal Internal API + * @{ + * @} + */ + +/** + * @defgroup makrs Marks + * @ingroup internal + * Marks group + * @warning Internal API: + * - It is not shipped to outside of Intel + * - It is delivered to internal Intel teams using e-mail or SVN access only + * @{ + */ +/** @brief user mark type */ +typedef int __itt_mark_type; + +/** + * @brief Creates a user mark type with the specified name using char or Unicode string. + * @param[in] name - name of mark to create + * @return Returns a handle to the mark type + */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +__itt_mark_type ITTAPI __itt_mark_createA(const char *name); +__itt_mark_type ITTAPI __itt_mark_createW(const wchar_t *name); +#ifdef UNICODE +# define __itt_mark_create __itt_mark_createW +# define __itt_mark_create_ptr __itt_mark_createW_ptr +#else /* UNICODE */ +# define __itt_mark_create __itt_mark_createA +# define __itt_mark_create_ptr __itt_mark_createA_ptr +#endif /* UNICODE */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +__itt_mark_type ITTAPI __itt_mark_create(const char *name); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(ITTAPI, __itt_mark_type, mark_createA, (const char *name), (name)) +ITT_STUB(ITTAPI, __itt_mark_type, mark_createW, (const wchar_t *name), (name)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, __itt_mark_type, mark_create, (const char *name), (name)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_mark_createA ITTNOTIFY_DATA(mark_createA) +#define __itt_mark_createA_ptr ITTNOTIFY_NAME(mark_createA) +#define __itt_mark_createW ITTNOTIFY_DATA(mark_createW) +#define __itt_mark_createW_ptr ITTNOTIFY_NAME(mark_createW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_mark_create ITTNOTIFY_DATA(mark_create) +#define __itt_mark_create_ptr ITTNOTIFY_NAME(mark_create) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_mark_createA(name) (__itt_mark_type)0 +#define __itt_mark_createA_ptr 0 +#define __itt_mark_createW(name) (__itt_mark_type)0 +#define __itt_mark_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_mark_create(name) (__itt_mark_type)0 +#define __itt_mark_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_mark_createA_ptr 0 +#define __itt_mark_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_mark_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Creates a "discrete" user mark type of the specified type and an optional parameter using char or Unicode string. + * + * - The mark of "discrete" type is placed to collection results in case of success. It appears in overtime view(s) as a special tick sign. + * - The call is "synchronous" - function returns after mark is actually added to results. + * - This function is useful, for example, to mark different phases of application + * (beginning of the next mark automatically meand end of current region). + * - Can be used together with "continuous" marks (see below) at the same collection session + * @param[in] mt - mark, created by __itt_mark_create(const char* name) function + * @param[in] parameter - string parameter of mark + * @return Returns zero value in case of success, non-zero value otherwise. + */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +int ITTAPI __itt_markA(__itt_mark_type mt, const char *parameter); +int ITTAPI __itt_markW(__itt_mark_type mt, const wchar_t *parameter); +#ifdef UNICODE +# define __itt_mark __itt_markW +# define __itt_mark_ptr __itt_markW_ptr +#else /* UNICODE */ +# define __itt_mark __itt_markA +# define __itt_mark_ptr __itt_markA_ptr +#endif /* UNICODE */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +int ITTAPI __itt_mark(__itt_mark_type mt, const char *parameter); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(ITTAPI, int, markA, (__itt_mark_type mt, const char *parameter), (mt, parameter)) +ITT_STUB(ITTAPI, int, markW, (__itt_mark_type mt, const wchar_t *parameter), (mt, parameter)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, int, mark, (__itt_mark_type mt, const char *parameter), (mt, parameter)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_markA ITTNOTIFY_DATA(markA) +#define __itt_markA_ptr ITTNOTIFY_NAME(markA) +#define __itt_markW ITTNOTIFY_DATA(markW) +#define __itt_markW_ptr ITTNOTIFY_NAME(markW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_mark ITTNOTIFY_DATA(mark) +#define __itt_mark_ptr ITTNOTIFY_NAME(mark) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_markA(mt, parameter) (int)0 +#define __itt_markA_ptr 0 +#define __itt_markW(mt, parameter) (int)0 +#define __itt_markW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_mark(mt, parameter) (int)0 +#define __itt_mark_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_markA_ptr 0 +#define __itt_markW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_mark_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Use this if necessary to create a "discrete" user event type (mark) for process + * rather then for one thread + * @see int __itt_mark(__itt_mark_type mt, const char* parameter); + */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +int ITTAPI __itt_mark_globalA(__itt_mark_type mt, const char *parameter); +int ITTAPI __itt_mark_globalW(__itt_mark_type mt, const wchar_t *parameter); +#ifdef UNICODE +# define __itt_mark_global __itt_mark_globalW +# define __itt_mark_global_ptr __itt_mark_globalW_ptr +#else /* UNICODE */ +# define __itt_mark_global __itt_mark_globalA +# define __itt_mark_global_ptr __itt_mark_globalA_ptr +#endif /* UNICODE */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +int ITTAPI __itt_mark_global(__itt_mark_type mt, const char *parameter); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(ITTAPI, int, mark_globalA, (__itt_mark_type mt, const char *parameter), (mt, parameter)) +ITT_STUB(ITTAPI, int, mark_globalW, (__itt_mark_type mt, const wchar_t *parameter), (mt, parameter)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, int, mark_global, (__itt_mark_type mt, const char *parameter), (mt, parameter)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_mark_globalA ITTNOTIFY_DATA(mark_globalA) +#define __itt_mark_globalA_ptr ITTNOTIFY_NAME(mark_globalA) +#define __itt_mark_globalW ITTNOTIFY_DATA(mark_globalW) +#define __itt_mark_globalW_ptr ITTNOTIFY_NAME(mark_globalW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_mark_global ITTNOTIFY_DATA(mark_global) +#define __itt_mark_global_ptr ITTNOTIFY_NAME(mark_global) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_mark_globalA(mt, parameter) (int)0 +#define __itt_mark_globalA_ptr 0 +#define __itt_mark_globalW(mt, parameter) (int)0 +#define __itt_mark_globalW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_mark_global(mt, parameter) (int)0 +#define __itt_mark_global_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_mark_globalA_ptr 0 +#define __itt_mark_globalW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_mark_global_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Creates an "end" point for "continuous" mark with specified name. + * + * - Returns zero value in case of success, non-zero value otherwise. + * Also returns non-zero value when preceding "begin" point for the + * mark with the same name failed to be created or not created. + * - The mark of "continuous" type is placed to collection results in + * case of success. It appears in overtime view(s) as a special tick + * sign (different from "discrete" mark) together with line from + * corresponding "begin" mark to "end" mark. + * @note Continuous marks can overlap and be nested inside each other. + * Discrete mark can be nested inside marked region + * @param[in] mt - mark, created by __itt_mark_create(const char* name) function + * @return Returns zero value in case of success, non-zero value otherwise. + */ +int ITTAPI __itt_mark_off(__itt_mark_type mt); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUB(ITTAPI, int, mark_off, (__itt_mark_type mt), (mt)) +#define __itt_mark_off ITTNOTIFY_DATA(mark_off) +#define __itt_mark_off_ptr ITTNOTIFY_NAME(mark_off) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_mark_off(mt) (int)0 +#define __itt_mark_off_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_mark_off_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Use this if necessary to create an "end" point for mark of process + * @see int __itt_mark_off(__itt_mark_type mt); + */ +int ITTAPI __itt_mark_global_off(__itt_mark_type mt); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUB(ITTAPI, int, mark_global_off, (__itt_mark_type mt), (mt)) +#define __itt_mark_global_off ITTNOTIFY_DATA(mark_global_off) +#define __itt_mark_global_off_ptr ITTNOTIFY_NAME(mark_global_off) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_mark_global_off(mt) (int)0 +#define __itt_mark_global_off_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_mark_global_off_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} marks group */ + +/** + * @defgroup counters Counters + * @ingroup internal + * Counters group + * @{ + */ +/** + * @brief opaque structure for counter identification + */ +typedef struct ___itt_counter *__itt_counter; + +/** + * @brief Create a counter with given name/domain for the calling thread + * + * After __itt_counter_create() is called, __itt_counter_inc() / __itt_counter_inc_delta() can be used + * to increment the counter on any thread + */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +__itt_counter ITTAPI __itt_counter_createA(const char *name, const char *domain); +__itt_counter ITTAPI __itt_counter_createW(const wchar_t *name, const wchar_t *domain); +#ifdef UNICODE +# define __itt_counter_create __itt_counter_createW +# define __itt_counter_create_ptr __itt_counter_createW_ptr +#else /* UNICODE */ +# define __itt_counter_create __itt_counter_createA +# define __itt_counter_create_ptr __itt_counter_createA_ptr +#endif /* UNICODE */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +__itt_counter ITTAPI __itt_counter_create(const char *name, const char *domain); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(ITTAPI, __itt_counter, counter_createA, (const char *name, const char *domain), (name, domain)) +ITT_STUB(ITTAPI, __itt_counter, counter_createW, (const wchar_t *name, const wchar_t *domain), (name, domain)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, __itt_counter, counter_create, (const char *name, const char *domain), (name, domain)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_counter_createA ITTNOTIFY_DATA(counter_createA) +#define __itt_counter_createA_ptr ITTNOTIFY_NAME(counter_createA) +#define __itt_counter_createW ITTNOTIFY_DATA(counter_createW) +#define __itt_counter_createW_ptr ITTNOTIFY_NAME(counter_createW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_counter_create ITTNOTIFY_DATA(counter_create) +#define __itt_counter_create_ptr ITTNOTIFY_NAME(counter_create) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_counter_createA(name, domain) +#define __itt_counter_createA_ptr 0 +#define __itt_counter_createW(name, domain) +#define __itt_counter_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_counter_create(name, domain) +#define __itt_counter_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_counter_createA_ptr 0 +#define __itt_counter_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_counter_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Destroy the counter identified by the pointer previously returned by __itt_counter_create() + */ +void ITTAPI __itt_counter_destroy(__itt_counter id); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, counter_destroy, (__itt_counter id), (id)) +#define __itt_counter_destroy ITTNOTIFY_VOID(counter_destroy) +#define __itt_counter_destroy_ptr ITTNOTIFY_NAME(counter_destroy) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_counter_destroy(id) +#define __itt_counter_destroy_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_counter_destroy_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Increment the counter value + */ +void ITTAPI __itt_counter_inc(__itt_counter id); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, counter_inc, (__itt_counter id), (id)) +#define __itt_counter_inc ITTNOTIFY_VOID(counter_inc) +#define __itt_counter_inc_ptr ITTNOTIFY_NAME(counter_inc) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_counter_inc(id) +#define __itt_counter_inc_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_counter_inc_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Increment the counter value with x + */ +void ITTAPI __itt_counter_inc_delta(__itt_counter id, unsigned long long value); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, counter_inc_delta, (__itt_counter id, unsigned long long value), (id, value)) +#define __itt_counter_inc_delta ITTNOTIFY_VOID(counter_inc_delta) +#define __itt_counter_inc_delta_ptr ITTNOTIFY_NAME(counter_inc_delta) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_counter_inc_delta(id, value) +#define __itt_counter_inc_delta_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_counter_inc_delta_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} counters group */ + +/** + * @defgroup stitch Stack Stitching + * @ingroup internal + * Stack Stitching group + * @{ + */ +/** + * @brief opaque structure for counter identification + */ +typedef struct ___itt_caller *__itt_caller; + +/** + * @brief Create the stitch point e.g. a point in call stack where other stacks should be stitched to. + * The function returns a unique identifier which is used to match the cut points with corresponding stitch points. + */ +__itt_caller ITTAPI __itt_stack_caller_create(void); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUB(ITTAPI, __itt_caller, stack_caller_create, (void), ()) +#define __itt_stack_caller_create ITTNOTIFY_DATA(stack_caller_create) +#define __itt_stack_caller_create_ptr ITTNOTIFY_NAME(stack_caller_create) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_stack_caller_create() (__itt_caller)0 +#define __itt_stack_caller_create_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_stack_caller_create_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Destroy the inforamtion about stitch point identified by the pointer previously returned by __itt_stack_caller_create() + */ +void ITTAPI __itt_stack_caller_destroy(__itt_caller id); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, stack_caller_destroy, (__itt_caller id), (id)) +#define __itt_stack_caller_destroy ITTNOTIFY_VOID(stack_caller_destroy) +#define __itt_stack_caller_destroy_ptr ITTNOTIFY_NAME(stack_caller_destroy) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_stack_caller_destroy(id) +#define __itt_stack_caller_destroy_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_stack_caller_destroy_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Sets the cut point. Stack from each event which occurs after this call will be cut + * at the same stack level the function was called and stitched to the corresponding stitch point. + */ +void ITTAPI __itt_stack_callee_enter(__itt_caller id); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, stack_callee_enter, (__itt_caller id), (id)) +#define __itt_stack_callee_enter ITTNOTIFY_VOID(stack_callee_enter) +#define __itt_stack_callee_enter_ptr ITTNOTIFY_NAME(stack_callee_enter) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_stack_callee_enter(id) +#define __itt_stack_callee_enter_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_stack_callee_enter_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief This function eliminates the cut point which was set by latest __itt_stack_callee_enter(). + */ +void ITTAPI __itt_stack_callee_leave(__itt_caller id); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, stack_callee_leave, (__itt_caller id), (id)) +#define __itt_stack_callee_leave ITTNOTIFY_VOID(stack_callee_leave) +#define __itt_stack_callee_leave_ptr ITTNOTIFY_NAME(stack_callee_leave) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_stack_callee_leave(id) +#define __itt_stack_callee_leave_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_stack_callee_leave_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** @} stitch group */ + +/* ***************************************************************************************************************************** */ + +/** @cond exclude_from_documentation */ +typedef enum __itt_error_code { + __itt_error_success = 0, /*!< no error */ + __itt_error_no_module = 1, /*!< module can't be loaded */ + /* %1$s -- library name; win: %2$d -- system error code; unx: %2$s -- system error message. */ + __itt_error_no_symbol = 2, /*!< symbol not found */ + /* %1$s -- library name, %2$s -- symbol name. */ + __itt_error_unknown_group = 3, /*!< unknown group specified */ + /* %1$s -- env var name, %2$s -- group name. */ + __itt_error_cant_read_env = 4, /*!< GetEnvironmentVariable() failed */ + /* %1$s -- env var name, %2$d -- system error. */ + __itt_error_env_too_long = 5, /*!< variable value too long */ + /* %1$s -- env var name, %2$d -- actual length of the var, %3$d -- max allowed length. */ + __itt_error_system = 6 /*!< pthread_mutexattr_init or pthread_mutex_init failed */ + /* %1$s -- function name, %2$d -- errno. */ +} __itt_error_code; + +typedef void (__itt_error_notification_t)(__itt_error_code code, va_list); +__itt_error_notification_t* __itt_set_error_handler(__itt_error_notification_t*); + +const char* ITTAPI __itt_api_version(void); +/** @endcond */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#define __itt_error_handler ITT_JOIN(INTEL_ITTNOTIFY_PREFIX, error_handler) +void __itt_error_handler(__itt_error_code code, va_list args); +extern const int ITTNOTIFY_NAME(err); +#define __itt_err ITTNOTIFY_NAME(err) +ITT_STUB(ITTAPI, const char*, api_version, (void), ()) +#define __itt_api_version ITTNOTIFY_DATA(api_version) +#define __itt_api_version_ptr ITTNOTIFY_NAME(api_version) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_api_version() (const char*)0 +#define __itt_api_version_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_api_version_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** @cond exclude_from_documentation */ +#ifdef __cplusplus +} +#endif /* __cplusplus */ +/** @endcond */ + +#endif /* _INTERNAL_ITTNOTIFY_H_ */ diff --git a/src/tbb/src/tbb/tools_api/ittnotify.h b/src/tbb/src/tbb/tools_api/ittnotify.h new file mode 100644 index 0000000..a3935bf --- /dev/null +++ b/src/tbb/src/tbb/tools_api/ittnotify.h @@ -0,0 +1,3367 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _ITTNOTIFY_H_ +#define _ITTNOTIFY_H_ + +/** +@file +@brief Public User API functions and types +@mainpage + +The ITT API is used to annotate a user's program with additional information +that can be used by correctness and performance tools. The user inserts +calls in their program. Those calls generate information that is collected +at runtime, and used by tools such as Amplifier and Inspector. + +@section API Concepts +The following general concepts are used throughout the API. + +@subsection Unicode Support +Many API functions take character string arguments. On Windows, there +are two versions of each such function. The function name is suffixed +by W if Unicode support is enabled, and by A otherwise. Any API function +that takes a character string argument adheres to this convention. + +@subsection Conditional Compilation +Many users prefer having an option to modify ITT API code when linking it +inside their runtimes. ITT API header file provides a mechanism to replace +ITT API function names inside your code with empty strings. To do this, +define the macros INTEL_NO_ITTNOTIFY_API during compilation and remove the +static library from the linker script. + +@subsection Domains +[see domains] +Domains provide a way to separate notification for different modules or +libraries in a program. Domains are specified by dotted character strings, +e.g. TBB.Internal.Control. + +A mechanism (to be specified) is provided to enable and disable +domains. By default, all domains are enabled. +@subsection Named Entities and Instances +Named entities (frames, regions, tasks, and markers) communicate +information about the program to the analysis tools. A named entity often +refers to a section of program code, or to some set of logical concepts +that the programmer wants to group together. + +Named entities relate to the programmer's static view of the program. When +the program actually executes, many instances of a given named entity +may be created. + +The API annotations denote instances of named entities. The actual +named entities are displayed using the analysis tools. In other words, +the named entities come into existence when instances are created. + +Instances of named entities may have instance identifiers (IDs). Some +API calls use instance identifiers to create relationships between +different instances of named entities. Other API calls associate data +with instances of named entities. + +Some named entities must always have instance IDs. In particular, regions +and frames always have IDs. Task and markers need IDs only if the ID is +needed in another API call (such as adding a relation or metadata). + +The lifetime of instance IDs is distinct from the lifetime of +instances. This allows various relationships to be specified separate +from the actual execution of instances. This flexibility comes at the +expense of extra API calls. + +The same ID may not be reused for different instances, unless a previous +[ref] __itt_id_destroy call for that ID has been issued. +*/ + +/** @cond exclude_from_documentation */ +#ifndef ITT_OS_WIN +# define ITT_OS_WIN 1 +#endif /* ITT_OS_WIN */ + +#ifndef ITT_OS_LINUX +# define ITT_OS_LINUX 2 +#endif /* ITT_OS_LINUX */ + +#ifndef ITT_OS_MAC +# define ITT_OS_MAC 3 +#endif /* ITT_OS_MAC */ + +#ifndef ITT_OS +# if defined WIN32 || defined _WIN32 +# define ITT_OS ITT_OS_WIN +# elif defined( __APPLE__ ) && defined( __MACH__ ) +# define ITT_OS ITT_OS_MAC +# else +# define ITT_OS ITT_OS_LINUX +# endif +#endif /* ITT_OS */ + +#ifndef ITT_PLATFORM_WIN +# define ITT_PLATFORM_WIN 1 +#endif /* ITT_PLATFORM_WIN */ + +#ifndef ITT_PLATFORM_POSIX +# define ITT_PLATFORM_POSIX 2 +#endif /* ITT_PLATFORM_POSIX */ + +#ifndef ITT_PLATFORM +# if ITT_OS==ITT_OS_WIN +# define ITT_PLATFORM ITT_PLATFORM_WIN +# else +# define ITT_PLATFORM ITT_PLATFORM_POSIX +# endif /* _WIN32 */ +#endif /* ITT_PLATFORM */ + +#if defined(_UNICODE) && !defined(UNICODE) +#define UNICODE +#endif + +#include <stddef.h> +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#include <tchar.h> +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#include <stdint.h> +#if defined(UNICODE) || defined(_UNICODE) +#include <wchar.h> +#endif /* UNICODE || _UNICODE */ +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +#ifndef CDECL +# if ITT_PLATFORM==ITT_PLATFORM_WIN +# define CDECL __cdecl +# else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +# if defined _M_X64 || defined _M_AMD64 || defined __x86_64__ +# define CDECL /* not actual on x86_64 platform */ +# else /* _M_X64 || _M_AMD64 || __x86_64__ */ +# define CDECL __attribute__ ((cdecl)) +# endif /* _M_X64 || _M_AMD64 || __x86_64__ */ +# endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* CDECL */ + +#ifndef STDCALL +# if ITT_PLATFORM==ITT_PLATFORM_WIN +# define STDCALL __stdcall +# else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +# if defined _M_X64 || defined _M_AMD64 || defined __x86_64__ +# define STDCALL /* not supported on x86_64 platform */ +# else /* _M_X64 || _M_AMD64 || __x86_64__ */ +# define STDCALL __attribute__ ((stdcall)) +# endif /* _M_X64 || _M_AMD64 || __x86_64__ */ +# endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* STDCALL */ + +#define ITTAPI CDECL +#define LIBITTAPI CDECL + +/* TODO: Temporary for compatibility! */ +#define ITTAPI_CALL CDECL +#define LIBITTAPI_CALL CDECL + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +/* use __forceinline (VC++ specific) */ +#define INLINE __forceinline +#define INLINE_ATTRIBUTE /* nothing */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +/* + * Generally, functions are not inlined unless optimization is specified. + * For functions declared inline, this attribute inlines the function even + * if no optimization level was specified. + */ +#ifdef __STRICT_ANSI__ +#define INLINE static +#else /* __STRICT_ANSI__ */ +#define INLINE static inline +#endif /* __STRICT_ANSI__ */ +#define INLINE_ATTRIBUTE __attribute__ ((always_inline)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +/** @endcond */ + +#ifdef INTEL_ITTNOTIFY_ENABLE_LEGACY +# if ITT_PLATFORM==ITT_PLATFORM_WIN +# pragma message("WARNING!!! Deprecated API is used. Please undefine INTEL_ITTNOTIFY_ENABLE_LEGACY macro") +# else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +// #warning usage leads to ICC's compilation error +// # warning "Deprecated API is used. Please undefine INTEL_ITTNOTIFY_ENABLE_LEGACY macro" +# endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +# include "legacy/ittnotify.h" +#endif /* INTEL_ITTNOTIFY_ENABLE_LEGACY */ + +/** @cond exclude_from_documentation */ +/* Helper macro for joining tokens */ +#define ITT_JOIN_AUX(p,n) p##n +#define ITT_JOIN(p,n) ITT_JOIN_AUX(p,n) + +#ifdef ITT_MAJOR +#undef ITT_MAJOR +#endif +#ifdef ITT_MINOR +#undef ITT_MINOR +#endif +#define ITT_MAJOR 3 +#define ITT_MINOR 0 + +/* Standard versioning of a token with major and minor version numbers */ +#define ITT_VERSIONIZE(x) \ + ITT_JOIN(x, \ + ITT_JOIN(_, \ + ITT_JOIN(ITT_MAJOR, \ + ITT_JOIN(_, ITT_MINOR)))) + +#ifndef INTEL_ITTNOTIFY_PREFIX +# define INTEL_ITTNOTIFY_PREFIX __itt_ +#endif /* INTEL_ITTNOTIFY_PREFIX */ +#ifndef INTEL_ITTNOTIFY_POSTFIX +# define INTEL_ITTNOTIFY_POSTFIX _ptr_ +#endif /* INTEL_ITTNOTIFY_POSTFIX */ + +#define ITTNOTIFY_NAME_AUX(n) ITT_JOIN(INTEL_ITTNOTIFY_PREFIX,n) +#define ITTNOTIFY_NAME(n) ITT_VERSIONIZE(ITTNOTIFY_NAME_AUX(ITT_JOIN(n,INTEL_ITTNOTIFY_POSTFIX))) + +#define ITTNOTIFY_VOID(n) (!ITTNOTIFY_NAME(n)) ? (void)0 : ITTNOTIFY_NAME(n) +#define ITTNOTIFY_DATA(n) (!ITTNOTIFY_NAME(n)) ? 0 : ITTNOTIFY_NAME(n) + +#define ITTNOTIFY_VOID_D0(n,d) (!(d)->flags) ? (void)0 : (!ITTNOTIFY_NAME(n)) ? (void)0 : ITTNOTIFY_NAME(n)(d) +#define ITTNOTIFY_VOID_D1(n,d,x) (!(d)->flags) ? (void)0 : (!ITTNOTIFY_NAME(n)) ? (void)0 : ITTNOTIFY_NAME(n)(d,x) +#define ITTNOTIFY_VOID_D2(n,d,x,y) (!(d)->flags) ? (void)0 : (!ITTNOTIFY_NAME(n)) ? (void)0 : ITTNOTIFY_NAME(n)(d,x,y) +#define ITTNOTIFY_VOID_D3(n,d,x,y,z) (!(d)->flags) ? (void)0 : (!ITTNOTIFY_NAME(n)) ? (void)0 : ITTNOTIFY_NAME(n)(d,x,y,z) +#define ITTNOTIFY_VOID_D4(n,d,x,y,z,a) (!(d)->flags) ? (void)0 : (!ITTNOTIFY_NAME(n)) ? (void)0 : ITTNOTIFY_NAME(n)(d,x,y,z,a) +#define ITTNOTIFY_VOID_D5(n,d,x,y,z,a,b) (!(d)->flags) ? (void)0 : (!ITTNOTIFY_NAME(n)) ? (void)0 : ITTNOTIFY_NAME(n)(d,x,y,z,a,b) +#define ITTNOTIFY_VOID_D6(n,d,x,y,z,a,b,c) (!(d)->flags) ? (void)0 : (!ITTNOTIFY_NAME(n)) ? (void)0 : ITTNOTIFY_NAME(n)(d,x,y,z,a,b,c) +#define ITTNOTIFY_DATA_D0(n,d) (!(d)->flags) ? 0 : (!ITTNOTIFY_NAME(n)) ? 0 : ITTNOTIFY_NAME(n)(d) +#define ITTNOTIFY_DATA_D1(n,d,x) (!(d)->flags) ? 0 : (!ITTNOTIFY_NAME(n)) ? 0 : ITTNOTIFY_NAME(n)(d,x) +#define ITTNOTIFY_DATA_D2(n,d,x,y) (!(d)->flags) ? 0 : (!ITTNOTIFY_NAME(n)) ? 0 : ITTNOTIFY_NAME(n)(d,x,y) +#define ITTNOTIFY_DATA_D3(n,d,x,y,z) (!(d)->flags) ? 0 : (!ITTNOTIFY_NAME(n)) ? 0 : ITTNOTIFY_NAME(n)(d,x,y,z) +#define ITTNOTIFY_DATA_D4(n,d,x,y,z,a) (!(d)->flags) ? 0 : (!ITTNOTIFY_NAME(n)) ? 0 : ITTNOTIFY_NAME(n)(d,x,y,z,a) +#define ITTNOTIFY_DATA_D5(n,d,x,y,z,a,b) (!(d)->flags) ? 0 : (!ITTNOTIFY_NAME(n)) ? 0 : ITTNOTIFY_NAME(n)(d,x,y,z,a,b) +#define ITTNOTIFY_DATA_D6(n,d,x,y,z,a,b,c) (!(d)->flags) ? 0 : (!ITTNOTIFY_NAME(n)) ? 0 : ITTNOTIFY_NAME(n)(d,x,y,z,a,b,c) + +#ifdef ITT_STUB +#undef ITT_STUB +#endif +#ifdef ITT_STUBV +#undef ITT_STUBV +#endif +#define ITT_STUBV(api,type,name,args) \ + typedef type (api* ITT_JOIN(ITTNOTIFY_NAME(name),_t)) args; \ + extern ITT_JOIN(ITTNOTIFY_NAME(name),_t) ITTNOTIFY_NAME(name); +#define ITT_STUB ITT_STUBV +/** @endcond */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @cond exclude_from_gpa_documentation */ +/** + * @defgroup public Public API + * @{ + * @} + */ + +/** + * @defgroup control Collection Control + * @ingroup public + * General behavior: application continues to run, but no profiling information is being collected + * + * Pausing occurs not only for the current thread but for all process as well as spawned processes + * - Intel(R) Parallel Inspector and Intel(R) Inspector XE: + * - Does not analyze or report errors that involve memory access. + * - Other errors are reported as usual. Pausing data collection in + * Intel(R) Parallel Inspector and Intel(R) Inspector XE + * only pauses tracing and analyzing memory access. + * It does not pause tracing or analyzing threading APIs. + * . + * - Intel(R) Parallel Amplifier and Intel(R) VTune(TM) Amplifier XE: + * - Does continue to record when new threads are started. + * . + * - Other effects: + * - Possible reduction of runtime overhead. + * . + * @{ + */ +/** @brief Pause collection */ +void ITTAPI __itt_pause(void); +/** @brief Resume collection */ +void ITTAPI __itt_resume(void); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, pause, (void)) +ITT_STUBV(ITTAPI, void, resume, (void)) +#define __itt_pause ITTNOTIFY_VOID(pause) +#define __itt_pause_ptr ITTNOTIFY_NAME(pause) +#define __itt_resume ITTNOTIFY_VOID(resume) +#define __itt_resume_ptr ITTNOTIFY_NAME(resume) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_pause() +#define __itt_pause_ptr 0 +#define __itt_resume() +#define __itt_resume_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_pause_ptr 0 +#define __itt_resume_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} control group */ +/** @endcond */ + +/** + * @defgroup threads Threads + * @ingroup public + * Give names to threads + * @{ + */ +/** + * @brief Sets thread name of calling thread + * @param[in] name - name of thread + */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +void ITTAPI __itt_thread_set_nameA(const char *name); +void ITTAPI __itt_thread_set_nameW(const wchar_t *name); +#if defined(UNICODE) || defined(_UNICODE) +# define __itt_thread_set_name __itt_thread_set_nameW +# define __itt_thread_set_name_ptr __itt_thread_set_nameW_ptr +#else /* UNICODE */ +# define __itt_thread_set_name __itt_thread_set_nameA +# define __itt_thread_set_name_ptr __itt_thread_set_nameA_ptr +#endif /* UNICODE */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +void ITTAPI __itt_thread_set_name(const char *name); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUBV(ITTAPI, void, thread_set_nameA, (const char *name)) +ITT_STUBV(ITTAPI, void, thread_set_nameW, (const wchar_t *name)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUBV(ITTAPI, void, thread_set_name, (const char *name)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_thread_set_nameA ITTNOTIFY_VOID(thread_set_nameA) +#define __itt_thread_set_nameA_ptr ITTNOTIFY_NAME(thread_set_nameA) +#define __itt_thread_set_nameW ITTNOTIFY_VOID(thread_set_nameW) +#define __itt_thread_set_nameW_ptr ITTNOTIFY_NAME(thread_set_nameW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_thread_set_name ITTNOTIFY_VOID(thread_set_name) +#define __itt_thread_set_name_ptr ITTNOTIFY_NAME(thread_set_name) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_thread_set_nameA(name) +#define __itt_thread_set_nameA_ptr 0 +#define __itt_thread_set_nameW(name) +#define __itt_thread_set_nameW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_thread_set_name(name) +#define __itt_thread_set_name_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_thread_set_nameA_ptr 0 +#define __itt_thread_set_nameW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_thread_set_name_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** @cond exclude_from_gpa_documentation */ + +/** + * @brief Mark current thread as ignored from this point on, for the duration of its existence. + */ +void ITTAPI __itt_thread_ignore(void); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, thread_ignore, (void)) +#define __itt_thread_ignore ITTNOTIFY_VOID(thread_ignore) +#define __itt_thread_ignore_ptr ITTNOTIFY_NAME(thread_ignore) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_thread_ignore() +#define __itt_thread_ignore_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_thread_ignore_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} threads group */ + +/** + * @defgroup sync Synchronization + * @ingroup public + * Indicate user-written synchronization code + * @{ + */ +/** + * @hideinitializer + * @brief possible value of attribute argument for sync object type + */ +#define __itt_attr_barrier 1 + +/** + * @hideinitializer + * @brief possible value of attribute argument for sync object type + */ +#define __itt_attr_mutex 2 + +/** +@brief Name a synchronization object +@param[in] addr Handle for the synchronization object. You should +use a real address to uniquely identify the synchronization object. +@param[in] objtype null-terminated object type string. If NULL is +passed, the name will be "User Synchronization". +@param[in] objname null-terminated object name string. If NULL, +no name will be assigned to the object. +@param[in] attribute one of [#__itt_attr_barrier, #__itt_attr_mutex] + */ + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +void ITTAPI __itt_sync_createA(void *addr, const char *objtype, const char *objname, int attribute); +void ITTAPI __itt_sync_createW(void *addr, const wchar_t *objtype, const wchar_t *objname, int attribute); +#if defined(UNICODE) || defined(_UNICODE) +# define __itt_sync_create __itt_sync_createW +# define __itt_sync_create_ptr __itt_sync_createW_ptr +#else /* UNICODE */ +# define __itt_sync_create __itt_sync_createA +# define __itt_sync_create_ptr __itt_sync_createA_ptr +#endif /* UNICODE */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +void ITTAPI __itt_sync_create (void *addr, const char *objtype, const char *objname, int attribute); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUBV(ITTAPI, void, sync_createA, (void *addr, const char *objtype, const char *objname, int attribute)) +ITT_STUBV(ITTAPI, void, sync_createW, (void *addr, const wchar_t *objtype, const wchar_t *objname, int attribute)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUBV(ITTAPI, void, sync_create, (void *addr, const char* objtype, const char* objname, int attribute)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_sync_createA ITTNOTIFY_VOID(sync_createA) +#define __itt_sync_createA_ptr ITTNOTIFY_NAME(sync_createA) +#define __itt_sync_createW ITTNOTIFY_VOID(sync_createW) +#define __itt_sync_createW_ptr ITTNOTIFY_NAME(sync_createW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_sync_create ITTNOTIFY_VOID(sync_create) +#define __itt_sync_create_ptr ITTNOTIFY_NAME(sync_create) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_sync_createA(addr, objtype, objname, attribute) +#define __itt_sync_createA_ptr 0 +#define __itt_sync_createW(addr, objtype, objname, attribute) +#define __itt_sync_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_sync_create(addr, objtype, objname, attribute) +#define __itt_sync_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_sync_createA_ptr 0 +#define __itt_sync_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_sync_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** +@brief Rename a synchronization object + +You can use the rename call to assign or reassign a name to a given +synchronization object. +@param[in] addr handle for the synchronization object. +@param[in] name null-terminated object name string. +*/ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +void ITTAPI __itt_sync_renameA(void *addr, const char *name); +void ITTAPI __itt_sync_renameW(void *addr, const wchar_t *name); +#if defined(UNICODE) || defined(_UNICODE) +# define __itt_sync_rename __itt_sync_renameW +# define __itt_sync_rename_ptr __itt_sync_renameW_ptr +#else /* UNICODE */ +# define __itt_sync_rename __itt_sync_renameA +# define __itt_sync_rename_ptr __itt_sync_renameA_ptr +#endif /* UNICODE */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +void ITTAPI __itt_sync_rename(void *addr, const char *name); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUBV(ITTAPI, void, sync_renameA, (void *addr, const char *name)) +ITT_STUBV(ITTAPI, void, sync_renameW, (void *addr, const wchar_t *name)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUBV(ITTAPI, void, sync_rename, (void *addr, const char *name)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_sync_renameA ITTNOTIFY_VOID(sync_renameA) +#define __itt_sync_renameA_ptr ITTNOTIFY_NAME(sync_renameA) +#define __itt_sync_renameW ITTNOTIFY_VOID(sync_renameW) +#define __itt_sync_renameW_ptr ITTNOTIFY_NAME(sync_renameW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_sync_rename ITTNOTIFY_VOID(sync_rename) +#define __itt_sync_rename_ptr ITTNOTIFY_NAME(sync_rename) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_sync_renameA(addr, name) +#define __itt_sync_renameA_ptr 0 +#define __itt_sync_renameW(addr, name) +#define __itt_sync_renameW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_sync_rename(addr, name) +#define __itt_sync_rename_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_sync_renameA_ptr 0 +#define __itt_sync_renameW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_sync_rename_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + @brief Destroy a synchronization object. + @param addr Handle for the synchronization object. + */ +void ITTAPI __itt_sync_destroy(void *addr); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, sync_destroy, (void *addr)) +#define __itt_sync_destroy ITTNOTIFY_VOID(sync_destroy) +#define __itt_sync_destroy_ptr ITTNOTIFY_NAME(sync_destroy) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_sync_destroy(addr) +#define __itt_sync_destroy_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_sync_destroy_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/*****************************************************************//** + * @name group of functions is used for performance measurement tools + *********************************************************************/ +/** @{ */ +/** + * @brief Enter spin loop on user-defined sync object + */ +void ITTAPI __itt_sync_prepare(void* addr); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, sync_prepare, (void *addr)) +#define __itt_sync_prepare ITTNOTIFY_VOID(sync_prepare) +#define __itt_sync_prepare_ptr ITTNOTIFY_NAME(sync_prepare) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_sync_prepare(addr) +#define __itt_sync_prepare_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_sync_prepare_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Quit spin loop without acquiring spin object + */ +void ITTAPI __itt_sync_cancel(void *addr); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, sync_cancel, (void *addr)) +#define __itt_sync_cancel ITTNOTIFY_VOID(sync_cancel) +#define __itt_sync_cancel_ptr ITTNOTIFY_NAME(sync_cancel) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_sync_cancel(addr) +#define __itt_sync_cancel_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_sync_cancel_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Successful spin loop completion (sync object acquired) + */ +void ITTAPI __itt_sync_acquired(void *addr); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, sync_acquired, (void *addr)) +#define __itt_sync_acquired ITTNOTIFY_VOID(sync_acquired) +#define __itt_sync_acquired_ptr ITTNOTIFY_NAME(sync_acquired) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_sync_acquired(addr) +#define __itt_sync_acquired_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_sync_acquired_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Start sync object releasing code. Is called before the lock release call. + */ +void ITTAPI __itt_sync_releasing(void* addr); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, sync_releasing, (void *addr)) +#define __itt_sync_releasing ITTNOTIFY_VOID(sync_releasing) +#define __itt_sync_releasing_ptr ITTNOTIFY_NAME(sync_releasing) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_sync_releasing(addr) +#define __itt_sync_releasing_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_sync_releasing_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} */ + +/** @} sync group */ + +/**************************************************************//** + * @name group of functions is used for correctness checking tools + ******************************************************************/ +/** @{ */ +/** + * @ingroup legacy + * @deprecated Legacy API + * @brief Fast synchronization which does no require spinning. + * - This special function is to be used by TBB and OpenMP libraries only when they know + * there is no spin but they need to suppress TC warnings about shared variable modifications. + * - It only has corresponding pointers in static library and does not have corresponding function + * in dynamic library. + * @see void __itt_sync_prepare(void* addr); + */ +void ITTAPI __itt_fsync_prepare(void* addr); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, fsync_prepare, (void *addr)) +#define __itt_fsync_prepare ITTNOTIFY_VOID(fsync_prepare) +#define __itt_fsync_prepare_ptr ITTNOTIFY_NAME(fsync_prepare) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_fsync_prepare(addr) +#define __itt_fsync_prepare_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_fsync_prepare_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @ingroup legacy + * @deprecated Legacy API + * @brief Fast synchronization which does no require spinning. + * - This special function is to be used by TBB and OpenMP libraries only when they know + * there is no spin but they need to suppress TC warnings about shared variable modifications. + * - It only has corresponding pointers in static library and does not have corresponding function + * in dynamic library. + * @see void __itt_sync_cancel(void *addr); + */ +void ITTAPI __itt_fsync_cancel(void *addr); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, fsync_cancel, (void *addr)) +#define __itt_fsync_cancel ITTNOTIFY_VOID(fsync_cancel) +#define __itt_fsync_cancel_ptr ITTNOTIFY_NAME(fsync_cancel) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_fsync_cancel(addr) +#define __itt_fsync_cancel_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_fsync_cancel_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @ingroup legacy + * @deprecated Legacy API + * @brief Fast synchronization which does no require spinning. + * - This special function is to be used by TBB and OpenMP libraries only when they know + * there is no spin but they need to suppress TC warnings about shared variable modifications. + * - It only has corresponding pointers in static library and does not have corresponding function + * in dynamic library. + * @see void __itt_sync_acquired(void *addr); + */ +void ITTAPI __itt_fsync_acquired(void *addr); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, fsync_acquired, (void *addr)) +#define __itt_fsync_acquired ITTNOTIFY_VOID(fsync_acquired) +#define __itt_fsync_acquired_ptr ITTNOTIFY_NAME(fsync_acquired) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_fsync_acquired(addr) +#define __itt_fsync_acquired_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_fsync_acquired_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @ingroup legacy + * @deprecated Legacy API + * @brief Fast synchronization which does no require spinning. + * - This special function is to be used by TBB and OpenMP libraries only when they know + * there is no spin but they need to suppress TC warnings about shared variable modifications. + * - It only has corresponding pointers in static library and does not have corresponding function + * in dynamic library. + * @see void __itt_sync_releasing(void* addr); + */ +void ITTAPI __itt_fsync_releasing(void* addr); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, fsync_releasing, (void *addr)) +#define __itt_fsync_releasing ITTNOTIFY_VOID(fsync_releasing) +#define __itt_fsync_releasing_ptr ITTNOTIFY_NAME(fsync_releasing) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_fsync_releasing(addr) +#define __itt_fsync_releasing_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_fsync_releasing_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} */ + +/** + * @defgroup model Modeling by Intel(R) Parallel Advisor + * @ingroup public + * This is the subset of itt used for modeling by Intel(R) Parallel Advisor. + * This API is called ONLY using annotate.h, by "Annotation" macros + * the user places in their sources during the parallelism modeling steps. + * + * site_begin/end and task_begin/end take the address of handle variables, + * which are writeable by the API. Handles must be 0 initialized prior + * to the first call to begin, or may cause a run-time failure. + * The handles are initialized in a multi-thread safe way by the API if + * the handle is 0. The commonly expected idiom is one static handle to + * identify a site or task. If a site or task of the same name has already + * been started during this collection, the same handle MAY be returned, + * but is not required to be - it is unspecified if data merging is done + * based on name. These routines also take an instance variable. Like + * the lexical instance, these must be 0 initialized. Unlike the lexical + * instance, this is used to track a single dynamic instance. + * + * API used by the Intel(R) Parallel Advisor to describe potential concurrency + * and related activities. User-added source annotations expand to calls + * to these procedures to enable modeling of a hypothetical concurrent + * execution serially. + * @{ + */ +#if !defined(_ADVISOR_ANNOTATE_H_) || defined(ANNOTATE_EXPAND_NULL) + +typedef void* __itt_model_site; /*!< @brief handle for lexical site */ +typedef void* __itt_model_site_instance; /*!< @brief handle for dynamic instance */ +typedef void* __itt_model_task; /*!< @brief handle for lexical site */ +typedef void* __itt_model_task_instance; /*!< @brief handle for dynamic instance */ + +/** + * @enum __itt_model_disable + * @brief Enumerator for the disable methods + */ +typedef enum { + __itt_model_disable_observation, + __itt_model_disable_collection +} __itt_model_disable; + +#endif /* !_ADVISOR_ANNOTATE_H_ || ANNOTATE_EXPAND_NULL */ + +/** + * @brief ANNOTATE_SITE_BEGIN/ANNOTATE_SITE_END support. + * + * site_begin/end model a potential concurrency site. + * site instances may be recursively nested with themselves. + * site_end exits the most recently started but unended site for the current + * thread. The handle passed to end may be used to validate structure. + * Instances of a site encountered on different threads concurrently + * are considered completely distinct. If the site name for two different + * lexical sites match, it is unspecified whether they are treated as the + * same or different for data presentation. + */ +void ITTAPI __itt_model_site_begin(__itt_model_site *site, __itt_model_site_instance *instance, const char *name); +#if ITT_PLATFORM==ITT_PLATFORM_WIN +void ITTAPI __itt_model_site_beginW(const wchar_t *name); +#endif +void ITTAPI __itt_model_site_beginAL(const char *name, size_t siteNameLen); +void ITTAPI __itt_model_site_end (__itt_model_site *site, __itt_model_site_instance *instance); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, model_site_begin, (__itt_model_site *site, __itt_model_site_instance *instance, const char *name)) +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUBV(ITTAPI, void, model_site_beginW, (const wchar_t *name)) +#endif +ITT_STUBV(ITTAPI, void, model_site_beginAL, (const char *name, size_t siteNameLen)) +ITT_STUBV(ITTAPI, void, model_site_end, (__itt_model_site *site, __itt_model_site_instance *instance)) +#define __itt_model_site_begin ITTNOTIFY_VOID(model_site_begin) +#define __itt_model_site_begin_ptr ITTNOTIFY_NAME(model_site_begin) +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_model_site_beginW ITTNOTIFY_VOID(model_site_beginW) +#define __itt_model_site_beginW_ptr ITTNOTIFY_NAME(model_site_beginW) +#endif +#define __itt_model_site_beginAL ITTNOTIFY_VOID(model_site_beginAL) +#define __itt_model_site_beginAL_ptr ITTNOTIFY_NAME(model_site_beginAL) +#define __itt_model_site_end ITTNOTIFY_VOID(model_site_end) +#define __itt_model_site_end_ptr ITTNOTIFY_NAME(model_site_end) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_model_site_begin(site, instance, name) +#define __itt_model_site_begin_ptr 0 +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_model_site_beginW(name) +#define __itt_model_site_beginW_ptr 0 +#endif +#define __itt_model_site_beginAL(name, siteNameLen) +#define __itt_model_site_beginAL_ptr 0 +#define __itt_model_site_end(site, instance) +#define __itt_model_site_end_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_model_site_begin_ptr 0 +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_model_site_beginW_ptr 0 +#endif +#define __itt_model_site_beginAL_ptr 0 +#define __itt_model_site_end_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief ANNOTATE_TASK_BEGIN/ANNOTATE_TASK_END support + * + * task_begin/end model a potential task, which is contained within the most + * closely enclosing dynamic site. task_end exits the most recently started + * but unended task. The handle passed to end may be used to validate + * structure. It is unspecified if bad dynamic nesting is detected. If it + * is, it should be encoded in the resulting data collection. The collector + * should not fail due to construct nesting issues, nor attempt to directly + * indicate the problem. + */ +void ITTAPI __itt_model_task_begin(__itt_model_task *task, __itt_model_task_instance *instance, const char *name); +#if ITT_PLATFORM==ITT_PLATFORM_WIN +void ITTAPI __itt_model_task_beginW(const wchar_t *name); +#endif +void ITTAPI __itt_model_task_beginAL(const char *name, size_t taskNameLen); +void ITTAPI __itt_model_task_end (__itt_model_task *task, __itt_model_task_instance *instance); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, model_task_begin, (__itt_model_task *task, __itt_model_task_instance *instance, const char *name)) +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUBV(ITTAPI, void, model_task_beginW, (const wchar_t *name)) +#endif +ITT_STUBV(ITTAPI, void, model_task_beginAL, (const char *name, size_t taskNameLen)) +ITT_STUBV(ITTAPI, void, model_task_end, (__itt_model_task *task, __itt_model_task_instance *instance)) +#define __itt_model_task_begin ITTNOTIFY_VOID(model_task_begin) +#define __itt_model_task_begin_ptr ITTNOTIFY_NAME(model_task_begin) +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_model_task_beginW ITTNOTIFY_VOID(model_task_beginW) +#define __itt_model_task_beginW_ptr ITTNOTIFY_NAME(model_task_beginW) +#endif +#define __itt_model_task_beginAL ITTNOTIFY_VOID(model_task_beginAL) +#define __itt_model_task_beginAL_ptr ITTNOTIFY_NAME(model_task_beginAL) +#define __itt_model_task_end ITTNOTIFY_VOID(model_task_end) +#define __itt_model_task_end_ptr ITTNOTIFY_NAME(model_task_end) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_model_task_begin(task, instance, name) +#define __itt_model_task_begin_ptr 0 +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_model_task_beginW(name) +#define __itt_model_task_beginW_ptr 0 +#endif +#define __itt_model_task_beginAL(name, siteNameLen) +#define __itt_model_task_beginAL_ptr 0 +#define __itt_model_task_end(task, instance) +#define __itt_model_task_end_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_model_task_begin_ptr 0 +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_model_task_beginW_ptr 0 +#endif +#define __itt_model_task_beginAL_ptr 0 +#define __itt_model_task_end_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief ANNOTATE_LOCK_ACQUIRE/ANNOTATE_LOCK_RELEASE support + * + * lock_acquire/release model a potential lock for both lockset and + * performance modeling. Each unique address is modeled as a separate + * lock, with invalid addresses being valid lock IDs. Specifically: + * no storage is accessed by the API at the specified address - it is only + * used for lock identification. Lock acquires may be self-nested and are + * unlocked by a corresponding number of releases. + * (These closely correspond to __itt_sync_acquired/__itt_sync_releasing, + * but may not have identical semantics.) + */ +void ITTAPI __itt_model_lock_acquire(void *lock); +void ITTAPI __itt_model_lock_release(void *lock); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, model_lock_acquire, (void *lock)) +ITT_STUBV(ITTAPI, void, model_lock_release, (void *lock)) +#define __itt_model_lock_acquire ITTNOTIFY_VOID(model_lock_acquire) +#define __itt_model_lock_acquire_ptr ITTNOTIFY_NAME(model_lock_acquire) +#define __itt_model_lock_release ITTNOTIFY_VOID(model_lock_release) +#define __itt_model_lock_release_ptr ITTNOTIFY_NAME(model_lock_release) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_model_lock_acquire(lock) +#define __itt_model_lock_acquire_ptr 0 +#define __itt_model_lock_release(lock) +#define __itt_model_lock_release_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_model_lock_acquire_ptr 0 +#define __itt_model_lock_release_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief ANNOTATE_RECORD_ALLOCATION/ANNOTATE_RECORD_DEALLOCATION support + * + * record_allocation/deallocation describe user-defined memory allocator + * behavior, which may be required for correctness modeling to understand + * when storage is not expected to be actually reused across threads. + */ +void ITTAPI __itt_model_record_allocation (void *addr, size_t size); +void ITTAPI __itt_model_record_deallocation(void *addr); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, model_record_allocation, (void *addr, size_t size)) +ITT_STUBV(ITTAPI, void, model_record_deallocation, (void *addr)) +#define __itt_model_record_allocation ITTNOTIFY_VOID(model_record_allocation) +#define __itt_model_record_allocation_ptr ITTNOTIFY_NAME(model_record_allocation) +#define __itt_model_record_deallocation ITTNOTIFY_VOID(model_record_deallocation) +#define __itt_model_record_deallocation_ptr ITTNOTIFY_NAME(model_record_deallocation) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_model_record_allocation(addr, size) +#define __itt_model_record_allocation_ptr 0 +#define __itt_model_record_deallocation(addr) +#define __itt_model_record_deallocation_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_model_record_allocation_ptr 0 +#define __itt_model_record_deallocation_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief ANNOTATE_INDUCTION_USES support + * + * Note particular storage is inductive through the end of the current site + */ +void ITTAPI __itt_model_induction_uses(void* addr, size_t size); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, model_induction_uses, (void *addr, size_t size)) +#define __itt_model_induction_uses ITTNOTIFY_VOID(model_induction_uses) +#define __itt_model_induction_uses_ptr ITTNOTIFY_NAME(model_induction_uses) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_model_induction_uses(addr, size) +#define __itt_model_induction_uses_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_model_induction_uses_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief ANNOTATE_REDUCTION_USES support + * + * Note particular storage is used for reduction through the end + * of the current site + */ +void ITTAPI __itt_model_reduction_uses(void* addr, size_t size); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, model_reduction_uses, (void *addr, size_t size)) +#define __itt_model_reduction_uses ITTNOTIFY_VOID(model_reduction_uses) +#define __itt_model_reduction_uses_ptr ITTNOTIFY_NAME(model_reduction_uses) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_model_reduction_uses(addr, size) +#define __itt_model_reduction_uses_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_model_reduction_uses_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief ANNOTATE_OBSERVE_USES support + * + * Have correctness modeling record observations about uses of storage + * through the end of the current site + */ +void ITTAPI __itt_model_observe_uses(void* addr, size_t size); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, model_observe_uses, (void *addr, size_t size)) +#define __itt_model_observe_uses ITTNOTIFY_VOID(model_observe_uses) +#define __itt_model_observe_uses_ptr ITTNOTIFY_NAME(model_observe_uses) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_model_observe_uses(addr, size) +#define __itt_model_observe_uses_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_model_observe_uses_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief ANNOTATE_CLEAR_USES support + * + * Clear the special handling of a piece of storage related to induction, + * reduction or observe_uses + */ +void ITTAPI __itt_model_clear_uses(void* addr); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, model_clear_uses, (void *addr)) +#define __itt_model_clear_uses ITTNOTIFY_VOID(model_clear_uses) +#define __itt_model_clear_uses_ptr ITTNOTIFY_NAME(model_clear_uses) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_model_clear_uses(addr) +#define __itt_model_clear_uses_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_model_clear_uses_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief ANNOTATE_DISABLE_*_PUSH/ANNOTATE_DISABLE_*_POP support + * + * disable_push/disable_pop push and pop disabling based on a parameter. + * Disabling observations stops processing of memory references during + * correctness modeling, and all annotations that occur in the disabled + * region. This allows description of code that is expected to be handled + * specially during conversion to parallelism or that is not recognized + * by tools (e.g. some kinds of synchronization operations.) + * This mechanism causes all annotations in the disabled region, other + * than disable_push and disable_pop, to be ignored. (For example, this + * might validly be used to disable an entire parallel site and the contained + * tasks and locking in it for data collection purposes.) + * The disable for collection is a more expensive operation, but reduces + * collector overhead significantly. This applies to BOTH correctness data + * collection and performance data collection. For example, a site + * containing a task might only enable data collection for the first 10 + * iterations. Both performance and correctness data should reflect this, + * and the program should run as close to full speed as possible when + * collection is disabled. + */ +void ITTAPI __itt_model_disable_push(__itt_model_disable x); +void ITTAPI __itt_model_disable_pop(void); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, model_disable_push, (__itt_model_disable x)) +ITT_STUBV(ITTAPI, void, model_disable_pop, (void)) +#define __itt_model_disable_push ITTNOTIFY_VOID(model_disable_push) +#define __itt_model_disable_push_ptr ITTNOTIFY_NAME(model_disable_push) +#define __itt_model_disable_pop ITTNOTIFY_VOID(model_disable_pop) +#define __itt_model_disable_pop_ptr ITTNOTIFY_NAME(model_disable_pop) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_model_disable_push(x) +#define __itt_model_disable_push_ptr 0 +#define __itt_model_disable_pop() +#define __itt_model_disable_pop_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_model_disable_push_ptr 0 +#define __itt_model_disable_pop_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} model group */ + +/** + * @defgroup heap Heap + * @ingroup public + * Heap group + * @{ + */ + +typedef void* __itt_heap_function; + +/** + * @brief Create an identification for heap function + * @return non-zero identifier or NULL + */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +__itt_heap_function ITTAPI __itt_heap_function_createA(const char* name, const char* domain); +__itt_heap_function ITTAPI __itt_heap_function_createW(const wchar_t* name, const wchar_t* domain); +#if defined(UNICODE) || defined(_UNICODE) +# define __itt_heap_function_create __itt_heap_function_createW +# define __itt_heap_function_create_ptr __itt_heap_function_createW_ptr +#else +# define __itt_heap_function_create __itt_heap_function_createA +# define __itt_heap_function_create_ptr __itt_heap_function_createA_ptr +#endif /* UNICODE */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +__itt_heap_function ITTAPI __itt_heap_function_create(const char* name, const char* domain); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(ITTAPI, __itt_heap_function, heap_function_createA, (const char* name, const char* domain)) +ITT_STUB(ITTAPI, __itt_heap_function, heap_function_createW, (const wchar_t* name, const wchar_t* domain)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, __itt_heap_function, heap_function_create, (const char* name, const char* domain)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_heap_function_createA ITTNOTIFY_DATA(heap_function_createA) +#define __itt_heap_function_createA_ptr ITTNOTIFY_NAME(heap_function_createA) +#define __itt_heap_function_createW ITTNOTIFY_DATA(heap_function_createW) +#define __itt_heap_function_createW_ptr ITTNOTIFY_NAME(heap_function_createW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_heap_function_create ITTNOTIFY_DATA(heap_function_create) +#define __itt_heap_function_create_ptr ITTNOTIFY_NAME(heap_function_create) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_heap_function_createA(name, domain) (__itt_heap_function)0 +#define __itt_heap_function_createA_ptr 0 +#define __itt_heap_function_createW(name, domain) (__itt_heap_function)0 +#define __itt_heap_function_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_heap_function_create(name, domain) (__itt_heap_function)0 +#define __itt_heap_function_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_heap_function_createA_ptr 0 +#define __itt_heap_function_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_heap_function_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Record an allocation begin occurrence. + */ +void ITTAPI __itt_heap_allocate_begin(__itt_heap_function h, size_t size, int initialized); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, heap_allocate_begin, (__itt_heap_function h, size_t size, int initialized)) +#define __itt_heap_allocate_begin ITTNOTIFY_VOID(heap_allocate_begin) +#define __itt_heap_allocate_begin_ptr ITTNOTIFY_NAME(heap_allocate_begin) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_heap_allocate_begin(h, size, initialized) +#define __itt_heap_allocate_begin_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_heap_allocate_begin_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Record an allocation end occurrence. + */ +void ITTAPI __itt_heap_allocate_end(__itt_heap_function h, void** addr, size_t size, int initialized); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, heap_allocate_end, (__itt_heap_function h, void** addr, size_t size, int initialized)) +#define __itt_heap_allocate_end ITTNOTIFY_VOID(heap_allocate_end) +#define __itt_heap_allocate_end_ptr ITTNOTIFY_NAME(heap_allocate_end) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_heap_allocate_end(h, addr, size, initialized) +#define __itt_heap_allocate_end_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_heap_allocate_end_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Record an free begin occurrence. + */ +void ITTAPI __itt_heap_free_begin(__itt_heap_function h, void* addr); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, heap_free_begin, (__itt_heap_function h, void* addr)) +#define __itt_heap_free_begin ITTNOTIFY_VOID(heap_free_begin) +#define __itt_heap_free_begin_ptr ITTNOTIFY_NAME(heap_free_begin) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_heap_free_begin(h, addr) +#define __itt_heap_free_begin_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_heap_free_begin_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Record an free end occurrence. + */ +void ITTAPI __itt_heap_free_end(__itt_heap_function h, void* addr); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, heap_free_end, (__itt_heap_function h, void* addr)) +#define __itt_heap_free_end ITTNOTIFY_VOID(heap_free_end) +#define __itt_heap_free_end_ptr ITTNOTIFY_NAME(heap_free_end) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_heap_free_end(h, addr) +#define __itt_heap_free_end_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_heap_free_end_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Record an reallocation begin occurrence. + */ +void ITTAPI __itt_heap_reallocate_begin(__itt_heap_function h, void* addr, size_t new_size, int initialized); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, heap_reallocate_begin, (__itt_heap_function h, void* addr, size_t new_size, int initialized)) +#define __itt_heap_reallocate_begin ITTNOTIFY_VOID(heap_reallocate_begin) +#define __itt_heap_reallocate_begin_ptr ITTNOTIFY_NAME(heap_reallocate_begin) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_heap_reallocate_begin(h, addr, new_size, initialized) +#define __itt_heap_reallocate_begin_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_heap_reallocate_begin_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Record an reallocation end occurrence. + */ +void ITTAPI __itt_heap_reallocate_end(__itt_heap_function h, void* addr, void** new_addr, size_t new_size, int initialized); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, heap_reallocate_end, (__itt_heap_function h, void* addr, void** new_addr, size_t new_size, int initialized)) +#define __itt_heap_reallocate_end ITTNOTIFY_VOID(heap_reallocate_end) +#define __itt_heap_reallocate_end_ptr ITTNOTIFY_NAME(heap_reallocate_end) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_heap_reallocate_end(h, addr, new_addr, new_size, initialized) +#define __itt_heap_reallocate_end_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_heap_reallocate_end_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** @brief internal access begin */ +void ITTAPI __itt_heap_internal_access_begin(void); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, heap_internal_access_begin, (void)) +#define __itt_heap_internal_access_begin ITTNOTIFY_VOID(heap_internal_access_begin) +#define __itt_heap_internal_access_begin_ptr ITTNOTIFY_NAME(heap_internal_access_begin) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_heap_internal_access_begin() +#define __itt_heap_internal_access_begin_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_heap_internal_access_begin_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** @brief internal access end */ +void ITTAPI __itt_heap_internal_access_end(void); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, heap_internal_access_end, (void)) +#define __itt_heap_internal_access_end ITTNOTIFY_VOID(heap_internal_access_end) +#define __itt_heap_internal_access_end_ptr ITTNOTIFY_NAME(heap_internal_access_end) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_heap_internal_access_end() +#define __itt_heap_internal_access_end_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_heap_internal_access_end_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} heap group */ +/** @endcond */ + +/* ========================================================================== */ + +/** + * @defgroup domains Domains + * @ingroup public + * Domains group + * @{ + */ + +/** @cond exclude_from_documentation */ +#pragma pack(push, 8) + +typedef struct ___itt_domain +{ + volatile int flags; /*!< Zero if disabled, non-zero if enabled. The meaning of different non-zero values is reserved to the runtime */ + const char* nameA; /*!< Copy of original name in ASCII. */ +#if defined(UNICODE) || defined(_UNICODE) + const wchar_t* nameW; /*!< Copy of original name in UNICODE. */ +#else /* UNICODE || _UNICODE */ + void* nameW; +#endif /* UNICODE || _UNICODE */ + int extra1; /*!< Reserved to the runtime */ + void* extra2; /*!< Reserved to the runtime */ + struct ___itt_domain* next; +} __itt_domain; + +#pragma pack(pop) +/** @endcond */ + +/** + * @ingroup domains + * @brief Create a domain. + * Create domain using some domain name: the URI naming style is recommended. + * Because the set of domains is expected to be static over the application's + * execution time, there is no mechanism to destroy a domain. + * Any domain can be accessed by any thread in the process, regardless of + * which thread created the domain. This call is thread-safe. + * @param[in] name name of domain + */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +__itt_domain* ITTAPI __itt_domain_createA(const char *name); +__itt_domain* ITTAPI __itt_domain_createW(const wchar_t *name); +#if defined(UNICODE) || defined(_UNICODE) +# define __itt_domain_create __itt_domain_createW +# define __itt_domain_create_ptr __itt_domain_createW_ptr +#else /* UNICODE */ +# define __itt_domain_create __itt_domain_createA +# define __itt_domain_create_ptr __itt_domain_createA_ptr +#endif /* UNICODE */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +__itt_domain* ITTAPI __itt_domain_create(const char *name); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(ITTAPI, __itt_domain*, domain_createA, (const char *name)) +ITT_STUB(ITTAPI, __itt_domain*, domain_createW, (const wchar_t *name)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, __itt_domain*, domain_create, (const char *name)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_domain_createA ITTNOTIFY_DATA(domain_createA) +#define __itt_domain_createA_ptr ITTNOTIFY_NAME(domain_createA) +#define __itt_domain_createW ITTNOTIFY_DATA(domain_createW) +#define __itt_domain_createW_ptr ITTNOTIFY_NAME(domain_createW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_domain_create ITTNOTIFY_DATA(domain_create) +#define __itt_domain_create_ptr ITTNOTIFY_NAME(domain_create) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_domain_createA(name) (__itt_domain*)0 +#define __itt_domain_createA_ptr 0 +#define __itt_domain_createW(name) (__itt_domain*)0 +#define __itt_domain_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_domain_create(name) (__itt_domain*)0 +#define __itt_domain_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_domain_createA_ptr 0 +#define __itt_domain_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_domain_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} domains group */ + +/** + * @defgroup ids IDs + * @ingroup public + * IDs group + * @{ + */ + +/** @cond exclude_from_documentation */ +#pragma pack(push, 8) + +typedef struct ___itt_id +{ + unsigned long long d1, d2, d3; +} __itt_id; + +#pragma pack(pop) +/** @endcond */ + +static const __itt_id __itt_null = { 0, 0, 0 }; + +/** + * @ingroup ids + * @brief A convenience function is provided to create an ID without domain control. + * @brief This is a convenience function to initialize an __itt_id structure. This function + * does not affect the trace collector runtime in any way. After you make the ID with this + * function, you still must create it with the __itt_id_create function before using the ID + * to identify a named entity. + * @param[in] addr The address of object; high QWORD of the ID value. + * @param[in] extra The extra data to unique identify object; low QWORD of the ID value. + */ + +INLINE __itt_id ITTAPI __itt_id_make(void* addr, unsigned long long extra) INLINE_ATTRIBUTE; +INLINE __itt_id ITTAPI __itt_id_make(void* addr, unsigned long long extra) +{ + __itt_id id = __itt_null; + id.d1 = (unsigned long long)((uintptr_t)addr); + id.d2 = (unsigned long long)extra; + id.d3 = (unsigned long long)0; /* Reserved. Must be zero */ + return id; +} + +/** + * @ingroup ids + * @brief Create an instance of identifier. + * This establishes the beginning of the lifetime of an instance of + * the given ID in the trace. Once this lifetime starts, the ID + * can be used to tag named entity instances in calls such as + * __itt_task_begin, and to specify relationships among + * identified named entity instances, using the \ref relations APIs. + * Instance IDs are not domain specific! + * @param[in] domain The domain controlling the execution of this call. + * @param[in] id The ID to create. + */ +void ITTAPI __itt_id_create(const __itt_domain *domain, __itt_id id); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, id_create, (const __itt_domain *domain, __itt_id id)) +#define __itt_id_create(d,x) ITTNOTIFY_VOID_D1(id_create,d,x) +#define __itt_id_create_ptr ITTNOTIFY_NAME(id_create) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_id_create(domain,id) +#define __itt_id_create_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_id_create_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @ingroup ids + * @brief Destroy an instance of identifier. + * This ends the lifetime of the current instance of the given ID value in the trace. + * Any relationships that are established after this lifetime ends are invalid. + * This call must be performed before the given ID value can be reused for a different + * named entity instance. + * @param[in] domain The domain controlling the execution of this call. + * @param[in] id The ID to destroy. + */ +void ITTAPI __itt_id_destroy(const __itt_domain *domain, __itt_id id); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, id_destroy, (const __itt_domain *domain, __itt_id id)) +#define __itt_id_destroy(d,x) ITTNOTIFY_VOID_D1(id_destroy,d,x) +#define __itt_id_destroy_ptr ITTNOTIFY_NAME(id_destroy) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_id_destroy(domain,id) +#define __itt_id_destroy_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_id_destroy_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} ids group */ + +/** + * @defgroup handless String Handles + * @ingroup public + * String Handles group + * @{ + */ + +/** @cond exclude_from_documentation */ +#pragma pack(push, 8) + +typedef struct ___itt_string_handle +{ + const char* strA; /*!< Copy of original string in ASCII. */ +#if defined(UNICODE) || defined(_UNICODE) + const wchar_t* strW; /*!< Copy of original string in UNICODE. */ +#else /* UNICODE || _UNICODE */ + void* strW; +#endif /* UNICODE || _UNICODE */ + int extra1; /*!< Reserved. Must be zero */ + void* extra2; /*!< Reserved. Must be zero */ + struct ___itt_string_handle* next; +} __itt_string_handle; + +#pragma pack(pop) +/** @endcond */ + +/** + * @ingroup handles + * @brief Create a string handle. + * Create and return handle value that can be associated with a string. + * Consecutive calls to __itt_string_handle_create with the same name + * return the same value. Because the set of string handles is expected to remain + * static during the application's execution time, there is no mechanism to destroy a string handle. + * Any string handle can be accessed by any thread in the process, regardless of which thread created + * the string handle. This call is thread-safe. + * @param[in] name The input string + */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +__itt_string_handle* ITTAPI __itt_string_handle_createA(const char *name); +__itt_string_handle* ITTAPI __itt_string_handle_createW(const wchar_t *name); +#if defined(UNICODE) || defined(_UNICODE) +# define __itt_string_handle_create __itt_string_handle_createW +# define __itt_string_handle_create_ptr __itt_string_handle_createW_ptr +#else /* UNICODE */ +# define __itt_string_handle_create __itt_string_handle_createA +# define __itt_string_handle_create_ptr __itt_string_handle_createA_ptr +#endif /* UNICODE */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +__itt_string_handle* ITTAPI __itt_string_handle_create(const char *name); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(ITTAPI, __itt_string_handle*, string_handle_createA, (const char *name)) +ITT_STUB(ITTAPI, __itt_string_handle*, string_handle_createW, (const wchar_t *name)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, __itt_string_handle*, string_handle_create, (const char *name)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_string_handle_createA ITTNOTIFY_DATA(string_handle_createA) +#define __itt_string_handle_createA_ptr ITTNOTIFY_NAME(string_handle_createA) +#define __itt_string_handle_createW ITTNOTIFY_DATA(string_handle_createW) +#define __itt_string_handle_createW_ptr ITTNOTIFY_NAME(string_handle_createW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_string_handle_create ITTNOTIFY_DATA(string_handle_create) +#define __itt_string_handle_create_ptr ITTNOTIFY_NAME(string_handle_create) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_string_handle_createA(name) (__itt_string_handle*)0 +#define __itt_string_handle_createA_ptr 0 +#define __itt_string_handle_createW(name) (__itt_string_handle*)0 +#define __itt_string_handle_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_string_handle_create(name) (__itt_string_handle*)0 +#define __itt_string_handle_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_string_handle_createA_ptr 0 +#define __itt_string_handle_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_string_handle_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} handles group */ + +/** @cond exclude_from_gpa_documentation */ + +/** + * @defgroup regions Regions + * @ingroup public + * Regions group + * @{ + */ +/** + * @ingroup regions + * @brief Begin of region instance. + * Successive calls to __itt_region_begin with the same ID are ignored + * until a call to __itt_region_end with the same ID + * @param[in] domain The domain for this region instance + * @param[in] id The instance ID for this region instance. Must not be __itt_null + * @param[in] parentid The instance ID for the parent of this region instance, or __itt_null + * @param[in] name The name of this region + */ +void ITTAPI __itt_region_begin(const __itt_domain *domain, __itt_id id, __itt_id parentid, __itt_string_handle *name); + +/** + * @ingroup regions + * @brief End of region instance. + * The first call to __itt_region_end with a given ID ends the + * region. Successive calls with the same ID are ignored, as are + * calls that do not have a matching __itt_region_begin call. + * @param[in] domain The domain for this region instance + * @param[in] id The instance ID for this region instance + */ +void ITTAPI __itt_region_end(const __itt_domain *domain, __itt_id id); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, region_begin, (const __itt_domain *domain, __itt_id id, __itt_id parentid, __itt_string_handle *name)) +ITT_STUBV(ITTAPI, void, region_end, (const __itt_domain *domain, __itt_id id)) +#define __itt_region_begin(d,x,y,z) ITTNOTIFY_VOID_D3(region_begin,d,x,y,z) +#define __itt_region_begin_ptr ITTNOTIFY_NAME(region_begin) +#define __itt_region_end(d,x) ITTNOTIFY_VOID_D1(region_end,d,x) +#define __itt_region_end_ptr ITTNOTIFY_NAME(region_end) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_region_begin(d,x,y,z) +#define __itt_region_begin_ptr 0 +#define __itt_region_end(d,x) +#define __itt_region_end_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_region_begin_ptr 0 +#define __itt_region_end_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} regions group */ + +/** + * @defgroup frames Frames + * @ingroup public + * Frames are similar to regions, but are intended to be easier to use and to implement. + * In particular: + * - Frames always represent periods of elapsed time + * - By default, frames have no nesting relationships + * @{ + */ + +/** + * @ingroup frames + * @brief Begin a frame instance. + * Successive calls to __itt_frame_begin with the + * same ID are ignored until a call to __itt_frame_end with the same ID. + * @param[in] domain The domain for this frame instance + * @param[in] id The instance ID for this frame instance or NULL + */ +void ITTAPI __itt_frame_begin_v3(const __itt_domain *domain, __itt_id *id); + +/** + * @ingroup frames + * @brief End a frame instance. + * The first call to __itt_frame_end with a given ID + * ends the frame. Successive calls with the same ID are ignored, as are + * calls that do not have a matching __itt_frame_begin call. + * @param[in] domain The domain for this frame instance + * @param[in] id The instance ID for this frame instance or NULL for current + */ +void ITTAPI __itt_frame_end_v3(const __itt_domain *domain, __itt_id *id); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, frame_begin_v3, (const __itt_domain *domain, __itt_id *id)) +ITT_STUBV(ITTAPI, void, frame_end_v3, (const __itt_domain *domain, __itt_id *id)) +#define __itt_frame_begin_v3(d,x) ITTNOTIFY_VOID_D1(frame_begin_v3,d,x) +#define __itt_frame_begin_v3_ptr ITTNOTIFY_NAME(frame_begin_v3) +#define __itt_frame_end_v3(d,x) ITTNOTIFY_VOID_D1(frame_end_v3,d,x) +#define __itt_frame_end_v3_ptr ITTNOTIFY_NAME(frame_end_v3) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_frame_begin_v3(domain,id) +#define __itt_frame_begin_v3_ptr 0 +#define __itt_frame_end_v3(domain,id) +#define __itt_frame_end_v3_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_frame_begin_v3_ptr 0 +#define __itt_frame_end_v3_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} frames group */ +/** @endcond */ + +/** + * @defgroup taskgroup Task Group + * @ingroup public + * Task Group + * @{ + */ +/** + * @ingroup task_groups + * @brief Denotes a task_group instance. + * Successive calls to __itt_task_group with the same ID are ignored. + * @param[in] domain The domain for this task_group instance + * @param[in] id The instance ID for this task_group instance. Must not be __itt_null. + * @param[in] parentid The instance ID for the parent of this task_group instance, or __itt_null. + * @param[in] name The name of this task_group + */ +void ITTAPI __itt_task_group(const __itt_domain *domain, __itt_id id, __itt_id parentid, __itt_string_handle *name); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, task_group, (const __itt_domain *domain, __itt_id id, __itt_id parentid, __itt_string_handle *name)) +#define __itt_task_group(d,x,y,z) ITTNOTIFY_VOID_D3(task_group,d,x,y,z) +#define __itt_task_group_ptr ITTNOTIFY_NAME(task_group) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_task_group(d,x,y,z) +#define __itt_task_group_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_task_group_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} taskgroup group */ + +/** + * @defgroup tasks Tasks + * @ingroup public + * A task instance represents a piece of work performed by a particular + * thread for a period of time. A call to __itt_task_begin creates a + * task instance. This becomes the current instance for that task on that + * thread. A following call to __itt_task_end on the same thread ends the + * instance. There may be multiple simultaneous instances of tasks with the + * same name on different threads. If an ID is specified, the task instance + * receives that ID. Nested tasks are allowed. + * + * Note: The task is defined by the bracketing of __itt_task_begin and + * __itt_task_end on the same thread. If some scheduling mechanism causes + * task switching (the thread executes a different user task) or task + * switching (the user task switches to a different thread) then this breaks + * the notion of current instance. Additional API calls are required to + * deal with that possibility. + * @{ + */ + +/** + * @ingroup tasks + * @brief Begin a task instance. + * @param[in] domain The domain for this task + * @param[in] taskid The instance ID for this task instance, or __itt_null + * @param[in] parentid The parent instance to which this task instance belongs, or __itt_null + * @param[in] name The name of this task + */ +void ITTAPI __itt_task_begin(const __itt_domain *domain, __itt_id taskid, __itt_id parentid, __itt_string_handle *name); + +/** + * @ingroup tasks + * @brief Begin a task instance. + * @param[in] domain The domain for this task + * @param[in] taskid The identifier for this task instance (may be 0) + * @param[in] parentid The parent of this task (may be 0) + * @param[in] fn The pointer to the function you are tracing + */ +void ITTAPI __itt_task_begin_fn(const __itt_domain *domain, __itt_id taskid, __itt_id parentid, void* fn); + +/** + * @ingroup tasks + * @brief End the current task instance. + * @param[in] domain The domain for this task + */ +void ITTAPI __itt_task_end(const __itt_domain *domain); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, task_begin, (const __itt_domain *domain, __itt_id id, __itt_id parentid, __itt_string_handle *name)) +ITT_STUBV(ITTAPI, void, task_begin_fn, (const __itt_domain *domain, __itt_id id, __itt_id parentid, void* fn)) +ITT_STUBV(ITTAPI, void, task_end, (const __itt_domain *domain)) +#define __itt_task_begin(d,x,y,z) ITTNOTIFY_VOID_D3(task_begin,d,x,y,z) +#define __itt_task_begin_ptr ITTNOTIFY_NAME(task_begin) +#define __itt_task_begin_fn(d,x,y,z) ITTNOTIFY_VOID_D3(task_begin_fn,d,x,y,z) +#define __itt_task_begin_fn_ptr ITTNOTIFY_NAME(task_begin_fn) +#define __itt_task_end(d) ITTNOTIFY_VOID_D0(task_end,d) +#define __itt_task_end_ptr ITTNOTIFY_NAME(task_end) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_task_begin(domain,id,parentid,name) +#define __itt_task_begin_ptr 0 +#define __itt_task_begin_fn(domain,id,parentid,fn) +#define __itt_task_begin_fn_ptr 0 +#define __itt_task_end(domain) +#define __itt_task_end_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_task_begin_ptr 0 +#define __itt_task_begin_fn_ptr 0 +#define __itt_task_end_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} tasks group */ + +/** + * @defgroup counters Counters + * @ingroup public + * Counters are user-defined objects with a monotonically increasing + * value. Counter values are 64-bit unsigned integers. Counter values + * are tracked per-thread. Counters have names that can be displayed in + * the tools. + * @{ + */ + +/** + * @ingroup counters + * @brief Increment a counter by one. + * The first call with a given name creates a counter by that name and sets its + * value to zero on every thread. Successive calls increment the counter value + * on the thread on which the call is issued. + * @param[in] domain The domain controlling the call. Counter names are not domain specific. + * The domain argument is used only to enable or disable the API calls. + * @param[in] name The name of the counter + */ +void ITTAPI __itt_counter_inc_v3(const __itt_domain *domain, __itt_string_handle *name); + +/** + * @ingroup counters + * @brief Increment a counter by the value specified in delta. + * @param[in] domain The domain controlling the call. Counter names are not domain specific. + * The domain argument is used only to enable or disable the API calls. + * @param[in] name The name of the counter + * @param[in] delta The amount by which to increment the counter + */ +void ITTAPI __itt_counter_inc_delta_v3(const __itt_domain *domain, __itt_string_handle *name, unsigned long long delta); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, counter_inc_v3, (const __itt_domain *domain, __itt_string_handle *name)) +ITT_STUBV(ITTAPI, void, counter_inc_delta_v3, (const __itt_domain *domain, __itt_string_handle *name, unsigned long long delta)) +#define __itt_counter_inc_v3(d,x) ITTNOTIFY_VOID_D1(counter_inc_v3,d,x) +#define __itt_counter_inc_v3_ptr ITTNOTIFY_NAME(counter_inc_v3) +#define __itt_counter_inc_delta_v3(d,x,y) ITTNOTIFY_VOID_D2(counter_inc_delta_v3,d,x,y) +#define __itt_counter_inc_delta_v3_ptr ITTNOTIFY_NAME(counter_inc_delta_v3) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_counter_inc_v3(domain,name) +#define __itt_counter_inc_v3_ptr 0 +#define __itt_counter_inc_delta_v3(domain,name,delta) +#define __itt_counter_inc_delta_v3_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_counter_inc_v3_ptr 0 +#define __itt_counter_inc_delta_v3_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} counters group */ + +/** + * @defgroup markers Markers + * Markers represent a single discreet event in time. Markers have a scope, + * described by an enumerated type __itt_scope. Markers are created by + * the API call __itt_marker. A marker instance can be given an ID for use in + * adding metadata. + * @{ + */ + +/** + * @brief Describes the scope of an event object in the trace. + */ +typedef enum +{ + __itt_scope_unknown = 0, + __itt_scope_global, + __itt_scope_track_group, + __itt_scope_track, + __itt_scope_task, + __itt_scope_marker +} __itt_scope; + +/** @cond exclude_from_documentation */ +#define __itt_marker_scope_unknown __itt_scope_unknown +#define __itt_marker_scope_global __itt_scope_global +#define __itt_marker_scope_process __itt_scope_track_group +#define __itt_marker_scope_thread __itt_scope_track +#define __itt_marker_scope_task __itt_scope_task +/** @endcond */ + +/** + * @ingroup markers + * @brief Create a marker instance + * @param[in] domain The domain for this marker + * @param[in] id The instance ID for this marker or __itt_null + * @param[in] name The name for this marker + * @param[in] scope The scope for this marker + */ +void ITTAPI __itt_marker(const __itt_domain *domain, __itt_id id, __itt_string_handle *name, __itt_scope scope); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, marker, (const __itt_domain *domain, __itt_id id, __itt_string_handle *name, __itt_scope scope)) +#define __itt_marker(d,x,y,z) ITTNOTIFY_VOID_D3(marker,d,x,y,z) +#define __itt_marker_ptr ITTNOTIFY_NAME(marker) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_marker(domain,id,name,scope) +#define __itt_marker_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_marker_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} markers group */ + +/** + * @defgroup metadata Metadata + * The metadata API is used to attach extra information to named + * entities. Metadata can be attached to an identified named entity by ID, + * or to the current entity (which is always a task). + * + * Conceptually metadata has a type (what kind of metadata), a key (the + * name of the metadata), and a value (the actual data). The encoding of + * the value depends on the type of the metadata. + * + * The type of metadata is specified by an enumerated type __itt_metdata_type. + * @{ + */ + +/** + * @ingroup parameters + * @brief describes the type of metadata + */ +typedef enum { + __itt_metadata_unknown = 0, + __itt_metadata_u64, /**< Unsigned 64-bit integer */ + __itt_metadata_s64, /**< Signed 64-bit integer */ + __itt_metadata_u32, /**< Unsigned 32-bit integer */ + __itt_metadata_s32, /**< Signed 32-bit integer */ + __itt_metadata_u16, /**< Unsigned 16-bit integer */ + __itt_metadata_s16, /**< Signed 16-bit integer */ + __itt_metadata_float, /**< Signed 32-bit floating-point */ + __itt_metadata_double /**< SIgned 64-bit floating-point */ +} __itt_metadata_type; + +/** + * @ingroup parameters + * @brief Add metadata to an instance of a named entity. + * @param[in] domain The domain controlling the call + * @param[in] id The identifier of the instance to which the metadata is to be added, or __itt_null to add to the current task + * @param[in] key The name of the metadata + * @param[in] type The type of the metadata + * @param[in] count The number of elements of the given type. If count == 0, no metadata will be added. + * @param[in] data The metadata itself +*/ +void ITTAPI __itt_metadata_add(const __itt_domain *domain, __itt_id id, __itt_string_handle *key, __itt_metadata_type type, size_t count, void *data); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, metadata_add, (const __itt_domain *domain, __itt_id id, __itt_string_handle *key, __itt_metadata_type type, size_t count, void *data)) +#define __itt_metadata_add(d,x,y,z,a,b) ITTNOTIFY_VOID_D5(metadata_add,d,x,y,z,a,b) +#define __itt_metadata_add_ptr ITTNOTIFY_NAME(metadata_add) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_metadata_add(d,x,y,z,a,b) +#define __itt_metadata_add_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_metadata_add_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @ingroup parameters + * @brief Add string metadata to an instance of a named entity. + * @param[in] domain The domain controlling the call + * @param[in] id The identifier of the instance to which the metadata is to be added, or __itt_null to add to the current task + * @param[in] key The name of the metadata + * @param[in] data The metadata itself + * @param[in] length The number of characters in the string, or -1 if the length is unknown but the string is null-terminated +*/ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +void ITTAPI __itt_metadata_str_addA(const __itt_domain *domain, __itt_id id, __itt_string_handle *key, const char *data, size_t length); +void ITTAPI __itt_metadata_str_addW(const __itt_domain *domain, __itt_id id, __itt_string_handle *key, const wchar_t *data, size_t length); +#if defined(UNICODE) || defined(_UNICODE) +# define __itt_metadata_str_add __itt_metadata_str_addW +# define __itt_metadata_str_add_ptr __itt_metadata_str_addW_ptr +#else /* UNICODE */ +# define __itt_metadata_str_add __itt_metadata_str_addA +# define __itt_metadata_str_add_ptr __itt_metadata_str_addA_ptr +#endif /* UNICODE */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +void ITTAPI __itt_metadata_str_add(const __itt_domain *domain, __itt_id id, __itt_string_handle *key, const char *data, size_t length); +#endif + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUBV(ITTAPI, void, metadata_str_addA, (const __itt_domain *domain, __itt_id id, __itt_string_handle *key, const char *data, size_t length)) +ITT_STUBV(ITTAPI, void, metadata_str_addW, (const __itt_domain *domain, __itt_id id, __itt_string_handle *key, const wchar_t *data, size_t length)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUBV(ITTAPI, void, metadata_str_add, (const __itt_domain *domain, __itt_id id, __itt_string_handle *key, const char *data, size_t length)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_metadata_str_addA(d,x,y,z,a) ITTNOTIFY_VOID_D4(metadata_str_addA,d,x,y,z,a) +#define __itt_metadata_str_addA_ptr ITTNOTIFY_NAME(metadata_str_addA) +#define __itt_metadata_str_addW(d,x,y,z,a) ITTNOTIFY_VOID_D4(metadata_str_addW,d,x,y,z,a) +#define __itt_metadata_str_addW_ptr ITTNOTIFY_NAME(metadata_str_addW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_metadata_str_add(d,x,y,z,a) ITTNOTIFY_VOID_D4(metadata_str_add,d,x,y,z,a) +#define __itt_metadata_str_add_ptr ITTNOTIFY_NAME(metadata_str_add) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_metadata_str_addA(d,x,y,z,a) +#define __itt_metadata_str_addA_ptr 0 +#define __itt_metadata_str_addW(d,x,y,z,a) +#define __itt_metadata_str_addW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_metadata_str_add(d,x,y,z,a) +#define __itt_metadata_str_add_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_metadata_str_addA_ptr 0 +#define __itt_metadata_str_addW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_metadata_str_add_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @ingroup parameters + * @brief Add metadata to an instance of a named entity. + * @param[in] domain The domain controlling the call + * @param[in] scope The scope of the instance to which the metadata is to be added + + * @param[in] id The identifier of the instance to which the metadata is to be added, or __itt_null to add to the current task + + * @param[in] key The name of the metadata + * @param[in] type The type of the metadata + * @param[in] count The number of elements of the given type. If count == 0, no metadata will be added. + * @param[in] data The metadata itself +*/ +void ITTAPI __itt_metadata_add_with_scope(const __itt_domain *domain, __itt_scope scope, __itt_string_handle *key, __itt_metadata_type type, size_t count, void *data); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, metadata_add_with_scope, (const __itt_domain *domain, __itt_scope scope, __itt_string_handle *key, __itt_metadata_type type, size_t count, void *data)) +#define __itt_metadata_add_with_scope(d,x,y,z,a,b) ITTNOTIFY_VOID_D5(metadata_add_with_scope,d,x,y,z,a,b) +#define __itt_metadata_add_with_scope_ptr ITTNOTIFY_NAME(metadata_add_with_scope) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_metadata_add_with_scope(d,x,y,z,a,b) +#define __itt_metadata_add_with_scope_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_metadata_add_with_scope_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @ingroup parameters + * @brief Add string metadata to an instance of a named entity. + * @param[in] domain The domain controlling the call + * @param[in] scope The scope of the instance to which the metadata is to be added + + * @param[in] id The identifier of the instance to which the metadata is to be added, or __itt_null to add to the current task + + * @param[in] key The name of the metadata + * @param[in] data The metadata itself + * @param[in] length The number of characters in the string, or -1 if the length is unknown but the string is null-terminated +*/ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +void ITTAPI __itt_metadata_str_add_with_scopeA(const __itt_domain *domain, __itt_scope scope, __itt_string_handle *key, const char *data, size_t length); +void ITTAPI __itt_metadata_str_add_with_scopeW(const __itt_domain *domain, __itt_scope scope, __itt_string_handle *key, const wchar_t *data, size_t length); +#if defined(UNICODE) || defined(_UNICODE) +# define __itt_metadata_str_add_with_scope __itt_metadata_str_add_with_scopeW +# define __itt_metadata_str_add_with_scope_ptr __itt_metadata_str_add_with_scopeW_ptr +#else /* UNICODE */ +# define __itt_metadata_str_add_with_scope __itt_metadata_str_add_with_scopeA +# define __itt_metadata_str_add_with_scope_ptr __itt_metadata_str_add_with_scopeA_ptr +#endif /* UNICODE */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +void ITTAPI __itt_metadata_str_add_with_scope(const __itt_domain *domain, __itt_scope scope, __itt_string_handle *key, const char *data, size_t length); +#endif + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUBV(ITTAPI, void, metadata_str_add_with_scopeA, (const __itt_domain *domain, __itt_scope scope, __itt_string_handle *key, const char *data, size_t length)) +ITT_STUBV(ITTAPI, void, metadata_str_add_with_scopeW, (const __itt_domain *domain, __itt_scope scope, __itt_string_handle *key, const wchar_t *data, size_t length)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUBV(ITTAPI, void, metadata_str_add_with_scope, (const __itt_domain *domain, __itt_scope scope, __itt_string_handle *key, const char *data, size_t length)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_metadata_str_add_with_scopeA(d,x,y,z,a) ITTNOTIFY_VOID_D4(metadata_str_add_with_scopeA,d,x,y,z,a) +#define __itt_metadata_str_add_with_scopeA_ptr ITTNOTIFY_NAME(metadata_str_add_with_scopeA) +#define __itt_metadata_str_add_with_scopeW(d,x,y,z,a) ITTNOTIFY_VOID_D4(metadata_str_add_with_scopeW,d,x,y,z,a) +#define __itt_metadata_str_add_with_scopeW_ptr ITTNOTIFY_NAME(metadata_str_add_with_scopeW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_metadata_str_add_with_scope(d,x,y,z,a) ITTNOTIFY_VOID_D4(metadata_str_add_with_scope,d,x,y,z,a) +#define __itt_metadata_str_add_with_scope_ptr ITTNOTIFY_NAME(metadata_str_add_with_scope) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_metadata_str_add_with_scopeA(d,x,y,z,a) +#define __itt_metadata_str_add_with_scopeA_ptr 0 +#define __itt_metadata_str_add_with_scopeW(d,x,y,z,a) +#define __itt_metadata_str_add_with_scopeW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_metadata_str_add_with_scope(d,x,y,z,a) +#define __itt_metadata_str_add_with_scope_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_metadata_str_add_with_scopeA_ptr 0 +#define __itt_metadata_str_add_with_scopeW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_metadata_str_add_with_scope_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** @} metadata group */ + +/** + * @defgroup relations Relations + * Instances of named entities can be explicitly associated with other + * instances using instance IDs and the relationship API calls. + * + * @{ + */ + +/** + * @ingroup relations + * @brief The kind of relation between two instances is specified by the enumerated type __itt_relation. + * Relations between instances can be added with an API call. The relation + * API uses instance IDs. Relations can be added before or after the actual + * instances are created and persist independently of the instances. This + * is the motivation for having different lifetimes for instance IDs and + * the actual instances. + */ +typedef enum +{ + __itt_relation_is_unknown = 0, + __itt_relation_is_dependent_on, /**< "A is dependent on B" means that A cannot start until B completes */ + __itt_relation_is_sibling_of, /**< "A is sibling of B" means that A and B were created as a group */ + __itt_relation_is_parent_of, /**< "A is parent of B" means that A created B */ + __itt_relation_is_continuation_of, /**< "A is continuation of B" means that A assumes the dependencies of B */ + __itt_relation_is_child_of, /**< "A is child of B" means that A was created by B (inverse of is_parent_of) */ + __itt_relation_is_continued_by, /**< "A is continued by B" means that B assumes the dependencies of A (inverse of is_continuation_of) */ + __itt_relation_is_predecessor_to /**< "A is predecessor to B" means that B cannot start until A completes (inverse of is_dependent_on) */ +} __itt_relation; + +/** + * @ingroup relations + * @brief Add a relation to the current task instance. + * The current task instance is the head of the relation. + * @param[in] domain The domain controlling this call + * @param[in] relation The kind of relation + * @param[in] tail The ID for the tail of the relation + */ +void ITTAPI __itt_relation_add_to_current(const __itt_domain *domain, __itt_relation relation, __itt_id tail); + +/** + * @ingroup relations + * @brief Add a relation between two instance identifiers. + * @param[in] domain The domain controlling this call + * @param[in] head The ID for the head of the relation + * @param[in] relation The kind of relation + * @param[in] tail The ID for the tail of the relation + */ +void ITTAPI __itt_relation_add(const __itt_domain *domain, __itt_id head, __itt_relation relation, __itt_id tail); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, relation_add_to_current, (const __itt_domain *domain, __itt_relation relation, __itt_id tail)) +ITT_STUBV(ITTAPI, void, relation_add, (const __itt_domain *domain, __itt_id head, __itt_relation relation, __itt_id tail)) +#define __itt_relation_add_to_current(d,x,y) ITTNOTIFY_VOID_D2(relation_add_to_current,d,x,y) +#define __itt_relation_add_to_current_ptr ITTNOTIFY_NAME(relation_add_to_current) +#define __itt_relation_add(d,x,y,z) ITTNOTIFY_VOID_D3(relation_add,d,x,y,z) +#define __itt_relation_add_ptr ITTNOTIFY_NAME(relation_add) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_relation_add_to_current(d,x,y) +#define __itt_relation_add_to_current_ptr 0 +#define __itt_relation_add(d,x,y,z) +#define __itt_relation_add_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_relation_add_to_current_ptr 0 +#define __itt_relation_add_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} relations group */ + +/** @cond exclude_from_documentation */ +#pragma pack(push, 8) + +typedef struct ___itt_clock_info +{ + unsigned long long clock_freq; /*!< Clock domain frequency */ + unsigned long long clock_base; /*!< Clock domain base timestamp */ +} __itt_clock_info; + +#pragma pack(pop) +/** @endcond */ + +/** @cond exclude_from_documentation */ +typedef void (ITTAPI *__itt_get_clock_info_fn)(__itt_clock_info* clock_info, void* data); +/** @endcond */ + +/** @cond exclude_from_documentation */ +#pragma pack(push, 8) + +typedef struct ___itt_clock_domain +{ + __itt_clock_info info; /*!< Most recent clock domain info */ + __itt_get_clock_info_fn fn; /*!< Callback function pointer */ + void* fn_data; /*!< Input argument for the callback function */ + int extra1; /*!< Reserved. Must be zero */ + void* extra2; /*!< Reserved. Must be zero */ + struct ___itt_clock_domain* next; +} __itt_clock_domain; + +#pragma pack(pop) +/** @endcond */ + +/** + * @ingroup clockdomains + * @brief Create a clock domain. + * Certain applications require the capability to trace their application using + * a clock domain different than the CPU, for instance the instrumentation of events + * that occur on a GPU. + * Because the set of domains is expected to be static over the application's execution time, + * there is no mechanism to destroy a domain. + * Any domain can be accessed by any thread in the process, regardless of which thread created + * the domain. This call is thread-safe. + * @param[in] fn A pointer to a callback function which retrieves alternative CPU timestamps + * @param[in] fn_data Argument for a callback function; may be NULL + */ +__itt_clock_domain* ITTAPI __itt_clock_domain_create(__itt_get_clock_info_fn fn, void* fn_data); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUB(ITTAPI, __itt_clock_domain*, clock_domain_create, (__itt_get_clock_info_fn fn, void* fn_data)) +#define __itt_clock_domain_create ITTNOTIFY_DATA(clock_domain_create) +#define __itt_clock_domain_create_ptr ITTNOTIFY_NAME(clock_domain_create) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_clock_domain_create(fn,fn_data) (__itt_clock_domain*)0 +#define __itt_clock_domain_create_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_clock_domain_create_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @ingroup clockdomains + * @brief Recalculate clock domains frequences and clock base timestamps. + */ +void ITTAPI __itt_clock_domain_reset(void); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, clock_domain_reset, (void)) +#define __itt_clock_domain_reset ITTNOTIFY_VOID(clock_domain_reset) +#define __itt_clock_domain_reset_ptr ITTNOTIFY_NAME(clock_domain_reset) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_clock_domain_reset() +#define __itt_clock_domain_reset_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_clock_domain_reset_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @ingroup clockdomain + * @brief Create an instance of identifier. This establishes the beginning of the lifetime of + * an instance of the given ID in the trace. Once this lifetime starts, the ID can be used to + * tag named entity instances in calls such as __itt_task_begin, and to specify relationships among + * identified named entity instances, using the \ref relations APIs. + * @param[in] domain The domain controlling the execution of this call. + * @param[in] clock_domain The clock domain controlling the execution of this call. + * @param[in] timestamp The user defined timestamp. + * @param[in] id The ID to create. + */ +void ITTAPI __itt_id_create_ex(const __itt_domain* domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id id); + +/** + * @ingroup clockdomain + * @brief Destroy an instance of identifier. This ends the lifetime of the current instance of the + * given ID value in the trace. Any relationships that are established after this lifetime ends are + * invalid. This call must be performed before the given ID value can be reused for a different + * named entity instance. + * @param[in] domain The domain controlling the execution of this call. + * @param[in] clock_domain The clock domain controlling the execution of this call. + * @param[in] timestamp The user defined timestamp. + * @param[in] id The ID to destroy. + */ +void ITTAPI __itt_id_destroy_ex(const __itt_domain* domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id id); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, id_create_ex, (const __itt_domain *domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id id)) +ITT_STUBV(ITTAPI, void, id_destroy_ex, (const __itt_domain *domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id id)) +#define __itt_id_create_ex(d,x,y,z) ITTNOTIFY_VOID_D3(id_create_ex,d,x,y,z) +#define __itt_id_create_ex_ptr ITTNOTIFY_NAME(id_create_ex) +#define __itt_id_destroy_ex(d,x,y,z) ITTNOTIFY_VOID_D3(id_destroy_ex,d,x,y,z) +#define __itt_id_destroy_ex_ptr ITTNOTIFY_NAME(id_destroy_ex) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_id_create_ex(domain,clock_domain,timestamp,id) +#define __itt_id_create_ex_ptr 0 +#define __itt_id_destroy_ex(domain,clock_domain,timestamp,id) +#define __itt_id_destroy_ex_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_id_create_ex_ptr 0 +#define __itt_id_destroy_ex_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @ingroup clockdomain + * @brief Begin a task instance. + * @param[in] domain The domain for this task + * @param[in] clock_domain The clock domain controlling the execution of this call. + * @param[in] timestamp The user defined timestamp. + * @param[in] taskid The instance ID for this task instance, or __itt_null + * @param[in] parentid The parent instance to which this task instance belongs, or __itt_null + * @param[in] name The name of this task + */ +void ITTAPI __itt_task_begin_ex(const __itt_domain* domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id taskid, __itt_id parentid, __itt_string_handle* name); + +/** + * @ingroup clockdomain + * @brief Begin a task instance. + * @param[in] domain The domain for this task + * @param[in] clock_domain The clock domain controlling the execution of this call. + * @param[in] timestamp The user defined timestamp. + * @param[in] taskid The identifier for this task instance, or __itt_null + * @param[in] parentid The parent of this task, or __itt_null + * @param[in] fn The pointer to the function you are tracing + */ +void ITTAPI __itt_task_begin_fn_ex(const __itt_domain* domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id taskid, __itt_id parentid, void* fn); + +/** + * @ingroup clockdomain + * @brief End the current task instance. + * @param[in] domain The domain for this task + * @param[in] clock_domain The clock domain controlling the execution of this call. + * @param[in] timestamp The user defined timestamp. + */ +void ITTAPI __itt_task_end_ex(const __itt_domain* domain, __itt_clock_domain* clock_domain, unsigned long long timestamp); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, task_begin_ex, (const __itt_domain *domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id id, __itt_id parentid, __itt_string_handle *name)) +ITT_STUBV(ITTAPI, void, task_begin_fn_ex, (const __itt_domain *domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id id, __itt_id parentid, void* fn)) +ITT_STUBV(ITTAPI, void, task_end_ex, (const __itt_domain *domain, __itt_clock_domain* clock_domain, unsigned long long timestamp)) +#define __itt_task_begin_ex(d,x,y,z,a,b) ITTNOTIFY_VOID_D5(task_begin_ex,d,x,y,z,a,b) +#define __itt_task_begin_ex_ptr ITTNOTIFY_NAME(task_begin_ex) +#define __itt_task_begin_fn_ex(d,x,y,z,a,b) ITTNOTIFY_VOID_D5(task_begin_fn_ex,d,x,y,z,a,b) +#define __itt_task_begin_fn_ex_ptr ITTNOTIFY_NAME(task_begin_fn_ex) +#define __itt_task_end_ex(d,x,y) ITTNOTIFY_VOID_D2(task_end_ex,d,x,y) +#define __itt_task_end_ex_ptr ITTNOTIFY_NAME(task_end_ex) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_task_begin_ex(domain,clock_domain,timestamp,id,parentid,name) +#define __itt_task_begin_ex_ptr 0 +#define __itt_task_begin_fn_ex(domain,clock_domain,timestamp,id,parentid,fn) +#define __itt_task_begin_fn_ex_ptr 0 +#define __itt_task_end_ex(domain,clock_domain,timestamp) +#define __itt_task_end_ex_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_task_begin_ex_ptr 0 +#define __itt_task_begin_fn_ex_ptr 0 +#define __itt_task_end_ex_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @ingroup markers + * @brief Create a marker instance. + * @param[in] domain The domain for this marker + * @param[in] clock_domain The clock domain controlling the execution of this call. + * @param[in] timestamp The user defined timestamp. + * @param[in] id The instance ID for this marker, or __itt_null + * @param[in] name The name for this marker + * @param[in] scope The scope for this marker + */ +void ITTAPI __itt_marker_ex(const __itt_domain *domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id id, __itt_string_handle *name, __itt_scope scope); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, marker_ex, (const __itt_domain *domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id id, __itt_string_handle *name, __itt_scope scope)) +#define __itt_marker_ex(d,x,y,z,a,b) ITTNOTIFY_VOID_D5(marker_ex,d,x,y,z,a,b) +#define __itt_marker_ex_ptr ITTNOTIFY_NAME(marker_ex) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_marker_ex(domain,clock_domain,timestamp,id,name,scope) +#define __itt_marker_ex_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_marker_ex_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @ingroup clockdomain + * @brief Add a relation to the current task instance. + * The current task instance is the head of the relation. + * @param[in] domain The domain controlling this call + * @param[in] clock_domain The clock domain controlling the execution of this call. + * @param[in] timestamp The user defined timestamp. + * @param[in] relation The kind of relation + * @param[in] tail The ID for the tail of the relation + */ +void ITTAPI __itt_relation_add_to_current_ex(const __itt_domain *domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_relation relation, __itt_id tail); + +/** + * @ingroup clockdomain + * @brief Add a relation between two instance identifiers. + * @param[in] domain The domain controlling this call + * @param[in] clock_domain The clock domain controlling the execution of this call. + * @param[in] timestamp The user defined timestamp. + * @param[in] head The ID for the head of the relation + * @param[in] relation The kind of relation + * @param[in] tail The ID for the tail of the relation + */ +void ITTAPI __itt_relation_add_ex(const __itt_domain *domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id head, __itt_relation relation, __itt_id tail); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, relation_add_to_current_ex, (const __itt_domain *domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_relation relation, __itt_id tail)) +ITT_STUBV(ITTAPI, void, relation_add_ex, (const __itt_domain *domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id head, __itt_relation relation, __itt_id tail)) +#define __itt_relation_add_to_current_ex(d,x,y,z,a) ITTNOTIFY_VOID_D4(relation_add_to_current_ex,d,x,y,z,a) +#define __itt_relation_add_to_current_ex_ptr ITTNOTIFY_NAME(relation_add_to_current_ex) +#define __itt_relation_add_ex(d,x,y,z,a,b) ITTNOTIFY_VOID_D5(relation_add_ex,d,x,y,z,a,b) +#define __itt_relation_add_ex_ptr ITTNOTIFY_NAME(relation_add_ex) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_relation_add_to_current_ex(domain,clock_domain,timestame,relation,tail) +#define __itt_relation_add_to_current_ex_ptr 0 +#define __itt_relation_add_ex(domain,clock_domain,timestamp,head,relation,tail) +#define __itt_relation_add_ex_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_relation_add_to_current_ex_ptr 0 +#define __itt_relation_add_ex_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** @cond exclude_from_documentation */ +typedef enum ___itt_track_group_type +{ + __itt_track_group_type_normal = 0 +} __itt_track_group_type; +/** @endcond */ + +/** @cond exclude_from_documentation */ +#pragma pack(push, 8) + +typedef struct ___itt_track_group +{ + __itt_string_handle* name; /*!< Name of the track group */ + struct ___itt_track* track; /*!< List of child tracks */ + __itt_track_group_type tgtype; /*!< Type of the track group */ + int extra1; /*!< Reserved. Must be zero */ + void* extra2; /*!< Reserved. Must be zero */ + struct ___itt_track_group* next; +} __itt_track_group; + +#pragma pack(pop) +/** @endcond */ + +/** + * @brief Placeholder for custom track types. Currently, "normal" custom track + * is the only available track type. + */ +typedef enum ___itt_track_type +{ + __itt_track_type_normal = 0 +#ifdef INTEL_ITTNOTIFY_API_PRIVATE + , __itt_track_type_queue +#endif /* INTEL_ITTNOTIFY_API_PRIVATE */ +} __itt_track_type; + +/** @cond exclude_from_documentation */ +#pragma pack(push, 8) + +typedef struct ___itt_track +{ + __itt_string_handle* name; /*!< Name of the track group */ + __itt_track_group* group; /*!< Parent group to a track */ + __itt_track_type ttype; /*!< Type of the track */ + int extra1; /*!< Reserved. Must be zero */ + void* extra2; /*!< Reserved. Must be zero */ + struct ___itt_track* next; +} __itt_track; + +#pragma pack(pop) +/** @endcond */ + +/** + * @brief Create logical track group. + */ +__itt_track_group* ITTAPI __itt_track_group_create(__itt_string_handle* name, __itt_track_group_type track_group_type); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUB(ITTAPI, __itt_track_group*, track_group_create, (__itt_string_handle* name, __itt_track_group_type track_group_type)) +#define __itt_track_group_create ITTNOTIFY_DATA(track_group_create) +#define __itt_track_group_create_ptr ITTNOTIFY_NAME(track_group_create) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_track_group_create(name) (__itt_track_group*)0 +#define __itt_track_group_create_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_track_group_create_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Create logical track. + */ +__itt_track* ITTAPI __itt_track_create(__itt_track_group* track_group, __itt_string_handle* name, __itt_track_type track_type); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUB(ITTAPI, __itt_track*, track_create, (__itt_track_group* track_group,__itt_string_handle* name, __itt_track_type track_type)) +#define __itt_track_create ITTNOTIFY_DATA(track_create) +#define __itt_track_create_ptr ITTNOTIFY_NAME(track_create) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_track_create(track_group,name,track_type) (__itt_track*)0 +#define __itt_track_create_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_track_create_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Set the logical track. + */ +void ITTAPI __itt_set_track(__itt_track* track); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, set_track, (__itt_track *track)) +#define __itt_set_track ITTNOTIFY_VOID(set_track) +#define __itt_set_track_ptr ITTNOTIFY_NAME(set_track) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_set_track(track) +#define __itt_set_track_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_set_track_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/* ========================================================================== */ +/** @cond exclude_from_gpa_documentation */ +/** + * @defgroup events Events + * @ingroup public + * Events group + * @{ + */ +/** @brief user event type */ +typedef int __itt_event; + +/** + * @brief Create an event notification + * @note name or namelen being null/name and namelen not matching, user event feature not enabled + * @return non-zero event identifier upon success and __itt_err otherwise + */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +__itt_event LIBITTAPI __itt_event_createA(const char *name, int namelen); +__itt_event LIBITTAPI __itt_event_createW(const wchar_t *name, int namelen); +#if defined(UNICODE) || defined(_UNICODE) +# define __itt_event_create __itt_event_createW +# define __itt_event_create_ptr __itt_event_createW_ptr +#else +# define __itt_event_create __itt_event_createA +# define __itt_event_create_ptr __itt_event_createA_ptr +#endif /* UNICODE */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +__itt_event LIBITTAPI __itt_event_create(const char *name, int namelen); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(LIBITTAPI, __itt_event, event_createA, (const char *name, int namelen)) +ITT_STUB(LIBITTAPI, __itt_event, event_createW, (const wchar_t *name, int namelen)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(LIBITTAPI, __itt_event, event_create, (const char *name, int namelen)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_event_createA ITTNOTIFY_DATA(event_createA) +#define __itt_event_createA_ptr ITTNOTIFY_NAME(event_createA) +#define __itt_event_createW ITTNOTIFY_DATA(event_createW) +#define __itt_event_createW_ptr ITTNOTIFY_NAME(event_createW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_event_create ITTNOTIFY_DATA(event_create) +#define __itt_event_create_ptr ITTNOTIFY_NAME(event_create) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_event_createA(name, namelen) (__itt_event)0 +#define __itt_event_createA_ptr 0 +#define __itt_event_createW(name, namelen) (__itt_event)0 +#define __itt_event_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_event_create(name, namelen) (__itt_event)0 +#define __itt_event_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_event_createA_ptr 0 +#define __itt_event_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_event_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Record an event occurrence. + * @return __itt_err upon failure (invalid event id/user event feature not enabled) + */ +int LIBITTAPI __itt_event_start(__itt_event event); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUB(LIBITTAPI, int, event_start, (__itt_event event)) +#define __itt_event_start ITTNOTIFY_DATA(event_start) +#define __itt_event_start_ptr ITTNOTIFY_NAME(event_start) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_event_start(event) (int)0 +#define __itt_event_start_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_event_start_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Record an event end occurrence. + * @note It is optional if events do not have durations. + * @return __itt_err upon failure (invalid event id/user event feature not enabled) + */ +int LIBITTAPI __itt_event_end(__itt_event event); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUB(LIBITTAPI, int, event_end, (__itt_event event)) +#define __itt_event_end ITTNOTIFY_DATA(event_end) +#define __itt_event_end_ptr ITTNOTIFY_NAME(event_end) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_event_end(event) (int)0 +#define __itt_event_end_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_event_end_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} events group */ +/** @endcond */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _ITTNOTIFY_H_ */ + +#ifdef INTEL_ITTNOTIFY_API_PRIVATE + +#ifndef _ITTNOTIFY_PRIVATE_ +#define _ITTNOTIFY_PRIVATE_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @ingroup tasks + * @brief Begin an overlapped task instance. + * @param[in] domain The domain for this task. + * @param[in] taskid The identifier for this task instance, *cannot* be __itt_null. + * @param[in] parentid The parent of this task, or __itt_null. + * @param[in] name The name of this task. + */ +void ITTAPI __itt_task_begin_overlapped(const __itt_domain* domain, __itt_id taskid, __itt_id parentid, __itt_string_handle* name); + +/** + * @ingroup clockdomain + * @brief Begin an overlapped task instance. + * @param[in] domain The domain for this task + * @param[in] clock_domain The clock domain controlling the execution of this call. + * @param[in] timestamp The user defined timestamp. + * @param[in] taskid The identifier for this task instance, *cannot* be __itt_null. + * @param[in] parentid The parent of this task, or __itt_null. + * @param[in] name The name of this task. + */ +void ITTAPI __itt_task_begin_overlapped_ex(const __itt_domain* domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id taskid, __itt_id parentid, __itt_string_handle* name); + +/** + * @ingroup tasks + * @brief End an overlapped task instance. + * @param[in] domain The domain for this task + * @param[in] taskid Explicit ID of finished task + */ +void ITTAPI __itt_task_end_overlapped(const __itt_domain *domain, __itt_id taskid); + +/** + * @ingroup clockdomain + * @brief End an overlapped task instance. + * @param[in] domain The domain for this task + * @param[in] clock_domain The clock domain controlling the execution of this call. + * @param[in] timestamp The user defined timestamp. + * @param[in] taskid Explicit ID of finished task + */ +void ITTAPI __itt_task_end_overlapped_ex(const __itt_domain* domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id taskid); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, task_begin_overlapped, (const __itt_domain *domain, __itt_id taskid, __itt_id parentid, __itt_string_handle *name)) +ITT_STUBV(ITTAPI, void, task_begin_overlapped_ex, (const __itt_domain* domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id taskid, __itt_id parentid, __itt_string_handle* name)) +ITT_STUBV(ITTAPI, void, task_end_overlapped, (const __itt_domain *domain, __itt_id taskid)) +ITT_STUBV(ITTAPI, void, task_end_overlapped_ex, (const __itt_domain* domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id taskid)) +#define __itt_task_begin_overlapped(d,x,y,z) ITTNOTIFY_VOID_D3(task_begin_overlapped,d,x,y,z) +#define __itt_task_begin_overlapped_ptr ITTNOTIFY_NAME(task_begin_overlapped) +#define __itt_task_begin_overlapped_ex(d,x,y,z,a,b) ITTNOTIFY_VOID_D5(task_begin_overlapped_ex,d,x,y,z,a,b) +#define __itt_task_begin_overlapped_ex_ptr ITTNOTIFY_NAME(task_begin_overlapped_ex) +#define __itt_task_end_overlapped(d,x) ITTNOTIFY_VOID_D1(task_end_overlapped,d,x) +#define __itt_task_end_overlapped_ptr ITTNOTIFY_NAME(task_end_overlapped) +#define __itt_task_end_overlapped_ex(d,x,y,z) ITTNOTIFY_VOID_D3(task_end_overlapped_ex,d,x,y,z) +#define __itt_task_end_overlapped_ex_ptr ITTNOTIFY_NAME(task_end_overlapped_ex) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_task_begin_overlapped(domain,taskid,parentid,name) +#define __itt_task_begin_overlapped_ptr 0 +#define __itt_task_begin_overlapped_ex(domain,clock_domain,timestamp,taskid,parentid,name) +#define __itt_task_begin_overlapped_ex_ptr 0 +#define __itt_task_end_overlapped(domain,taskid) +#define __itt_task_end_overlapped_ptr 0 +#define __itt_task_end_overlapped_ex(domain,clock_domain,timestamp,taskid) +#define __itt_task_end_overlapped_ex_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_task_begin_overlapped_ptr 0 +#define __itt_task_begin_overlapped_ex_ptr 0 +#define __itt_task_end_overlapped_ptr 0 +#define __itt_task_end_overlapped_ex_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @defgroup makrs_internal Marks + * @ingroup internal + * Marks group + * @warning Internal API: + * - It is not shipped to outside of Intel + * - It is delivered to internal Intel teams using e-mail or SVN access only + * @{ + */ +/** @brief user mark type */ +typedef int __itt_mark_type; + +/** + * @brief Creates a user mark type with the specified name using char or Unicode string. + * @param[in] name - name of mark to create + * @return Returns a handle to the mark type + */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +__itt_mark_type ITTAPI __itt_mark_createA(const char *name); +__itt_mark_type ITTAPI __itt_mark_createW(const wchar_t *name); +#if defined(UNICODE) || defined(_UNICODE) +# define __itt_mark_create __itt_mark_createW +# define __itt_mark_create_ptr __itt_mark_createW_ptr +#else /* UNICODE */ +# define __itt_mark_create __itt_mark_createA +# define __itt_mark_create_ptr __itt_mark_createA_ptr +#endif /* UNICODE */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +__itt_mark_type ITTAPI __itt_mark_create(const char *name); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(ITTAPI, __itt_mark_type, mark_createA, (const char *name)) +ITT_STUB(ITTAPI, __itt_mark_type, mark_createW, (const wchar_t *name)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, __itt_mark_type, mark_create, (const char *name)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_mark_createA ITTNOTIFY_DATA(mark_createA) +#define __itt_mark_createA_ptr ITTNOTIFY_NAME(mark_createA) +#define __itt_mark_createW ITTNOTIFY_DATA(mark_createW) +#define __itt_mark_createW_ptr ITTNOTIFY_NAME(mark_createW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_mark_create ITTNOTIFY_DATA(mark_create) +#define __itt_mark_create_ptr ITTNOTIFY_NAME(mark_create) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_mark_createA(name) (__itt_mark_type)0 +#define __itt_mark_createA_ptr 0 +#define __itt_mark_createW(name) (__itt_mark_type)0 +#define __itt_mark_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_mark_create(name) (__itt_mark_type)0 +#define __itt_mark_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_mark_createA_ptr 0 +#define __itt_mark_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_mark_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Creates a "discrete" user mark type of the specified type and an optional parameter using char or Unicode string. + * + * - The mark of "discrete" type is placed to collection results in case of success. It appears in overtime view(s) as a special tick sign. + * - The call is "synchronous" - function returns after mark is actually added to results. + * - This function is useful, for example, to mark different phases of application + * (beginning of the next mark automatically meand end of current region). + * - Can be used together with "continuous" marks (see below) at the same collection session + * @param[in] mt - mark, created by __itt_mark_create(const char* name) function + * @param[in] parameter - string parameter of mark + * @return Returns zero value in case of success, non-zero value otherwise. + */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +int ITTAPI __itt_markA(__itt_mark_type mt, const char *parameter); +int ITTAPI __itt_markW(__itt_mark_type mt, const wchar_t *parameter); +#if defined(UNICODE) || defined(_UNICODE) +# define __itt_mark __itt_markW +# define __itt_mark_ptr __itt_markW_ptr +#else /* UNICODE */ +# define __itt_mark __itt_markA +# define __itt_mark_ptr __itt_markA_ptr +#endif /* UNICODE */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +int ITTAPI __itt_mark(__itt_mark_type mt, const char *parameter); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(ITTAPI, int, markA, (__itt_mark_type mt, const char *parameter)) +ITT_STUB(ITTAPI, int, markW, (__itt_mark_type mt, const wchar_t *parameter)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, int, mark, (__itt_mark_type mt, const char *parameter)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_markA ITTNOTIFY_DATA(markA) +#define __itt_markA_ptr ITTNOTIFY_NAME(markA) +#define __itt_markW ITTNOTIFY_DATA(markW) +#define __itt_markW_ptr ITTNOTIFY_NAME(markW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_mark ITTNOTIFY_DATA(mark) +#define __itt_mark_ptr ITTNOTIFY_NAME(mark) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_markA(mt, parameter) (int)0 +#define __itt_markA_ptr 0 +#define __itt_markW(mt, parameter) (int)0 +#define __itt_markW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_mark(mt, parameter) (int)0 +#define __itt_mark_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_markA_ptr 0 +#define __itt_markW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_mark_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Use this if necessary to create a "discrete" user event type (mark) for process + * rather then for one thread + * @see int __itt_mark(__itt_mark_type mt, const char* parameter); + */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +int ITTAPI __itt_mark_globalA(__itt_mark_type mt, const char *parameter); +int ITTAPI __itt_mark_globalW(__itt_mark_type mt, const wchar_t *parameter); +#if defined(UNICODE) || defined(_UNICODE) +# define __itt_mark_global __itt_mark_globalW +# define __itt_mark_global_ptr __itt_mark_globalW_ptr +#else /* UNICODE */ +# define __itt_mark_global __itt_mark_globalA +# define __itt_mark_global_ptr __itt_mark_globalA_ptr +#endif /* UNICODE */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +int ITTAPI __itt_mark_global(__itt_mark_type mt, const char *parameter); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(ITTAPI, int, mark_globalA, (__itt_mark_type mt, const char *parameter)) +ITT_STUB(ITTAPI, int, mark_globalW, (__itt_mark_type mt, const wchar_t *parameter)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, int, mark_global, (__itt_mark_type mt, const char *parameter)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_mark_globalA ITTNOTIFY_DATA(mark_globalA) +#define __itt_mark_globalA_ptr ITTNOTIFY_NAME(mark_globalA) +#define __itt_mark_globalW ITTNOTIFY_DATA(mark_globalW) +#define __itt_mark_globalW_ptr ITTNOTIFY_NAME(mark_globalW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_mark_global ITTNOTIFY_DATA(mark_global) +#define __itt_mark_global_ptr ITTNOTIFY_NAME(mark_global) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_mark_globalA(mt, parameter) (int)0 +#define __itt_mark_globalA_ptr 0 +#define __itt_mark_globalW(mt, parameter) (int)0 +#define __itt_mark_globalW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_mark_global(mt, parameter) (int)0 +#define __itt_mark_global_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_mark_globalA_ptr 0 +#define __itt_mark_globalW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_mark_global_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Creates an "end" point for "continuous" mark with specified name. + * + * - Returns zero value in case of success, non-zero value otherwise. + * Also returns non-zero value when preceding "begin" point for the + * mark with the same name failed to be created or not created. + * - The mark of "continuous" type is placed to collection results in + * case of success. It appears in overtime view(s) as a special tick + * sign (different from "discrete" mark) together with line from + * corresponding "begin" mark to "end" mark. + * @note Continuous marks can overlap and be nested inside each other. + * Discrete mark can be nested inside marked region + * @param[in] mt - mark, created by __itt_mark_create(const char* name) function + * @return Returns zero value in case of success, non-zero value otherwise. + */ +int ITTAPI __itt_mark_off(__itt_mark_type mt); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUB(ITTAPI, int, mark_off, (__itt_mark_type mt)) +#define __itt_mark_off ITTNOTIFY_DATA(mark_off) +#define __itt_mark_off_ptr ITTNOTIFY_NAME(mark_off) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_mark_off(mt) (int)0 +#define __itt_mark_off_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_mark_off_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Use this if necessary to create an "end" point for mark of process + * @see int __itt_mark_off(__itt_mark_type mt); + */ +int ITTAPI __itt_mark_global_off(__itt_mark_type mt); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUB(ITTAPI, int, mark_global_off, (__itt_mark_type mt)) +#define __itt_mark_global_off ITTNOTIFY_DATA(mark_global_off) +#define __itt_mark_global_off_ptr ITTNOTIFY_NAME(mark_global_off) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_mark_global_off(mt) (int)0 +#define __itt_mark_global_off_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_mark_global_off_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} marks group */ + +/** + * @defgroup counters_internal Counters + * @ingroup internal + * Counters group + * @{ + */ +/** + * @brief opaque structure for counter identification + */ +typedef struct ___itt_counter *__itt_counter; + +/** + * @brief Create a counter with given name/domain for the calling thread + * + * After __itt_counter_create() is called, __itt_counter_inc() / __itt_counter_inc_delta() can be used + * to increment the counter on any thread + */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +__itt_counter ITTAPI __itt_counter_createA(const char *name, const char *domain); +__itt_counter ITTAPI __itt_counter_createW(const wchar_t *name, const wchar_t *domain); +#if defined(UNICODE) || defined(_UNICODE) +# define __itt_counter_create __itt_counter_createW +# define __itt_counter_create_ptr __itt_counter_createW_ptr +#else /* UNICODE */ +# define __itt_counter_create __itt_counter_createA +# define __itt_counter_create_ptr __itt_counter_createA_ptr +#endif /* UNICODE */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +__itt_counter ITTAPI __itt_counter_create(const char *name, const char *domain); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(ITTAPI, __itt_counter, counter_createA, (const char *name, const char *domain)) +ITT_STUB(ITTAPI, __itt_counter, counter_createW, (const wchar_t *name, const wchar_t *domain)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, __itt_counter, counter_create, (const char *name, const char *domain)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_counter_createA ITTNOTIFY_DATA(counter_createA) +#define __itt_counter_createA_ptr ITTNOTIFY_NAME(counter_createA) +#define __itt_counter_createW ITTNOTIFY_DATA(counter_createW) +#define __itt_counter_createW_ptr ITTNOTIFY_NAME(counter_createW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_counter_create ITTNOTIFY_DATA(counter_create) +#define __itt_counter_create_ptr ITTNOTIFY_NAME(counter_create) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_counter_createA(name, domain) +#define __itt_counter_createA_ptr 0 +#define __itt_counter_createW(name, domain) +#define __itt_counter_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_counter_create(name, domain) +#define __itt_counter_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_counter_createA_ptr 0 +#define __itt_counter_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_counter_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Destroy the counter identified by the pointer previously returned by __itt_counter_create() + */ +void ITTAPI __itt_counter_destroy(__itt_counter id); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, counter_destroy, (__itt_counter id)) +#define __itt_counter_destroy ITTNOTIFY_VOID(counter_destroy) +#define __itt_counter_destroy_ptr ITTNOTIFY_NAME(counter_destroy) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_counter_destroy(id) +#define __itt_counter_destroy_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_counter_destroy_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Increment the counter value + */ +void ITTAPI __itt_counter_inc(__itt_counter id); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, counter_inc, (__itt_counter id)) +#define __itt_counter_inc ITTNOTIFY_VOID(counter_inc) +#define __itt_counter_inc_ptr ITTNOTIFY_NAME(counter_inc) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_counter_inc(id) +#define __itt_counter_inc_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_counter_inc_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Increment the counter value with x + */ +void ITTAPI __itt_counter_inc_delta(__itt_counter id, unsigned long long value); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, counter_inc_delta, (__itt_counter id, unsigned long long value)) +#define __itt_counter_inc_delta ITTNOTIFY_VOID(counter_inc_delta) +#define __itt_counter_inc_delta_ptr ITTNOTIFY_NAME(counter_inc_delta) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_counter_inc_delta(id, value) +#define __itt_counter_inc_delta_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_counter_inc_delta_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} counters group */ + +/** + * @defgroup stitch Stack Stitching + * @ingroup internal + * Stack Stitching group + * @{ + */ +/** + * @brief opaque structure for counter identification + */ +typedef struct ___itt_caller *__itt_caller; + +/** + * @brief Create the stitch point e.g. a point in call stack where other stacks should be stitched to. + * The function returns a unique identifier which is used to match the cut points with corresponding stitch points. + */ +__itt_caller ITTAPI __itt_stack_caller_create(void); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUB(ITTAPI, __itt_caller, stack_caller_create, (void)) +#define __itt_stack_caller_create ITTNOTIFY_DATA(stack_caller_create) +#define __itt_stack_caller_create_ptr ITTNOTIFY_NAME(stack_caller_create) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_stack_caller_create() (__itt_caller)0 +#define __itt_stack_caller_create_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_stack_caller_create_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Destroy the inforamtion about stitch point identified by the pointer previously returned by __itt_stack_caller_create() + */ +void ITTAPI __itt_stack_caller_destroy(__itt_caller id); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, stack_caller_destroy, (__itt_caller id)) +#define __itt_stack_caller_destroy ITTNOTIFY_VOID(stack_caller_destroy) +#define __itt_stack_caller_destroy_ptr ITTNOTIFY_NAME(stack_caller_destroy) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_stack_caller_destroy(id) +#define __itt_stack_caller_destroy_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_stack_caller_destroy_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Sets the cut point. Stack from each event which occurs after this call will be cut + * at the same stack level the function was called and stitched to the corresponding stitch point. + */ +void ITTAPI __itt_stack_callee_enter(__itt_caller id); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, stack_callee_enter, (__itt_caller id)) +#define __itt_stack_callee_enter ITTNOTIFY_VOID(stack_callee_enter) +#define __itt_stack_callee_enter_ptr ITTNOTIFY_NAME(stack_callee_enter) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_stack_callee_enter(id) +#define __itt_stack_callee_enter_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_stack_callee_enter_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief This function eliminates the cut point which was set by latest __itt_stack_callee_enter(). + */ +void ITTAPI __itt_stack_callee_leave(__itt_caller id); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, stack_callee_leave, (__itt_caller id)) +#define __itt_stack_callee_leave ITTNOTIFY_VOID(stack_callee_leave) +#define __itt_stack_callee_leave_ptr ITTNOTIFY_NAME(stack_callee_leave) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_stack_callee_leave(id) +#define __itt_stack_callee_leave_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_stack_callee_leave_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** @} stitch group */ + +/* ***************************************************************************************************************************** */ + +#include <stdarg.h> + +/** @cond exclude_from_documentation */ +typedef enum __itt_error_code +{ + __itt_error_success = 0, /*!< no error */ + __itt_error_no_module = 1, /*!< module can't be loaded */ + /* %1$s -- library name; win: %2$d -- system error code; unx: %2$s -- system error message. */ + __itt_error_no_symbol = 2, /*!< symbol not found */ + /* %1$s -- library name, %2$s -- symbol name. */ + __itt_error_unknown_group = 3, /*!< unknown group specified */ + /* %1$s -- env var name, %2$s -- group name. */ + __itt_error_cant_read_env = 4, /*!< GetEnvironmentVariable() failed */ + /* %1$s -- env var name, %2$d -- system error. */ + __itt_error_env_too_long = 5, /*!< variable value too long */ + /* %1$s -- env var name, %2$d -- actual length of the var, %3$d -- max allowed length. */ + __itt_error_system = 6 /*!< pthread_mutexattr_init or pthread_mutex_init failed */ + /* %1$s -- function name, %2$d -- errno. */ +} __itt_error_code; + +typedef void (__itt_error_handler_t)(__itt_error_code code, va_list); +__itt_error_handler_t* __itt_set_error_handler(__itt_error_handler_t*); + +const char* ITTAPI __itt_api_version(void); +/** @endcond */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#define __itt_error_handler ITT_JOIN(INTEL_ITTNOTIFY_PREFIX, error_handler) +void __itt_error_handler(__itt_error_code code, va_list args); +extern const int ITTNOTIFY_NAME(err); +#define __itt_err ITTNOTIFY_NAME(err) +ITT_STUB(ITTAPI, const char*, api_version, (void)) +#define __itt_api_version ITTNOTIFY_DATA(api_version) +#define __itt_api_version_ptr ITTNOTIFY_NAME(api_version) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_api_version() (const char*)0 +#define __itt_api_version_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_api_version_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _ITTNOTIFY_PRIVATE_ */ + +#endif /* INTEL_ITTNOTIFY_API_PRIVATE */ diff --git a/src/tbb/src/tbb/tools_api/ittnotify_config.h b/src/tbb/src/tbb/tools_api/ittnotify_config.h new file mode 100644 index 0000000..fe1c1c6 --- /dev/null +++ b/src/tbb/src/tbb/tools_api/ittnotify_config.h @@ -0,0 +1,450 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _ITTNOTIFY_CONFIG_H_ +#define _ITTNOTIFY_CONFIG_H_ + +/** @cond exclude_from_documentation */ +#ifndef ITT_OS_WIN +# define ITT_OS_WIN 1 +#endif /* ITT_OS_WIN */ + +#ifndef ITT_OS_LINUX +# define ITT_OS_LINUX 2 +#endif /* ITT_OS_LINUX */ + +#ifndef ITT_OS_MAC +# define ITT_OS_MAC 3 +#endif /* ITT_OS_MAC */ + +#ifndef ITT_OS +# if defined WIN32 || defined _WIN32 +# define ITT_OS ITT_OS_WIN +# elif defined( __APPLE__ ) && defined( __MACH__ ) +# define ITT_OS ITT_OS_MAC +# else +# define ITT_OS ITT_OS_LINUX +# endif +#endif /* ITT_OS */ + +#ifndef ITT_PLATFORM_WIN +# define ITT_PLATFORM_WIN 1 +#endif /* ITT_PLATFORM_WIN */ + +#ifndef ITT_PLATFORM_POSIX +# define ITT_PLATFORM_POSIX 2 +#endif /* ITT_PLATFORM_POSIX */ + +#ifndef ITT_PLATFORM +# if ITT_OS==ITT_OS_WIN +# define ITT_PLATFORM ITT_PLATFORM_WIN +# else +# define ITT_PLATFORM ITT_PLATFORM_POSIX +# endif /* _WIN32 */ +#endif /* ITT_PLATFORM */ + +#if defined(_UNICODE) && !defined(UNICODE) +#define UNICODE +#endif + +#include <stddef.h> +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#include <tchar.h> +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#include <stdint.h> +#if defined(UNICODE) || defined(_UNICODE) +#include <wchar.h> +#endif /* UNICODE || _UNICODE */ +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +#ifndef CDECL +# if ITT_PLATFORM==ITT_PLATFORM_WIN +# define CDECL __cdecl +# else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +# if defined _M_X64 || defined _M_AMD64 || defined __x86_64__ +# define CDECL /* not actual on x86_64 platform */ +# else /* _M_X64 || _M_AMD64 || __x86_64__ */ +# define CDECL __attribute__ ((cdecl)) +# endif /* _M_X64 || _M_AMD64 || __x86_64__ */ +# endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* CDECL */ + +#ifndef STDCALL +# if ITT_PLATFORM==ITT_PLATFORM_WIN +# define STDCALL __stdcall +# else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +# if defined _M_X64 || defined _M_AMD64 || defined __x86_64__ +# define STDCALL /* not supported on x86_64 platform */ +# else /* _M_X64 || _M_AMD64 || __x86_64__ */ +# define STDCALL __attribute__ ((stdcall)) +# endif /* _M_X64 || _M_AMD64 || __x86_64__ */ +# endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* STDCALL */ + +#define ITTAPI CDECL +#define LIBITTAPI CDECL + +/* TODO: Temporary for compatibility! */ +#define ITTAPI_CALL CDECL +#define LIBITTAPI_CALL CDECL + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +/* use __forceinline (VC++ specific) */ +#define INLINE __forceinline +#define INLINE_ATTRIBUTE /* nothing */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +/* + * Generally, functions are not inlined unless optimization is specified. + * For functions declared inline, this attribute inlines the function even + * if no optimization level was specified. + */ +#ifdef __STRICT_ANSI__ +#define INLINE static +#else /* __STRICT_ANSI__ */ +#define INLINE static inline +#endif /* __STRICT_ANSI__ */ +#define INLINE_ATTRIBUTE __attribute__ ((always_inline)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +/** @endcond */ + +#ifndef ITT_ARCH_IA32 +# define ITT_ARCH_IA32 1 +#endif /* ITT_ARCH_IA32 */ + +#ifndef ITT_ARCH_IA32E +# define ITT_ARCH_IA32E 2 +#endif /* ITT_ARCH_IA32E */ + +#ifndef ITT_ARCH_IA64 +# define ITT_ARCH_IA64 3 +#endif /* ITT_ARCH_IA64 */ + +#ifndef ITT_ARCH +# if defined _M_X64 || defined _M_AMD64 || defined __x86_64__ +# define ITT_ARCH ITT_ARCH_IA32E +# elif defined _M_IA64 || defined __ia64 +# define ITT_ARCH ITT_ARCH_IA64 +# else +# define ITT_ARCH ITT_ARCH_IA32 +# endif +#endif + +#ifdef __cplusplus +# define ITT_EXTERN_C extern "C" +#else +# define ITT_EXTERN_C /* nothing */ +#endif /* __cplusplus */ + +#define ITT_TO_STR_AUX(x) #x +#define ITT_TO_STR(x) ITT_TO_STR_AUX(x) + +#define __ITT_BUILD_ASSERT(expr, suffix) do { static char __itt_build_check_##suffix[(expr) ? 1 : -1]; __itt_build_check_##suffix[0] = 0; } while(0) +#define _ITT_BUILD_ASSERT(expr, suffix) __ITT_BUILD_ASSERT((expr), suffix) +#define ITT_BUILD_ASSERT(expr) _ITT_BUILD_ASSERT((expr), __LINE__) + +#define ITT_MAGIC { 0xED, 0xAB, 0xAB, 0xEC, 0x0D, 0xEE, 0xDA, 0x30 } + +/* Replace with snapshot date YYYYMMDD for promotion build. */ +#define API_VERSION_BUILD 20111111 + +#ifndef API_VERSION_NUM +#define API_VERSION_NUM 0.0.0 +#endif /* API_VERSION_NUM */ + +#define API_VERSION "ITT-API-Version " ITT_TO_STR(API_VERSION_NUM) " (" ITT_TO_STR(API_VERSION_BUILD) ")" + +/* OS communication functions */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#include <windows.h> +typedef HMODULE lib_t; +typedef DWORD TIDT; +typedef CRITICAL_SECTION mutex_t; +#define MUTEX_INITIALIZER { 0 } +#define strong_alias(name, aliasname) /* empty for Windows */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#include <dlfcn.h> +#if defined(UNICODE) || defined(_UNICODE) +#include <wchar.h> +#endif /* UNICODE */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE 1 /* need for PTHREAD_MUTEX_RECURSIVE */ +#endif /* _GNU_SOURCE */ +#include <pthread.h> +typedef void* lib_t; +typedef pthread_t TIDT; +typedef pthread_mutex_t mutex_t; +#define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +#define _strong_alias(name, aliasname) extern __typeof (name) aliasname __attribute__ ((alias (#name))); +#define strong_alias(name, aliasname) _strong_alias(name, aliasname) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_get_proc(lib, name) GetProcAddress(lib, name) +#define __itt_mutex_init(mutex) InitializeCriticalSection(mutex) +#define __itt_mutex_lock(mutex) EnterCriticalSection(mutex) +#define __itt_mutex_unlock(mutex) LeaveCriticalSection(mutex) +#define __itt_load_lib(name) LoadLibraryA(name) +#define __itt_unload_lib(handle) FreeLibrary(handle) +#define __itt_system_error() (int)GetLastError() +#define __itt_fstrcmp(s1, s2) lstrcmpA(s1, s2) +#define __itt_fstrlen(s) lstrlenA(s) +#define __itt_fstrcpyn(s1, s2, l) lstrcpynA(s1, s2, l) +#define __itt_fstrdup(s) _strdup(s) +#define __itt_thread_id() GetCurrentThreadId() +#define __itt_thread_yield() SwitchToThread() +#ifndef ITT_SIMPLE_INIT +INLINE int __itt_interlocked_increment(volatile long* ptr) +{ + return InterlockedIncrement(ptr); +} +#endif /* ITT_SIMPLE_INIT */ +#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ +#define __itt_get_proc(lib, name) dlsym(lib, name) +#define __itt_mutex_init(mutex) \ + { \ + pthread_mutexattr_t mutex_attr; \ + int error_code = pthread_mutexattr_init(&mutex_attr); \ + if (error_code) \ + __itt_report_error(__itt_error_system, "pthread_mutexattr_init", error_code); \ + error_code = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE); \ + if (error_code) \ + __itt_report_error(__itt_error_system, "pthread_mutexattr_settype", error_code); \ + error_code = pthread_mutex_init(mutex, &mutex_attr); \ + if (error_code) \ + __itt_report_error(__itt_error_system, "pthread_mutex_init", error_code); \ + error_code = pthread_mutexattr_destroy(&mutex_attr); \ + if (error_code) \ + __itt_report_error(__itt_error_system, "pthread_mutexattr_destroy", error_code); \ + } +#define __itt_mutex_lock(mutex) pthread_mutex_lock(mutex) +#define __itt_mutex_unlock(mutex) pthread_mutex_unlock(mutex) +#define __itt_load_lib(name) dlopen(name, RTLD_LAZY) +#define __itt_unload_lib(handle) dlclose(handle) +#define __itt_system_error() errno +#define __itt_fstrcmp(s1, s2) strcmp(s1, s2) +#define __itt_fstrlen(s) strlen(s) +#define __itt_fstrcpyn(s1, s2, l) strncpy(s1, s2, l) +#define __itt_fstrdup(s) strdup(s) +#define __itt_thread_id() pthread_self() +#define __itt_thread_yield() sched_yield() +#if ITT_ARCH==ITT_ARCH_IA64 +#ifdef __INTEL_COMPILER +#define __TBB_machine_fetchadd4(addr, val) __fetchadd4_acq((void *)addr, val) +#else /* __INTEL_COMPILER */ +/* TODO: Add Support for not Intel compilers for IA64 */ +#endif /* __INTEL_COMPILER */ +#else /* ITT_ARCH!=ITT_ARCH_IA64 */ +INLINE int __TBB_machine_fetchadd4(volatile void* ptr, long addend) +{ + int result; + __asm__ __volatile__("lock\nxaddl %0,%1" + : "=r"(result),"=m"(*(long*)ptr) + : "0"(addend), "m"(*(long*)ptr) + : "memory"); + return result; +} +#endif /* ITT_ARCH==ITT_ARCH_IA64 */ + +#ifndef ITT_SIMPLE_INIT +INLINE int __itt_interlocked_increment(volatile long* ptr) +{ + return __TBB_machine_fetchadd4(ptr, 1) + 1; +} +#endif /* ITT_SIMPLE_INIT */ +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +typedef enum { + __itt_collection_normal = 0, + __itt_collection_paused = 1 +} __itt_collection_state; + +typedef enum { + __itt_thread_normal = 0, + __itt_thread_ignored = 1 +} __itt_thread_state; + +#pragma pack(push, 8) + +typedef struct ___itt_thread_info +{ + const char* nameA; /*!< Copy of original name in ASCII. */ +#if defined(UNICODE) || defined(_UNICODE) + const wchar_t* nameW; /*!< Copy of original name in UNICODE. */ +#else /* UNICODE || _UNICODE */ + void* nameW; +#endif /* UNICODE || _UNICODE */ + TIDT tid; + __itt_thread_state state; /*!< Thread state (paused or normal) */ + int extra1; /*!< Reserved to the runtime */ + void* extra2; /*!< Reserved to the runtime */ + struct ___itt_thread_info* next; +} __itt_thread_info; + +#include "ittnotify_types.h" /* For __itt_group_id definition */ + +typedef struct ___itt_api_info_20101001 +{ + const char* name; + void** func_ptr; + void* init_func; + __itt_group_id group; +} __itt_api_info_20101001; + +typedef struct ___itt_api_info +{ + const char* name; + void** func_ptr; + void* init_func; + void* null_func; + __itt_group_id group; +} __itt_api_info; + +struct ___itt_domain; +struct ___itt_string_handle; + +typedef struct ___itt_global +{ + unsigned char magic[8]; + unsigned long version_major; + unsigned long version_minor; + unsigned long version_build; + volatile long api_initialized; + volatile long mutex_initialized; + volatile long atomic_counter; + mutex_t mutex; + lib_t lib; + void* error_handler; + const char** dll_path_ptr; + __itt_api_info* api_list_ptr; + struct ___itt_global* next; + /* Joinable structures below */ + __itt_thread_info* thread_list; + struct ___itt_domain* domain_list; + struct ___itt_string_handle* string_list; + __itt_collection_state state; +} __itt_global; + +#pragma pack(pop) + +#define NEW_THREAD_INFO_W(gptr,h,h_tail,t,s,n) { \ + h = (__itt_thread_info*)malloc(sizeof(__itt_thread_info)); \ + if (h != NULL) { \ + h->tid = t; \ + h->nameA = NULL; \ + h->nameW = n ? _wcsdup(n) : NULL; \ + h->state = s; \ + h->extra1 = 0; /* reserved */ \ + h->extra2 = NULL; /* reserved */ \ + h->next = NULL; \ + if (h_tail == NULL) \ + (gptr)->thread_list = h; \ + else \ + h_tail->next = h; \ + } \ +} + +#define NEW_THREAD_INFO_A(gptr,h,h_tail,t,s,n) { \ + h = (__itt_thread_info*)malloc(sizeof(__itt_thread_info)); \ + if (h != NULL) { \ + h->tid = t; \ + h->nameA = n ? __itt_fstrdup(n) : NULL; \ + h->nameW = NULL; \ + h->state = s; \ + h->extra1 = 0; /* reserved */ \ + h->extra2 = NULL; /* reserved */ \ + h->next = NULL; \ + if (h_tail == NULL) \ + (gptr)->thread_list = h; \ + else \ + h_tail->next = h; \ + } \ +} + +#define NEW_DOMAIN_W(gptr,h,h_tail,name) { \ + h = (__itt_domain*)malloc(sizeof(__itt_domain)); \ + if (h != NULL) { \ + h->flags = 0; /* domain is disabled by default */ \ + h->nameA = NULL; \ + h->nameW = name ? _wcsdup(name) : NULL; \ + h->extra1 = 0; /* reserved */ \ + h->extra2 = NULL; /* reserved */ \ + h->next = NULL; \ + if (h_tail == NULL) \ + (gptr)->domain_list = h; \ + else \ + h_tail->next = h; \ + } \ +} + +#define NEW_DOMAIN_A(gptr,h,h_tail,name) { \ + h = (__itt_domain*)malloc(sizeof(__itt_domain)); \ + if (h != NULL) { \ + h->flags = 0; /* domain is disabled by default */ \ + h->nameA = name ? __itt_fstrdup(name) : NULL; \ + h->nameW = NULL; \ + h->extra1 = 0; /* reserved */ \ + h->extra2 = NULL; /* reserved */ \ + h->next = NULL; \ + if (h_tail == NULL) \ + (gptr)->domain_list = h; \ + else \ + h_tail->next = h; \ + } \ +} + +#define NEW_STRING_HANDLE_W(gptr,h,h_tail,name) { \ + h = (__itt_string_handle*)malloc(sizeof(__itt_string_handle)); \ + if (h != NULL) { \ + h->strA = NULL; \ + h->strW = name ? _wcsdup(name) : NULL; \ + h->extra1 = 0; /* reserved */ \ + h->extra2 = NULL; /* reserved */ \ + h->next = NULL; \ + if (h_tail == NULL) \ + (gptr)->string_list = h; \ + else \ + h_tail->next = h; \ + } \ +} + +#define NEW_STRING_HANDLE_A(gptr,h,h_tail,name) { \ + h = (__itt_string_handle*)malloc(sizeof(__itt_string_handle)); \ + if (h != NULL) { \ + h->strA = name ? __itt_fstrdup(name) : NULL; \ + h->strW = NULL; \ + h->extra1 = 0; /* reserved */ \ + h->extra2 = NULL; /* reserved */ \ + h->next = NULL; \ + if (h_tail == NULL) \ + (gptr)->string_list = h; \ + else \ + h_tail->next = h; \ + } \ +} + +#endif /* _ITTNOTIFY_CONFIG_H_ */ diff --git a/src/tbb/src/tbb/tools_api/ittnotify_static.c b/src/tbb/src/tbb/tools_api/ittnotify_static.c new file mode 100644 index 0000000..be55706 --- /dev/null +++ b/src/tbb/src/tbb/tools_api/ittnotify_static.c @@ -0,0 +1,1015 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "ittnotify_config.h" + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define PATH_MAX 512 +#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ +#include <limits.h> +#include <dlfcn.h> +#include <errno.h> +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> + +#define INTEL_NO_MACRO_BODY +#define INTEL_ITTNOTIFY_API_PRIVATE +#include "ittnotify.h" +#include "legacy/ittnotify.h" + +#include "disable_warnings.h" + +static const char api_version[] = API_VERSION "\0\n@(#) 201495 2011-12-01 14:14:56Z\n"; + +#define _N_(n) ITT_JOIN(INTEL_ITTNOTIFY_PREFIX,n) + +#if ITT_OS==ITT_OS_WIN +static const char* ittnotify_lib_name = "libittnotify.dll"; +#elif ITT_OS==ITT_OS_LINUX +static const char* ittnotify_lib_name = "libittnotify.so"; +#elif ITT_OS==ITT_OS_MAC +static const char* ittnotify_lib_name = "libittnotify.dylib"; +#else +#error Unsupported or unknown OS. +#endif + +#ifndef LIB_VAR_NAME +#if ITT_ARCH==ITT_ARCH_IA32 +#define LIB_VAR_NAME INTEL_LIBITTNOTIFY32 +#else +#define LIB_VAR_NAME INTEL_LIBITTNOTIFY64 +#endif +#endif /* LIB_VAR_NAME */ + +#define ITT_MUTEX_INIT_AND_LOCK(p) { \ + if (!p.mutex_initialized) \ + { \ + if (__itt_interlocked_increment(&p.atomic_counter) == 1) \ + { \ + __itt_mutex_init(&p.mutex); \ + p.mutex_initialized = 1; \ + } \ + else \ + while (!p.mutex_initialized) \ + __itt_thread_yield(); \ + } \ + __itt_mutex_lock(&p.mutex); \ +} + +const int _N_(err) = 0; + +typedef int (__itt_init_ittlib_t)(const char*, __itt_group_id); + +/* this define used to control initialization function name. */ +#ifndef __itt_init_ittlib_name +ITT_EXTERN_C int _N_(init_ittlib)(const char*, __itt_group_id); +static __itt_init_ittlib_t* __itt_init_ittlib_ptr = _N_(init_ittlib); +#define __itt_init_ittlib_name __itt_init_ittlib_ptr +#endif /* __itt_init_ittlib_name */ + +typedef void (__itt_fini_ittlib_t)(void); + +/* this define used to control finalization function name. */ +#ifndef __itt_fini_ittlib_name +ITT_EXTERN_C void _N_(fini_ittlib)(void); +static __itt_fini_ittlib_t* __itt_fini_ittlib_ptr = _N_(fini_ittlib); +#define __itt_fini_ittlib_name __itt_fini_ittlib_ptr +#endif /* __itt_fini_ittlib_name */ + +/* building pointers to imported funcs */ +#undef ITT_STUBV +#undef ITT_STUB +#define ITT_STUB(api,type,name,args,params,ptr,group,format) \ +static type api ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)) args;\ +typedef type api ITT_JOIN(_N_(name),_t) args; \ +ITT_EXTERN_C { ITT_JOIN(_N_(name),_t)* ITTNOTIFY_NAME(name) = ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)); } \ +static type api ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)) args \ +{ \ + __itt_init_ittlib_name(NULL, __itt_group_all); \ + if (ITTNOTIFY_NAME(name) && ITTNOTIFY_NAME(name) != ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init))) \ + return ITTNOTIFY_NAME(name) params; \ + else \ + return (type)0; \ +} + +#define ITT_STUBV(api,type,name,args,params,ptr,group,format) \ +static type api ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)) args;\ +typedef type api ITT_JOIN(_N_(name),_t) args; \ +ITT_EXTERN_C { \ +ITT_JOIN(_N_(name),_t)* ITTNOTIFY_NAME(name) = ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)); } \ +static type api ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)) args \ +{ \ + __itt_init_ittlib_name(NULL, __itt_group_all); \ + if (ITTNOTIFY_NAME(name) && ITTNOTIFY_NAME(name) != ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init))) \ + ITTNOTIFY_NAME(name) params; \ + else \ + return; \ +} + +#undef __ITT_INTERNAL_INIT +#include "ittnotify_static.h" + +#undef ITT_STUB +#undef ITT_STUBV +#define ITT_STUB(api,type,name,args,params,ptr,group,format) \ +static type api ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)) args;\ +typedef type api ITT_JOIN(_N_(name),_t) args; \ +ITT_EXTERN_C { \ +ITT_JOIN(_N_(name),_t)* ITTNOTIFY_NAME(name) = ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)); } + +#define ITT_STUBV(api,type,name,args,params,ptr,group,format) \ +static type api ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)) args;\ +typedef type api ITT_JOIN(_N_(name),_t) args; \ +ITT_EXTERN_C { ITT_JOIN(_N_(name),_t)* ITTNOTIFY_NAME(name) = ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)); } + +#define __ITT_INTERNAL_INIT +#include "ittnotify_static.h" +#undef __ITT_INTERNAL_INIT + +ITT_GROUP_LIST(group_list); + +#pragma pack(push, 8) + +typedef struct ___itt_group_alias +{ + const char* env_var; + __itt_group_id groups; +} __itt_group_alias; + +static __itt_group_alias group_alias[] = { + { "KMP_FOR_TPROFILE", (__itt_group_id)(__itt_group_control | __itt_group_thread | __itt_group_sync | __itt_group_mark) }, + { "KMP_FOR_TCHECK", (__itt_group_id)(__itt_group_control | __itt_group_thread | __itt_group_sync | __itt_group_fsync | __itt_group_mark) }, + { NULL, (__itt_group_none) }, + { api_version, (__itt_group_none) } /* !!! Just to avoid unused code elimination !!! */ +}; + +#pragma pack(pop) + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#pragma warning(push) +#pragma warning(disable: 4054) /* warning C4054: 'type cast' : from function pointer 'XXX' to data pointer 'void *' */ +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +static __itt_api_info api_list[] = { +/* Define functions with static implementation */ +#undef ITT_STUB +#undef ITT_STUBV +#define ITT_STUB(api,type,name,args,params,nameindll,group,format) {ITT_TO_STR(ITT_JOIN(__itt_,nameindll)), (void**)(void*)&ITTNOTIFY_NAME(name), (void*)&ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)), (void*)&ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)), (__itt_group_id)(group)}, +#define ITT_STUBV ITT_STUB +#define __ITT_INTERNAL_INIT +#include "ittnotify_static.h" +#undef __ITT_INTERNAL_INIT +/* Define functions without static implementation */ +#undef ITT_STUB +#undef ITT_STUBV +#define ITT_STUB(api,type,name,args,params,nameindll,group,format) {ITT_TO_STR(ITT_JOIN(__itt_,nameindll)), (void**)(void*)&ITTNOTIFY_NAME(name), (void*)&ITT_VERSIONIZE(ITT_JOIN(_N_(name),_init)), NULL, (__itt_group_id)(group)}, +#define ITT_STUBV ITT_STUB +#include "ittnotify_static.h" + {NULL, NULL, NULL, NULL, __itt_group_none} +}; + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#pragma warning(pop) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/* private, init thread info item. used for internal purposes */ +static __itt_thread_info init_thread_info = { + (const char*)NULL, /* nameA */ +#if defined(UNICODE) || defined(_UNICODE) + (const wchar_t*)NULL, /* nameW */ +#else + (void*)NULL, /* nameW */ +#endif + 0, /* tid */ + __itt_thread_normal, /* state */ + 0, /* extra1 */ + (void*)NULL, /* extra2 */ + (__itt_thread_info*)NULL /* next */ +}; + +/* private, NULL domain item. used for internal purposes */ +static __itt_domain null_domain = { + 0, /* flags: disabled by default */ + (const char*)NULL, /* nameA */ +#if defined(UNICODE) || defined(_UNICODE) + (const wchar_t*)NULL, /* nameW */ +#else + (void*)NULL, /* nameW */ +#endif + 0, /* extra1 */ + (void*)NULL, /* extra2 */ + (__itt_domain*)NULL /* next */ +}; + +/* private, NULL string handle item. used for internal purposes */ +static __itt_string_handle null_string_handle = { + (const char*)NULL, /* strA */ +#if defined(UNICODE) || defined(_UNICODE) + (const wchar_t*)NULL, /* strW */ +#else + (void*)NULL, /* strW */ +#endif + 0, /* extra1 */ + (void*)NULL, /* extra2 */ + (__itt_string_handle*)NULL /* next */ +}; + +static const char dll_path[PATH_MAX] = { 0 }; + +/* static part descriptor which handles. all notification api attributes. */ +__itt_global __itt_ittapi_global = { + ITT_MAGIC, /* identification info */ + ITT_MAJOR, ITT_MINOR, API_VERSION_BUILD, /* version info */ + 0, /* api_initialized */ + 0, /* mutex_initialized */ + 0, /* atomic_counter */ + MUTEX_INITIALIZER, /* mutex */ + NULL, /* dynamic library handle */ + NULL, /* error_handler */ + (const char**)&dll_path, /* dll_path_ptr */ + (__itt_api_info*)&api_list, /* api_list_ptr */ + NULL, /* next __itt_global */ + (__itt_thread_info*)&init_thread_info, /* thread_list */ + (__itt_domain*)&null_domain, /* domain_list */ + (__itt_string_handle*)&null_string_handle, /* string_list */ + __itt_collection_normal /* collection state */ +}; + +typedef void (__itt_api_init_t)(__itt_global*, __itt_group_id); +typedef void (__itt_api_fini_t)(__itt_global*); + +/* ========================================================================= */ + +#ifdef ITT_NOTIFY_EXT_REPORT +ITT_EXTERN_C void _N_(error_handler)(__itt_error_code, va_list args); +#endif /* ITT_NOTIFY_EXT_REPORT */ + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#pragma warning(push) +#pragma warning(disable: 4055) /* warning C4055: 'type cast' : from data pointer 'void *' to function pointer 'XXX' */ +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +static void __itt_report_error(__itt_error_code code, ...) +{ + va_list args; + va_start(args, code); + if (__itt_ittapi_global.error_handler != NULL) + { + __itt_error_handler_t* handler = (__itt_error_handler_t*)__itt_ittapi_global.error_handler; + handler(code, args); + } +#ifdef ITT_NOTIFY_EXT_REPORT + _N_(error_handler)(code, args); +#endif /* ITT_NOTIFY_EXT_REPORT */ + va_end(args); +} + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#pragma warning(pop) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +static __itt_domain* ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(domain_createW),_init))(const wchar_t* name) +{ + __itt_domain *h_tail, *h; + + if (!__itt_ittapi_global.api_initialized && __itt_ittapi_global.thread_list->tid == 0) + { + __itt_init_ittlib_name(NULL, __itt_group_all); + if (ITTNOTIFY_NAME(domain_createW) && ITTNOTIFY_NAME(domain_createW) != ITT_VERSIONIZE(ITT_JOIN(_N_(domain_createW),_init))) + return ITTNOTIFY_NAME(domain_createW)(name); + } + + if (name == NULL) + return __itt_ittapi_global.domain_list; + + ITT_MUTEX_INIT_AND_LOCK(__itt_ittapi_global); + for (h_tail = NULL, h = __itt_ittapi_global.domain_list; h != NULL; h_tail = h, h = h->next) + if (h->nameW != NULL && !wcscmp(h->nameW, name)) + break; + if (h == NULL) { + NEW_DOMAIN_W(&__itt_ittapi_global,h,h_tail,name); + } + __itt_mutex_unlock(&__itt_ittapi_global.mutex); + return h; +} + +static __itt_domain* ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(domain_createA),_init))(const char* name) +#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ +static __itt_domain* ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(domain_create),_init))(const char* name) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +{ + __itt_domain *h_tail, *h; + + if (!__itt_ittapi_global.api_initialized && __itt_ittapi_global.thread_list->tid == 0) + { + __itt_init_ittlib_name(NULL, __itt_group_all); +#if ITT_PLATFORM==ITT_PLATFORM_WIN + if (ITTNOTIFY_NAME(domain_createA) && ITTNOTIFY_NAME(domain_createA) != ITT_VERSIONIZE(ITT_JOIN(_N_(domain_createA),_init))) + return ITTNOTIFY_NAME(domain_createA)(name); +#else + if (ITTNOTIFY_NAME(domain_create) && ITTNOTIFY_NAME(domain_create) != ITT_VERSIONIZE(ITT_JOIN(_N_(domain_create),_init))) + return ITTNOTIFY_NAME(domain_create)(name); +#endif + } + + if (name == NULL) + return __itt_ittapi_global.domain_list; + + ITT_MUTEX_INIT_AND_LOCK(__itt_ittapi_global); + for (h_tail = NULL, h = __itt_ittapi_global.domain_list; h != NULL; h_tail = h, h = h->next) + if (h->nameA != NULL && !__itt_fstrcmp(h->nameA, name)) + break; + if (h == NULL) { + NEW_DOMAIN_A(&__itt_ittapi_global,h,h_tail,name); + } + __itt_mutex_unlock(&__itt_ittapi_global.mutex); + return h; +} + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +static __itt_string_handle* ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(string_handle_createW),_init))(const wchar_t* name) +{ + __itt_string_handle *h_tail, *h; + + if (!__itt_ittapi_global.api_initialized && __itt_ittapi_global.thread_list->tid == 0) + { + __itt_init_ittlib_name(NULL, __itt_group_all); + if (ITTNOTIFY_NAME(string_handle_createW) && ITTNOTIFY_NAME(string_handle_createW) != ITT_VERSIONIZE(ITT_JOIN(_N_(string_handle_createW),_init))) + return ITTNOTIFY_NAME(string_handle_createW)(name); + } + + if (name == NULL) + return __itt_ittapi_global.string_list; + + ITT_MUTEX_INIT_AND_LOCK(__itt_ittapi_global); + for (h_tail = NULL, h = __itt_ittapi_global.string_list; h != NULL; h_tail = h, h = h->next) + if (h->strW != NULL && !wcscmp(h->strW, name)) + break; + if (h == NULL) { + NEW_STRING_HANDLE_W(&__itt_ittapi_global,h,h_tail,name); + } + __itt_mutex_unlock(&__itt_ittapi_global.mutex); + return h; +} + +static __itt_string_handle* ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(string_handle_createA),_init))(const char* name) +#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ +static __itt_string_handle* ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(string_handle_create),_init))(const char* name) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +{ + __itt_string_handle *h_tail, *h; + + if (!__itt_ittapi_global.api_initialized && __itt_ittapi_global.thread_list->tid == 0) + { + __itt_init_ittlib_name(NULL, __itt_group_all); +#if ITT_PLATFORM==ITT_PLATFORM_WIN + if (ITTNOTIFY_NAME(string_handle_createA) && ITTNOTIFY_NAME(string_handle_createA) != ITT_VERSIONIZE(ITT_JOIN(_N_(string_handle_createA),_init))) + return ITTNOTIFY_NAME(string_handle_createA)(name); +#else + if (ITTNOTIFY_NAME(string_handle_create) && ITTNOTIFY_NAME(string_handle_create) != ITT_VERSIONIZE(ITT_JOIN(_N_(string_handle_create),_init))) + return ITTNOTIFY_NAME(string_handle_create)(name); +#endif + } + + if (name == NULL) + return __itt_ittapi_global.string_list; + + ITT_MUTEX_INIT_AND_LOCK(__itt_ittapi_global); + for (h_tail = NULL, h = __itt_ittapi_global.string_list; h != NULL; h_tail = h, h = h->next) + if (h->strA != NULL && !__itt_fstrcmp(h->strA, name)) + break; + if (h == NULL) { + NEW_STRING_HANDLE_A(&__itt_ittapi_global,h,h_tail,name); + } + __itt_mutex_unlock(&__itt_ittapi_global.mutex); + return h; +} + +/* -------------------------------------------------------------------------- */ + +static void ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(pause),_init))(void) +{ + if (!__itt_ittapi_global.api_initialized && __itt_ittapi_global.thread_list->tid == 0) + { + __itt_init_ittlib_name(NULL, __itt_group_all); + if (ITTNOTIFY_NAME(pause) && ITTNOTIFY_NAME(pause) != ITT_VERSIONIZE(ITT_JOIN(_N_(pause),_init))) + { + ITTNOTIFY_NAME(pause)(); + return; + } + } + __itt_ittapi_global.state = __itt_collection_paused; +} + +static void ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(resume),_init))(void) +{ + if (!__itt_ittapi_global.api_initialized && __itt_ittapi_global.thread_list->tid == 0) + { + __itt_init_ittlib_name(NULL, __itt_group_all); + if (ITTNOTIFY_NAME(resume) && ITTNOTIFY_NAME(resume) != ITT_VERSIONIZE(ITT_JOIN(_N_(resume),_init))) + { + ITTNOTIFY_NAME(resume)(); + return; + } + } + __itt_ittapi_global.state = __itt_collection_normal; +} + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +static void ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(thread_set_nameW),_init))(const wchar_t* name) +{ + TIDT tid = __itt_thread_id(); + __itt_thread_info *h_tail, *h; + + if (!__itt_ittapi_global.api_initialized && __itt_ittapi_global.thread_list->tid == 0) + { + __itt_init_ittlib_name(NULL, __itt_group_all); + if (ITTNOTIFY_NAME(thread_set_nameW) && ITTNOTIFY_NAME(thread_set_nameW) != ITT_VERSIONIZE(ITT_JOIN(_N_(thread_set_nameW),_init))) + { + ITTNOTIFY_NAME(thread_set_nameW)(name); + return; + } + } + + __itt_mutex_lock(&__itt_ittapi_global.mutex); + for (h_tail = NULL, h = __itt_ittapi_global.thread_list; h != NULL; h_tail = h, h = h->next) + if (h->tid == tid) + break; + if (h == NULL) { + NEW_THREAD_INFO_W(&__itt_ittapi_global, h, h_tail, tid, __itt_thread_normal, name); + } + else + { + h->nameW = name ? _wcsdup(name) : NULL; + } + __itt_mutex_unlock(&__itt_ittapi_global.mutex); +} + +static int ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(thr_name_setW),_init))(const wchar_t* name, int namelen) +{ + namelen = namelen; + ITT_VERSIONIZE(ITT_JOIN(_N_(thread_set_nameW),_init))(name); + return 0; +} + +static void ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(thread_set_nameA),_init))(const char* name) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +static void ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(thread_set_name),_init))(const char* name) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +{ + TIDT tid = __itt_thread_id(); + __itt_thread_info *h_tail, *h; + + if (!__itt_ittapi_global.api_initialized && __itt_ittapi_global.thread_list->tid == 0) + { + __itt_init_ittlib_name(NULL, __itt_group_all); +#if ITT_PLATFORM==ITT_PLATFORM_WIN + if (ITTNOTIFY_NAME(thread_set_nameA) && ITTNOTIFY_NAME(thread_set_nameA) != ITT_VERSIONIZE(ITT_JOIN(_N_(thread_set_nameA),_init))) + { + ITTNOTIFY_NAME(thread_set_nameA)(name); + return; + } +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + if (ITTNOTIFY_NAME(thread_set_name) && ITTNOTIFY_NAME(thread_set_name) != ITT_VERSIONIZE(ITT_JOIN(_N_(thread_set_name),_init))) + { + ITTNOTIFY_NAME(thread_set_name)(name); + return; + } +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + } + + __itt_mutex_lock(&__itt_ittapi_global.mutex); + for (h_tail = NULL, h = __itt_ittapi_global.thread_list; h != NULL; h_tail = h, h = h->next) + if (h->tid == tid) + break; + if (h == NULL) { + NEW_THREAD_INFO_A(&__itt_ittapi_global, h, h_tail, tid, __itt_thread_normal, name); + } + else + { + h->nameA = name ? __itt_fstrdup(name) : NULL; + } + __itt_mutex_unlock(&__itt_ittapi_global.mutex); +} + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +static int ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(thr_name_setA),_init))(const char* name, int namelen) +{ + namelen = namelen; + ITT_VERSIONIZE(ITT_JOIN(_N_(thread_set_nameA),_init))(name); + return 0; +} +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +static int ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(thr_name_set),_init))(const char* name, int namelen) +{ + namelen = namelen; + ITT_VERSIONIZE(ITT_JOIN(_N_(thread_set_name),_init))(name); + return 0; +} +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +static void ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(thread_ignore),_init))(void) +{ + TIDT tid = __itt_thread_id(); + __itt_thread_info *h_tail, *h; + + if (!__itt_ittapi_global.api_initialized && __itt_ittapi_global.thread_list->tid == 0) + { + __itt_init_ittlib_name(NULL, __itt_group_all); + if (ITTNOTIFY_NAME(thread_ignore) && ITTNOTIFY_NAME(thread_ignore) != ITT_VERSIONIZE(ITT_JOIN(_N_(thread_ignore),_init))) + { + ITTNOTIFY_NAME(thread_ignore)(); + return; + } + } + + __itt_mutex_lock(&__itt_ittapi_global.mutex); + for (h_tail = NULL, h = __itt_ittapi_global.thread_list; h != NULL; h_tail = h, h = h->next) + if (h->tid == tid) + break; + if (h == NULL) { + static const char* name = "unknown"; + NEW_THREAD_INFO_A(&__itt_ittapi_global, h, h_tail, tid, __itt_thread_ignored, name); + } + else + { + h->state = __itt_thread_ignored; + } + __itt_mutex_unlock(&__itt_ittapi_global.mutex); +} + +static void ITTAPI ITT_VERSIONIZE(ITT_JOIN(_N_(thr_ignore),_init))(void) +{ + ITT_VERSIONIZE(ITT_JOIN(_N_(thread_ignore),_init))(); +} + +/* -------------------------------------------------------------------------- */ + +static const char* __itt_fsplit(const char* s, const char* sep, const char** out, int* len) +{ + int i; + int j; + + if (!s || !sep || !out || !len) + return NULL; + + for (i = 0; s[i]; i++) + { + int b = 0; + for (j = 0; sep[j]; j++) + if (s[i] == sep[j]) + { + b = 1; + break; + } + if (!b) + break; + } + + if (!s[i]) + return NULL; + + *len = 0; + *out = &s[i]; + + for (; s[i]; i++, (*len)++) + { + int b = 0; + for (j = 0; sep[j]; j++) + if (s[i] == sep[j]) + { + b = 1; + break; + } + if (b) + break; + } + + for (; s[i]; i++) + { + int b = 0; + for (j = 0; sep[j]; j++) + if (s[i] == sep[j]) + { + b = 1; + break; + } + if (!b) + break; + } + + return &s[i]; +} + +/* This function return value of env variable that placed into static buffer. + * !!! The same static buffer is used for subsequent calls. !!! + * This was done to aviod dynamic allocation for few calls. + * Actually we need this function only four times. + */ +static const char* __itt_get_env_var(const char* name) +{ +#define MAX_ENV_VALUE_SIZE 4086 + static char env_buff[MAX_ENV_VALUE_SIZE]; + static char* env_value = (char*)env_buff; + + if (name != NULL) + { +#if ITT_PLATFORM==ITT_PLATFORM_WIN + size_t max_len = MAX_ENV_VALUE_SIZE - (size_t)(env_value - env_buff); + DWORD rc = GetEnvironmentVariableA(name, env_value, (DWORD)max_len); + if (rc >= max_len) + __itt_report_error(__itt_error_env_too_long, name, (size_t)rc - 1, (size_t)(max_len - 1)); + else if (rc > 0) + { + const char* ret = (const char*)env_value; + env_value += rc + 1; + return ret; + } + else + { + /* If environment variable is empty, GetEnvirornmentVariables() + * returns zero (number of characters (not including terminating null), + * and GetLastError() returns ERROR_SUCCESS. */ + DWORD err = GetLastError(); + if (err == ERROR_SUCCESS) + return env_value; + + if (err != ERROR_ENVVAR_NOT_FOUND) + __itt_report_error(__itt_error_cant_read_env, name, (int)err); + } +#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ + char* env = getenv(name); + if (env != NULL) + { + size_t len = strlen(env); + size_t max_len = MAX_ENV_VALUE_SIZE - (size_t)(env_value - env_buff); + if (len < max_len) + { + const char* ret = (const char*)env_value; + strncpy(env_value, env, len + 1); + env_value += len + 1; + return ret; + } else + __itt_report_error(__itt_error_env_too_long, name, (size_t)len, (size_t)(max_len - 1)); + } +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + } + return NULL; +} + +#if ITT_PLATFORM==ITT_PLATFORM_WIN + +#include <Winreg.h> + +typedef LONG (APIENTRY* RegCloseKeyProcType)(HKEY); +typedef LONG (APIENTRY* RegOpenKeyExAProcType)(HKEY, LPCTSTR, DWORD, REGSAM, PHKEY); +typedef LONG (APIENTRY* RegGetValueAProcType)(HKEY, LPCTSTR, LPCTSTR, DWORD, LPDWORD, PVOID, LPDWORD); + +/* This function return value of registry key that placed into static buffer. + * This was done to aviod dynamic memory allocation. + */ +static const char* __itt_get_lib_name_registry(void) +{ +#define MAX_REG_VALUE_SIZE 4086 + static char reg_buff[MAX_REG_VALUE_SIZE]; + DWORD size; + LONG res; + HKEY hKey; + RegCloseKeyProcType pRegCloseKey; + RegOpenKeyExAProcType pRegOpenKeyExA; + RegGetValueAProcType pRegGetValueA; + HMODULE h_advapi32 = LoadLibraryA("advapi32.dll"); + DWORD autodetect = 0; + + if (h_advapi32 == NULL) + { + return NULL; + } + + pRegCloseKey = (RegCloseKeyProcType)GetProcAddress(h_advapi32, "CloseKey"); + pRegOpenKeyExA = (RegOpenKeyExAProcType)GetProcAddress(h_advapi32, "RegOpenKeyExA"); + pRegGetValueA = (RegGetValueAProcType)GetProcAddress(h_advapi32, "RegGetValueA"); + + if (pRegCloseKey == NULL || + pRegOpenKeyExA == NULL || + pRegGetValueA == NULL) + { + FreeLibrary(h_advapi32); + return NULL; + } + + res = pRegOpenKeyExA(HKEY_CURRENT_USER, (LPCTSTR)"Software\\Intel Corporation\\ITT Environment\\Collector", 0, KEY_READ, &hKey); + if (res != ERROR_SUCCESS || hKey == 0) + { + FreeLibrary(h_advapi32); + return NULL; + } + + size = sizeof(DWORD); + res = pRegGetValueA(hKey, (LPCTSTR)"AutoDetect", NULL, RRF_RT_REG_DWORD, NULL, (BYTE*)&autodetect, &size); + if (res != ERROR_SUCCESS || size == 0 || autodetect == 0) + { + pRegCloseKey(hKey); + FreeLibrary(h_advapi32); + return NULL; + } + + size = MAX_REG_VALUE_SIZE-1; + res = pRegGetValueA(hKey, (LPCTSTR)ITT_TO_STR(LIB_VAR_NAME), NULL, REG_SZ, NULL, (BYTE*)®_buff, &size); + pRegCloseKey(hKey); + FreeLibrary(h_advapi32); + + return (res == ERROR_SUCCESS && size > 0) ? reg_buff : NULL; +} + +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +static const char* __itt_get_lib_name(void) +{ + const char* lib_name = __itt_get_env_var(ITT_TO_STR(LIB_VAR_NAME)); +#if ITT_PLATFORM==ITT_PLATFORM_WIN + if (lib_name == NULL) + lib_name = __itt_get_lib_name_registry(); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + return lib_name; +} + +#ifndef min +#define min(a,b) (a) < (b) ? (a) : (b) +#endif /* min */ + +static __itt_group_id __itt_get_groups(void) +{ + register int i; + __itt_group_id res = __itt_group_none; + const char* var_name = "INTEL_ITTNOTIFY_GROUPS"; + const char* group_str = __itt_get_env_var(var_name); + + if (group_str != NULL) + { + int len; + char gr[255]; + const char* chunk; + while ((group_str = __itt_fsplit(group_str, ",; ", &chunk, &len)) != NULL) + { + __itt_fstrcpyn(gr, chunk, sizeof(gr)); + + gr[min((unsigned)len, sizeof(gr) - 1)] = 0; + + for (i = 0; group_list[i].name != NULL; i++) + { + if (!__itt_fstrcmp(gr, group_list[i].name)) + { + res = (__itt_group_id)(res | group_list[i].id); + break; + } + } + } + /* TODO: !!! Workaround for bug with warning for unknown group !!! + * Should be fixed in new initialization scheme. + * Now the following groups should be set always. */ + for (i = 0; group_list[i].id != __itt_group_none; i++) + if (group_list[i].id != __itt_group_all && + group_list[i].id > __itt_group_splitter_min && + group_list[i].id < __itt_group_splitter_max) + res = (__itt_group_id)(res | group_list[i].id); + return res; + } + else + { + for (i = 0; group_alias[i].env_var != NULL; i++) + if (__itt_get_env_var(group_alias[i].env_var) != NULL) + return group_alias[i].groups; + } + + return res; +} + +static int __itt_lib_version(lib_t lib) +{ + if (lib == NULL) + return 0; + if (__itt_get_proc(lib, "__itt_api_init")) + return 2; + if (__itt_get_proc(lib, "__itt_api_version")) + return 1; + return 0; +} + +/* It's not used right now! Comment it out to avoid warnings. +static void __itt_reinit_all_pointers(void) +{ + register int i; + // Fill all pointers with initial stubs + for (i = 0; __itt_ittapi_global.api_list_ptr[i].name != NULL; i++) + *__itt_ittapi_global.api_list_ptr[i].func_ptr = __itt_ittapi_global.api_list_ptr[i].init_func; +} +*/ + +static void __itt_nullify_all_pointers(void) +{ + register int i; + /* Nulify all pointers except domain_create and string_handle_create */ + for (i = 0; __itt_ittapi_global.api_list_ptr[i].name != NULL; i++) + *__itt_ittapi_global.api_list_ptr[i].func_ptr = __itt_ittapi_global.api_list_ptr[i].null_func; +} + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#pragma warning(push) +#pragma warning(disable: 4054) /* warning C4054: 'type cast' : from function pointer 'XXX' to data pointer 'void *' */ +#pragma warning(disable: 4055) /* warning C4055: 'type cast' : from data pointer 'void *' to function pointer 'XXX' */ +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +ITT_EXTERN_C void _N_(fini_ittlib)(void) +{ + __itt_api_fini_t* __itt_api_fini_ptr; + static volatile TIDT current_thread = 0; + + if (__itt_ittapi_global.api_initialized) + { + __itt_mutex_lock(&__itt_ittapi_global.mutex); + if (__itt_ittapi_global.api_initialized) + { + if (current_thread == 0) + { + current_thread = __itt_thread_id(); + __itt_api_fini_ptr = (__itt_api_fini_t*)__itt_get_proc(__itt_ittapi_global.lib, "__itt_api_fini"); + if (__itt_api_fini_ptr) + __itt_api_fini_ptr(&__itt_ittapi_global); + + __itt_nullify_all_pointers(); + + /* TODO: !!! not safe !!! don't support unload so far. + * if (__itt_ittapi_global.lib != NULL) + * __itt_unload_lib(__itt_ittapi_global.lib); + * __itt_ittapi_global.lib = NULL; + */ + __itt_ittapi_global.api_initialized = 0; + current_thread = 0; + } + } + __itt_mutex_unlock(&__itt_ittapi_global.mutex); + } +} + +ITT_EXTERN_C int _N_(init_ittlib)(const char* lib_name, __itt_group_id init_groups) +{ + register int i; + __itt_group_id groups; +#ifdef ITT_COMPLETE_GROUP + __itt_group_id zero_group = __itt_group_none; +#endif /* ITT_COMPLETE_GROUP */ + static volatile TIDT current_thread = 0; + + if (!__itt_ittapi_global.api_initialized) + { +#ifndef ITT_SIMPLE_INIT + ITT_MUTEX_INIT_AND_LOCK(__itt_ittapi_global); +#endif /* ITT_SIMPLE_INIT */ + + if (!__itt_ittapi_global.api_initialized) + { + if (current_thread == 0) + { + current_thread = __itt_thread_id(); + __itt_ittapi_global.thread_list->tid = current_thread; + if (lib_name == NULL) + lib_name = __itt_get_lib_name(); + groups = __itt_get_groups(); + if (groups != __itt_group_none || lib_name != NULL) + { + __itt_ittapi_global.lib = __itt_load_lib((lib_name == NULL) ? ittnotify_lib_name : lib_name); + if (__itt_ittapi_global.lib != NULL) + { + __itt_api_init_t* __itt_api_init_ptr; + int lib_version = __itt_lib_version(__itt_ittapi_global.lib); + + switch (lib_version) { + case 0: + groups = __itt_group_legacy; + case 1: + /* Fill all pointers from dynamic library */ + for (i = 0; __itt_ittapi_global.api_list_ptr[i].name != NULL; i++) + { + if (__itt_ittapi_global.api_list_ptr[i].group & groups & init_groups) + { + *__itt_ittapi_global.api_list_ptr[i].func_ptr = (void*)__itt_get_proc(__itt_ittapi_global.lib, __itt_ittapi_global.api_list_ptr[i].name); + if (*__itt_ittapi_global.api_list_ptr[i].func_ptr == NULL) + { + /* Restore pointers for function with static implementation */ + *__itt_ittapi_global.api_list_ptr[i].func_ptr = __itt_ittapi_global.api_list_ptr[i].null_func; + __itt_report_error(__itt_error_no_symbol, lib_name, __itt_ittapi_global.api_list_ptr[i].name); +#ifdef ITT_COMPLETE_GROUP + zero_group = (__itt_group_id)(zero_group | __itt_ittapi_global.api_list_ptr[i].group); +#endif /* ITT_COMPLETE_GROUP */ + } + } + else + *__itt_ittapi_global.api_list_ptr[i].func_ptr = __itt_ittapi_global.api_list_ptr[i].null_func; + } + + if (groups == __itt_group_legacy) + { + /* Compatibility with legacy tools */ + ITTNOTIFY_NAME(thread_ignore) = ITTNOTIFY_NAME(thr_ignore); +#if ITT_PLATFORM==ITT_PLATFORM_WIN + ITTNOTIFY_NAME(sync_createA) = ITTNOTIFY_NAME(sync_set_nameA); + ITTNOTIFY_NAME(sync_createW) = ITTNOTIFY_NAME(sync_set_nameW); +#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ + ITTNOTIFY_NAME(sync_create) = ITTNOTIFY_NAME(sync_set_name); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + ITTNOTIFY_NAME(sync_prepare) = ITTNOTIFY_NAME(notify_sync_prepare); + ITTNOTIFY_NAME(sync_cancel) = ITTNOTIFY_NAME(notify_sync_cancel); + ITTNOTIFY_NAME(sync_acquired) = ITTNOTIFY_NAME(notify_sync_acquired); + ITTNOTIFY_NAME(sync_releasing) = ITTNOTIFY_NAME(notify_sync_releasing); + } + +#ifdef ITT_COMPLETE_GROUP + for (i = 0; __itt_ittapi_global.api_list_ptr[i].name != NULL; i++) + if (__itt_ittapi_global.api_list_ptr[i].group & zero_group) + *__itt_ittapi_global.api_list_ptr[i].func_ptr = __itt_ittapi_global.api_list_ptr[i].null_func; +#endif /* ITT_COMPLETE_GROUP */ + break; + case 2: + __itt_api_init_ptr = (__itt_api_init_t*)__itt_get_proc(__itt_ittapi_global.lib, "__itt_api_init"); + if (__itt_api_init_ptr) + __itt_api_init_ptr(&__itt_ittapi_global, init_groups); + break; + } + } + else + { + __itt_nullify_all_pointers(); + + __itt_report_error(__itt_error_no_module, lib_name, +#if ITT_PLATFORM==ITT_PLATFORM_WIN + __itt_system_error() +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + dlerror() +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + ); + } + } + else + { + __itt_nullify_all_pointers(); + } + __itt_ittapi_global.api_initialized = 1; + current_thread = 0; + /* !!! Just to avoid unused code elimination !!! */ + if (__itt_fini_ittlib_ptr == _N_(fini_ittlib)) current_thread = 0; + } + } + +#ifndef ITT_SIMPLE_INIT + __itt_mutex_unlock(&__itt_ittapi_global.mutex); +#endif /* ITT_SIMPLE_INIT */ + } + + /* Evaluating if any function ptr is non empty and it's in init_groups */ + for (i = 0; __itt_ittapi_global.api_list_ptr[i].name != NULL; i++) + if (*__itt_ittapi_global.api_list_ptr[i].func_ptr != __itt_ittapi_global.api_list_ptr[i].null_func && + __itt_ittapi_global.api_list_ptr[i].group & init_groups) + return 1; + return 0; +} + +ITT_EXTERN_C __itt_error_handler_t* _N_(set_error_handler)(__itt_error_handler_t* handler) +{ + __itt_error_handler_t* prev = (__itt_error_handler_t*)__itt_ittapi_global.error_handler; + __itt_ittapi_global.error_handler = (void*)handler; + return prev; +} + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#pragma warning(pop) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ diff --git a/src/tbb/src/tbb/tools_api/ittnotify_static.h b/src/tbb/src/tbb/tools_api/ittnotify_static.h new file mode 100644 index 0000000..52aad68 --- /dev/null +++ b/src/tbb/src/tbb/tools_api/ittnotify_static.h @@ -0,0 +1,301 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "ittnotify_config.h" + +#ifndef ITT_FORMAT_DEFINED +# ifndef ITT_FORMAT +# define ITT_FORMAT +# endif /* ITT_FORMAT */ +# ifndef ITT_NO_PARAMS +# define ITT_NO_PARAMS +# endif /* ITT_NO_PARAMS */ +#endif /* ITT_FORMAT_DEFINED */ + +/* + * parameters for macro expected: + * ITT_STUB(api, type, func_name, arguments, params, func_name_in_dll, group, printf_fmt) + */ +#ifdef __ITT_INTERNAL_INIT + +#ifndef __ITT_INTERNAL_BODY +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(ITTAPI, __itt_domain*, domain_createA, (const char *name), (ITT_FORMAT name), domain_createA, __itt_group_structure, "\"%s\"") +ITT_STUB(ITTAPI, __itt_domain*, domain_createW, (const wchar_t *name), (ITT_FORMAT name), domain_createW, __itt_group_structure, "\"%S\"") +#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, __itt_domain*, domain_create, (const char *name), (ITT_FORMAT name), domain_create, __itt_group_structure, "\"%s\"") +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(ITTAPI, __itt_string_handle*, string_handle_createA, (const char *name), (ITT_FORMAT name), string_handle_createA, __itt_group_structure, "\"%s\"") +ITT_STUB(ITTAPI, __itt_string_handle*, string_handle_createW, (const wchar_t *name), (ITT_FORMAT name), string_handle_createW, __itt_group_structure, "\"%S\"") +#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, __itt_string_handle*, string_handle_create, (const char *name), (ITT_FORMAT name), string_handle_create, __itt_group_structure, "\"%s\"") +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +ITT_STUBV(ITTAPI, void, pause, (void), (ITT_NO_PARAMS), pause, __itt_group_control | __itt_group_legacy, "no args") +ITT_STUBV(ITTAPI, void, resume, (void), (ITT_NO_PARAMS), resume, __itt_group_control | __itt_group_legacy, "no args") + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUBV(ITTAPI, void, thread_set_nameA, (const char *name), (ITT_FORMAT name), thread_set_nameA, __itt_group_thread, "\"%s\"") +ITT_STUBV(ITTAPI, void, thread_set_nameW, (const wchar_t *name), (ITT_FORMAT name), thread_set_nameW, __itt_group_thread, "\"%S\"") +#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ +ITT_STUBV(ITTAPI, void, thread_set_name, (const char *name), (ITT_FORMAT name), thread_set_name, __itt_group_thread, "\"%s\"") +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUBV(ITTAPI, void, thread_ignore, (void), (ITT_NO_PARAMS), thread_ignore, __itt_group_thread, "no args") + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(LIBITTAPI, int, thr_name_setA, (const char *name, int namelen), (ITT_FORMAT name, namelen), thr_name_setA, __itt_group_thread | __itt_group_legacy, "\"%s\", %d") +ITT_STUB(LIBITTAPI, int, thr_name_setW, (const wchar_t *name, int namelen), (ITT_FORMAT name, namelen), thr_name_setW, __itt_group_thread | __itt_group_legacy, "\"%S\", %d") +#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ +ITT_STUB(LIBITTAPI, int, thr_name_set, (const char *name, int namelen), (ITT_FORMAT name, namelen), thr_name_set, __itt_group_thread | __itt_group_legacy, "\"%s\", %d") +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUBV(LIBITTAPI, void, thr_ignore, (void), (ITT_NO_PARAMS), thr_ignore, __itt_group_thread | __itt_group_legacy, "no args") +#endif /* __ITT_INTERNAL_BODY */ + +#else /* __ITT_INTERNAL_INIT */ + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUBV(ITTAPI, void, sync_createA, (void *addr, const char *objtype, const char *objname, int attribute), (ITT_FORMAT addr, objtype, objname, attribute), sync_createA, __itt_group_sync | __itt_group_fsync, "%p, \"%s\", \"%s\", %x") +ITT_STUBV(ITTAPI, void, sync_createW, (void *addr, const wchar_t *objtype, const wchar_t *objname, int attribute), (ITT_FORMAT addr, objtype, objname, attribute), sync_createW, __itt_group_sync | __itt_group_fsync, "%p, \"%S\", \"%S\", %x") +ITT_STUBV(ITTAPI, void, sync_renameA, (void *addr, const char *name), (ITT_FORMAT addr, name), sync_renameA, __itt_group_sync | __itt_group_fsync, "%p, \"%s\"") +ITT_STUBV(ITTAPI, void, sync_renameW, (void *addr, const wchar_t *name), (ITT_FORMAT addr, name), sync_renameW, __itt_group_sync | __itt_group_fsync, "%p, \"%S\"") +#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ +ITT_STUBV(ITTAPI, void, sync_create, (void *addr, const char *objtype, const char *objname, int attribute), (ITT_FORMAT addr, objtype, objname, attribute), sync_create, __itt_group_sync | __itt_group_fsync, "%p, \"%s\", \"%s\", %x") +ITT_STUBV(ITTAPI, void, sync_rename, (void *addr, const char *name), (ITT_FORMAT addr, name), sync_rename, __itt_group_sync | __itt_group_fsync, "%p, \"%s\"") +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUBV(ITTAPI, void, sync_destroy, (void *addr), (ITT_FORMAT addr), sync_destroy, __itt_group_sync | __itt_group_fsync, "%p") + +ITT_STUBV(ITTAPI, void, sync_prepare, (void* addr), (ITT_FORMAT addr), sync_prepare, __itt_group_sync, "%p") +ITT_STUBV(ITTAPI, void, sync_cancel, (void *addr), (ITT_FORMAT addr), sync_cancel, __itt_group_sync, "%p") +ITT_STUBV(ITTAPI, void, sync_acquired, (void *addr), (ITT_FORMAT addr), sync_acquired, __itt_group_sync, "%p") +ITT_STUBV(ITTAPI, void, sync_releasing, (void* addr), (ITT_FORMAT addr), sync_releasing, __itt_group_sync, "%p") + +ITT_STUBV(ITTAPI, void, fsync_prepare, (void* addr), (ITT_FORMAT addr), sync_prepare, __itt_group_fsync, "%p") +ITT_STUBV(ITTAPI, void, fsync_cancel, (void *addr), (ITT_FORMAT addr), sync_cancel, __itt_group_fsync, "%p") +ITT_STUBV(ITTAPI, void, fsync_acquired, (void *addr), (ITT_FORMAT addr), sync_acquired, __itt_group_fsync, "%p") +ITT_STUBV(ITTAPI, void, fsync_releasing, (void* addr), (ITT_FORMAT addr), sync_releasing, __itt_group_fsync, "%p") + +ITT_STUBV(ITTAPI, void, model_site_begin, (__itt_model_site *site, __itt_model_site_instance *instance, const char *name), (ITT_FORMAT site, instance, name), model_site_begin, __itt_group_model, "%p, %p, \"%s\"") +ITT_STUBV(ITTAPI, void, model_site_end, (__itt_model_site *site, __itt_model_site_instance *instance), (ITT_FORMAT site, instance), model_site_end, __itt_group_model, "%p, %p") +ITT_STUBV(ITTAPI, void, model_task_begin, (__itt_model_task *task, __itt_model_task_instance *instance, const char *name), (ITT_FORMAT task, instance, name), model_task_begin, __itt_group_model, "%p, %p, \"%s\"") +ITT_STUBV(ITTAPI, void, model_task_end, (__itt_model_task *task, __itt_model_task_instance *instance), (ITT_FORMAT task, instance), model_task_end, __itt_group_model, "%p, %p") +ITT_STUBV(ITTAPI, void, model_lock_acquire, (void *lock), (ITT_FORMAT lock), model_lock_acquire, __itt_group_model, "%p") +ITT_STUBV(ITTAPI, void, model_lock_release, (void *lock), (ITT_FORMAT lock), model_lock_release, __itt_group_model, "%p") +ITT_STUBV(ITTAPI, void, model_record_allocation, (void *addr, size_t size), (ITT_FORMAT addr, size), model_record_allocation, __itt_group_model, "%p, %d") +ITT_STUBV(ITTAPI, void, model_record_deallocation, (void *addr), (ITT_FORMAT addr), model_record_deallocation, __itt_group_model, "%p") +ITT_STUBV(ITTAPI, void, model_induction_uses, (void* addr, size_t size), (ITT_FORMAT addr, size), model_induction_uses, __itt_group_model, "%p, %d") +ITT_STUBV(ITTAPI, void, model_reduction_uses, (void* addr, size_t size), (ITT_FORMAT addr, size), model_reduction_uses, __itt_group_model, "%p, %d") +ITT_STUBV(ITTAPI, void, model_observe_uses, (void* addr, size_t size), (ITT_FORMAT addr, size), model_observe_uses, __itt_group_model, "%p, %d") +ITT_STUBV(ITTAPI, void, model_clear_uses, (void* addr), (ITT_FORMAT addr), model_clear_uses, __itt_group_model, "%p") +ITT_STUBV(ITTAPI, void, model_disable_push, (__itt_model_disable x), (ITT_FORMAT x), model_disable_push, __itt_group_model, "%p") +ITT_STUBV(ITTAPI, void, model_disable_pop, (void), (ITT_NO_PARAMS), model_disable_pop, __itt_group_model, "no args") + +#ifndef __ITT_INTERNAL_BODY +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUBV(ITTAPI, void, model_site_beginW, (const wchar_t *name), (ITT_FORMAT name), model_site_beginW, __itt_group_model, "\"%s\"") +ITT_STUBV(ITTAPI, void, model_task_beginW, (const wchar_t *name), (ITT_FORMAT name), model_task_beginW, __itt_group_model, "\"%s\"") +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUBV(ITTAPI, void, model_site_beginAL, (const char *name, size_t len), (ITT_FORMAT name, len), model_site_beginAL, __itt_group_model, "\"%s\", %d") +ITT_STUBV(ITTAPI, void, model_task_beginAL, (const char *name, size_t len), (ITT_FORMAT name, len), model_task_beginAL, __itt_group_model, "\"%s\", %d") +#endif /* __ITT_INTERNAL_BODY */ + +#ifndef __ITT_INTERNAL_BODY +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(ITTAPI, __itt_heap_function, heap_function_createA, (const char *name, const char *domain), (ITT_FORMAT name, domain), heap_function_createA, __itt_group_heap, "\"%s\", \"%s\"") +ITT_STUB(ITTAPI, __itt_heap_function, heap_function_createW, (const wchar_t *name, const wchar_t *domain), (ITT_FORMAT name, domain), heap_function_createW, __itt_group_heap, "\"%s\", \"%s\"") +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, __itt_heap_function, heap_function_create, (const char *name, const char *domain), (ITT_FORMAT name, domain), heap_function_create, __itt_group_heap, "\"%s\", \"%s\"") +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* __ITT_INTERNAL_BODY */ +ITT_STUBV(ITTAPI, void, heap_allocate_begin, (__itt_heap_function h, size_t size, int initialized), (ITT_FORMAT h, size, initialized), heap_allocate_begin, __itt_group_heap, "%p, %lu, %d") +ITT_STUBV(ITTAPI, void, heap_allocate_end, (__itt_heap_function h, void** addr, size_t size, int initialized), (ITT_FORMAT h, addr, size, initialized), heap_allocate_end, __itt_group_heap, "%p, %p, %lu, %d") +ITT_STUBV(ITTAPI, void, heap_free_begin, (__itt_heap_function h, void* addr), (ITT_FORMAT h, addr), heap_free_begin, __itt_group_heap, "%p, %p") +ITT_STUBV(ITTAPI, void, heap_free_end, (__itt_heap_function h, void* addr), (ITT_FORMAT h, addr), heap_free_end, __itt_group_heap, "%p, %p") +ITT_STUBV(ITTAPI, void, heap_reallocate_begin, (__itt_heap_function h, void* addr, size_t new_size, int initialized), (ITT_FORMAT h, addr, new_size, initialized), heap_reallocate_begin, __itt_group_heap, "%p, %p, %lu, %d") +ITT_STUBV(ITTAPI, void, heap_reallocate_end, (__itt_heap_function h, void* addr, void** new_addr, size_t new_size, int initialized), (ITT_FORMAT h, addr, new_addr, new_size, initialized), heap_reallocate_end, __itt_group_heap, "%p, %p, %p, %lu, %d") +ITT_STUBV(ITTAPI, void, heap_internal_access_begin, (void), (ITT_NO_PARAMS), heap_internal_access_begin, __itt_group_heap, "no args") +ITT_STUBV(ITTAPI, void, heap_internal_access_end, (void), (ITT_NO_PARAMS), heap_internal_access_end, __itt_group_heap, "no args") + +ITT_STUBV(ITTAPI, void, id_create, (const __itt_domain *domain, __itt_id id), (ITT_FORMAT domain, id), id_create, __itt_group_structure, "%p, %lu") +ITT_STUBV(ITTAPI, void, id_destroy, (const __itt_domain *domain, __itt_id id), (ITT_FORMAT domain, id), id_destroy, __itt_group_structure, "%p, %lu") + +ITT_STUBV(ITTAPI, void, region_begin, (const __itt_domain *domain, __itt_id id, __itt_id parent, __itt_string_handle *name), (ITT_FORMAT domain, id, parent, name), region_begin, __itt_group_structure, "%p, %lu, %lu, %p") +ITT_STUBV(ITTAPI, void, region_end, (const __itt_domain *domain, __itt_id id), (ITT_FORMAT domain, id), region_end, __itt_group_structure, "%p, %lu") + +#ifndef __ITT_INTERNAL_BODY +ITT_STUBV(ITTAPI, void, frame_begin_v3, (const __itt_domain *domain, __itt_id *id), (ITT_FORMAT domain, id), frame_begin_v3, __itt_group_structure, "%p, %p") +ITT_STUBV(ITTAPI, void, frame_end_v3, (const __itt_domain *domain, __itt_id *id), (ITT_FORMAT domain, id), frame_end_v3, __itt_group_structure, "%p, %p") +#endif /* __ITT_INTERNAL_BODY */ + +ITT_STUBV(ITTAPI, void, task_group, (const __itt_domain *domain, __itt_id id, __itt_id parent, __itt_string_handle *name), (ITT_FORMAT domain, id, parent, name), task_group, __itt_group_structure, "%p, %lu, %lu, %p") + +ITT_STUBV(ITTAPI, void, task_begin, (const __itt_domain *domain, __itt_id id, __itt_id parent, __itt_string_handle *name), (ITT_FORMAT domain, id, parent, name), task_begin, __itt_group_structure, "%p, %lu, %lu, %p") +ITT_STUBV(ITTAPI, void, task_begin_fn, (const __itt_domain *domain, __itt_id id, __itt_id parent, void* fn), (ITT_FORMAT domain, id, parent, fn), task_begin_fn, __itt_group_structure, "%p, %lu, %lu, %p") +ITT_STUBV(ITTAPI, void, task_end, (const __itt_domain *domain), (ITT_FORMAT domain), task_end, __itt_group_structure, "%p") + +ITT_STUBV(ITTAPI, void, counter_inc_v3, (const __itt_domain *domain, __itt_string_handle *name), (ITT_FORMAT domain, name), counter_inc_v3, __itt_group_structure, "%p, %p") +ITT_STUBV(ITTAPI, void, counter_inc_delta_v3, (const __itt_domain *domain, __itt_string_handle *name, unsigned long long value), (ITT_FORMAT domain, name, value), counter_inc_delta_v3, __itt_group_structure, "%p, %p, %lu") + +ITT_STUBV(ITTAPI, void, marker, (const __itt_domain *domain, __itt_id id, __itt_string_handle *name, __itt_scope scope), (ITT_FORMAT domain, id, name, scope), marker, __itt_group_structure, "%p, %lu, %p, %d") + +ITT_STUBV(ITTAPI, void, metadata_add, (const __itt_domain *domain, __itt_id id, __itt_string_handle *key, __itt_metadata_type type, size_t count, void *data), (ITT_FORMAT domain, id, key, type, count, data), metadata_add, __itt_group_structure, "%p, %lu, %p, %d, %lu, %p") +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUBV(ITTAPI, void, metadata_str_addA, (const __itt_domain *domain, __itt_id id, __itt_string_handle *key, const char* data, size_t length), (ITT_FORMAT domain, id, key, data, length), metadata_str_addA, __itt_group_structure, "%p, %lu, %p, %p, %lu") +ITT_STUBV(ITTAPI, void, metadata_str_addW, (const __itt_domain *domain, __itt_id id, __itt_string_handle *key, const wchar_t* data, size_t length), (ITT_FORMAT domain, id, key, data, length), metadata_str_addW, __itt_group_structure, "%p, %lu, %p, %p, %lu") +#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ +ITT_STUBV(ITTAPI, void, metadata_str_add, (const __itt_domain *domain, __itt_id id, __itt_string_handle *key, const char* data, size_t length), (ITT_FORMAT domain, id, key, data, length), metadata_str_add, __itt_group_structure, "%p, %lu, %p, %p, %lu") +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +ITT_STUBV(ITTAPI, void, relation_add_to_current, (const __itt_domain *domain, __itt_relation relation, __itt_id tail), (ITT_FORMAT domain, relation, tail), relation_add_to_current, __itt_group_structure, "%p, %lu, %p") +ITT_STUBV(ITTAPI, void, relation_add, (const __itt_domain *domain, __itt_id head, __itt_relation relation, __itt_id tail), (ITT_FORMAT domain, head, relation, tail), relation_add, __itt_group_structure, "%p, %p, %lu, %p") + +#ifndef __ITT_INTERNAL_BODY +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(LIBITTAPI, __itt_event, event_createA, (const char *name, int namelen), (ITT_FORMAT name, namelen), event_createA, __itt_group_mark | __itt_group_legacy, "\"%s\", %d") +ITT_STUB(LIBITTAPI, __itt_event, event_createW, (const wchar_t *name, int namelen), (ITT_FORMAT name, namelen), event_createW, __itt_group_mark | __itt_group_legacy, "\"%S\", %d") +#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ +ITT_STUB(LIBITTAPI, __itt_event, event_create, (const char *name, int namelen), (ITT_FORMAT name, namelen), event_create, __itt_group_mark | __itt_group_legacy, "\"%s\", %d") +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(LIBITTAPI, int, event_start, (__itt_event event), (ITT_FORMAT event), event_start, __itt_group_mark | __itt_group_legacy, "%d") +ITT_STUB(LIBITTAPI, int, event_end, (__itt_event event), (ITT_FORMAT event), event_end, __itt_group_mark | __itt_group_legacy, "%d") +#endif /* __ITT_INTERNAL_BODY */ + +#ifndef __ITT_INTERNAL_BODY +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUBV(ITTAPI, void, sync_set_nameA, (void *addr, const char *objtype, const char *objname, int attribute), (ITT_FORMAT addr, objtype, objname, attribute), sync_set_nameA, __itt_group_sync | __itt_group_fsync | __itt_group_legacy, "%p, \"%s\", \"%s\", %x") +ITT_STUBV(ITTAPI, void, sync_set_nameW, (void *addr, const wchar_t *objtype, const wchar_t *objname, int attribute), (ITT_FORMAT addr, objtype, objname, attribute), sync_set_nameW, __itt_group_sync | __itt_group_fsync | __itt_group_legacy, "%p, \"%S\", \"%S\", %x") +#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ +ITT_STUBV(ITTAPI, void, sync_set_name, (void *addr, const char *objtype, const char *objname, int attribute), (ITT_FORMAT addr, objtype, objname, attribute), sync_set_name, __itt_group_sync | __itt_group_fsync | __itt_group_legacy, "p, \"%s\", \"%s\", %x") +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(LIBITTAPI, int, notify_sync_nameA, (void *p, const char *objtype, int typelen, const char *objname, int namelen, int attribute), (ITT_FORMAT p, objtype, typelen, objname, namelen, attribute), notify_sync_nameA, __itt_group_sync | __itt_group_fsync | __itt_group_legacy, "%p, \"%s\", %d, \"%s\", %d, %x") +ITT_STUB(LIBITTAPI, int, notify_sync_nameW, (void *p, const wchar_t *objtype, int typelen, const wchar_t *objname, int namelen, int attribute), (ITT_FORMAT p, objtype, typelen, objname, namelen, attribute), notify_sync_nameW, __itt_group_sync | __itt_group_fsync | __itt_group_legacy, "%p, \"%S\", %d, \"%S\", %d, %x") +#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ +ITT_STUB(LIBITTAPI, int, notify_sync_name, (void *p, const char *objtype, int typelen, const char *objname, int namelen, int attribute), (ITT_FORMAT p, objtype, typelen, objname, namelen, attribute), notify_sync_name, __itt_group_sync | __itt_group_fsync | __itt_group_legacy, "%p, \"%s\", %d, \"%s\", %d, %x") +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +ITT_STUBV(LIBITTAPI, void, notify_sync_prepare, (void *p), (ITT_FORMAT p), notify_sync_prepare, __itt_group_sync | __itt_group_fsync | __itt_group_legacy, "%p") +ITT_STUBV(LIBITTAPI, void, notify_sync_cancel, (void *p), (ITT_FORMAT p), notify_sync_cancel, __itt_group_sync | __itt_group_fsync | __itt_group_legacy, "%p") +ITT_STUBV(LIBITTAPI, void, notify_sync_acquired, (void *p), (ITT_FORMAT p), notify_sync_acquired, __itt_group_sync | __itt_group_fsync | __itt_group_legacy, "%p") +ITT_STUBV(LIBITTAPI, void, notify_sync_releasing, (void *p), (ITT_FORMAT p), notify_sync_releasing, __itt_group_sync | __itt_group_fsync | __itt_group_legacy, "%p") +#endif /* __ITT_INTERNAL_BODY */ + +ITT_STUBV(LIBITTAPI, void, memory_read, (void *addr, size_t size), (ITT_FORMAT addr, size), memory_read, __itt_group_legacy, "%p, %lu") +ITT_STUBV(LIBITTAPI, void, memory_write, (void *addr, size_t size), (ITT_FORMAT addr, size), memory_write, __itt_group_legacy, "%p, %lu") +ITT_STUBV(LIBITTAPI, void, memory_update, (void *addr, size_t size), (ITT_FORMAT addr, size), memory_update, __itt_group_legacy, "%p, %lu") + +ITT_STUB(LIBITTAPI, __itt_state_t, state_get, (void), (ITT_NO_PARAMS), state_get, __itt_group_legacy, "no args") +ITT_STUB(LIBITTAPI, __itt_state_t, state_set, (__itt_state_t s), (ITT_FORMAT s), state_set, __itt_group_legacy, "%d") +ITT_STUB(LIBITTAPI, __itt_obj_state_t, obj_mode_set, (__itt_obj_prop_t p, __itt_obj_state_t s), (ITT_FORMAT p, s), obj_mode_set, __itt_group_legacy, "%d, %d") +ITT_STUB(LIBITTAPI, __itt_thr_state_t, thr_mode_set, (__itt_thr_prop_t p, __itt_thr_state_t s), (ITT_FORMAT p, s), thr_mode_set, __itt_group_legacy, "%d, %d") + +#ifndef __ITT_INTERNAL_BODY +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(ITTAPI, __itt_frame, frame_createA, (const char *domain), (ITT_FORMAT domain), frame_createA, __itt_group_frame, "\"%s\"") +ITT_STUB(ITTAPI, __itt_frame, frame_createW, (const wchar_t *domain), (ITT_FORMAT domain), frame_createW, __itt_group_frame, "\"%s\"") +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, __itt_frame, frame_create, (const char *domain), (ITT_FORMAT domain), frame_create, __itt_group_frame, "\"%s\"") +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* __ITT_INTERNAL_BODY */ +ITT_STUBV(ITTAPI, void, frame_begin, (__itt_frame frame), (ITT_FORMAT frame), frame_begin, __itt_group_frame, "%p") +ITT_STUBV(ITTAPI, void, frame_end, (__itt_frame frame), (ITT_FORMAT frame), frame_end, __itt_group_frame, "%p") + +#ifndef __ITT_INTERNAL_BODY +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(ITTAPI, __itt_counter, counter_createA, (const char *name, const char *domain), (ITT_FORMAT name, domain), counter_createA, __itt_group_counter, "\"%s\", \"%s\"") +ITT_STUB(ITTAPI, __itt_counter, counter_createW, (const wchar_t *name, const wchar_t *domain), (ITT_FORMAT name, domain), counter_createW, __itt_group_counter, "\"%s\", \"%s\"") +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, __itt_counter, counter_create, (const char *name, const char *domain), (ITT_FORMAT name, domain), counter_create, __itt_group_counter, "\"%s\", \"%s\"") +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* __ITT_INTERNAL_BODY */ +ITT_STUBV(ITTAPI, void, counter_destroy, (__itt_counter id), (ITT_FORMAT id), counter_destroy, __itt_group_counter, "%p") +ITT_STUBV(ITTAPI, void, counter_inc, (__itt_counter id), (ITT_FORMAT id), counter_inc, __itt_group_counter, "%p") +ITT_STUBV(ITTAPI, void, counter_inc_delta, (__itt_counter id, unsigned long long value), (ITT_FORMAT id, value), counter_inc_delta, __itt_group_counter, "%p, %lu") + +#ifndef __ITT_INTERNAL_BODY +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(ITTAPI, __itt_mark_type, mark_createA, (const char *name), (ITT_FORMAT name), mark_createA, __itt_group_mark, "\"%s\"") +ITT_STUB(ITTAPI, __itt_mark_type, mark_createW, (const wchar_t *name), (ITT_FORMAT name), mark_createW, __itt_group_mark, "\"%S\"") +#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, __itt_mark_type, mark_create, (const char *name), (ITT_FORMAT name), mark_create, __itt_group_mark, "\"%s\"") +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* __ITT_INTERNAL_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(ITTAPI, int, markA, (__itt_mark_type mt, const char *parameter), (ITT_FORMAT mt, parameter), markA, __itt_group_mark, "%d, \"%s\"") +ITT_STUB(ITTAPI, int, markW, (__itt_mark_type mt, const wchar_t *parameter), (ITT_FORMAT mt, parameter), markW, __itt_group_mark, "%d, \"%S\"") +#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, int, mark, (__itt_mark_type mt, const char *parameter), (ITT_FORMAT mt, parameter), mark, __itt_group_mark, "%d, \"%s\"") +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, int, mark_off, (__itt_mark_type mt), (ITT_FORMAT mt), mark_off, __itt_group_mark, "%d") +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(ITTAPI, int, mark_globalA, (__itt_mark_type mt, const char *parameter), (ITT_FORMAT mt, parameter), mark_globalA, __itt_group_mark, "%d, \"%s\"") +ITT_STUB(ITTAPI, int, mark_globalW, (__itt_mark_type mt, const wchar_t *parameter), (ITT_FORMAT mt, parameter), mark_globalW, __itt_group_mark, "%d, \"%S\"") +#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, int, mark_global, (__itt_mark_type mt, const char *parameter), (ITT_FORMAT mt, parameter), mark_global, __itt_group_mark, "%d, \"%S\"") +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, int, mark_global_off, (__itt_mark_type mt), (ITT_FORMAT mt), mark_global_off, __itt_group_mark, "%d") + +#ifndef __ITT_INTERNAL_BODY +ITT_STUB(ITTAPI, __itt_caller, stack_caller_create, (void), (ITT_NO_PARAMS), stack_caller_create, __itt_group_stitch, "no args") +#endif /* __ITT_INTERNAL_BODY */ +ITT_STUBV(ITTAPI, void, stack_caller_destroy, (__itt_caller id), (ITT_FORMAT id), stack_caller_destroy, __itt_group_stitch, "%p") +ITT_STUBV(ITTAPI, void, stack_callee_enter, (__itt_caller id), (ITT_FORMAT id), stack_callee_enter, __itt_group_stitch, "%p") +ITT_STUBV(ITTAPI, void, stack_callee_leave, (__itt_caller id), (ITT_FORMAT id), stack_callee_leave, __itt_group_stitch, "%p") + +ITT_STUB(ITTAPI, __itt_clock_domain*, clock_domain_create, (__itt_get_clock_info_fn fn, void* fn_data), (ITT_FORMAT fn, fn_data), clock_domain_create, __itt_group_structure, "%p, %p") +ITT_STUBV(ITTAPI, void, clock_domain_reset, (void), (ITT_NO_PARAMS), clock_domain_reset, __itt_group_structure, "no args") +ITT_STUBV(ITTAPI, void, id_create_ex, (const __itt_domain *domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id id), (ITT_FORMAT domain, clock_domain, timestamp, id), id_create_ex, __itt_group_structure, "%p, %p, %lu, %lu") +ITT_STUBV(ITTAPI, void, id_destroy_ex, (const __itt_domain *domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id id), (ITT_FORMAT domain, clock_domain, timestamp, id), id_destroy_ex, __itt_group_structure, "%p, %p, %lu, %lu") +ITT_STUBV(ITTAPI, void, task_begin_ex, (const __itt_domain *domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id id, __itt_id parentid, __itt_string_handle *name), (ITT_FORMAT domain, clock_domain, timestamp, id, parentid, name), task_begin_ex, __itt_group_structure, "%p, %p, %lu, %lu, %lu, %p") +ITT_STUBV(ITTAPI, void, task_begin_fn_ex, (const __itt_domain *domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id id, __itt_id parentid, void* fn), (ITT_FORMAT domain, clock_domain, timestamp, id, parentid, fn), task_begin_fn_ex, __itt_group_structure, "%p, %p, %lu, %lu, %lu, %p") +ITT_STUBV(ITTAPI, void, task_end_ex, (const __itt_domain *domain, __itt_clock_domain* clock_domain, unsigned long long timestamp), (ITT_FORMAT domain, clock_domain, timestamp), task_end_ex, __itt_group_structure, "%p, %p, %lu") +ITT_STUBV(ITTAPI, void, task_begin_overlapped, (const __itt_domain *domain, __itt_id id, __itt_id parent, __itt_string_handle *name), (ITT_FORMAT domain, id, parent, name), task_begin_overlapped, __itt_group_structure, "%p, %lu, %lu, %p") +ITT_STUBV(ITTAPI, void, task_begin_overlapped_ex, (const __itt_domain *domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id id, __itt_id parentid, __itt_string_handle *name), (ITT_FORMAT domain, clock_domain, timestamp, id, parentid, name), task_begin_overlapped_ex, __itt_group_structure, "%p, %p, %lu, %lu, %lu, %p") +ITT_STUBV(ITTAPI, void, task_end_overlapped, (const __itt_domain *domain, __itt_id id), (ITT_FORMAT domain, id), task_end_overlapped, __itt_group_structure, "%p, %lu") +ITT_STUBV(ITTAPI, void, task_end_overlapped_ex, (const __itt_domain *domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id id), (ITT_FORMAT domain, clock_domain, timestamp, id), task_end_overlapped_ex, __itt_group_structure, "%p, %p, %lu, %lu") +ITT_STUBV(ITTAPI, void, marker_ex, (const __itt_domain *domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id id, __itt_string_handle *name, __itt_scope scope), (ITT_FORMAT domain, clock_domain, timestamp, id, name, scope), marker_ex, __itt_group_structure, "%p, %p, %lu, %lu, %p, %d") +ITT_STUBV(ITTAPI, void, metadata_add_with_scope, (const __itt_domain *domain, __itt_scope scope, __itt_string_handle *key, __itt_metadata_type type, size_t count, void *data), (ITT_FORMAT domain, scope, key, type, count, data), metadata_add_with_scope, __itt_group_structure, "%p, %d, %p, %d, %lu, %p") +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUBV(ITTAPI, void, metadata_str_add_with_scopeA, (const __itt_domain *domain, __itt_scope scope, __itt_string_handle *key, const char *data, size_t length), (ITT_FORMAT domain, scope, key, data, length), metadata_str_add_with_scopeA, __itt_group_structure, "%p, %d, %p, %p, %lu") +ITT_STUBV(ITTAPI, void, metadata_str_add_with_scopeW, (const __itt_domain *domain, __itt_scope scope, __itt_string_handle *key, const wchar_t *data, size_t length), (ITT_FORMAT domain, scope, key, data, length), metadata_str_add_with_scopeW, __itt_group_structure, "%p, %d, %p, %p, %lu") +#else /* ITT_PLATFORM!=ITT_PLATFORM_WIN */ +ITT_STUBV(ITTAPI, void, metadata_str_add_with_scope, (const __itt_domain *domain, __itt_scope scope, __itt_string_handle *key, const char *data, size_t length), (ITT_FORMAT domain, scope, key, data, length), metadata_str_add_with_scope, __itt_group_structure, "%p, %d, %p, %p, %lu") +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUBV(ITTAPI, void, relation_add_to_current_ex, (const __itt_domain *domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_relation relation, __itt_id tail), (ITT_FORMAT domain, clock_domain, timestamp, relation, tail), relation_add_to_current_ex, __itt_group_structure, "%p, %p, %lu, %d, %lu") +ITT_STUBV(ITTAPI, void, relation_add_ex, (const __itt_domain *domain, __itt_clock_domain* clock_domain, unsigned long long timestamp, __itt_id head, __itt_relation relation, __itt_id tail), (ITT_FORMAT domain, clock_domain, timestamp, head, relation, tail), relation_add_ex, __itt_group_structure, "%p, %p, %lu, %lu, %d, %lu") +ITT_STUB(ITTAPI, __itt_track_group*, track_group_create, (__itt_string_handle* name, __itt_track_group_type track_group_type), (ITT_FORMAT name, track_group_type), track_group_create, __itt_group_structure, "%p, %d") +ITT_STUB(ITTAPI, __itt_track*, track_create, (__itt_track_group* track_group,__itt_string_handle* name, __itt_track_type track_type), (ITT_FORMAT track_group, name, track_type), track_create, __itt_group_structure, "%p, %p, %d") +ITT_STUBV(ITTAPI, void, set_track, (__itt_track *track), (ITT_FORMAT track), set_track, __itt_group_structure, "%p") + +#ifndef __ITT_INTERNAL_BODY +ITT_STUB(ITTAPI, const char*, api_version, (void), (ITT_NO_PARAMS), api_version, __itt_group_all & ~__itt_group_legacy, "no args") +#endif /* __ITT_INTERNAL_BODY */ + +#endif /* __ITT_INTERNAL_INIT */ diff --git a/src/tbb/src/tbb/tools_api/ittnotify_types.h b/src/tbb/src/tbb/tools_api/ittnotify_types.h new file mode 100644 index 0000000..f33d6ac --- /dev/null +++ b/src/tbb/src/tbb/tools_api/ittnotify_types.h @@ -0,0 +1,81 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _ITTNOTIFY_TYPES_H_ +#define _ITTNOTIFY_TYPES_H_ + +typedef enum ___itt_group_id +{ + __itt_group_none = 0, + __itt_group_legacy = 1<<0, + __itt_group_control = 1<<1, + __itt_group_thread = 1<<2, + __itt_group_mark = 1<<3, + __itt_group_sync = 1<<4, + __itt_group_fsync = 1<<5, + __itt_group_jit = 1<<6, + __itt_group_model = 1<<7, + __itt_group_splitter_min = 1<<7, + __itt_group_counter = 1<<8, + __itt_group_frame = 1<<9, + __itt_group_stitch = 1<<10, + __itt_group_heap = 1<<11, + __itt_group_splitter_max = 1<<12, + __itt_group_structure = 1<<12, + __itt_group_all = -1 +} __itt_group_id; + +#pragma pack(push, 8) + +typedef struct ___itt_group_list +{ + __itt_group_id id; + const char* name; +} __itt_group_list; + +#pragma pack(pop) + +#define ITT_GROUP_LIST(varname) \ + static __itt_group_list varname[] = { \ + { __itt_group_all, "all" }, \ + { __itt_group_control, "control" }, \ + { __itt_group_thread, "thread" }, \ + { __itt_group_mark, "mark" }, \ + { __itt_group_sync, "sync" }, \ + { __itt_group_fsync, "fsync" }, \ + { __itt_group_jit, "jit" }, \ + { __itt_group_model, "model" }, \ + { __itt_group_counter, "counter" }, \ + { __itt_group_frame, "frame" }, \ + { __itt_group_stitch, "stitch" }, \ + { __itt_group_heap, "heap" }, \ + { __itt_group_structure, "structure" }, \ + { __itt_group_none, NULL } \ + } + +#endif /* _ITTNOTIFY_TYPES_H_ */ diff --git a/src/tbb/src/tbb/tools_api/legacy/ittnotify.h b/src/tbb/src/tbb/tools_api/legacy/ittnotify.h new file mode 100644 index 0000000..b0dde48 --- /dev/null +++ b/src/tbb/src/tbb/tools_api/legacy/ittnotify.h @@ -0,0 +1,983 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _LEGACY_ITTNOTIFY_H_ +#define _LEGACY_ITTNOTIFY_H_ + +/** + * @file + * @brief Legacy User API functions and types + */ + +/** @cond exclude_from_documentation */ +#ifndef ITT_OS_WIN +# define ITT_OS_WIN 1 +#endif /* ITT_OS_WIN */ + +#ifndef ITT_OS_LINUX +# define ITT_OS_LINUX 2 +#endif /* ITT_OS_LINUX */ + +#ifndef ITT_OS_MAC +# define ITT_OS_MAC 3 +#endif /* ITT_OS_MAC */ + +#ifndef ITT_OS +# if defined WIN32 || defined _WIN32 +# define ITT_OS ITT_OS_WIN +# elif defined( __APPLE__ ) && defined( __MACH__ ) +# define ITT_OS ITT_OS_MAC +# else +# define ITT_OS ITT_OS_LINUX +# endif +#endif /* ITT_OS */ + +#ifndef ITT_PLATFORM_WIN +# define ITT_PLATFORM_WIN 1 +#endif /* ITT_PLATFORM_WIN */ + +#ifndef ITT_PLATFORM_POSIX +# define ITT_PLATFORM_POSIX 2 +#endif /* ITT_PLATFORM_POSIX */ + +#ifndef ITT_PLATFORM +# if ITT_OS==ITT_OS_WIN +# define ITT_PLATFORM ITT_PLATFORM_WIN +# else +# define ITT_PLATFORM ITT_PLATFORM_POSIX +# endif /* _WIN32 */ +#endif /* ITT_PLATFORM */ + +#if defined(_UNICODE) && !defined(UNICODE) +#define UNICODE +#endif + +#include <stddef.h> +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#include <tchar.h> +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#include <stdint.h> +#if defined(UNICODE) || defined(_UNICODE) +#include <wchar.h> +#endif /* UNICODE || _UNICODE */ +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +#ifndef CDECL +# if ITT_PLATFORM==ITT_PLATFORM_WIN +# define CDECL __cdecl +# else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +# if defined _M_X64 || defined _M_AMD64 || defined __x86_64__ +# define CDECL /* not actual on x86_64 platform */ +# else /* _M_X64 || _M_AMD64 || __x86_64__ */ +# define CDECL __attribute__ ((cdecl)) +# endif /* _M_X64 || _M_AMD64 || __x86_64__ */ +# endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* CDECL */ + +#ifndef STDCALL +# if ITT_PLATFORM==ITT_PLATFORM_WIN +# define STDCALL __stdcall +# else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +# if defined _M_X64 || defined _M_AMD64 || defined __x86_64__ +# define STDCALL /* not supported on x86_64 platform */ +# else /* _M_X64 || _M_AMD64 || __x86_64__ */ +# define STDCALL __attribute__ ((stdcall)) +# endif /* _M_X64 || _M_AMD64 || __x86_64__ */ +# endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* STDCALL */ + +#define ITTAPI CDECL +#define LIBITTAPI CDECL + +/* TODO: Temporary for compatibility! */ +#define ITTAPI_CALL CDECL +#define LIBITTAPI_CALL CDECL + +#if ITT_PLATFORM==ITT_PLATFORM_WIN +/* use __forceinline (VC++ specific) */ +#define INLINE __forceinline +#define INLINE_ATTRIBUTE /* nothing */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +/* + * Generally, functions are not inlined unless optimization is specified. + * For functions declared inline, this attribute inlines the function even + * if no optimization level was specified. + */ +#ifdef __STRICT_ANSI__ +#define INLINE static +#else /* __STRICT_ANSI__ */ +#define INLINE static inline +#endif /* __STRICT_ANSI__ */ +#define INLINE_ATTRIBUTE __attribute__ ((always_inline)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +/** @endcond */ + +/** @cond exclude_from_documentation */ +/* Helper macro for joining tokens */ +#define ITT_JOIN_AUX(p,n) p##n +#define ITT_JOIN(p,n) ITT_JOIN_AUX(p,n) + +#ifdef ITT_MAJOR +#undef ITT_MAJOR +#endif +#ifdef ITT_MINOR +#undef ITT_MINOR +#endif +#define ITT_MAJOR 3 +#define ITT_MINOR 0 + +/* Standard versioning of a token with major and minor version numbers */ +#define ITT_VERSIONIZE(x) \ + ITT_JOIN(x, \ + ITT_JOIN(_, \ + ITT_JOIN(ITT_MAJOR, \ + ITT_JOIN(_, ITT_MINOR)))) + +#ifndef INTEL_ITTNOTIFY_PREFIX +# define INTEL_ITTNOTIFY_PREFIX __itt_ +#endif /* INTEL_ITTNOTIFY_PREFIX */ +#ifndef INTEL_ITTNOTIFY_POSTFIX +# define INTEL_ITTNOTIFY_POSTFIX _ptr_ +#endif /* INTEL_ITTNOTIFY_POSTFIX */ + +#define ITTNOTIFY_NAME_AUX(n) ITT_JOIN(INTEL_ITTNOTIFY_PREFIX,n) +#define ITTNOTIFY_NAME(n) ITT_VERSIONIZE(ITTNOTIFY_NAME_AUX(ITT_JOIN(n,INTEL_ITTNOTIFY_POSTFIX))) + +#define ITTNOTIFY_VOID(n) (!ITTNOTIFY_NAME(n)) ? (void)0 : ITTNOTIFY_NAME(n) +#define ITTNOTIFY_DATA(n) (!ITTNOTIFY_NAME(n)) ? 0 : ITTNOTIFY_NAME(n) + +#define ITTNOTIFY_VOID_D0(n,d) (!(d)->flags) ? (void)0 : (!ITTNOTIFY_NAME(n)) ? (void)0 : ITTNOTIFY_NAME(n)(d) +#define ITTNOTIFY_VOID_D1(n,d,x) (!(d)->flags) ? (void)0 : (!ITTNOTIFY_NAME(n)) ? (void)0 : ITTNOTIFY_NAME(n)(d,x) +#define ITTNOTIFY_VOID_D2(n,d,x,y) (!(d)->flags) ? (void)0 : (!ITTNOTIFY_NAME(n)) ? (void)0 : ITTNOTIFY_NAME(n)(d,x,y) +#define ITTNOTIFY_VOID_D3(n,d,x,y,z) (!(d)->flags) ? (void)0 : (!ITTNOTIFY_NAME(n)) ? (void)0 : ITTNOTIFY_NAME(n)(d,x,y,z) +#define ITTNOTIFY_VOID_D4(n,d,x,y,z,a) (!(d)->flags) ? (void)0 : (!ITTNOTIFY_NAME(n)) ? (void)0 : ITTNOTIFY_NAME(n)(d,x,y,z,a) +#define ITTNOTIFY_VOID_D5(n,d,x,y,z,a,b) (!(d)->flags) ? (void)0 : (!ITTNOTIFY_NAME(n)) ? (void)0 : ITTNOTIFY_NAME(n)(d,x,y,z,a,b) +#define ITTNOTIFY_VOID_D6(n,d,x,y,z,a,b,c) (!(d)->flags) ? (void)0 : (!ITTNOTIFY_NAME(n)) ? (void)0 : ITTNOTIFY_NAME(n)(d,x,y,z,a,b,c) +#define ITTNOTIFY_DATA_D0(n,d) (!(d)->flags) ? 0 : (!ITTNOTIFY_NAME(n)) ? 0 : ITTNOTIFY_NAME(n)(d) +#define ITTNOTIFY_DATA_D1(n,d,x) (!(d)->flags) ? 0 : (!ITTNOTIFY_NAME(n)) ? 0 : ITTNOTIFY_NAME(n)(d,x) +#define ITTNOTIFY_DATA_D2(n,d,x,y) (!(d)->flags) ? 0 : (!ITTNOTIFY_NAME(n)) ? 0 : ITTNOTIFY_NAME(n)(d,x,y) +#define ITTNOTIFY_DATA_D3(n,d,x,y,z) (!(d)->flags) ? 0 : (!ITTNOTIFY_NAME(n)) ? 0 : ITTNOTIFY_NAME(n)(d,x,y,z) +#define ITTNOTIFY_DATA_D4(n,d,x,y,z,a) (!(d)->flags) ? 0 : (!ITTNOTIFY_NAME(n)) ? 0 : ITTNOTIFY_NAME(n)(d,x,y,z,a) +#define ITTNOTIFY_DATA_D5(n,d,x,y,z,a,b) (!(d)->flags) ? 0 : (!ITTNOTIFY_NAME(n)) ? 0 : ITTNOTIFY_NAME(n)(d,x,y,z,a,b) +#define ITTNOTIFY_DATA_D6(n,d,x,y,z,a,b,c) (!(d)->flags) ? 0 : (!ITTNOTIFY_NAME(n)) ? 0 : ITTNOTIFY_NAME(n)(d,x,y,z,a,b,c) + +#ifdef ITT_STUB +#undef ITT_STUB +#endif +#ifdef ITT_STUBV +#undef ITT_STUBV +#endif +#define ITT_STUBV(api,type,name,args) \ + typedef type (api* ITT_JOIN(ITTNOTIFY_NAME(name),_t)) args; \ + extern ITT_JOIN(ITTNOTIFY_NAME(name),_t) ITTNOTIFY_NAME(name); +#define ITT_STUB ITT_STUBV +/** @endcond */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup legacy Legacy API + * @{ + * @} + */ + +/** + * @defgroup legacy_control Collection Control + * @ingroup legacy + * General behavior: application continues to run, but no profiling information is being collected + * + * Pausing occurs not only for the current thread but for all process as well as spawned processes + * - Intel(R) Parallel Inspector and Intel(R) Inspector XE: + * - Does not analyze or report errors that involve memory access. + * - Other errors are reported as usual. Pausing data collection in + * Intel(R) Parallel Inspector and Intel(R) Inspector XE + * only pauses tracing and analyzing memory access. + * It does not pause tracing or analyzing threading APIs. + * . + * - Intel(R) Parallel Amplifier and Intel(R) VTune(TM) Amplifier XE: + * - Does continue to record when new threads are started. + * . + * - Other effects: + * - Possible reduction of runtime overhead. + * . + * @{ + */ +#ifndef _ITTNOTIFY_H_ +/** @brief Pause collection */ +void ITTAPI __itt_pause(void); +/** @brief Resume collection */ +void ITTAPI __itt_resume(void); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, pause, (void)) +ITT_STUBV(ITTAPI, void, resume, (void)) +#define __itt_pause ITTNOTIFY_VOID(pause) +#define __itt_pause_ptr ITTNOTIFY_NAME(pause) +#define __itt_resume ITTNOTIFY_VOID(resume) +#define __itt_resume_ptr ITTNOTIFY_NAME(resume) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_pause() +#define __itt_pause_ptr 0 +#define __itt_resume() +#define __itt_resume_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_pause_ptr 0 +#define __itt_resume_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +#endif /* _ITTNOTIFY_H_ */ +/** @} legacy_control group */ + +/** + * @defgroup legacy_threads Threads + * @ingroup legacy + * Threads group + * @warning Legacy API + * @{ + */ +/** + * @deprecated Legacy API + * @brief Set name to be associated with thread in analysis GUI. + * @return __itt_err upon failure (name or namelen being null,name and namelen mismatched) + */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +int LIBITTAPI __itt_thr_name_setA(const char *name, int namelen); +int LIBITTAPI __itt_thr_name_setW(const wchar_t *name, int namelen); +#if defined(UNICODE) || defined(_UNICODE) +# define __itt_thr_name_set __itt_thr_name_setW +# define __itt_thr_name_set_ptr __itt_thr_name_setW_ptr +#else +# define __itt_thr_name_set __itt_thr_name_setA +# define __itt_thr_name_set_ptr __itt_thr_name_setA_ptr +#endif /* UNICODE */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +int LIBITTAPI __itt_thr_name_set(const char *name, int namelen); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(LIBITTAPI, int, thr_name_setA, (const char *name, int namelen)) +ITT_STUB(LIBITTAPI, int, thr_name_setW, (const wchar_t *name, int namelen)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(LIBITTAPI, int, thr_name_set, (const char *name, int namelen)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_thr_name_setA ITTNOTIFY_DATA(thr_name_setA) +#define __itt_thr_name_setA_ptr ITTNOTIFY_NAME(thr_name_setA) +#define __itt_thr_name_setW ITTNOTIFY_DATA(thr_name_setW) +#define __itt_thr_name_setW_ptr ITTNOTIFY_NAME(thr_name_setW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_thr_name_set ITTNOTIFY_DATA(thr_name_set) +#define __itt_thr_name_set_ptr ITTNOTIFY_NAME(thr_name_set) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_thr_name_setA(name, namelen) +#define __itt_thr_name_setA_ptr 0 +#define __itt_thr_name_setW(name, namelen) +#define __itt_thr_name_setW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_thr_name_set(name, namelen) +#define __itt_thr_name_set_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_thr_name_setA_ptr 0 +#define __itt_thr_name_setW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_thr_name_set_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @deprecated Legacy API + * @brief Mark current thread as ignored from this point on, for the duration of its existence. + */ +void LIBITTAPI __itt_thr_ignore(void); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(LIBITTAPI, void, thr_ignore, (void)) +#define __itt_thr_ignore ITTNOTIFY_VOID(thr_ignore) +#define __itt_thr_ignore_ptr ITTNOTIFY_NAME(thr_ignore) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_thr_ignore() +#define __itt_thr_ignore_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_thr_ignore_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} legacy_threads group */ + +/** + * @defgroup legacy_sync Synchronization + * @ingroup legacy + * Synchronization group + * @warning Legacy API + * @{ + */ +/** + * @hideinitializer + * @brief possible value of attribute argument for sync object type + */ +#define __itt_attr_barrier 1 + +/** + * @hideinitializer + * @brief possible value of attribute argument for sync object type + */ +#define __itt_attr_mutex 2 + +/** + * @deprecated Legacy API + * @brief Assign a name to a sync object using char or Unicode string + * @param[in] addr - pointer to the sync object. You should use a real pointer to your object + * to make sure that the values don't clash with other object addresses + * @param[in] objtype - null-terminated object type string. If NULL is passed, the object will + * be assumed to be of generic "User Synchronization" type + * @param[in] objname - null-terminated object name string. If NULL, no name will be assigned + * to the object -- you can use the __itt_sync_rename call later to assign + * the name + * @param[in] attribute - one of [#__itt_attr_barrier, #__itt_attr_mutex] values which defines the + * exact semantics of how prepare/acquired/releasing calls work. + */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +void ITTAPI __itt_sync_set_nameA(void *addr, const char *objtype, const char *objname, int attribute); +void ITTAPI __itt_sync_set_nameW(void *addr, const wchar_t *objtype, const wchar_t *objname, int attribute); +#if defined(UNICODE) || defined(_UNICODE) +# define __itt_sync_set_name __itt_sync_set_nameW +# define __itt_sync_set_name_ptr __itt_sync_set_nameW_ptr +#else /* UNICODE */ +# define __itt_sync_set_name __itt_sync_set_nameA +# define __itt_sync_set_name_ptr __itt_sync_set_nameA_ptr +#endif /* UNICODE */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +void ITTAPI __itt_sync_set_name(void *addr, const char* objtype, const char* objname, int attribute); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUBV(ITTAPI, void, sync_set_nameA, (void *addr, const char *objtype, const char *objname, int attribute)) +ITT_STUBV(ITTAPI, void, sync_set_nameW, (void *addr, const wchar_t *objtype, const wchar_t *objname, int attribute)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUBV(ITTAPI, void, sync_set_name, (void *addr, const char *objtype, const char *objname, int attribute)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_sync_set_nameA ITTNOTIFY_VOID(sync_set_nameA) +#define __itt_sync_set_nameA_ptr ITTNOTIFY_NAME(sync_set_nameA) +#define __itt_sync_set_nameW ITTNOTIFY_VOID(sync_set_nameW) +#define __itt_sync_set_nameW_ptr ITTNOTIFY_NAME(sync_set_nameW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_sync_set_name ITTNOTIFY_VOID(sync_set_name) +#define __itt_sync_set_name_ptr ITTNOTIFY_NAME(sync_set_name) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_sync_set_nameA(addr, objtype, objname, attribute) +#define __itt_sync_set_nameA_ptr 0 +#define __itt_sync_set_nameW(addr, objtype, objname, attribute) +#define __itt_sync_set_nameW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_sync_set_name(addr, objtype, objname, attribute) +#define __itt_sync_set_name_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_sync_set_nameA_ptr 0 +#define __itt_sync_set_nameW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_sync_set_name_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @deprecated Legacy API + * @brief Assign a name and type to a sync object using char or Unicode string + * @param[in] addr - pointer to the sync object. You should use a real pointer to your object + * to make sure that the values don't clash with other object addresses + * @param[in] objtype - null-terminated object type string. If NULL is passed, the object will + * be assumed to be of generic "User Synchronization" type + * @param[in] objname - null-terminated object name string. If NULL, no name will be assigned + * to the object -- you can use the __itt_sync_rename call later to assign + * the name + * @param[in] typelen, namelen - a lenght of string for appropriate objtype and objname parameter + * @param[in] attribute - one of [#__itt_attr_barrier, #__itt_attr_mutex] values which defines the + * exact semantics of how prepare/acquired/releasing calls work. + * @return __itt_err upon failure (name or namelen being null,name and namelen mismatched) + */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +int LIBITTAPI __itt_notify_sync_nameA(void *addr, const char *objtype, int typelen, const char *objname, int namelen, int attribute); +int LIBITTAPI __itt_notify_sync_nameW(void *addr, const wchar_t *objtype, int typelen, const wchar_t *objname, int namelen, int attribute); +#if defined(UNICODE) || defined(_UNICODE) +# define __itt_notify_sync_name __itt_notify_sync_nameW +#else +# define __itt_notify_sync_name __itt_notify_sync_nameA +#endif +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +int LIBITTAPI __itt_notify_sync_name(void *addr, const char *objtype, int typelen, const char *objname, int namelen, int attribute); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(LIBITTAPI, int, notify_sync_nameA, (void *addr, const char *objtype, int typelen, const char *objname, int namelen, int attribute)) +ITT_STUB(LIBITTAPI, int, notify_sync_nameW, (void *addr, const wchar_t *objtype, int typelen, const wchar_t *objname, int namelen, int attribute)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(LIBITTAPI, int, notify_sync_name, (void *addr, const char *objtype, int typelen, const char *objname, int namelen, int attribute)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_notify_sync_nameA ITTNOTIFY_DATA(notify_sync_nameA) +#define __itt_notify_sync_nameA_ptr ITTNOTIFY_NAME(notify_sync_nameA) +#define __itt_notify_sync_nameW ITTNOTIFY_DATA(notify_sync_nameW) +#define __itt_notify_sync_nameW_ptr ITTNOTIFY_NAME(notify_sync_nameW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_notify_sync_name ITTNOTIFY_DATA(notify_sync_name) +#define __itt_notify_sync_name_ptr ITTNOTIFY_NAME(notify_sync_name) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_notify_sync_nameA(addr, objtype, typelen, objname, namelen, attribute) +#define __itt_notify_sync_nameA_ptr 0 +#define __itt_notify_sync_nameW(addr, objtype, typelen, objname, namelen, attribute) +#define __itt_notify_sync_nameW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_notify_sync_name(addr, objtype, typelen, objname, namelen, attribute) +#define __itt_notify_sync_name_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_notify_sync_nameA_ptr 0 +#define __itt_notify_sync_nameW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_notify_sync_name_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @deprecated Legacy API + * @brief Enter spin loop on user-defined sync object + */ +void LIBITTAPI __itt_notify_sync_prepare(void* addr); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(LIBITTAPI, void, notify_sync_prepare, (void *addr)) +#define __itt_notify_sync_prepare ITTNOTIFY_VOID(notify_sync_prepare) +#define __itt_notify_sync_prepare_ptr ITTNOTIFY_NAME(notify_sync_prepare) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_notify_sync_prepare(addr) +#define __itt_notify_sync_prepare_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_notify_sync_prepare_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @deprecated Legacy API + * @brief Quit spin loop without acquiring spin object + */ +void LIBITTAPI __itt_notify_sync_cancel(void *addr); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(LIBITTAPI, void, notify_sync_cancel, (void *addr)) +#define __itt_notify_sync_cancel ITTNOTIFY_VOID(notify_sync_cancel) +#define __itt_notify_sync_cancel_ptr ITTNOTIFY_NAME(notify_sync_cancel) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_notify_sync_cancel(addr) +#define __itt_notify_sync_cancel_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_notify_sync_cancel_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @deprecated Legacy API + * @brief Successful spin loop completion (sync object acquired) + */ +void LIBITTAPI __itt_notify_sync_acquired(void *addr); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(LIBITTAPI, void, notify_sync_acquired, (void *addr)) +#define __itt_notify_sync_acquired ITTNOTIFY_VOID(notify_sync_acquired) +#define __itt_notify_sync_acquired_ptr ITTNOTIFY_NAME(notify_sync_acquired) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_notify_sync_acquired(addr) +#define __itt_notify_sync_acquired_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_notify_sync_acquired_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @deprecated Legacy API + * @brief Start sync object releasing code. Is called before the lock release call. + */ +void LIBITTAPI __itt_notify_sync_releasing(void* addr); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(LIBITTAPI, void, notify_sync_releasing, (void *addr)) +#define __itt_notify_sync_releasing ITTNOTIFY_VOID(notify_sync_releasing) +#define __itt_notify_sync_releasing_ptr ITTNOTIFY_NAME(notify_sync_releasing) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_notify_sync_releasing(addr) +#define __itt_notify_sync_releasing_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_notify_sync_releasing_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} legacy_sync group */ + +#ifndef _ITTNOTIFY_H_ +/** + * @defgroup legacy_events Events + * @ingroup legacy + * Events group + * @{ + */ + +/** @brief user event type */ +typedef int __itt_event; + +/** + * @brief Create an event notification + * @note name or namelen being null/name and namelen not matching, user event feature not enabled + * @return non-zero event identifier upon success and __itt_err otherwise + */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +__itt_event LIBITTAPI __itt_event_createA(const char *name, int namelen); +__itt_event LIBITTAPI __itt_event_createW(const wchar_t *name, int namelen); +#if defined(UNICODE) || defined(_UNICODE) +# define __itt_event_create __itt_event_createW +# define __itt_event_create_ptr __itt_event_createW_ptr +#else +# define __itt_event_create __itt_event_createA +# define __itt_event_create_ptr __itt_event_createA_ptr +#endif /* UNICODE */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +__itt_event LIBITTAPI __itt_event_create(const char *name, int namelen); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(LIBITTAPI, __itt_event, event_createA, (const char *name, int namelen)) +ITT_STUB(LIBITTAPI, __itt_event, event_createW, (const wchar_t *name, int namelen)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(LIBITTAPI, __itt_event, event_create, (const char *name, int namelen)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_event_createA ITTNOTIFY_DATA(event_createA) +#define __itt_event_createA_ptr ITTNOTIFY_NAME(event_createA) +#define __itt_event_createW ITTNOTIFY_DATA(event_createW) +#define __itt_event_createW_ptr ITTNOTIFY_NAME(event_createW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_event_create ITTNOTIFY_DATA(event_create) +#define __itt_event_create_ptr ITTNOTIFY_NAME(event_create) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_event_createA(name, namelen) (__itt_event)0 +#define __itt_event_createA_ptr 0 +#define __itt_event_createW(name, namelen) (__itt_event)0 +#define __itt_event_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_event_create(name, namelen) (__itt_event)0 +#define __itt_event_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_event_createA_ptr 0 +#define __itt_event_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_event_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Record an event occurrence. + * @return __itt_err upon failure (invalid event id/user event feature not enabled) + */ +int LIBITTAPI __itt_event_start(__itt_event event); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUB(LIBITTAPI, int, event_start, (__itt_event event)) +#define __itt_event_start ITTNOTIFY_DATA(event_start) +#define __itt_event_start_ptr ITTNOTIFY_NAME(event_start) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_event_start(event) (int)0 +#define __itt_event_start_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_event_start_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @brief Record an event end occurrence. + * @note It is optional if events do not have durations. + * @return __itt_err upon failure (invalid event id/user event feature not enabled) + */ +int LIBITTAPI __itt_event_end(__itt_event event); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUB(LIBITTAPI, int, event_end, (__itt_event event)) +#define __itt_event_end ITTNOTIFY_DATA(event_end) +#define __itt_event_end_ptr ITTNOTIFY_NAME(event_end) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_event_end(event) (int)0 +#define __itt_event_end_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_event_end_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} legacy_events group */ +#endif /* _ITTNOTIFY_H_ */ + +/** + * @defgroup legacy_memory Memory Accesses + * @ingroup legacy + */ + +/** + * @deprecated Legacy API + * @brief Inform the tool of memory accesses on reading + */ +void LIBITTAPI __itt_memory_read(void *addr, size_t size); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(LIBITTAPI, void, memory_read, (void *addr, size_t size)) +#define __itt_memory_read ITTNOTIFY_VOID(memory_read) +#define __itt_memory_read_ptr ITTNOTIFY_NAME(memory_read) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_memory_read(addr, size) +#define __itt_memory_read_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_memory_read_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @deprecated Legacy API + * @brief Inform the tool of memory accesses on writing + */ +void LIBITTAPI __itt_memory_write(void *addr, size_t size); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(LIBITTAPI, void, memory_write, (void *addr, size_t size)) +#define __itt_memory_write ITTNOTIFY_VOID(memory_write) +#define __itt_memory_write_ptr ITTNOTIFY_NAME(memory_write) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_memory_write(addr, size) +#define __itt_memory_write_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_memory_write_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @deprecated Legacy API + * @brief Inform the tool of memory accesses on updating + */ +void LIBITTAPI __itt_memory_update(void *address, size_t size); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(LIBITTAPI, void, memory_update, (void *addr, size_t size)) +#define __itt_memory_update ITTNOTIFY_VOID(memory_update) +#define __itt_memory_update_ptr ITTNOTIFY_NAME(memory_update) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_memory_update(addr, size) +#define __itt_memory_update_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_memory_update_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} legacy_memory group */ + +/** + * @defgroup legacy_state Thread and Object States + * @ingroup legacy + */ + +/** @brief state type */ +typedef int __itt_state_t; + +/** @cond exclude_from_documentation */ +typedef enum __itt_obj_state { + __itt_obj_state_err = 0, + __itt_obj_state_clr = 1, + __itt_obj_state_set = 2, + __itt_obj_state_use = 3 +} __itt_obj_state_t; + +typedef enum __itt_thr_state { + __itt_thr_state_err = 0, + __itt_thr_state_clr = 1, + __itt_thr_state_set = 2 +} __itt_thr_state_t; + +typedef enum __itt_obj_prop { + __itt_obj_prop_watch = 1, + __itt_obj_prop_ignore = 2, + __itt_obj_prop_sharable = 3 +} __itt_obj_prop_t; + +typedef enum __itt_thr_prop { + __itt_thr_prop_quiet = 1 +} __itt_thr_prop_t; +/** @endcond */ + +/** + * @deprecated Legacy API + * @brief managing thread and object states + */ +__itt_state_t LIBITTAPI __itt_state_get(void); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUB(ITTAPI, __itt_state_t, state_get, (void)) +#define __itt_state_get ITTNOTIFY_DATA(state_get) +#define __itt_state_get_ptr ITTNOTIFY_NAME(state_get) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_state_get(void) (__itt_state_t)0 +#define __itt_state_get_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_state_get_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @deprecated Legacy API + * @brief managing thread and object states + */ +__itt_state_t LIBITTAPI __itt_state_set(__itt_state_t s); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUB(ITTAPI, __itt_state_t, state_set, (__itt_state_t s)) +#define __itt_state_set ITTNOTIFY_DATA(state_set) +#define __itt_state_set_ptr ITTNOTIFY_NAME(state_set) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_state_set(s) (__itt_state_t)0 +#define __itt_state_set_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_state_set_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @deprecated Legacy API + * @brief managing thread and object modes + */ +__itt_thr_state_t LIBITTAPI __itt_thr_mode_set(__itt_thr_prop_t p, __itt_thr_state_t s); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUB(ITTAPI, __itt_thr_state_t, thr_mode_set, (__itt_thr_prop_t p, __itt_thr_state_t s)) +#define __itt_thr_mode_set ITTNOTIFY_DATA(thr_mode_set) +#define __itt_thr_mode_set_ptr ITTNOTIFY_NAME(thr_mode_set) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_thr_mode_set(p, s) (__itt_thr_state_t)0 +#define __itt_thr_mode_set_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_thr_mode_set_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** + * @deprecated Legacy API + * @brief managing thread and object modes + */ +__itt_obj_state_t LIBITTAPI __itt_obj_mode_set(__itt_obj_prop_t p, __itt_obj_state_t s); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUB(ITTAPI, __itt_obj_state_t, obj_mode_set, (__itt_obj_prop_t p, __itt_obj_state_t s)) +#define __itt_obj_mode_set ITTNOTIFY_DATA(obj_mode_set) +#define __itt_obj_mode_set_ptr ITTNOTIFY_NAME(obj_mode_set) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_obj_mode_set(p, s) (__itt_obj_state_t)0 +#define __itt_obj_mode_set_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_obj_mode_set_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} legacy_state group */ + +/** + * @defgroup frames Frames + * @ingroup legacy + * Frames group + * @{ + */ +/** + * @brief opaque structure for frame identification + */ +typedef struct __itt_frame_t *__itt_frame; + +/** + * @brief Create a global frame with given domain + */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +__itt_frame ITTAPI __itt_frame_createA(const char *domain); +__itt_frame ITTAPI __itt_frame_createW(const wchar_t *domain); +#if defined(UNICODE) || defined(_UNICODE) +# define __itt_frame_create __itt_frame_createW +# define __itt_frame_create_ptr __itt_frame_createW_ptr +#else /* UNICODE */ +# define __itt_frame_create __itt_frame_createA +# define __itt_frame_create_ptr __itt_frame_createA_ptr +#endif /* UNICODE */ +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +__itt_frame ITTAPI __itt_frame_create(const char *domain); +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +#if ITT_PLATFORM==ITT_PLATFORM_WIN +ITT_STUB(ITTAPI, __itt_frame, frame_createA, (const char *domain)) +ITT_STUB(ITTAPI, __itt_frame, frame_createW, (const wchar_t *domain)) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +ITT_STUB(ITTAPI, __itt_frame, frame_create, (const char *domain)) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_frame_createA ITTNOTIFY_DATA(frame_createA) +#define __itt_frame_createA_ptr ITTNOTIFY_NAME(frame_createA) +#define __itt_frame_createW ITTNOTIFY_DATA(frame_createW) +#define __itt_frame_createW_ptr ITTNOTIFY_NAME(frame_createW) +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_frame_create ITTNOTIFY_DATA(frame_create) +#define __itt_frame_create_ptr ITTNOTIFY_NAME(frame_create) +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#else /* INTEL_NO_ITTNOTIFY_API */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_frame_createA(domain) +#define __itt_frame_createA_ptr 0 +#define __itt_frame_createW(domain) +#define __itt_frame_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_frame_create(domain) +#define __itt_frame_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#define __itt_frame_createA_ptr 0 +#define __itt_frame_createW_ptr 0 +#else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#define __itt_frame_create_ptr 0 +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ + +/** @brief Record an frame begin occurrence. */ +void ITTAPI __itt_frame_begin(__itt_frame frame); +/** @brief Record an frame end occurrence. */ +void ITTAPI __itt_frame_end (__itt_frame frame); + +/** @cond exclude_from_documentation */ +#ifndef INTEL_NO_MACRO_BODY +#ifndef INTEL_NO_ITTNOTIFY_API +ITT_STUBV(ITTAPI, void, frame_begin, (__itt_frame frame)) +ITT_STUBV(ITTAPI, void, frame_end, (__itt_frame frame)) +#define __itt_frame_begin ITTNOTIFY_VOID(frame_begin) +#define __itt_frame_begin_ptr ITTNOTIFY_NAME(frame_begin) +#define __itt_frame_end ITTNOTIFY_VOID(frame_end) +#define __itt_frame_end_ptr ITTNOTIFY_NAME(frame_end) +#else /* INTEL_NO_ITTNOTIFY_API */ +#define __itt_frame_begin(frame) +#define __itt_frame_begin_ptr 0 +#define __itt_frame_end(frame) +#define __itt_frame_end_ptr 0 +#endif /* INTEL_NO_ITTNOTIFY_API */ +#else /* INTEL_NO_MACRO_BODY */ +#define __itt_frame_begin_ptr 0 +#define __itt_frame_end_ptr 0 +#endif /* INTEL_NO_MACRO_BODY */ +/** @endcond */ +/** @} frames group */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _LEGACY_ITTNOTIFY_H_ */ diff --git a/src/tbb/src/tbb/tools_api/prototype/ittnotify.h b/src/tbb/src/tbb/tools_api/prototype/ittnotify.h new file mode 100644 index 0000000..856d6b6 --- /dev/null +++ b/src/tbb/src/tbb/tools_api/prototype/ittnotify.h @@ -0,0 +1,148 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _PROTOTYPE_ITTNOTIFY_H_ +#define _PROTOTYPE_ITTNOTIFY_H_ +/** + * @file + * @brief Prototype User API functions and types + */ + +/** @cond exclude_from_documentation */ +#ifndef ITT_OS_WIN +# define ITT_OS_WIN 1 +#endif /* ITT_OS_WIN */ + +#ifndef ITT_OS_LINUX +# define ITT_OS_LINUX 2 +#endif /* ITT_OS_LINUX */ + +#ifndef ITT_OS_MAC +# define ITT_OS_MAC 3 +#endif /* ITT_OS_MAC */ + +#ifndef ITT_OS +# if defined WIN32 || defined _WIN32 +# define ITT_OS ITT_OS_WIN +# elif defined( __APPLE__ ) && defined( __MACH__ ) +# define ITT_OS ITT_OS_MAC +# else +# define ITT_OS ITT_OS_LINUX +# endif +#endif /* ITT_OS */ + +#ifndef ITT_PLATFORM_WIN +# define ITT_PLATFORM_WIN 1 +#endif /* ITT_PLATFORM_WIN */ + +#ifndef ITT_PLATFORM_POSIX +# define ITT_PLATFORM_POSIX 2 +#endif /* ITT_PLATFORM_POSIX */ + +#ifndef ITT_PLATFORM +# if ITT_OS==ITT_OS_WIN +# define ITT_PLATFORM ITT_PLATFORM_WIN +# else +# define ITT_PLATFORM ITT_PLATFORM_POSIX +# endif /* _WIN32 */ +#endif /* ITT_PLATFORM */ + +#include <stddef.h> +#include <stdarg.h> +#if ITT_PLATFORM==ITT_PLATFORM_WIN +#include <tchar.h> +#endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ + +#ifndef CDECL +# if ITT_PLATFORM==ITT_PLATFORM_WIN +# define CDECL __cdecl +# else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +# define CDECL /* nothing */ +# endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* CDECL */ + +#ifndef STDCALL +# if ITT_PLATFORM==ITT_PLATFORM_WIN +# define STDCALL __stdcall +# else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +# define STDCALL /* nothing */ +# endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ +#endif /* STDCALL */ + +#define ITTAPI_CALL CDECL +#define LIBITTAPI_CALL /* nothing */ + +#define ITT_JOIN_AUX(p,n) p##n +#define ITT_JOIN(p,n) ITT_JOIN_AUX(p,n) + +#ifndef INTEL_ITTNOTIFY_PREFIX +# define INTEL_ITTNOTIFY_PREFIX __itt_ +#endif /* INTEL_ITTNOTIFY_PREFIX */ +#ifndef INTEL_ITTNOTIFY_POSTFIX +# define INTEL_ITTNOTIFY_POSTFIX _ptr_ +#endif /* INTEL_ITTNOTIFY_POSTFIX */ + +#define ITTNOTIFY_NAME_AUX(n) ITT_JOIN(INTEL_ITTNOTIFY_PREFIX,n) +#define ITTNOTIFY_NAME(n) ITTNOTIFY_NAME_AUX(ITT_JOIN(n,INTEL_ITTNOTIFY_POSTFIX)) + +#define ITTNOTIFY_VOID(n) (!ITTNOTIFY_NAME(n)) ? (void)0 : ITTNOTIFY_NAME(n) +#define ITTNOTIFY_DATA(n) (!ITTNOTIFY_NAME(n)) ? 0 : ITTNOTIFY_NAME(n) + +#ifdef ITT_STUB +#undef ITT_STUB +#endif +#ifdef ITT_STUBV +#undef ITT_STUBV +#endif +#define ITT_STUBV(api,type,name,args,params) \ + typedef type (api* ITT_JOIN(ITTNOTIFY_NAME(name),_t)) args; \ + extern ITT_JOIN(ITTNOTIFY_NAME(name),_t) ITTNOTIFY_NAME(name); +#define ITT_STUB ITT_STUBV + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ +/** @endcond */ + +/** + * @defgroup prototype Prototype API + * @{ + * @} + */ + +/**************************************************************************** + * ??? group + ****************************************************************************/ + +/** @cond exclude_from_documentation */ +#ifdef __cplusplus +} +#endif /* __cplusplus */ +/** @endcond */ + +#endif /* _PROTOTYPE_ITTNOTIFY_H_ */ diff --git a/src/tbb/src/tbb/win32-tbb-export.def b/src/tbb/src/tbb/win32-tbb-export.def new file mode 100644 index 0000000..488ad0b --- /dev/null +++ b/src/tbb/src/tbb/win32-tbb-export.def @@ -0,0 +1,31 @@ +; Copyright 2005-2012 Intel Corporation. All Rights Reserved. +; +; This file is part of Threading Building Blocks. +; +; Threading Building Blocks is free software; you can redistribute it +; and/or modify it under the terms of the GNU General Public License +; version 2 as published by the Free Software Foundation. +; +; Threading Building Blocks is distributed in the hope that it will be +; useful, but WITHOUT ANY WARRANTY; without even the implied warranty +; of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with Threading Building Blocks; if not, write to the Free Software +; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +; +; As a special exception, you may use this file as part of a free software +; library without restriction. Specifically, if other files instantiate +; templates or use macros or inline functions from this file, or you compile +; this file and link it with other files to produce an executable, this +; file does not by itself cause the resulting executable to be covered by +; the GNU General Public License. This exception does not however +; invalidate any other reasons why the executable file might be covered by +; the GNU General Public License. + +EXPORTS + +#define __TBB_SYMBOL( sym ) sym +#include "win32-tbb-export.lst" + diff --git a/src/tbb/src/tbb/win32-tbb-export.lst b/src/tbb/src/tbb/win32-tbb-export.lst new file mode 100644 index 0000000..2c8e98a --- /dev/null +++ b/src/tbb/src/tbb/win32-tbb-export.lst @@ -0,0 +1,300 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + The source code contained or described herein and all documents related + to the source code ("Material") are owned by Intel Corporation or its + suppliers or licensors. Title to the Material remains with Intel + Corporation or its suppliers and licensors. The Material is protected + by worldwide copyright laws and treaty provisions. No part of the + Material may be used, copied, reproduced, modified, published, uploaded, + posted, transmitted, distributed, or disclosed in any way without + Intel's prior express written permission. + + No license under any patent, copyright, trade secret or other + intellectual property right is granted to or conferred upon you by + disclosure or delivery of the Materials, either expressly, by + implication, inducement, estoppel or otherwise. Any license under such + intellectual property rights must be express and approved by Intel in + writing. +*/ + +#include "tbb/tbb_config.h" + +// Assembly-language support that is called directly by clients +// __TBB_SYMBOL( __TBB_machine_cmpswp1 ) +// __TBB_SYMBOL( __TBB_machine_cmpswp2 ) +// __TBB_SYMBOL( __TBB_machine_cmpswp4 ) +__TBB_SYMBOL( __TBB_machine_cmpswp8 ) +// __TBB_SYMBOL( __TBB_machine_fetchadd1 ) +// __TBB_SYMBOL( __TBB_machine_fetchadd2 ) +// __TBB_SYMBOL( __TBB_machine_fetchadd4 ) +__TBB_SYMBOL( __TBB_machine_fetchadd8 ) +// __TBB_SYMBOL( __TBB_machine_fetchstore1 ) +// __TBB_SYMBOL( __TBB_machine_fetchstore2 ) +// __TBB_SYMBOL( __TBB_machine_fetchstore4 ) +__TBB_SYMBOL( __TBB_machine_fetchstore8 ) +__TBB_SYMBOL( __TBB_machine_store8 ) +__TBB_SYMBOL( __TBB_machine_load8 ) +__TBB_SYMBOL( __TBB_machine_trylockbyte ) + +// cache_aligned_allocator.cpp +__TBB_SYMBOL( ?NFS_Allocate@internal@tbb@@YAPAXIIPAX@Z ) +__TBB_SYMBOL( ?NFS_GetLineSize@internal@tbb@@YAIXZ ) +__TBB_SYMBOL( ?NFS_Free@internal@tbb@@YAXPAX@Z ) +__TBB_SYMBOL( ?allocate_via_handler_v3@internal@tbb@@YAPAXI@Z ) +__TBB_SYMBOL( ?deallocate_via_handler_v3@internal@tbb@@YAXPAX@Z ) +__TBB_SYMBOL( ?is_malloc_used_v3@internal@tbb@@YA_NXZ ) + +// task.cpp v3 +__TBB_SYMBOL( ?allocate@allocate_additional_child_of_proxy@internal@tbb@@QBEAAVtask@3@I@Z ) +__TBB_SYMBOL( ?allocate@allocate_child_proxy@internal@tbb@@QBEAAVtask@3@I@Z ) +__TBB_SYMBOL( ?allocate@allocate_continuation_proxy@internal@tbb@@QBEAAVtask@3@I@Z ) +__TBB_SYMBOL( ?allocate@allocate_root_proxy@internal@tbb@@SAAAVtask@3@I@Z ) +__TBB_SYMBOL( ?destroy@task_base@internal@interface5@tbb@@SAXAAVtask@4@@Z ) +__TBB_SYMBOL( ?free@allocate_additional_child_of_proxy@internal@tbb@@QBEXAAVtask@3@@Z ) +__TBB_SYMBOL( ?free@allocate_child_proxy@internal@tbb@@QBEXAAVtask@3@@Z ) +__TBB_SYMBOL( ?free@allocate_continuation_proxy@internal@tbb@@QBEXAAVtask@3@@Z ) +__TBB_SYMBOL( ?free@allocate_root_proxy@internal@tbb@@SAXAAVtask@3@@Z ) +__TBB_SYMBOL( ?internal_set_ref_count@task@tbb@@AAEXH@Z ) +__TBB_SYMBOL( ?internal_decrement_ref_count@task@tbb@@AAEHXZ ) +__TBB_SYMBOL( ?is_owned_by_current_thread@task@tbb@@QBE_NXZ ) +__TBB_SYMBOL( ?note_affinity@task@tbb@@UAEXG@Z ) +__TBB_SYMBOL( ?resize@affinity_partitioner_base_v3@internal@tbb@@AAEXI@Z ) +__TBB_SYMBOL( ?self@task@tbb@@SAAAV12@XZ ) +__TBB_SYMBOL( ?spawn_and_wait_for_all@task@tbb@@QAEXAAVtask_list@2@@Z ) +__TBB_SYMBOL( ?default_num_threads@task_scheduler_init@tbb@@SAHXZ ) +__TBB_SYMBOL( ?initialize@task_scheduler_init@tbb@@QAEXHI@Z ) +__TBB_SYMBOL( ?initialize@task_scheduler_init@tbb@@QAEXH@Z ) +__TBB_SYMBOL( ?terminate@task_scheduler_init@tbb@@QAEXXZ ) +__TBB_SYMBOL( ?observe@task_scheduler_observer_v3@internal@tbb@@QAEX_N@Z ) + +#if !TBB_NO_LEGACY +// task_v2.cpp +__TBB_SYMBOL( ?destroy@task@tbb@@QAEXAAV12@@Z ) +#endif + +// exception handling support +#if __TBB_TASK_GROUP_CONTEXT +__TBB_SYMBOL( ?allocate@allocate_root_with_context_proxy@internal@tbb@@QBEAAVtask@3@I@Z ) +__TBB_SYMBOL( ?free@allocate_root_with_context_proxy@internal@tbb@@QBEXAAVtask@3@@Z ) +__TBB_SYMBOL( ?change_group@task@tbb@@QAEXAAVtask_group_context@2@@Z ) +__TBB_SYMBOL( ?is_group_execution_cancelled@task_group_context@tbb@@QBE_NXZ ) +__TBB_SYMBOL( ?cancel_group_execution@task_group_context@tbb@@QAE_NXZ ) +__TBB_SYMBOL( ?reset@task_group_context@tbb@@QAEXXZ ) +__TBB_SYMBOL( ?init@task_group_context@tbb@@IAEXXZ ) +__TBB_SYMBOL( ?register_pending_exception@task_group_context@tbb@@QAEXXZ ) +__TBB_SYMBOL( ??1task_group_context@tbb@@QAE@XZ ) +#if __TBB_TASK_PRIORITY +__TBB_SYMBOL( ?set_priority@task_group_context@tbb@@QAEXW4priority_t@2@@Z ) +__TBB_SYMBOL( ?priority@task_group_context@tbb@@QBE?AW4priority_t@2@XZ ) +#endif /* __TBB_TASK_PRIORITY */ +__TBB_SYMBOL( ?name@captured_exception@tbb@@UBEPBDXZ ) +__TBB_SYMBOL( ?what@captured_exception@tbb@@UBEPBDXZ ) +__TBB_SYMBOL( ??1captured_exception@tbb@@UAE@XZ ) +__TBB_SYMBOL( ?move@captured_exception@tbb@@UAEPAV12@XZ ) +__TBB_SYMBOL( ?destroy@captured_exception@tbb@@UAEXXZ ) +__TBB_SYMBOL( ?set@captured_exception@tbb@@QAEXPBD0@Z ) +__TBB_SYMBOL( ?clear@captured_exception@tbb@@QAEXXZ ) +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +// Symbols for exceptions thrown from TBB +__TBB_SYMBOL( ?throw_bad_last_alloc_exception_v4@internal@tbb@@YAXXZ ) +__TBB_SYMBOL( ?throw_exception_v4@internal@tbb@@YAXW4exception_id@12@@Z ) +__TBB_SYMBOL( ?what@bad_last_alloc@tbb@@UBEPBDXZ ) +__TBB_SYMBOL( ?what@missing_wait@tbb@@UBEPBDXZ ) +__TBB_SYMBOL( ?what@invalid_multiple_scheduling@tbb@@UBEPBDXZ ) +__TBB_SYMBOL( ?what@improper_lock@tbb@@UBEPBDXZ ) +__TBB_SYMBOL( ?what@user_abort@tbb@@UBEPBDXZ ) + +// tbb_misc.cpp +__TBB_SYMBOL( ?assertion_failure@tbb@@YAXPBDH00@Z ) +__TBB_SYMBOL( ?get_initial_auto_partitioner_divisor@internal@tbb@@YAIXZ ) +__TBB_SYMBOL( ?handle_perror@internal@tbb@@YAXHPBD@Z ) +__TBB_SYMBOL( ?set_assertion_handler@tbb@@YAP6AXPBDH00@ZP6AX0H00@Z@Z ) +__TBB_SYMBOL( ?runtime_warning@internal@tbb@@YAXPBDZZ ) +__TBB_SYMBOL( TBB_runtime_interface_version ) + +// tbb_main.cpp +__TBB_SYMBOL( ?itt_load_pointer_with_acquire_v3@internal@tbb@@YAPAXPBX@Z ) +__TBB_SYMBOL( ?itt_store_pointer_with_release_v3@internal@tbb@@YAXPAX0@Z ) +__TBB_SYMBOL( ?call_itt_notify_v5@internal@tbb@@YAXHPAX@Z ) +__TBB_SYMBOL( ?itt_set_sync_name_v3@internal@tbb@@YAXPAXPB_W@Z ) +__TBB_SYMBOL( ?itt_load_pointer_v3@internal@tbb@@YAPAXPBX@Z ) + +// pipeline.cpp +__TBB_SYMBOL( ??0pipeline@tbb@@QAE@XZ ) +__TBB_SYMBOL( ??1filter@tbb@@UAE@XZ ) +__TBB_SYMBOL( ??1pipeline@tbb@@UAE@XZ ) +__TBB_SYMBOL( ??_7pipeline@tbb@@6B@ ) +__TBB_SYMBOL( ?add_filter@pipeline@tbb@@QAEXAAVfilter@2@@Z ) +__TBB_SYMBOL( ?clear@pipeline@tbb@@QAEXXZ ) +__TBB_SYMBOL( ?inject_token@pipeline@tbb@@AAEXAAVtask@2@@Z ) +__TBB_SYMBOL( ?run@pipeline@tbb@@QAEXI@Z ) +#if __TBB_TASK_GROUP_CONTEXT +__TBB_SYMBOL( ?run@pipeline@tbb@@QAEXIAAVtask_group_context@2@@Z ) +#endif +__TBB_SYMBOL( ?process_item@thread_bound_filter@tbb@@QAE?AW4result_type@12@XZ ) +__TBB_SYMBOL( ?try_process_item@thread_bound_filter@tbb@@QAE?AW4result_type@12@XZ ) +__TBB_SYMBOL( ?set_end_of_input@filter@tbb@@IAEXXZ ) + +// queuing_rw_mutex.cpp +__TBB_SYMBOL( ?internal_construct@queuing_rw_mutex@tbb@@QAEXXZ ) +__TBB_SYMBOL( ?acquire@scoped_lock@queuing_rw_mutex@tbb@@QAEXAAV23@_N@Z ) +__TBB_SYMBOL( ?downgrade_to_reader@scoped_lock@queuing_rw_mutex@tbb@@QAE_NXZ ) +__TBB_SYMBOL( ?release@scoped_lock@queuing_rw_mutex@tbb@@QAEXXZ ) +__TBB_SYMBOL( ?upgrade_to_writer@scoped_lock@queuing_rw_mutex@tbb@@QAE_NXZ ) +__TBB_SYMBOL( ?try_acquire@scoped_lock@queuing_rw_mutex@tbb@@QAE_NAAV23@_N@Z ) + +// reader_writer_lock.cpp +__TBB_SYMBOL( ?try_lock_read@reader_writer_lock@interface5@tbb@@QAE_NXZ ) +__TBB_SYMBOL( ?try_lock@reader_writer_lock@interface5@tbb@@QAE_NXZ ) +__TBB_SYMBOL( ?unlock@reader_writer_lock@interface5@tbb@@QAEXXZ ) +__TBB_SYMBOL( ?lock_read@reader_writer_lock@interface5@tbb@@QAEXXZ ) +__TBB_SYMBOL( ?lock@reader_writer_lock@interface5@tbb@@QAEXXZ ) +__TBB_SYMBOL( ?internal_construct@reader_writer_lock@interface5@tbb@@AAEXXZ ) +__TBB_SYMBOL( ?internal_destroy@reader_writer_lock@interface5@tbb@@AAEXXZ ) +__TBB_SYMBOL( ?internal_construct@scoped_lock@reader_writer_lock@interface5@tbb@@AAEXAAV234@@Z ) +__TBB_SYMBOL( ?internal_destroy@scoped_lock@reader_writer_lock@interface5@tbb@@AAEXXZ ) +__TBB_SYMBOL( ?internal_construct@scoped_lock_read@reader_writer_lock@interface5@tbb@@AAEXAAV234@@Z ) +__TBB_SYMBOL( ?internal_destroy@scoped_lock_read@reader_writer_lock@interface5@tbb@@AAEXXZ ) + +#if !TBB_NO_LEGACY +// spin_rw_mutex.cpp v2 +__TBB_SYMBOL( ?internal_acquire_reader@spin_rw_mutex@tbb@@CAXPAV12@@Z ) +__TBB_SYMBOL( ?internal_acquire_writer@spin_rw_mutex@tbb@@CA_NPAV12@@Z ) +__TBB_SYMBOL( ?internal_downgrade@spin_rw_mutex@tbb@@CAXPAV12@@Z ) +__TBB_SYMBOL( ?internal_itt_releasing@spin_rw_mutex@tbb@@CAXPAV12@@Z ) +__TBB_SYMBOL( ?internal_release_reader@spin_rw_mutex@tbb@@CAXPAV12@@Z ) +__TBB_SYMBOL( ?internal_release_writer@spin_rw_mutex@tbb@@CAXPAV12@@Z ) +__TBB_SYMBOL( ?internal_upgrade@spin_rw_mutex@tbb@@CA_NPAV12@@Z ) +__TBB_SYMBOL( ?internal_try_acquire_writer@spin_rw_mutex@tbb@@CA_NPAV12@@Z ) +__TBB_SYMBOL( ?internal_try_acquire_reader@spin_rw_mutex@tbb@@CA_NPAV12@@Z ) +#endif + +// spin_rw_mutex v3 +__TBB_SYMBOL( ?internal_construct@spin_rw_mutex_v3@tbb@@AAEXXZ ) +__TBB_SYMBOL( ?internal_upgrade@spin_rw_mutex_v3@tbb@@AAE_NXZ ) +__TBB_SYMBOL( ?internal_downgrade@spin_rw_mutex_v3@tbb@@AAEXXZ ) +__TBB_SYMBOL( ?internal_acquire_reader@spin_rw_mutex_v3@tbb@@AAEXXZ ) +__TBB_SYMBOL( ?internal_acquire_writer@spin_rw_mutex_v3@tbb@@AAE_NXZ ) +__TBB_SYMBOL( ?internal_release_reader@spin_rw_mutex_v3@tbb@@AAEXXZ ) +__TBB_SYMBOL( ?internal_release_writer@spin_rw_mutex_v3@tbb@@AAEXXZ ) +__TBB_SYMBOL( ?internal_try_acquire_reader@spin_rw_mutex_v3@tbb@@AAE_NXZ ) +__TBB_SYMBOL( ?internal_try_acquire_writer@spin_rw_mutex_v3@tbb@@AAE_NXZ ) + +// spin_mutex.cpp +__TBB_SYMBOL( ?internal_construct@spin_mutex@tbb@@QAEXXZ ) +__TBB_SYMBOL( ?internal_acquire@scoped_lock@spin_mutex@tbb@@AAEXAAV23@@Z ) +__TBB_SYMBOL( ?internal_release@scoped_lock@spin_mutex@tbb@@AAEXXZ ) +__TBB_SYMBOL( ?internal_try_acquire@scoped_lock@spin_mutex@tbb@@AAE_NAAV23@@Z ) + +// mutex.cpp +__TBB_SYMBOL( ?internal_acquire@scoped_lock@mutex@tbb@@AAEXAAV23@@Z ) +__TBB_SYMBOL( ?internal_release@scoped_lock@mutex@tbb@@AAEXXZ ) +__TBB_SYMBOL( ?internal_try_acquire@scoped_lock@mutex@tbb@@AAE_NAAV23@@Z ) +__TBB_SYMBOL( ?internal_construct@mutex@tbb@@AAEXXZ ) +__TBB_SYMBOL( ?internal_destroy@mutex@tbb@@AAEXXZ ) + +// recursive_mutex.cpp +__TBB_SYMBOL( ?internal_acquire@scoped_lock@recursive_mutex@tbb@@AAEXAAV23@@Z ) +__TBB_SYMBOL( ?internal_release@scoped_lock@recursive_mutex@tbb@@AAEXXZ ) +__TBB_SYMBOL( ?internal_try_acquire@scoped_lock@recursive_mutex@tbb@@AAE_NAAV23@@Z ) +__TBB_SYMBOL( ?internal_construct@recursive_mutex@tbb@@AAEXXZ ) +__TBB_SYMBOL( ?internal_destroy@recursive_mutex@tbb@@AAEXXZ ) + +// queuing_mutex.cpp +__TBB_SYMBOL( ?internal_construct@queuing_mutex@tbb@@QAEXXZ ) +__TBB_SYMBOL( ?acquire@scoped_lock@queuing_mutex@tbb@@QAEXAAV23@@Z ) +__TBB_SYMBOL( ?release@scoped_lock@queuing_mutex@tbb@@QAEXXZ ) +__TBB_SYMBOL( ?try_acquire@scoped_lock@queuing_mutex@tbb@@QAE_NAAV23@@Z ) + +// critical_section.cpp +__TBB_SYMBOL( ?internal_construct@critical_section_v4@internal@tbb@@QAEXXZ ) + +#if !TBB_NO_LEGACY +// concurrent_hash_map.cpp +__TBB_SYMBOL( ?internal_grow_predicate@hash_map_segment_base@internal@tbb@@QBE_NXZ ) + +// concurrent_queue.cpp v2 +__TBB_SYMBOL( ?advance@concurrent_queue_iterator_base@internal@tbb@@IAEXXZ ) +__TBB_SYMBOL( ?assign@concurrent_queue_iterator_base@internal@tbb@@IAEXABV123@@Z ) +__TBB_SYMBOL( ?internal_size@concurrent_queue_base@internal@tbb@@IBEHXZ ) +__TBB_SYMBOL( ??0concurrent_queue_base@internal@tbb@@IAE@I@Z ) +__TBB_SYMBOL( ??0concurrent_queue_iterator_base@internal@tbb@@IAE@ABVconcurrent_queue_base@12@@Z ) +__TBB_SYMBOL( ??1concurrent_queue_base@internal@tbb@@MAE@XZ ) +__TBB_SYMBOL( ??1concurrent_queue_iterator_base@internal@tbb@@IAE@XZ ) +__TBB_SYMBOL( ?internal_pop@concurrent_queue_base@internal@tbb@@IAEXPAX@Z ) +__TBB_SYMBOL( ?internal_pop_if_present@concurrent_queue_base@internal@tbb@@IAE_NPAX@Z ) +__TBB_SYMBOL( ?internal_push@concurrent_queue_base@internal@tbb@@IAEXPBX@Z ) +__TBB_SYMBOL( ?internal_push_if_not_full@concurrent_queue_base@internal@tbb@@IAE_NPBX@Z ) +__TBB_SYMBOL( ?internal_set_capacity@concurrent_queue_base@internal@tbb@@IAEXHI@Z ) +#endif + +// concurrent_queue v3 +__TBB_SYMBOL( ??1concurrent_queue_iterator_base_v3@internal@tbb@@IAE@XZ ) +__TBB_SYMBOL( ??0concurrent_queue_iterator_base_v3@internal@tbb@@IAE@ABVconcurrent_queue_base_v3@12@@Z ) +__TBB_SYMBOL( ??0concurrent_queue_iterator_base_v3@internal@tbb@@IAE@ABVconcurrent_queue_base_v3@12@I@Z ) +__TBB_SYMBOL( ?advance@concurrent_queue_iterator_base_v3@internal@tbb@@IAEXXZ ) +__TBB_SYMBOL( ?assign@concurrent_queue_iterator_base_v3@internal@tbb@@IAEXABV123@@Z ) +__TBB_SYMBOL( ??0concurrent_queue_base_v3@internal@tbb@@IAE@I@Z ) +__TBB_SYMBOL( ??1concurrent_queue_base_v3@internal@tbb@@MAE@XZ ) +__TBB_SYMBOL( ?internal_pop@concurrent_queue_base_v3@internal@tbb@@IAEXPAX@Z ) +__TBB_SYMBOL( ?internal_pop_if_present@concurrent_queue_base_v3@internal@tbb@@IAE_NPAX@Z ) +__TBB_SYMBOL( ?internal_abort@concurrent_queue_base_v3@internal@tbb@@IAEXXZ ) +__TBB_SYMBOL( ?internal_push@concurrent_queue_base_v3@internal@tbb@@IAEXPBX@Z ) +__TBB_SYMBOL( ?internal_push_if_not_full@concurrent_queue_base_v3@internal@tbb@@IAE_NPBX@Z ) +__TBB_SYMBOL( ?internal_size@concurrent_queue_base_v3@internal@tbb@@IBEHXZ ) +__TBB_SYMBOL( ?internal_empty@concurrent_queue_base_v3@internal@tbb@@IBE_NXZ ) +__TBB_SYMBOL( ?internal_set_capacity@concurrent_queue_base_v3@internal@tbb@@IAEXHI@Z ) +__TBB_SYMBOL( ?internal_finish_clear@concurrent_queue_base_v3@internal@tbb@@IAEXXZ ) +__TBB_SYMBOL( ?internal_throw_exception@concurrent_queue_base_v3@internal@tbb@@IBEXXZ ) +__TBB_SYMBOL( ?assign@concurrent_queue_base_v3@internal@tbb@@IAEXABV123@@Z ) + +#if !TBB_NO_LEGACY +// concurrent_vector.cpp v2 +__TBB_SYMBOL( ?internal_assign@concurrent_vector_base@internal@tbb@@IAEXABV123@IP6AXPAXI@ZP6AX1PBXI@Z4@Z ) +__TBB_SYMBOL( ?internal_capacity@concurrent_vector_base@internal@tbb@@IBEIXZ ) +__TBB_SYMBOL( ?internal_clear@concurrent_vector_base@internal@tbb@@IAEXP6AXPAXI@Z_N@Z ) +__TBB_SYMBOL( ?internal_copy@concurrent_vector_base@internal@tbb@@IAEXABV123@IP6AXPAXPBXI@Z@Z ) +__TBB_SYMBOL( ?internal_grow_by@concurrent_vector_base@internal@tbb@@IAEIIIP6AXPAXI@Z@Z ) +__TBB_SYMBOL( ?internal_grow_to_at_least@concurrent_vector_base@internal@tbb@@IAEXIIP6AXPAXI@Z@Z ) +__TBB_SYMBOL( ?internal_push_back@concurrent_vector_base@internal@tbb@@IAEPAXIAAI@Z ) +__TBB_SYMBOL( ?internal_reserve@concurrent_vector_base@internal@tbb@@IAEXIII@Z ) +#endif + +// concurrent_vector v3 +__TBB_SYMBOL( ??1concurrent_vector_base_v3@internal@tbb@@IAE@XZ ) +__TBB_SYMBOL( ?internal_assign@concurrent_vector_base_v3@internal@tbb@@IAEXABV123@IP6AXPAXI@ZP6AX1PBXI@Z4@Z ) +__TBB_SYMBOL( ?internal_capacity@concurrent_vector_base_v3@internal@tbb@@IBEIXZ ) +__TBB_SYMBOL( ?internal_clear@concurrent_vector_base_v3@internal@tbb@@IAEIP6AXPAXI@Z@Z ) +__TBB_SYMBOL( ?internal_copy@concurrent_vector_base_v3@internal@tbb@@IAEXABV123@IP6AXPAXPBXI@Z@Z ) +__TBB_SYMBOL( ?internal_grow_by@concurrent_vector_base_v3@internal@tbb@@IAEIIIP6AXPAXPBXI@Z1@Z ) +__TBB_SYMBOL( ?internal_grow_to_at_least@concurrent_vector_base_v3@internal@tbb@@IAEXIIP6AXPAXPBXI@Z1@Z ) +__TBB_SYMBOL( ?internal_push_back@concurrent_vector_base_v3@internal@tbb@@IAEPAXIAAI@Z ) +__TBB_SYMBOL( ?internal_reserve@concurrent_vector_base_v3@internal@tbb@@IAEXIII@Z ) +__TBB_SYMBOL( ?internal_compact@concurrent_vector_base_v3@internal@tbb@@IAEPAXIPAXP6AX0I@ZP6AX0PBXI@Z@Z ) +__TBB_SYMBOL( ?internal_swap@concurrent_vector_base_v3@internal@tbb@@IAEXAAV123@@Z ) +__TBB_SYMBOL( ?internal_throw_exception@concurrent_vector_base_v3@internal@tbb@@IBEXI@Z ) +__TBB_SYMBOL( ?internal_resize@concurrent_vector_base_v3@internal@tbb@@IAEXIIIPBXP6AXPAXI@ZP6AX10I@Z@Z ) +__TBB_SYMBOL( ?internal_grow_to_at_least_with_result@concurrent_vector_base_v3@internal@tbb@@IAEIIIP6AXPAXPBXI@Z1@Z ) + +// tbb_thread +__TBB_SYMBOL( ?join@tbb_thread_v3@internal@tbb@@QAEXXZ ) +__TBB_SYMBOL( ?detach@tbb_thread_v3@internal@tbb@@QAEXXZ ) +__TBB_SYMBOL( ?internal_start@tbb_thread_v3@internal@tbb@@AAEXP6GIPAX@Z0@Z ) +__TBB_SYMBOL( ?allocate_closure_v3@internal@tbb@@YAPAXI@Z ) +__TBB_SYMBOL( ?free_closure_v3@internal@tbb@@YAXPAX@Z ) +__TBB_SYMBOL( ?hardware_concurrency@tbb_thread_v3@internal@tbb@@SAIXZ ) +__TBB_SYMBOL( ?thread_yield_v3@internal@tbb@@YAXXZ ) +__TBB_SYMBOL( ?thread_sleep_v3@internal@tbb@@YAXABVinterval_t@tick_count@2@@Z ) +__TBB_SYMBOL( ?move_v3@internal@tbb@@YAXAAVtbb_thread_v3@12@0@Z ) +__TBB_SYMBOL( ?thread_get_id_v3@internal@tbb@@YA?AVid@tbb_thread_v3@12@XZ ) + +// condition_variable +__TBB_SYMBOL( ?internal_initialize_condition_variable@internal@interface5@tbb@@YAXAATcondvar_impl_t@123@@Z ) +__TBB_SYMBOL( ?internal_condition_variable_wait@internal@interface5@tbb@@YA_NAATcondvar_impl_t@123@PAVmutex@3@PBVinterval_t@tick_count@3@@Z ) +__TBB_SYMBOL( ?internal_condition_variable_notify_one@internal@interface5@tbb@@YAXAATcondvar_impl_t@123@@Z ) +__TBB_SYMBOL( ?internal_condition_variable_notify_all@internal@interface5@tbb@@YAXAATcondvar_impl_t@123@@Z ) +__TBB_SYMBOL( ?internal_destroy_condition_variable@internal@interface5@tbb@@YAXAATcondvar_impl_t@123@@Z ) + +#undef __TBB_SYMBOL diff --git a/src/tbb/src/tbb/win64-gcc-tbb-export.def b/src/tbb/src/tbb/win64-gcc-tbb-export.def new file mode 100644 index 0000000..e3a9533 --- /dev/null +++ b/src/tbb/src/tbb/win64-gcc-tbb-export.def @@ -0,0 +1,53 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + + +{ +global: + +#define __TBB_SYMBOL( sym ) sym; +#include "win64-gcc-tbb-export.lst" + +local: + +/* TBB symbols */ +*3tbb*; +*__TBB*; + +/* Intel Compiler (libirc) symbols */ +__intel_*; +_intel_*; +get_msg_buf; +get_text_buf; +message_catalog; +print_buf; +irc__get_msg; +irc__print; + +}; + diff --git a/src/tbb/src/tbb/win64-gcc-tbb-export.lst b/src/tbb/src/tbb/win64-gcc-tbb-export.lst new file mode 100644 index 0000000..b693825 --- /dev/null +++ b/src/tbb/src/tbb/win64-gcc-tbb-export.lst @@ -0,0 +1,350 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + The source code contained or described herein and all documents related + to the source code ("Material") are owned by Intel Corporation or its + suppliers or licensors. Title to the Material remains with Intel + Corporation or its suppliers and licensors. The Material is protected + by worldwide copyright laws and treaty provisions. No part of the + Material may be used, copied, reproduced, modified, published, uploaded, + posted, transmitted, distributed, or disclosed in any way without + Intel's prior express written permission. + + No license under any patent, copyright, trade secret or other + intellectual property right is granted to or conferred upon you by + disclosure or delivery of the Materials, either expressly, by + implication, inducement, estoppel or otherwise. Any license under such + intellectual property rights must be express and approved by Intel in + writing. +*/ + + +#include "tbb/tbb_config.h" + +/* cache_aligned_allocator.cpp */ +__TBB_SYMBOL( _ZN3tbb8internal12NFS_AllocateEyyPv ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal15NFS_GetLineSizeEv ) +__TBB_SYMBOL( _ZN3tbb8internal8NFS_FreeEPv ) +__TBB_SYMBOL( _ZN3tbb8internal23allocate_via_handler_v3Ey ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal25deallocate_via_handler_v3EPv ) +__TBB_SYMBOL( _ZN3tbb8internal17is_malloc_used_v3Ev ) + +/* task.cpp v3 */ +__TBB_SYMBOL( _ZN3tbb4task13note_affinityEt ) +__TBB_SYMBOL( _ZN3tbb4task22internal_set_ref_countEi ) +__TBB_SYMBOL( _ZN3tbb4task28internal_decrement_ref_countEv ) +__TBB_SYMBOL( _ZN3tbb4task22spawn_and_wait_for_allERNS_9task_listE ) +__TBB_SYMBOL( _ZN3tbb4task4selfEv ) +__TBB_SYMBOL( _ZN3tbb10interface58internal9task_base7destroyERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb4task26is_owned_by_current_threadEv ) +__TBB_SYMBOL( _ZN3tbb8internal19allocate_root_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZN3tbb8internal19allocate_root_proxy8allocateEy ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal28affinity_partitioner_base_v36resizeEj ) +__TBB_SYMBOL( _ZNK3tbb8internal20allocate_child_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb8internal20allocate_child_proxy8allocateEy ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZNK3tbb8internal27allocate_continuation_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb8internal27allocate_continuation_proxy8allocateEy ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZNK3tbb8internal34allocate_additional_child_of_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZNK3tbb8internal34allocate_additional_child_of_proxy8allocateEy ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZTIN3tbb4taskE ) +__TBB_SYMBOL( _ZTSN3tbb4taskE ) +__TBB_SYMBOL( _ZTVN3tbb4taskE ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init19default_num_threadsEv ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init10initializeEiy ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init10initializeEi ) +__TBB_SYMBOL( _ZN3tbb19task_scheduler_init9terminateEv ) +__TBB_SYMBOL( _ZN3tbb8internal26task_scheduler_observer_v37observeEb ) +__TBB_SYMBOL( _ZN3tbb10empty_task7executeEv ) +__TBB_SYMBOL( _ZN3tbb10empty_taskD0Ev ) +__TBB_SYMBOL( _ZN3tbb10empty_taskD1Ev ) +__TBB_SYMBOL( _ZTIN3tbb10empty_taskE ) +__TBB_SYMBOL( _ZTSN3tbb10empty_taskE ) +__TBB_SYMBOL( _ZTVN3tbb10empty_taskE ) + +#if !TBB_NO_LEGACY +/* task_v2.cpp */ +__TBB_SYMBOL( _ZN3tbb4task7destroyERS0_ ) +#endif /* !TBB_NO_LEGACY */ + +/* Exception handling in task scheduler */ +#if __TBB_TASK_GROUP_CONTEXT +__TBB_SYMBOL( _ZNK3tbb8internal32allocate_root_with_context_proxy8allocateEy ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZNK3tbb8internal32allocate_root_with_context_proxy4freeERNS_4taskE ) +__TBB_SYMBOL( _ZN3tbb4task12change_groupERNS_18task_group_contextE ) +__TBB_SYMBOL( _ZNK3tbb18task_group_context28is_group_execution_cancelledEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context22cancel_group_executionEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context26register_pending_exceptionEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context5resetEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_context4initEv ) +__TBB_SYMBOL( _ZN3tbb18task_group_contextD1Ev ) +__TBB_SYMBOL( _ZN3tbb18task_group_contextD2Ev ) +#if __TBB_TASK_PRIORITY +__TBB_SYMBOL( _ZN3tbb18task_group_context12set_priorityENS_10priority_tE ) +__TBB_SYMBOL( _ZNK3tbb18task_group_context8priorityEv ) +#endif /* __TBB_TASK_PRIORITY */ +__TBB_SYMBOL( _ZNK3tbb18captured_exception4nameEv ) +__TBB_SYMBOL( _ZNK3tbb18captured_exception4whatEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception10throw_selfEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception3setEPKcS2_ ) +__TBB_SYMBOL( _ZN3tbb18captured_exception4moveEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception5clearEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception7destroyEv ) +__TBB_SYMBOL( _ZN3tbb18captured_exception8allocateEPKcS2_ ) +__TBB_SYMBOL( _ZN3tbb18captured_exceptionD0Ev ) +__TBB_SYMBOL( _ZN3tbb18captured_exceptionD1Ev ) +__TBB_SYMBOL( _ZN3tbb18captured_exceptionD2Ev ) +__TBB_SYMBOL( _ZTIN3tbb18captured_exceptionE ) +__TBB_SYMBOL( _ZTSN3tbb18captured_exceptionE ) +__TBB_SYMBOL( _ZTVN3tbb18captured_exceptionE ) +__TBB_SYMBOL( _ZN3tbb13tbb_exceptionD2Ev ) +__TBB_SYMBOL( _ZTIN3tbb13tbb_exceptionE ) +__TBB_SYMBOL( _ZTSN3tbb13tbb_exceptionE ) +__TBB_SYMBOL( _ZTVN3tbb13tbb_exceptionE ) +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +/* Symbols for exceptions thrown from TBB */ +__TBB_SYMBOL( _ZN3tbb8internal33throw_bad_last_alloc_exception_v4Ev ) +__TBB_SYMBOL( _ZN3tbb8internal18throw_exception_v4ENS0_12exception_idE ) +__TBB_SYMBOL( _ZN3tbb14bad_last_allocD0Ev ) +__TBB_SYMBOL( _ZN3tbb14bad_last_allocD1Ev ) +__TBB_SYMBOL( _ZNK3tbb14bad_last_alloc4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb14bad_last_allocE ) +__TBB_SYMBOL( _ZTSN3tbb14bad_last_allocE ) +__TBB_SYMBOL( _ZTVN3tbb14bad_last_allocE ) +__TBB_SYMBOL( _ZN3tbb12missing_waitD0Ev ) +__TBB_SYMBOL( _ZN3tbb12missing_waitD1Ev ) +__TBB_SYMBOL( _ZNK3tbb12missing_wait4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb12missing_waitE ) +__TBB_SYMBOL( _ZTSN3tbb12missing_waitE ) +__TBB_SYMBOL( _ZTVN3tbb12missing_waitE ) +__TBB_SYMBOL( _ZN3tbb27invalid_multiple_schedulingD0Ev ) +__TBB_SYMBOL( _ZN3tbb27invalid_multiple_schedulingD1Ev ) +__TBB_SYMBOL( _ZNK3tbb27invalid_multiple_scheduling4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb27invalid_multiple_schedulingE ) +__TBB_SYMBOL( _ZTSN3tbb27invalid_multiple_schedulingE ) +__TBB_SYMBOL( _ZTVN3tbb27invalid_multiple_schedulingE ) +__TBB_SYMBOL( _ZN3tbb13improper_lockD0Ev ) +__TBB_SYMBOL( _ZN3tbb13improper_lockD1Ev ) +__TBB_SYMBOL( _ZNK3tbb13improper_lock4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb13improper_lockE ) +__TBB_SYMBOL( _ZTSN3tbb13improper_lockE ) +__TBB_SYMBOL( _ZTVN3tbb13improper_lockE ) +__TBB_SYMBOL( _ZN3tbb10user_abortD0Ev ) +__TBB_SYMBOL( _ZN3tbb10user_abortD1Ev ) +__TBB_SYMBOL( _ZNK3tbb10user_abort4whatEv ) +__TBB_SYMBOL( _ZTIN3tbb10user_abortE ) +__TBB_SYMBOL( _ZTSN3tbb10user_abortE ) +__TBB_SYMBOL( _ZTVN3tbb10user_abortE ) + +/* tbb_misc.cpp */ +__TBB_SYMBOL( _ZN3tbb17assertion_failureEPKciS1_S1_ ) +__TBB_SYMBOL( _ZN3tbb21set_assertion_handlerEPFvPKciS1_S1_E ) +__TBB_SYMBOL( _ZN3tbb8internal36get_initial_auto_partitioner_divisorEv ) +__TBB_SYMBOL( _ZN3tbb8internal13handle_perrorEiPKc ) +__TBB_SYMBOL( _ZN3tbb8internal15runtime_warningEPKcz ) +__TBB_SYMBOL( TBB_runtime_interface_version ) + +/* tbb_main.cpp */ +__TBB_SYMBOL( _ZN3tbb8internal32itt_load_pointer_with_acquire_v3EPKv ) +__TBB_SYMBOL( _ZN3tbb8internal33itt_store_pointer_with_release_v3EPvS1_ ) +__TBB_SYMBOL( _ZN3tbb8internal18call_itt_notify_v5EiPv ) +__TBB_SYMBOL( _ZN3tbb8internal20itt_set_sync_name_v3EPvPKc ) +__TBB_SYMBOL( _ZN3tbb8internal19itt_load_pointer_v3EPKv ) + +/* pipeline.cpp */ +__TBB_SYMBOL( _ZTIN3tbb6filterE ) +__TBB_SYMBOL( _ZTSN3tbb6filterE ) +__TBB_SYMBOL( _ZTVN3tbb6filterE ) +__TBB_SYMBOL( _ZN3tbb6filterD2Ev ) +__TBB_SYMBOL( _ZN3tbb8pipeline10add_filterERNS_6filterE ) +__TBB_SYMBOL( _ZN3tbb8pipeline12inject_tokenERNS_4taskE ) +__TBB_SYMBOL( _ZN3tbb8pipeline13remove_filterERNS_6filterE ) +__TBB_SYMBOL( _ZN3tbb8pipeline3runEy ) // MODIFIED LINUX ENTRY +#if __TBB_TASK_GROUP_CONTEXT +__TBB_SYMBOL( _ZN3tbb8pipeline3runEyRNS_18task_group_contextE ) // MODIFIED LINUX ENTRY +#endif +__TBB_SYMBOL( _ZN3tbb8pipeline5clearEv ) +__TBB_SYMBOL( _ZN3tbb19thread_bound_filter12process_itemEv ) +__TBB_SYMBOL( _ZN3tbb19thread_bound_filter16try_process_itemEv ) +__TBB_SYMBOL( _ZTIN3tbb8pipelineE ) +__TBB_SYMBOL( _ZTSN3tbb8pipelineE ) +__TBB_SYMBOL( _ZTVN3tbb8pipelineE ) +__TBB_SYMBOL( _ZN3tbb8pipelineC1Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineC2Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineD0Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineD1Ev ) +__TBB_SYMBOL( _ZN3tbb8pipelineD2Ev ) +__TBB_SYMBOL( _ZN3tbb6filter16set_end_of_inputEv ) + +/* queuing_rw_mutex.cpp */ +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex18internal_constructEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock17upgrade_to_writerEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock19downgrade_to_readerEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock7acquireERS0_b ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock7releaseEv ) +__TBB_SYMBOL( _ZN3tbb16queuing_rw_mutex11scoped_lock11try_acquireERS0_b ) + +/* reader_writer_lock.cpp */ +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock11scoped_lock16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock11scoped_lock18internal_constructERS1_ ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock13try_lock_readEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock16scoped_lock_read16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock16scoped_lock_read18internal_constructERS1_ ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock18internal_constructEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock4lockEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock6unlockEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock8try_lockEv ) +__TBB_SYMBOL( _ZN3tbb10interface518reader_writer_lock9lock_readEv ) + +#if !TBB_NO_LEGACY +/* spin_rw_mutex.cpp v2 */ +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex16internal_upgradeEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex22internal_itt_releasingEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_acquire_readerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_acquire_writerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex18internal_downgradeEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_release_readerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex23internal_release_writerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex27internal_try_acquire_readerEPS0_ ) +__TBB_SYMBOL( _ZN3tbb13spin_rw_mutex27internal_try_acquire_writerEPS0_ ) +#endif + +/* spin_rw_mutex v3 */ +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v318internal_constructEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v316internal_upgradeEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v318internal_downgradeEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_acquire_readerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_acquire_writerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_release_readerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v323internal_release_writerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v327internal_try_acquire_readerEv ) +__TBB_SYMBOL( _ZN3tbb16spin_rw_mutex_v327internal_try_acquire_writerEv ) + +/* spin_mutex.cpp */ +__TBB_SYMBOL( _ZN3tbb10spin_mutex11scoped_lock16internal_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb10spin_mutex11scoped_lock16internal_releaseEv ) +__TBB_SYMBOL( _ZN3tbb10spin_mutex11scoped_lock20internal_try_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb10spin_mutex18internal_constructEv ) + +/* mutex.cpp */ +__TBB_SYMBOL( _ZN3tbb5mutex11scoped_lock16internal_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb5mutex11scoped_lock16internal_releaseEv ) +__TBB_SYMBOL( _ZN3tbb5mutex11scoped_lock20internal_try_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb5mutex16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb5mutex18internal_constructEv ) + +/* recursive_mutex.cpp */ +__TBB_SYMBOL( _ZN3tbb15recursive_mutex11scoped_lock16internal_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex11scoped_lock16internal_releaseEv ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex11scoped_lock20internal_try_acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex16internal_destroyEv ) +__TBB_SYMBOL( _ZN3tbb15recursive_mutex18internal_constructEv ) + +/* QueuingMutex.cpp */ +__TBB_SYMBOL( _ZN3tbb13queuing_mutex18internal_constructEv ) +__TBB_SYMBOL( _ZN3tbb13queuing_mutex11scoped_lock7acquireERS0_ ) +__TBB_SYMBOL( _ZN3tbb13queuing_mutex11scoped_lock7releaseEv ) +__TBB_SYMBOL( _ZN3tbb13queuing_mutex11scoped_lock11try_acquireERS0_ ) + +/* critical_section.cpp */ +__TBB_SYMBOL( _ZN3tbb8internal19critical_section_v418internal_constructEv ) + +#if !TBB_NO_LEGACY +/* concurrent_hash_map */ +__TBB_SYMBOL( _ZNK3tbb8internal21hash_map_segment_base23internal_grow_predicateEv ) + +/* concurrent_queue.cpp v2 */ +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base12internal_popEPv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base13internal_pushEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base21internal_set_capacityExy ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base23internal_pop_if_presentEPv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_base25internal_push_if_not_fullEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_baseC2Ey ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal21concurrent_queue_baseD2Ev ) +__TBB_SYMBOL( _ZTIN3tbb8internal21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZTSN3tbb8internal21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZTVN3tbb8internal21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_base6assignERKS1_ ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_base7advanceEv ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_baseC2ERKNS0_21concurrent_queue_baseE ) +__TBB_SYMBOL( _ZN3tbb8internal30concurrent_queue_iterator_baseD2Ev ) +__TBB_SYMBOL( _ZNK3tbb8internal21concurrent_queue_base13internal_sizeEv ) +#endif + +/* concurrent_queue v3 */ +/* constructors */ +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v3C2Ey ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v3C2ERKNS0_24concurrent_queue_base_v3E ) +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v3C2ERKNS0_24concurrent_queue_base_v3Ey ) // MODIFIED LINUX ENTRY +/* destructors */ +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v3D2Ev ) +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v3D2Ev ) +/* typeinfo */ +__TBB_SYMBOL( _ZTIN3tbb8internal24concurrent_queue_base_v3E ) +__TBB_SYMBOL( _ZTSN3tbb8internal24concurrent_queue_base_v3E ) +/* vtable */ +__TBB_SYMBOL( _ZTVN3tbb8internal24concurrent_queue_base_v3E ) +/* methods */ +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v36assignERKS1_ ) +__TBB_SYMBOL( _ZN3tbb8internal33concurrent_queue_iterator_base_v37advanceEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v313internal_pushEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v325internal_push_if_not_fullEPKv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v312internal_popEPv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v323internal_pop_if_presentEPv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v314internal_abortEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v321internal_finish_clearEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v321internal_set_capacityExy ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZNK3tbb8internal24concurrent_queue_base_v313internal_sizeEv ) +__TBB_SYMBOL( _ZNK3tbb8internal24concurrent_queue_base_v314internal_emptyEv ) +__TBB_SYMBOL( _ZNK3tbb8internal24concurrent_queue_base_v324internal_throw_exceptionEv ) +__TBB_SYMBOL( _ZN3tbb8internal24concurrent_queue_base_v36assignERKS1_ ) + +#if !TBB_NO_LEGACY +/* concurrent_vector.cpp v2 */ +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base13internal_copyERKS1_yPFvPvPKvyE ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base14internal_clearEPFvPvyEb ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base15internal_assignERKS1_yPFvPvyEPFvS4_PKvyESA_ ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base16internal_grow_byEyyPFvPvyE ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base16internal_reserveEyyy ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base18internal_push_backEyRy ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal22concurrent_vector_base25internal_grow_to_at_leastEyyPFvPvyE ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZNK3tbb8internal22concurrent_vector_base17internal_capacityEv ) +#endif + +/* concurrent_vector v3 */ +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v313internal_copyERKS1_yPFvPvPKvyE ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v314internal_clearEPFvPvyE ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v315internal_assignERKS1_yPFvPvyEPFvS4_PKvyESA_ ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v316internal_grow_byEyyPFvPvPKvyES4_ ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v316internal_reserveEyyy ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v318internal_push_backEyRy ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v325internal_grow_to_at_leastEyyPFvPvPKvyES4_ ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZNK3tbb8internal25concurrent_vector_base_v317internal_capacityEv ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v316internal_compactEyPvPFvS2_yEPFvS2_PKvyE ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v313internal_swapERS1_ ) +__TBB_SYMBOL( _ZNK3tbb8internal25concurrent_vector_base_v324internal_throw_exceptionEy ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v3D2Ev ) +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v315internal_resizeEyyyPKvPFvPvyEPFvS4_S3_yE ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal25concurrent_vector_base_v337internal_grow_to_at_least_with_resultEyyPFvPvPKvyES4_ ) // MODIFIED LINUX ENTRY + +/* tbb_thread */ +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v320hardware_concurrencyEv ) +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v36detachEv ) +__TBB_SYMBOL( _ZN3tbb8internal16thread_get_id_v3Ev ) +__TBB_SYMBOL( _ZN3tbb8internal15free_closure_v3EPv ) +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v34joinEv ) +__TBB_SYMBOL( _ZN3tbb8internal13tbb_thread_v314internal_startEPFjPvES2_ ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal19allocate_closure_v3Ey ) // MODIFIED LINUX ENTRY +__TBB_SYMBOL( _ZN3tbb8internal7move_v3ERNS0_13tbb_thread_v3ES2_ ) +__TBB_SYMBOL( _ZN3tbb8internal15thread_yield_v3Ev ) +__TBB_SYMBOL( _ZN3tbb8internal15thread_sleep_v3ERKNS_10tick_count10interval_tE ) + +/* condition_variable */ +__TBB_SYMBOL( _ZN3tbb10interface58internal32internal_condition_variable_waitERNS1_14condvar_impl_tEPNS_5mutexEPKNS_10tick_count10interval_tE ) +__TBB_SYMBOL( _ZN3tbb10interface58internal35internal_destroy_condition_variableERNS1_14condvar_impl_tE ) +__TBB_SYMBOL( _ZN3tbb10interface58internal38internal_condition_variable_notify_allERNS1_14condvar_impl_tE ) +__TBB_SYMBOL( _ZN3tbb10interface58internal38internal_condition_variable_notify_oneERNS1_14condvar_impl_tE ) +__TBB_SYMBOL( _ZN3tbb10interface58internal38internal_initialize_condition_variableERNS1_14condvar_impl_tE ) + +#undef __TBB_SYMBOL diff --git a/src/tbb/src/tbb/win64-tbb-export.def b/src/tbb/src/tbb/win64-tbb-export.def new file mode 100644 index 0000000..59926ff --- /dev/null +++ b/src/tbb/src/tbb/win64-tbb-export.def @@ -0,0 +1,26 @@ +; Copyright 2005-2012 Intel Corporation. All Rights Reserved. +; +; The source code contained or described herein and all documents related +; to the source code ("Material") are owned by Intel Corporation or its +; suppliers or licensors. Title to the Material remains with Intel +; Corporation or its suppliers and licensors. The Material is protected +; by worldwide copyright laws and treaty provisions. No part of the +; Material may be used, copied, reproduced, modified, published, uploaded, +; posted, transmitted, distributed, or disclosed in any way without +; Intel's prior express written permission. +; +; No license under any patent, copyright, trade secret or other +; intellectual property right is granted to or conferred upon you by +; disclosure or delivery of the Materials, either expressly, by +; implication, inducement, estoppel or otherwise. Any license under such +; intellectual property rights must be express and approved by Intel in +; writing. +; +; This file is organized with a section for each .cpp file. +; Each of these sections is in alphabetical order. + +EXPORTS + +#define __TBB_SYMBOL( sym ) sym +#include "win64-tbb-export.lst" + diff --git a/src/tbb/src/tbb/win64-tbb-export.lst b/src/tbb/src/tbb/win64-tbb-export.lst new file mode 100644 index 0000000..ae2661e --- /dev/null +++ b/src/tbb/src/tbb/win64-tbb-export.lst @@ -0,0 +1,296 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + The source code contained or described herein and all documents related + to the source code ("Material") are owned by Intel Corporation or its + suppliers or licensors. Title to the Material remains with Intel + Corporation or its suppliers and licensors. The Material is protected + by worldwide copyright laws and treaty provisions. No part of the + Material may be used, copied, reproduced, modified, published, uploaded, + posted, transmitted, distributed, or disclosed in any way without + Intel's prior express written permission. + + No license under any patent, copyright, trade secret or other + intellectual property right is granted to or conferred upon you by + disclosure or delivery of the Materials, either expressly, by + implication, inducement, estoppel or otherwise. Any license under such + intellectual property rights must be express and approved by Intel in + writing. +*/ + +// This file is organized with a section for each .cpp file. +// Each of these sections is in alphabetical order. + +#include "tbb/tbb_config.h" + +// Assembly-language support that is called directly by clients +__TBB_SYMBOL( __TBB_machine_cmpswp1 ) +__TBB_SYMBOL( __TBB_machine_fetchadd1 ) +__TBB_SYMBOL( __TBB_machine_fetchstore1 ) +__TBB_SYMBOL( __TBB_machine_cmpswp2 ) +__TBB_SYMBOL( __TBB_machine_fetchadd2 ) +__TBB_SYMBOL( __TBB_machine_fetchstore2 ) +__TBB_SYMBOL( __TBB_machine_pause ) + +// cache_aligned_allocator.cpp +__TBB_SYMBOL( ?NFS_Allocate@internal@tbb@@YAPEAX_K0PEAX@Z ) +__TBB_SYMBOL( ?NFS_GetLineSize@internal@tbb@@YA_KXZ ) +__TBB_SYMBOL( ?NFS_Free@internal@tbb@@YAXPEAX@Z ) +__TBB_SYMBOL( ?allocate_via_handler_v3@internal@tbb@@YAPEAX_K@Z ) +__TBB_SYMBOL( ?deallocate_via_handler_v3@internal@tbb@@YAXPEAX@Z ) +__TBB_SYMBOL( ?is_malloc_used_v3@internal@tbb@@YA_NXZ ) + + +// task.cpp v3 +__TBB_SYMBOL( ?resize@affinity_partitioner_base_v3@internal@tbb@@AEAAXI@Z ) +__TBB_SYMBOL( ?allocate@allocate_additional_child_of_proxy@internal@tbb@@QEBAAEAVtask@3@_K@Z ) +__TBB_SYMBOL( ?allocate@allocate_child_proxy@internal@tbb@@QEBAAEAVtask@3@_K@Z ) +__TBB_SYMBOL( ?allocate@allocate_continuation_proxy@internal@tbb@@QEBAAEAVtask@3@_K@Z ) +__TBB_SYMBOL( ?allocate@allocate_root_proxy@internal@tbb@@SAAEAVtask@3@_K@Z ) +__TBB_SYMBOL( ?destroy@task_base@internal@interface5@tbb@@SAXAEAVtask@4@@Z ) +__TBB_SYMBOL( ?free@allocate_additional_child_of_proxy@internal@tbb@@QEBAXAEAVtask@3@@Z ) +__TBB_SYMBOL( ?free@allocate_child_proxy@internal@tbb@@QEBAXAEAVtask@3@@Z ) +__TBB_SYMBOL( ?free@allocate_continuation_proxy@internal@tbb@@QEBAXAEAVtask@3@@Z ) +__TBB_SYMBOL( ?free@allocate_root_proxy@internal@tbb@@SAXAEAVtask@3@@Z ) +__TBB_SYMBOL( ?internal_set_ref_count@task@tbb@@AEAAXH@Z ) +__TBB_SYMBOL( ?internal_decrement_ref_count@task@tbb@@AEAA_JXZ ) +__TBB_SYMBOL( ?is_owned_by_current_thread@task@tbb@@QEBA_NXZ ) +__TBB_SYMBOL( ?note_affinity@task@tbb@@UEAAXG@Z ) +__TBB_SYMBOL( ?self@task@tbb@@SAAEAV12@XZ ) +__TBB_SYMBOL( ?spawn_and_wait_for_all@task@tbb@@QEAAXAEAVtask_list@2@@Z ) +__TBB_SYMBOL( ?default_num_threads@task_scheduler_init@tbb@@SAHXZ ) +__TBB_SYMBOL( ?initialize@task_scheduler_init@tbb@@QEAAXH_K@Z ) +__TBB_SYMBOL( ?initialize@task_scheduler_init@tbb@@QEAAXH@Z ) +__TBB_SYMBOL( ?terminate@task_scheduler_init@tbb@@QEAAXXZ ) +__TBB_SYMBOL( ?observe@task_scheduler_observer_v3@internal@tbb@@QEAAX_N@Z ) + +#if !TBB_NO_LEGACY +// task_v2.cpp +__TBB_SYMBOL( ?destroy@task@tbb@@QEAAXAEAV12@@Z ) +#endif + +// Exception handling in task scheduler +#if __TBB_TASK_GROUP_CONTEXT +__TBB_SYMBOL( ?allocate@allocate_root_with_context_proxy@internal@tbb@@QEBAAEAVtask@3@_K@Z ) +__TBB_SYMBOL( ?free@allocate_root_with_context_proxy@internal@tbb@@QEBAXAEAVtask@3@@Z ) +__TBB_SYMBOL( ?change_group@task@tbb@@QEAAXAEAVtask_group_context@2@@Z ) +__TBB_SYMBOL( ?is_group_execution_cancelled@task_group_context@tbb@@QEBA_NXZ ) +__TBB_SYMBOL( ?cancel_group_execution@task_group_context@tbb@@QEAA_NXZ ) +__TBB_SYMBOL( ?reset@task_group_context@tbb@@QEAAXXZ ) +__TBB_SYMBOL( ?init@task_group_context@tbb@@IEAAXXZ ) +__TBB_SYMBOL( ?register_pending_exception@task_group_context@tbb@@QEAAXXZ ) +__TBB_SYMBOL( ??1task_group_context@tbb@@QEAA@XZ ) +#if __TBB_TASK_PRIORITY +__TBB_SYMBOL( ?set_priority@task_group_context@tbb@@QEAAXW4priority_t@2@@Z ) +__TBB_SYMBOL( ?priority@task_group_context@tbb@@QEBA?AW4priority_t@2@XZ ) +#endif /* __TBB_TASK_PRIORITY */ +__TBB_SYMBOL( ?name@captured_exception@tbb@@UEBAPEBDXZ ) +__TBB_SYMBOL( ?what@captured_exception@tbb@@UEBAPEBDXZ ) +__TBB_SYMBOL( ??1captured_exception@tbb@@UEAA@XZ ) +__TBB_SYMBOL( ?move@captured_exception@tbb@@UEAAPEAV12@XZ ) +__TBB_SYMBOL( ?destroy@captured_exception@tbb@@UEAAXXZ ) +__TBB_SYMBOL( ?set@captured_exception@tbb@@QEAAXPEBD0@Z ) +__TBB_SYMBOL( ?clear@captured_exception@tbb@@QEAAXXZ ) +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +// Symbols for exceptions thrown from TBB +__TBB_SYMBOL( ?throw_bad_last_alloc_exception_v4@internal@tbb@@YAXXZ ) +__TBB_SYMBOL( ?throw_exception_v4@internal@tbb@@YAXW4exception_id@12@@Z ) +__TBB_SYMBOL( ?what@bad_last_alloc@tbb@@UEBAPEBDXZ ) +__TBB_SYMBOL( ?what@missing_wait@tbb@@UEBAPEBDXZ ) +__TBB_SYMBOL( ?what@invalid_multiple_scheduling@tbb@@UEBAPEBDXZ ) +__TBB_SYMBOL( ?what@improper_lock@tbb@@UEBAPEBDXZ ) +__TBB_SYMBOL( ?what@user_abort@tbb@@UEBAPEBDXZ ) + +// tbb_misc.cpp +__TBB_SYMBOL( ?assertion_failure@tbb@@YAXPEBDH00@Z ) +__TBB_SYMBOL( ?get_initial_auto_partitioner_divisor@internal@tbb@@YA_KXZ ) +__TBB_SYMBOL( ?handle_perror@internal@tbb@@YAXHPEBD@Z ) +__TBB_SYMBOL( ?set_assertion_handler@tbb@@YAP6AXPEBDH00@ZP6AX0H00@Z@Z ) +__TBB_SYMBOL( ?runtime_warning@internal@tbb@@YAXPEBDZZ ) +__TBB_SYMBOL( TBB_runtime_interface_version ) + +// tbb_main.cpp +__TBB_SYMBOL( ?itt_load_pointer_with_acquire_v3@internal@tbb@@YAPEAXPEBX@Z ) +__TBB_SYMBOL( ?itt_store_pointer_with_release_v3@internal@tbb@@YAXPEAX0@Z ) +__TBB_SYMBOL( ?call_itt_notify_v5@internal@tbb@@YAXHPEAX@Z ) +__TBB_SYMBOL( ?itt_load_pointer_v3@internal@tbb@@YAPEAXPEBX@Z ) +__TBB_SYMBOL( ?itt_set_sync_name_v3@internal@tbb@@YAXPEAXPEB_W@Z ) + +// pipeline.cpp +__TBB_SYMBOL( ??_7pipeline@tbb@@6B@ ) +__TBB_SYMBOL( ??0pipeline@tbb@@QEAA@XZ ) +__TBB_SYMBOL( ??1filter@tbb@@UEAA@XZ ) +__TBB_SYMBOL( ??1pipeline@tbb@@UEAA@XZ ) +__TBB_SYMBOL( ?add_filter@pipeline@tbb@@QEAAXAEAVfilter@2@@Z ) +__TBB_SYMBOL( ?clear@pipeline@tbb@@QEAAXXZ ) +__TBB_SYMBOL( ?inject_token@pipeline@tbb@@AEAAXAEAVtask@2@@Z ) +__TBB_SYMBOL( ?run@pipeline@tbb@@QEAAX_K@Z ) +#if __TBB_TASK_GROUP_CONTEXT +__TBB_SYMBOL( ?run@pipeline@tbb@@QEAAX_KAEAVtask_group_context@2@@Z ) +#endif +__TBB_SYMBOL( ?process_item@thread_bound_filter@tbb@@QEAA?AW4result_type@12@XZ ) +__TBB_SYMBOL( ?try_process_item@thread_bound_filter@tbb@@QEAA?AW4result_type@12@XZ ) +__TBB_SYMBOL( ?set_end_of_input@filter@tbb@@IEAAXXZ ) + +// queuing_rw_mutex.cpp +__TBB_SYMBOL( ?internal_construct@queuing_rw_mutex@tbb@@QEAAXXZ ) +__TBB_SYMBOL( ?acquire@scoped_lock@queuing_rw_mutex@tbb@@QEAAXAEAV23@_N@Z ) +__TBB_SYMBOL( ?downgrade_to_reader@scoped_lock@queuing_rw_mutex@tbb@@QEAA_NXZ ) +__TBB_SYMBOL( ?release@scoped_lock@queuing_rw_mutex@tbb@@QEAAXXZ ) +__TBB_SYMBOL( ?upgrade_to_writer@scoped_lock@queuing_rw_mutex@tbb@@QEAA_NXZ ) +__TBB_SYMBOL( ?try_acquire@scoped_lock@queuing_rw_mutex@tbb@@QEAA_NAEAV23@_N@Z ) + +// reader_writer_lock.cpp +__TBB_SYMBOL( ?try_lock_read@reader_writer_lock@interface5@tbb@@QEAA_NXZ ) +__TBB_SYMBOL( ?try_lock@reader_writer_lock@interface5@tbb@@QEAA_NXZ ) +__TBB_SYMBOL( ?unlock@reader_writer_lock@interface5@tbb@@QEAAXXZ ) +__TBB_SYMBOL( ?lock_read@reader_writer_lock@interface5@tbb@@QEAAXXZ ) +__TBB_SYMBOL( ?lock@reader_writer_lock@interface5@tbb@@QEAAXXZ ) +__TBB_SYMBOL( ?internal_construct@reader_writer_lock@interface5@tbb@@AEAAXXZ ) +__TBB_SYMBOL( ?internal_destroy@reader_writer_lock@interface5@tbb@@AEAAXXZ ) +__TBB_SYMBOL( ?internal_construct@scoped_lock@reader_writer_lock@interface5@tbb@@AEAAXAEAV234@@Z ) +__TBB_SYMBOL( ?internal_destroy@scoped_lock@reader_writer_lock@interface5@tbb@@AEAAXXZ ) +__TBB_SYMBOL( ?internal_construct@scoped_lock_read@reader_writer_lock@interface5@tbb@@AEAAXAEAV234@@Z ) +__TBB_SYMBOL( ?internal_destroy@scoped_lock_read@reader_writer_lock@interface5@tbb@@AEAAXXZ ) + +#if !TBB_NO_LEGACY +// spin_rw_mutex.cpp v2 +__TBB_SYMBOL( ?internal_itt_releasing@spin_rw_mutex@tbb@@CAXPEAV12@@Z ) +__TBB_SYMBOL( ?internal_acquire_writer@spin_rw_mutex@tbb@@CA_NPEAV12@@Z ) +__TBB_SYMBOL( ?internal_acquire_reader@spin_rw_mutex@tbb@@CAXPEAV12@@Z ) +__TBB_SYMBOL( ?internal_downgrade@spin_rw_mutex@tbb@@CAXPEAV12@@Z ) +__TBB_SYMBOL( ?internal_upgrade@spin_rw_mutex@tbb@@CA_NPEAV12@@Z ) +__TBB_SYMBOL( ?internal_release_reader@spin_rw_mutex@tbb@@CAXPEAV12@@Z ) +__TBB_SYMBOL( ?internal_release_writer@spin_rw_mutex@tbb@@CAXPEAV12@@Z ) +__TBB_SYMBOL( ?internal_try_acquire_writer@spin_rw_mutex@tbb@@CA_NPEAV12@@Z ) +__TBB_SYMBOL( ?internal_try_acquire_reader@spin_rw_mutex@tbb@@CA_NPEAV12@@Z ) +#endif + +// spin_rw_mutex v3 +__TBB_SYMBOL( ?internal_construct@spin_rw_mutex_v3@tbb@@AEAAXXZ ) +__TBB_SYMBOL( ?internal_upgrade@spin_rw_mutex_v3@tbb@@AEAA_NXZ ) +__TBB_SYMBOL( ?internal_downgrade@spin_rw_mutex_v3@tbb@@AEAAXXZ ) +__TBB_SYMBOL( ?internal_acquire_reader@spin_rw_mutex_v3@tbb@@AEAAXXZ ) +__TBB_SYMBOL( ?internal_acquire_writer@spin_rw_mutex_v3@tbb@@AEAA_NXZ ) +__TBB_SYMBOL( ?internal_release_reader@spin_rw_mutex_v3@tbb@@AEAAXXZ ) +__TBB_SYMBOL( ?internal_release_writer@spin_rw_mutex_v3@tbb@@AEAAXXZ ) +__TBB_SYMBOL( ?internal_try_acquire_reader@spin_rw_mutex_v3@tbb@@AEAA_NXZ ) +__TBB_SYMBOL( ?internal_try_acquire_writer@spin_rw_mutex_v3@tbb@@AEAA_NXZ ) + +// spin_mutex.cpp +__TBB_SYMBOL( ?internal_construct@spin_mutex@tbb@@QEAAXXZ ) +__TBB_SYMBOL( ?internal_acquire@scoped_lock@spin_mutex@tbb@@AEAAXAEAV23@@Z ) +__TBB_SYMBOL( ?internal_release@scoped_lock@spin_mutex@tbb@@AEAAXXZ ) +__TBB_SYMBOL( ?internal_try_acquire@scoped_lock@spin_mutex@tbb@@AEAA_NAEAV23@@Z ) + +// mutex.cpp +__TBB_SYMBOL( ?internal_acquire@scoped_lock@mutex@tbb@@AEAAXAEAV23@@Z ) +__TBB_SYMBOL( ?internal_release@scoped_lock@mutex@tbb@@AEAAXXZ ) +__TBB_SYMBOL( ?internal_try_acquire@scoped_lock@mutex@tbb@@AEAA_NAEAV23@@Z ) +__TBB_SYMBOL( ?internal_construct@mutex@tbb@@AEAAXXZ ) +__TBB_SYMBOL( ?internal_destroy@mutex@tbb@@AEAAXXZ ) + +// recursive_mutex.cpp +__TBB_SYMBOL( ?internal_construct@recursive_mutex@tbb@@AEAAXXZ ) +__TBB_SYMBOL( ?internal_destroy@recursive_mutex@tbb@@AEAAXXZ ) +__TBB_SYMBOL( ?internal_acquire@scoped_lock@recursive_mutex@tbb@@AEAAXAEAV23@@Z ) +__TBB_SYMBOL( ?internal_try_acquire@scoped_lock@recursive_mutex@tbb@@AEAA_NAEAV23@@Z ) +__TBB_SYMBOL( ?internal_release@scoped_lock@recursive_mutex@tbb@@AEAAXXZ ) + +// queuing_mutex.cpp +__TBB_SYMBOL( ?internal_construct@queuing_mutex@tbb@@QEAAXXZ ) +__TBB_SYMBOL( ?acquire@scoped_lock@queuing_mutex@tbb@@QEAAXAEAV23@@Z ) +__TBB_SYMBOL( ?release@scoped_lock@queuing_mutex@tbb@@QEAAXXZ ) +__TBB_SYMBOL( ?try_acquire@scoped_lock@queuing_mutex@tbb@@QEAA_NAEAV23@@Z ) + +//critical_section.cpp +__TBB_SYMBOL( ?internal_construct@critical_section_v4@internal@tbb@@QEAAXXZ ) + +#if !TBB_NO_LEGACY +// concurrent_hash_map.cpp +__TBB_SYMBOL( ?internal_grow_predicate@hash_map_segment_base@internal@tbb@@QEBA_NXZ ) + +// concurrent_queue.cpp v2 +__TBB_SYMBOL( ??0concurrent_queue_base@internal@tbb@@IEAA@_K@Z ) +__TBB_SYMBOL( ??0concurrent_queue_iterator_base@internal@tbb@@IEAA@AEBVconcurrent_queue_base@12@@Z ) +__TBB_SYMBOL( ??1concurrent_queue_base@internal@tbb@@MEAA@XZ ) +__TBB_SYMBOL( ??1concurrent_queue_iterator_base@internal@tbb@@IEAA@XZ ) +__TBB_SYMBOL( ?advance@concurrent_queue_iterator_base@internal@tbb@@IEAAXXZ ) +__TBB_SYMBOL( ?assign@concurrent_queue_iterator_base@internal@tbb@@IEAAXAEBV123@@Z ) +__TBB_SYMBOL( ?internal_pop@concurrent_queue_base@internal@tbb@@IEAAXPEAX@Z ) +__TBB_SYMBOL( ?internal_pop_if_present@concurrent_queue_base@internal@tbb@@IEAA_NPEAX@Z ) +__TBB_SYMBOL( ?internal_push@concurrent_queue_base@internal@tbb@@IEAAXPEBX@Z ) +__TBB_SYMBOL( ?internal_push_if_not_full@concurrent_queue_base@internal@tbb@@IEAA_NPEBX@Z ) +__TBB_SYMBOL( ?internal_set_capacity@concurrent_queue_base@internal@tbb@@IEAAX_J_K@Z ) +__TBB_SYMBOL( ?internal_size@concurrent_queue_base@internal@tbb@@IEBA_JXZ ) +#endif + +// concurrent_queue v3 +__TBB_SYMBOL( ??0concurrent_queue_iterator_base_v3@internal@tbb@@IEAA@AEBVconcurrent_queue_base_v3@12@@Z ) +__TBB_SYMBOL( ??0concurrent_queue_iterator_base_v3@internal@tbb@@IEAA@AEBVconcurrent_queue_base_v3@12@_K@Z ) +__TBB_SYMBOL( ??1concurrent_queue_iterator_base_v3@internal@tbb@@IEAA@XZ ) +__TBB_SYMBOL( ?assign@concurrent_queue_iterator_base_v3@internal@tbb@@IEAAXAEBV123@@Z ) +__TBB_SYMBOL( ?advance@concurrent_queue_iterator_base_v3@internal@tbb@@IEAAXXZ ) +__TBB_SYMBOL( ??0concurrent_queue_base_v3@internal@tbb@@IEAA@_K@Z ) +__TBB_SYMBOL( ??1concurrent_queue_base_v3@internal@tbb@@MEAA@XZ ) +__TBB_SYMBOL( ?internal_push@concurrent_queue_base_v3@internal@tbb@@IEAAXPEBX@Z ) +__TBB_SYMBOL( ?internal_push_if_not_full@concurrent_queue_base_v3@internal@tbb@@IEAA_NPEBX@Z ) +__TBB_SYMBOL( ?internal_pop@concurrent_queue_base_v3@internal@tbb@@IEAAXPEAX@Z ) +__TBB_SYMBOL( ?internal_pop_if_present@concurrent_queue_base_v3@internal@tbb@@IEAA_NPEAX@Z ) +__TBB_SYMBOL( ?internal_abort@concurrent_queue_base_v3@internal@tbb@@IEAAXXZ ) +__TBB_SYMBOL( ?internal_size@concurrent_queue_base_v3@internal@tbb@@IEBA_JXZ ) +__TBB_SYMBOL( ?internal_empty@concurrent_queue_base_v3@internal@tbb@@IEBA_NXZ ) +__TBB_SYMBOL( ?internal_finish_clear@concurrent_queue_base_v3@internal@tbb@@IEAAXXZ ) +__TBB_SYMBOL( ?internal_set_capacity@concurrent_queue_base_v3@internal@tbb@@IEAAX_J_K@Z ) +__TBB_SYMBOL( ?internal_throw_exception@concurrent_queue_base_v3@internal@tbb@@IEBAXXZ ) +__TBB_SYMBOL( ?assign@concurrent_queue_base_v3@internal@tbb@@IEAAXAEBV123@@Z ) + +#if !TBB_NO_LEGACY +// concurrent_vector.cpp v2 +__TBB_SYMBOL( ?internal_assign@concurrent_vector_base@internal@tbb@@IEAAXAEBV123@_KP6AXPEAX1@ZP6AX2PEBX1@Z5@Z ) +__TBB_SYMBOL( ?internal_capacity@concurrent_vector_base@internal@tbb@@IEBA_KXZ ) +__TBB_SYMBOL( ?internal_clear@concurrent_vector_base@internal@tbb@@IEAAXP6AXPEAX_K@Z_N@Z ) +__TBB_SYMBOL( ?internal_copy@concurrent_vector_base@internal@tbb@@IEAAXAEBV123@_KP6AXPEAXPEBX1@Z@Z ) +__TBB_SYMBOL( ?internal_grow_by@concurrent_vector_base@internal@tbb@@IEAA_K_K0P6AXPEAX0@Z@Z ) +__TBB_SYMBOL( ?internal_grow_to_at_least@concurrent_vector_base@internal@tbb@@IEAAX_K0P6AXPEAX0@Z@Z ) +__TBB_SYMBOL( ?internal_push_back@concurrent_vector_base@internal@tbb@@IEAAPEAX_KAEA_K@Z ) +__TBB_SYMBOL( ?internal_reserve@concurrent_vector_base@internal@tbb@@IEAAX_K00@Z ) +#endif + +// concurrent_vector v3 +__TBB_SYMBOL( ??1concurrent_vector_base_v3@internal@tbb@@IEAA@XZ ) +__TBB_SYMBOL( ?internal_assign@concurrent_vector_base_v3@internal@tbb@@IEAAXAEBV123@_KP6AXPEAX1@ZP6AX2PEBX1@Z5@Z ) +__TBB_SYMBOL( ?internal_capacity@concurrent_vector_base_v3@internal@tbb@@IEBA_KXZ ) +__TBB_SYMBOL( ?internal_clear@concurrent_vector_base_v3@internal@tbb@@IEAA_KP6AXPEAX_K@Z@Z ) +__TBB_SYMBOL( ?internal_copy@concurrent_vector_base_v3@internal@tbb@@IEAAXAEBV123@_KP6AXPEAXPEBX1@Z@Z ) +__TBB_SYMBOL( ?internal_grow_by@concurrent_vector_base_v3@internal@tbb@@IEAA_K_K0P6AXPEAXPEBX0@Z2@Z ) +__TBB_SYMBOL( ?internal_grow_to_at_least@concurrent_vector_base_v3@internal@tbb@@IEAAX_K0P6AXPEAXPEBX0@Z2@Z ) +__TBB_SYMBOL( ?internal_push_back@concurrent_vector_base_v3@internal@tbb@@IEAAPEAX_KAEA_K@Z ) +__TBB_SYMBOL( ?internal_reserve@concurrent_vector_base_v3@internal@tbb@@IEAAX_K00@Z ) +__TBB_SYMBOL( ?internal_compact@concurrent_vector_base_v3@internal@tbb@@IEAAPEAX_KPEAXP6AX10@ZP6AX1PEBX0@Z@Z ) +__TBB_SYMBOL( ?internal_swap@concurrent_vector_base_v3@internal@tbb@@IEAAXAEAV123@@Z ) +__TBB_SYMBOL( ?internal_throw_exception@concurrent_vector_base_v3@internal@tbb@@IEBAX_K@Z ) +__TBB_SYMBOL( ?internal_resize@concurrent_vector_base_v3@internal@tbb@@IEAAX_K00PEBXP6AXPEAX0@ZP6AX210@Z@Z ) +__TBB_SYMBOL( ?internal_grow_to_at_least_with_result@concurrent_vector_base_v3@internal@tbb@@IEAA_K_K0P6AXPEAXPEBX0@Z2@Z ) + +// tbb_thread +__TBB_SYMBOL( ?allocate_closure_v3@internal@tbb@@YAPEAX_K@Z ) +__TBB_SYMBOL( ?detach@tbb_thread_v3@internal@tbb@@QEAAXXZ ) +__TBB_SYMBOL( ?free_closure_v3@internal@tbb@@YAXPEAX@Z ) +__TBB_SYMBOL( ?hardware_concurrency@tbb_thread_v3@internal@tbb@@SAIXZ ) +__TBB_SYMBOL( ?internal_start@tbb_thread_v3@internal@tbb@@AEAAXP6AIPEAX@Z0@Z ) +__TBB_SYMBOL( ?join@tbb_thread_v3@internal@tbb@@QEAAXXZ ) +__TBB_SYMBOL( ?move_v3@internal@tbb@@YAXAEAVtbb_thread_v3@12@0@Z ) +__TBB_SYMBOL( ?thread_get_id_v3@internal@tbb@@YA?AVid@tbb_thread_v3@12@XZ ) +__TBB_SYMBOL( ?thread_sleep_v3@internal@tbb@@YAXAEBVinterval_t@tick_count@2@@Z ) +__TBB_SYMBOL( ?thread_yield_v3@internal@tbb@@YAXXZ ) + +// condition_variable +__TBB_SYMBOL( ?internal_initialize_condition_variable@internal@interface5@tbb@@YAXAEATcondvar_impl_t@123@@Z ) +__TBB_SYMBOL( ?internal_condition_variable_wait@internal@interface5@tbb@@YA_NAEATcondvar_impl_t@123@PEAVmutex@3@PEBVinterval_t@tick_count@3@@Z ) +__TBB_SYMBOL( ?internal_condition_variable_notify_one@internal@interface5@tbb@@YAXAEATcondvar_impl_t@123@@Z ) +__TBB_SYMBOL( ?internal_condition_variable_notify_all@internal@interface5@tbb@@YAXAEATcondvar_impl_t@123@@Z ) +__TBB_SYMBOL( ?internal_destroy_condition_variable@internal@interface5@tbb@@YAXAEATcondvar_impl_t@123@@Z ) + +#undef __TBB_SYMBOL diff --git a/src/tbb/src/tbb/xbox360-tbb-export.def b/src/tbb/src/tbb/xbox360-tbb-export.def new file mode 100644 index 0000000..66c6580 --- /dev/null +++ b/src/tbb/src/tbb/xbox360-tbb-export.def @@ -0,0 +1,234 @@ +; Copyright 2005-2012 Intel Corporation. All Rights Reserved. +; +; This file is part of Threading Building Blocks. +; +; Threading Building Blocks is free software; you can redistribute it +; and/or modify it under the terms of the GNU General Public License +; version 2 as published by the Free Software Foundation. +; +; Threading Building Blocks is distributed in the hope that it will be +; useful, but WITHOUT ANY WARRANTY; without even the implied warranty +; of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with Threading Building Blocks; if not, write to the Free Software +; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +; +; As a special exception, you may use this file as part of a free software +; library without restriction. Specifically, if other files instantiate +; templates or use macros or inline functions from this file, or you compile +; this file and link it with other files to produce an executable, this +; file does not by itself cause the resulting executable to be covered by +; the GNU General Public License. This exception does not however +; invalidate any other reasons why the executable file might be covered by +; the GNU General Public License. + +EXPORTS + +; Assembly-language support that is called directly by clients +;__TBB_machine_cmpswp1 +;__TBB_machine_cmpswp2 +;__TBB_machine_cmpswp4 +;__TBB_machine_cmpswp8 +;__TBB_machine_fetchadd1 +;__TBB_machine_fetchadd2 +;__TBB_machine_fetchadd4 +;__TBB_machine_fetchadd8 +;__TBB_machine_fetchstore1 +;__TBB_machine_fetchstore2 +;__TBB_machine_fetchstore4 +;__TBB_machine_fetchstore8 +;__TBB_machine_store8 +;__TBB_machine_load8 +;__TBB_machine_trylockbyte + +; cache_aligned_allocator.cpp +?NFS_Allocate@internal@tbb@@YAPAXIIPAX@Z @1 +?NFS_GetLineSize@internal@tbb@@YAIXZ @2 +?NFS_Free@internal@tbb@@YAXPAX@Z @3 +?allocate_via_handler_v3@internal@tbb@@YAPAXI@Z @4 +?deallocate_via_handler_v3@internal@tbb@@YAXPAX@Z @5 +?is_malloc_used_v3@internal@tbb@@YA_NXZ @6 + +; task.cpp v3 +?allocate@allocate_additional_child_of_proxy@internal@tbb@@QBAAAVtask@3@I@Z @7 +?allocate@allocate_child_proxy@internal@tbb@@QBAAAVtask@3@I@Z @8 +?allocate@allocate_continuation_proxy@internal@tbb@@QBAAAVtask@3@I@Z @9 +?allocate@allocate_root_proxy@internal@tbb@@SAAAVtask@3@I@Z @10 +?destroy@task@tbb@@QAAXAAV12@@Z @11 +?free@allocate_additional_child_of_proxy@internal@tbb@@QBAXAAVtask@3@@Z @12 +?free@allocate_child_proxy@internal@tbb@@QBAXAAVtask@3@@Z @13 +?free@allocate_continuation_proxy@internal@tbb@@QBAXAAVtask@3@@Z @14 +?free@allocate_root_proxy@internal@tbb@@SAXAAVtask@3@@Z @15 +?internal_set_ref_count@task@tbb@@AAAXH@Z @16 +?is_owned_by_current_thread@task@tbb@@QBA_NXZ @17 +?note_affinity@task@tbb@@UAAXG@Z @18 +?resize@affinity_partitioner_base_v3@internal@tbb@@AAAXI@Z @19 +?self@task@tbb@@SAAAV12@XZ @20 +?spawn_and_wait_for_all@task@tbb@@QAAXAAVtask_list@2@@Z @21 +?default_num_threads@task_scheduler_init@tbb@@SAHXZ @22 +?initialize@task_scheduler_init@tbb@@QAAXHI@Z @23 +?initialize@task_scheduler_init@tbb@@QAAXH@Z @24 +?terminate@task_scheduler_init@tbb@@QAAXXZ @25 +?observe@task_scheduler_observer_v3@internal@tbb@@QAAX_N@Z @26 + +; exception handling support +?allocate@allocate_root_with_context_proxy@internal@tbb@@QBAAAVtask@3@I@Z @27 +?free@allocate_root_with_context_proxy@internal@tbb@@QBAXAAVtask@3@@Z @28 +?is_group_execution_cancelled@task_group_context@tbb@@QBA_NXZ @29 +?cancel_group_execution@task_group_context@tbb@@QAA_NXZ @30 +?reset@task_group_context@tbb@@QAAXXZ @31 +?init@task_group_context@tbb@@IAAXXZ @32 +??1task_group_context@tbb@@QAA@XZ @33 +?name@captured_exception@tbb@@UBAPBDXZ @34 +?what@captured_exception@tbb@@UBAPBDXZ @35 +??1captured_exception@tbb@@UAA@XZ @36 + +; tbb_misc.cpp +?assertion_failure@tbb@@YAXPBDH00@Z @37 +?get_initial_auto_partitioner_divisor@internal@tbb@@YAIXZ @38 +?handle_perror@internal@tbb@@YAXHPBD@Z @39 +?set_assertion_handler@tbb@@YAP6AXPBDH00@ZP6AX0H00@Z@Z @40 +?runtime_warning@internal@tbb@@YAXPBDZZ @41 + +; tbb_main.cpp +?itt_load_pointer_with_acquire_v3@internal@tbb@@YAPAXPBX@Z @42 +?itt_store_pointer_with_release_v3@internal@tbb@@YAXPAX0@Z @43 + +; pipeline.cpp +??0pipeline@tbb@@QAA@XZ @44 +??1filter@tbb@@UAA@XZ @45 +??1pipeline@tbb@@UAA@XZ @46 +??_7pipeline@tbb@@6B@ @47 +?add_filter@pipeline@tbb@@QAAXAAVfilter@2@@Z @48 +?clear@pipeline@tbb@@QAAXXZ @49 +?inject_token@pipeline@tbb@@AAAXAAVtask@2@@Z @50 +?run@pipeline@tbb@@QAAXI@Z @51 + +; queuing_rw_mutex.cpp +?acquire@scoped_lock@queuing_rw_mutex@tbb@@QAAXAAV23@_N@Z @52 +?downgrade_to_reader@scoped_lock@queuing_rw_mutex@tbb@@QAA_NXZ @53 +?release@scoped_lock@queuing_rw_mutex@tbb@@QAAXXZ @54 +?upgrade_to_writer@scoped_lock@queuing_rw_mutex@tbb@@QAA_NXZ @55 +?try_acquire@scoped_lock@queuing_rw_mutex@tbb@@QAA_NAAV23@_N@Z @56 + +#if !TBB_NO_LEGACY +; spin_rw_mutex.cpp v2 +?internal_acquire_reader@spin_rw_mutex@tbb@@CAXPAV12@@Z @57 +?internal_acquire_writer@spin_rw_mutex@tbb@@CA_NPAV12@@Z @58 +?internal_downgrade@spin_rw_mutex@tbb@@CAXPAV12@@Z @59 +?internal_itt_releasing@spin_rw_mutex@tbb@@CAXPAV12@@Z @60 +?internal_release_reader@spin_rw_mutex@tbb@@CAXPAV12@@Z @61 +?internal_release_writer@spin_rw_mutex@tbb@@CAXPAV12@@Z @62 +?internal_upgrade@spin_rw_mutex@tbb@@CA_NPAV12@@Z @63 +?internal_try_acquire_writer@spin_rw_mutex@tbb@@CA_NPAV12@@Z @64 +?internal_try_acquire_reader@spin_rw_mutex@tbb@@CA_NPAV12@@Z @65 +#endif + +; spin_rw_mutex v3 +?internal_upgrade@spin_rw_mutex_v3@tbb@@AAA_NXZ @66 +?internal_downgrade@spin_rw_mutex_v3@tbb@@AAAXXZ @67 +?internal_acquire_reader@spin_rw_mutex_v3@tbb@@AAAXXZ @68 +?internal_acquire_writer@spin_rw_mutex_v3@tbb@@AAA_NXZ @69 +?internal_release_reader@spin_rw_mutex_v3@tbb@@AAAXXZ @70 +?internal_release_writer@spin_rw_mutex_v3@tbb@@AAAXXZ @71 +?internal_try_acquire_reader@spin_rw_mutex_v3@tbb@@AAA_NXZ @72 +?internal_try_acquire_writer@spin_rw_mutex_v3@tbb@@AAA_NXZ @73 + +; spin_mutex.cpp +?internal_acquire@scoped_lock@spin_mutex@tbb@@AAAXAAV23@@Z @74 +?internal_release@scoped_lock@spin_mutex@tbb@@AAAXXZ @75 +?internal_try_acquire@scoped_lock@spin_mutex@tbb@@AAA_NAAV23@@Z @76 + +; mutex.cpp +?internal_acquire@scoped_lock@mutex@tbb@@AAAXAAV23@@Z @77 +?internal_release@scoped_lock@mutex@tbb@@AAAXXZ @78 +?internal_try_acquire@scoped_lock@mutex@tbb@@AAA_NAAV23@@Z @79 +?internal_construct@mutex@tbb@@AAAXXZ @80 +?internal_destroy@mutex@tbb@@AAAXXZ @81 + +; recursive_mutex.cpp +?internal_acquire@scoped_lock@recursive_mutex@tbb@@AAAXAAV23@@Z @82 +?internal_release@scoped_lock@recursive_mutex@tbb@@AAAXXZ @83 +?internal_try_acquire@scoped_lock@recursive_mutex@tbb@@AAA_NAAV23@@Z @84 +?internal_construct@recursive_mutex@tbb@@AAAXXZ @85 +?internal_destroy@recursive_mutex@tbb@@AAAXXZ @86 + +; queuing_mutex.cpp +?acquire@scoped_lock@queuing_mutex@tbb@@QAAXAAV23@@Z @87 +?release@scoped_lock@queuing_mutex@tbb@@QAAXXZ @88 +?try_acquire@scoped_lock@queuing_mutex@tbb@@QAA_NAAV23@@Z @89 + +; concurrent_hash_map.cpp +?internal_grow_predicate@hash_map_segment_base@internal@tbb@@QBA_NXZ @90 + +#if !TBB_NO_LEGACY +; concurrent_queue.cpp v2 +?advance@concurrent_queue_iterator_base@internal@tbb@@IAAXXZ @91 +?assign@concurrent_queue_iterator_base@internal@tbb@@IAAXABV123@@Z @92 +?internal_size@concurrent_queue_base@internal@tbb@@IBAHXZ @93 +??0concurrent_queue_base@internal@tbb@@IAA@I@Z @94 +??0concurrent_queue_iterator_base@internal@tbb@@IAA@ABVconcurrent_queue_base@12@@Z @95 +??1concurrent_queue_base@internal@tbb@@MAA@XZ @96 +??1concurrent_queue_iterator_base@internal@tbb@@IAA@XZ @97 +?internal_pop@concurrent_queue_base@internal@tbb@@IAAXPAX@Z @98 +?internal_pop_if_present@concurrent_queue_base@internal@tbb@@IAA_NPAX@Z @99 +?internal_push@concurrent_queue_base@internal@tbb@@IAAXPBX@Z @100 +?internal_push_if_not_full@concurrent_queue_base@internal@tbb@@IAA_NPBX@Z @101 +?internal_set_capacity@concurrent_queue_base@internal@tbb@@IAAXHI@Z @102 +#endif + +; concurrent_queue v3 +??1concurrent_queue_iterator_base_v3@internal@tbb@@IAA@XZ @103 +??0concurrent_queue_iterator_base_v3@internal@tbb@@IAA@ABVconcurrent_queue_base_v3@12@@Z @104 +?advance@concurrent_queue_iterator_base_v3@internal@tbb@@IAAXXZ @105 +?assign@concurrent_queue_iterator_base_v3@internal@tbb@@IAAXABV123@@Z @106 +??0concurrent_queue_base_v3@internal@tbb@@IAA@I@Z @107 +??1concurrent_queue_base_v3@internal@tbb@@MAA@XZ @108 +?internal_pop@concurrent_queue_base_v3@internal@tbb@@IAAXPAX@Z @109 +?internal_pop_if_present@concurrent_queue_base_v3@internal@tbb@@IAA_NPAX@Z @110 +?internal_push@concurrent_queue_base_v3@internal@tbb@@IAAXPBX@Z @111 +?internal_push_if_not_full@concurrent_queue_base_v3@internal@tbb@@IAA_NPBX@Z @112 +?internal_size@concurrent_queue_base_v3@internal@tbb@@IBAHXZ @113 +?internal_set_capacity@concurrent_queue_base_v3@internal@tbb@@IAAXHI@Z @114 +?internal_finish_clear@concurrent_queue_base_v3@internal@tbb@@IAAXXZ @115 +?internal_throw_exception@concurrent_queue_base_v3@internal@tbb@@IBAXXZ @116 + +#if !TBB_NO_LEGACY +; concurrent_vector.cpp v2 +?internal_assign@concurrent_vector_base@internal@tbb@@IAAXABV123@IP6AXPAXI@ZP6AX1PBXI@Z4@Z @117 +?internal_capacity@concurrent_vector_base@internal@tbb@@IBAIXZ @118 +?internal_clear@concurrent_vector_base@internal@tbb@@IAAXP6AXPAXI@Z_N@Z @119 +?internal_copy@concurrent_vector_base@internal@tbb@@IAAXABV123@IP6AXPAXPBXI@Z@Z @120 +?internal_grow_by@concurrent_vector_base@internal@tbb@@IAAIIIP6AXPAXI@Z@Z @121 +?internal_grow_to_at_least@concurrent_vector_base@internal@tbb@@IAAXIIP6AXPAXI@Z@Z @122 +?internal_push_back@concurrent_vector_base@internal@tbb@@IAAPAXIAAI@Z @123 +?internal_reserve@concurrent_vector_base@internal@tbb@@IAAXIII@Z @124 +#endif + +; concurrent_vector v3 +??1concurrent_vector_base_v3@internal@tbb@@IAA@XZ @125 +?internal_assign@concurrent_vector_base_v3@internal@tbb@@IAAXABV123@IP6AXPAXI@ZP6AX1PBXI@Z4@Z @126 +?internal_capacity@concurrent_vector_base_v3@internal@tbb@@IBAIXZ @127 +?internal_clear@concurrent_vector_base_v3@internal@tbb@@IAAIP6AXPAXI@Z@Z @128 +?internal_copy@concurrent_vector_base_v3@internal@tbb@@IAAXABV123@IP6AXPAXPBXI@Z@Z @129 +?internal_grow_by@concurrent_vector_base_v3@internal@tbb@@IAAIIIP6AXPAXPBXI@Z1@Z @130 +?internal_grow_to_at_least@concurrent_vector_base_v3@internal@tbb@@IAAXIIP6AXPAXPBXI@Z1@Z @131 +?internal_push_back@concurrent_vector_base_v3@internal@tbb@@IAAPAXIAAI@Z @132 +?internal_reserve@concurrent_vector_base_v3@internal@tbb@@IAAXIII@Z @133 +?internal_compact@concurrent_vector_base_v3@internal@tbb@@IAAPAXIPAXP6AX0I@ZP6AX0PBXI@Z@Z @134 +?internal_swap@concurrent_vector_base_v3@internal@tbb@@IAAXAAV123@@Z @135 +?internal_throw_exception@concurrent_vector_base_v3@internal@tbb@@IBAXI@Z @136 + +; tbb_thread +?join@tbb_thread_v3@internal@tbb@@QAAXXZ @137 +?detach@tbb_thread_v3@internal@tbb@@QAAXXZ @138 +?internal_start@tbb_thread_v3@internal@tbb@@AAAXP6AIPAX@Z0@Z @139 +?allocate_closure_v3@internal@tbb@@YAPAXI@Z @140 +?free_closure_v3@internal@tbb@@YAXPAX@Z @141 +?hardware_concurrency@tbb_thread_v3@internal@tbb@@SAIXZ @142 +?thread_yield_v3@internal@tbb@@YAXXZ @143 +?thread_sleep_v3@internal@tbb@@YAXABVinterval_t@tick_count@2@@Z @144 +?move_v3@internal@tbb@@YAXAAVtbb_thread_v3@12@0@Z @145 +?thread_get_id_v3@internal@tbb@@YA?AVid@tbb_thread_v3@12@XZ @146 diff --git a/src/tbb/src/tbbmalloc/Customize.h b/src/tbb/src/tbbmalloc/Customize.h new file mode 100644 index 0000000..de3fb18 --- /dev/null +++ b/src/tbb/src/tbbmalloc/Customize.h @@ -0,0 +1,152 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _TBB_malloc_Customize_H_ +#define _TBB_malloc_Customize_H_ + +// customizing MALLOC_ASSERT macro +#include "tbb/tbb_stddef.h" +#define MALLOC_ASSERT(assertion, message) __TBB_ASSERT(assertion, message) + +#ifndef MALLOC_DEBUG +#define MALLOC_DEBUG TBB_USE_DEBUG +#endif + +#include "tbb/tbb_machine.h" + +#if DO_ITT_NOTIFY +#include "tbb/itt_notify.h" +#define MALLOC_ITT_SYNC_PREPARE(pointer) ITT_NOTIFY(sync_prepare, (pointer)) +#define MALLOC_ITT_SYNC_ACQUIRED(pointer) ITT_NOTIFY(sync_acquired, (pointer)) +#define MALLOC_ITT_SYNC_RELEASING(pointer) ITT_NOTIFY(sync_releasing, (pointer)) +#define MALLOC_ITT_SYNC_CANCEL(pointer) ITT_NOTIFY(sync_cancel, (pointer)) +#else +#define MALLOC_ITT_SYNC_PREPARE(pointer) ((void)0) +#define MALLOC_ITT_SYNC_ACQUIRED(pointer) ((void)0) +#define MALLOC_ITT_SYNC_RELEASING(pointer) ((void)0) +#define MALLOC_ITT_SYNC_CANCEL(pointer) ((void)0) +#endif + +//! Stripped down version of spin_mutex. +/** Instances of MallocMutex must be declared in memory that is zero-initialized. + There are no constructors. This is a feature that lets it be + used in situations where the mutex might be used while file-scope constructors + are running. + + There are no methods "acquire" or "release". The scoped_lock must be used + in a strict block-scoped locking pattern. Omitting these methods permitted + further simplification. */ +class MallocMutex : tbb::internal::no_copy { + __TBB_atomic_flag value; + +public: + class scoped_lock : tbb::internal::no_copy { + __TBB_Flag unlock_value; + MallocMutex& mutex; + public: + scoped_lock( MallocMutex& m ) : unlock_value(__TBB_LockByte(m.value)), mutex(m) {} + scoped_lock( MallocMutex& m, bool block, bool *locked ) : mutex(m) { + unlock_value = 1; + if (block) { + unlock_value = __TBB_LockByte(m.value); + if (locked) *locked = true; + } else { + if (__TBB_TryLockByte(m.value)) { + unlock_value = 0; + if (locked) *locked = true; + } else + if (locked) *locked = false; + } + } + ~scoped_lock() { + if (!unlock_value) __TBB_UnlockByte(mutex.value, unlock_value); + } + }; + friend class scoped_lock; +}; + +inline intptr_t AtomicIncrement( volatile intptr_t& counter ) { + return __TBB_FetchAndAddW( &counter, 1 )+1; +} + +inline uintptr_t AtomicAdd( volatile intptr_t& counter, intptr_t value ) { + return __TBB_FetchAndAddW( &counter, value ); +} + +inline intptr_t AtomicCompareExchange( volatile intptr_t& location, intptr_t new_value, intptr_t comparand) { + return __TBB_CompareAndSwapW( &location, new_value, comparand ); +} + +inline intptr_t FencedLoad( const volatile intptr_t &location ) { + return __TBB_load_with_acquire(location); +} + +inline void FencedStore( volatile intptr_t &location, intptr_t value ) { + __TBB_store_with_release(location, value); +} + +inline void SpinWaitWhileEq(const volatile intptr_t &location, const intptr_t value) { + tbb::internal::spin_wait_while_eq(location, value); +} + +inline void SpinWaitUntilEq(const volatile intptr_t &location, const intptr_t value) { + tbb::internal::spin_wait_until_eq(location, value); +} + +inline intptr_t BitScanRev(uintptr_t x) { + return !x? -1 : __TBB_Log2(x); +} + +inline void AtomicOr(volatile void *operand, uintptr_t addend) { + __TBB_AtomicOR(operand, addend); +} + +inline void AtomicAnd(volatile void *operand, uintptr_t addend) { + __TBB_AtomicAND(operand, addend); +} + +#define USE_DEFAULT_MEMORY_MAPPING 1 + +// To support malloc replacement with LD_PRELOAD +#include "proxy.h" + +#if MALLOC_LD_PRELOAD +#define malloc_proxy __TBB_malloc_proxy +extern "C" void * __TBB_malloc_proxy(size_t) __attribute__ ((weak)); +#else +const bool malloc_proxy = false; +#endif + +namespace rml { +namespace internal { + void init_tbbmalloc(); +} } // namespaces + +#define MALLOC_EXTRA_INITIALIZATION rml::internal::init_tbbmalloc() + +#endif /* _TBB_malloc_Customize_H_ */ diff --git a/src/tbb/src/tbbmalloc/MapMemory.h b/src/tbb/src/tbbmalloc/MapMemory.h new file mode 100644 index 0000000..b036cf4 --- /dev/null +++ b/src/tbb/src/tbbmalloc/MapMemory.h @@ -0,0 +1,129 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _itt_shared_malloc_MapMemory_H +#define _itt_shared_malloc_MapMemory_H + +#include <stdlib.h> + +void *ErrnoPreservingMalloc(size_t bytes) +{ + int prevErrno = errno; + void *ret = malloc( bytes ); + if (!ret) + errno = prevErrno; + return ret; +} + +#if __linux__ || __APPLE__ || __sun || __FreeBSD__ + +#if __sun && !defined(_XPG4_2) + // To have void* as mmap's 1st argument + #define _XPG4_2 1 + #define XPG4_WAS_DEFINED 1 +#endif + +#include <sys/mman.h> +#if __linux__ +/* __TBB_MAP_HUGETLB is MAP_HUGETLB from system header linux/mman.h. + The header do not included here, as on some Linux flavors inclusion of + linux/mman.h leads to compilation error, + while changing of MAP_HUGETLB is highly unexpected. +*/ +#define __TBB_MAP_HUGETLB 0x40000 +#else +#define __TBB_MAP_HUGETLB 0 +#endif + +#if XPG4_WAS_DEFINED + #undef _XPG4_2 + #undef XPG4_WAS_DEFINED +#endif + +#define MEMORY_MAPPING_USES_MALLOC 0 +void* MapMemory (size_t bytes, bool hugePages) +{ + void* result = 0; + int prevErrno = errno; +#ifndef MAP_ANONYMOUS +// Mac OS* X defines MAP_ANON, which is deprecated in Linux. +#define MAP_ANONYMOUS MAP_ANON +#endif /* MAP_ANONYMOUS */ + int addFlags = hugePages? __TBB_MAP_HUGETLB : 0; + result = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|addFlags, -1, 0); + if (result==MAP_FAILED) + errno = prevErrno; + return result==MAP_FAILED? 0: result; +} + +int UnmapMemory(void *area, size_t bytes) +{ + int prevErrno = errno; + int ret = munmap(area, bytes); + if (-1 == ret) + errno = prevErrno; + return ret; +} + +#elif (_WIN32 || _WIN64) && !_XBOX +#include <windows.h> + +#define MEMORY_MAPPING_USES_MALLOC 0 +void* MapMemory (size_t bytes, bool) +{ + /* Is VirtualAlloc thread safe? */ + return VirtualAlloc(NULL, bytes, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); +} + +int UnmapMemory(void *area, size_t bytes) +{ + BOOL result = VirtualFree(area, 0, MEM_RELEASE); + return !result; +} + +#else + +#define MEMORY_MAPPING_USES_MALLOC 1 +void* MapMemory (size_t bytes, bool) +{ + return ErrnoPreservingMalloc( bytes ); +} + +int UnmapMemory(void *area, size_t bytes) +{ + free( area ); + return 0; +} + +#endif /* OS dependent */ + +#if MALLOC_CHECK_RECURSION && MEMORY_MAPPING_USES_MALLOC +#error Impossible to protect against malloc recursion when memory mapping uses malloc. +#endif + +#endif /* _itt_shared_malloc_MapMemory_H */ diff --git a/src/tbb/src/tbbmalloc/Statistics.h b/src/tbb/src/tbbmalloc/Statistics.h new file mode 100644 index 0000000..b6bd5be --- /dev/null +++ b/src/tbb/src/tbbmalloc/Statistics.h @@ -0,0 +1,137 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#define MAX_THREADS 1024 +#define NUM_OF_BINS 30 +#define ThreadCommonCounters NUM_OF_BINS + +enum counter_type { + allocBlockNew = 0, + allocBlockPublic, + allocBumpPtrUsed, + allocFreeListUsed, + allocPrivatized, + examineEmptyEnough, + examineNotEmpty, + freeRestoreBumpPtr, + freeByOtherThread, + freeToActiveBlock, + freeToInactiveBlock, + freeBlockPublic, + freeBlockBack, + MaxCounters +}; +enum common_counter_type { + allocNewLargeObj = 0, + allocCachedLargeObj, + cacheLargeObj, + freeLargeObj, + lockPublicFreeList, + freeToOtherThread +}; + +#if COLLECT_STATISTICS +/* Statistics reporting callback registred via a static object dtor + on Posix or DLL_PROCESS_DETACH on Windows. + */ + +static bool reportAllocationStatistics; + +struct bin_counters { + int counter[MaxCounters]; +}; + +static bin_counters statistic[MAX_THREADS][NUM_OF_BINS+1]; //zero-initialized; + +static inline int STAT_increment(int thread, int bin, int ctr) +{ + return reportAllocationStatistics && thread < MAX_THREADS ? ++(statistic[thread][bin].counter[ctr]) : 0; +} + +static inline void initStatisticsCollection() { +#if defined(MALLOCENV_COLLECT_STATISTICS) + if (NULL != getenv(MALLOCENV_COLLECT_STATISTICS)) + reportAllocationStatistics = true; +#endif +} + +#else +#define STAT_increment(a,b,c) ((void)0) +#endif /* COLLECT_STATISTICS */ + +#if COLLECT_STATISTICS +static inline void STAT_print(int thread) +{ + if (!reportAllocationStatistics) + return; + + char filename[100]; +#if USE_PTHREAD + sprintf(filename, "stat_ScalableMalloc_proc%04d_thr%04d.log", getpid(), thread); +#else + sprintf(filename, "stat_ScalableMalloc_thr%04d.log", thread); +#endif + FILE* outfile = fopen(filename, "w"); + for(int i=0; i<NUM_OF_BINS; ++i) + { + bin_counters& ctrs = statistic[thread][i]; + fprintf(outfile, "Thr%04d Bin%02d", thread, i); + fprintf(outfile, ": allocNewBlocks %5d", ctrs.counter[allocBlockNew]); + fprintf(outfile, ", allocPublicBlocks %5d", ctrs.counter[allocBlockPublic]); + fprintf(outfile, ", restoreBumpPtr %5d", ctrs.counter[freeRestoreBumpPtr]); + fprintf(outfile, ", privatizeCalled %10d", ctrs.counter[allocPrivatized]); + fprintf(outfile, ", emptyEnough %10d", ctrs.counter[examineEmptyEnough]); + fprintf(outfile, ", notEmptyEnough %10d", ctrs.counter[examineNotEmpty]); + fprintf(outfile, ", freeBlocksPublic %5d", ctrs.counter[freeBlockPublic]); + fprintf(outfile, ", freeBlocksBack %5d", ctrs.counter[freeBlockBack]); + fprintf(outfile, "\n"); + } + for(int i=0; i<NUM_OF_BINS; ++i) + { + bin_counters& ctrs = statistic[thread][i]; + fprintf(outfile, "Thr%04d Bin%02d", thread, i); + fprintf(outfile, ": allocBumpPtr %10d", ctrs.counter[allocBumpPtrUsed]); + fprintf(outfile, ", allocFreeList %10d", ctrs.counter[allocFreeListUsed]); + fprintf(outfile, ", freeToActiveBlk %10d", ctrs.counter[freeToActiveBlock]); + fprintf(outfile, ", freeToInactive %10d", ctrs.counter[freeToInactiveBlock]); + fprintf(outfile, ", freedByOther %10d", ctrs.counter[freeByOtherThread]); + fprintf(outfile, "\n"); + } + bin_counters& ctrs = statistic[thread][ThreadCommonCounters]; + fprintf(outfile, "Thr%04d common counters", thread); + fprintf(outfile, ": allocNewLargeObject %5d", ctrs.counter[allocNewLargeObj]); + fprintf(outfile, ": allocCachedLargeObject %5d", ctrs.counter[allocCachedLargeObj]); + fprintf(outfile, ", cacheLargeObject %5d", ctrs.counter[cacheLargeObj]); + fprintf(outfile, ", freeLargeObject %5d", ctrs.counter[freeLargeObj]); + fprintf(outfile, ", lockPublicFreeList %5d", ctrs.counter[lockPublicFreeList]); + fprintf(outfile, ", freeToOtherThread %10d", ctrs.counter[freeToOtherThread]); + fprintf(outfile, "\n"); + + fclose(outfile); +} +#endif diff --git a/src/tbb/src/tbbmalloc/TypeDefinitions.h b/src/tbb/src/tbbmalloc/TypeDefinitions.h new file mode 100644 index 0000000..5098ce2 --- /dev/null +++ b/src/tbb/src/tbbmalloc/TypeDefinitions.h @@ -0,0 +1,118 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _itt_shared_malloc_TypeDefinitions_H_ +#define _itt_shared_malloc_TypeDefinitions_H_ + +// Define preprocessor symbols used to determine architecture +#if _WIN32||_WIN64 +# if defined(_M_X64)||defined(__x86_64__) // the latter for MinGW support +# define __ARCH_x86_64 1 +# elif defined(_M_IA64) +# define __ARCH_ipf 1 +# elif defined(_M_IX86)||defined(__i386__) // the latter for MinGW support +# define __ARCH_x86_32 1 +# else +# error Unknown processor architecture for Windows +# endif +# define USE_WINTHREAD 1 +#else /* Assume generic Unix */ +# if __x86_64__ +# define __ARCH_x86_64 1 +# elif __ia64__ +# define __ARCH_ipf 1 +# elif __i386__ || __i386 +# define __ARCH_x86_32 1 +# else +# define __ARCH_other 1 +# endif +# define USE_PTHREAD 1 +#endif + +// According to C99 standard INTPTR_MIN defined for C++ +// iff __STDC_LIMIT_MACROS pre-defined +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +// Include files containing declarations of intptr_t and uintptr_t +#include <stddef.h> // size_t +#if _MSC_VER +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +#else +#include <stdint.h> +#endif + +namespace rml { +namespace internal { + +extern bool original_malloc_found; +extern void* (*original_malloc_ptr)(size_t); +extern void (*original_free_ptr)(void*); + +} } // namespaces + +//! PROVIDE YOUR OWN Customize.h IF YOU FEEL NECESSARY +#include "Customize.h" + +/* + * Functions to align an integer down or up to the given power of two, + * and test for such an alignment, and for power of two. + */ +template<typename T> +static inline T alignDown(T arg, uintptr_t alignment) { + return T( (uintptr_t)arg & ~(alignment-1)); +} +template<typename T> +static inline T alignUp (T arg, uintptr_t alignment) { + return T(((uintptr_t)arg+(alignment-1)) & ~(alignment-1)); + // /*is this better?*/ return (((uintptr_t)arg-1) | (alignment-1)) + 1; +} +template<typename T> // works for not power-of-2 alignments +static inline T alignUpGeneric(T arg, uintptr_t alignment) { + if (size_t rem = arg % alignment) { + arg += alignment - rem; + } + return arg; +} +template<typename T> +static inline bool isAligned(T arg, uintptr_t alignment) { + return 0==((uintptr_t)arg & (alignment-1)); +} +static inline bool isPowerOfTwo(uintptr_t arg) { + return arg && (0==(arg & (arg-1))); +} +static inline bool isPowerOfTwoMultiple(uintptr_t arg, uintptr_t divisor) { + // Divisor is assumed to be a power of two (which is valid for current uses). + MALLOC_ASSERT( isPowerOfTwo(divisor), "Divisor should be a power of two" ); + return arg && (0==(arg & (arg-divisor))); +} + +#endif /* _itt_shared_malloc_TypeDefinitions_H_ */ diff --git a/src/tbb/src/tbbmalloc/backend.cpp b/src/tbb/src/tbbmalloc/backend.cpp new file mode 100644 index 0000000..62c015e --- /dev/null +++ b/src/tbb/src/tbbmalloc/backend.cpp @@ -0,0 +1,1125 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include <string.h> /* for memset */ +#include <errno.h> +#include "tbbmalloc_internal.h" + +namespace rml { +namespace internal { + +/*********** Code to acquire memory from the OS or other executive ****************/ + +/* + syscall/malloc can set non-zero errno in case of failure, + but later allocator might be able to find memory to fulfil the request. + And we do not want changing of errno by successful scalable_malloc call. + To support this, restore old errno in (get|free)RawMemory, and set errno + in frontend just before returning to user code. + Please note: every syscall/libc call used inside scalable_malloc that + sets errno must be protected this way, not just memory allocation per se. +*/ + +#if USE_DEFAULT_MEMORY_MAPPING +#include "MapMemory.h" +#else +/* assume MapMemory and UnmapMemory are customized */ +#endif + +void* getRawMemory (size_t size, bool hugePages) { + return MapMemory(size, hugePages); +} + +bool freeRawMemory (void *object, size_t size) { + return UnmapMemory(object, size); +} + +void *Backend::getRawMem(size_t &size) const +{ + if (extMemPool->userPool()) { + size = alignUpGeneric(size, extMemPool->granularity); + return (*extMemPool->rawAlloc)(extMemPool->poolId, size); + } + if (ExtMemoryPool::useHugePages) { + size_t hugeSize = alignUpGeneric(size, ExtMemoryPool::hugePageSize); + if (void *res = getRawMemory(hugeSize, /*hugePages=*/true)) { + size = hugeSize; + return res; + } + ExtMemoryPool::useHugePages = false; + } + size_t granSize = alignUpGeneric(size, extMemPool->granularity); + if (void *res = getRawMemory(granSize, /*hugePages=*/false)) { + size = granSize; + return res; + } + return NULL; +} + +void Backend::freeRawMem(void *object, size_t size) const +{ + if (extMemPool->userPool()) + (*extMemPool->rawFree)(extMemPool->poolId, object, size); + else { + // something that looks like a huge page is releasing, + // so a huge page might be available at next allocation + // TODO: keep page status in regions and use exact check here + if (ExtMemoryPool::hugePageSize && !(size % ExtMemoryPool::hugePageSize)) + ExtMemoryPool::useHugePages = true; + freeRawMemory(object, size); + } +} + +/********* End memory acquisition code ********************************/ + +// Protected object size. After successful locking returns size of locked block, +// and releasing requires setting block size. +class GuardedSize : tbb::internal::no_copy { + uintptr_t value; +public: + enum State { + LOCKED, + COAL_BLOCK, // block is coalescing now + MAX_LOCKED_VAL = COAL_BLOCK, + LAST_REGION_BLOCK, // used to mark last block in region + // values after this are "normal" block sizes + MAX_SPEC_VAL = LAST_REGION_BLOCK + }; + + void initLocked() { value = LOCKED; } + void makeCoalscing() { + MALLOC_ASSERT(value == LOCKED, ASSERT_TEXT); + value = COAL_BLOCK; + } + size_t tryLock(State state) { + size_t szVal, sz; + MALLOC_ASSERT(state <= MAX_LOCKED_VAL, ASSERT_TEXT); + for (;;) { + sz = FencedLoad((intptr_t&)value); + if (sz <= MAX_LOCKED_VAL) + break; + szVal = AtomicCompareExchange((intptr_t&)value, state, sz); + + if (szVal==sz) + break; + } + return sz; + } + void unlock(size_t size) { + MALLOC_ASSERT(value <= MAX_LOCKED_VAL, "The lock is not locked"); + MALLOC_ASSERT(size > MAX_LOCKED_VAL, ASSERT_TEXT); + FencedStore((intptr_t&)value, size); + } + friend void Backend::IndexedBins::verify(); +}; + +struct MemRegion { + MemRegion *next, // keep all regions in any pool to release all them on + *prev; // pool destroying, 2-linked list to release individual + // regions. + size_t allocSz, // got from poll callback + blockSz; // initial and maximal inner block size + bool exact; // region tageted to exact large object allocation +}; + +// this data must be unmodified while block is in use, so separate it +class BlockMutexes { +protected: + GuardedSize myL, // lock for me + leftL; // lock for left neighbor +}; + +class FreeBlock : BlockMutexes { +public: + static const size_t minBlockSize; + friend void Backend::IndexedBins::verify(); + + FreeBlock *prev, // in 2-linked list related to bin + *next, + *nextToFree; // used to form a queue during coalescing + // valid only when block is in processing, i.e. one is not free and not + size_t sizeTmp; // used outside of backend + int myBin; // bin that is owner of the block + bool aligned; + bool blockInBin; // this block in myBin already + + FreeBlock *rightNeig(size_t sz) const { + MALLOC_ASSERT(sz, ASSERT_TEXT); + return (FreeBlock*)((uintptr_t)this+sz); + } + FreeBlock *leftNeig(size_t sz) const { + MALLOC_ASSERT(sz, ASSERT_TEXT); + return (FreeBlock*)((uintptr_t)this - sz); + } + + void initHeader() { myL.initLocked(); leftL.initLocked(); } + void setMeFree(size_t size) { myL.unlock(size); } + size_t trySetMeUsed(GuardedSize::State s) { return myL.tryLock(s); } + + void setLeftFree(size_t sz) { leftL.unlock(sz); } + size_t trySetLeftUsed(GuardedSize::State s) { return leftL.tryLock(s); } + + size_t tryLockBlock() { + size_t rSz, sz = trySetMeUsed(GuardedSize::LOCKED); + + if (sz <= GuardedSize::MAX_LOCKED_VAL) + return false; + rSz = rightNeig(sz)->trySetLeftUsed(GuardedSize::LOCKED); + if (rSz <= GuardedSize::MAX_LOCKED_VAL) { + setMeFree(sz); + return false; + } + MALLOC_ASSERT(rSz == sz, ASSERT_TEXT); + return sz; + } + void markCoalescing(size_t blockSz) { + myL.makeCoalscing(); + rightNeig(blockSz)->leftL.makeCoalscing(); + sizeTmp = blockSz; + nextToFree = NULL; + } + void markUsed() { + myL.initLocked(); + rightNeig(sizeTmp)->leftL.initLocked(); + nextToFree = NULL; + } + static void markBlocks(FreeBlock *fBlock, int num, size_t size) { + for (int i=1; i<num; i++) { + fBlock = (FreeBlock*)((uintptr_t)fBlock + size); + fBlock->initHeader(); + } + } +}; + +// Last block in any region. Its "size" field is GuardedSize::LAST_REGION_BLOCK, +// This kind of blocks used to find region header +// and have a possibility to return region back to OS +struct LastFreeBlock : public FreeBlock { + MemRegion *memRegion; +}; + +const size_t FreeBlock::minBlockSize = sizeof(FreeBlock); + +void CoalRequestQ::putBlock(FreeBlock *fBlock) +{ + MALLOC_ASSERT(fBlock->sizeTmp >= FreeBlock::minBlockSize, ASSERT_TEXT); + fBlock->markUsed(); + + for (;;) { + FreeBlock *myBlToFree = (FreeBlock*)FencedLoad((intptr_t&)blocksToFree); + + fBlock->nextToFree = myBlToFree; + if (myBlToFree == + (FreeBlock*)AtomicCompareExchange((intptr_t&)blocksToFree, + (intptr_t)fBlock, + (intptr_t)myBlToFree)) + return; + } +} + +FreeBlock *CoalRequestQ::getAll() +{ + for (;;) { + FreeBlock *myBlToFree = (FreeBlock*)FencedLoad((intptr_t&)blocksToFree); + + if (!myBlToFree) + return NULL; + else { + if (myBlToFree == + (FreeBlock*)AtomicCompareExchange((intptr_t&)blocksToFree, + 0, (intptr_t)myBlToFree)) + return myBlToFree; + else + continue; + } + } +} + +// try to remove block from bin; if split result stay in the bin, not remove it +// but split the block +// alignedBin, if the bin is 16KB-aligned right side. +FreeBlock *Backend::IndexedBins::getBlock(int binIdx, BackendSync *sync, + size_t size, bool res16Kaligned, bool alignedBin, bool wait, + int *binLocked) +{ + Bin *b = &freeBins[binIdx]; +try_next: + FreeBlock *fBlock = NULL; + if (b->head) { + bool locked; + MallocMutex::scoped_lock scopedLock(b->tLock, wait, &locked); + + if (!locked) { + if (binLocked) (*binLocked)++; + return NULL; + } + + for (FreeBlock *curr = b->head; curr; curr = curr->next) { + size_t szBlock = curr->tryLockBlock(); + if (!szBlock) { + goto try_next; + } + + if (alignedBin || !res16Kaligned) { + size_t splitSz = szBlock - size; + // If we got a block as split result, + // it must have a room for control structures. + if (szBlock >= size && (splitSz >= FreeBlock::minBlockSize || + !splitSz)) + fBlock = curr; + } else { + void *newB = alignUp(curr, blockSize); + uintptr_t rightNew = (uintptr_t)newB + size; + uintptr_t rightCurr = (uintptr_t)curr + szBlock; + // appropriate size, and left and right split results + // are either big enough or non-exitent + if (rightNew <= rightCurr + && (newB==curr || + (uintptr_t)newB-(uintptr_t)curr >= FreeBlock::minBlockSize) + && (rightNew==rightCurr || + rightCurr - rightNew >= FreeBlock::minBlockSize)) + fBlock = curr; + } + if (fBlock) { + // consume must be called before result of removing from a bin + // is visible externally. + sync->consume(); + if (alignedBin && res16Kaligned && + Backend::sizeToBin(szBlock-size) == Backend::sizeToBin(szBlock)) { + // free remainder of fBlock stay in same bin, + // so no need to remove it from the bin + // TODO: add more "still here" cases + FreeBlock *newFBlock = fBlock; + // return block from right side of fBlock + fBlock = (FreeBlock*)((uintptr_t)newFBlock + szBlock - size); + MALLOC_ASSERT(isAligned(fBlock, blockSize), "Invalid free block"); + fBlock->initHeader(); + fBlock->setLeftFree(szBlock - size); + newFBlock->setMeFree(szBlock - size); + + fBlock->sizeTmp = size; + } else { + b->removeBlock(fBlock); + if (freeBins[binIdx].empty()) + bitMask.set(binIdx, false); + fBlock->sizeTmp = szBlock; + } + break; + } else { // block size is not valid, search for next block in the bin + curr->setMeFree(szBlock); + curr->rightNeig(szBlock)->setLeftFree(szBlock); + } + } + } + return fBlock; +} + +void Backend::Bin::removeBlock(FreeBlock *fBlock) +{ + if (head == fBlock) + head = fBlock->next; + if (tail == fBlock) + tail = fBlock->prev; + if (fBlock->prev) + fBlock->prev->next = fBlock->next; + if (fBlock->next) + fBlock->next->prev = fBlock->prev; +} + +void Backend::IndexedBins::addBlock(int binIdx, FreeBlock *fBlock, size_t blockSz) +{ + Bin *b = &freeBins[binIdx]; + + fBlock->myBin = binIdx; + fBlock->aligned = toAlignedBin(fBlock, blockSz); + fBlock->prev = NULL; + { + MallocMutex::scoped_lock scopedLock(b->tLock); + fBlock->next = b->head; + b->head = fBlock; + if (fBlock->next) + fBlock->next->prev = fBlock; + if (!b->tail) + b->tail = fBlock; + } + bitMask.set(binIdx, true); +} + +bool Backend::IndexedBins::tryAddBlock(int binIdx, FreeBlock *fBlock, bool addToTail) +{ + bool locked; + Bin *b = &freeBins[binIdx]; + + fBlock->myBin = binIdx; + fBlock->aligned = toAlignedBin(fBlock, fBlock->sizeTmp); + if (addToTail) { + fBlock->next = NULL; + { + MallocMutex::scoped_lock scopedLock(b->tLock, /*wait=*/false, &locked); + if (!locked) + return false; + fBlock->prev = b->tail; + b->tail = fBlock; + if (fBlock->prev) + fBlock->prev->next = fBlock; + if (!b->head) + b->head = fBlock; + } + } else { + fBlock->prev = NULL; + { + MallocMutex::scoped_lock scopedLock(b->tLock, /*wait=*/false, &locked); + if (!locked) + return false; + fBlock->next = b->head; + b->head = fBlock; + if (fBlock->next) + fBlock->next->prev = fBlock; + if (!b->tail) + b->tail = fBlock; + } + } + bitMask.set(binIdx, true); + return true; +} + +void Backend::IndexedBins::reset() +{ + for (int i=0; i<Backend::freeBinsNum; i++) + freeBins[i].reset(); + bitMask.reset(); +} + +void Backend::IndexedBins::lockRemoveBlock(int binIdx, FreeBlock *fBlock) +{ + MallocMutex::scoped_lock scopedLock(freeBins[binIdx].tLock); + freeBins[binIdx].removeBlock(fBlock); + if (freeBins[binIdx].empty()) + bitMask.set(binIdx, false); +} + +bool ExtMemoryPool::regionsAreReleaseable() const +{ + return !keepAllMemory && !delayRegsReleasing; +} + +// try to allocate num blocks of size Bytes from particular "generic" bin +// res16Kaligned is true if result must be 16KB alined +FreeBlock *Backend::getFromBin(int binIdx, int num, size_t size, bool res16Kaligned, + int *binLocked) +{ + FreeBlock *fBlock = + freeLargeBins.getBlock(binIdx, &bkndSync, num*size, res16Kaligned, + /*alignedBin=*/false, /*wait=*/false, binLocked); + if (fBlock) { + if (res16Kaligned) { + size_t fBlockSz = fBlock->sizeTmp; + uintptr_t fBlockEnd = (uintptr_t)fBlock + fBlockSz; + FreeBlock *newB = alignUp(fBlock, blockSize); + FreeBlock *rightPart = (FreeBlock*)((uintptr_t)newB + num*size); + + // Space to use is in the middle, + // ... return free right part + if ((uintptr_t)rightPart != fBlockEnd) { + rightPart->initHeader(); // to prevent coalescing rightPart with fBlock + coalescAndPut(rightPart, fBlockEnd - (uintptr_t)rightPart); + } + // ... and free left part + if (newB != fBlock) { + newB->initHeader(); // to prevent coalescing fBlock with newB + coalescAndPut(fBlock, (uintptr_t)newB - (uintptr_t)fBlock); + } + + fBlock = newB; + MALLOC_ASSERT(isAligned(fBlock, blockSize), ASSERT_TEXT); + } else { + if (size_t splitSz = fBlock->sizeTmp - num*size) { + // split block and return free right part + FreeBlock *splitB = (FreeBlock*)((uintptr_t)fBlock + num*size); + splitB->initHeader(); + coalescAndPut(splitB, splitSz); + } + } + bkndSync.signal(); + FreeBlock::markBlocks(fBlock, num, size); + } + + return fBlock; +} + +// try to allocate size Byte block from any of 16KB-alined spaces. +// res16Kaligned is true if result must be 16KN alined +FreeBlock *Backend::getFromAlignedSpace(int binIdx, int num, size_t size, + bool res16Kaligned, bool wait, int *binLocked) +{ + FreeBlock *fBlock = + freeAlignedBins.getBlock(binIdx, &bkndSync, num*size, res16Kaligned, + /*alignedBin=*/true, wait, binLocked); + + if (fBlock) { + if (fBlock->sizeTmp != num*size) { // i.e., need to split the block + FreeBlock *newAlgnd; + size_t newSz; + + if (res16Kaligned) { + newAlgnd = fBlock; + fBlock = (FreeBlock*)((uintptr_t)newAlgnd + newAlgnd->sizeTmp + - num*size); + MALLOC_ASSERT(isAligned(fBlock, blockSize), "Invalid free block"); + fBlock->initHeader(); + newSz = newAlgnd->sizeTmp - num*size; + } else { + newAlgnd = (FreeBlock*)((uintptr_t)fBlock + num*size); + newSz = fBlock->sizeTmp - num*size; + newAlgnd->initHeader(); + } + coalescAndPut(newAlgnd, newSz); + } + bkndSync.signal(); + MALLOC_ASSERT(!res16Kaligned || isAligned(fBlock, blockSize), ASSERT_TEXT); + FreeBlock::markBlocks(fBlock, num, size); + } + return fBlock; +} + +void Backend::correctMaxRequestSize(size_t requestSize) +{ + if (requestSize < maxBinedSize) { + for (size_t oldMax = FencedLoad((intptr_t&)maxRequestedSize); + requestSize > oldMax; ) { + size_t val = AtomicCompareExchange((intptr_t&)maxRequestedSize, + requestSize, oldMax); + if (val == oldMax) + break; + oldMax = val; + } + } +} + +// try to allocate size Byte block in available bins +// res16Kaligned is true if result must be 16KB aligned +FreeBlock *Backend::genericGetBlock(int num, size_t size, bool res16Kaligned) +{ + // after (soft|hard)CachesCleanup we can get memory in large bins, + // while after addNewRegion only in ALGN_SPACE_BIN. This flag + // is for large bins update status. + bool largeBinsUpdated = true; + FreeBlock *block = NULL; + const size_t totalReqSize = num*size; + const int nativeBin = sizeToBin(totalReqSize); + // If we found 2 or less locked bins, it's time to ask more memory from OS. + // But nothing can be asked from fixed pool. + int lockedBinsThreshold = extMemPool->fixedPool || size>=maxBinedSize? 0 : 2; + + correctMaxRequestSize(totalReqSize); + scanCoalescQ(/*forceCoalescQDrop=*/false); + + for (;;) { + const intptr_t startModifiedCnt = bkndSync.getNumOfMods(); + int numOfLockedBins; + + for (;;) { + numOfLockedBins = 0; + + // TODO: try different bin search order + if (res16Kaligned) { + if (!block) + for ( int i=freeAlignedBins.getMinNonemptyBin(nativeBin); + i<freeBinsNum; i=freeAlignedBins.getMinNonemptyBin(i+1) ){ + block = getFromAlignedSpace(i, num, size, /*res16Kaligned=*/true, /*wait=*/false, &numOfLockedBins); + if (block) break; + } + if (!block && largeBinsUpdated) + for ( int i=freeLargeBins.getMinNonemptyBin(nativeBin); + i<freeBinsNum; i=freeLargeBins.getMinNonemptyBin(i+1) ){ + block = getFromBin(i, num, size, /*res16Kaligned=*/true, &numOfLockedBins); + if (block) break; + } + } else { + if (!block && largeBinsUpdated) + for ( int i=freeLargeBins.getMinNonemptyBin(nativeBin); + i<freeBinsNum; i=freeLargeBins.getMinNonemptyBin(i+1) ){ + block = getFromBin(i, num, size, /*res16Kaligned=*/false, &numOfLockedBins); + if (block) break; + } + if (!block) + for ( int i=freeAlignedBins.getMinNonemptyBin(nativeBin); + i<freeBinsNum; i=freeAlignedBins.getMinNonemptyBin(i+1) ){ + block = getFromAlignedSpace(i, num, size, /*res16Kaligned=*/false, /*wait=*/false, &numOfLockedBins); + if (block) break; + } + } + if (block || numOfLockedBins<=lockedBinsThreshold) + break; + } + if (block) + break; + + largeBinsUpdated = scanCoalescQ(/*forceCoalescQDrop=*/true); + largeBinsUpdated = extMemPool->softCachesCleanup() || largeBinsUpdated; + if (!largeBinsUpdated) { + size_t maxBinSize = 0; + + // Another thread is modifying backend while we can't get the block. + // Wait while it leaves and re-do the scan + // before trying other ways to extend the backend. + if (bkndSync.waitTillSignalled(startModifiedCnt) + // semaphore is protecting adding more more memory from OS + || memExtendingSema.wait()) + continue; + + if (startModifiedCnt != bkndSync.getNumOfMods()) { + memExtendingSema.signal(); + continue; + } + + // To keep objects below maxBinedSize, region must be larger then that. + // So trying to balance between too small regions (that leads to + // fragmentation) and too large ones (that leads to excessive address + // space consumption). If region is "quite large", allocate only one, + // to prevent fragmentation. It supposely doesn't hurt perfromance, + // because the object requested by user is large. + const size_t regSz_sizeBased = size>=maxBinedSize? + size : + alignUp(4*FencedLoad((intptr_t&)maxRequestedSize), 1024*1024); + if (size == blockSize || regSz_sizeBased < maxBinedSize) { + for (unsigned idx=0; idx<4; idx++) { + size_t binSize = addNewRegion(maxBinedSize, /*exact=*/false); + if (!binSize) + break; + if (binSize > maxBinSize) + maxBinSize = binSize; + } + } else { + largeBinsUpdated = true; + maxBinSize = addNewRegion(regSz_sizeBased, /*exact=*/true); + } + memExtendingSema.signal(); + + // size can be >= maxBinedSize, when getRawMem failed + // for this allocation, and allocation in bins + // is our last chance to fulfil the request. + // Sadly, size is larger then max bin, so have to give up. + if (maxBinSize && maxBinSize < size) + return NULL; + + if (!maxBinSize) { // no regions have been added, try to clean cache + if (extMemPool->hardCachesCleanup()) + largeBinsUpdated = true; + else { + if (bkndSync.waitTillSignalled(startModifiedCnt)) + continue; + // OS can't give us more memory, but we have some in locked bins + if (lockedBinsThreshold && numOfLockedBins) { + lockedBinsThreshold = 0; + continue; + } + return NULL; + } + } + } + } + return block; +} + +LargeMemoryBlock *Backend::getLargeBlock(size_t size) +{ + LargeMemoryBlock *lmb = + (LargeMemoryBlock*)genericGetBlock(1, size, /*res16Kaligned=*/false); + if (lmb) { + lmb->unalignedSize = size; + if (extMemPool->mustBeAddedToGlobalLargeBlockList()) + extMemPool->lmbList.add(lmb); + } + return lmb; +} + +void *Backend::getBackRefSpace(size_t size, bool *rawMemUsed) +{ + // This block is released only at shutdown, so it can prevent + // a entire region releasing when it's received from the backend, + // so prefer getRawMemory using. + if (void *ret = getRawMemory(size, /*hugePages=*/false)) { + *rawMemUsed = true; + return ret; + } + void *ret = genericGetBlock(1, size, /*res16Kaligned=*/false); + if (ret) *rawMemUsed = false; + return ret; +} + +void Backend::putBackRefSpace(void *b, size_t size, bool rawMemUsed) +{ + if (rawMemUsed) + freeRawMemory(b, size); + // ignore not raw mem, as it released on region releasing +} + +void Backend::removeBlockFromBin(FreeBlock *fBlock) +{ + if (fBlock->myBin != Backend::NO_BIN) + if (fBlock->aligned) + freeAlignedBins.lockRemoveBlock(fBlock->myBin, fBlock); + else + freeLargeBins.lockRemoveBlock(fBlock->myBin, fBlock); +} + +void Backend::genericPutBlock(FreeBlock *fBlock, size_t blockSz) +{ + bkndSync.consume(); + coalescAndPut(fBlock, blockSz); + bkndSync.signal(); +} + +void AllLargeBlocksList::add(LargeMemoryBlock *lmb) +{ + MallocMutex::scoped_lock scoped_cs(largeObjLock); + lmb->gPrev = NULL; + lmb->gNext = loHead; + if (lmb->gNext) + lmb->gNext->gPrev = lmb; + loHead = lmb; +} + +void AllLargeBlocksList::remove(LargeMemoryBlock *lmb) +{ + MallocMutex::scoped_lock scoped_cs(largeObjLock); + if (loHead == lmb) + loHead = lmb->gNext; + if (lmb->gNext) + lmb->gNext->gPrev = lmb->gPrev; + if (lmb->gPrev) + lmb->gPrev->gNext = lmb->gNext; +} + +void AllLargeBlocksList::removeAll(Backend *backend) +{ + LargeMemoryBlock *next, *lmb = loHead; + loHead = NULL; + + for (; lmb; lmb = next) { + next = lmb->gNext; + // nothing left to AllLargeBlocksList::remove + lmb->gNext = lmb->gPrev = NULL; + removeBackRef(lmb->backRefIdx); + backend->putLargeBlock(lmb); + } +} + +void Backend::putLargeBlock(LargeMemoryBlock *lmb) +{ + if (extMemPool->mustBeAddedToGlobalLargeBlockList()) + extMemPool->lmbList.remove(lmb); + genericPutBlock((FreeBlock *)lmb, lmb->unalignedSize); +} + +void Backend::releaseRegion(MemRegion *memRegion) +{ + { + MallocMutex::scoped_lock lock(regionListLock); + if (regionList == memRegion) + regionList = memRegion->next; + if (memRegion->next) + memRegion->next->prev = memRegion->prev; + if (memRegion->prev) + memRegion->prev->next = memRegion->next; + } + freeRawMem(memRegion, memRegion->allocSz); +} + +// coalesce fBlock with its neighborhood +FreeBlock *Backend::doCoalesc(FreeBlock *fBlock, MemRegion **mRegion) +{ + FreeBlock *resBlock = fBlock; + size_t resSize = fBlock->sizeTmp; + MemRegion *memRegion = NULL; + + fBlock->markCoalescing(resSize); + resBlock->blockInBin = false; + + // coalesing with left neighbor + size_t leftSz = fBlock->trySetLeftUsed(GuardedSize::COAL_BLOCK); + if (leftSz != GuardedSize::LOCKED) { + if (leftSz == GuardedSize::COAL_BLOCK) { + coalescQ.putBlock(fBlock); + return NULL; + } else { + FreeBlock *left = fBlock->leftNeig(leftSz); + size_t lSz = left->trySetMeUsed(GuardedSize::COAL_BLOCK); + if (lSz <= GuardedSize::MAX_LOCKED_VAL) { + fBlock->setLeftFree(leftSz); // rollback + coalescQ.putBlock(fBlock); + return NULL; + } else { + MALLOC_ASSERT(lSz == leftSz, "Invalid header"); + left->blockInBin = true; + resBlock = left; + resSize += leftSz; + resBlock->sizeTmp = resSize; + } + } + } + // coalesing with right neighbor + FreeBlock *right = fBlock->rightNeig(fBlock->sizeTmp); + size_t rightSz = right->trySetMeUsed(GuardedSize::COAL_BLOCK); + if (rightSz != GuardedSize::LOCKED) { + // LastFreeBlock is on the right side + if (GuardedSize::LAST_REGION_BLOCK == rightSz) { + right->setMeFree(GuardedSize::LAST_REGION_BLOCK); + memRegion = static_cast<LastFreeBlock*>(right)->memRegion; + } else if (GuardedSize::COAL_BLOCK == rightSz) { + if (resBlock->blockInBin) { + resBlock->blockInBin = false; + removeBlockFromBin(resBlock); + } + coalescQ.putBlock(resBlock); + return NULL; + } else { + size_t rSz = right->rightNeig(rightSz)-> + trySetLeftUsed(GuardedSize::COAL_BLOCK); + if (rSz <= GuardedSize::MAX_LOCKED_VAL) { + right->setMeFree(rightSz); // rollback + if (resBlock->blockInBin) { + resBlock->blockInBin = false; + removeBlockFromBin(resBlock); + } + coalescQ.putBlock(resBlock); + return NULL; + } else { + MALLOC_ASSERT(rSz == rightSz, "Invalid header"); + removeBlockFromBin(right); + resSize += rightSz; + + // Is LastFreeBlock on the right side of right? + FreeBlock *nextRight = right->rightNeig(rightSz); + size_t nextRightSz = nextRight-> + trySetMeUsed(GuardedSize::COAL_BLOCK); + if (nextRightSz > GuardedSize::MAX_LOCKED_VAL) { + if (nextRightSz == GuardedSize::LAST_REGION_BLOCK) + memRegion = static_cast<LastFreeBlock*>(nextRight)->memRegion; + + nextRight->setMeFree(nextRightSz); + } + } + } + } + if (memRegion) { + MALLOC_ASSERT((uintptr_t)memRegion + memRegion->allocSz >= + (uintptr_t)right + sizeof(LastFreeBlock), ASSERT_TEXT); + MALLOC_ASSERT((uintptr_t)memRegion < (uintptr_t)resBlock, ASSERT_TEXT); + *mRegion = memRegion; + } else + *mRegion = NULL; + resBlock->sizeTmp = resSize; + return resBlock; +} + +void Backend::coalescAndPutList(FreeBlock *list, bool forceCoalescQDrop, bool doStat) +{ + FreeBlock *helper; + MemRegion *memRegion; + int alignedSpaceIdx = -1; + + for (;list; list = helper) { + bool addToTail = false; + helper = list->nextToFree; + FreeBlock *toRet = doCoalesc(list, &memRegion); + if (!toRet) + continue; + + if (memRegion && memRegion->blockSz == toRet->sizeTmp + && !extMemPool->fixedPool) { + if (extMemPool->regionsAreReleaseable()) { + // release the region, because there is no used blocks in it + if (toRet->blockInBin) + removeBlockFromBin(toRet); + releaseRegion(memRegion); + continue; + } else // add block from empty region to end of bin, + addToTail = true; // preserving for exact fit + } + size_t currSz = toRet->sizeTmp; + int bin = sizeToBin(currSz); + bool toAligned = toAlignedBin(toRet, currSz); + bool needAddToBin = true; + + if (toRet->blockInBin) { + // is it stay in same bin? + if (toRet->myBin == bin && toRet->aligned == toAligned) + needAddToBin = false; + else { + toRet->blockInBin = false; + removeBlockFromBin(toRet); + } + } + + // not stay in same bin, or bin-less, add it + if (needAddToBin) { + toRet->prev = toRet->next = toRet->nextToFree = NULL; + toRet->myBin = NO_BIN; + + // If the block is too small to fit in any bin, keep it bin-less. + // It's not a leak because the block later can be coalesced. + if (currSz >= minBinedSize) { + toRet->sizeTmp = currSz; + if (!(toAligned? + freeAlignedBins.tryAddBlock(bin, toRet, addToTail) : + freeLargeBins.tryAddBlock(bin, toRet, addToTail))) { + coalescQ.putBlock(toRet); + continue; + } + } + toRet->sizeTmp = 0; + } + // Free (possibly coalesced) free block. + // Adding to bin must be done before this point, + // because after a block is free it can be coalesced, and + // using its pointer became unsafe. + // Remember that coalescing is not done under any global lock. + toRet->setMeFree(currSz); + toRet->rightNeig(currSz)->setLeftFree(currSz); + } +} + +// Coalesce fBlock and add it back to a bin; +// processing delayed coalescing requests. +void Backend::coalescAndPut(FreeBlock *fBlock, size_t blockSz) +{ + fBlock->sizeTmp = blockSz; + fBlock->nextToFree = NULL; + + coalescAndPutList(fBlock, /*forceCoalescQDrop=*/false, /*doStat=*/false); +} + +bool Backend::scanCoalescQ(bool forceCoalescQDrop) +{ + FreeBlock *currCoalescList = coalescQ.getAll(); + + if (currCoalescList) + coalescAndPutList(currCoalescList, forceCoalescQDrop, /*doStat=*/true); + return currCoalescList; +} + +FreeBlock *Backend::findBlockInRegion(MemRegion *region) +{ + FreeBlock *fBlock; + size_t blockSz; + uintptr_t fBlockEnd, + lastFreeBlock = (uintptr_t)region + region->allocSz - sizeof(LastFreeBlock); + + if (region->exact) { + fBlock = (FreeBlock *)alignUp((uintptr_t)region + sizeof(MemRegion), + largeObjectAlignment); + fBlockEnd = lastFreeBlock; + } else { // right bound is 16KB-aligned, keep LastFreeBlock after it + fBlock = (FreeBlock *)((uintptr_t)region + sizeof(MemRegion)); + fBlockEnd = alignDown(lastFreeBlock, blockSize); + } + if (fBlockEnd <= (uintptr_t)fBlock) + return NULL; // allocSz is too small + blockSz = fBlockEnd - (uintptr_t)fBlock; + // TODO: extend get16KBlock to support degradation, i.e. getting less blocks + // then requested, and then relax this check + // (now all or nothing is implemented, check according to this) + if (blockSz < numOfBlocksAllocOnMiss*blockSize) + return NULL; + + region->blockSz = blockSz; + return fBlock; +} + +// startUseBlock adds free block to a bin, the block can be used and +// even released after this, so the region must be added to regionList already +void Backend::startUseBlock(MemRegion *region, FreeBlock *fBlock) +{ + size_t blockSz = region->blockSz; + fBlock->initHeader(); + fBlock->setMeFree(blockSz); + + LastFreeBlock *lastBl = static_cast<LastFreeBlock*>(fBlock->rightNeig(blockSz)); + lastBl->initHeader(); + lastBl->setMeFree(GuardedSize::LAST_REGION_BLOCK); + lastBl->setLeftFree(blockSz); + lastBl->myBin = NO_BIN; + lastBl->memRegion = region; + + unsigned targetBin = sizeToBin(blockSz); + if (!region->exact && toAlignedBin(fBlock, blockSz)) { + freeAlignedBins.addBlock(targetBin, fBlock, blockSz); + } else { + freeLargeBins.addBlock(targetBin, fBlock, blockSz); + } +} + +size_t Backend::addNewRegion(size_t rawSize, bool exact) +{ + // to guarantee that header is not overwritten in used blocks + MALLOC_ASSERT(sizeof(BlockMutexes) <= sizeof(BlockI), ASSERT_TEXT); + // to guarantee that block length is not conflicting with + // special values of GuardedSize + MALLOC_ASSERT(FreeBlock::minBlockSize > GuardedSize::MAX_SPEC_VAL, ASSERT_TEXT); + // "exact" means that not less than rawSize for block inside the region. + // Reserve space for region header, worst case alignment + // and last block mark. + if (exact) + rawSize += sizeof(MemRegion) + largeObjectAlignment + + FreeBlock::minBlockSize + sizeof(LastFreeBlock); + + MemRegion *region = (MemRegion*)getRawMem(rawSize); + if (!region) return 0; + if (rawSize < sizeof(MemRegion)) { + if (!extMemPool->fixedPool) + freeRawMem(region, rawSize); + return 0; + } + + region->exact = exact; + region->allocSz = rawSize; + FreeBlock *fBlock = findBlockInRegion(region); + if (!fBlock) { + if (!extMemPool->fixedPool) + freeRawMem(region, rawSize); + return 0; + } + // adding to global list of all regions + { + region->prev = NULL; + MallocMutex::scoped_lock lock(regionListLock); + region->next = regionList; + regionList = region; + if (regionList->next) + regionList->next->prev = regionList; + } + // copy it here, as just after starting to use region it might be released + size_t blockSz = region->blockSz; + + startUseBlock(region, fBlock); + bkndSync.pureSignal(); + return blockSz; +} + +void Backend::reset() +{ + MemRegion *curr; + + MALLOC_ASSERT(extMemPool->userPool(), "Only user pool can be reset."); + // no active threads are allowed in backend while reset() called + verify(); + + freeLargeBins.reset(); + freeAlignedBins.reset(); + + for (curr = regionList; curr; curr = curr->next) { + FreeBlock *fBlock = findBlockInRegion(curr); + MALLOC_ASSERT(fBlock, "A memory region unexpectedly got smaller"); + startUseBlock(curr, fBlock); + } +} + +bool Backend::destroy() +{ + // no active threads are allowed in backend while destroy() called + verify(); + while (regionList) { + MemRegion *helper = regionList->next; + if (inUserPool()) + (*extMemPool->rawFree)(extMemPool->poolId, regionList, + regionList->allocSz); + else { + freeRawMemory(regionList, regionList->allocSz); + } + regionList = helper; + } + return true; +} + +void Backend::IndexedBins::verify() +{ + for (int i=0; i<freeBinsNum; i++) { + for (FreeBlock *fb = freeBins[i].head; fb; fb=fb->next) { + uintptr_t mySz = fb->myL.value; + MALLOC_ASSERT(mySz>GuardedSize::MAX_SPEC_VAL, ASSERT_TEXT); + FreeBlock *right = (FreeBlock*)((uintptr_t)fb + mySz); + MALLOC_ASSERT(right->myL.value<=GuardedSize::MAX_SPEC_VAL, ASSERT_TEXT); + MALLOC_ASSERT(right->leftL.value==mySz, ASSERT_TEXT); + MALLOC_ASSERT(fb->leftL.value<=GuardedSize::MAX_SPEC_VAL, ASSERT_TEXT); + } + } +} + +// For correct operation, it must be called when no other threads +// is changing backend. +void Backend::verify() +{ +#if MALLOC_DEBUG + scanCoalescQ(/*forceCoalescQDrop=*/false); + + freeLargeBins.verify(); + freeAlignedBins.verify(); +#endif // MALLOC_DEBUG +} + +#if _TBBMALLOC_BACKEND_LOG +size_t Backend::Bin::countFreeBlocks() +{ + size_t cnt = 0; + { + MallocMutex::scoped_lock lock(tLock); + for (FreeBlock *fb = head; fb; fb = fb->next) + cnt++; + } + return cnt; +} + +void Backend::IndexedBins::reportStat(FILE *f) +{ + for (int i=0; i<Backend::freeBinsNum; i++) + if (size_t cnt = freeBins[i].countFreeBlocks()) + fprintf(f, "%d:%lu ", i, cnt); +} + +void Backend::reportStat(FILE *f) +{ + int regNum = 0; + + scanCoalescQ(/*forceCoalescQDrop=*/false); + + { + MallocMutex::scoped_lock lock(regionListLock); + for (MemRegion *curr = regionList; curr; curr = curr->next) + regNum++; + } + fprintf(f, "%d regions\nlarge ", regNum); + freeLargeBins.reportStat(f); + fprintf(f, "\naligned "); + freeAlignedBins.reportStat(f); + fprintf(f, "\n"); +} +#endif // _TBBMALLOC_BACKEND_LOG + +} } // namespaces diff --git a/src/tbb/src/tbbmalloc/backref.cpp b/src/tbb/src/tbbmalloc/backref.cpp new file mode 100644 index 0000000..1973f02 --- /dev/null +++ b/src/tbb/src/tbbmalloc/backref.cpp @@ -0,0 +1,292 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include <string.h> +#include <new> /* for placement new */ +#include "tbbmalloc_internal.h" + +namespace rml { +namespace internal { + + +/********* backreferences ***********************/ +/* Each 16KB block and each large memory object header contains BackRefIdx + * that points out in some BackRefBlock which points back to this block or header. + */ +struct BackRefBlock : public BlockI { + BackRefBlock *nextForUse; // the next in the chain of blocks with free items + FreeObject *bumpPtr; // bump pointer moves from the end to the beginning of the block + FreeObject *freeList; + // list of all blocks that were allocated from raw mem (i.e., not from backend) + BackRefBlock *nextRawMemBlock; + int allocatedCount; // the number of objects allocated + int myNum; // the index in the parent array + MallocMutex blockMutex; + bool addedToForUse; // this block is already added to the listForUse chain + + BackRefBlock(BackRefBlock *blockToUse, int num) : + nextForUse(NULL), bumpPtr((FreeObject*)((uintptr_t)blockToUse + blockSize - sizeof(void*))), + freeList(NULL), nextRawMemBlock(NULL), allocatedCount(0), myNum(num), + addedToForUse(false) { + memset(&blockMutex, 0, sizeof(MallocMutex)); + // index in BackRefMaster must fit to uint16_t + MALLOC_ASSERT(!(myNum >> 16), ASSERT_TEXT); + } + + // when BackRefMaster::findFreeBlock() calls get16KBlock + // BackRefBlock::bytes is used implicitly + // TODO: take into account VirtualAlloc granularity + static const int bytes = blockSize; +}; + +// max number of backreference pointers in 16KB block +static const int BR_MAX_CNT = (BackRefBlock::bytes-sizeof(BackRefBlock))/sizeof(void*); + +struct BackRefMaster { +/* A 16KB block can hold up to ~2K back pointers to 16KB blocks or large objects, + * so it can address at least 32MB. The array of 64KB holds 8K pointers + * to such blocks, addressing ~256 GB. + */ + static const size_t bytes = 64*1024; + static const int dataSz; +/* space is reserved for master table and 4 leaves + taking into account VirtualAlloc allocation granularity */ + static const int leaves = 4; + static const size_t masterSize = BackRefMaster::bytes+leaves*BackRefBlock::bytes; + + Backend *backend; + BackRefBlock *active; // if defined, use it for allocations + BackRefBlock *listForUse; // the chain of data blocks with free items + BackRefBlock *allRawMemBlocks; + intptr_t lastUsed; // index of the last used block + bool rawMemUsed; + BackRefBlock *backRefBl[1]; // the real size of the array is dataSz + + BackRefBlock *findFreeBlock(); + void addBackRefBlockToList(BackRefBlock *bl); + void addEmptyBackRefBlock(BackRefBlock *newBl); +}; + +const int BackRefMaster::dataSz + = 1+(BackRefMaster::bytes-sizeof(BackRefMaster))/sizeof(BackRefBlock*); + +static MallocMutex backRefMutex; +static BackRefMaster *backRefMaster; + +bool initBackRefMaster(Backend *backend) +{ + bool rawMemUsed; + BackRefMaster *master = + (BackRefMaster*)backend->getBackRefSpace(BackRefMaster::masterSize, + &rawMemUsed); + if (! master) + return false; + master->backend = backend; + master->listForUse = master->allRawMemBlocks = NULL; + master->rawMemUsed = rawMemUsed; + master->lastUsed = -1; + for (int i=0; i<BackRefMaster::leaves; i++) { + BackRefBlock *bl = (BackRefBlock *)((uintptr_t)master + BackRefMaster::bytes + i*BackRefBlock::bytes); + master->addEmptyBackRefBlock(bl); + if (i) + master->addBackRefBlockToList(bl); + else // active leaf is not needed in listForUse + master->active = bl; + } + // backRefMaster is read in getBackRef, so publish it in consistent state + FencedStore((intptr_t&)backRefMaster, (intptr_t)master); + return true; +} + +void destroyBackRefMaster(Backend *backend) +{ + if (backRefMaster) { // Is initBackRefMaster() called? + for (BackRefBlock *curr=backRefMaster->allRawMemBlocks; curr; ) { + BackRefBlock *next = curr->nextRawMemBlock; + // allRawMemBlocks list is only for raw mem blocks + backend->putBackRefSpace(curr, BackRefBlock::bytes, /*rawMemUsed=*/true); + curr = next; + } + backend->putBackRefSpace(backRefMaster, BackRefMaster::masterSize, + backRefMaster->rawMemUsed); + } +} + +void BackRefMaster::addBackRefBlockToList(BackRefBlock *bl) +{ + bl->nextForUse = listForUse; + listForUse = bl; + bl->addedToForUse = true; +} + +void BackRefMaster::addEmptyBackRefBlock(BackRefBlock *newBl) +{ + intptr_t nextLU = lastUsed+1; + memset((char*)newBl+sizeof(BackRefBlock), 0, + BackRefBlock::bytes-sizeof(BackRefBlock)); + new (newBl) BackRefBlock(newBl, nextLU); + backRefBl[nextLU] = newBl; + // lastUsed is read in getBackRef, and access to backRefBl[lastUsed] + // is possible only after checking backref against current lastUsed + FencedStore(lastUsed, nextLU); +} + +BackRefBlock *BackRefMaster::findFreeBlock() +{ + if (active->allocatedCount < BR_MAX_CNT) + return active; + + if (listForUse) { // use released list + active = listForUse; + listForUse = listForUse->nextForUse; + MALLOC_ASSERT(active->addedToForUse, ASSERT_TEXT); + active->addedToForUse = false; + } else if (lastUsed-1 < backRefMaster->dataSz) { // allocate new data node + bool rawMemUsed; + BackRefBlock *newBl = + (BackRefBlock*)backend->getBackRefSpace(BackRefBlock::bytes, &rawMemUsed); + if (!newBl) return NULL; + backRefMaster->addEmptyBackRefBlock(newBl); + if (rawMemUsed) { + newBl->nextRawMemBlock = backRefMaster->allRawMemBlocks; + backRefMaster->allRawMemBlocks = newBl; + } else + newBl->nextRawMemBlock = NULL; + active = newBl; + } else // no free blocks, give up + return NULL; + return active; +} + +void *getBackRef(BackRefIdx backRefIdx) +{ + // !backRefMaster means no initialization done, so it can't be valid memory + // see addEmptyBackRefBlock for fences around lastUsed + if (!FencedLoad((intptr_t&)backRefMaster) + || backRefIdx.getMaster() > FencedLoad(backRefMaster->lastUsed) + || backRefIdx.getOffset() >= BR_MAX_CNT) + return NULL; + return *(void**)((uintptr_t)backRefMaster->backRefBl[backRefIdx.getMaster()] + + sizeof(BackRefBlock)+backRefIdx.getOffset()*sizeof(void*)); +} + +void setBackRef(BackRefIdx backRefIdx, void *newPtr) +{ + MALLOC_ASSERT(backRefIdx.getMaster()<=backRefMaster->lastUsed && backRefIdx.getOffset()<BR_MAX_CNT, + ASSERT_TEXT); + *(void**)((uintptr_t)backRefMaster->backRefBl[backRefIdx.getMaster()] + + sizeof(BackRefBlock) + backRefIdx.getOffset()*sizeof(void*)) = newPtr; +} + +BackRefIdx BackRefIdx::newBackRef(bool largeObj) +{ + BackRefBlock *blockToUse; + void **toUse; + BackRefIdx res; + + do { + { // global lock taken to find a block + MallocMutex::scoped_lock lock(backRefMutex); + + MALLOC_ASSERT(backRefMaster, ASSERT_TEXT); + blockToUse = backRefMaster->findFreeBlock(); + if (!blockToUse) + return BackRefIdx(); + } + toUse = NULL; + { // the block is locked to find a reference + MallocMutex::scoped_lock lock(blockToUse->blockMutex); + + if (blockToUse->freeList) { + toUse = (void**)blockToUse->freeList; + blockToUse->freeList = blockToUse->freeList->next; + MALLOC_ASSERT(!blockToUse->freeList || + ((uintptr_t)blockToUse->freeList>=(uintptr_t)blockToUse + && (uintptr_t)blockToUse->freeList < + (uintptr_t)blockToUse + blockSize), ASSERT_TEXT); + } else if (blockToUse->allocatedCount < BR_MAX_CNT) { + toUse = (void**)blockToUse->bumpPtr; + blockToUse->bumpPtr = + (FreeObject*)((uintptr_t)blockToUse->bumpPtr - sizeof(void*)); + if (blockToUse->allocatedCount == BR_MAX_CNT-1) { + MALLOC_ASSERT((uintptr_t)blockToUse->bumpPtr + < (uintptr_t)blockToUse+sizeof(BackRefBlock), + ASSERT_TEXT); + blockToUse->bumpPtr = NULL; + } + } + if (toUse) + blockToUse->allocatedCount++; + } // end of lock scope + } while (!toUse); + res.master = blockToUse->myNum; + uintptr_t offset = + ((uintptr_t)toUse - ((uintptr_t)blockToUse + sizeof(BackRefBlock)))/sizeof(void*); + // Is offset too big? + MALLOC_ASSERT(!(offset >> 15), ASSERT_TEXT); + res.offset = offset; + if (largeObj) res.largeObj = largeObj; + + return res; +} + +void removeBackRef(BackRefIdx backRefIdx) +{ + MALLOC_ASSERT(!backRefIdx.isInvalid(), ASSERT_TEXT); + MALLOC_ASSERT(backRefIdx.getMaster()<=backRefMaster->lastUsed + && backRefIdx.getOffset()<BR_MAX_CNT, ASSERT_TEXT); + BackRefBlock *currBlock = backRefMaster->backRefBl[backRefIdx.getMaster()]; + FreeObject *freeObj = (FreeObject*)((uintptr_t)currBlock + sizeof(BackRefBlock) + + backRefIdx.getOffset()*sizeof(void*)); + MALLOC_ASSERT(((uintptr_t)freeObj>(uintptr_t)currBlock && + (uintptr_t)freeObj<(uintptr_t)currBlock + blockSize), ASSERT_TEXT); + { + MallocMutex::scoped_lock lock(currBlock->blockMutex); + + freeObj->next = currBlock->freeList; + MALLOC_ASSERT(!freeObj->next || + ((uintptr_t)freeObj->next > (uintptr_t)currBlock + && (uintptr_t)freeObj->next < + (uintptr_t)currBlock + blockSize), ASSERT_TEXT); + currBlock->freeList = freeObj; + currBlock->allocatedCount--; + } + // TODO: do we need double-check here? + if (!currBlock->addedToForUse && currBlock!=backRefMaster->active) { + MallocMutex::scoped_lock lock(backRefMutex); + + if (!currBlock->addedToForUse && currBlock!=backRefMaster->active) + backRefMaster->addBackRefBlockToList(currBlock); + } +} + +/********* End of backreferences ***********************/ + +} // namespace internal +} // namespace rml + diff --git a/src/tbb/src/tbbmalloc/frontend.cpp b/src/tbb/src/tbbmalloc/frontend.cpp new file mode 100644 index 0000000..7002e71 --- /dev/null +++ b/src/tbb/src/tbbmalloc/frontend.cpp @@ -0,0 +1,2645 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + + +#include "tbbmalloc_internal.h" +#include <errno.h> +#include <new> /* for placement new */ +#include <string.h> /* for memset */ + +//! Define the main synchronization method +#define FINE_GRAIN_LOCKS + +#if USE_PTHREAD + #define TlsSetValue_func pthread_setspecific + #define TlsGetValue_func pthread_getspecific + #include <sched.h> + inline void do_yield() {sched_yield();} + #include <dlfcn.h> /* for dlsym */ + extern "C" { static void mallocThreadShutdownNotification(void*); } + +#elif USE_WINTHREAD + #define TlsSetValue_func TlsSetValue + #define TlsGetValue_func TlsGetValue + inline void do_yield() {SwitchToThread();} + +#else + #error Must define USE_PTHREAD or USE_WINTHREAD + +#endif + + +#define FREELIST_NONBLOCKING 1 + +namespace rml { +class MemoryPool; +namespace internal { + +class Block; +class MemoryPool; + +#if MALLOC_CHECK_RECURSION + +inline bool isMallocInitialized(); + +bool RecursiveMallocCallProtector::noRecursion() { + MALLOC_ASSERT(isMallocInitialized(), + "Recursion status can be checked only when initialization was done."); + return !mallocRecursionDetected; +} + +#endif // MALLOC_CHECK_RECURSION + +/* + * Block::objectSize value used to mark blocks allocated by startupAlloc + */ +const uint16_t startupAllocObjSizeMark = ~(uint16_t)0; + +/* + * This number of bins in the TLS that leads to blocks that we can allocate in. + */ +const uint32_t numBlockBinLimit = 31; + +/* + * The following constant is used to define the size of struct Block, the block header. + * The intent is to have the size of a Block multiple of the cache line size, this allows us to + * get good alignment at the cost of some overhead equal to the amount of padding included in the Block. + */ +const int blockHeaderAlignment = estimatedCacheLineSize; + +/********* The data structures and global objects **************/ + +/* + * The malloc routines themselves need to be able to occasionally malloc some space, + * in order to set up the structures used by the thread local structures. This + * routine preforms that fuctions. + */ +class BootStrapBlocks { + MallocMutex bootStrapLock; + Block *bootStrapBlock; + Block *bootStrapBlockUsed; + FreeObject *bootStrapObjectList; +public: + void *allocate(MemoryPool *memPool, size_t size); + void free(void* ptr); + void reset(); +}; + +class ThreadId { + static tls_key_t Tid_key; + static intptr_t ThreadIdCount; + + unsigned int id; +public: + + static void init() { +#if USE_WINTHREAD + Tid_key = TlsAlloc(); +#else + int status = pthread_key_create( &Tid_key, NULL ); + if ( status ) { + fprintf (stderr, "The memory manager cannot create tls key during initialization; exiting \n"); + exit(1); + } +#endif /* USE_WINTHREAD */ + } + static void destroy() { + if( Tid_key ) { +#if USE_WINTHREAD + TlsFree( Tid_key ); +#else + int status = pthread_key_delete( Tid_key ); + if ( status ) { + fprintf (stderr, "The memory manager cannot delete tls key; exiting \n"); + exit(1); + } +#endif /* USE_WINTHREAD */ + Tid_key = 0; + } + } + static ThreadId get() { + ThreadId result; + result.id = reinterpret_cast<intptr_t>(TlsGetValue_func(Tid_key)); + if( !result.id ) { + RecursiveMallocCallProtector scoped; + // Thread-local value is zero -> first call from this thread, + // need to initialize with next ID value (IDs start from 1) + result.id = AtomicIncrement(ThreadIdCount); // returned new value! + TlsSetValue_func( Tid_key, reinterpret_cast<void*>(result.id) ); + } + return result; + } + + bool defined() const { return id; } + void undef() { id = 0; } + void invalid() { id = (unsigned int)-1; } + bool own() const { return id == ThreadId::get().id; } + + friend bool operator==(const ThreadId &id1, const ThreadId &id2); + friend unsigned int getThreadId(); +}; + +tls_key_t ThreadId::Tid_key; +intptr_t ThreadId::ThreadIdCount; + +bool operator==(const ThreadId &id1, const ThreadId &id2) { + return id1.id == id2.id; +} + +unsigned int getThreadId() { return ThreadId::get().id; } + +/*********** Code to provide thread ID and a thread-local void pointer **********/ + +TLSKey::TLSKey() +{ +#if USE_WINTHREAD + TLS_pointer_key = TlsAlloc(); +#else + int status = pthread_key_create( &TLS_pointer_key, mallocThreadShutdownNotification ); + if ( status ) { + fprintf (stderr, "The memory manager cannot create tls key during initialization; exiting \n"); + exit(1); + } +#endif /* USE_WINTHREAD */ +} + +TLSKey::~TLSKey() +{ +#if USE_WINTHREAD + TlsFree(TLS_pointer_key); +#else + int status1 = pthread_key_delete(TLS_pointer_key); + if ( status1 ) { + fprintf (stderr, "The memory manager cannot delete tls key during; exiting \n"); + exit(1); + } +#endif /* USE_WINTHREAD */ +} + +inline TLSData* TLSKey::getThreadMallocTLS() const +{ + return (TLSData *)TlsGetValue_func( TLS_pointer_key ); +} + +inline void TLSKey::setThreadMallocTLS( TLSData * newvalue ) { + RecursiveMallocCallProtector scoped; + TlsSetValue_func( TLS_pointer_key, newvalue ); +} + +/* The 'next' field in the block header has to maintain some invariants: + * it needs to be on a 16K boundary and the first field in the block. + * Any value stored there needs to have the lower 14 bits set to 0 + * so that various assert work. This means that if you want to smash this memory + * for debugging purposes you will need to obey this invariant. + * The total size of the header needs to be a power of 2 to simplify + * the alignment requirements. For now it is a 128 byte structure. + * To avoid false sharing, the fields changed only locally are separated + * from the fields changed by foreign threads. + * Changing the size of the block header would require to change + * some bin allocation sizes, in particular "fitting" sizes (see above). + */ +class Bin; +class StartupBlock; +class TLSData; + +class LifoList { +public: + inline LifoList(); + inline void push(Block *block); + inline Block *pop(); + +private: + Block *top; +#ifdef FINE_GRAIN_LOCKS + MallocMutex lock; +#endif /* FINE_GRAIN_LOCKS */ +}; + +/* + * When a block that is not completely free is returned for reuse by other threads + * this is where the block goes. + * + * LifoList assumes zero initialization; so below its constructors are omitted, + * to avoid linking with C++ libraries on Linux. + */ + +class OrphanedBlocks { + LifoList bins[numBlockBinLimit]; +public: + Block *get(Bin* bin, unsigned int size); + void put(Bin* bin, Block *block); + void reset(); +}; + +class MemoryPool { + // if no explicit grainsize, expect to see malloc in user's pAlloc + // and set reasonable low granularity + static const size_t defaultGranularity = estimatedCacheLineSize; + + MemoryPool(); // deny +public: + static MallocMutex memPoolListLock; + + // list of all active pools is used to release + // all TLS data on thread termination or library unload + MemoryPool *next, + *prev; + ExtMemoryPool extMemPool; + OrphanedBlocks orphanedBlocks; + BootStrapBlocks bootStrapBlocks; + + bool init(intptr_t poolId, const MemPoolPolicy* memPoolPolicy); + static void initDefaultPool(); + void reset(); + void destroy(); + + Bin *getAllocationBin(size_t size); + Block *getEmptyBlock(size_t size); + void returnEmptyBlock(Block *block, bool poolTheBlock); +}; + +static char defaultMemPool_space[sizeof(MemoryPool)]; +static MemoryPool *defaultMemPool = (MemoryPool *)defaultMemPool_space; +const size_t MemoryPool::defaultGranularity; +// zero-initialized +MallocMutex MemoryPool::memPoolListLock; +bool ExtMemoryPool::useHugePages; +size_t ExtMemoryPool::hugePageSize; + +// Block is 16KB-aligned. To prvent false sharing, separate locally-accessed +// fields and fields commonly accessed by not owner threads. +class GlobalBlockFields : public BlockI { +protected: + FreeObject *publicFreeList; + Block *nextPrivatizable; +}; + +class LocalBlockFields : public GlobalBlockFields { +protected: + size_t __pad_local_fields[(blockHeaderAlignment - + sizeof(GlobalBlockFields))/sizeof(size_t)]; + + Block *next; + Block *previous; /* Use double linked list to speed up removal */ + uint16_t objectSize; + ThreadId owner; + FreeObject *bumpPtr; /* Bump pointer moves from the end to the beginning of a block */ + FreeObject *freeList; + BackRefIdx backRefIdx; + unsigned int allocatedCount; /* Number of objects allocated (obviously by the owning thread) */ + bool isFull; + bool orphaned; + + friend void *BootStrapBlocks::allocate(MemoryPool *memPool, size_t size); + friend class FreeBlockPool; + friend class StartupBlock; + friend class LifoList; + friend Block *MemoryPool::getEmptyBlock(size_t size); +}; + +class Block : public LocalBlockFields { + size_t __pad_public_fields[(2*blockHeaderAlignment - + sizeof(LocalBlockFields))/sizeof(size_t)]; +public: + bool empty() const { return allocatedCount==0 && publicFreeList==NULL; } + inline FreeObject* allocate(); + inline FreeObject *allocateFromFreeList(); + inline bool emptyEnoughToUse(); + bool freeListNonNull() { return freeList; } + void freePublicObject(FreeObject *objectToFree); + inline void freeOwnObject(MemoryPool *memPool, FreeObject *objectToFree); + void makeEmpty(); + void privatizePublicFreeList(); + void restoreBumpPtr(); + void privatizeOrphaned(Bin *bin); + void shareOrphaned(const Bin *bin); + unsigned int getSize() const { + MALLOC_ASSERT(isStartupAllocObject() || objectSize<minLargeObjectSize, + "Invalid object size"); + return objectSize; + } + const BackRefIdx *getBackRefIdx() const { return &backRefIdx; } + bool ownBlock() const { return !orphaned && owner.own(); } + bool isStartupAllocObject() const { return objectSize == startupAllocObjSizeMark; } + inline FreeObject *findObjectToFree(void *object) const; + bool checkFreePrecond(void *object) const { + if (allocatedCount>0) + if (startupAllocObjSizeMark == objectSize) // startup block + return object<=bumpPtr; + else + return allocatedCount <= (blockSize-sizeof(Block))/objectSize + && (!bumpPtr || object>bumpPtr); + return false; + } + const BackRefIdx *getBackRef() const { return &backRefIdx; } + void initEmptyBlock(Bin* tlsBin, size_t size); + +protected: + void cleanBlockHeader(); + +private: + static const float emptyEnoughRatio; /* "Reactivate" a block if this share of its objects is free. */ + + inline FreeObject *allocateFromBumpPtr(); + inline FreeObject *findAllocatedObject(const void *address) const; + inline bool isProperlyPlaced(const void *object) const; + + friend class Bin; + friend class TLSData; + friend void MemoryPool::destroy(); +}; + +const float Block::emptyEnoughRatio = 1.0 / 4.0; + +class Bin { + Block *activeBlk; + Block *mailbox; + MallocMutex mailLock; + +public: + inline Block* getActiveBlock() const { return activeBlk; } + void resetActiveBlock() { activeBlk = 0; } + bool activeBlockUnused() const { return activeBlk && !activeBlk->allocatedCount; } + inline void setActiveBlock(Block *block); + inline Block* setPreviousBlockActive(); + Block* getPublicFreeListBlock(); + void moveBlockToBinFront(Block *block); + void processLessUsedBlock(MemoryPool *memPool, Block *block); + + void outofTLSBin (Block* block); + void verifyTLSBin (size_t size) const; + void pushTLSBin(Block* block); + + void verifyInitState() const { + MALLOC_ASSERT( activeBlk == 0, ASSERT_TEXT ); + MALLOC_ASSERT( mailbox == 0, ASSERT_TEXT ); + } + + friend void Block::freePublicObject (FreeObject *objectToFree); +}; + +/********* End of the data structures **************/ + +/* + * There are bins for all 8 byte aligned objects less than this segregated size; 8 bins in total + */ +const uint32_t minSmallObjectIndex = 0; +const uint32_t numSmallObjectBins = 8; +const uint32_t maxSmallObjectSize = 64; + +/* + * There are 4 bins between each couple of powers of 2 [64-128-256-...] + * from maxSmallObjectSize till this size; 16 bins in total + */ +const uint32_t minSegregatedObjectIndex = minSmallObjectIndex+numSmallObjectBins; +const uint32_t numSegregatedObjectBins = 16; +const uint32_t maxSegregatedObjectSize = 1024; + +/* + * And there are 5 bins with allocation sizes that are multiples of estimatedCacheLineSize + * and selected to fit 9, 6, 4, 3, and 2 allocations in a block. + */ +const uint32_t minFittingIndex = minSegregatedObjectIndex+numSegregatedObjectBins; +const uint32_t numFittingBins = 5; + +const uint32_t fittingAlignment = estimatedCacheLineSize; + +#define SET_FITTING_SIZE(N) ( (blockSize-sizeof(Block))/N ) & ~(fittingAlignment-1) +// For blockSize=16*1024, sizeof(Block)=2*estimatedCacheLineSize and fittingAlignment=estimatedCacheLineSize, +// the comments show the fitting sizes and the amounts left unused for estimatedCacheLineSize=64/128: +const uint32_t fittingSize1 = SET_FITTING_SIZE(9); // 1792/1792 128/000 +const uint32_t fittingSize2 = SET_FITTING_SIZE(6); // 2688/2688 128/000 +const uint32_t fittingSize3 = SET_FITTING_SIZE(4); // 4032/3968 128/256 +const uint32_t fittingSize4 = SET_FITTING_SIZE(3); // 5376/5376 128/000 +const uint32_t fittingSize5 = SET_FITTING_SIZE(2); // 8128/8064 000/000 +#undef SET_FITTING_SIZE + +/* + * The total number of thread-specific Block-based bins + */ +const uint32_t numBlockBins = minFittingIndex+numFittingBins; + +/* + * Objects of this size and larger are considered large objects. + */ +const uint32_t minLargeObjectSize = fittingSize5 + 1; + +/* + * Default granularity of memory pools + */ + +#if USE_WINTHREAD +const size_t scalableMallocPoolGranularity = 64*1024; // for VirtualAlloc use +#else +const size_t scalableMallocPoolGranularity = 4*1024; // page size, for mmap use +#endif + +/* + * Per-thread pool of 16KB blocks. Idea behind it is to not share with other + * threads memory that are likely in local cache(s) of our CPU. + */ +class FreeBlockPool { + Block *head; + Block *tail; + int size; + Backend *backend; + bool lastAccessMiss; + void insertBlock(Block *block); +public: + static const int POOL_HIGH_MARK = 32; + static const int POOL_LOW_MARK = 8; + + class ResOfGet { + ResOfGet(); + public: + Block* block; + bool lastAccMiss; + ResOfGet(Block *b, bool lastMiss) : block(b), lastAccMiss(lastMiss) {} + }; + + // allocated in zero-initialized memory + FreeBlockPool(Backend *bknd) : backend(bknd) {} + ResOfGet getBlock(); + void returnBlock(Block *block); + bool releaseAllBlocks(); +}; + +class TLSData { +#if USE_PTHREAD + MemoryPool *memPool; +#endif +public: + Bin bin[numBlockBinLimit]; + FreeBlockPool freeBlocks; +#if USE_PTHREAD + TLSData(MemoryPool *mPool, Backend *bknd) : memPool(mPool), freeBlocks(bknd) {} + MemoryPool *getMemPool() const { return memPool; } +#else + TLSData(MemoryPool * /*memPool*/, Backend *bknd) : freeBlocks(bknd) {} +#endif + void release(MemoryPool *mPool); +}; + +TLSData *TLSKey::createTLS(MemoryPool *memPool, Backend *backend) +{ + MALLOC_ASSERT( sizeof(TLSData) >= sizeof(Bin) * numBlockBins + sizeof(FreeBlockPool), ASSERT_TEXT ); + TLSData* tls = (TLSData*) memPool->bootStrapBlocks.allocate(memPool, sizeof(TLSData)); + if ( !tls ) + return NULL; + new(tls) TLSData(memPool, backend); + /* the block contains zeroes after bootStrapMalloc, so bins are initialized */ +#if MALLOC_DEBUG + for (uint32_t i = 0; i < numBlockBinLimit; i++) + tls->bin[i].verifyInitState(); +#endif + setThreadMallocTLS(tls); + return tls; +} + +bool ExtMemoryPool::release16KBCaches() +{ + bool released = false; + TLSData *tlsData = tlsPointerKey.getThreadMallocTLS(); + + if (tlsData) { + released = tlsData->freeBlocks.releaseAllBlocks(); + + // active blocks can be not used, so return them to backend + for (uint32_t i=0; i<numBlockBinLimit; i++) + if (tlsData->bin[i].activeBlockUnused()) { + Block *block = tlsData->bin[i].getActiveBlock(); + tlsData->bin[i].outofTLSBin(block); + // 16KB blocks in user's pools not have valid backRefIdx + if (!userPool()) + removeBackRef(*(block->getBackRefIdx())); + backend.put16KBlock(block); + + released = true; + } + } + return released; +} + + +#if MALLOC_CHECK_RECURSION +MallocMutex RecursiveMallocCallProtector::rmc_mutex; +pthread_t RecursiveMallocCallProtector::owner_thread; +void *RecursiveMallocCallProtector::autoObjPtr; +bool RecursiveMallocCallProtector::mallocRecursionDetected; +#if __FreeBSD__ +bool RecursiveMallocCallProtector::canUsePthread; +#endif + +#endif + +/*********** End code to provide thread ID and a TLS pointer **********/ + +static void *internalMalloc(size_t size); +static void internalFree(void *object); +static void *internalPoolMalloc(MemoryPool* mPool, size_t size); +static bool internalPoolFree(MemoryPool *mPool, void *object); + +#if !MALLOC_DEBUG +#if __INTEL_COMPILER || _MSC_VER +#define NOINLINE(decl) __declspec(noinline) decl +#define ALWAYSINLINE(decl) __forceinline decl +#elif __GNUC__ +#define NOINLINE(decl) decl __attribute__ ((noinline)) +#define ALWAYSINLINE(decl) decl __attribute__ ((always_inline)) +#else +#define NOINLINE(decl) decl +#define ALWAYSINLINE(decl) decl +#endif + +static NOINLINE( void doInitialization() ); +ALWAYSINLINE( bool isMallocInitialized() ); + +#undef ALWAYSINLINE +#undef NOINLINE +#endif /* !MALLOC_DEBUG */ + + +/********* Now some rough utility code to deal with indexing the size bins. **************/ + +/* + * Given a number return the highest non-zero bit in it. It is intended to work with 32-bit values only. + * Moreover, on IPF, for sake of simplicity and performance, it is narrowed to only serve for 64 to 1023. + * This is enough for current algorithm of distribution of sizes among bins. + * __TBB_Log2 is not used here to minimize dependencies on TBB specific sources. + */ +#if _WIN64 && _MSC_VER>=1400 && !__INTEL_COMPILER +extern "C" unsigned char _BitScanReverse( unsigned long* i, unsigned long w ); +#pragma intrinsic(_BitScanReverse) +#endif +static inline unsigned int highestBitPos(unsigned int n) +{ + MALLOC_ASSERT( n>=64 && n<1024, ASSERT_TEXT ); // only needed for bsr array lookup, but always true + unsigned int pos; +#if __ARCH_x86_32||__ARCH_x86_64 + +# if __linux__||__APPLE__||__FreeBSD__||__NetBSD__||__sun||__MINGW32__ + __asm__ ("bsr %1,%0" : "=r"(pos) : "r"(n)); +# elif (_WIN32 && (!_WIN64 || __INTEL_COMPILER)) + __asm + { + bsr eax, n + mov pos, eax + } +# elif _WIN64 && _MSC_VER>=1400 + _BitScanReverse((unsigned long*)&pos, (unsigned long)n); +# else +# error highestBitPos() not implemented for this platform +# endif + +#else + static unsigned int bsr[16] = {0/*N/A*/,6,7,7,8,8,8,8,9,9,9,9,9,9,9,9}; + pos = bsr[ n>>6 ]; +#endif /* __ARCH_* */ + return pos; +} + +/* + * Depending on indexRequest, for a given size return either the index into the bin + * for objects of this size, or the actual size of objects in this bin. + */ +template<bool indexRequest> +static unsigned int getIndexOrObjectSize (unsigned int size) +{ + if (size <= maxSmallObjectSize) { // selection from 4/8/16/24/32/40/48/56/64 + /* Index 0 holds up to 8 bytes, Index 1 16 and so forth */ + return indexRequest ? (size - 1) >> 3 : alignUp(size,8); + } + else if (size <= maxSegregatedObjectSize ) { // 80/96/112/128 / 160/192/224/256 / 320/384/448/512 / 640/768/896/1024 + unsigned int order = highestBitPos(size-1); // which group of bin sizes? + MALLOC_ASSERT( 6<=order && order<=9, ASSERT_TEXT ); + if (indexRequest) + return minSegregatedObjectIndex - (4*6) - 4 + (4*order) + ((size-1)>>(order-2)); + else { + unsigned int alignment = 128 >> (9-order); // alignment in the group + MALLOC_ASSERT( alignment==16 || alignment==32 || alignment==64 || alignment==128, ASSERT_TEXT ); + return alignUp(size,alignment); + } + } + else { + if( size <= fittingSize3 ) { + if( size <= fittingSize2 ) { + if( size <= fittingSize1 ) + return indexRequest ? minFittingIndex : fittingSize1; + else + return indexRequest ? minFittingIndex+1 : fittingSize2; + } else + return indexRequest ? minFittingIndex+2 : fittingSize3; + } else { + if( size <= fittingSize5 ) { + if( size <= fittingSize4 ) + return indexRequest ? minFittingIndex+3 : fittingSize4; + else + return indexRequest ? minFittingIndex+4 : fittingSize5; + } else { + MALLOC_ASSERT( 0,ASSERT_TEXT ); // this should not happen + return ~0U; + } + } + } +} + +static unsigned int getIndex (unsigned int size) +{ + return getIndexOrObjectSize</*indexRequest*/true>(size); +} + +static unsigned int getObjectSize (unsigned int size) +{ + return getIndexOrObjectSize</*indexRequest*/false>(size); +} + + +void *BootStrapBlocks::allocate(MemoryPool *memPool, size_t size) +{ + FreeObject *result; + + MALLOC_ASSERT( size == sizeof(TLSData), ASSERT_TEXT ); + + { // Lock with acquire + MallocMutex::scoped_lock scoped_cs(bootStrapLock); + + if( bootStrapObjectList) { + result = bootStrapObjectList; + bootStrapObjectList = bootStrapObjectList->next; + } else { + if (!bootStrapBlock) { + bootStrapBlock = memPool->getEmptyBlock(size); + if (!bootStrapBlock) return NULL; + } + result = bootStrapBlock->bumpPtr; + bootStrapBlock->bumpPtr = (FreeObject *)((uintptr_t)bootStrapBlock->bumpPtr - bootStrapBlock->objectSize); + if ((uintptr_t)bootStrapBlock->bumpPtr < (uintptr_t)bootStrapBlock+sizeof(Block)) { + bootStrapBlock->bumpPtr = NULL; + bootStrapBlock->next = bootStrapBlockUsed; + bootStrapBlockUsed = bootStrapBlock; + bootStrapBlock = NULL; + } + } + } // Unlock with release + + memset (result, 0, size); + return (void*)result; +} + +void BootStrapBlocks::free(void* ptr) +{ + MALLOC_ASSERT( ptr, ASSERT_TEXT ); + { // Lock with acquire + MallocMutex::scoped_lock scoped_cs(bootStrapLock); + ((FreeObject*)ptr)->next = bootStrapObjectList; + bootStrapObjectList = (FreeObject*)ptr; + } // Unlock with release +} + +void BootStrapBlocks::reset() +{ + bootStrapBlock = bootStrapBlockUsed = NULL; + bootStrapObjectList = NULL; +} + +#if !(FREELIST_NONBLOCKING) +static MallocMutex publicFreeListLock; // lock for changes of publicFreeList +#endif + +const uintptr_t UNUSABLE = 0x1; +inline bool isSolidPtr( void* ptr ) +{ + return (UNUSABLE|(uintptr_t)ptr)!=UNUSABLE; +} +inline bool isNotForUse( void* ptr ) +{ + return (uintptr_t)ptr==UNUSABLE; +} + +/********* End rough utility code **************/ + +#ifdef FINE_GRAIN_LOCKS +/* LifoList assumes zero initialization so a vector of it can be created + * by just allocating some space with no call to constructor. + * On Linux, it seems to be necessary to avoid linking with C++ libraries. + * + * By usage convention there is no race on the initialization. */ +LifoList::LifoList( ) : top(NULL) +{ + // MallocMutex assumes zero initialization + memset(&lock, 0, sizeof(MallocMutex)); +} + +void LifoList::push(Block *block) +{ + MallocMutex::scoped_lock scoped_cs(lock); + block->next = top; + top = block; +} + +Block *LifoList::pop() +{ + Block *block=NULL; + if (!top) goto done; + { + MallocMutex::scoped_lock scoped_cs(lock); + if (!top) goto done; + block = top; + top = block->next; + } +done: + return block; +} + +#endif /* FINE_GRAIN_LOCKS */ + +/********* Thread and block related code *************/ + +/* + * Return the bin for the given size. If the TLS bin structure is absent, create it. + */ +Bin* MemoryPool::getAllocationBin(size_t size) +{ + TLSData* tls = extMemPool.tlsPointerKey.getThreadMallocTLS(); + if( !tls ) + tls = extMemPool.tlsPointerKey.createTLS(this, &extMemPool.backend); + MALLOC_ASSERT( tls, ASSERT_TEXT ); + return tls->bin + getIndex(size); +} + +/* Return an empty uninitialized block in a non-blocking fashion. */ +Block *MemoryPool::getEmptyBlock(size_t size) +{ + FreeBlockPool::ResOfGet resOfGet(NULL, false); + Block *result = NULL, *b; + TLSData* tls = extMemPool.tlsPointerKey.getThreadMallocTLS(); + + if (tls) + resOfGet = tls->freeBlocks.getBlock(); + if (resOfGet.block) { + result = resOfGet.block; + } else { + int i, num = resOfGet.lastAccMiss? Backend::numOfBlocksAllocOnMiss : 1; + BackRefIdx backRefIdx[Backend::numOfBlocksAllocOnMiss]; + + result = static_cast<Block*>(extMemPool.backend.get16KBlock(num)); + if (!result) return NULL; + + if (!extMemPool.userPool()) + for (i=0; i<num; i++) { + backRefIdx[i] = BackRefIdx::newBackRef(/*largeObj=*/false); + if (backRefIdx[i].isInvalid()) { + // roll back resource allocation + for (int j=0; j<i; j++) + removeBackRef(backRefIdx[j]); + Block *b; + for (b=result, i=0; i<num; + b=(Block*)((uintptr_t)b+blockSize), i++) + extMemPool.backend.put16KBlock(b); + return NULL; + } + } + // resources were allocated, register blocks + for (b=result, i=0; i<num; b=(Block*)((uintptr_t)b+blockSize), i++) { + // 16KB block in user's pool must have invalid backRefIdx + if (extMemPool.userPool()) { + new (&b->backRefIdx) BackRefIdx(); + } else { + setBackRef(backRefIdx[i], b); + b->backRefIdx = backRefIdx[i]; + } + // all but first one go to per-thread pool + if (i > 0) { + MALLOC_ASSERT(tls, ASSERT_TEXT); + tls->freeBlocks.returnBlock(b); + } + } + } + if (result) { + result->initEmptyBlock(tls? tls->bin : NULL, size); + STAT_increment(result->owner, getIndex(result->objectSize), allocBlockNew); + } + return result; +} + +void MemoryPool::returnEmptyBlock(Block *block, bool poolTheBlock) +{ + block->makeEmpty(); + if (poolTheBlock) { + extMemPool.tlsPointerKey.getThreadMallocTLS()->freeBlocks.returnBlock(block); + } + else { + // 16KB blocks in user's pools not have valid backRefIdx + if (!extMemPool.userPool()) + removeBackRef(*(block->getBackRefIdx())); + extMemPool.backend.put16KBlock(block); + } +} + +bool ExtMemoryPool::init(intptr_t poolId, rawAllocType rawAlloc, + rawFreeType rawFree, size_t granularity, + bool keepAllMemory, bool fixedPool) +{ + this->poolId = poolId; + this->rawAlloc = rawAlloc; + this->rawFree = rawFree; + this->granularity = granularity; + this->keepAllMemory = keepAllMemory; + this->fixedPool = fixedPool; + this->delayRegsReleasing = false; + initTLS(); + // allocate initial region for user's objects placement + return backend.bootstrap(this); +} + +void ExtMemoryPool::initTLS() { new (&tlsPointerKey) TLSKey(); } + +TLSData *ExtMemoryPool::getTLS() +{ + return tlsPointerKey.getThreadMallocTLS(); +} + +void ExtMemoryPool::clearTLS() +{ + tlsPointerKey.setThreadMallocTLS(NULL); +} + +bool MemoryPool::init(intptr_t poolId, const MemPoolPolicy *policy) +{ + if (!extMemPool.init(poolId, policy->pAlloc, policy->pFree, + policy->granularity? policy->granularity : defaultGranularity, + policy->keepAllMemory, policy->fixedPool)) + return false; + { + MallocMutex::scoped_lock lock(memPoolListLock); + next = defaultMemPool->next; + defaultMemPool->next = this; + prev = defaultMemPool; + if (next) + next->prev = this; + } + return true; +} + +void MemoryPool::reset() +{ + // memory is not releasing during pool reset + // TODO: mark regions to release unused on next reset() + extMemPool.delayRegionsReleasing(true); + + bootStrapBlocks.reset(); + orphanedBlocks.reset(); + extMemPool.reset(); + + extMemPool.initTLS(); + extMemPool.delayRegionsReleasing(false); +} + +void MemoryPool::destroy() +{ + { + MallocMutex::scoped_lock lock(memPoolListLock); + // remove itself from global pool list + if (prev) + prev->next = next; + if (next) + next->prev = prev; + } + // 16KB blocks in non-default pool does not have backreferencies, + // only large objects do + for (LargeMemoryBlock *lmb = extMemPool.lmbList.getHead(); lmb; ) { + LargeMemoryBlock *next = lmb->gNext; + if (extMemPool.userPool()) + removeBackRef(lmb->backRefIdx); + // For speeding up pool destroy, not returning blocks + // to backend, as we destroy backend at ones. + // But must return blocks that are too big to hit backend. + if (ExtMemoryPool::tooLargeToBeBined(lmb->unalignedSize)) + extMemPool.backend.putLargeBlock(lmb); + lmb = next; + } + extMemPool.destroy(); +} + +void Bin::verifyTLSBin (size_t size) const +{ + suppress_unused_warning(size); +#if MALLOC_DEBUG +/* The debug version verifies the TLSBin as needed */ + uint32_t objSize = getObjectSize(size); + + if (activeBlk) { + MALLOC_ASSERT( activeBlk->owner.own(), ASSERT_TEXT ); + MALLOC_ASSERT( activeBlk->objectSize == objSize, ASSERT_TEXT ); +#if MALLOC_DEBUG>1 + for (Block* temp = activeBlk->next; temp; temp=temp->next) { + MALLOC_ASSERT( temp!=activeBlk, ASSERT_TEXT ); + MALLOC_ASSERT( temp->owner.own(), ASSERT_TEXT ); + MALLOC_ASSERT( temp->objectSize == objSize, ASSERT_TEXT ); + MALLOC_ASSERT( temp->previous->next == temp, ASSERT_TEXT ); + if (temp->next) { + MALLOC_ASSERT( temp->next->previous == temp, ASSERT_TEXT ); + } + } + for (Block* temp = activeBlk->previous; temp; temp=temp->previous) { + MALLOC_ASSERT( temp!=activeBlk, ASSERT_TEXT ); + MALLOC_ASSERT( temp->owner.own(), ASSERT_TEXT ); + MALLOC_ASSERT( temp->objectSize == objSize, ASSERT_TEXT ); + MALLOC_ASSERT( temp->next->previous == temp, ASSERT_TEXT ); + if (temp->previous) { + MALLOC_ASSERT( temp->previous->next == temp, ASSERT_TEXT ); + } + } +#endif /* MALLOC_DEBUG>1 */ + } +#endif /* MALLOC_DEBUG */ +} + +/* + * Add a block to the start of this tls bin list. + */ +void Bin::pushTLSBin(Block* block) +{ + /* The objectSize should be defined and not a parameter + because the function is applied to partially filled blocks as well */ + unsigned int size = block->objectSize; + + MALLOC_ASSERT( block->owner == ThreadId::get(), ASSERT_TEXT ); + MALLOC_ASSERT( block->objectSize != 0, ASSERT_TEXT ); + MALLOC_ASSERT( block->next == NULL, ASSERT_TEXT ); + MALLOC_ASSERT( block->previous == NULL, ASSERT_TEXT ); + + MALLOC_ASSERT( this, ASSERT_TEXT ); + verifyTLSBin(size); + + block->next = activeBlk; + if( activeBlk ) { + block->previous = activeBlk->previous; + activeBlk->previous = block; + if( block->previous ) + block->previous->next = block; + } else { + activeBlk = block; + } + + verifyTLSBin(size); +} + +/* + * Take a block out of its tls bin (e.g. before removal). + */ +void Bin::outofTLSBin(Block* block) +{ + unsigned int size = block->objectSize; + + MALLOC_ASSERT( block->owner == ThreadId::get(), ASSERT_TEXT ); + MALLOC_ASSERT( block->objectSize != 0, ASSERT_TEXT ); + + MALLOC_ASSERT( this, ASSERT_TEXT ); + verifyTLSBin(size); + + if (block == activeBlk) { + activeBlk = block->previous? block->previous : block->next; + } + /* Delink the block */ + if (block->previous) { + MALLOC_ASSERT( block->previous->next == block, ASSERT_TEXT ); + block->previous->next = block->next; + } + if (block->next) { + MALLOC_ASSERT( block->next->previous == block, ASSERT_TEXT ); + block->next->previous = block->previous; + } + block->next = NULL; + block->previous = NULL; + + verifyTLSBin(size); +} + +Block* Bin::getPublicFreeListBlock() +{ + Block* block; + MALLOC_ASSERT( this, ASSERT_TEXT ); + // if this method is called, active block usage must be unsuccesful + MALLOC_ASSERT( !activeBlk && !mailbox || activeBlk && activeBlk->isFull, ASSERT_TEXT ); + +// the counter should be changed STAT_increment(getThreadId(), ThreadCommonCounters, lockPublicFreeList); + { + MallocMutex::scoped_lock scoped_cs(mailLock); + block = mailbox; + if( block ) { + MALLOC_ASSERT( block->ownBlock(), ASSERT_TEXT ); + MALLOC_ASSERT( !isNotForUse(block->nextPrivatizable), ASSERT_TEXT ); + mailbox = block->nextPrivatizable; + block->nextPrivatizable = (Block*) this; + } + } + if( block ) { + MALLOC_ASSERT( isSolidPtr(block->publicFreeList), ASSERT_TEXT ); + block->privatizePublicFreeList(); + } + return block; +} + +bool Block::emptyEnoughToUse() +{ + const float threshold = (blockSize - sizeof(Block)) * (1-emptyEnoughRatio); + + if (bumpPtr) { + /* If we are still using a bump ptr for this block it is empty enough to use. */ + STAT_increment(owner, getIndex(objectSize), examineEmptyEnough); + isFull = false; + return 1; + } + + /* allocatedCount shows how many objects in the block are in use; however it still counts + blocks freed by other threads; so prior call to privatizePublicFreeList() is recommended */ + isFull = (allocatedCount*objectSize > threshold)? true: false; +#if COLLECT_STATISTICS + if (isFull) + STAT_increment(owner, getIndex(objectSize), examineNotEmpty); + else + STAT_increment(owner, getIndex(objectSize), examineEmptyEnough); +#endif + return !isFull; +} + +/* Restore the bump pointer for an empty block that is planned to use */ +void Block::restoreBumpPtr() +{ + MALLOC_ASSERT( allocatedCount == 0, ASSERT_TEXT ); + MALLOC_ASSERT( publicFreeList == NULL, ASSERT_TEXT ); + STAT_increment(owner, getIndex(objectSize), freeRestoreBumpPtr); + bumpPtr = (FreeObject *)((uintptr_t)this + blockSize - objectSize); + freeList = NULL; + isFull = 0; +} + +void Block::freeOwnObject(MemoryPool *memPool, FreeObject *objectToFree) +{ + objectToFree->next = freeList; + freeList = objectToFree; + allocatedCount--; + MALLOC_ASSERT( allocatedCount < (blockSize-sizeof(Block))/objectSize, ASSERT_TEXT ); +#if COLLECT_STATISTICS + if (getActiveBlock(memPool->getAllocationBin(block->objectSize)) != block) + STAT_increment(myTid, getIndex(block->objectSize), freeToInactiveBlock); + else + STAT_increment(myTid, getIndex(block->objectSize), freeToActiveBlock); +#endif + if (isFull) { + if (emptyEnoughToUse()) + memPool->getAllocationBin(objectSize)->moveBlockToBinFront(this); + } else { + if (allocatedCount==0 && publicFreeList==NULL) + memPool->getAllocationBin(objectSize)-> + processLessUsedBlock(memPool, this); + } +} + +void Block::freePublicObject (FreeObject *objectToFree) +{ + FreeObject *localPublicFreeList; + + MALLOC_ITT_SYNC_RELEASING(&publicFreeList); +#if FREELIST_NONBLOCKING + FreeObject *temp = publicFreeList; + do { + localPublicFreeList = objectToFree->next = temp; + temp = (FreeObject*)AtomicCompareExchange( + (intptr_t&)publicFreeList, + (intptr_t)objectToFree, (intptr_t)localPublicFreeList ); + // no backoff necessary because trying to make change, not waiting for a change + } while( temp != localPublicFreeList ); +#else + STAT_increment(getThreadId(), ThreadCommonCounters, lockPublicFreeList); + { + MallocMutex::scoped_lock scoped_cs(publicFreeListLock); + localPublicFreeList = objectToFree->next = publicFreeList; + publicFreeList = objectToFree; + } +#endif + + if( localPublicFreeList==NULL ) { + // if the block is abandoned, its nextPrivatizable pointer should be UNUSABLE + // otherwise, it should point to the bin the block belongs to. + // reading nextPrivatizable is thread-safe below, because: + // 1) the executing thread atomically got localPublicFreeList==NULL and changed it to non-NULL; + // 2) only owning thread can change it back to NULL, + // 3) but it can not be done until the block is put to the mailbox + // So the executing thread is now the only one that can change nextPrivatizable + if( !isNotForUse(nextPrivatizable) ) { + MALLOC_ASSERT( nextPrivatizable!=NULL, ASSERT_TEXT ); + MALLOC_ASSERT( owner.defined(), ASSERT_TEXT ); + Bin* theBin = (Bin*) nextPrivatizable; + MallocMutex::scoped_lock scoped_cs(theBin->mailLock); + nextPrivatizable = theBin->mailbox; + theBin->mailbox = this; + } else { + MALLOC_ASSERT( !owner.defined(), ASSERT_TEXT ); + } + } + STAT_increment(ThreadId::get(), ThreadCommonCounters, freeToOtherThread); + STAT_increment(owner, getIndex(objectSize), freeByOtherThread); +} + +void Block::privatizePublicFreeList() +{ + FreeObject *temp, *localPublicFreeList; + + MALLOC_ASSERT( owner.own(), ASSERT_TEXT ); +#if FREELIST_NONBLOCKING + temp = publicFreeList; + do { + localPublicFreeList = temp; + temp = (FreeObject*)AtomicCompareExchange( + (intptr_t&)publicFreeList, + 0, (intptr_t)localPublicFreeList); + // no backoff necessary because trying to make change, not waiting for a change + } while( temp != localPublicFreeList ); +#else + STAT_increment(owner, ThreadCommonCounters, lockPublicFreeList); + { + MallocMutex::scoped_lock scoped_cs(publicFreeListLock); + localPublicFreeList = publicFreeList; + publicFreeList = NULL; + } + temp = localPublicFreeList; +#endif + MALLOC_ITT_SYNC_ACQUIRED(&publicFreeList); + + MALLOC_ASSERT( localPublicFreeList && localPublicFreeList==temp, ASSERT_TEXT ); // there should be something in publicFreeList! + if( !isNotForUse(temp) ) { // return/getPartialBlock could set it to UNUSABLE + MALLOC_ASSERT( allocatedCount <= (blockSize-sizeof(Block))/objectSize, ASSERT_TEXT ); + /* other threads did not change the counter freeing our blocks */ + allocatedCount--; + while( isSolidPtr(temp->next) ){ // the list will end with either NULL or UNUSABLE + temp = temp->next; + allocatedCount--; + } + MALLOC_ASSERT( allocatedCount < (blockSize-sizeof(Block))/objectSize, ASSERT_TEXT ); + /* merge with local freeList */ + temp->next = freeList; + freeList = localPublicFreeList; + STAT_increment(owner, getIndex(objectSize), allocPrivatized); + } +} + +void Block::privatizeOrphaned(Bin* bin) +{ + next = NULL; + previous = NULL; + MALLOC_ASSERT( publicFreeList!=NULL, ASSERT_TEXT ); + /* There is not a race here since no other thread owns this block */ + MALLOC_ASSERT( !owner.defined(), ASSERT_TEXT ); + owner = ThreadId::get(); + MALLOC_ASSERT(orphaned, ASSERT_TEXT); + orphaned = false; + // It is safe to change nextPrivatizable, as publicFreeList is not null + MALLOC_ASSERT( isNotForUse(nextPrivatizable), ASSERT_TEXT ); + nextPrivatizable = (Block*)bin; + // the next call is required to change publicFreeList to 0 + privatizePublicFreeList(); + if( allocatedCount ) { + emptyEnoughToUse(); // check its fullness and set result->isFull + } else { + restoreBumpPtr(); + } + MALLOC_ASSERT( !isNotForUse(publicFreeList), ASSERT_TEXT ); +} + +void Block::shareOrphaned(const Bin *bin) +{ + MALLOC_ASSERT( bin, ASSERT_TEXT ); + STAT_increment(owner, index, freeBlockPublic); + MALLOC_ASSERT(!orphaned, ASSERT_TEXT); + orphaned = true; + // need to set publicFreeList to non-zero, so other threads + // will not change nextPrivatizable and it can be zeroed. + if ((intptr_t)nextPrivatizable==(intptr_t)bin) { + void* oldval; +#if FREELIST_NONBLOCKING + oldval = (void*)AtomicCompareExchange((intptr_t&)publicFreeList, (intptr_t)UNUSABLE, 0); +#else + STAT_increment(owner, ThreadCommonCounters, lockPublicFreeList); + { + MallocMutex::scoped_lock scoped_cs(publicFreeListLock); + if ( (oldval=publicFreeList)==NULL ) + (uintptr_t&)(publicFreeList) = UNUSABLE; + } +#endif + if ( oldval!=NULL ) { + // another thread freed an object; we need to wait until it finishes. + // I believe there is no need for exponential backoff, as the wait here is not for a lock; + // but need to yield, so the thread we wait has a chance to run. + int count = 256; + while( (intptr_t)const_cast<Block* volatile &>(nextPrivatizable)==(intptr_t)bin ) { + if (--count==0) { + do_yield(); + count = 256; + } + } + } + } else { + MALLOC_ASSERT( isSolidPtr(publicFreeList), ASSERT_TEXT ); + } + MALLOC_ASSERT( publicFreeList!=NULL, ASSERT_TEXT ); + // now it is safe to change our data + previous = NULL; + owner.undef(); + // it is caller responsibility to ensure that the list of blocks + // formed by nextPrivatizable pointers is kept consistent if required. + // if only called from thread shutdown code, it does not matter. + (uintptr_t&)(nextPrivatizable) = UNUSABLE; +} + +void Block::cleanBlockHeader() +{ + next = NULL; + previous = NULL; + freeList = NULL; + allocatedCount = 0; + isFull = 0; + orphaned = false; + + publicFreeList = NULL; +} + +void Block::initEmptyBlock(Bin* tlsBin, size_t size) +{ + // Having getIndex and getObjectSize called next to each other + // allows better compiler optimization as they basically share the code. + unsigned int index = getIndex(size); + unsigned int objSz = getObjectSize(size); + + cleanBlockHeader(); + objectSize = objSz; + owner = ThreadId::get(); + // bump pointer should be prepared for first allocation - thus mode it down to objectSize + bumpPtr = (FreeObject *)((uintptr_t)this + blockSize - objectSize); + + // each block should have the address where the head of the list of "privatizable" blocks is kept + // the only exception is a block for boot strap which is initialized when TLS is yet NULL + nextPrivatizable = tlsBin? (Block*)(tlsBin + index) : NULL; + TRACEF(( "[ScalableMalloc trace] Empty block %p is initialized, owner is %d, objectSize is %d, bumpPtr is %p\n", + this, owner, objectSize, bumpPtr )); +} + +Block *OrphanedBlocks::get(Bin* bin, unsigned int size) +{ + Block *result; + MALLOC_ASSERT( bin, ASSERT_TEXT ); + unsigned int index = getIndex(size); + result = bins[index].pop(); + if (result) { + MALLOC_ITT_SYNC_ACQUIRED(bins+index); + result->privatizeOrphaned(bin); + STAT_increment(result->owner, index, allocBlockPublic); + } + return result; +} + +void OrphanedBlocks::put(Bin* bin, Block *block) +{ + unsigned int index = getIndex(block->getSize()); + block->shareOrphaned(bin); + MALLOC_ITT_SYNC_RELEASING(bins+index); + bins[index].push(block); +} + +void OrphanedBlocks::reset() +{ + for (uint32_t i=0; i<numBlockBinLimit; i++) + new (bins+i) LifoList(); +} + +void FreeBlockPool::insertBlock(Block *block) +{ + size++; + block->next = head; + head = block; + if (!tail) + tail = block; +} + +FreeBlockPool::ResOfGet FreeBlockPool::getBlock() +{ + Block *b = head; + + if (head) { + size--; + head = head->next; + if (!head) + tail = NULL; + lastAccessMiss = false; + } else + lastAccessMiss = true; + + return ResOfGet(b, lastAccessMiss); +} + +void FreeBlockPool::returnBlock(Block *block) +{ + MALLOC_ASSERT( size <= POOL_HIGH_MARK, ASSERT_TEXT ); + if (size == POOL_HIGH_MARK) { + // release cold blocks and add hot one + Block *headToFree = head, + *helper; + for (int i=0; i<POOL_LOW_MARK-2; i++) + headToFree = headToFree->next; + tail = headToFree; + headToFree = headToFree->next; + tail->next = NULL; + size = POOL_LOW_MARK-1; + // 16KB blocks from user pools not have valid backreference + for (Block *currBl = headToFree; currBl; currBl = helper) { + helper = currBl->next; + if (!backend->inUserPool()) + removeBackRef(currBl->backRefIdx); + backend->put16KBlock(currBl); + } + } + insertBlock(block); +} + +bool FreeBlockPool::releaseAllBlocks() +{ + Block *helper; + bool nonEmpty = size; + + for (Block *currBl = head; currBl; currBl=helper) { + helper = currBl->next; + // 16KB blocks in user's pools not have valid backRefIdx + if (!backend->inUserPool()) + removeBackRef(currBl->backRefIdx); + backend->put16KBlock(currBl); + } + head = tail = NULL; + size = 0; + + return nonEmpty; +} + +/* We have a block give it back to the malloc block manager */ +void Block::makeEmpty() +{ + // it is caller's responsibility to ensure no data is lost before calling this + MALLOC_ASSERT( allocatedCount==0, ASSERT_TEXT ); + MALLOC_ASSERT( publicFreeList==NULL, ASSERT_TEXT ); + STAT_increment(owner, getIndex(objectSize), freeBlockBack); + + cleanBlockHeader(); + + nextPrivatizable = NULL; + + objectSize = 0; + owner.invalid(); + // for an empty block, bump pointer should point right after the end of the block + bumpPtr = (FreeObject *)((uintptr_t)this + blockSize); +} + +inline void Bin::setActiveBlock (Block *block) +{ +// MALLOC_ASSERT( bin, ASSERT_TEXT ); + MALLOC_ASSERT( block->owner.own(), ASSERT_TEXT ); + // it is the caller responsibility to keep bin consistence (i.e. ensure this block is in the bin list) + activeBlk = block; +} + +inline Block* Bin::setPreviousBlockActive() +{ + MALLOC_ASSERT( activeBlk, ASSERT_TEXT ); + Block* temp = activeBlk->previous; + if( temp ) { + MALLOC_ASSERT( temp->isFull == 0, ASSERT_TEXT ); + activeBlk = temp; + } + return temp; +} + +FreeObject *Block::findObjectToFree(void *object) const +{ + FreeObject *objectToFree; + // Due to aligned allocations, a pointer passed to scalable_free + // might differ from the address of internally allocated object. + // Small objects however should always be fine. + if (objectSize <= maxSegregatedObjectSize) + objectToFree = (FreeObject*)object; + // "Fitting size" allocations are suspicious if aligned higher than naturally + else { + if ( ! isAligned(object,2*fittingAlignment) ) + // TODO: the above check is questionable - it gives false negatives in ~50% cases, + // so might even be slower in average than unconditional use of findAllocatedObject. + // here it should be a "real" object + objectToFree = (FreeObject*)object; + else + // here object can be an aligned address, so applying additional checks + objectToFree = findAllocatedObject(object); + MALLOC_ASSERT( isAligned(objectToFree,fittingAlignment), ASSERT_TEXT ); + } + MALLOC_ASSERT( isProperlyPlaced(objectToFree), ASSERT_TEXT ); + + return objectToFree; +} + +void TLSData::release(MemoryPool *mPool) +{ + freeBlocks.releaseAllBlocks(); + + for (unsigned index = 0; index < numBlockBins; index++) { + Block *activeBlk = bin[index].getActiveBlock(); + if (!activeBlk) + continue; + Block *threadlessBlock = activeBlk->previous; + while (threadlessBlock) { + Block *threadBlock = threadlessBlock->previous; + if (threadlessBlock->empty()) { + /* we destroy the thread, so not use its block pool */ + mPool->returnEmptyBlock(threadlessBlock, /*poolTheBlock=*/false); + } else { + mPool->orphanedBlocks.put(bin+index, threadlessBlock); + } + threadlessBlock = threadBlock; + } + threadlessBlock = activeBlk; + while (threadlessBlock) { + Block *threadBlock = threadlessBlock->next; + if (threadlessBlock->empty()) { + /* we destroy the thread, so not use its block pool */ + mPool->returnEmptyBlock(threadlessBlock, /*poolTheBlock=*/false); + } else { + mPool->orphanedBlocks.put(bin+index, threadlessBlock); + } + threadlessBlock = threadBlock; + } + bin[index].resetActiveBlock(); + } +} + + +#if MALLOC_CHECK_RECURSION +// TODO: Use deducated heap for this + +/* + * It's a special kind of allocation that can be used when malloc is + * not available (either during startup or when malloc was already called and + * we are, say, inside pthread_setspecific's call). + * Block can contain objects of different sizes, + * allocations are performed by moving bump pointer and increasing of object counter, + * releasing is done via counter of objects allocated in the block + * or moving bump pointer if releasing object is on a bound. + */ + +class StartupBlock : public Block { + size_t availableSize() { + return blockSize - ((uintptr_t)bumpPtr - (uintptr_t)this); + } + static StartupBlock *getBlock(); +public: + static FreeObject *allocate(size_t size); + static size_t msize(void *ptr) { return *((size_t*)ptr - 1); } + void free(void *ptr); +}; + +static MallocMutex startupMallocLock; +static StartupBlock *firstStartupBlock; + +StartupBlock *StartupBlock::getBlock() +{ + BackRefIdx backRefIdx = BackRefIdx::newBackRef(/*largeObj=*/false); + if (backRefIdx.isInvalid()) return NULL; + + StartupBlock *block = static_cast<StartupBlock*>( + defaultMemPool->extMemPool.backend.get16KBlock(1)); + if (!block) return NULL; + + block->cleanBlockHeader(); + setBackRef(backRefIdx, block); + block->backRefIdx = backRefIdx; + // use startupAllocObjSizeMark to mark objects from startup block marker + block->objectSize = startupAllocObjSizeMark; + block->bumpPtr = (FreeObject *)((uintptr_t)block + sizeof(StartupBlock)); + return block; +} + +FreeObject *StartupBlock::allocate(size_t size) +{ + FreeObject *result; + StartupBlock *newBlock = NULL; + bool newBlockUnused = false; + + /* Objects must be aligned on their natural bounds, + and objects bigger than word on word's bound. */ + size = alignUp(size, sizeof(size_t)); + // We need size of an object to implement msize. + size_t reqSize = size + sizeof(size_t); + // speculatively allocates newBlock to try avoid allocation while holding lock + /* TODO: The function is called when malloc nested call is detected, + so simultaneous usage from different threads seems unlikely. + If pre-allocation is found useless, the code might be simplified. */ + if (!firstStartupBlock || firstStartupBlock->availableSize() < reqSize) { + newBlock = StartupBlock::getBlock(); + if (!newBlock) return NULL; + } + { + MallocMutex::scoped_lock scoped_cs(startupMallocLock); + // Re-check whether we need a new block (conditions might have changed) + if (!firstStartupBlock || firstStartupBlock->availableSize() < reqSize) { + if (!newBlock) { + newBlock = StartupBlock::getBlock(); + if (!newBlock) return NULL; + } + newBlock->next = (Block*)firstStartupBlock; + if (firstStartupBlock) + firstStartupBlock->previous = (Block*)newBlock; + firstStartupBlock = newBlock; + } else + newBlockUnused = true; + result = firstStartupBlock->bumpPtr; + firstStartupBlock->allocatedCount++; + firstStartupBlock->bumpPtr = + (FreeObject *)((uintptr_t)firstStartupBlock->bumpPtr + reqSize); + } + if (newBlock && newBlockUnused) + defaultMemPool->returnEmptyBlock(newBlock, /*poolTheBlock=*/false); + + // keep object size at the negative offset + *((size_t*)result) = size; + return (FreeObject*)((size_t*)result+1); +} + +void StartupBlock::free(void *ptr) +{ + Block* blockToRelease = NULL; + { + MallocMutex::scoped_lock scoped_cs(startupMallocLock); + + MALLOC_ASSERT(firstStartupBlock, ASSERT_TEXT); + MALLOC_ASSERT(startupAllocObjSizeMark==objectSize + && allocatedCount>0, ASSERT_TEXT); + MALLOC_ASSERT((uintptr_t)ptr>=(uintptr_t)this+sizeof(StartupBlock) + && (uintptr_t)ptr+StartupBlock::msize(ptr)<=(uintptr_t)this+blockSize, + ASSERT_TEXT); + if (0 == --allocatedCount) { + if (this == firstStartupBlock) + firstStartupBlock = (StartupBlock*)firstStartupBlock->next; + if (previous) + previous->next = next; + if (next) + next->previous = previous; + blockToRelease = this; + } else if ((uintptr_t)ptr + StartupBlock::msize(ptr) == (uintptr_t)bumpPtr) { + // last object in the block released + FreeObject *newBump = (FreeObject*)((size_t*)ptr - 1); + MALLOC_ASSERT((uintptr_t)newBump>(uintptr_t)this+sizeof(StartupBlock), + ASSERT_TEXT); + bumpPtr = newBump; + } + } + if (blockToRelease) { + blockToRelease->previous = blockToRelease->next = NULL; + defaultMemPool->returnEmptyBlock(blockToRelease, /*poolTheBlock=*/false); + } +} + +#endif /* MALLOC_CHECK_RECURSION */ + +/********* End thread related code *************/ + +/********* Library initialization *************/ + +//! Value indicating the state of initialization. +/* 0 = initialization not started. + * 1 = initialization started but not finished. + * 2 = initialization finished. + * In theory, we only need values 0 and 2. But value 1 is nonetheless + * useful for detecting errors in the double-check pattern. + */ +static intptr_t mallocInitialized; // implicitly initialized to 0 +static MallocMutex initMutex; + +#include "../tbb/tbb_version.h" + +/** The leading "\0" is here so that applying "strings" to the binary + delivers a clean result. */ +static char VersionString[] = "\0" TBBMALLOC_VERSION_STRINGS; + +#if _XBOX +bool GetBoolEnvironmentVariable(const char *name) { return false; } +#else +bool GetBoolEnvironmentVariable(const char *name) +{ + if( const char* s = getenv(name) ) + return strcmp(s,"0") != 0; + return false; +} +#endif + +void MemoryPool::initDefaultPool() +{ +#if __linux__ + if (FILE *f = fopen("/proc/meminfo", "r")) { + const int SZ = 100; + char buf[SZ]; + long long totalHugePages=0, hugePageSize=0; + MALLOC_ASSERT(sizeof(totalHugePages) >= 8, + "At least 64 bits required for keeping page size/numbers."); + + while (fgets(buf, SZ, f)) { + if (1 == sscanf(buf, "HugePages_Total: %llu", &totalHugePages)) + continue; + sscanf(buf, "Hugepagesize: %llu kB", &hugePageSize); + } + fclose(f); + if (totalHugePages) + ExtMemoryPool::useHugePages = true; + if (hugePageSize) + ExtMemoryPool::hugePageSize = hugePageSize*1024; + } +#endif +} + +inline bool isMallocInitialized() { + // Load must have acquire fence; otherwise thread taking "initialized" path + // might perform textually later loads *before* mallocInitialized becomes 2. + return 2 == FencedLoad(mallocInitialized); +} + +bool isMallocInitializedExt() { + return isMallocInitialized(); +} + +/* + * Allocator initialization routine; + * it is called lazily on the very first scalable_malloc call. + */ +static void initMemoryManager() +{ + TRACEF(( "[ScalableMalloc trace] sizeof(Block) is %d (expected 128); sizeof(uintptr_t) is %d\n", + sizeof(Block), sizeof(uintptr_t) )); + MALLOC_ASSERT( 2*blockHeaderAlignment == sizeof(Block), ASSERT_TEXT ); + MALLOC_ASSERT( sizeof(FreeObject) == sizeof(void*), ASSERT_TEXT ); + + bool initOk = defaultMemPool-> + extMemPool.init(0, NULL, NULL, scalableMallocPoolGranularity, + /*keepAllMemory=*/false, /*fixedPool=*/false); +// TODO: add error handling, and on error do something better than exit(1) + if (!initOk || !initBackRefMaster(&defaultMemPool->extMemPool.backend)) { + fprintf (stderr, "The memory manager cannot access sufficient memory to initialize; exiting \n"); + exit(1); + } + ThreadId::init(); // Create keys for thread id + MemoryPool::initDefaultPool(); +#if COLLECT_STATISTICS + initStatisticsCollection(); +#endif +} + +//! Ensures that initMemoryManager() is called once and only once. +/** Does not return until initMemoryManager() has been completed by a thread. + There is no need to call this routine if mallocInitialized==2 . */ +static void doInitialization() +{ + MallocMutex::scoped_lock lock( initMutex ); + if (mallocInitialized!=2) { + MALLOC_ASSERT( mallocInitialized==0, ASSERT_TEXT ); + mallocInitialized = 1; + RecursiveMallocCallProtector scoped; + initMemoryManager(); +#ifdef MALLOC_EXTRA_INITIALIZATION + MALLOC_EXTRA_INITIALIZATION; +#endif +#if MALLOC_CHECK_RECURSION + RecursiveMallocCallProtector::detectNaiveOverload(); +#endif + MALLOC_ASSERT( mallocInitialized==1, ASSERT_TEXT ); + // Store must have release fence, otherwise mallocInitialized==2 + // might become remotely visible before side effects of + // initMemoryManager() become remotely visible. + FencedStore( mallocInitialized, 2 ); + if( GetBoolEnvironmentVariable("TBB_VERSION") ) { + fputs(VersionString+1,stderr); + fprintf(stderr, "TBBmalloc: scalable allocator\t%s\n", + ExtMemoryPool::useHugePages? "use huge pages" : "no huge pages" ); + } + } + /* It can't be 0 or I would have initialized it */ + MALLOC_ASSERT( mallocInitialized==2, ASSERT_TEXT ); +} + +/********* End library initialization *************/ + +/********* The malloc show begins *************/ + + +FreeObject *Block::allocateFromFreeList() +{ + FreeObject *result; + + if (!freeList) return NULL; + + result = freeList; + MALLOC_ASSERT( result, ASSERT_TEXT ); + + freeList = result->next; + MALLOC_ASSERT( allocatedCount < (blockSize-sizeof(Block))/objectSize, ASSERT_TEXT ); + allocatedCount++; + STAT_increment(owner, getIndex(objectSize), allocFreeListUsed); + + return result; +} + +FreeObject *Block::allocateFromBumpPtr() +{ + FreeObject *result = bumpPtr; + if (result) { + bumpPtr = (FreeObject *) ((uintptr_t) bumpPtr - objectSize); + if ( (uintptr_t)bumpPtr < (uintptr_t)this+sizeof(Block) ) { + bumpPtr = NULL; + } + MALLOC_ASSERT( allocatedCount < (blockSize-sizeof(Block))/objectSize, ASSERT_TEXT ); + allocatedCount++; + STAT_increment(owner, getIndex(objectSize), allocBumpPtrUsed); + } + return result; +} + +inline FreeObject* Block::allocate() +{ + MALLOC_ASSERT( owner.own(), ASSERT_TEXT ); + + /* for better cache locality, first looking in the free list. */ + if ( FreeObject *result = allocateFromFreeList() ) { + return result; + } + MALLOC_ASSERT( !freeList, ASSERT_TEXT ); + + /* if free list is empty, try thread local bump pointer allocation. */ + if ( FreeObject *result = allocateFromBumpPtr() ) { + return result; + } + MALLOC_ASSERT( !bumpPtr, ASSERT_TEXT ); + + /* the block is considered full. */ + isFull = 1; + return NULL; +} + +void Bin::moveBlockToBinFront(Block *block) +{ + /* move the block to the front of the bin */ + if (block == activeBlk) return; + outofTLSBin(block); + pushTLSBin(block); +} + +void Bin::processLessUsedBlock(MemoryPool *memPool, Block *block) +{ + if (block != activeBlk) { + /* We are not actively using this block; return it to the general block pool */ + outofTLSBin(block); + memPool->returnEmptyBlock(block, /*poolTheBlock=*/true); + } else { + /* all objects are free - let's restore the bump pointer */ + block->restoreBumpPtr(); + } +} + +#if USE_PTHREAD && (__TBB_SOURCE_DIRECTLY_INCLUDED || __TBB_USE_DLOPEN_REENTRANCY_WORKAROUND) + +/* Decrease race interval between dynamic library unloading and pthread key + destructor. Protect only Pthreads with supported unloading. */ +class ShutdownSync { +/* flag is the number of threads in pthread key dtor body + (i.e., between threadDtorStart() and threadDtorDone()) + or the signal to skip dtor, if flag < 0 */ + intptr_t flag; + static const intptr_t skipDtor = INTPTR_MIN/2; +public: +/* Suppose that 2*abs(skipDtor) or more threads never call threadExitStart() + simultaneously, so flag is never becomes negative because of that. */ + bool threadDtorStart() { + if (flag < 0) + return false; + if (AtomicIncrement(flag) <= 0) { // note that new value returned + AtomicAdd(flag, -1); // flag is spoiled by us, restore it + return false; + } + return true; + } + void threadDtorDone() { + AtomicAdd(flag, -1); + } + void processExit() { + if (AtomicAdd(flag, skipDtor) != 0) + SpinWaitUntilEq(flag, skipDtor); + } +}; + +#else + +class ShutdownSync { +public: + bool threadDtorStart() { return true; } + void threadDtorDone() { } + void processExit() { } +}; + +#endif // USE_PTHREAD && (__TBB_SOURCE_DIRECTLY_INCLUDED || __TBB_USE_DLOPEN_REENTRANCY_WORKAROUND) + +static ShutdownSync shutdownSync; + +/* + * All aligned allocations fall into one of the following categories: + * 1. if both request size and alignment are <= maxSegregatedObjectSize, + * we just align the size up, and request this amount, because for every size + * aligned to some power of 2, the allocated object is at least that aligned. + * 2. for size<minLargeObjectSize, check if already guaranteed fittingAlignment is enough. + * 3. if size+alignment<minLargeObjectSize, we take an object of fittingSizeN and align + * its address up; given such pointer, scalable_free could find the real object. + * Wrapping of size+alignment is impossible because maximal allowed + * alignment plus minLargeObjectSize can't lead to wrapping. + * 4. otherwise, aligned large object is allocated. + */ +static void *allocateAligned(MemoryPool *memPool, size_t size, size_t alignment) +{ + MALLOC_ASSERT( isPowerOfTwo(alignment), ASSERT_TEXT ); + + if (!isMallocInitialized()) doInitialization(); + + void *result; + if (size<=maxSegregatedObjectSize && alignment<=maxSegregatedObjectSize) + result = internalPoolMalloc(memPool, alignUp(size? size: sizeof(size_t), alignment)); + else if (size<minLargeObjectSize) { + if (alignment<=fittingAlignment) + result = internalPoolMalloc(memPool, size); + else if (size+alignment < minLargeObjectSize) { + void *unaligned = internalPoolMalloc(memPool, size+alignment); + if (!unaligned) return NULL; + result = alignUp(unaligned, alignment); + } else + goto LargeObjAlloc; + } else { + LargeObjAlloc: + /* This can be the first allocation call. */ + if (!isMallocInitialized()) + doInitialization(); + // take into account only alignment that are higher then natural + result = memPool->extMemPool.mallocLargeObject(size, + largeObjectAlignment>alignment? + largeObjectAlignment: alignment); + } + + MALLOC_ASSERT( isAligned(result, alignment), ASSERT_TEXT ); + return result; +} + +static void *reallocAligned(MemoryPool *memPool, void *ptr, + size_t size, size_t alignment = 0) +{ + void *result; + size_t copySize; + + if (isLargeObject(ptr)) { + LargeMemoryBlock* lmb = ((LargeObjectHdr *)ptr - 1)->memoryBlock; + copySize = lmb->unalignedSize-((uintptr_t)ptr-(uintptr_t)lmb); + if (size <= copySize && (0==alignment || isAligned(ptr, alignment))) { + lmb->objectSize = size; + return ptr; + } else { + copySize = lmb->objectSize; + result = alignment ? allocateAligned(memPool, size, alignment) : + internalPoolMalloc(memPool, size); + } + } else { + Block* block = (Block *)alignDown(ptr, blockSize); + copySize = block->getSize(); + if (size <= copySize && (0==alignment || isAligned(ptr, alignment))) { + return ptr; + } else { + result = alignment ? allocateAligned(memPool, size, alignment) : + internalPoolMalloc(memPool, size); + } + } + if (result) { + memcpy(result, ptr, copySize<size? copySize: size); + internalPoolFree(memPool, ptr); + } + return result; +} + +/* A predicate checks if an object is properly placed inside its block */ +inline bool Block::isProperlyPlaced(const void *object) const +{ + return 0 == ((uintptr_t)this + blockSize - (uintptr_t)object) % objectSize; +} + +/* Finds the real object inside the block */ +FreeObject *Block::findAllocatedObject(const void *address) const +{ + // calculate offset from the end of the block space + uint16_t offset = (uintptr_t)this + blockSize - (uintptr_t)address; + MALLOC_ASSERT( offset<=blockSize-sizeof(Block), ASSERT_TEXT ); + // find offset difference from a multiple of allocation size + offset %= objectSize; + // and move the address down to where the real object starts. + return (FreeObject*)((uintptr_t)address - (offset? objectSize-offset: 0)); +} + +/* + * Bad dereference caused by a foreign pointer is possible only here, not earlier in call chain. + * Separate function isolates SEH code, as it has bad influence on compiler optimization. + */ +static inline BackRefIdx safer_dereference (const BackRefIdx *ptr) +{ + BackRefIdx id; +#if _MSC_VER + __try { +#endif + id = *ptr; +#if _MSC_VER + } __except( GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION? + EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH ) { + id = BackRefIdx(); + } +#endif + return id; +} + +bool isLargeObject(void *object) +{ + if (!isAligned(object, largeObjectAlignment)) + return false; + LargeObjectHdr *header = (LargeObjectHdr*)object - 1; + BackRefIdx idx = safer_dereference(&header->backRefIdx); + + return idx.isLargeObject() + // in valid LargeObjectHdr memoryBlock points somewhere before header + // TODO: more strict check + && (uintptr_t)header->memoryBlock < (uintptr_t)header + && getBackRef(idx) == header; +} + +static inline bool isSmallObject (void *ptr) +{ + void* expected = alignDown(ptr, blockSize); + const BackRefIdx* idx = ((Block*)expected)->getBackRef(); + + return expected == getBackRef(safer_dereference(idx)); +} + +/**** Check if an object was allocated by scalable_malloc ****/ +static inline bool isRecognized (void* ptr) +{ + return isLargeObject(ptr) || isSmallObject(ptr); +} + +static inline void freeSmallObject(MemoryPool *memPool, void *object) +{ + /* mask low bits to get the block */ + Block *block = (Block *)alignDown(object, blockSize); + MALLOC_ASSERT( block->checkFreePrecond(object), + "Possible double free or heap corruption." ); + +#if MALLOC_CHECK_RECURSION + if (block->isStartupAllocObject()) { + ((StartupBlock *)block)->free(object); + return; + } +#endif + FreeObject *objectToFree = block->findObjectToFree(object); + + if (block->ownBlock()) + block->freeOwnObject(memPool, objectToFree); + else /* Slower path to add to the shared list, the allocatedCount is updated by the owner thread in malloc. */ + block->freePublicObject(objectToFree); + +} + +static void *internalPoolMalloc(MemoryPool* memPool, size_t size) +{ + Bin* bin; + Block * mallocBlock; + + if (!memPool) return NULL; + + if (!size) size = sizeof(size_t); + + /* + * Use Large Object Allocation + */ + if (size >= minLargeObjectSize) + return memPool->extMemPool.mallocLargeObject(size, largeObjectAlignment); + + /* + * Get an element in thread-local array corresponding to the given size; + * It keeps ptr to the active block for allocations of this size + */ + bin = memPool->getAllocationBin(size); + if ( !bin ) return NULL; + + /* Get a block to try to allocate in. */ + for( mallocBlock = bin->getActiveBlock(); mallocBlock; + mallocBlock = bin->setPreviousBlockActive() ) // the previous block should be empty enough + { + if( FreeObject *result = mallocBlock->allocate() ) + return result; + } + + /* + * else privatize publicly freed objects in some block and allocate from it + */ + mallocBlock = bin->getPublicFreeListBlock(); + if (mallocBlock) { + if (mallocBlock->emptyEnoughToUse()) { + bin->moveBlockToBinFront(mallocBlock); + } + MALLOC_ASSERT( mallocBlock->freeListNonNull(), ASSERT_TEXT ); + if ( FreeObject *result = mallocBlock->allocateFromFreeList() ) + return result; + /* Else something strange happened, need to retry from the beginning; */ + TRACEF(( "[ScalableMalloc trace] Something is wrong: no objects in public free list; reentering.\n" )); + return internalPoolMalloc(memPool, size); + } + + /* + * no suitable own blocks, try to get a partial block that some other thread has discarded. + */ + mallocBlock = memPool->orphanedBlocks.get(bin, size); + while (mallocBlock) { + bin->pushTLSBin(mallocBlock); + bin->setActiveBlock(mallocBlock); // TODO: move under the below condition? + if( FreeObject *result = mallocBlock->allocate() ) + return result; + mallocBlock = memPool->orphanedBlocks.get(bin, size); + } + + /* + * else try to get a new empty block + */ + mallocBlock = memPool->getEmptyBlock(size); + if (mallocBlock) { + bin->pushTLSBin(mallocBlock); + bin->setActiveBlock(mallocBlock); + if( FreeObject *result = mallocBlock->allocate() ) + return result; + /* Else something strange happened, need to retry from the beginning; */ + TRACEF(( "[ScalableMalloc trace] Something is wrong: no objects in empty block; reentering.\n" )); + return internalPoolMalloc(memPool, size); + } + /* + * else nothing works so return NULL + */ + TRACEF(( "[ScalableMalloc trace] No memory found, returning NULL.\n" )); + return NULL; +} + +static bool internalPoolFree(MemoryPool *memPool, void *object) +{ + if (!memPool || !object) return false; + + // The library is initialized at allocation call, so releasing while + // not initialized means foreign object is releasing. + MALLOC_ASSERT(isMallocInitialized(), ASSERT_TEXT); + MALLOC_ASSERT(memPool->extMemPool.userPool() || isRecognized(object), + "Invalid pointer in pool_free detected."); + if (isLargeObject(object)) + memPool->extMemPool.freeLargeObject(object); + else + freeSmallObject(memPool, object); + return true; +} + +static void *internalMalloc(size_t size) +{ + if (!size) size = sizeof(size_t); + +#if MALLOC_CHECK_RECURSION + if (RecursiveMallocCallProtector::sameThreadActive()) + return size<minLargeObjectSize? StartupBlock::allocate(size) : + (FreeObject*)defaultMemPool->extMemPool.mallocLargeObject(size, blockSize); +#endif + + if (!isMallocInitialized()) + doInitialization(); + + return internalPoolMalloc(defaultMemPool, size); +} + +static void internalFree(void *object) +{ + internalPoolFree(defaultMemPool, object); +} + +static size_t internalMsize(void* ptr) +{ + if (ptr) { + MALLOC_ASSERT(isRecognized(ptr), "Invalid pointer in scalable_msize detected."); + if (isLargeObject(ptr)) { + LargeMemoryBlock* lmb = ((LargeObjectHdr*)ptr - 1)->memoryBlock; + return lmb->objectSize; + } else { + Block* block = (Block *)alignDown(ptr, blockSize); +#if MALLOC_CHECK_RECURSION + size_t size = block->getSize()? block->getSize() : StartupBlock::msize(ptr); +#else + size_t size = block->getSize(); +#endif + MALLOC_ASSERT(size>0 && size<minLargeObjectSize, ASSERT_TEXT); + return size; + } + } + errno = EINVAL; + // Unlike _msize, return 0 in case of parameter error. + // Returning size_t(-1) looks more like the way to troubles. + return 0; +} + +} // namespace internal + +using namespace rml::internal; + +// legacy entry point saved for compatibility with binaries complied +// with pre-6003 versions of TBB +rml::MemoryPool *pool_create(intptr_t pool_id, const MemPoolPolicy *policy) +{ + rml::MemoryPool *pool; + MemPoolPolicy pol(policy->pAlloc, policy->pFree, policy->granularity); + + pool_create_v1(pool_id, &pol, &pool); + return pool; +} + +rml::MemPoolError pool_create_v1(intptr_t pool_id, const MemPoolPolicy *policy, + rml::MemoryPool **pool) +{ + if ( !policy->pAlloc || policy->version<MemPoolPolicy::VERSION + // empty pFree allowed only for fixed pools + || !(policy->fixedPool || policy->pFree) ) { + *pool = NULL; + return INVALID_POLICY; + } + if ( policy->version>MemPoolPolicy::VERSION // future versions are not supported + // new flags can be added in place of reserved, but default + // behaviour must be supported by this version + || policy->reserved ) { + *pool = NULL; + return UNSUPPORTED_POLICY; + } + if (!isMallocInitialized()) + doInitialization(); + + rml::internal::MemoryPool *memPool = + (rml::internal::MemoryPool*)internalMalloc((sizeof(rml::internal::MemoryPool))); + if (!memPool) { + *pool = NULL; + return NO_MEMORY; + } + memset(memPool, 0, sizeof(rml::internal::MemoryPool)); + if (!memPool->init(pool_id, policy)) { + internalFree(memPool); + *pool = NULL; + return NO_MEMORY; + } + + *pool = (rml::MemoryPool*)memPool; + return POOL_OK; +} + +bool pool_destroy(rml::MemoryPool* memPool) +{ + if (!memPool) return false; + ((rml::internal::MemoryPool*)memPool)->destroy(); + internalFree(memPool); + + return true; +} + +bool pool_reset(rml::MemoryPool* memPool) +{ + if (!memPool) return false; + + ((rml::internal::MemoryPool*)memPool)->reset(); + return true; +} + +void *pool_malloc(rml::MemoryPool* mPool, size_t size) +{ + return internalPoolMalloc((rml::internal::MemoryPool*)mPool, size); +} + +void *pool_realloc(rml::MemoryPool* mPool, void *object, size_t size) +{ + if (!object) + return internalPoolMalloc((rml::internal::MemoryPool*)mPool, size); + if (!size) { + internalPoolFree((rml::internal::MemoryPool*)mPool, object); + return NULL; + } + return reallocAligned((rml::internal::MemoryPool*)mPool, object, size, 0); +} + +void *pool_aligned_malloc(rml::MemoryPool* mPool, size_t size, size_t alignment) +{ + if (!isPowerOfTwo(alignment) || 0==size) + return NULL; + + return allocateAligned((rml::internal::MemoryPool*)mPool, size, alignment); +} + +void *pool_aligned_realloc(rml::MemoryPool* memPool, void *ptr, size_t size, size_t alignment) +{ + if (!isPowerOfTwo(alignment)) + return NULL; + rml::internal::MemoryPool *mPool = (rml::internal::MemoryPool*)memPool; + void *tmp; + + if (!ptr) + tmp = allocateAligned(mPool, size, alignment); + else if (!size) { + internalPoolFree(mPool, ptr); + return NULL; + } else + tmp = reallocAligned(mPool, ptr, size, alignment); + + return tmp; +} + +bool pool_free(rml::MemoryPool *mPool, void *object) +{ + return internalPoolFree((rml::internal::MemoryPool*)mPool, object); +} + +} // namespace rml + +using namespace rml::internal; + +/* + * When a thread is shutting down this routine should be called to remove all the thread ids + * from the malloc blocks and replace them with a NULL thread id. + * + */ +#if MALLOC_TRACE +static unsigned int threadGoingDownCount = 0; +#endif + +/* + * for pthreads, the function is set as a callback in pthread_key_create for TLS bin. + * it will be automatically called at thread exit with the key value as the argument. + * + * for Windows, it should be called directly e.g. from DllMain +*/ +void mallocThreadShutdownNotification(void* arg) +{ + // Check whether TLS has been initialized + if (!isMallocInitialized()) return; + + TRACEF(( "[ScalableMalloc trace] Thread id %d blocks return start %d\n", + getThreadId(), threadGoingDownCount++ )); +#if USE_WINTHREAD + MallocMutex::scoped_lock lock(MemoryPool::memPoolListLock); + // The routine is called once per thread, need to walk through all pools on Windows + for (MemoryPool *memPool = defaultMemPool; memPool; memPool = memPool->next) { + TLSData *tls = memPool->extMemPool.getTLS(); +#else + if (!shutdownSync.threadDtorStart()) return; + // The routine is called for each memPool, just need to get memPool from TLSData. + TLSData *tls = (TLSData*)arg; + MemoryPool *memPool = tls->getMemPool(); +#endif + if (tls) { + tls->release(memPool); + memPool->bootStrapBlocks.free(tls); + memPool->extMemPool.clearTLS(); + } +#if USE_WINTHREAD + } // for memPool (Windows only) +#else + shutdownSync.threadDtorDone(); +#endif + + TRACEF(( "[ScalableMalloc trace] Thread id %d blocks return end\n", getThreadId() )); +} + +#if USE_WINTHREAD +extern "C" void __TBB_mallocThreadShutdownNotification() +{ + mallocThreadShutdownNotification(NULL); +} +#endif + +extern "C" void __TBB_mallocProcessShutdownNotification() +{ + if (!isMallocInitialized()) return; + + shutdownSync.processExit(); +#if __TBB_SOURCE_DIRECTLY_INCLUDED +/* Pthread keys must be deleted as soon as possible to not call key dtor + on thread termination when then the tbbmalloc code can be already unloaded. +*/ + defaultMemPool->destroy(); + destroyBackRefMaster(&defaultMemPool->extMemPool.backend); + ThreadId::destroy(); // Delete key for thread id +#elif __TBB_USE_DLOPEN_REENTRANCY_WORKAROUND +/* In most cases we prevent unloading tbbmalloc, and don't clean up memory + on process shutdown. When impossible to prevent, library unload results + in shutdown notification, and it makes sense to release unused memory + at that point (we can't release all memory because it's possible that + it will be accessed after this point). + TODO: better support systems where we can't prevent unloading by removing + pthread destructors and releasing caches. + */ + defaultMemPool->extMemPool.hardCachesCleanup(); +#endif // __TBB_SOURCE_DIRECTLY_INCLUDED + +#if COLLECT_STATISTICS + ThreadId nThreads = ThreadIdCount; + for( int i=1; i<=nThreads && i<MAX_THREADS; ++i ) + STAT_print(i); +#endif +} + +extern "C" void * scalable_malloc(size_t size) +{ + void *ptr = internalMalloc(size); + if (!ptr) errno = ENOMEM; + return ptr; +} + +extern "C" void scalable_free (void *object) { + internalFree(object); +} + +/* + * A variant that provides additional memory safety, by checking whether the given address + * was obtained with this allocator, and if not redirecting to the provided alternative call. + */ +extern "C" void safer_scalable_free (void *object, void (*original_free)(void*)) +{ + if (!object) + return; + + // must check 1st for large object, because small object check touches 4 pages on left, + // and it can be unaccessable + if (isLargeObject(object)) + defaultMemPool->extMemPool.freeLargeObject(object); + else if (isSmallObject(object)) + freeSmallObject(defaultMemPool, object); + else if (original_free) + original_free(object); +} + +/********* End the free code *************/ + +/********* Code for scalable_realloc ***********/ + +/* + * From K&R + * "realloc changes the size of the object pointed to by p to size. The contents will + * be unchanged up to the minimum of the old and the new sizes. If the new size is larger, + * the new space is uninitialized. realloc returns a pointer to the new space, or + * NULL if the request cannot be satisfied, in which case *p is unchanged." + * + */ +extern "C" void* scalable_realloc(void* ptr, size_t size) +{ + void *tmp; + + if (!ptr) + tmp = internalMalloc(size); + else if (!size) { + internalFree(ptr); + return NULL; + } else + tmp = reallocAligned(defaultMemPool, ptr, size, 0); + + if (!tmp) errno = ENOMEM; + return tmp; +} + +/* + * A variant that provides additional memory safety, by checking whether the given address + * was obtained with this allocator, and if not redirecting to the provided alternative call. + */ +extern "C" void* safer_scalable_realloc (void* ptr, size_t sz, void* original_realloc) +{ + void *tmp; // TODO: fix warnings about uninitialized use of tmp + + if (!ptr) { + tmp = internalMalloc(sz); + } else if (isRecognized(ptr)) { + if (!sz) { + internalFree(ptr); + return NULL; + } else { + tmp = reallocAligned(defaultMemPool, ptr, sz, 0); + } + } +#if USE_WINTHREAD + else if (original_realloc && sz) { + orig_ptrs *original_ptrs = static_cast<orig_ptrs*>(original_realloc); + if ( original_ptrs->orig_msize ){ + size_t oldSize = original_ptrs->orig_msize(ptr); + tmp = internalMalloc(sz); + if (tmp) { + memcpy(tmp, ptr, sz<oldSize? sz : oldSize); + if ( original_ptrs->orig_free ){ + original_ptrs->orig_free( ptr ); + } + } + } else + tmp = NULL; + } +#else + else if (original_realloc) { + typedef void* (*realloc_ptr_t)(void*,size_t); + realloc_ptr_t original_realloc_ptr; + (void *&)original_realloc_ptr = original_realloc; + tmp = original_realloc_ptr(ptr,sz); + } +#endif + else tmp = NULL; + + if (!tmp) errno = ENOMEM; + return tmp; +} + +/********* End code for scalable_realloc ***********/ + +/********* Code for scalable_calloc ***********/ + +/* + * From K&R + * calloc returns a pointer to space for an array of nobj objects, + * each of size size, or NULL if the request cannot be satisfied. + * The space is initialized to zero bytes. + * + */ + +extern "C" void * scalable_calloc(size_t nobj, size_t size) +{ + size_t arraySize = nobj * size; + void* result = internalMalloc(arraySize); + if (result) + memset(result, 0, arraySize); + else + errno = ENOMEM; + return result; +} + +/********* End code for scalable_calloc ***********/ + +/********* Code for aligned allocation API **********/ + +extern "C" int scalable_posix_memalign(void **memptr, size_t alignment, size_t size) +{ + if ( !isPowerOfTwoMultiple(alignment, sizeof(void*)) ) + return EINVAL; + void *result = allocateAligned(defaultMemPool, size, alignment); + if (!result) + return ENOMEM; + *memptr = result; + return 0; +} + +extern "C" void * scalable_aligned_malloc(size_t size, size_t alignment) +{ + if (!isPowerOfTwo(alignment) || 0==size) { + errno = EINVAL; + return NULL; + } + void *tmp = allocateAligned(defaultMemPool, size, alignment); + if (!tmp) errno = ENOMEM; + return tmp; +} + +extern "C" void * scalable_aligned_realloc(void *ptr, size_t size, size_t alignment) +{ + if (!isPowerOfTwo(alignment)) { + errno = EINVAL; + return NULL; + } + void *tmp; + + if (!ptr) + tmp = allocateAligned(defaultMemPool, size, alignment); + else if (!size) { + scalable_free(ptr); + return NULL; + } else + tmp = reallocAligned(defaultMemPool, ptr, size, alignment); + + if (!tmp) errno = ENOMEM; + return tmp; +} + +extern "C" void * safer_scalable_aligned_realloc(void *ptr, size_t size, size_t alignment, void* orig_function) +{ + /* corner cases left out of reallocAligned to not deal with errno there */ + if (!isPowerOfTwo(alignment)) { + errno = EINVAL; + return NULL; + } + void *tmp; + + if (!ptr) { + tmp = allocateAligned(defaultMemPool, size, alignment); + } else if (isRecognized(ptr)) { + if (!size) { + internalFree(ptr); + return NULL; + } else { + tmp = reallocAligned(defaultMemPool, ptr, size, alignment); + } + } +#if USE_WINTHREAD + else { + orig_ptrs *original_ptrs = static_cast<orig_ptrs*>(orig_function); + if (size) { + // Without orig_msize, we can't do anything with this. + // Just keeping old pointer. + if ( original_ptrs->orig_msize ){ + size_t oldSize = original_ptrs->orig_msize(ptr); + tmp = allocateAligned(defaultMemPool, size, alignment); + if (tmp) { + memcpy(tmp, ptr, size<oldSize? size : oldSize); + if ( original_ptrs->orig_free ){ + original_ptrs->orig_free( ptr ); + } + } + } else + tmp = NULL; + } else { + if ( original_ptrs->orig_free ){ + original_ptrs->orig_free( ptr ); + } + return NULL; + } + } +#endif + suppress_unused_warning(orig_function); + if (!tmp) errno = ENOMEM; + return tmp; +} + +extern "C" void scalable_aligned_free(void *ptr) +{ + internalFree(ptr); +} + +/********* end code for aligned allocation API **********/ + +/********* Code for scalable_msize ***********/ + +/* + * Returns the size of a memory block allocated in the heap. + */ +extern "C" size_t scalable_msize(void* ptr) +{ + return internalMsize(ptr); +} + +/* + * A variant that provides additional memory safety, by checking whether the given address + * was obtained with this allocator, and if not redirecting to the provided alternative call. + */ +extern "C" size_t safer_scalable_msize (void *object, size_t (*original_msize)(void*)) +{ + if (object) { + // Check if the memory was allocated by scalable_malloc + if (isRecognized(object)) + return internalMsize(object); + else if (original_msize) + return original_msize(object); + } + // object is NULL or unknown + errno = EINVAL; + return 0; +} + +/********* End code for scalable_msize ***********/ diff --git a/src/tbb/src/tbbmalloc/large_objects.cpp b/src/tbb/src/tbbmalloc/large_objects.cpp new file mode 100644 index 0000000..b07ee5b --- /dev/null +++ b/src/tbb/src/tbbmalloc/large_objects.cpp @@ -0,0 +1,281 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbbmalloc_internal.h" + +/********* Allocation of large objects ************/ + + +namespace rml { +namespace internal { + +static struct LargeBlockCacheStat { + uintptr_t age; +} loCacheStat; + +bool LargeObjectCache::CacheBin::put(ExtMemoryPool *extMemPool, + LargeMemoryBlock *ptr) +{ + bool blockCached = true; + ptr->prev = NULL; + ptr->age = extMemPool->loc.cleanupCacheIfNeed(extMemPool); + + { + MallocMutex::scoped_lock scoped_cs(lock); + if (lastCleanedAge) { + ptr->next = first; + first = ptr; + if (ptr->next) ptr->next->prev = ptr; + if (!last) { + MALLOC_ASSERT(0 == oldest, ASSERT_TEXT); + oldest = ptr->age; + last = ptr; + } + } else { + // 1st object of such size was released. + // Not cache it, and remeber when this occurs + // to take into account during cache miss. + lastCleanedAge = ptr->age; + blockCached = false; + } + } + return blockCached; +} + +LargeMemoryBlock *LargeObjectCache::CacheBin::get(ExtMemoryPool *extMemPool, + size_t size) +{ + uintptr_t currAge = extMemPool->loc.cleanupCacheIfNeed(extMemPool); + LargeMemoryBlock *result=NULL; + { + MallocMutex::scoped_lock scoped_cs(lock); + if (first) { + result = first; + first = result->next; + if (first) + first->prev = NULL; + else { + last = NULL; + oldest = 0; + } + } else { + /* If cache miss occured, set ageThreshold to twice the difference + between current time and last time cache was cleaned. */ + ageThreshold = 2*(currAge - lastCleanedAge); + } + } + return result; +} + +bool LargeObjectCache::CacheBin::cleanToThreshold(ExtMemoryPool *extMemPool, + uintptr_t currAge) +{ + LargeMemoryBlock *toRelease = NULL; + bool released = false; + + /* oldest may be more recent then age, that's why cast to signed type + was used. age overflow is also processed correctly. */ + if (last && (intptr_t)(currAge - oldest) > ageThreshold) { + MallocMutex::scoped_lock scoped_cs(lock); + // double check + if (last && (intptr_t)(currAge - last->age) > ageThreshold) { + do { + last = last->prev; + } while (last && (intptr_t)(currAge - last->age) > ageThreshold); + if (last) { + toRelease = last->next; + oldest = last->age; + last->next = NULL; + } else { + toRelease = first; + first = NULL; + oldest = 0; + } + MALLOC_ASSERT( toRelease, ASSERT_TEXT ); + lastCleanedAge = toRelease->age; + } + else + return false; + } + released = toRelease; + + while ( toRelease ) { + LargeMemoryBlock *helper = toRelease->next; + removeBackRef(toRelease->backRefIdx); + extMemPool->backend.putLargeBlock(toRelease); + toRelease = helper; + } + return released; +} + +bool LargeObjectCache::CacheBin::cleanAll(ExtMemoryPool *extMemPool) +{ + LargeMemoryBlock *toRelease = NULL; + bool released = false; + + if (last) { + MallocMutex::scoped_lock scoped_cs(lock); + // double check + if (last) { + toRelease = first; + last = NULL; + first = NULL; + oldest = 0; + } + else + return false; + } + released = toRelease; + + while ( toRelease ) { + LargeMemoryBlock *helper = toRelease->next; + removeBackRef(toRelease->backRefIdx); + extMemPool->backend.putLargeBlock(toRelease); + toRelease = helper; + } + return released; +} + +// release from cache blocks that are older than ageThreshold +bool LargeObjectCache::regularCleanup(ExtMemoryPool *extMemPool, uintptr_t currAge) +{ + bool released = false; + + for (int i = numLargeBlockBins-1; i >= 0; i--) + if (bin[i].cleanToThreshold(extMemPool, currAge)) + released = true; + return released; +} + +bool ExtMemoryPool::softCachesCleanup() +{ + // TODO: cleanup small objects as well + return loc.regularCleanup(this, FencedLoad((intptr_t&)loCacheStat.age)); +} + +uintptr_t LargeObjectCache::cleanupCacheIfNeed(ExtMemoryPool *extMemPool) +{ + /* loCacheStat.age overflow is OK, as we only want difference between + * its current value and some recent. + * + * Both malloc and free should increment loCacheStat.age, as in + * a different case multiple cached blocks would have same age, + * and accuracy of predictors suffers. + */ + uintptr_t currAge = (uintptr_t)AtomicIncrement((intptr_t&)loCacheStat.age); + + if ( 0 == currAge % cacheCleanupFreq ) + regularCleanup(extMemPool, currAge); + + return currAge; +} + +LargeMemoryBlock *LargeObjectCache::get(ExtMemoryPool *extMemPool, size_t size) +{ + MALLOC_ASSERT( size%largeBlockCacheStep==0, ASSERT_TEXT ); + LargeMemoryBlock *lmb = NULL; + size_t idx = sizeToIdx(size); + if (idx<numLargeBlockBins) { + lmb = bin[idx].get(extMemPool, size); + if (lmb) { + MALLOC_ITT_SYNC_ACQUIRED(bin+idx); + STAT_increment(getThreadId(), ThreadCommonCounters, allocCachedLargeBlk); + } + } + return lmb; +} + +void *ExtMemoryPool::mallocLargeObject(size_t size, size_t alignment) +{ + size_t headersSize = sizeof(LargeMemoryBlock)+sizeof(LargeObjectHdr); + // TODO: take into account that they are already largeObjectAlignment-aligned + size_t allocationSize = alignUp(size+headersSize+alignment, largeBlockCacheStep); + + if (allocationSize < size) // allocationSize is wrapped around after alignUp + return NULL; + + LargeMemoryBlock* lmb = loc.get(this, allocationSize); + if (!lmb) { + BackRefIdx backRefIdx = BackRefIdx::newBackRef(/*largeObj=*/true); + if (backRefIdx.isInvalid()) + return NULL; + + // unalignedSize is set in getLargeBlock + lmb = backend.getLargeBlock(allocationSize); + if (!lmb) { + removeBackRef(backRefIdx); + return NULL; + } + lmb->backRefIdx = backRefIdx; + STAT_increment(getThreadId(), ThreadCommonCounters, allocNewLargeObj); + } + + void *alignedArea = (void*)alignUp((uintptr_t)lmb+headersSize, alignment); + LargeObjectHdr *header = (LargeObjectHdr*)alignedArea-1; + header->memoryBlock = lmb; + header->backRefIdx = lmb->backRefIdx; + setBackRef(header->backRefIdx, header); + + lmb->objectSize = size; + + MALLOC_ASSERT( isLargeObject(alignedArea), ASSERT_TEXT ); + return alignedArea; +} + +bool LargeObjectCache::put(ExtMemoryPool *extMemPool, LargeMemoryBlock *largeBlock) +{ + size_t idx = sizeToIdx(largeBlock->unalignedSize); + if (idx<numLargeBlockBins) { + MALLOC_ITT_SYNC_RELEASING(bin+idx); + if (bin[idx].put(extMemPool, largeBlock)) { + STAT_increment(getThreadId(), ThreadCommonCounters, cacheLargeBlk); + return true; + } else + return false; + } + return false; +} + +void ExtMemoryPool::freeLargeObject(void *object) +{ + LargeObjectHdr *header = (LargeObjectHdr*)object - 1; + + // overwrite backRefIdx to simplify double free detection + header->backRefIdx = BackRefIdx(); + if (!loc.put(this, header->memoryBlock)) { + removeBackRef(header->memoryBlock->backRefIdx); + backend.putLargeBlock(header->memoryBlock); + STAT_increment(getThreadId(), ThreadCommonCounters, freeLargeObj); + } +} + +/*********** End allocation of large objects **********/ + +} // namespace internal +} // namespace rml + diff --git a/src/tbb/src/tbbmalloc/lin32-proxy-export.def b/src/tbb/src/tbbmalloc/lin32-proxy-export.def new file mode 100644 index 0000000..a1e3937 --- /dev/null +++ b/src/tbb/src/tbbmalloc/lin32-proxy-export.def @@ -0,0 +1,59 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +{ +global: +calloc; +free; +malloc; +realloc; +posix_memalign; +memalign; +valloc; +pvalloc; +mallinfo; +mallopt; +__TBB_malloc_proxy; +__TBB_internal_find_original_malloc; +_ZdaPv; /* next ones are new/delete */ +_ZdaPvRKSt9nothrow_t; +_ZdlPv; +_ZdlPvRKSt9nothrow_t; +_Znaj; +_ZnajRKSt9nothrow_t; +_Znwj; +_ZnwjRKSt9nothrow_t; + +local: + +/* TBB symbols */ +*3rml8internal*; +*3tbb*; +*__TBB*; + +}; diff --git a/src/tbb/src/tbbmalloc/lin32-tbbmalloc-export.def b/src/tbb/src/tbbmalloc/lin32-tbbmalloc-export.def new file mode 100644 index 0000000..f2fc293 --- /dev/null +++ b/src/tbb/src/tbbmalloc/lin32-tbbmalloc-export.def @@ -0,0 +1,80 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +{ +global: + +scalable_calloc; +scalable_free; +scalable_malloc; +scalable_realloc; +scalable_posix_memalign; +scalable_aligned_malloc; +scalable_aligned_realloc; +scalable_aligned_free; +__TBB_internal_calloc; +__TBB_internal_free; +__TBB_internal_malloc; +__TBB_internal_realloc; +__TBB_internal_posix_memalign; +scalable_msize; +/* memory pool stuff */ +_ZN3rml10pool_resetEPNS_10MemoryPoolE; +_ZN3rml11pool_createEiPKNS_13MemPoolPolicyE; +_ZN3rml14pool_create_v1EiPKNS_13MemPoolPolicyEPPNS_10MemoryPoolE; +_ZN3rml11pool_mallocEPNS_10MemoryPoolEj; +_ZN3rml12pool_destroyEPNS_10MemoryPoolE; +_ZN3rml9pool_freeEPNS_10MemoryPoolEPv; +_ZN3rml12pool_reallocEPNS_10MemoryPoolEPvj; +_ZN3rml20pool_aligned_reallocEPNS_10MemoryPoolEPvjj; +_ZN3rml19pool_aligned_mallocEPNS_10MemoryPoolEjj; + +local: + +/* TBB symbols */ +*3rml*; +*3tbb*; +*__TBB*; +__itt_*; +ITT_DoOneTimeInitialization; +TBB_runtime_interface_version; + +/* Intel Compiler (libirc) symbols */ +__intel_*; +_intel_*; +get_memcpy_largest_cachelinesize; +get_memcpy_largest_cache_size; +get_mem_ops_method; +init_mem_ops_method; +irc__get_msg; +irc__print; +override_mem_ops_method; +set_memcpy_largest_cachelinesize; +set_memcpy_largest_cache_size; + +}; diff --git a/src/tbb/src/tbbmalloc/lin64-proxy-export.def b/src/tbb/src/tbbmalloc/lin64-proxy-export.def new file mode 100644 index 0000000..f14eba8 --- /dev/null +++ b/src/tbb/src/tbbmalloc/lin64-proxy-export.def @@ -0,0 +1,59 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +{ +global: +calloc; +free; +malloc; +realloc; +posix_memalign; +memalign; +valloc; +pvalloc; +mallinfo; +mallopt; +__TBB_malloc_proxy; +__TBB_internal_find_original_malloc; +_ZdaPv; /* next ones are new/delete */ +_ZdaPvRKSt9nothrow_t; +_ZdlPv; +_ZdlPvRKSt9nothrow_t; +_Znam; +_ZnamRKSt9nothrow_t; +_Znwm; +_ZnwmRKSt9nothrow_t; + +local: + +/* TBB symbols */ +*3rml8internal*; +*3tbb*; +*__TBB*; + +}; diff --git a/src/tbb/src/tbbmalloc/lin64-tbbmalloc-export.def b/src/tbb/src/tbbmalloc/lin64-tbbmalloc-export.def new file mode 100644 index 0000000..2c8c885 --- /dev/null +++ b/src/tbb/src/tbbmalloc/lin64-tbbmalloc-export.def @@ -0,0 +1,80 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +{ +global: + +scalable_calloc; +scalable_free; +scalable_malloc; +scalable_realloc; +scalable_posix_memalign; +scalable_aligned_malloc; +scalable_aligned_realloc; +scalable_aligned_free; +__TBB_internal_calloc; +__TBB_internal_free; +__TBB_internal_malloc; +__TBB_internal_realloc; +__TBB_internal_posix_memalign; +scalable_msize; +/* memory pool stuff */ +_ZN3rml11pool_createElPKNS_13MemPoolPolicyE; +_ZN3rml14pool_create_v1ElPKNS_13MemPoolPolicyEPPNS_10MemoryPoolE; +_ZN3rml10pool_resetEPNS_10MemoryPoolE; +_ZN3rml11pool_mallocEPNS_10MemoryPoolEm; +_ZN3rml12pool_destroyEPNS_10MemoryPoolE; +_ZN3rml9pool_freeEPNS_10MemoryPoolEPv; +_ZN3rml12pool_reallocEPNS_10MemoryPoolEPvm; +_ZN3rml20pool_aligned_reallocEPNS_10MemoryPoolEPvmm; +_ZN3rml19pool_aligned_mallocEPNS_10MemoryPoolEmm; + +local: + +/* TBB symbols */ +*3rml*; +*3tbb*; +*__TBB*; +__itt_*; +ITT_DoOneTimeInitialization; +TBB_runtime_interface_version; + +/* Intel Compiler (libirc) symbols */ +__intel_*; +_intel_*; +get_memcpy_largest_cachelinesize; +get_memcpy_largest_cache_size; +get_mem_ops_method; +init_mem_ops_method; +irc__get_msg; +irc__print; +override_mem_ops_method; +set_memcpy_largest_cachelinesize; +set_memcpy_largest_cache_size; + +}; diff --git a/src/tbb/src/tbbmalloc/lin64ipf-proxy-export.def b/src/tbb/src/tbbmalloc/lin64ipf-proxy-export.def new file mode 100644 index 0000000..f14eba8 --- /dev/null +++ b/src/tbb/src/tbbmalloc/lin64ipf-proxy-export.def @@ -0,0 +1,59 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +{ +global: +calloc; +free; +malloc; +realloc; +posix_memalign; +memalign; +valloc; +pvalloc; +mallinfo; +mallopt; +__TBB_malloc_proxy; +__TBB_internal_find_original_malloc; +_ZdaPv; /* next ones are new/delete */ +_ZdaPvRKSt9nothrow_t; +_ZdlPv; +_ZdlPvRKSt9nothrow_t; +_Znam; +_ZnamRKSt9nothrow_t; +_Znwm; +_ZnwmRKSt9nothrow_t; + +local: + +/* TBB symbols */ +*3rml8internal*; +*3tbb*; +*__TBB*; + +}; diff --git a/src/tbb/src/tbbmalloc/lin64ipf-tbbmalloc-export.def b/src/tbb/src/tbbmalloc/lin64ipf-tbbmalloc-export.def new file mode 100644 index 0000000..2c8c885 --- /dev/null +++ b/src/tbb/src/tbbmalloc/lin64ipf-tbbmalloc-export.def @@ -0,0 +1,80 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +{ +global: + +scalable_calloc; +scalable_free; +scalable_malloc; +scalable_realloc; +scalable_posix_memalign; +scalable_aligned_malloc; +scalable_aligned_realloc; +scalable_aligned_free; +__TBB_internal_calloc; +__TBB_internal_free; +__TBB_internal_malloc; +__TBB_internal_realloc; +__TBB_internal_posix_memalign; +scalable_msize; +/* memory pool stuff */ +_ZN3rml11pool_createElPKNS_13MemPoolPolicyE; +_ZN3rml14pool_create_v1ElPKNS_13MemPoolPolicyEPPNS_10MemoryPoolE; +_ZN3rml10pool_resetEPNS_10MemoryPoolE; +_ZN3rml11pool_mallocEPNS_10MemoryPoolEm; +_ZN3rml12pool_destroyEPNS_10MemoryPoolE; +_ZN3rml9pool_freeEPNS_10MemoryPoolEPv; +_ZN3rml12pool_reallocEPNS_10MemoryPoolEPvm; +_ZN3rml20pool_aligned_reallocEPNS_10MemoryPoolEPvmm; +_ZN3rml19pool_aligned_mallocEPNS_10MemoryPoolEmm; + +local: + +/* TBB symbols */ +*3rml*; +*3tbb*; +*__TBB*; +__itt_*; +ITT_DoOneTimeInitialization; +TBB_runtime_interface_version; + +/* Intel Compiler (libirc) symbols */ +__intel_*; +_intel_*; +get_memcpy_largest_cachelinesize; +get_memcpy_largest_cache_size; +get_mem_ops_method; +init_mem_ops_method; +irc__get_msg; +irc__print; +override_mem_ops_method; +set_memcpy_largest_cachelinesize; +set_memcpy_largest_cache_size; + +}; diff --git a/src/tbb/src/tbbmalloc/mac32-tbbmalloc-export.def b/src/tbb/src/tbbmalloc/mac32-tbbmalloc-export.def new file mode 100644 index 0000000..0a66a5b --- /dev/null +++ b/src/tbb/src/tbbmalloc/mac32-tbbmalloc-export.def @@ -0,0 +1,39 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + The source code contained or described herein and all documents related + to the source code ("Material") are owned by Intel Corporation or its + suppliers or licensors. Title to the Material remains with Intel + Corporation or its suppliers and licensors. The Material is protected + by worldwide copyright laws and treaty provisions. No part of the + Material may be used, copied, reproduced, modified, published, uploaded, + posted, transmitted, distributed, or disclosed in any way without + Intel's prior express written permission. + + No license under any patent, copyright, trade secret or other + intellectual property right is granted to or conferred upon you by + disclosure or delivery of the Materials, either expressly, by + implication, inducement, estoppel or otherwise. Any license under such + intellectual property rights must be express and approved by Intel in + writing. +*/ + +_scalable_calloc +_scalable_free +_scalable_malloc +_scalable_realloc +_scalable_posix_memalign +_scalable_aligned_malloc +_scalable_aligned_realloc +_scalable_aligned_free +_scalable_msize +/* memory pool stuff */ +__ZN3rml11pool_createElPKNS_13MemPoolPolicyE +__ZN3rml14pool_create_v1ElPKNS_13MemPoolPolicyEPPNS_10MemoryPoolE +__ZN3rml10pool_resetEPNS_10MemoryPoolE +__ZN3rml12pool_destroyEPNS_10MemoryPoolE +__ZN3rml11pool_mallocEPNS_10MemoryPoolEm +__ZN3rml9pool_freeEPNS_10MemoryPoolEPv +__ZN3rml12pool_reallocEPNS_10MemoryPoolEPvm +__ZN3rml20pool_aligned_reallocEPNS_10MemoryPoolEPvmm +__ZN3rml19pool_aligned_mallocEPNS_10MemoryPoolEmm diff --git a/src/tbb/src/tbbmalloc/mac64-tbbmalloc-export.def b/src/tbb/src/tbbmalloc/mac64-tbbmalloc-export.def new file mode 100644 index 0000000..0a66a5b --- /dev/null +++ b/src/tbb/src/tbbmalloc/mac64-tbbmalloc-export.def @@ -0,0 +1,39 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + The source code contained or described herein and all documents related + to the source code ("Material") are owned by Intel Corporation or its + suppliers or licensors. Title to the Material remains with Intel + Corporation or its suppliers and licensors. The Material is protected + by worldwide copyright laws and treaty provisions. No part of the + Material may be used, copied, reproduced, modified, published, uploaded, + posted, transmitted, distributed, or disclosed in any way without + Intel's prior express written permission. + + No license under any patent, copyright, trade secret or other + intellectual property right is granted to or conferred upon you by + disclosure or delivery of the Materials, either expressly, by + implication, inducement, estoppel or otherwise. Any license under such + intellectual property rights must be express and approved by Intel in + writing. +*/ + +_scalable_calloc +_scalable_free +_scalable_malloc +_scalable_realloc +_scalable_posix_memalign +_scalable_aligned_malloc +_scalable_aligned_realloc +_scalable_aligned_free +_scalable_msize +/* memory pool stuff */ +__ZN3rml11pool_createElPKNS_13MemPoolPolicyE +__ZN3rml14pool_create_v1ElPKNS_13MemPoolPolicyEPPNS_10MemoryPoolE +__ZN3rml10pool_resetEPNS_10MemoryPoolE +__ZN3rml12pool_destroyEPNS_10MemoryPoolE +__ZN3rml11pool_mallocEPNS_10MemoryPoolEm +__ZN3rml9pool_freeEPNS_10MemoryPoolEPv +__ZN3rml12pool_reallocEPNS_10MemoryPoolEPvm +__ZN3rml20pool_aligned_reallocEPNS_10MemoryPoolEPvmm +__ZN3rml19pool_aligned_mallocEPNS_10MemoryPoolEmm diff --git a/src/tbb/src/tbbmalloc/proxy.cpp b/src/tbb/src/tbbmalloc/proxy.cpp new file mode 100644 index 0000000..7687432 --- /dev/null +++ b/src/tbb/src/tbbmalloc/proxy.cpp @@ -0,0 +1,482 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "proxy.h" + +#if !defined(__EXCEPTIONS) && !defined(_CPPUNWIND) && !defined(__SUNPRO_CC) || defined(_XBOX) + #if TBB_USE_EXCEPTIONS + #error Compilation settings do not support exception handling. Please do not set TBB_USE_EXCEPTIONS macro or set it to 0. + #elif !defined(TBB_USE_EXCEPTIONS) + #define TBB_USE_EXCEPTIONS 0 + #endif +#elif !defined(TBB_USE_EXCEPTIONS) + #define TBB_USE_EXCEPTIONS 1 +#endif + +#if MALLOC_LD_PRELOAD + +/*** service functions and variables ***/ + +#include <unistd.h> // for sysconf +#include <dlfcn.h> + +static long memoryPageSize; + +static inline void initPageSize() +{ + memoryPageSize = sysconf(_SC_PAGESIZE); +} + +/* For the expected behaviour (i.e., finding malloc/free/etc from libc.so, + not from ld-linux.so) dlsym(RTLD_NEXT) should be called from + a LD_PRELOADed library, not another dynamic library. + So we have to put find_original_malloc here. + */ +extern "C" bool __TBB_internal_find_original_malloc(int num, const char *names[], + void *ptrs[]) +{ + for (int i=0; i<num; i++) + if (NULL == (ptrs[i] = dlsym (RTLD_NEXT, names[i]))) + return false; + + return true; +} + +/* __TBB_malloc_proxy used as a weak symbol by libtbbmalloc for: + 1) detection that the proxy library is loaded + 2) check that dlsym("malloc") found something different from our replacement malloc +*/ +extern "C" void *__TBB_malloc_proxy() __attribute__ ((alias ("malloc"))); + +#ifndef __THROW +#define __THROW +#endif + +/*** replacements for malloc and the family ***/ + +extern "C" { + +void *malloc(size_t size) __THROW +{ + return __TBB_internal_malloc(size); +} + +void * calloc(size_t num, size_t size) __THROW +{ + return __TBB_internal_calloc(num, size); +} + +void free(void *object) __THROW +{ + __TBB_internal_free(object); +} + +void * realloc(void* ptr, size_t sz) __THROW +{ + return __TBB_internal_realloc(ptr, sz); +} + +int posix_memalign(void **memptr, size_t alignment, size_t size) __THROW +{ + return __TBB_internal_posix_memalign(memptr, alignment, size); +} + +/* The older *NIX interface for aligned allocations; + it's formally substituted by posix_memalign and deprecated, + so we do not expect it to cause cyclic dependency with C RTL. */ +void * memalign(size_t alignment, size_t size) __THROW +{ + return scalable_aligned_malloc(size, alignment); +} + +/* valloc allocates memory aligned on a page boundary */ +void * valloc(size_t size) __THROW +{ + if (! memoryPageSize) initPageSize(); + + return scalable_aligned_malloc(size, memoryPageSize); +} + +/* pvalloc allocates smallest set of complete pages which can hold + the requested number of bytes. Result is aligned on page boundary. */ +void * pvalloc(size_t size) __THROW +{ + if (! memoryPageSize) initPageSize(); + // align size up to the page size + size = ((size-1) | (memoryPageSize-1)) + 1; + + return scalable_aligned_malloc(size, memoryPageSize); +} + +int mallopt(int /*param*/, int /*value*/) __THROW +{ + return 1; +} + +} /* extern "C" */ + +#if __linux__ +#include <malloc.h> +#include <string.h> // for memset + +extern "C" struct mallinfo mallinfo() __THROW +{ + struct mallinfo m; + memset(&m, 0, sizeof(struct mallinfo)); + + return m; +} +#endif /* __linux__ */ + +/*** replacements for global operators new and delete ***/ + +#include <new> + +void * operator new(size_t sz) throw (std::bad_alloc) { + void *res = scalable_malloc(sz); +#if TBB_USE_EXCEPTIONS + if (NULL == res) + throw std::bad_alloc(); +#endif /* TBB_USE_EXCEPTIONS */ + return res; +} +void* operator new[](size_t sz) throw (std::bad_alloc) { + void *res = scalable_malloc(sz); +#if TBB_USE_EXCEPTIONS + if (NULL == res) + throw std::bad_alloc(); +#endif /* TBB_USE_EXCEPTIONS */ + return res; +} +void operator delete(void* ptr) throw() { + scalable_free(ptr); +} +void operator delete[](void* ptr) throw() { + scalable_free(ptr); +} +void* operator new(size_t sz, const std::nothrow_t&) throw() { + return scalable_malloc(sz); +} +void* operator new[](std::size_t sz, const std::nothrow_t&) throw() { + return scalable_malloc(sz); +} +void operator delete(void* ptr, const std::nothrow_t&) throw() { + scalable_free(ptr); +} +void operator delete[](void* ptr, const std::nothrow_t&) throw() { + scalable_free(ptr); +} + +#endif /* MALLOC_LD_PRELOAD */ + + +#ifdef _WIN32 +#include <windows.h> + +#include <stdio.h> +#include "tbb_function_replacement.h" + +void safer_scalable_free2( void *ptr) +{ + safer_scalable_free( ptr, NULL ); +} + +// we do not support _expand(); +void* safer_expand( void *, size_t ) +{ + return NULL; +} + +#define __TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(CRTLIB)\ +void (*orig_free_##CRTLIB)(void*); \ +void safer_scalable_free_##CRTLIB( void *ptr) \ +{ \ + safer_scalable_free( ptr, orig_free_##CRTLIB ); \ +} \ + \ +size_t (*orig_msize_##CRTLIB)(void*); \ +size_t safer_scalable_msize_##CRTLIB( void *ptr) \ +{ \ + return safer_scalable_msize( ptr, orig_msize_##CRTLIB ); \ +} \ + \ +void* safer_scalable_realloc_##CRTLIB( void *ptr, size_t size ) \ +{ \ + orig_ptrs func_ptrs = {orig_free_##CRTLIB, orig_msize_##CRTLIB}; \ + return safer_scalable_realloc( ptr, size, &func_ptrs ); \ +} \ + \ +void* safer_scalable_aligned_realloc_##CRTLIB( void *ptr, size_t size, size_t aligment ) \ +{ \ + orig_ptrs func_ptrs = {orig_free_##CRTLIB, orig_msize_##CRTLIB}; \ + return safer_scalable_aligned_realloc( ptr, size, aligment, &func_ptrs ); \ +} + +// limit is 30 bytes/60 symbols per line +const char* known_bytecodes[] = { +#if _WIN64 + "4883EC284885C974", //release free() win64 + "4883EC384885C975", //release msize() win64 + "4885C974375348", //release free() 8.0.50727.42 win64 + "48894C24084883EC28BA", //debug prologue for win64 + "4C8BC1488B0DA6E4040033", //win64 SDK + "4883EC284885C975", //release msize() 10.0.21003.1 win64 +#else + "558BEC6A018B", //debug free() & _msize() 8.0.50727.4053 win32 + "6A1868********E8", //release free() 8.0.50727.4053 win32 + "6A1C68********E8", //release _msize() 8.0.50727.4053 win32 + "8BFF558BEC6A", //debug free() & _msize() 9.0.21022.8 win32 + "8BFF558BEC83", //debug free() & _msize() 10.0.21003.1 win32 +#endif + NULL + }; + +#if _WIN64 +#define __TBB_ORIG_ALLOCATOR_REPLACEMENT_CALL(CRT_VER)\ + ReplaceFunctionWithStore( #CRT_VER "d.dll", "free", (FUNCPTR)safer_scalable_free_ ## CRT_VER ## d, known_bytecodes, (FUNCPTR*)&orig_free_ ## CRT_VER ## d ); \ + ReplaceFunctionWithStore( #CRT_VER ".dll", "free", (FUNCPTR)safer_scalable_free_ ## CRT_VER, known_bytecodes, (FUNCPTR*)&orig_free_ ## CRT_VER ); \ + ReplaceFunctionWithStore( #CRT_VER "d.dll", "_msize",(FUNCPTR)safer_scalable_msize_ ## CRT_VER ## d, known_bytecodes, (FUNCPTR*)&orig_msize_ ## CRT_VER ## d ); \ + ReplaceFunctionWithStore( #CRT_VER ".dll", "_msize",(FUNCPTR)safer_scalable_msize_ ## CRT_VER, known_bytecodes, (FUNCPTR*)&orig_msize_ ## CRT_VER ); \ + ReplaceFunctionWithStore( #CRT_VER "d.dll", "realloc", (FUNCPTR)safer_scalable_realloc_ ## CRT_VER ## d, 0, NULL); \ + ReplaceFunctionWithStore( #CRT_VER ".dll", "realloc", (FUNCPTR)safer_scalable_realloc_ ## CRT_VER, 0, NULL); \ + ReplaceFunctionWithStore( #CRT_VER "d.dll", "_aligned_free", (FUNCPTR)safer_scalable_free_ ## CRT_VER ## d, 0, NULL); \ + ReplaceFunctionWithStore( #CRT_VER ".dll", "_aligned_free", (FUNCPTR)safer_scalable_free_ ## CRT_VER, 0, NULL); \ + ReplaceFunctionWithStore( #CRT_VER "d.dll", "_aligned_realloc",(FUNCPTR)safer_scalable_aligned_realloc_ ## CRT_VER ## d, 0, NULL); \ + ReplaceFunctionWithStore( #CRT_VER ".dll", "_aligned_realloc",(FUNCPTR)safer_scalable_aligned_realloc_ ## CRT_VER, 0, NULL); +#else +#define __TBB_ORIG_ALLOCATOR_REPLACEMENT_CALL(CRT_VER)\ + ReplaceFunctionWithStore( #CRT_VER "d.dll", "free", (FUNCPTR)safer_scalable_free_ ## CRT_VER ## d, known_bytecodes, (FUNCPTR*)&orig_free_ ## CRT_VER ## d ); \ + ReplaceFunctionWithStore( #CRT_VER ".dll", "free", (FUNCPTR)safer_scalable_free_ ## CRT_VER, known_bytecodes, (FUNCPTR*)&orig_free_ ## CRT_VER ); \ + ReplaceFunctionWithStore( #CRT_VER "d.dll", "_msize",(FUNCPTR)safer_scalable_msize_ ## CRT_VER ## d, known_bytecodes, (FUNCPTR*)&orig_msize_ ## CRT_VER ## d ); \ + ReplaceFunctionWithStore( #CRT_VER ".dll", "_msize",(FUNCPTR)safer_scalable_msize_ ## CRT_VER, known_bytecodes, (FUNCPTR*)&orig_msize_ ## CRT_VER ); \ + ReplaceFunctionWithStore( #CRT_VER "d.dll", "realloc", (FUNCPTR)safer_scalable_realloc_ ## CRT_VER ## d, 0, NULL); \ + ReplaceFunctionWithStore( #CRT_VER ".dll", "realloc", (FUNCPTR)safer_scalable_realloc_ ## CRT_VER, 0, NULL); \ + ReplaceFunctionWithStore( #CRT_VER "d.dll", "_aligned_free", (FUNCPTR)safer_scalable_free_ ## CRT_VER ## d, 0, NULL); \ + ReplaceFunctionWithStore( #CRT_VER ".dll", "_aligned_free", (FUNCPTR)safer_scalable_free_ ## CRT_VER, 0, NULL); \ + ReplaceFunctionWithStore( #CRT_VER "d.dll", "_aligned_realloc",(FUNCPTR)safer_scalable_aligned_realloc_ ## CRT_VER ## d, 0, NULL); \ + ReplaceFunctionWithStore( #CRT_VER ".dll", "_aligned_realloc",(FUNCPTR)safer_scalable_aligned_realloc_ ## CRT_VER, 0, NULL); +#endif + +__TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(msvcr70d); +__TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(msvcr70); +__TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(msvcr71d); +__TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(msvcr71); +__TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(msvcr80d); +__TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(msvcr80); +__TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(msvcr90d); +__TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(msvcr90); +__TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(msvcr100d); +__TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(msvcr100); +__TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(msvcr110d); +__TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(msvcr110); + + +/*** replacements for global operators new and delete ***/ + +#include <new> + +#if _MSC_VER && !defined(__INTEL_COMPILER) +#pragma warning( push ) +#pragma warning( disable : 4290 ) +#endif + +void * operator_new(size_t sz) throw (std::bad_alloc) { + void *res = scalable_malloc(sz); + if (NULL == res) throw std::bad_alloc(); + return res; +} +void* operator_new_arr(size_t sz) throw (std::bad_alloc) { + void *res = scalable_malloc(sz); + if (NULL == res) throw std::bad_alloc(); + return res; +} +void operator_delete(void* ptr) throw() { + safer_scalable_free2(ptr); +} +#if _MSC_VER && !defined(__INTEL_COMPILER) +#pragma warning( pop ) +#endif + +void operator_delete_arr(void* ptr) throw() { + safer_scalable_free2(ptr); +} +void* operator_new_t(size_t sz, const std::nothrow_t&) throw() { + return scalable_malloc(sz); +} +void* operator_new_arr_t(std::size_t sz, const std::nothrow_t&) throw() { + return scalable_malloc(sz); +} +void operator_delete_t(void* ptr, const std::nothrow_t&) throw() { + safer_scalable_free2(ptr); +} +void operator_delete_arr_t(void* ptr, const std::nothrow_t&) throw() { + safer_scalable_free2(ptr); +} + +const char* modules_to_replace[] = { + "msvcr80d.dll", + "msvcr80.dll", + "msvcr90d.dll", + "msvcr90.dll", + "msvcr100d.dll", + "msvcr100.dll", + "msvcr110d.dll", + "msvcr110.dll", + "msvcr70d.dll", + "msvcr70.dll", + "msvcr71d.dll", + "msvcr71.dll", + }; + +/* +We need to replace following functions: +malloc +calloc +_aligned_malloc +_expand (by dummy implementation) +??2@YAPAXI@Z operator new (ia32) +??_U@YAPAXI@Z void * operator new[] (size_t size) (ia32) +??3@YAXPAX@Z operator delete (ia32) +??_V@YAXPAX@Z operator delete[] (ia32) +??2@YAPEAX_K@Z void * operator new(unsigned __int64) (intel64) +??_V@YAXPEAX@Z void * operator new[](unsigned __int64) (intel64) +??3@YAXPEAX@Z operator delete (intel64) +??_V@YAXPEAX@Z operator delete[] (intel64) +??2@YAPAXIABUnothrow_t@std@@@Z void * operator new (size_t sz, const std::nothrow_t&) throw() (optional) +??_U@YAPAXIABUnothrow_t@std@@@Z void * operator new[] (size_t sz, const std::nothrow_t&) throw() (optional) + +and these functions have runtime-specific replacement: +realloc +free +_msize +_aligned_realloc +_aligned_free +*/ + +typedef struct FRData_t { + //char *_module; + const char *_func; + FUNCPTR _fptr; + FRR_ON_ERROR _on_error; +} FRDATA; + +FRDATA routines_to_replace[] = { + { "malloc", (FUNCPTR)scalable_malloc, FRR_FAIL }, + { "calloc", (FUNCPTR)scalable_calloc, FRR_FAIL }, + { "_aligned_malloc", (FUNCPTR)scalable_aligned_malloc, FRR_FAIL }, + { "_expand", (FUNCPTR)safer_expand, FRR_IGNORE }, +#if _WIN64 + { "??2@YAPEAX_K@Z", (FUNCPTR)operator_new, FRR_FAIL }, + { "??_U@YAPEAX_K@Z", (FUNCPTR)operator_new_arr, FRR_FAIL }, + { "??3@YAXPEAX@Z", (FUNCPTR)operator_delete, FRR_FAIL }, + { "??_V@YAXPEAX@Z", (FUNCPTR)operator_delete_arr, FRR_FAIL }, +#else + { "??2@YAPAXI@Z", (FUNCPTR)operator_new, FRR_FAIL }, + { "??_U@YAPAXI@Z", (FUNCPTR)operator_new_arr, FRR_FAIL }, + { "??3@YAXPAX@Z", (FUNCPTR)operator_delete, FRR_FAIL }, + { "??_V@YAXPAX@Z", (FUNCPTR)operator_delete_arr, FRR_FAIL }, +#endif + { "??2@YAPAXIABUnothrow_t@std@@@Z", (FUNCPTR)operator_new_t, FRR_IGNORE }, + { "??_U@YAPAXIABUnothrow_t@std@@@Z", (FUNCPTR)operator_new_arr_t, FRR_IGNORE } +}; + +#ifndef UNICODE +void ReplaceFunctionWithStore( const char*dllName, const char *funcName, FUNCPTR newFunc, const char ** opcodes, FUNCPTR* origFunc ) +#else +void ReplaceFunctionWithStore( const wchar_t *dllName, const char *funcName, FUNCPTR newFunc, const char ** opcodes, FUNCPTR* origFunc ) +#endif +{ + FRR_TYPE type = ReplaceFunction( dllName, funcName, newFunc, opcodes, origFunc ); + if (type == FRR_NODLL) return; + if ( type != FRR_OK ) + { + fprintf(stderr, "Failed to replace function %s in module %s\n", + funcName, dllName); + exit(1); + } +} + +void doMallocReplacement() +{ + int i,j; + + // Replace functions and keep backup of original code (separate for each runtime) + __TBB_ORIG_ALLOCATOR_REPLACEMENT_CALL(msvcr70) + __TBB_ORIG_ALLOCATOR_REPLACEMENT_CALL(msvcr71) + __TBB_ORIG_ALLOCATOR_REPLACEMENT_CALL(msvcr80) + __TBB_ORIG_ALLOCATOR_REPLACEMENT_CALL(msvcr90) + __TBB_ORIG_ALLOCATOR_REPLACEMENT_CALL(msvcr100) + __TBB_ORIG_ALLOCATOR_REPLACEMENT_CALL(msvcr110) + + // Replace functions without storing original code + int modules_to_replace_count = sizeof(modules_to_replace) / sizeof(modules_to_replace[0]); + int routines_to_replace_count = sizeof(routines_to_replace) / sizeof(routines_to_replace[0]); + for ( j=0; j<modules_to_replace_count; j++ ) + for (i = 0; i < routines_to_replace_count; i++) + { +#if !_WIN64 + // in Microsoft* Visual Studio* 11 Beta 32-bit operator delete consists of 2 bytes only: short jump to free(ptr); + // replacement should be skipped for this particular case. + if ( (strcmp(modules_to_replace[j],"msvcr110.dll")==0) && (strcmp(routines_to_replace[i]._func,"??3@YAXPAX@Z")==0) ) continue; +#endif + FRR_TYPE type = ReplaceFunction( modules_to_replace[j], routines_to_replace[i]._func, routines_to_replace[i]._fptr, NULL, NULL ); + if (type == FRR_NODLL) break; + if (type != FRR_OK && routines_to_replace[i]._on_error==FRR_FAIL) + { + fprintf(stderr, "Failed to replace function %s in module %s\n", + routines_to_replace[i]._func, modules_to_replace[j]); + exit(1); + } + } +} + +extern "C" BOOL WINAPI DllMain( HINSTANCE hInst, DWORD callReason, LPVOID reserved ) +{ + + if ( callReason==DLL_PROCESS_ATTACH && reserved && hInst ) { +#if TBBMALLOC_USE_TBB_FOR_ALLOCATOR_ENV_CONTROLLED + char pinEnvVariable[50]; + if( GetEnvironmentVariable("TBBMALLOC_USE_TBB_FOR_ALLOCATOR", pinEnvVariable, 50)) + { + doMallocReplacement(); + } +#else + doMallocReplacement(); +#endif + } + + return TRUE; +} + +// Just to make the linker happy and link the DLL to the application +extern "C" __declspec(dllexport) void __TBB_malloc_proxy() +{ + +} + +#endif //_WIN32 diff --git a/src/tbb/src/tbbmalloc/proxy.h b/src/tbb/src/tbbmalloc/proxy.h new file mode 100644 index 0000000..a98f9b5 --- /dev/null +++ b/src/tbb/src/tbbmalloc/proxy.h @@ -0,0 +1,72 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef _TBB_malloc_proxy_H_ +#define _TBB_malloc_proxy_H_ + +#if __linux__ +#define MALLOC_LD_PRELOAD 1 +#endif + +// MALLOC_LD_PRELOAD depends on MALLOC_CHECK_RECURSION stuff +#if __linux__ || __APPLE__ || __sun || __FreeBSD__ || MALLOC_LD_PRELOAD +#define MALLOC_CHECK_RECURSION 1 +#endif + +#include <stddef.h> + +extern "C" { + void * scalable_malloc(size_t size); + void * scalable_calloc(size_t nobj, size_t size); + void scalable_free(void *ptr); + void * scalable_realloc(void* ptr, size_t size); + void * scalable_aligned_malloc(size_t size, size_t alignment); + void * scalable_aligned_realloc(void* ptr, size_t size, size_t alignment); + int scalable_posix_memalign(void **memptr, size_t alignment, size_t size); + size_t scalable_msize(void *ptr); + void safer_scalable_free( void *ptr, void (*original_free)(void*)); + void * safer_scalable_realloc( void *ptr, size_t, void* ); + void * safer_scalable_aligned_realloc( void *ptr, size_t, size_t, void* ); + size_t safer_scalable_msize( void *ptr, size_t (*orig_msize_crt80d)(void*)); + + void * __TBB_internal_malloc(size_t size); + void * __TBB_internal_calloc(size_t num, size_t size); + void __TBB_internal_free(void *ptr); + void * __TBB_internal_realloc(void* ptr, size_t sz); + int __TBB_internal_posix_memalign(void **memptr, size_t alignment, size_t size); + + bool __TBB_internal_find_original_malloc(int num, const char *names[], void *table[]); +} // extern "C" + +// Struct with original free() and _msize() pointers +struct orig_ptrs { + void (*orig_free) (void*); + size_t (*orig_msize)(void*); +}; + +#endif /* _TBB_malloc_proxy_H_ */ diff --git a/src/tbb/src/tbbmalloc/tbb_function_replacement.cpp b/src/tbb/src/tbbmalloc/tbb_function_replacement.cpp new file mode 100644 index 0000000..d13be8b --- /dev/null +++ b/src/tbb/src/tbbmalloc/tbb_function_replacement.cpp @@ -0,0 +1,476 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Works on windows only +#ifdef _WIN32 +#define _CRT_SECURE_NO_DEPRECATE 1 +#define __TBB_NO_IMPLICIT_LINKAGE 1 + +#include <windows.h> +#include <new> +#include <stdio.h> +#include "tbb_function_replacement.h" + +#include "tbb/tbb_config.h" +#include "tbb/tbb_stddef.h" +#include "../tbb/tbb_assert_impl.h" + +inline UINT_PTR Ptr2Addrint(LPVOID ptr) +{ + Int2Ptr i2p; + i2p.lpv = ptr; + return i2p.uip; +} + +inline LPVOID Addrint2Ptr(UINT_PTR ptr) +{ + Int2Ptr i2p; + i2p.uip = ptr; + return i2p.lpv; +} + +// Is the distance between addr1 and addr2 smaller than dist +inline bool IsInDistance(UINT_PTR addr1, UINT_PTR addr2, __int64 dist) +{ + __int64 diff = addr1>addr2 ? addr1-addr2 : addr2-addr1; + return diff<dist; +} + +/* + * When inserting a probe in 64 bits process the distance between the insertion + * point and the target may be bigger than 2^32. In this case we are using + * indirect jump through memory where the offset to this memory location + * is smaller than 2^32 and it contains the absolute address (8 bytes). + * + * This class is used to hold the pages used for the above trampolines. + * Since this utility will be used to replace malloc functions this implementation + * doesn't allocate memory dynamically. + * + * The struct MemoryBuffer holds the data about a page in the memory used for + * replacing functions in Intel64 where the target is too far to be replaced + * with a short jump. All the calculations of m_base and m_next are in a multiple + * of SIZE_OF_ADDRESS (which is 8 in Win64). + */ +class MemoryProvider { +private: + struct MemoryBuffer { + UINT_PTR m_base; // base address of the buffer + UINT_PTR m_next; // next free location in the buffer + DWORD m_size; // size of buffer + + // Default constructor + MemoryBuffer() : m_base(0), m_next(0), m_size(0) {} + + // Constructor + MemoryBuffer(void *base, DWORD size) + { + m_base = Ptr2Addrint(base); + m_next = m_base; + m_size = size; + } + }; + +MemoryBuffer *CreateBuffer(UINT_PTR addr) + { + // No more room in the pages database + if (m_lastBuffer - m_pages == MAX_NUM_BUFFERS) + return 0; + + void *newAddr = Addrint2Ptr(addr); + // Get information for the region which the given address belongs to + MEMORY_BASIC_INFORMATION memInfo; + if (VirtualQuery(newAddr, &memInfo, sizeof(memInfo)) != sizeof(memInfo)) + return 0; + + for(;;) { + // The new address to check is beyond the current region and aligned to allocation size + newAddr = Addrint2Ptr( (Ptr2Addrint(memInfo.BaseAddress) + memInfo.RegionSize + m_allocSize) & ~(UINT_PTR)(m_allocSize-1) ); + + // Check that the address is in the right distance. + // VirtualAlloc can only round the address down; so it will remain in the right distance + if (!IsInDistance(addr, Ptr2Addrint(newAddr), MAX_DISTANCE)) + break; + + if (VirtualQuery(newAddr, &memInfo, sizeof(memInfo)) != sizeof(memInfo)) + break; + + if (memInfo.State == MEM_FREE && memInfo.RegionSize >= m_allocSize) + { + // Found a free region, try to allocate a page in this region + void *newPage = VirtualAlloc(newAddr, m_allocSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); + if (!newPage) + break; + + // Add the new page to the pages database + MemoryBuffer *pBuff = new (m_lastBuffer) MemoryBuffer(newPage, m_allocSize); + ++m_lastBuffer; + return pBuff; + } + } + + // Failed to find a buffer in the distance + return 0; + } + +public: + MemoryProvider() + { + SYSTEM_INFO sysInfo; + GetSystemInfo(&sysInfo); + m_allocSize = sysInfo.dwAllocationGranularity; + m_lastBuffer = &m_pages[0]; + } + + // We can't free the pages in the destructor because the trampolines + // are using these memory locations and a replaced function might be called + // after the destructor was called. + ~MemoryProvider() + { + } + + // Return a memory location in distance less than 2^31 from input address + UINT_PTR GetLocation(UINT_PTR addr) + { + MemoryBuffer *pBuff = m_pages; + for (; pBuff<m_lastBuffer && IsInDistance(pBuff->m_next, addr, MAX_DISTANCE); ++pBuff) + { + if (pBuff->m_next < pBuff->m_base + pBuff->m_size) + { + UINT_PTR loc = pBuff->m_next; + pBuff->m_next += MAX_PROBE_SIZE; + return loc; + } + } + + pBuff = CreateBuffer(addr); + if(!pBuff) + return 0; + + UINT_PTR loc = pBuff->m_next; + pBuff->m_next += MAX_PROBE_SIZE; + return loc; + } + +private: + MemoryBuffer m_pages[MAX_NUM_BUFFERS]; + MemoryBuffer *m_lastBuffer; + DWORD m_allocSize; +}; + +static MemoryProvider memProvider; + +// Compare opcodes from dictionary (str1) and opcodes from code (str2) +// str1 might contain '*' to mask adresses +// RETURN: NULL if opcodes did not match, string lentgh of str1 on success +size_t compareStrings( const char *str1, const char *str2 ) +{ + size_t str1Lentgh = strlen(str1); + for (size_t i=0; i<str1Lentgh; i++){ + if( str1[i] != '*' && str1[i] != str2[i] ) return 0; + } + return str1Lentgh; +} + +// Check function prologue with know prologues from the dictionary +// opcodes - dictionary +// inpAddr - pointer to function prologue +// Dictionary contains opcodes for several full asm instructions +// + one opcode byte for the next asm instruction for safe address processing +// RETURN: number of bytes for safe bytes replacement +// (matched_pattern/2-1) +UINT CheckOpcodes( const char ** opcodes, void *inpAddr ) +{ + static size_t opcodesStringsCount = 0; + static size_t maxOpcodesLength = 0; + static size_t opcodes_pointer = (size_t)opcodes; + char opcodeString[61]; + size_t i; + size_t result; + + // Get the values for static variables + // max length and number of patterns + if( !opcodesStringsCount || opcodes_pointer != (size_t)opcodes ){ + while( *(opcodes + opcodesStringsCount)!= NULL ){ + if( (i=strlen(*(opcodes + opcodesStringsCount))) > maxOpcodesLength ) + maxOpcodesLength = i; + opcodesStringsCount++; + } + opcodes_pointer = (size_t)opcodes; + __TBB_ASSERT( maxOpcodesLength < 61, "Limit is 30 opcodes/60 symbols per pattern" ); + } + + // Translate prologue opcodes to string format to compare + for( i=0; i< maxOpcodesLength/2; i++ ){ + sprintf( opcodeString + 2*i, "%.2X", *((unsigned char*)inpAddr+i) ); + } + opcodeString[maxOpcodesLength] = 0; + + // Compare translated opcodes with patterns + for( i=0; i< opcodesStringsCount; i++ ){ + result = compareStrings( opcodes[i],opcodeString ); + if( result ) + return (UINT)(result/2-1); + } + // TODO: to add more stuff to patterns + __TBB_ASSERT( false, "CheckOpcodes failed" ); + + // No matches found just do not store original calls + return 0; +} + +// Insert jump relative instruction to the input address +// RETURN: the size of the trampoline or 0 on failure +static DWORD InsertTrampoline32(void *inpAddr, void *targetAddr, const char ** opcodes, void** storedAddr) +{ + UINT opcodesNumber = SIZE_OF_RELJUMP; + UINT_PTR srcAddr = Ptr2Addrint(inpAddr); + UINT_PTR tgtAddr = Ptr2Addrint(targetAddr); + // Check that the target fits in 32 bits + if (!IsInDistance(srcAddr, tgtAddr, MAX_DISTANCE)) + return 0; + + UINT_PTR offset; + UINT offset32; + UCHAR *codePtr = (UCHAR *)inpAddr; + + // If requested, store original function code + if ( storedAddr ){ + opcodesNumber = CheckOpcodes( opcodes, inpAddr ); + if( opcodesNumber >= SIZE_OF_RELJUMP ){ + UINT_PTR strdAddr = memProvider.GetLocation(srcAddr); + if (!strdAddr) + return 0; + *storedAddr = Addrint2Ptr(strdAddr); + // Set 'executable' flag for original instructions in the new place + DWORD pageFlags = PAGE_EXECUTE_READWRITE; + if (!VirtualProtect(*storedAddr, MAX_PROBE_SIZE, pageFlags, &pageFlags)) return 0; + // Copy original instructions to the new place + memcpy(*storedAddr, codePtr, opcodesNumber); + // Set jump to the code after replacement + offset = srcAddr - strdAddr - SIZE_OF_RELJUMP; + offset32 = (UINT)((offset & 0xFFFFFFFF)); + *((UCHAR*)*storedAddr+opcodesNumber) = 0xE9; + memcpy(((UCHAR*)*storedAddr+opcodesNumber+1), &offset32, sizeof(offset32)); + }else{ + // No matches found just do not store original calls + *storedAddr = NULL; + } + } + + // The following will work correctly even if srcAddr>tgtAddr, as long as + // address difference is less than 2^31, which is guaranteed by IsInDistance. + offset = tgtAddr - srcAddr - SIZE_OF_RELJUMP; + offset32 = (UINT)(offset & 0xFFFFFFFF); + // Insert the jump to the new code + *codePtr = 0xE9; + memcpy(codePtr+1, &offset32, sizeof(offset32)); + + // Fill the rest with NOPs to correctly see disassembler of old code in debugger. + for( unsigned i=SIZE_OF_RELJUMP; i<opcodesNumber; i++ ){ + *(codePtr+i) = 0x90; + } + + return SIZE_OF_RELJUMP; +} + +// This function is called when the offset doesn't fit in 32 bits +// 1 Find and allocate a page in the small distance (<2^31) from input address +// 2 Put jump RIP relative indirect through the address in the close page +// 3 Put the absolute address of the target in the allocated location +// RETURN: the size of the trampoline or 0 on failure +static DWORD InsertTrampoline64(void *inpAddr, void *targetAddr, const char ** opcodes, void** storedAddr) +{ + UINT opcodesNumber = SIZE_OF_INDJUMP; + + UINT_PTR srcAddr = Ptr2Addrint(inpAddr); + UINT_PTR tgtAddr = Ptr2Addrint(targetAddr); + + // Get a location close to the source address + UINT_PTR location = memProvider.GetLocation(srcAddr); + if (!location) + return 0; + + UINT_PTR offset; + UINT offset32; + UCHAR *codePtr = (UCHAR *)inpAddr; + + // Fill the location + UINT_PTR *locPtr = (UINT_PTR *)Addrint2Ptr(location); + *locPtr = tgtAddr; + + // If requested, store original function code + if( storedAddr ){ + opcodesNumber = CheckOpcodes( opcodes, inpAddr ); + if( opcodesNumber >= SIZE_OF_INDJUMP ){ + UINT_PTR strdAddr = memProvider.GetLocation(srcAddr); + if (!strdAddr) + return 0; + *storedAddr = Addrint2Ptr(strdAddr); + // Set 'executable' flag for original instructions in the new place + DWORD pageFlags = PAGE_EXECUTE_READWRITE; + if (!VirtualProtect(*storedAddr, MAX_PROBE_SIZE, pageFlags, &pageFlags)) return 0; + // Copy original instructions to the new place + memcpy(*storedAddr, codePtr, opcodesNumber); + // Set jump to the code after replacement. It is within the distance of relative jump! + offset = srcAddr - strdAddr - SIZE_OF_RELJUMP; + offset32 = (UINT)((offset & 0xFFFFFFFF)); + *((UCHAR*)*storedAddr+opcodesNumber) = 0xE9; + memcpy(((UCHAR*)*storedAddr+opcodesNumber+1), &offset32, sizeof(offset32)); + }else{ + // No matches found just do not store original calls + *storedAddr = NULL; + } + } + + // Fill the buffer + offset = location - srcAddr - SIZE_OF_INDJUMP; + offset32 = (UINT)(offset & 0xFFFFFFFF); + *(codePtr) = 0xFF; + *(codePtr+1) = 0x25; + memcpy(codePtr+2, &offset32, sizeof(offset32)); + + // Fill the rest with NOPs to correctly see disassembler of old code in debugger. + for( unsigned i=SIZE_OF_INDJUMP; i<opcodesNumber; i++ ){ + *(codePtr+i) = 0x90; + } + + return SIZE_OF_INDJUMP; +} + +// Insert a jump instruction in the inpAddr to the targetAddr +// 1. Get the memory protection of the page containing the input address +// 2. Change the memory protection to writable +// 3. Call InsertTrampoline32 or InsertTrampoline64 +// 4. Restore memory protection +// RETURN: FALSE on failure, TRUE on success +static bool InsertTrampoline(void *inpAddr, void *targetAddr, const char ** opcodes, void** origFunc) +{ + DWORD probeSize; + // Change page protection to EXECUTE+WRITE + DWORD origProt = 0; + if (!VirtualProtect(inpAddr, MAX_PROBE_SIZE, PAGE_EXECUTE_WRITECOPY, &origProt)) + return FALSE; + probeSize = InsertTrampoline32(inpAddr, targetAddr, opcodes, origFunc); + if (!probeSize) + probeSize = InsertTrampoline64(inpAddr, targetAddr, opcodes, origFunc); + + // Restore original protection + VirtualProtect(inpAddr, MAX_PROBE_SIZE, origProt, &origProt); + + if (!probeSize) + return FALSE; + + FlushInstructionCache(GetCurrentProcess(), inpAddr, probeSize); + FlushInstructionCache(GetCurrentProcess(), origFunc, probeSize); + + return TRUE; +} + +// Routine to replace the functions +// TODO: replace opcodesNumber with opcodes and opcodes number to check if we replace right code. +FRR_TYPE ReplaceFunctionA(const char *dllName, const char *funcName, FUNCPTR newFunc, const char ** opcodes, FUNCPTR* origFunc) +{ + // Cache the results of the last search for the module + // Assume that there was no DLL unload between + static char cachedName[MAX_PATH+1]; + static HMODULE cachedHM = 0; + + if (!dllName || !*dllName) + return FRR_NODLL; + + if (!cachedHM || strncmp(dllName, cachedName, MAX_PATH) != 0) + { + // Find the module handle for the input dll + HMODULE hModule = GetModuleHandleA(dllName); + if (hModule == 0) + { + // Couldn't find the module with the input name + cachedHM = 0; + return FRR_NODLL; + } + + cachedHM = hModule; + strncpy(cachedName, dllName, MAX_PATH); + } + + FARPROC inpFunc = GetProcAddress(cachedHM, funcName); + if (inpFunc == 0) + { + // Function was not found + return FRR_NOFUNC; + } + + if (!InsertTrampoline((void*)inpFunc, (void*)newFunc, opcodes, (void**)origFunc)){ + // Failed to insert the trampoline to the target address + return FRR_FAILED; + } + + return FRR_OK; +} + +FRR_TYPE ReplaceFunctionW(const wchar_t *dllName, const char *funcName, FUNCPTR newFunc, const char ** opcodes, FUNCPTR* origFunc) +{ + // Cache the results of the last search for the module + // Assume that there was no DLL unload between + static wchar_t cachedName[MAX_PATH+1]; + static HMODULE cachedHM = 0; + + if (!dllName || !*dllName) + return FRR_NODLL; + + if (!cachedHM || wcsncmp(dllName, cachedName, MAX_PATH) != 0) + { + // Find the module handle for the input dll + HMODULE hModule = GetModuleHandleW(dllName); + if (hModule == 0) + { + // Couldn't find the module with the input name + cachedHM = 0; + return FRR_NODLL; + } + + cachedHM = hModule; + wcsncpy(cachedName, dllName, MAX_PATH); + } + + FARPROC inpFunc = GetProcAddress(cachedHM, funcName); + if (inpFunc == 0) + { + // Function was not found + return FRR_NOFUNC; + } + + if (!InsertTrampoline((void*)inpFunc, (void*)newFunc, opcodes, (void**)origFunc)){ + // Failed to insert the trampoline to the target address + return FRR_FAILED; + } + + return FRR_OK; +} + +#endif //_WIN32 diff --git a/src/tbb/src/tbbmalloc/tbb_function_replacement.h b/src/tbb/src/tbbmalloc/tbb_function_replacement.h new file mode 100644 index 0000000..37eea33 --- /dev/null +++ b/src/tbb/src/tbbmalloc/tbb_function_replacement.h @@ -0,0 +1,85 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_function_replacement_H +#define __TBB_function_replacement_H + +#include <stddef.h> //for ptrdiff_t +typedef enum { + FRR_OK, /* Succeeded in replacing the function */ + FRR_NODLL, /* The requested DLL was not found */ + FRR_NOFUNC, /* The requested function was not found */ + FRR_FAILED, /* The function replacement request failed */ +} FRR_TYPE; + +typedef enum { + FRR_FAIL, /* Required function */ + FRR_IGNORE, /* optional function */ +} FRR_ON_ERROR; + +typedef void (*FUNCPTR)(); + +#ifndef UNICODE +#define ReplaceFunction ReplaceFunctionA +#else +#define ReplaceFunction ReplaceFunctionW +#endif //UNICODE + +FRR_TYPE ReplaceFunctionA(const char *dllName, const char *funcName, FUNCPTR newFunc, const char ** opcodes, FUNCPTR* origFunc=NULL); +FRR_TYPE ReplaceFunctionW(const wchar_t *dllName, const char *funcName, FUNCPTR newFunc, const char ** opcodes, FUNCPTR* origFunc=NULL); + +// Utilities to convert between ADDRESS and LPVOID +union Int2Ptr { + UINT_PTR uip; + LPVOID lpv; +}; + +inline UINT_PTR Ptr2Addrint(LPVOID ptr); +inline LPVOID Addrint2Ptr(UINT_PTR ptr); + +// Use this value as the maximum size the trampoline region +const unsigned MAX_PROBE_SIZE = 32; + +// The size of a jump relative instruction "e9 00 00 00 00" +const unsigned SIZE_OF_RELJUMP = 5; + +// The size of jump RIP relative indirect "ff 25 00 00 00 00" +const unsigned SIZE_OF_INDJUMP = 6; + +// The size of address we put in the location (in Intel64) +const unsigned SIZE_OF_ADDRESS = 8; + +// The max distance covered in 32 bits: 2^31 - 1 - C +// where C should not be smaller than the size of a probe. +// The latter is important to correctly handle "backward" jumps. +const __int64 MAX_DISTANCE = (((__int64)1 << 31) - 1) - MAX_PROBE_SIZE; + +// The maximum number of distinct buffers in memory +const ptrdiff_t MAX_NUM_BUFFERS = 256; + +#endif //__TBB_function_replacement_H diff --git a/src/tbb/src/tbbmalloc/tbbmalloc.cpp b/src/tbb/src/tbbmalloc/tbbmalloc.cpp new file mode 100644 index 0000000..b26534b --- /dev/null +++ b/src/tbb/src/tbbmalloc/tbbmalloc.cpp @@ -0,0 +1,233 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "TypeDefinitions.h" // Customize.h and proxy.h get included +#include "tbbmalloc_internal_api.h" + +#include "../tbb/itt_notify.h" // for __TBB_load_ittnotify() + +#include "../tbb/tbb_assert_impl.h" // Out-of-line TBB assertion handling routines are instantiated here. + +#undef UNICODE + +#if USE_PTHREAD +#include <dlfcn.h> +#elif USE_WINTHREAD +#include "tbb/machine/windows_api.h" +#endif + +#if MALLOC_CHECK_RECURSION + +#include <pthread.h> +#include <stdio.h> +#include <unistd.h> +#if __sun +#include <string.h> /* for memset */ +#include <errno.h> +#endif + +#if MALLOC_LD_PRELOAD + +extern "C" { + +void safer_scalable_free( void*, void (*)(void*) ); +void * safer_scalable_realloc( void*, size_t, void* ); + +bool __TBB_internal_find_original_malloc(int num, const char *names[], void *table[]) __attribute__ ((weak)); + +} + +#endif /* MALLOC_LD_PRELOAD */ +#endif /* MALLOC_CHECK_RECURSION */ + +namespace rml { +namespace internal { + +#if MALLOC_CHECK_RECURSION + +void* (*original_malloc_ptr)(size_t) = 0; +void (*original_free_ptr)(void*) = 0; +#if MALLOC_LD_PRELOAD +static void* (*original_calloc_ptr)(size_t,size_t) = 0; +static void* (*original_realloc_ptr)(void*,size_t) = 0; +#endif + +#endif /* MALLOC_CHECK_RECURSION */ + +/** Caller is responsible for ensuring this routine is called exactly once. */ +extern "C" void MallocInitializeITT() { +#if DO_ITT_NOTIFY + tbb::internal::__TBB_load_ittnotify(); +#endif +} + +#if TBB_USE_DEBUG +#define DEBUG_SUFFIX "_debug" +#else +#define DEBUG_SUFFIX +#endif /* TBB_USE_DEBUG */ + +// MALLOCLIB_NAME is the name of the TBB memory allocator library. +#if _WIN32||_WIN64 +#define MALLOCLIB_NAME "tbbmalloc" DEBUG_SUFFIX ".dll" +#elif __APPLE__ +#define MALLOCLIB_NAME "libtbbmalloc" DEBUG_SUFFIX ".dylib" +#elif __linux__ +#define MALLOCLIB_NAME "libtbbmalloc" DEBUG_SUFFIX __TBB_STRING(.so.TBB_COMPATIBLE_INTERFACE_VERSION) +#elif __FreeBSD__ || __NetBSD__ || __sun || _AIX +#define MALLOCLIB_NAME "libtbbmalloc" DEBUG_SUFFIX ".so" +#else +#error Unknown OS +#endif + +void init_tbbmalloc() { +#if MALLOC_LD_PRELOAD + if (malloc_proxy && __TBB_internal_find_original_malloc) { + const char *alloc_names[] = { "malloc", "free", "realloc", "calloc"}; + void *orig_alloc_ptrs[4]; + + if (__TBB_internal_find_original_malloc(4, alloc_names, orig_alloc_ptrs)) { + (void *&)original_malloc_ptr = orig_alloc_ptrs[0]; + (void *&)original_free_ptr = orig_alloc_ptrs[1]; + (void *&)original_realloc_ptr = orig_alloc_ptrs[2]; + (void *&)original_calloc_ptr = orig_alloc_ptrs[3]; + MALLOC_ASSERT( original_malloc_ptr!=malloc_proxy, + "standard malloc not found" ); +/* It's workaround for a bug in GNU Libc 2.9 (as it shipped with Fedora 10). + 1st call to libc's malloc should be not from threaded code. + */ + original_free_ptr(original_malloc_ptr(1024)); + original_malloc_found = 1; + } + } +#endif /* MALLOC_LD_PRELOAD */ + +#if DO_ITT_NOTIFY + MallocInitializeITT(); +#endif + +/* Preventing TBB allocator library from unloading to prevent + resource leak, as memory is not released on the library unload. +*/ +#if USE_WINTHREAD && !__TBB_SOURCE_DIRECTLY_INCLUDED + // Prevent Windows from displaying message boxes if it fails to load library + UINT prev_mode = SetErrorMode (SEM_FAILCRITICALERRORS); + HMODULE lib = LoadLibrary(MALLOCLIB_NAME); + MALLOC_ASSERT(lib, "Allocator can't load ifself."); + SetErrorMode (prev_mode); +#endif /* USE_PTHREAD && !__TBB_SOURCE_DIRECTLY_INCLUDED */ +} + +#if !__TBB_SOURCE_DIRECTLY_INCLUDED +#if USE_WINTHREAD +extern "C" BOOL WINAPI DllMain( HINSTANCE hInst, DWORD callReason, LPVOID ) +{ + + if (callReason==DLL_THREAD_DETACH) + { + __TBB_mallocThreadShutdownNotification(); + } + else if (callReason==DLL_PROCESS_DETACH) + { + __TBB_mallocProcessShutdownNotification(); + } + return TRUE; +} +#else +struct RegisterProcessShutdownNotification { + RegisterProcessShutdownNotification() { + // prevents unloading, POSIX case + void *ret = dlopen(MALLOCLIB_NAME, RTLD_NOW); + MALLOC_ASSERT(ret, "Allocator can't load ifself."); + } + ~RegisterProcessShutdownNotification() { + __TBB_mallocProcessShutdownNotification(); + } +}; + +static RegisterProcessShutdownNotification reg; +#endif /* USE_WINTHREAD */ +#endif /* !__TBB_SOURCE_DIRECTLY_INCLUDED */ + +#if MALLOC_CHECK_RECURSION + +bool original_malloc_found; + +#if MALLOC_LD_PRELOAD + +extern "C" { + +void * __TBB_internal_malloc(size_t size) +{ + return scalable_malloc(size); +} + +void * __TBB_internal_calloc(size_t num, size_t size) +{ + return scalable_calloc(num, size); +} + +int __TBB_internal_posix_memalign(void **memptr, size_t alignment, size_t size) +{ + return scalable_posix_memalign(memptr, alignment, size); +} + +void* __TBB_internal_realloc(void* ptr, size_t sz) +{ + return safer_scalable_realloc(ptr, sz, (void*&)original_realloc_ptr); +} + +void __TBB_internal_free(void *object) +{ + safer_scalable_free(object, original_free_ptr); +} + +} /* extern "C" */ + +#endif /* MALLOC_LD_PRELOAD */ + +#endif /* MALLOC_CHECK_RECURSION */ + +} } // namespaces + +#if __TBB_ipf +/* It was found that on IPF inlining of __TBB_machine_lockbyte leads + to serious performance regression with ICC 10.0. So keep it out-of-line. + + This code is copy-pasted from tbb_misc.cpp. + */ +extern "C" intptr_t __TBB_machine_lockbyte( volatile unsigned char& flag ) { + if ( !__TBB_TryLockByte(flag) ) { + tbb::internal::atomic_backoff b; + do { + b.pause(); + } while ( !__TBB_TryLockByte(flag) ); + } + return 0; +} +#endif diff --git a/src/tbb/src/tbbmalloc/tbbmalloc.rc b/src/tbb/src/tbbmalloc/tbbmalloc.rc new file mode 100644 index 0000000..be0bd76 --- /dev/null +++ b/src/tbb/src/tbbmalloc/tbbmalloc.rc @@ -0,0 +1,129 @@ +// Copyright 2005-2012 Intel Corporation. All Rights Reserved. +// +// This file is part of Threading Building Blocks. +// +// Threading Building Blocks is free software; you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// Threading Building Blocks is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Threading Building Blocks; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// Microsoft Visual C++ generated resource script. +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include <winresrc.h> +#define ENDL "\r\n" +#include "tbb/tbb_version.h" + +#define TBBMALLOC_VERNUMBERS TBB_VERSION_MAJOR, TBB_VERSION_MINOR, __TBB_VERSION_YMD +#define TBBMALLOC_VERSION __TBB_STRING(TBBMALLOC_VERNUMBERS) + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Neutral resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// manifest integration +#ifdef TBB_MANIFEST +#include "winuser.h" +2 RT_MANIFEST tbbmanifest.exe.manifest +#endif + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION TBBMALLOC_VERNUMBERS + PRODUCTVERSION TBB_VERNUMBERS + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "CompanyName", "Intel Corporation\0" + VALUE "FileDescription", "Scalable Allocator library\0" + VALUE "FileVersion", TBBMALLOC_VERSION "\0" +//what is it? VALUE "InternalName", "tbbmalloc\0" + VALUE "LegalCopyright", "Copyright 2005-2012 Intel Corporation. All Rights Reserved.\0" + VALUE "LegalTrademarks", "\0" +#ifndef TBB_USE_DEBUG + VALUE "OriginalFilename", "tbbmalloc.dll\0" +#else + VALUE "OriginalFilename", "tbbmalloc_debug.dll\0" +#endif + VALUE "ProductName", "Intel(R) Threading Building Blocks for Windows\0" + VALUE "ProductVersion", TBB_VERSION "\0" + VALUE "Comments", TBB_VERSION_STRINGS "\0" + VALUE "PrivateBuild", "\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END + +#endif // Neutral resources +///////////////////////////////////////////////////////////////////////////// + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/tbb/src/tbbmalloc/tbbmalloc_internal.h b/src/tbb/src/tbbmalloc/tbbmalloc_internal.h new file mode 100644 index 0000000..74cf8cd --- /dev/null +++ b/src/tbb/src/tbbmalloc/tbbmalloc_internal.h @@ -0,0 +1,676 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_tbbmalloc_internal_H +#define __TBB_tbbmalloc_internal_H 1 + + +#include "TypeDefinitions.h" /* Also includes customization layer Customize.h */ + +#if USE_PTHREAD + // Some pthreads documentation says that <pthreads.h> must be first header. + #include <pthread.h> + typedef pthread_key_t tls_key_t; +#elif USE_WINTHREAD + #include "tbb/machine/windows_api.h" + typedef DWORD tls_key_t; +#else + #error Must define USE_PTHREAD or USE_WINTHREAD +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> // for CHAR_BIT +#include <string.h> // for memset +#if MALLOC_CHECK_RECURSION +#include <new> /* for placement new */ +#endif +#include "tbb/scalable_allocator.h" +#include "tbbmalloc_internal_api.h" + +#if __sun || __SUNPRO_CC +#define __asm__ asm +#endif + +/********* Various compile-time options **************/ + +#if !__TBB_DEFINE_MIC && __TBB_MIC_NATIVE + #error Intel(R) Many Integrated Core Compiler does not define __MIC__ anymore. +#endif + +#define MALLOC_TRACE 0 + +#if MALLOC_TRACE +#define TRACEF(x) printf x +#else +#define TRACEF(x) ((void)0) +#endif /* MALLOC_TRACE */ + +#define ASSERT_TEXT NULL + +#define COLLECT_STATISTICS MALLOC_DEBUG && defined(MALLOCENV_COLLECT_STATISTICS) +#include "Statistics.h" + +/********* End compile-time options **************/ + +namespace rml { + +namespace internal { + +//! Utility template function to prevent "unused" warnings by various compilers. +template<typename T> +void suppress_unused_warning( const T& ) {} + +/********** Various numeric parameters controlling allocations ********/ + +/* + * blockSize - the size of a block, it must be larger than maxSegregatedObjectSize. + * + */ +const uintptr_t blockSize = 16*1024; + +/* + * Difference between object sizes in large block bins + */ +const uint32_t largeBlockCacheStep = 8*1024; + +/* + * Large blocks cache cleanup frequency. + * It should be power of 2 for the fast checking. + */ +const unsigned cacheCleanupFreq = 256; + +/* + * Best estimate of cache line size, for the purpose of avoiding false sharing. + * Too high causes memory overhead, too low causes false-sharing overhead. + * Because, e.g., 32-bit code might run on a 64-bit system with a larger cache line size, + * it would probably be better to probe at runtime where possible and/or allow for an environment variable override, + * but currently this is still used for compile-time layout of class Block, so the change is not entirely trivial. + */ +#if __powerpc64__ || __ppc64__ || __bgp__ +const uint32_t estimatedCacheLineSize = 128; +#else +const uint32_t estimatedCacheLineSize = 64; +#endif + +/* + * Alignment of large (>= minLargeObjectSize) objects. + */ +const size_t largeObjectAlignment = estimatedCacheLineSize; + +/********** End of numeric parameters controlling allocations *********/ + +class BlockI; +struct LargeMemoryBlock; +struct ExtMemoryPool; +struct MemRegion; +class FreeBlock; +class TLSData; +class Backend; +class MemoryPool; +extern const uint32_t minLargeObjectSize; + +class TLSKey { + tls_key_t TLS_pointer_key; +public: + TLSKey(); + ~TLSKey(); + TLSData* getThreadMallocTLS() const; + void setThreadMallocTLS( TLSData * newvalue ); + TLSData* createTLS(MemoryPool *memPool, Backend *backend); +}; + +class LargeObjectCache { + // The number of bins to cache large objects. +#if __TBB_DEFINE_MIC + static const uint32_t numLargeBlockBins = 11; // for 100KB max cached size +#else + static const uint32_t numLargeBlockBins = 1024; // for ~8MB max cached size +#endif + // 2-linked list of same-size cached blocks + class CacheBin { + LargeMemoryBlock *first, + *last; + /* age of an oldest block in the list; equal to last->age, if last defined, + used for quick cheching it without acquiring the lock. */ + uintptr_t oldest; + /* currAge when something was excluded out of list because of the age, + not because of cache hit */ + uintptr_t lastCleanedAge; + /* Current threshold value for the blocks of a particular size. + Set on cache miss. */ + intptr_t ageThreshold; + + MallocMutex lock; + /* should be placed in zero-initialized memory, ctor not needed. */ + CacheBin(); + public: + void init() { memset(this, 0, sizeof(CacheBin)); } + inline bool put(ExtMemoryPool *extMemPool, LargeMemoryBlock* ptr); + inline LargeMemoryBlock *get(ExtMemoryPool *extMemPool, size_t size); + bool cleanToThreshold(ExtMemoryPool *extMemPool, uintptr_t currAge); + bool cleanAll(ExtMemoryPool *extMemPool); + }; + + // bins with lists of recently freed large blocks cached for re-use + CacheBin bin[numLargeBlockBins]; + + static int sizeToIdx(size_t size) { + // minLargeObjectSize is minimal size of a large object + return (size-minLargeObjectSize)/largeBlockCacheStep; + } +public: + bool put(ExtMemoryPool *extMemPool, LargeMemoryBlock *largeBlock); + LargeMemoryBlock *get(ExtMemoryPool *extMemPool, size_t size); + + uintptr_t cleanupCacheIfNeed(ExtMemoryPool *extMemPool); + bool regularCleanup(ExtMemoryPool *extMemPool, uintptr_t currAge); + bool cleanAll(ExtMemoryPool *extMemPool) { + bool released = false; + for (int i = numLargeBlockBins-1; i >= 0; i--) + released |= bin[i].cleanAll(extMemPool); + return released; + } + void reset() { + for (int i = numLargeBlockBins-1; i >= 0; i--) + bin[i].init(); + } +}; + +class BackRefIdx { // composite index to backreference array +private: + uint16_t master; // index in BackRefMaster + uint16_t largeObj:1; // is this object "large"? + uint16_t offset :15; // offset from beginning of BackRefBlock +public: + BackRefIdx() : master((uint16_t)-1) {} + bool isInvalid() const { return master == (uint16_t)-1; } + bool isLargeObject() const { return largeObj; } + uint16_t getMaster() const { return master; } + uint16_t getOffset() const { return offset; } + + // only newBackRef can modify BackRefIdx + static BackRefIdx newBackRef(bool largeObj); +}; + +// Block header is used during block coalescing +// and must be preserved in used blocks. +class BlockI { + intptr_t blockState[2]; +}; + +struct LargeMemoryBlock : public BlockI { + LargeMemoryBlock *next, // ptrs in list of cached blocks + *prev, + // 2-linked list of pool's large objects + // Used to destroy backrefs on pool destroy/reset (backrefs are global) + // and for releasing all non-bined blocks. + *gPrev, + *gNext; + uintptr_t age; // age of block while in cache + size_t objectSize; // the size requested by a client + size_t unalignedSize; // the size requested from getMemory + BackRefIdx backRefIdx; // cached here, used copy is in LargeObjectHdr +}; + +// global state of blocks currently in processing +class BackendSync { + // Class instances should reside in zero-initialized memory! + // The number of blocks currently removed from a bin and not returned back + intptr_t blocksInProcessing; // to another + intptr_t binsModifications; // incremented on every bin modification +public: + void consume() { AtomicIncrement(blocksInProcessing); } + void pureSignal() { AtomicIncrement(binsModifications); } + void signal() { + MALLOC_ITT_SYNC_RELEASING(&blocksInProcessing); + AtomicIncrement(binsModifications); + intptr_t prev = AtomicAdd(blocksInProcessing, -1); + MALLOC_ASSERT(prev > 0, ASSERT_TEXT); + suppress_unused_warning(prev); + } + intptr_t getNumOfMods() const { return FencedLoad(binsModifications); } + // return true if need re-do the search + bool waitTillSignalled(intptr_t startModifiedCnt) { + intptr_t myBlocksNum = FencedLoad(blocksInProcessing); + if (!myBlocksNum) { + // no threads, but were bins modified since scanned? + return startModifiedCnt != getNumOfMods(); + } + MALLOC_ITT_SYNC_PREPARE(&blocksInProcessing); + for (;;) { + SpinWaitWhileEq(blocksInProcessing, myBlocksNum); + if (myBlocksNum > blocksInProcessing) + break; + myBlocksNum = FencedLoad(blocksInProcessing); + } + MALLOC_ITT_SYNC_ACQUIRED(&blocksInProcessing); + return true; + } +}; + +class CoalRequestQ { // queue of free blocks that coalescing was delayed + FreeBlock *blocksToFree; +public: + FreeBlock *getAll(); // return current list of blocks and make queue empty + void putBlock(FreeBlock *fBlock); +}; + +template<unsigned NUM> +class BitMask { + static const int SZ = NUM/( CHAR_BIT*sizeof(uintptr_t)) + (NUM % sizeof(uintptr_t) ? 1:0); + static const unsigned WORD_LEN = CHAR_BIT*sizeof(uintptr_t); + uintptr_t mask[SZ]; +public: + void set(size_t idx, bool val) { + MALLOC_ASSERT(idx<NUM, ASSERT_TEXT); + + size_t i = idx / WORD_LEN; + int pos = WORD_LEN - idx % WORD_LEN - 1; + if (val) + AtomicOr(&mask[i], 1ULL << pos); + else + AtomicAnd(&mask[i], ~(1ULL << pos)); + } + int getMinTrue(unsigned startIdx) const { + size_t idx = startIdx / WORD_LEN; + uintptr_t curr; + int pos; + + if (startIdx % WORD_LEN) { // clear bits before startIdx + pos = WORD_LEN - startIdx % WORD_LEN; + curr = mask[idx] & ((1ULL<<pos) - 1); + } else + curr = mask[idx]; + + for (int i=idx; i<SZ; i++, curr=mask[i]) { + if (-1 != (pos = BitScanRev(curr))) + return (i+1)*WORD_LEN - pos - 1; + } + return -1; + } + void reset() { for (int i=0; i<SZ; i++) mask[i] = 0; } +}; + +class MemExtendingSema { + intptr_t active; +public: + bool wait() { + bool rescanBins = false; + // up to 3 threads can add more memory from OS simultaneously, + // rest of threads have to wait + for (;;) { + intptr_t prevCnt = FencedLoad(active); + if (prevCnt < 3) { + intptr_t n = AtomicCompareExchange(active, prevCnt+1, prevCnt); + if (n == prevCnt) + break; + } else { + SpinWaitWhileEq(active, prevCnt); + rescanBins = true; + break; + } + } + return rescanBins; + } + void signal() { AtomicAdd(active, -1); } +}; + +class Backend { +public: + static const unsigned minPower2 = 3+10; + static const unsigned maxPower2 = 12+10; + // 2^13 B, i.e. 8KB + static const size_t minBinedSize = 1 << minPower2; + // 2^22 B, i.e. 4MB + static const size_t maxBinedSize = 1 << maxPower2; + + static const int freeBinsNum = + (maxBinedSize-minBinedSize)/largeBlockCacheStep + 1; + + // if previous access missed per-thread 16KB blocks pool, + // allocate numOfBlocksAllocOnMiss blocks in advance + static const int numOfBlocksAllocOnMiss = 2; + + enum { + NO_BIN = -1, + HUGE_BIN = freeBinsNum-1 + }; + + // Bin keeps 2-linked list of free blocks. It must be 2-linked + // because during coalescing a block it's removed from a middle of the list. + struct Bin { + FreeBlock *head, + *tail; + MallocMutex tLock; + + void removeBlock(FreeBlock *fBlock); + void reset() { head = tail = 0; } +#if _TBBMALLOC_BACKEND_LOG + size_t countFreeBlocks(); +#endif + bool empty() const { return !head; } + }; + + // array of bins accomplished bitmask for fast finding of non-empty bins + class IndexedBins { + BitMask<Backend::freeBinsNum> bitMask; + Bin freeBins[Backend::freeBinsNum]; + public: + FreeBlock *getBlock(int binIdx, BackendSync *sync, size_t size, + bool res16Kaligned, bool alignedBin, bool wait, + int *resLocked); + void lockRemoveBlock(int binIdx, FreeBlock *fBlock); + void addBlock(int binIdx, FreeBlock *fBlock, size_t blockSz); + bool tryAddBlock(int binIdx, FreeBlock *fBlock, bool addToTail); + int getMinNonemptyBin(unsigned startBin) const { + int p = bitMask.getMinTrue(startBin); + return p == -1 ? Backend::freeBinsNum : p; + } + void verify(); +#if _TBBMALLOC_BACKEND_LOG + void reportStat(FILE *f); +#endif + void reset(); + }; + +private: + ExtMemoryPool *extMemPool; + // used for release every region on pool destroying + MemRegion *regionList; + MallocMutex regionListLock; + + CoalRequestQ coalescQ; // queue of coalescing requests + BackendSync bkndSync; + // semaphore protecting adding more more memory from OS + MemExtendingSema memExtendingSema; + + // Using of maximal observed requested size allows descrease + // memory consumption for small requests and descrease fragmentation + // for workloads when small and large allocation requests are mixed. + // TODO: decrease, not only increase it + size_t maxRequestedSize; + void correctMaxRequestSize(size_t requestSize); + + size_t addNewRegion(size_t rawSize, bool exact); + FreeBlock *findBlockInRegion(MemRegion *region); + void startUseBlock(MemRegion *region, FreeBlock *fBlock); + void releaseRegion(MemRegion *region); + + FreeBlock *genericGetBlock(int num, size_t size, bool res16Kaligned); + void genericPutBlock(FreeBlock *fBlock, size_t blockSz); + FreeBlock *getFromAlignedSpace(int binIdx, int num, size_t size, bool res16Kaligned, bool wait, int *locked); + FreeBlock *getFromBin(int binIdx, int num, size_t size, bool res16Kaligned, int *locked); + + FreeBlock *doCoalesc(FreeBlock *fBlock, MemRegion **memRegion); + void coalescAndPutList(FreeBlock *head, bool forceCoalescQDrop, bool doStat); + bool scanCoalescQ(bool forceCoalescQDrop); + void coalescAndPut(FreeBlock *fBlock, size_t blockSz); + + void removeBlockFromBin(FreeBlock *fBlock); + + void *getRawMem(size_t &size) const; + void freeRawMem(void *object, size_t size) const; + +public: + void verify(); +#if _TBBMALLOC_BACKEND_LOG + void reportStat(FILE *f); +#endif + bool bootstrap(ExtMemoryPool *extMemoryPool) { + extMemPool = extMemoryPool; + return addNewRegion(2*1024*1024, /*exact=*/false); + } + void reset(); + bool destroy(); + + BlockI *get16KBlock(int num) { + BlockI *b = (BlockI*) + genericGetBlock(num, blockSize, /*res16Kaligned=*/true); + MALLOC_ASSERT(isAligned(b, blockSize), ASSERT_TEXT); + return b; + } + void put16KBlock(BlockI *block) { + genericPutBlock((FreeBlock *)block, blockSize); + } + void *getBackRefSpace(size_t size, bool *rawMemUsed); + void putBackRefSpace(void *b, size_t size, bool rawMemUsed); + + bool inUserPool() const; + + LargeMemoryBlock *getLargeBlock(size_t size); + void putLargeBlock(LargeMemoryBlock *lmb); +private: + static int sizeToBin(size_t size) { + if (size >= maxBinedSize) + return HUGE_BIN; + else if (size < minBinedSize) + return NO_BIN; + + int bin = (size - minBinedSize)/largeBlockCacheStep; + + MALLOC_ASSERT(bin < HUGE_BIN, "Invalid size."); + return bin; + } + static bool toAlignedBin(FreeBlock *block, size_t size) { + return isAligned((uintptr_t)block+size, blockSize) && size >= blockSize; + } + + IndexedBins freeLargeBins, + freeAlignedBins; +}; + +class AllLargeBlocksList { + MallocMutex largeObjLock; + LargeMemoryBlock *loHead; +public: + LargeMemoryBlock *getHead() { return loHead; } + void add(LargeMemoryBlock *lmb); + void remove(LargeMemoryBlock *lmb); + void removeAll(Backend *backend); +}; + +struct ExtMemoryPool { + static size_t hugePageSize; + static bool useHugePages; + Backend backend; + + intptr_t poolId; + // to find all large objects + AllLargeBlocksList lmbList; + // Callbacks to be used instead of MapMemory/UnmapMemory. + rawAllocType rawAlloc; + rawFreeType rawFree; + size_t granularity; + bool keepAllMemory, + delayRegsReleasing, + fixedPool; + TLSKey tlsPointerKey; // per-pool TLS key + + LargeObjectCache loc; + + static bool tooLargeToBeBined(size_t sz) { return sz >= Backend::maxBinedSize; } + + bool init(intptr_t poolId, rawAllocType rawAlloc, rawFreeType rawFree, + size_t granularity, bool keepAllMemory, bool fixedPool); + void initTLS(); + inline TLSData *getTLS(); + void clearTLS(); + + // i.e., not system default pool for scalable_malloc/scalable_free + bool userPool() const { return rawAlloc; } + + // true if something has beed released + bool softCachesCleanup(); + bool release16KBCaches(); + // TODO: to release all thread's pools, not just current thread + bool hardCachesCleanup() { return loc.cleanAll(this) | release16KBCaches(); } + void reset() { + lmbList.removeAll(&backend); + loc.reset(); + tlsPointerKey.~TLSKey(); + backend.reset(); + } + void destroy() { + // pthread_key_dtors must be disabled before memory unmapping + // TODO: race-free solution + tlsPointerKey.~TLSKey(); + if (rawFree || !userPool()) + backend.destroy(); + } + bool mustBeAddedToGlobalLargeBlockList() const { return userPool(); } + void delayRegionsReleasing(bool mode) { delayRegsReleasing = mode; } + inline bool regionsAreReleaseable() const; + + void *mallocLargeObject(size_t size, size_t alignment); + void freeLargeObject(void *object); +}; + +inline bool Backend::inUserPool() const { return extMemPool->userPool(); } + +struct LargeObjectHdr { + LargeMemoryBlock *memoryBlock; + /* Backreference points to LargeObjectHdr. + Duplicated in LargeMemoryBlock to reuse in subsequent allocations. */ + BackRefIdx backRefIdx; +}; + +struct FreeObject { + FreeObject *next; +}; + +/******* A helper class to support overriding malloc with scalable_malloc *******/ +#if MALLOC_CHECK_RECURSION + +class RecursiveMallocCallProtector { + // pointer to an automatic data of holding thread + static void *autoObjPtr; + static MallocMutex rmc_mutex; + static pthread_t owner_thread; +/* Under FreeBSD 8.0 1st call to any pthread function including pthread_self + leads to pthread initialization, that causes malloc calls. As 1st usage of + RecursiveMallocCallProtector can be before pthread initialized, pthread calls + can't be used in 1st instance of RecursiveMallocCallProtector. + RecursiveMallocCallProtector is used 1st time in checkInitialization(), + so there is a guarantee that on 2nd usage pthread is initialized. + No such situation observed with other supported OSes. + */ +#if __FreeBSD__ + static bool canUsePthread; +#else + static const bool canUsePthread = true; +#endif +/* + The variable modified in checkInitialization, + so can be read without memory barriers. + */ + static bool mallocRecursionDetected; + + MallocMutex::scoped_lock* lock_acquired; + char scoped_lock_space[sizeof(MallocMutex::scoped_lock)+1]; + + static uintptr_t absDiffPtr(void *x, void *y) { + uintptr_t xi = (uintptr_t)x, yi = (uintptr_t)y; + return xi > yi ? xi - yi : yi - xi; + } +public: + + RecursiveMallocCallProtector() : lock_acquired(NULL) { + lock_acquired = new (scoped_lock_space) MallocMutex::scoped_lock( rmc_mutex ); + if (canUsePthread) + owner_thread = pthread_self(); + autoObjPtr = &scoped_lock_space; + } + ~RecursiveMallocCallProtector() { + if (lock_acquired) { + autoObjPtr = NULL; + lock_acquired->~scoped_lock(); + } + } + static bool sameThreadActive() { + if (!autoObjPtr) // fast path + return false; + // Some thread has an active recursive call protector; check if the current one. + // Exact pthread_self based test + if (canUsePthread) { + if (pthread_equal( owner_thread, pthread_self() )) { + mallocRecursionDetected = true; + return true; + } else + return false; + } + // inexact stack size based test + const uintptr_t threadStackSz = 2*1024*1024; + int dummy; + return absDiffPtr(autoObjPtr, &dummy)<threadStackSz; + } + static bool noRecursion(); +/* The function is called on 1st scalable_malloc call to check if malloc calls + scalable_malloc (nested call must set mallocRecursionDetected). */ + static void detectNaiveOverload() { + if (!malloc_proxy) { +#if __FreeBSD__ +/* If !canUsePthread, we can't call pthread_self() before, but now pthread + is already on, so can do it. False positives here lead to silent switching + from malloc to mmap for all large allocations with bad performance impact. */ + if (!canUsePthread) { + canUsePthread = true; + owner_thread = pthread_self(); + } +#endif + free(malloc(1)); + } + } +}; + +#else + +class RecursiveMallocCallProtector { +public: + RecursiveMallocCallProtector() {} + ~RecursiveMallocCallProtector() {} +}; + +#endif /* MALLOC_CHECK_RECURSION */ + +bool isMallocInitializedExt(); + +bool isLargeObject(void *object); + +unsigned int getThreadId(); + +bool initBackRefMaster(Backend *backend); +void destroyBackRefMaster(Backend *backend); +void removeBackRef(BackRefIdx backRefIdx); +void setBackRef(BackRefIdx backRefIdx, void *newPtr); +void *getBackRef(BackRefIdx backRefIdx); + +} // namespace internal +} // namespace rml + +#endif // __TBB_tbbmalloc_internal_H diff --git a/src/tbb/src/tbbmalloc/tbbmalloc_internal_api.h b/src/tbb/src/tbbmalloc/tbbmalloc_internal_api.h new file mode 100644 index 0000000..aeb2599 --- /dev/null +++ b/src/tbb/src/tbbmalloc/tbbmalloc_internal_api.h @@ -0,0 +1,45 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_tbbmalloc_internal_api_H +#define __TBB_tbbmalloc_internal_api_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +void __TBB_mallocProcessShutdownNotification(); +#if _WIN32||_WIN64 +void __TBB_mallocThreadShutdownNotification(); +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif // __TBB_tbbmalloc_internal_api_H diff --git a/src/tbb/src/tbbmalloc/win32-gcc-tbbmalloc-export.def b/src/tbb/src/tbbmalloc/win32-gcc-tbbmalloc-export.def new file mode 100644 index 0000000..45e5589 --- /dev/null +++ b/src/tbb/src/tbbmalloc/win32-gcc-tbbmalloc-export.def @@ -0,0 +1,56 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +{ +global: +scalable_calloc; +scalable_free; +scalable_malloc; +scalable_realloc; +scalable_posix_memalign; +scalable_aligned_malloc; +scalable_aligned_realloc; +scalable_aligned_free; +safer_scalable_free; +safer_scalable_realloc; +scalable_msize; +safer_scalable_msize; +safer_scalable_aligned_realloc; +/* memory pool stuff */ +_ZN3rml10pool_resetEPNS_10MemoryPoolE; +_ZN3rml11pool_createEiPKNS_13MemPoolPolicyE; +_ZN3rml14pool_create_v1EiPKNS_13MemPoolPolicyEPPNS_10MemoryPoolE; +_ZN3rml11pool_mallocEPNS_10MemoryPoolEj; +_ZN3rml12pool_destroyEPNS_10MemoryPoolE; +_ZN3rml9pool_freeEPNS_10MemoryPoolEPv; +_ZN3rml12pool_reallocEPNS_10MemoryPoolEPvj; +_ZN3rml20pool_aligned_reallocEPNS_10MemoryPoolEPvjj; +_ZN3rml19pool_aligned_mallocEPNS_10MemoryPoolEjj; + +local:*; +}; diff --git a/src/tbb/src/tbbmalloc/win32-tbbmalloc-export.def b/src/tbb/src/tbbmalloc/win32-tbbmalloc-export.def new file mode 100644 index 0000000..48a92e3 --- /dev/null +++ b/src/tbb/src/tbbmalloc/win32-tbbmalloc-export.def @@ -0,0 +1,51 @@ +; Copyright 2005-2012 Intel Corporation. All Rights Reserved. +; +; This file is part of Threading Building Blocks. +; +; Threading Building Blocks is free software; you can redistribute it +; and/or modify it under the terms of the GNU General Public License +; version 2 as published by the Free Software Foundation. +; +; Threading Building Blocks is distributed in the hope that it will be +; useful, but WITHOUT ANY WARRANTY; without even the implied warranty +; of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with Threading Building Blocks; if not, write to the Free Software +; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +; +; As a special exception, you may use this file as part of a free software +; library without restriction. Specifically, if other files instantiate +; templates or use macros or inline functions from this file, or you compile +; this file and link it with other files to produce an executable, this +; file does not by itself cause the resulting executable to be covered by +; the GNU General Public License. This exception does not however +; invalidate any other reasons why the executable file might be covered by +; the GNU General Public License. + +EXPORTS + +; frontend.cpp +scalable_calloc +scalable_free +scalable_malloc +scalable_realloc +scalable_posix_memalign +scalable_aligned_malloc +scalable_aligned_realloc +scalable_aligned_free +safer_scalable_free +safer_scalable_realloc +scalable_msize +safer_scalable_msize +safer_scalable_aligned_realloc +?pool_create@rml@@YAPAVMemoryPool@1@HPBUMemPoolPolicy@1@@Z +?pool_create_v1@rml@@YA?AW4MemPoolError@1@HPBUMemPoolPolicy@1@PAPAVMemoryPool@1@@Z +?pool_destroy@rml@@YA_NPAVMemoryPool@1@@Z +?pool_malloc@rml@@YAPAXPAVMemoryPool@1@I@Z +?pool_free@rml@@YA_NPAVMemoryPool@1@PAX@Z +?pool_reset@rml@@YA_NPAVMemoryPool@1@@Z +?pool_realloc@rml@@YAPAXPAVMemoryPool@1@PAXI@Z +?pool_aligned_realloc@rml@@YAPAXPAVMemoryPool@1@PAXII@Z +?pool_aligned_malloc@rml@@YAPAXPAVMemoryPool@1@II@Z diff --git a/src/tbb/src/tbbmalloc/win64-gcc-tbbmalloc-export.def b/src/tbb/src/tbbmalloc/win64-gcc-tbbmalloc-export.def new file mode 100644 index 0000000..762828c --- /dev/null +++ b/src/tbb/src/tbbmalloc/win64-gcc-tbbmalloc-export.def @@ -0,0 +1,56 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +{ +global: +scalable_calloc; +scalable_free; +scalable_malloc; +scalable_realloc; +scalable_posix_memalign; +scalable_aligned_malloc; +scalable_aligned_realloc; +scalable_aligned_free; +safer_scalable_free; +safer_scalable_realloc; +scalable_msize; +safer_scalable_msize; +safer_scalable_aligned_realloc; +/* memory pool stuff */ +_ZN3rml10pool_resetEPNS_10MemoryPoolE; +_ZN3rml11pool_createExPKNS_13MemPoolPolicyE; +_ZN3rml14pool_create_v1ExPKNS_13MemPoolPolicyEPPNS_10MemoryPoolE; +_ZN3rml11pool_mallocEPNS_10MemoryPoolEy; +_ZN3rml12pool_destroyEPNS_10MemoryPoolE; +_ZN3rml9pool_freeEPNS_10MemoryPoolEPv; +_ZN3rml12pool_reallocEPNS_10MemoryPoolEPvy; +_ZN3rml20pool_aligned_reallocEPNS_10MemoryPoolEPvyy; +_ZN3rml19pool_aligned_mallocEPNS_10MemoryPoolEyy; + +local:*; +}; diff --git a/src/tbb/src/tbbmalloc/win64-tbbmalloc-export.def b/src/tbb/src/tbbmalloc/win64-tbbmalloc-export.def new file mode 100644 index 0000000..5e07e82 --- /dev/null +++ b/src/tbb/src/tbbmalloc/win64-tbbmalloc-export.def @@ -0,0 +1,52 @@ +; Copyright 2005-2012 Intel Corporation. All Rights Reserved. +; +; This file is part of Threading Building Blocks. +; +; Threading Building Blocks is free software; you can redistribute it +; and/or modify it under the terms of the GNU General Public License +; version 2 as published by the Free Software Foundation. +; +; Threading Building Blocks is distributed in the hope that it will be +; useful, but WITHOUT ANY WARRANTY; without even the implied warranty +; of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with Threading Building Blocks; if not, write to the Free Software +; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +; +; As a special exception, you may use this file as part of a free software +; library without restriction. Specifically, if other files instantiate +; templates or use macros or inline functions from this file, or you compile +; this file and link it with other files to produce an executable, this +; file does not by itself cause the resulting executable to be covered by +; the GNU General Public License. This exception does not however +; invalidate any other reasons why the executable file might be covered by +; the GNU General Public License. + +EXPORTS + +; frontend.cpp +scalable_calloc +scalable_free +scalable_malloc +scalable_realloc +scalable_posix_memalign +scalable_aligned_malloc +scalable_aligned_realloc +scalable_aligned_free +safer_scalable_free +safer_scalable_realloc +scalable_msize +safer_scalable_msize +safer_scalable_aligned_realloc +; memory pool stuff +?pool_create@rml@@YAPEAVMemoryPool@1@_JPEBUMemPoolPolicy@1@@Z +?pool_create_v1@rml@@YA?AW4MemPoolError@1@_JPEBUMemPoolPolicy@1@PEAPEAVMemoryPool@1@@Z +?pool_destroy@rml@@YA_NPEAVMemoryPool@1@@Z +?pool_malloc@rml@@YAPEAXPEAVMemoryPool@1@_K@Z +?pool_free@rml@@YA_NPEAVMemoryPool@1@PEAX@Z +?pool_reset@rml@@YA_NPEAVMemoryPool@1@@Z +?pool_realloc@rml@@YAPEAXPEAVMemoryPool@1@PEAX_K@Z +?pool_aligned_realloc@rml@@YAPEAXPEAVMemoryPool@1@PEAX_K2@Z +?pool_aligned_malloc@rml@@YAPEAXPEAVMemoryPool@1@_K1@Z diff --git a/src/tbb/src/tbbmalloc/xbox360-tbbmalloc-export.def b/src/tbb/src/tbbmalloc/xbox360-tbbmalloc-export.def new file mode 100644 index 0000000..ae0bb71 --- /dev/null +++ b/src/tbb/src/tbbmalloc/xbox360-tbbmalloc-export.def @@ -0,0 +1,42 @@ +; Copyright 2005-2012 Intel Corporation. All Rights Reserved. +; +; This file is part of Threading Building Blocks. +; +; Threading Building Blocks is free software; you can redistribute it +; and/or modify it under the terms of the GNU General Public License +; version 2 as published by the Free Software Foundation. +; +; Threading Building Blocks is distributed in the hope that it will be +; useful, but WITHOUT ANY WARRANTY; without even the implied warranty +; of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with Threading Building Blocks; if not, write to the Free Software +; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +; +; As a special exception, you may use this file as part of a free software +; library without restriction. Specifically, if other files instantiate +; templates or use macros or inline functions from this file, or you compile +; this file and link it with other files to produce an executable, this +; file does not by itself cause the resulting executable to be covered by +; the GNU General Public License. This exception does not however +; invalidate any other reasons why the executable file might be covered by +; the GNU General Public License. + +EXPORTS + +; MemoryAllocator.cpp +scalable_calloc @1 +scalable_free @2 +scalable_malloc @3 +scalable_realloc @4 +scalable_posix_memalign @5 +scalable_aligned_malloc @6 +scalable_aligned_realloc @7 +scalable_aligned_free @8 +safer_scalable_free @9 +safer_scalable_realloc @10 +scalable_msize @11 +safer_scalable_msize @12 +safer_scalable_aligned_realloc @13 diff --git a/src/tbb/src/tbbproxy/tbbproxy-windows.asm b/src/tbb/src/tbbproxy/tbbproxy-windows.asm new file mode 100644 index 0000000..6570207 --- /dev/null +++ b/src/tbb/src/tbbproxy/tbbproxy-windows.asm @@ -0,0 +1,121 @@ +; Copyright 2005-2012 Intel Corporation. All Rights Reserved. +; +; This file is part of Threading Building Blocks. +; +; Threading Building Blocks is free software; you can redistribute it +; and/or modify it under the terms of the GNU General Public License +; version 2 as published by the Free Software Foundation. +; +; Threading Building Blocks is distributed in the hope that it will be +; useful, but WITHOUT ANY WARRANTY; without even the implied warranty +; of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with Threading Building Blocks; if not, write to the Free Software +; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +; +; As a special exception, you may use this file as part of a free software +; library without restriction. Specifically, if other files instantiate +; templates or use macros or inline functions from this file, or you compile +; this file and link it with other files to produce an executable, this +; file does not by itself cause the resulting executable to be covered by +; the GNU General Public License. This exception does not however +; invalidate any other reasons why the executable file might be covered by +; the GNU General Public License. + +#include "tbb/tbb_config.h" + +// __TBB_STRING macro defined in "tbb_stddef.h". However, we cannot include "tbb_stddef.h" +// because it contains a lot of C/C++ definitions. So, we have to define __TBB_STRING here: +#define __TBB_STRING_AUX( x ) #x +#define __TBB_STRING( x ) __TBB_STRING_AUX( x ) + +// Eliminate difference between IA-32 and Intel 64: AWORD is a type of pointer, LANG is language +// specification for extern directive. +#ifdef ARCH_ia32 + #define AWORD dword + #define LANG c +#else + #define AWORD qword + #define LANG +#endif + +#ifdef ARCH_ia32 + // These directives are required for IA32 architecture only. + .686 + .model flat, syscall +#endif + +/* + Symbol names. +*/ + +// Note: masm for IA-32 does not like symbols defined as "name:" in data sections, +// so we have to define symbols with "name label type" directive instead. + +fname macro sym:req + align sizeof AWORD + Ln_&sym& label byte + byte "&sym&", 0 +endm + +.const // Symbol names are constants. +#define __TBB_SYMBOL( sym ) fname sym +#include __TBB_STRING( __TBB_LST ) + +/* + Symbol descriptors. +*/ + +extern LANG __tbb_internal_runtime_loader_stub : AWORD + +fsymbol macro sym:req + Ls_&sym& label AWORD + AWORD __tbb_internal_runtime_loader_stub + AWORD Ln_&sym& + dword sizeof AWORD + dword 1 +endm + +.data +align sizeof AWORD +public LANG __tbb_internal_runtime_loader_symbols +__tbb_internal_runtime_loader_symbols label AWORD +#define __TBB_SYMBOL( sym ) fsymbol sym +#include __TBB_STRING( __TBB_LST ) +AWORD 0, 0 // Terminator of the __tbb_internal_runtime_loader_symbols array. +dword 0, 0 + +/* + Generate functions. +*/ + +// Helper assembler macro to handle different naming conventions on IA-32 and Intel 64: +// IA-32: C++ names preserved, C names require leading underscore. +// Intel 64: All names preserved. +mangle macro name:req + #ifdef ARCH_ia32 + if @instr( 1, name, <?> ) + exitm @catstr( name ) + else + exitm @catstr( <_>, name ) + endif + #else + exitm @catstr( name ) + #endif +endm + +function macro sym:req + mangle( sym ) proc + jmp AWORD ptr Ls_&sym& + mangle( sym ) endp +endm + +.code +#define __TBB_SYMBOL( sym ) function sym +#include __TBB_STRING( __TBB_LST ) + +end + +// end of file // diff --git a/src/tbb/src/tbbproxy/tbbproxy.cpp b/src/tbb/src/tbbproxy/tbbproxy.cpp new file mode 100644 index 0000000..d97b70b --- /dev/null +++ b/src/tbb/src/tbbproxy/tbbproxy.cpp @@ -0,0 +1,616 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#define TBB_PREVIEW_RUNTIME_LOADER 1 +#include "tbb/runtime_loader.h" +#include "tbb/tbb_stddef.h" + +// C standard headers. +#include <cctype> // isspace +#include <cstdarg> // va_list, etc. +#include <cstdio> // fprintf, stderr, etc. +#include <cstdlib> // malloc, free, abort. +#include <cstring> // strlen, etc. + +// C++ standard headers. +#include <typeinfo> + +// OS-specific includes. +#if _WIN32 || _WIN64 + #include <windows.h> + #define snprintf _snprintf + #undef max +#else + #include <dlfcn.h> // dlopen, dlsym, dlclose, dlerror. +#endif + +#if TBB_USE_ASSERT + // We cannot use __TBB_ASSERT as it is because it calls a function from tbb library which may + // be not yet loaded. Redefine __TBB_ASSERT not to call tbb functions. + #undef __TBB_ASSERT + #define __TBB_ASSERT( cond, msg ) { \ + if ( ! (cond) ) { \ + say( "%s:%d: Assertion failed: %s.", __FILE__, __LINE__, (msg) ); \ + } /* if */ \ + /* TODO: abort? */ \ + } +#endif + +// Declare here, define at the bottom. +extern "C" int __tbb_internal_runtime_loader_stub(); + +namespace tbb { + +namespace interface6 { + +namespace internal { + +namespace runtime_loader { + + +/* + ------------------------------------------------------------------------------------------------ + User interaction utilities. + ------------------------------------------------------------------------------------------------ +*/ + + +// Print message to stderr. Do not call it directly, use say() or tell() instead. +static void _say( char const * format, va_list args ) { + /* + On Linux Intel 64, vsnprintf() modifies args argument, so vsnprintf() crashes if it + is called for the second time with the same args. To prevent the crash, we have to + pass a fresh intact copy of args to vsnprintf() each time. + + On Windows, unfortunately, standard va_copy() macro is not available. However, it + seems vsnprintf() does not modify args argument. + */ + #if ! ( _WIN32 || _WIN64 ) + va_list _args; + __va_copy( _args, args ); // Make copy of args. + #define args _args // Substitute args with its copy, _args. + #endif + int len = vsnprintf( NULL, 0, format, args ); + #if ! ( _WIN32 || _WIN64 ) + #undef args // Remove substitution. + va_end( _args ); + #endif + char * buf = reinterpret_cast< char * >( malloc( len + 1 ) ); + if ( buf == NULL ) { + abort(); + } // if + vsnprintf( buf, len + 1, format, args ); + fprintf( stderr, "TBB: %s\n", buf ); + free( buf ); +} // _say + + +// Debug/test/troubleshooting printing controlled by TBB_VERSION environment variable. +// To enable printing, the variable must be set and not empty. +// Do not call it directly, use tell() instead. +static void _tell( char const * format, va_list args ) { + char const * var = getenv( "TBB_VERSION" ); + if ( var != NULL && var[ 0 ] != 0 ) { + _say( format, args ); + } // if +} // _tell + + +// Print message to stderr unconditinally. +static void say( char const * format, ... ) { + va_list args; + va_start( args, format ); + _say( format, args ); + va_end( args ); +} // say + + +// Debug/test/troubleshooting printing controlled by TBB_VERSION environment variable. +// To enable printing, the variable must be set and not empty. +static void tell( char const * format, ... ) { + va_list args; + va_start( args, format ); + _tell( format, args ); + va_end( args ); +} // tell + + +// Error reporting utility. Behavior depends on mode. +static tbb::runtime_loader::error_code error( tbb::runtime_loader::error_mode mode, tbb::runtime_loader::error_code err, char const * format, ... ) { + va_list args; + va_start( args, format ); + if ( mode == tbb::runtime_loader::em_abort ) { + // In em_abort mode error message printed unconditionally. + _say( format, args ); + } else { + // In other modes printing depends on TBB_VERSION environment variable. + _tell( format, args ); + } // if + va_end( args ); + switch ( mode ) { + case tbb::runtime_loader::em_abort : { + say( "Aborting..." ); + #if TBB_USE_DEBUG && ( _WIN32 || _WIN64 ) + DebugBreak(); + #endif + abort(); + } break; + case tbb::runtime_loader::em_throw : { + throw err; + } break; + case tbb::runtime_loader::em_status : { + // Do nothing. + } break; + } // switch + return err; +} // error + + +/* + ------------------------------------------------------------------------------------------------ + General-purpose string manupulation utilities. + ------------------------------------------------------------------------------------------------ +*/ + + +// Delete character ch from string str in-place. +static void strip( char * str, char ch ) { + int in = 0; // Input character index. + int out = 0; // Output character index. + for ( ; ; ) { + if ( str[ in ] != ch ) { + str[ out ] = str[ in ]; + ++ out; + } // if + if ( str[ in ] == 0 ) { + break; + } // if + ++ in; + } // forever +} // func strip + + +// Strip trailing whitespaces in-place. +static void trim( char * str ) { + size_t len = strlen( str ); + while ( len > 0 && isspace( str[ len - 1 ] ) ) { + -- len; + } // while + str[ len ] = 0; +} // func trim + + +#if _WIN32 || _WIN64 + // "When specifying a path, be sure to use backslashes (\), not forward slashes (/)." + // (see http://msdn.microsoft.com/en-us/library/ms886736.aspx). + const char proper_slash = '\\'; + inline char char_or_slash( char c ) { return c=='/'? '\\': c; } +#else + const char proper_slash = '/'; + inline char char_or_slash( char c ) { return c; } +#endif + +// Concatenate name of directory and name of file. +void cat_file( char const * dir, char const * file, char * buffer, size_t len ) { + size_t i = 0; + // Copy directory name + for( ; i<len && *dir; ++i, ++dir ) { + buffer[i] = char_or_slash(*dir); + } + // Append trailing slash if missed. + if( i>0 && i<len && buffer[i-1]!=proper_slash ) { + buffer[i++] = proper_slash; + } + // Copy file name + __TBB_ASSERT( char_or_slash(*file)!=proper_slash, "File name starts with a slash" ); + for( ; i<len && *file; ++i, ++file ) { + buffer[i] = *file; + } + // Append null terminator + buffer[ i<len? i: len-1 ] = '\0'; +} // cat_file + + +/* + ------------------------------------------------------------------------------------------------ + Windows implementation of dlopen, dlclose, dlsym, dlerror. + ------------------------------------------------------------------------------------------------ +*/ + + +#if _WIN32 || _WIN64 + + // Implement Unix-like interface (dlopen, dlclose, dlsym, dlerror) via Win32 API functions. + + // Type of dlopen result. + typedef HMODULE handle_t; + + enum rtld_flags_t { + RTLD_NOW, + RTLD_GLOBAL + }; // enum rtld_flags_t + + // Unix-like dlopen(). + static handle_t dlopen( char const * name, rtld_flags_t ) { + return LoadLibrary( name ); + } // dlopen + + // Unix-like dlsym(). + static void * dlsym( handle_t lib, char const * sym ) { + return (void*)GetProcAddress( lib, sym ); + } // dlsym + + // Unix-like dlclose(). + static int dlclose( handle_t lib ) { + return ! FreeLibrary( lib ); + } // dlclose + + // The function mimics Unix dlerror() function. + // Note: Not thread-safe due to statically allocated buffer. + static char * dlerror() { + + static char buffer[ 2048 ]; // Note: statically allocated buffer. + + DWORD err = GetLastError(); + if ( err == ERROR_SUCCESS ) { + return NULL; + } // if + + DWORD rc; + rc = + FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + err, + MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language. + reinterpret_cast< LPTSTR >( & buffer ), + sizeof( buffer ), + NULL + ); + if ( rc == 0 ) { + // FormatMessage() failed to format system error message. Buffer to short or another issue. + snprintf( buffer, sizeof( buffer ), "System error %u.", err ); + } else { + /* + FormatMessage() returns Windows-style end-of-lines, "\r\n". When string is printed, + printf() also replaces all the occurences of "\n" with "\r\n" (again!), so sequences + like "\r\r\r\n" appear in output. It is not too good. Stripping all "\r" normalizes + string and returns it to canonical form, so printf() will produce correct end-of-line + sequences. + */ + strip( buffer, '\r' ); // Delete carriage returns if any. + trim( buffer ); // Delete trailing newlines and spaces. + } // if + + return buffer; + + } // dlerror + +#else + + // Type of dlopen() result. + typedef void * handle_t; + +#endif + + +/* + ------------------------------------------------------------------------------------------------ + Runtime loader stuff. + ------------------------------------------------------------------------------------------------ +*/ + + +// Descriptor table declaration. It is defined in assembler file. +enum symbol_type_t { + st_object = 0, + st_function = 1 +}; // enum symbol_type_t +struct symbol_t { + void * addr; + char const * name; + int size; + symbol_type_t type; +}; // symbol_t +extern "C" symbol_t __tbb_internal_runtime_loader_symbols[]; + +// Hooks for internal use (e. g. for testing). +tbb::runtime_loader::error_mode stub_mode = tbb::runtime_loader::em_abort; + +static char const * tbb_dll_name = __TBB_STRING(__TBB_DLL_NAME); // Name of TBB library. +static handle_t handle = NULL; // Handle of loaded TBB library or NULL. +static int version = 0; // Version of the loaded library. +static int counter = 0; // Number of runtime_loader objects using the loaded library. + +#define ANOTHER_RTL "probably multiple runtime_loader objects work in parallel" + + +// One attempt to load library (dll_name can be a full path or just a file name). +static tbb::runtime_loader::error_code _load( char const * dll_name, int min_ver, int max_ver ) { + + tbb::runtime_loader::error_mode mode = tbb::runtime_loader::em_status; + tbb::runtime_loader::error_code code = tbb::runtime_loader::ec_ok; + + /* + If these variables declared at the first usage, Intel compiler (on Windows IA-32) isues + warning(s): + transfer of control [goto error] bypasses initialization of: ... + Declaring variables at the beginning of the function eliminates warnings. + */ + typedef int (*int_func_t)( void ); + char const * get_ver_name = "TBB_runtime_interface_version"; // Name of function. + int_func_t get_ver_func = NULL; // Pointer to function. + handle_t _handle = NULL; + int _version = 0; + int total = 0; + int not_found = 0; + + // This function should be called iff there is no loaded library. + __TBB_ASSERT( handle == NULL, "Handle is invalid; " ANOTHER_RTL ); + __TBB_ASSERT( version == 0, "Version is invalid; " ANOTHER_RTL ); + __TBB_ASSERT( counter == 0, "Counter is invalid; " ANOTHER_RTL ); + + tell( "Loading \"%s\"...", dll_name ); + + // First load the library. + _handle = dlopen( dll_name, RTLD_NOW ); + if ( _handle == NULL ) { + char * msg = dlerror(); + code = error( mode, tbb::runtime_loader::ec_no_lib, "Loading \"%s\" failed; system error: %s", dll_name, msg ); + goto error; + } // if + + // Then try to find out its version. + /* + g++ 3.4 issues error: + ISO C++ forbids casting between pointer-to-function and pointer-to-object + on reinterpret_cast<>. Thus, we have no choice but using C-style type cast. + */ + get_ver_func = (int_func_t) dlsym( _handle, get_ver_name ); + if ( get_ver_func == NULL ) { + code = error( mode, tbb::runtime_loader::ec_bad_lib, "Symbol \"%s\" not found; library rejected.", get_ver_name ); + goto error; + } // if + _version = get_ver_func(); + if ( ! ( min_ver <= _version && _version <= max_ver ) ) { + code = error( mode, tbb::runtime_loader::ec_bad_ver, "Version %d is out of requested range; library rejected.", _version ); + goto error; + } // if + + // Library is suitable. Mark it as loaded. + handle = _handle; + version = _version; + counter += 1; + __TBB_ASSERT( counter == 1, "Counter is invalid; " ANOTHER_RTL ); + + // Now search for all known symbols. + for ( int i = 0; __tbb_internal_runtime_loader_symbols[ i ].name != NULL; ++ i ) { + symbol_t & symbol = __tbb_internal_runtime_loader_symbols[ i ]; + // Verify symbol descriptor. + __TBB_ASSERT( symbol.type == st_object || symbol.type == st_function, "Invalid symbol type" ); + #if _WIN32 || _WIN64 + __TBB_ASSERT( symbol.type == st_function, "Should not be symbols of object type on Windows" ); + #endif + if ( symbol.type == st_object ) { + __TBB_ASSERT( symbol.addr != NULL, "Object address invalid" ); + __TBB_ASSERT( symbol.size > 0, "Symbol size must be > 0" ); + __TBB_ASSERT( symbol.size <= 0x1000, "Symbol size too big" ); + } else { // Function + // __TBB_ASSERT( symbol.addr == reinterpret_cast< void * >( & stub ), "Invalid symbol address" ); + __TBB_ASSERT( symbol.size == sizeof( void * ), "Invalid symbol size" ); + } // if + void * addr = dlsym( _handle, symbol.name ); + if ( addr != NULL ) { + if ( symbol.type == st_object ) { + if ( strncmp( symbol.name, "_ZTS", 4 ) == 0 ) { + // If object name begins with "_ZTS", it is a string, mangled type name. + // Its value must equal to name of symbol without "_ZTS" prefix. + char const * name = static_cast< char const * >( addr ); + __TBB_ASSERT( strlen( name ) + 1 == size_t( symbol.size ), "Unexpected size of typeinfo name" ); + __TBB_ASSERT( strcmp( symbol.name + 4, name ) == 0, "Unexpected content of typeinfo name" ); + strncpy( reinterpret_cast< char * >( symbol.addr ), name, symbol.size ); + reinterpret_cast< char * >( symbol.addr )[ symbol.size - 1 ] = 0; + } else { + #if TBB_USE_ASSERT + // If object name begins with "_ZTI", it is an object of std::type_info class. + // Its protected value must equal to name of symbol without "_ZTI" prefix. + if ( strncmp( symbol.name, "_ZTI", 4 ) == 0 ) { + std::type_info const * info = static_cast< std::type_info const * >( addr ); + __TBB_ASSERT( size_t( symbol.size ) >= sizeof( std::type_info ), "typeinfo size is too small" ); + // std::type_info::name is not a virtual method, it is safe to call it. + __TBB_ASSERT( strcmp( symbol.name + 4, info->name() ) == 0, "Unexpected content of typeinfo" ); + } // if + #endif + // Copy object content from libtbb into runtime_loader. + memcpy( symbol.addr, addr, symbol.size ); + }; // if + } else { // Function + symbol.addr = addr; + } // if + } else { + char const * msg = dlerror(); + tell( "Symbol \"%s\" not found; system error: %s", symbol.name, msg ); + ++ not_found; + } // if + ++ total; + } // for i + + if ( not_found > 0 ) { + tell( "%d of %d symbols not found.", not_found, total ); + } // if + + tell( "The library successfully loaded." ); + return code; + + error: + if ( _handle != NULL ) { + int rc = dlclose( _handle ); + if ( rc != 0 ) { + // Error occurred. + __TBB_ASSERT( rc != 0, "Unexpected error: dlclose() failed" ); + } // if + } // if + _handle = NULL; + return code; + +} // _load + + +static tbb::runtime_loader::error_code load( tbb::runtime_loader::error_mode mode, char const * path[], int min_ver, int max_ver ) { + // Check arguments first. + if ( min_ver <= 0 ) { + return error( mode, tbb::runtime_loader::ec_bad_arg, "tbb::runtime_loader::load(): Invalid value of min_ver argument: %d.", min_ver ); + } // if + if ( max_ver <= 0 ) { + return error( mode, tbb::runtime_loader::ec_bad_arg, "tbb::runtime_loader::load(): Invalid value of max_ver argument: %d.", max_ver ); + } // if + if ( min_ver > max_ver ) { + return error( mode, tbb::runtime_loader::ec_bad_arg, "tbb::runtime_loader::load(): min_ver and max_ver specify empty range: [%d, %d].", min_ver, max_ver ); + } // if + if ( min_ver == max_ver ) { + tell( "Searching for \"%s\" version %d...", tbb_dll_name, min_ver ); + } else if ( max_ver == INT_MAX ) { + tell( "Searching for \"%s\" version %d+...", tbb_dll_name, min_ver ); + } else { + tell( "Searching for \"%s\" version in range [%d, %d]...", tbb_dll_name, min_ver, max_ver ); + } // if + // Then check whether a library already loaded. + if ( handle != NULL ) { + // Library already loaded. Check whether the version is compatible. + __TBB_ASSERT( version > 0, "Version is invalid; " ANOTHER_RTL ); + __TBB_ASSERT( counter > 0, "Counter is invalid; " ANOTHER_RTL ); + if ( min_ver <= version && version <= max_ver ) { + // Version is ok, let us use this library. + tell( "Library version %d is already loaded.", version ); + counter += 1; + return tbb::runtime_loader::ec_ok; + } else { + // Version is not suitable. + return error( mode, tbb::runtime_loader::ec_bad_ver, "Library version %d is already loaded.", version ); + } // if + } // if + // There is no loaded library, try to load it using provided directories. + __TBB_ASSERT( version == 0, "Version is invalid; " ANOTHER_RTL ); + __TBB_ASSERT( counter == 0, "Counter is invalid; " ANOTHER_RTL ); + size_t namelen = strlen(tbb_dll_name); + size_t buflen = 0; + char * buffer = NULL; + for ( int i = 0; path[i] != NULL; ++ i ) { + size_t len = strlen(path[i]) + namelen + 2; // 1 for slash and 1 for null terminator + if( buflen<len ) { + free( buffer ); + buflen = len; + buffer = (char*)malloc( buflen ); + } + cat_file( path[i], tbb_dll_name, buffer, buflen ); + __TBB_ASSERT(strstr(buffer,tbb_dll_name), "Name concatenation error"); + tbb::runtime_loader::error_code ec = _load( buffer, min_ver, max_ver ); + if ( ec == tbb::runtime_loader::ec_ok ) { + return ec; // Success. Exiting... + } // if + } // for i + free( buffer ); + return error( mode, tbb::runtime_loader::ec_no_lib, "No suitable library found." ); +} // load + + + + +// Supress "defined but not used" compiler warnings. +static void const * dummy[] = { + (void *) & strip, + (void *) & trim, + & dummy, + NULL +}; + + +} // namespace runtime_loader + +} // namespace internal + + +runtime_loader::runtime_loader( error_mode mode ) : + my_mode( mode ), + my_status( ec_ok ), + my_loaded( false ) +{ +} // ctor + + +runtime_loader::runtime_loader( char const * path[], int min_ver, int max_ver, error_mode mode ) : + my_mode( mode ), + my_status( ec_ok ), + my_loaded( false ) +{ + load( path, min_ver, max_ver ); +} // ctor + + +runtime_loader::~runtime_loader() { +} // dtor + + +tbb::runtime_loader::error_code runtime_loader::load( char const * path[], int min_ver, int max_ver ) { + if ( my_loaded ) { + my_status = tbb::interface6::internal::runtime_loader::error( my_mode, ec_bad_call, "tbb::runtime_loader::load(): Library already loaded by this runtime_loader object." ); + } else { + my_status = internal::runtime_loader::load( my_mode, path, min_ver, max_ver ); + if ( my_status == ec_ok ) { + my_loaded = true; + } // if + } // if + return my_status; +} // load + + + + +tbb::runtime_loader::error_code runtime_loader::status() { + return my_status; +} // status + + +} // namespace interface6 + +} // namespace tbb + + +// Stub function replaces all TBB entry points when no library is loaded. +int __tbb_internal_runtime_loader_stub() { + char const * msg = NULL; + if ( tbb::interface6::internal::runtime_loader::handle == NULL ) { + msg = "A function is called while TBB library is not loaded"; + } else { + msg = "A function is called which is not present in loaded TBB library"; + } // if + return tbb::interface6::internal::runtime_loader::error( tbb::interface6::internal::runtime_loader::stub_mode, tbb::runtime_loader::ec_no_lib, msg ); +} // stub + + +// end of file // diff --git a/src/tbb/src/test/harness.h b/src/tbb/src/test/harness.h new file mode 100644 index 0000000..e435b39 --- /dev/null +++ b/src/tbb/src/test/harness.h @@ -0,0 +1,546 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Declarations for rock-bottom simple test harness. +// Just include this file to use it. +// Every test is presumed to have a command line of the form "test [-v] [MinThreads[:MaxThreads]]" +// The default for MinThreads is 1, for MaxThreads 4. +// The defaults can be overridden by defining macros HARNESS_DEFAULT_MIN_THREADS +// and HARNESS_DEFAULT_MAX_THREADS before including harness.h + +#ifndef tbb_tests_harness_H +#define tbb_tests_harness_H + +#include "tbb/tbb_config.h" + +namespace Harness { + enum TestResult { + Done, + Skipped, + Unknown + }; +} + +//! Entry point to a TBB unit test application +/** It MUST be defined by the test application. + + If HARNESS_NO_PARSE_COMMAND_LINE macro was not explicitly set before including harness.h, + then global variables MinThread, and MaxThread will be available and + initialized when it is called. + + Returns Harness::Done when the tests passed successfully. When the test fail, it must + not return, calling exit(errcode) or abort() instead. When the test is not supported + for the given platform/compiler/etc, it should return Harness::Skipped. + + To provide non-standard variant of main() for the test, define HARNESS_CUSTOM_MAIN + before including harness.h **/ +int TestMain (); + +#if __INTEL_COMPILER +#define __TBB_LAMBDAS_PRESENT ( _TBB_CPP0X && __INTEL_COMPILER > 1100 ) +#elif __GNUC__ +#define __TBB_LAMBDAS_PRESENT ( _TBB_CPP0X && __TBB_GCC_VERSION >= 40500 ) +#elif _MSC_VER +#define __TBB_LAMBDAS_PRESENT ( _MSC_VER>=1600 ) +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1400 + #define __TBB_EXCEPTION_TYPE_INFO_BROKEN 1 +#else + #define __TBB_EXCEPTION_TYPE_INFO_BROKEN 0 +#endif + +#if __SUNPRO_CC + #include <stdlib.h> + #include <string.h> +#else /* !__SUNPRO_CC */ + #include <cstdlib> +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + #include <cstring> +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif +#endif /* !__SUNPRO_CC */ + +#include <new> + +#if __TBB_MIC_NATIVE + #include "harness_mic.h" +#else + #define HARNESS_EXPORT + #define REPORT_FATAL_ERROR REPORT +#endif /* !__MIC__ */ + +#if _WIN32||_WIN64 + #include "tbb/machine/windows_api.h" +#if _XBOX + #undef HARNESS_NO_PARSE_COMMAND_LINE + #define HARNESS_NO_PARSE_COMMAND_LINE 1 +#endif + #include <process.h> +#else + #include <pthread.h> +#endif +#if __linux__ + #include <sys/utsname.h> /* for uname */ + #include <errno.h> /* for use in LinuxKernelVersion() */ +#endif + +#include "harness_report.h" + +#if !HARNESS_NO_ASSERT +#include "harness_assert.h" + +typedef void (*test_error_extra_t)(void); +static test_error_extra_t ErrorExtraCall; +//! Set additional handler to process failed assertions +void SetHarnessErrorProcessing( test_error_extra_t extra_call ) { + ErrorExtraCall = extra_call; + // TODO: add tbb::set_assertion_handler(ReportError); +} +//! Reports errors issued by failed assertions +void ReportError( const char* filename, int line, const char* expression, const char * message ) { +#if __TBB_ICL_11_1_CODE_GEN_BROKEN + printf("%s:%d, assertion %s: %s\n", filename, line, expression, message ? message : "failed" ); +#else + REPORT_FATAL_ERROR("%s:%d, assertion %s: %s\n", filename, line, expression, message ? message : "failed" ); +#endif + if( ErrorExtraCall ) + (*ErrorExtraCall)(); +#if HARNESS_TERMINATE_ON_ASSERT + TerminateProcess(GetCurrentProcess(), 1); +#elif HARNESS_EXIT_ON_ASSERT + exit(1); +#else + abort(); +#endif /* HARNESS_EXIT_ON_ASSERT */ +} +//! Reports warnings issued by failed warning assertions +void ReportWarning( const char* filename, int line, const char* expression, const char * message ) { + REPORT("Warning: %s:%d, assertion %s: %s\n", filename, line, expression, message ? message : "failed" ); +} +#else +//! Utility template function to prevent "unused" warnings by various compilers. +template<typename T> void suppress_unused_warning( const T& ) {} + +#define ASSERT(p,msg) (suppress_unused_warning(p), (void)0) +#define ASSERT_WARNING(p,msg) (suppress_unused_warning(p), (void)0) +#endif /* HARNESS_NO_ASSERT */ + +#if !HARNESS_NO_PARSE_COMMAND_LINE + +//! Controls level of commentary printed via printf-like REMARK() macro. +/** If true, makes the test print commentary. If false, test should print "done" and nothing more. */ +static bool Verbose; + +#ifndef HARNESS_DEFAULT_MIN_THREADS + #define HARNESS_DEFAULT_MIN_THREADS 1 +#endif + +//! Minimum number of threads +static int MinThread = HARNESS_DEFAULT_MIN_THREADS; + +#ifndef HARNESS_DEFAULT_MAX_THREADS + #define HARNESS_DEFAULT_MAX_THREADS 4 +#endif + +//! Maximum number of threads +static int MaxThread = HARNESS_DEFAULT_MAX_THREADS; + +//! Parse command line of the form "name [-v] [MinThreads[:MaxThreads]]" +/** Sets Verbose, MinThread, and MaxThread accordingly. + The nthread argument can be a single number or a range of the form m:n. + A single number m is interpreted as if written m:m. + The numbers must be non-negative. + Clients often treat the value 0 as "run sequentially." */ +static void ParseCommandLine( int argc, char* argv[] ) { + if( !argc ) REPORT("Command line with 0 arguments\n"); + int i = 1; + if( i<argc ) { + if( strncmp( argv[i], "-v", 2 )==0 ) { + Verbose = true; + ++i; + } + } + if( i<argc ) { + char* endptr; + MinThread = strtol( argv[i], &endptr, 0 ); + if( *endptr==':' ) + MaxThread = strtol( endptr+1, &endptr, 0 ); + else if( *endptr=='\0' ) + MaxThread = MinThread; + if( *endptr!='\0' ) { + REPORT_FATAL_ERROR("garbled nthread range\n"); + exit(1); + } + if( MinThread<0 ) { + REPORT_FATAL_ERROR("nthread must be nonnegative\n"); + exit(1); + } + if( MaxThread<MinThread ) { + REPORT_FATAL_ERROR("nthread range is backwards\n"); + exit(1); + } + ++i; + } +#if __TBB_STDARGS_BROKEN + if ( !argc ) + argc = 1; + else { + while ( i < argc && argv[i][0] == 0 ) + ++i; + } +#endif /* __TBB_STDARGS_BROKEN */ + if( i!=argc ) { + REPORT_FATAL_ERROR("Usage: %s [-v] [nthread|minthread:maxthread]\n", argv[0] ); + exit(1); + } +} +#endif /* HARNESS_NO_PARSE_COMMAND_LINE */ + +#if HARNESS_USE_PROXY + #define TBB_PREVIEW_RUNTIME_LOADER 1 + #include "tbb/runtime_loader.h" + static char const * _path[] = { ".", NULL }; + static tbb::runtime_loader _runtime_loader( _path ); +#endif // HARNESS_USE_PROXY + +#if !HARNESS_CUSTOM_MAIN + +#if __TBB_MPI_INTEROP +#undef SEEK_SET +#undef SEEK_CUR +#undef SEEK_END +#include "mpi.h" +#endif + +HARNESS_EXPORT +#if HARNESS_NO_PARSE_COMMAND_LINE +int main() { +#if __TBB_MPI_INTEROP + MPI_Init(NULL,NULL); +#endif +#else +int main(int argc, char* argv[]) { + ParseCommandLine( argc, argv ); +#if __TBB_MPI_INTEROP + MPI_Init(&argc,&argv); +#endif +#endif +#if __TBB_MPI_INTEROP + // Simple TBB/MPI interoperability harness for most of tests + // Worker processes send blocking messages to the master process about their rank and group size + // Master process receives this info and print it in verbose mode + int rank, size, myrank; + MPI_Status status; + MPI_Comm_size(MPI_COMM_WORLD,&size); + MPI_Comm_rank(MPI_COMM_WORLD,&myrank); + if (myrank == 0) { +#if !HARNESS_NO_PARSE_COMMAND_LINE + REMARK("Hello mpi world. I am %d of %d\n", myrank, size); +#endif + for ( int i = 1; i < size; i++ ) { + MPI_Recv (&rank, 1, MPI_INT, i, 1, MPI_COMM_WORLD, &status); + MPI_Recv (&size, 1, MPI_INT, i, 1, MPI_COMM_WORLD, &status); +#if !HARNESS_NO_PARSE_COMMAND_LINE + REMARK("Hello mpi world. I am %d of %d\n", rank, size); +#endif + } + } else { + MPI_Send (&myrank, 1, MPI_INT, 0, 1, MPI_COMM_WORLD); + MPI_Send (&size, 1, MPI_INT, 0, 1, MPI_COMM_WORLD); + } +#endif +#if __TBB_MIC + int res = Harness::Unknown; + #pragma offload target(mic:-1) out(res) + { + res = TestMain (); + } +#else + int res = TestMain (); +#endif + ASSERT( res==Harness::Done || res==Harness::Skipped, "Wrong return code by TestMain"); +#if __TBB_MPI_INTEROP + if (myrank == 0) { + REPORT( res==Harness::Done ? "done\n" : "skip\n" ); + } + MPI_Finalize(); +#else + REPORT( res==Harness::Done ? "done\n" : "skip\n" ); +#endif + return 0; +} + +#endif /* !HARNESS_CUSTOM_MAIN */ + +//! Base class for prohibiting compiler-generated operator= +class NoAssign { + //! Assignment not allowed + void operator=( const NoAssign& ); +public: +#if __GNUC__ + //! Explicitly define default construction, because otherwise gcc issues gratuitous warning. + NoAssign() {} +#endif /* __GNUC__ */ +}; + +//! Base class for prohibiting compiler-generated copy constructor or operator= +class NoCopy: NoAssign { + //! Copy construction not allowed + NoCopy( const NoCopy& ); +public: + NoCopy() {} +}; + +//! For internal use by template function NativeParallelFor +template<typename Index, typename Body> +class NativeParallelForTask: NoCopy { +public: + NativeParallelForTask( Index index_, const Body& body_ ) : + index(index_), + body(body_) + {} + + //! Start task + void start() { +#if _WIN32||_WIN64 + unsigned thread_id; + thread_handle = (HANDLE)_beginthreadex( NULL, 0, thread_function, this, 0, &thread_id ); + ASSERT( thread_handle!=0, "NativeParallelFor: _beginthreadex failed" ); +#else +#if __ICC==1100 + #pragma warning (push) + #pragma warning (disable: 2193) +#endif /* __ICC==1100 */ + // Some machines may have very large hard stack limit. When the test is + // launched by make, the default stack size is set to the hard limit, and + // calls to pthread_create fail with out-of-memory error. + // Therefore we set the stack size explicitly (as for TBB worker threads). +// TODO: make a single definition of MByte used by all tests. + const size_t MByte = 1024*1024; +#if __i386__||__i386 + const size_t stack_size = 1*MByte; +#elif __x86_64__ + const size_t stack_size = 2*MByte; +#else + const size_t stack_size = 4*MByte; +#endif + pthread_attr_t attr_stack; + int status = pthread_attr_init(&attr_stack); + ASSERT(0==status, "NativeParallelFor: pthread_attr_init failed"); + status = pthread_attr_setstacksize( &attr_stack, stack_size ); + ASSERT(0==status, "NativeParallelFor: pthread_attr_setstacksize failed"); + status = pthread_create(&thread_id, &attr_stack, thread_function, this); + ASSERT(0==status, "NativeParallelFor: pthread_create failed"); + pthread_attr_destroy(&attr_stack); +#if __ICC==1100 + #pragma warning (pop) +#endif +#endif /* _WIN32||_WIN64 */ + } + + //! Wait for task to finish + void wait_to_finish() { +#if _WIN32||_WIN64 + DWORD status = WaitForSingleObject( thread_handle, INFINITE ); + ASSERT( status!=WAIT_FAILED, "WaitForSingleObject failed" ); + CloseHandle( thread_handle ); +#else + int status = pthread_join( thread_id, NULL ); + ASSERT( !status, "pthread_join failed" ); +#endif +#if HARNESS_NO_ASSERT + (void)status; +#endif + } + +private: +#if _WIN32||_WIN64 + HANDLE thread_handle; +#else + pthread_t thread_id; +#endif + + //! Range over which task will invoke the body. + const Index index; + + //! Body to invoke over the range. + const Body body; + +#if _WIN32||_WIN64 + static unsigned __stdcall thread_function( void* object ) +#else + static void* thread_function(void* object) +#endif + { + NativeParallelForTask& self = *static_cast<NativeParallelForTask*>(object); + (self.body)(self.index); + return 0; + } +}; + +//! Execute body(i) in parallel for i in the interval [0,n). +/** Each iteration is performed by a separate thread. */ +template<typename Index, typename Body> +void NativeParallelFor( Index n, const Body& body ) { + typedef NativeParallelForTask<Index,Body> task; + + if( n>0 ) { + // Allocate array to hold the tasks + task* array = static_cast<task*>(operator new( n*sizeof(task) )); + + // Construct the tasks + for( Index i=0; i!=n; ++i ) + new( &array[i] ) task(i,body); + + // Start the tasks + for( Index i=0; i!=n; ++i ) + array[i].start(); + + // Wait for the tasks to finish and destroy each one. + for( Index i=n; i; --i ) { + array[i-1].wait_to_finish(); + array[i-1].~task(); + } + + // Deallocate the task array + operator delete(array); + } +} + +//! The function to zero-initialize arrays; useful to avoid warnings +template <typename T> +void zero_fill(void* array, size_t n) { + memset(array, 0, sizeof(T)*n); +} + +#if __SUNPRO_CC && defined(min) +#undef min +#undef max +#endif + +#ifndef min +//! Utility template function returning lesser of the two values. +/** Provided here to avoid including not strict safe <algorithm>.\n + In case operands cause signed/unsigned or size mismatch warnings it is caller's + responsibility to do the appropriate cast before calling the function. **/ +template<typename T1, typename T2> +T1 min ( const T1& val1, const T2& val2 ) { + return val1 < val2 ? val1 : val2; +} +#endif /* !min */ + +#ifndef max +//! Utility template function returning greater of the two values. +/** Provided here to avoid including not strict safe <algorithm>.\n + In case operands cause signed/unsigned or size mismatch warnings it is caller's + responsibility to do the appropriate cast before calling the function. **/ +template<typename T1, typename T2> +T1 max ( const T1& val1, const T2& val2 ) { + return val1 < val2 ? val2 : val1; +} +#endif /* !max */ + +#if __linux__ +inline unsigned LinuxKernelVersion() +{ + unsigned digit1, digit2, digit3; + struct utsname utsnameBuf; + + if (-1 == uname(&utsnameBuf)) { + REPORT_FATAL_ERROR("Can't call uname: errno %d\n", errno); + exit(1); + } + if (3 != sscanf(utsnameBuf.release, "%u.%u.%u", &digit1, &digit2, &digit3)) { + REPORT_FATAL_ERROR("Unable to parse OS release '%s'\n", utsnameBuf.release); + exit(1); + } + return 1000000*digit1+1000*digit2+digit3; +} +#endif + +namespace Harness { + +#if !HARNESS_NO_ASSERT +//! Base class that asserts that no operations are made with the object after its destruction. +class NoAfterlife { +protected: + enum state_t { + LIVE=0x56781234, + DEAD=0xDEADBEEF + } m_state; + +public: + NoAfterlife() : m_state(LIVE) {} + NoAfterlife( const NoAfterlife& src ) : m_state(LIVE) { + ASSERT( src.IsLive(), "Constructing from the dead source" ); + } + ~NoAfterlife() { + ASSERT( IsLive(), "Repeated destructor call" ); + m_state = DEAD; + } + const NoAfterlife& operator=( const NoAfterlife& src ) { + ASSERT( IsLive(), NULL ); + ASSERT( src.IsLive(), NULL ); + return *this; + } + void AssertLive() const { + ASSERT( IsLive(), "Already dead" ); + } + bool IsLive() const { + return m_state == LIVE; + } +}; // NoAfterlife +#endif /* !HARNESS_NO_ASSERT */ + +#if _WIN32 || _WIN64 + void Sleep ( int ms ) { ::Sleep(ms); } + + typedef DWORD tid_t; + tid_t CurrentTid () { return GetCurrentThreadId(); } + +#else /* !WIN */ + + void Sleep ( int ms ) { + timespec requested = { ms / 1000, (ms % 1000)*1000000 }; + timespec remaining = { 0, 0 }; + nanosleep(&requested, &remaining); + } + + typedef pthread_t tid_t; + tid_t CurrentTid () { return pthread_self(); } +#endif /* !WIN */ + +} // namespace Harness + +#endif /* tbb_tests_harness_H */ diff --git a/src/tbb/src/test/harness_allocator.h b/src/tbb/src/test/harness_allocator.h new file mode 100644 index 0000000..43e124e --- /dev/null +++ b/src/tbb/src/test/harness_allocator.h @@ -0,0 +1,293 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Declarations for simple estimate of the memory being used by a program. +// Not yet implemented for Mac. +// This header is an optional part of the test harness. +// It assumes that "harness_assert.h" has already been included. + +#if __linux__ || __APPLE__ || __sun +#include <unistd.h> +#elif _WIN32 +#include "tbb/machine/windows_api.h" +#endif /* OS specific */ +#include <new> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include <stdexcept> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +#include "tbb/atomic.h" + +#if __SUNPRO_CC +using std::printf; +#endif + +#if defined(_MSC_VER) && defined(_Wp64) + // Workaround for overzealous compiler warnings in /Wp64 mode + #pragma warning (push) + #pragma warning (disable: 4267) +#endif + + +template <typename base_alloc_t, typename count_t = tbb::atomic<size_t> > +class static_counting_allocator : public base_alloc_t +{ +public: + typedef typename base_alloc_t::pointer pointer; + typedef typename base_alloc_t::const_pointer const_pointer; + typedef typename base_alloc_t::reference reference; + typedef typename base_alloc_t::const_reference const_reference; + typedef typename base_alloc_t::value_type value_type; + typedef typename base_alloc_t::size_type size_type; + typedef typename base_alloc_t::difference_type difference_type; + template<typename U> struct rebind { + typedef static_counting_allocator<typename base_alloc_t::template rebind<U>::other,count_t> other; + }; + + static size_t max_items; + static count_t items_allocated; + static count_t items_freed; + static count_t allocations; + static count_t frees; + static bool verbose, throwing; + + static_counting_allocator() throw() { } + + static_counting_allocator(const base_alloc_t& src) throw() + : base_alloc_t(src) { } + + static_counting_allocator(const static_counting_allocator& src) throw() + : base_alloc_t(src) { } + + template<typename U, typename C> + static_counting_allocator(const static_counting_allocator<U, C>& src) throw() + : base_alloc_t(src) { } + + pointer allocate(const size_type n) + { + if(verbose) printf("\t+%d|", int(n)); + if(max_items && items_allocated + n >= max_items) { + if(verbose) printf("items limit hits!"); + if(throwing) + __TBB_THROW( std::bad_alloc() ); + return NULL; + } + allocations++; + items_allocated += n; + return base_alloc_t::allocate(n, pointer(0)); + } + + pointer allocate(const size_type n, const void * const) + { return allocate(n); } + + void deallocate(const pointer ptr, const size_type n) + { + if(verbose) printf("\t-%d|", int(n)); + frees++; + items_freed += n; + base_alloc_t::deallocate(ptr, n); + } + + static void init_counters(bool v = false) { + verbose = v; + if(verbose) printf("\n------------------------------------------- Allocations:\n"); + items_allocated = 0; + items_freed = 0; + allocations = 0; + frees = 0; + max_items = 0; + } + + static void set_limits(size_type max = 0, bool do_throw = true) { + max_items = max; + throwing = do_throw; + } +}; + +template <typename base_alloc_t, typename count_t> +size_t static_counting_allocator<base_alloc_t, count_t>::max_items; +template <typename base_alloc_t, typename count_t> +count_t static_counting_allocator<base_alloc_t, count_t>::items_allocated; +template <typename base_alloc_t, typename count_t> +count_t static_counting_allocator<base_alloc_t, count_t>::items_freed; +template <typename base_alloc_t, typename count_t> +count_t static_counting_allocator<base_alloc_t, count_t>::allocations; +template <typename base_alloc_t, typename count_t> +count_t static_counting_allocator<base_alloc_t, count_t>::frees; +template <typename base_alloc_t, typename count_t> +bool static_counting_allocator<base_alloc_t, count_t>::verbose; +template <typename base_alloc_t, typename count_t> +bool static_counting_allocator<base_alloc_t, count_t>::throwing; + +template <typename base_alloc_t, typename count_t = tbb::atomic<size_t> > +class local_counting_allocator : public base_alloc_t +{ +public: + typedef typename base_alloc_t::pointer pointer; + typedef typename base_alloc_t::const_pointer const_pointer; + typedef typename base_alloc_t::reference reference; + typedef typename base_alloc_t::const_reference const_reference; + typedef typename base_alloc_t::value_type value_type; + typedef typename base_alloc_t::size_type size_type; + typedef typename base_alloc_t::difference_type difference_type; + template<typename U> struct rebind { + typedef local_counting_allocator<typename base_alloc_t::template rebind<U>::other,count_t> other; + }; + + count_t items_allocated; + count_t items_freed; + count_t allocations; + count_t frees; + size_t max_items; + + local_counting_allocator() throw() { + items_allocated = 0; + items_freed = 0; + allocations = 0; + frees = 0; + max_items = 0; + } + + local_counting_allocator(const local_counting_allocator &a) throw() + : base_alloc_t(a) + , items_allocated(a.items_allocated) + , items_freed(a.items_freed) + , allocations(a.allocations) + , frees(a.frees) + , max_items(a.max_items) + { } + + template<typename U, typename C> + local_counting_allocator(const static_counting_allocator<U,C> &) throw() { + items_allocated = static_counting_allocator<U,C>::items_allocated; + items_freed = static_counting_allocator<U,C>::items_freed; + allocations = static_counting_allocator<U,C>::allocations; + frees = static_counting_allocator<U,C>::frees; + max_items = static_counting_allocator<U,C>::max_items; + } + + template<typename U, typename C> + local_counting_allocator(const local_counting_allocator<U,C> &a) throw() + : items_allocated(a.items_allocated) + , items_freed(a.items_freed) + , allocations(a.allocations) + , frees(a.frees) + , max_items(a.max_items) + { } + + bool operator==(const local_counting_allocator &a) const + { return &a == this; } + + pointer allocate(const size_type n) + { + if(max_items && items_allocated + n >= max_items) + __TBB_THROW( std::bad_alloc() ); + ++allocations; + items_allocated += n; + return base_alloc_t::allocate(n, pointer(0)); + } + + pointer allocate(const size_type n, const void * const) + { return allocate(n); } + + void deallocate(const pointer ptr, const size_type n) + { + ++frees; + items_freed += n; + base_alloc_t::deallocate(ptr, n); + } + + void set_limits(size_type max = 0) { + max_items = max; + } +}; + +template <typename T, template<typename X> class Allocator = std::allocator> +class debug_allocator : public Allocator<T> +{ +public: + typedef Allocator<T> base_allocator_type; + typedef typename base_allocator_type::value_type value_type; + typedef typename base_allocator_type::pointer pointer; + typedef typename base_allocator_type::const_pointer const_pointer; + typedef typename base_allocator_type::reference reference; + typedef typename base_allocator_type::const_reference const_reference; + typedef typename base_allocator_type::size_type size_type; + typedef typename base_allocator_type::difference_type difference_type; + template<typename U> struct rebind { + typedef debug_allocator<U, Allocator> other; + }; + + debug_allocator() throw() { } + debug_allocator(const debug_allocator &a) throw() : base_allocator_type( a ) { } + template<typename U> + debug_allocator(const debug_allocator<U> &a) throw() : base_allocator_type( Allocator<U>( a ) ) { } + + pointer allocate(const size_type n, const void *hint = 0 ) { + pointer ptr = base_allocator_type::allocate( n, hint ); + std::memset( ptr, 0xE3E3E3E3, n * sizeof(value_type) ); + return ptr; + } +}; + +//! Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1 +/** @ingroup memory_allocation */ +template<template<typename T> class Allocator> +class debug_allocator<void, Allocator> : public Allocator<void> { +public: + typedef Allocator<void> base_allocator_type; + typedef typename base_allocator_type::value_type value_type; + typedef typename base_allocator_type::pointer pointer; + typedef typename base_allocator_type::const_pointer const_pointer; + template<typename U> struct rebind { + typedef debug_allocator<U, Allocator> other; + }; +}; + +template<typename T1, template<typename X1> class B1, typename T2, template<typename X2> class B2> +inline bool operator==( const debug_allocator<T1,B1> &a, const debug_allocator<T2,B2> &b) { + return static_cast< B1<T1> >(a) == static_cast< B2<T2> >(b); +} +template<typename T1, template<typename X1> class B1, typename T2, template<typename X2> class B2> +inline bool operator!=( const debug_allocator<T1,B1> &a, const debug_allocator<T2,B2> &b) { + return static_cast< B1<T1> >(a) != static_cast< B2<T2> >(b); +} + +#if defined(_MSC_VER) && defined(_Wp64) + // Workaround for overzealous compiler warnings in /Wp64 mode + #pragma warning (pop) +#endif // warning 4267 is back diff --git a/src/tbb/src/test/harness_assert.h b/src/tbb/src/test/harness_assert.h new file mode 100644 index 0000000..8b0e822 --- /dev/null +++ b/src/tbb/src/test/harness_assert.h @@ -0,0 +1,48 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Just the assertion portion of the harness. +// This is useful for writing portions of tests that include +// the minimal number of necessary header files. +// +// The full "harness.h" must be included later. + +#ifndef harness_assert_H +#define harness_assert_H + +void ReportError( const char* filename, int line, const char* expression, const char* message); +void ReportWarning( const char* filename, int line, const char* expression, const char* message); + +#define ASSERT(p,message) ((p)?(void)0:ReportError(__FILE__,__LINE__,#p,message)) +#define ASSERT_WARNING(p,message) ((p)?(void)0:ReportWarning(__FILE__,__LINE__,#p,message)) + +//! Compile-time error if x and y have different types +template<typename T> +void AssertSameType( const T& /*x*/, const T& /*y*/ ) {} + +#endif /* harness_assert_H */ diff --git a/src/tbb/src/test/harness_bad_expr.h b/src/tbb/src/test/harness_bad_expr.h new file mode 100644 index 0000000..c8cc7aa --- /dev/null +++ b/src/tbb/src/test/harness_bad_expr.h @@ -0,0 +1,85 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Declarations for checking __TBB_ASSERT checks inside TBB. +// This header is an optional part of the test harness. +// It assumes that "harness.h" has already been included. + +#define TRY_BAD_EXPR_ENABLED (TBB_USE_ASSERT && TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN) + +#if TRY_BAD_EXPR_ENABLED + +//! Check that expression x raises assertion failure with message containing given substring. +/** Assumes that tbb::set_assertion_handler( AssertionFailureHandler ) was called earlier. */ +#define TRY_BAD_EXPR(x,substr) \ + { \ + const char* message = NULL; \ + bool okay = false; \ + try { \ + x; \ + } catch( AssertionFailure a ) { \ + okay = true; \ + message = a.message; \ + } \ + CheckAssertionFailure(__LINE__,#x,okay,message,substr); \ + } + +//! Exception object that holds a message. +struct AssertionFailure { + const char* message; + AssertionFailure( const char* filename, int line, const char* expression, const char* comment ); +}; + +AssertionFailure::AssertionFailure( const char* filename, int line, const char* expression, const char* comment ) : + message(comment) +{ + ASSERT(filename,"missing filename"); + ASSERT(0<line,"line number must be positive"); + // All of our current files have fewer than 4000 lines. + ASSERT(line<5000,"dubiously high line number"); + ASSERT(expression,"missing expression"); +} + +void AssertionFailureHandler( const char* filename, int line, const char* expression, const char* comment ) { + throw AssertionFailure(filename,line,expression,comment); +} + +void CheckAssertionFailure( int line, const char* expression, bool okay, const char* message, const char* substr ) { + if( !okay ) { + REPORT("Line %d, %s failed to fail\n", line, expression ); + abort(); + } else if( !message ) { + REPORT("Line %d, %s failed without a message\n", line, expression ); + abort(); + } else if( strstr(message,substr)==0 ) { + REPORT("Line %d, %s failed with message '%s' missing substring '%s'\n", __LINE__, expression, message, substr ); + abort(); + } +} + +#endif /* TRY_BAD_EXPR_ENABLED */ diff --git a/src/tbb/src/test/harness_barrier.h b/src/tbb/src/test/harness_barrier.h new file mode 100644 index 0000000..3923df7 --- /dev/null +++ b/src/tbb/src/test/harness_barrier.h @@ -0,0 +1,84 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/atomic.h" + +#ifndef harness_barrier_H +#define harness_barrier_H + +namespace Harness { + +class SpinBarrier +{ + unsigned numThreads; + tbb::atomic<unsigned> numThreadsFinished; /* threads reached barrier in this epoch */ + tbb::atomic<unsigned> epoch; /* how many times this barrier used - XXX move to a separate cache line */ + + struct DummyCallback { + void operator() () const {} + }; + + SpinBarrier( const SpinBarrier& ); // no copy ctor + void operator=( const SpinBarrier& ); // no assignment +public: + SpinBarrier( unsigned nthreads = 0 ) { initialize(nthreads); }; + + void initialize( unsigned nthreads ) { + numThreads = nthreads; + numThreadsFinished = 0; + epoch = 0; + }; + + // onOpenBarrierCallback is called by last thread arrived on a barrier + template<typename Callback> + bool wait(const Callback &onOpenBarrierCallback) + { // return true if last thread + unsigned myEpoch = epoch; + int threadsLeft = numThreads - numThreadsFinished.fetch_and_increment() - 1; + ASSERT(threadsLeft>=0, "Broken barrier"); + if (threadsLeft > 0) { + /* not the last threading reaching barrier, wait until epoch changes & return 0 */ + tbb::internal::spin_wait_while_eq(epoch, myEpoch); + return false; + } + /* No more threads left to enter, so I'm the last one reaching this epoch; + reset the barrier, increment epoch, and return non-zero */ + onOpenBarrierCallback(); + numThreadsFinished = 0; + epoch = myEpoch+1; /* wakes up threads waiting to exit this epoch */ + return true; + } + bool wait() + { + return wait(DummyCallback()); + } +}; + +} + +#endif //harness_barrier_H diff --git a/src/tbb/src/test/harness_concurrency_tracker.h b/src/tbb/src/test/harness_concurrency_tracker.h new file mode 100644 index 0000000..a0c562f --- /dev/null +++ b/src/tbb/src/test/harness_concurrency_tracker.h @@ -0,0 +1,85 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef tbb_tests_harness_concurrency_tracker_H +#define tbb_tests_harness_concurrency_tracker_H + +#include "harness.h" +#include "tbb/atomic.h" +#include "../tbb/tls.h" + +namespace Harness { + +static tbb::atomic<unsigned> ctInstantParallelism; +static tbb::atomic<unsigned> ctPeakParallelism; +static tbb::internal::tls<uintptr_t> ctNested; + +class ConcurrencyTracker { + bool m_Outer; + + static void Started () { + unsigned p = ++ctInstantParallelism; + unsigned q = ctPeakParallelism; + while( q<p ) { + q = ctPeakParallelism.compare_and_swap(p,q); + } + } + + static void Stopped () { + ASSERT ( ctInstantParallelism > 0, "Mismatched call to ConcurrencyTracker::Stopped()" ); + --ctInstantParallelism; + } +public: + ConcurrencyTracker() : m_Outer(false) { + uintptr_t nested = ctNested; + ASSERT (nested == 0 || nested == 1, NULL); + if ( !ctNested ) { + Started(); + m_Outer = true; + ctNested = 1; + } + } + ~ConcurrencyTracker() { + if ( m_Outer ) { + Stopped(); + ctNested = 0; + } + } + + static unsigned PeakParallelism() { return ctPeakParallelism; } + static unsigned InstantParallelism() { return ctInstantParallelism; } + + static void Reset() { + ASSERT (ctInstantParallelism == 0, "Reset cannot be called when concurrency tracking is underway"); + ctInstantParallelism = ctPeakParallelism = 0; + } +}; // ConcurrencyTracker + +} // namespace Harness + +#endif /* tbb_tests_harness_concurrency_tracker_H */ diff --git a/src/tbb/src/test/harness_cpu.h b/src/tbb/src/test/harness_cpu.h new file mode 100644 index 0000000..1e58c38 --- /dev/null +++ b/src/tbb/src/test/harness_cpu.h @@ -0,0 +1,129 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Declarations for simple estimate of CPU time being used by a program. +// This header is an optional part of the test harness. +// It assumes that "harness_assert.h" has already been included. + +#if _WIN32 +#if !_XBOX + #include <windows.h> +#endif +#else + #include <sys/time.h> + #include <sys/resource.h> +#endif + +//! Return time (in seconds) spent by the current process in user mode. +/* Returns 0 if not implemented on platform. */ +static double GetCPUUserTime() { +#if _XBOX + return 0; +#elif _WIN32 + FILETIME my_times[4]; + bool status = GetProcessTimes(GetCurrentProcess(), my_times, my_times+1, my_times+2, my_times+3)!=0; + ASSERT( status, NULL ); + LARGE_INTEGER usrtime; + usrtime.LowPart = my_times[3].dwLowDateTime; + usrtime.HighPart = my_times[3].dwHighDateTime; + return double(usrtime.QuadPart)*1E-7; +#else + // Generic UNIX, including __APPLE__ + + // On Linux, there is no good way to get CPU usage info for the current process: + // getrusage(RUSAGE_SELF, ...) that is used now only returns info for the calling thread; + // getrusage(RUSAGE_CHILDREN, ...) only counts for finished children threads; + // tms_utime and tms_cutime got with times(struct tms*) are equivalent to the above items; + // finally, /proc/self/task/<task_id>/stat doesn't exist on older kernels + // and it isn't quite convenient to read it for every task_id. + + struct rusage resources; + bool status = getrusage(RUSAGE_SELF, &resources)==0; + ASSERT( status, NULL ); + return (double(resources.ru_utime.tv_sec)*1E6 + double(resources.ru_utime.tv_usec))*1E-6; +#endif +} + +#include "tbb/tick_count.h" +#include <cstdio> + +// The resolution of GetCPUUserTime is 10-15 ms or so; waittime should be a few times bigger. +const double WAITTIME = 0.1; // in seconds, i.e. 100 ms +const double THRESHOLD = WAITTIME/100; + +static void TestCPUUserTime( int nthreads, int nactive = 1 ) { + // The test will always pass on Linux; read the comments in GetCPUUserTime for details + // Also it will not detect spinning issues on systems with only one processing core. + + int nworkers = nthreads-nactive; + if( !nworkers ) return; + double lastusrtime = GetCPUUserTime(); + if( !lastusrtime ) return; + + static double minimal_waittime = WAITTIME, + maximal_waittime = WAITTIME * 10; + double usrtime; + double waittime; + tbb::tick_count stamp = tbb::tick_count::now(); + // wait for GetCPUUserTime update + while( (usrtime=GetCPUUserTime())-lastusrtime < THRESHOLD ) { + volatile intptr_t k = (intptr_t)&usrtime; + for ( int i = 0; i < 1000; ++i ) ++k; + if ( (waittime = (tbb::tick_count::now()-stamp).seconds()) > maximal_waittime ) { + REPORT( "Warning: %.2f sec elapsed but user mode time is still below its threshold (%g < %g)\n", + waittime, usrtime - lastusrtime, THRESHOLD ); + break; + } + } + lastusrtime = usrtime; + + // Wait for workers to go sleep + stamp = tbb::tick_count::now(); + while( ((waittime=(tbb::tick_count::now()-stamp).seconds()) < minimal_waittime) + || ((usrtime=GetCPUUserTime()-lastusrtime) < THRESHOLD) ) + { + if ( waittime > maximal_waittime ) { + REPORT( "Warning: %.2f sec elapsed but GetCPUUserTime reported only %g sec\n", waittime, usrtime ); + break; + } + } + + // Test that all workers sleep when no work. + while( nactive>1 && usrtime-nactive*waittime<0 ) { + // probably the number of active threads was mispredicted + --nactive; ++nworkers; + } + double avg_worker_usrtime = (usrtime-nactive*waittime)/nworkers; + + if( avg_worker_usrtime > waittime/2 ) + REPORT( "ERROR: %d worker threads are spinning; waittime: %g; usrtime: %g; avg worker usrtime: %g\n", + nworkers, waittime, usrtime, avg_worker_usrtime); + else + REMARK("%d worker threads; waittime: %g; usrtime: %g; avg worker usrtime: %g\n", + nworkers, waittime, usrtime, avg_worker_usrtime); +} diff --git a/src/tbb/src/test/harness_defs.h b/src/tbb/src/test/harness_defs.h new file mode 100644 index 0000000..9a13a68 --- /dev/null +++ b/src/tbb/src/test/harness_defs.h @@ -0,0 +1,50 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef __TBB_harness_defs_H +#define __TBB_harness_defs_H + +#include "tbb/tbb_config.h" + +#if __TBB_TEST_PIC && !__PIC__ +#define __TBB_TEST_SKIP_PIC_MODE 1 +#else +#define __TBB_TEST_SKIP_PIC_MODE 0 +#endif + +#if __TBB_TEST_GCC_BUILTINS && !__TBB_GCC_BUILTIN_ATOMICS_PRESENT +#define __TBB_TEST_SKIP_BUILTINS_MODE 1 +#else +#define __TBB_TEST_SKIP_BUILTINS_MODE 0 +#endif + +#ifndef TBB_USE_GCC_BUILTINS + #define TBB_USE_GCC_BUILTINS __TBB_TEST_GCC_BUILTINS && __TBB_GCC_BUILTIN_ATOMICS_PRESENT +#endif + +#endif /* __TBB_harness_defs_H */ diff --git a/src/tbb/src/test/harness_dynamic_libs.h b/src/tbb/src/test/harness_dynamic_libs.h new file mode 100644 index 0000000..2b26f85 --- /dev/null +++ b/src/tbb/src/test/harness_dynamic_libs.h @@ -0,0 +1,85 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if _WIN32 || _WIN64 +#include "tbb/machine/windows_api.h" +#else +#include <dlfcn.h> +#endif + +namespace Harness { + +#if _WIN32 || _WIN64 +typedef HMODULE LIBRARY_HANDLE; +#else +typedef void *LIBRARY_HANDLE; +#endif + +#if _WIN32 || _WIN64 +#define TEST_LIBRARY_NAME(base) base".dll" +#elif __APPLE__ +#define TEST_LIBRARY_NAME(base) base".dylib" +#else +#define TEST_LIBRARY_NAME(base) base".so" +#endif + +LIBRARY_HANDLE OpenLibrary(const char *name) +{ +#if _WIN32 || _WIN64 + return ::LoadLibrary(name); +#else + return dlopen(name, RTLD_NOW|RTLD_GLOBAL); +#endif +} + +void CloseLibrary(LIBRARY_HANDLE lib) +{ +#if _WIN32 || _WIN64 + BOOL ret = FreeLibrary(lib); + ASSERT(ret, "FreeLibrary must be successful"); +#else + int ret = dlclose(lib); + ASSERT(ret == 0, "dlclose must be successful"); +#endif +} + +typedef void (*FunctionAddress)(); + +FunctionAddress GetAddress(Harness::LIBRARY_HANDLE lib, const char *name) +{ + union { FunctionAddress func; void *symb; } converter; +#if _WIN32 || _WIN64 + converter.symb = (void*)GetProcAddress(lib, name); +#else + converter.symb = (void*)dlsym(lib, name); +#endif + ASSERT(converter.func, "Can't find required symbol in dynamic library"); + return converter.func; +} + +} // namespace Harness diff --git a/src/tbb/src/test/harness_eh.h b/src/tbb/src/test/harness_eh.h new file mode 100644 index 0000000..7c93435 --- /dev/null +++ b/src/tbb/src/test/harness_eh.h @@ -0,0 +1,235 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include <typeinfo> +#include "tbb/tbb_exception.h" +#include "tbb/atomic.h" +#include "harness.h" +#include "harness_concurrency_tracker.h" + +int g_NumThreads = 0; +Harness::tid_t g_Master = 0; + +tbb::atomic<intptr_t> g_CurExecuted, + g_ExecutedAtCatch, + g_ExceptionsThrown; +volatile bool g_ExceptionCaught = false, + g_UnknownException = false; + +volatile bool g_ThrowException = true, + g_Flog = false; + +bool g_ExceptionInMaster = false; +bool g_SolitaryException = false; + +//! Number of exceptions propagated into the user code (i.e. intercepted by the tests) +tbb::atomic<intptr_t> g_Exceptions; + +inline void ResetEhGlobals ( bool throwException = true, bool flog = false ) { + Harness::ConcurrencyTracker::Reset(); + g_CurExecuted = g_ExecutedAtCatch = 0; + g_ExceptionCaught = false; + g_UnknownException = false; + g_ThrowException = throwException; + g_Flog = flog; + g_ExceptionsThrown = g_Exceptions = 0; +} + +#if TBB_USE_EXCEPTIONS +class test_exception : public std::exception { + const char* my_description; +public: + test_exception ( const char* description ) : my_description(description) {} + + const char* what() const throw() { return my_description; } +}; + +class solitary_test_exception : public test_exception { +public: + solitary_test_exception ( const char* description ) : test_exception(description) {} +}; + +#if TBB_USE_CAPTURED_EXCEPTION + typedef tbb::captured_exception PropagatedException; + #define EXCEPTION_NAME(e) e.name() +#else + typedef test_exception PropagatedException; + #define EXCEPTION_NAME(e) typeid(e).name() +#endif + +#define EXCEPTION_DESCR "Test exception" + +#if HARNESS_EH_SIMPLE_MODE + +static void ThrowTestException () { + ++g_ExceptionsThrown; + throw test_exception(EXCEPTION_DESCR); +} + +#else /* !HARNESS_EH_SIMPLE_MODE */ + +static void ThrowTestException ( intptr_t threshold ) { + if ( !g_ThrowException || (!g_Flog && (g_ExceptionInMaster ^ (Harness::CurrentTid() == g_Master))) ) + return; + while ( Existed() < threshold ) + __TBB_Yield(); + if ( !g_SolitaryException ) { + ++g_ExceptionsThrown; + throw test_exception(EXCEPTION_DESCR); + } + if ( g_ExceptionsThrown.compare_and_swap(1, 0) == 0 ) + throw solitary_test_exception(EXCEPTION_DESCR); +} +#endif /* !HARNESS_EH_SIMPLE_MODE */ + +#define CATCH() \ + } catch ( PropagatedException& e ) { \ + g_ExecutedAtCatch = g_CurExecuted; \ + ASSERT( e.what(), "Empty what() string" ); \ + ASSERT (__TBB_EXCEPTION_TYPE_INFO_BROKEN || strcmp(EXCEPTION_NAME(e), (g_SolitaryException ? typeid(solitary_test_exception) : typeid(test_exception)).name() ) == 0, "Unexpected original exception name"); \ + ASSERT (__TBB_EXCEPTION_TYPE_INFO_BROKEN || strcmp(e.what(), EXCEPTION_DESCR) == 0, "Unexpected original exception info"); \ + g_ExceptionCaught = exceptionCaught = true; \ + ++g_Exceptions; \ + } catch ( tbb::tbb_exception& e ) { \ + REPORT("Unexpected %s\n", e.name()); \ + ASSERT (g_UnknownException && !g_UnknownException, "Unexpected tbb::tbb_exception" ); \ + } catch ( std::exception& e ) { \ + REPORT("Unexpected %s\n", typeid(e).name()); \ + ASSERT (g_UnknownException && !g_UnknownException, "Unexpected std::exception" ); \ + } catch ( ... ) { \ + g_ExceptionCaught = exceptionCaught = true; \ + g_UnknownException = unknownException = true; \ + } \ + if ( !g_SolitaryException ) \ + REMARK_ONCE ("Multiple exceptions mode: %d throws", (intptr_t)g_ExceptionsThrown); + +#define ASSERT_EXCEPTION() \ + ASSERT (g_ExceptionsThrown ? g_ExceptionCaught : true, "throw without catch"); \ + ASSERT (!g_ExceptionsThrown ? !g_ExceptionCaught : true, "catch without throw"); \ + ASSERT (g_ExceptionCaught, "no exception occurred"); \ + ASSERT (__TBB_EXCEPTION_TYPE_INFO_BROKEN || !g_UnknownException, "unknown exception was caught") + +#define CATCH_AND_ASSERT() \ + CATCH() \ + ASSERT_EXCEPTION() + +#else /* !TBB_USE_EXCEPTIONS */ + +inline void ThrowTestException ( intptr_t ) {} + +#endif /* !TBB_USE_EXCEPTIONS */ + +#define TRY() \ + bool exceptionCaught = false, unknownException = false; \ + __TBB_TRY { + +// "exceptionCaught || unknownException" is used only to "touch" otherwise unused local variables +#define CATCH_AND_FAIL() } __TBB_CATCH(...) { \ + ASSERT (false, "Canceling tasks must not cause any exceptions"); \ + (void)(exceptionCaught && unknownException); \ + } + +const int c_Timeout = 1000000; + +void WaitUntilConcurrencyPeaks ( int expected_peak ) { + if ( g_Flog ) + return; + int n = 0; +retry: + while ( ++n < c_Timeout && (int)Harness::ConcurrencyTracker::PeakParallelism() < expected_peak ) + __TBB_Yield(); + ASSERT_WARNING( n < c_Timeout, "Missed wakeup or machine is overloaded?" ); + // Workaround in case a missed wakeup takes place + if ( n == c_Timeout ) { + tbb::task &r = *new( tbb::task::allocate_root() ) tbb::empty_task(); + r.spawn(r); + n = 0; + goto retry; + } +} + +inline void WaitUntilConcurrencyPeaks () { WaitUntilConcurrencyPeaks(g_NumThreads); } + +inline bool IsMaster() { + return Harness::CurrentTid() == g_Master; +} + +inline bool IsThrowingThread() { + return g_ExceptionInMaster ^ IsMaster() ? true : false; +} + +class CancellatorTask : public tbb::task { + static volatile bool s_Ready; + tbb::task_group_context &m_groupToCancel; + intptr_t m_cancellationThreshold; + + tbb::task* execute () { + Harness::ConcurrencyTracker ct; + s_Ready = true; + while ( g_CurExecuted < m_cancellationThreshold ) + __TBB_Yield(); + m_groupToCancel.cancel_group_execution(); + g_ExecutedAtCatch = g_CurExecuted; + return NULL; + } +public: + CancellatorTask ( tbb::task_group_context& ctx, intptr_t threshold ) + : m_groupToCancel(ctx), m_cancellationThreshold(threshold) + { + s_Ready = false; + } + + static void Reset () { s_Ready = false; } + + static bool WaitUntilReady () { + const intptr_t limit = 10000000; + intptr_t n = 0; + do { + __TBB_Yield(); + } while( !s_Ready && ++n < limit ); + ASSERT( s_Ready || n == limit, NULL ); + return s_Ready; + } +}; + +volatile bool CancellatorTask::s_Ready = false; + +template<class LauncherTaskT, class CancellatorTaskT> +void RunCancellationTest ( intptr_t threshold = 1 ) +{ + tbb::task_group_context ctx; + tbb::empty_task &r = *new( tbb::task::allocate_root(ctx) ) tbb::empty_task; + r.set_ref_count(3); + r.spawn( *new( r.allocate_child() ) CancellatorTaskT(ctx, threshold) ); + __TBB_Yield(); + r.spawn( *new( r.allocate_child() ) LauncherTaskT(ctx) ); + TRY(); + r.wait_for_all(); + CATCH_AND_FAIL(); + r.destroy(r); +} diff --git a/src/tbb/src/test/harness_graph.h b/src/tbb/src/test/harness_graph.h new file mode 100644 index 0000000..da8bf8d --- /dev/null +++ b/src/tbb/src/test/harness_graph.h @@ -0,0 +1,395 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/** @file harness_graph.cpp + This contains common helper classes and functions for testing graph nodes +**/ + +#ifndef harness_graph_H +#define harness_graph_H + +#include "harness.h" +#include "tbb/flow_graph.h" +#include "tbb/null_rw_mutex.h" +#include "tbb/atomic.h" +#include "tbb/concurrent_unordered_map.h" + +// Needed conversion to and from continue_msg, but didn't want to add +// conversion operators to the class, since we don't want it in general, +// only in these tests. +template<typename InputType, typename OutputType> +struct convertor { + static OutputType convert_value(const InputType &i) { + return OutputType(i); + } +}; + +template<typename InputType> +struct convertor<InputType,tbb::flow::continue_msg> { + static tbb::flow::continue_msg convert_value(const InputType &/*i*/) { + return tbb::flow::continue_msg(); + } +}; + +template<typename OutputType> +struct convertor<tbb::flow::continue_msg,OutputType> { + static OutputType convert_value(const tbb::flow::continue_msg &/*i*/) { + return OutputType(); + } +}; + +// helper for multifunction_node tests. +template<size_t N> +struct mof_helper { + template<typename InputType, typename ports_type> + static inline void output_converted_value(const InputType &i, ports_type &p) { + (void)std::get<N-1>(p).try_put(convertor<InputType,typename std::tuple_element<N-1,ports_type>::type::output_type>::convert_value(i)); + output_converted_value<N-1>(i, p); + } +}; + +template<> +struct mof_helper<1> { + template<typename InputType, typename ports_type> + static inline void output_converted_value(const InputType &i, ports_type &p) { + // just emit a default-constructed object + (void)std::get<0>(p).try_put(convertor<InputType,typename std::tuple_element<0,ports_type>::type::output_type>::convert_value(i)); + } +}; + +template< typename InputType, typename OutputType > +struct harness_graph_default_functor { + static OutputType construct( InputType v ) { + return OutputType(v); + } +}; + +template< typename OutputType > +struct harness_graph_default_functor< tbb::flow::continue_msg, OutputType > { + static OutputType construct( tbb::flow::continue_msg ) { + return OutputType(); + } +}; + +template< typename InputType > +struct harness_graph_default_functor< InputType, tbb::flow::continue_msg > { + static tbb::flow::continue_msg construct( InputType ) { + return tbb::flow::continue_msg(); + } +}; + +template< > +struct harness_graph_default_functor< tbb::flow::continue_msg, tbb::flow::continue_msg > { + static tbb::flow::continue_msg construct( tbb::flow::continue_msg ) { + return tbb::flow::continue_msg(); + } +}; + +template<typename InputType, typename OutputSet> +struct harness_graph_default_multifunction_functor { + static const int N = std::tuple_size<OutputSet>::value; + typedef typename tbb::flow::multifunction_node<InputType,OutputSet>::output_ports_type ports_type; + static void construct(const InputType &i, ports_type &p) { + mof_helper<N>::output_converted_value(i, p); + } +}; + +static tbb::atomic<size_t> current_executors; + +//! An executor that accepts InputType and generates OutputType +template< typename InputType, typename OutputType, typename M=tbb::null_rw_mutex > +struct harness_graph_executor { + + typedef OutputType (*function_ptr_type)( InputType v ); + + static M mutex; + static function_ptr_type fptr; + static tbb::atomic<size_t> execute_count; + static size_t max_executors; + + static inline OutputType func( InputType v ) { + typename M::scoped_lock l( mutex ); + size_t c = current_executors.fetch_and_increment(); + ASSERT( max_executors == 0 || c <= max_executors, NULL ); + ++execute_count; + OutputType v2 = (*fptr)(v); + current_executors.fetch_and_decrement(); + return v2; + } + + struct functor { + tbb::atomic<size_t> my_execute_count; + functor() { my_execute_count = 0; } + functor( const functor &f ) { my_execute_count = f.my_execute_count; } + OutputType operator()( InputType i ) { + typename M::scoped_lock l( harness_graph_executor::mutex ); + size_t c = current_executors.fetch_and_increment(); + ASSERT( harness_graph_executor::max_executors == 0 || c <= harness_graph_executor::max_executors, NULL ); + ++execute_count; + my_execute_count.fetch_and_increment(); + OutputType v2 = (*harness_graph_executor::fptr)(i); + current_executors.fetch_and_decrement(); + return v2; + } + }; + +}; + +//! A multifunction executor that accepts InputType and has only one Output of OutputType. +template< typename InputType, typename OutputTuple, typename M=tbb::null_rw_mutex > +struct harness_graph_multifunction_executor { + typedef typename tbb::flow::multifunction_node<InputType,OutputTuple>::output_ports_type ports_type; + typedef typename std::tuple_element<0,OutputTuple>::type OutputType; + + typedef void (*mfunction_ptr_type)( const InputType& v, ports_type &p ); + + static M mutex; + static mfunction_ptr_type fptr; + static tbb::atomic<size_t> execute_count; + static size_t max_executors; + + + static inline void func( const InputType &v, ports_type &p ) { + typename M::scoped_lock l( mutex ); + size_t c = current_executors.fetch_and_increment(); + ASSERT( max_executors == 0 || c <= max_executors, NULL ); + ASSERT(std::tuple_size<OutputTuple>::value == 1, NULL); + ++execute_count; + (*fptr)(v,p); + current_executors.fetch_and_decrement(); + } + + struct functor { + tbb::atomic<size_t> my_execute_count; + functor() { my_execute_count = 0; } + functor( const functor &f ) { my_execute_count = f.my_execute_count; } + void operator()( const InputType &i, ports_type &p ) { + typename M::scoped_lock l( harness_graph_multifunction_executor::mutex ); + size_t c = current_executors.fetch_and_increment(); + ASSERT( harness_graph_multifunction_executor::max_executors == 0 || c <= harness_graph_multifunction_executor::max_executors, NULL ); + ++execute_count; + my_execute_count.fetch_and_increment(); + (*harness_graph_multifunction_executor::fptr)(i,p); + current_executors.fetch_and_decrement(); + } + }; + +}; + +template< typename InputType, typename OutputType, typename M > +M harness_graph_executor<InputType, OutputType, M>::mutex; + +template< typename InputType, typename OutputType, typename M > +tbb::atomic<size_t> harness_graph_executor<InputType, OutputType, M>::execute_count; + +template< typename InputType, typename OutputType, typename M > +typename harness_graph_executor<InputType, OutputType, M>::function_ptr_type harness_graph_executor<InputType, OutputType, M>::fptr + = harness_graph_default_functor< InputType, OutputType >::construct; + +template< typename InputType, typename OutputType, typename M > +size_t harness_graph_executor<InputType, OutputType, M>::max_executors = 0; + +// static vars for multifunction_node tests +template< typename InputType, typename OutputTuple, typename M > +M harness_graph_multifunction_executor<InputType, OutputTuple, M>::mutex; + +template< typename InputType, typename OutputTuple, typename M > +tbb::atomic<size_t> harness_graph_multifunction_executor<InputType, OutputTuple, M>::execute_count; + +template< typename InputType, typename OutputTuple, typename M > +typename harness_graph_multifunction_executor<InputType, OutputTuple, M>::mfunction_ptr_type harness_graph_multifunction_executor<InputType, OutputTuple, M>::fptr + = harness_graph_default_multifunction_functor< InputType, OutputTuple >::construct; + +template< typename InputType, typename OutputTuple, typename M > +size_t harness_graph_multifunction_executor<InputType, OutputTuple, M>::max_executors = 0; + +//! Counts the number of puts received +template< typename T > +struct harness_counting_receiver : public tbb::flow::receiver<T>, NoCopy { + + tbb::atomic< size_t > my_count; + T max_value; + size_t num_copies; + + harness_counting_receiver() : num_copies(1) { + my_count = 0; + } + + void initialize_map( const T& m, size_t c ) { + my_count = 0; + max_value = m; + num_copies = c; + } + + /* override */ bool try_put( const T & ) { + ++my_count; + return true; + } + + void validate() { + size_t n = my_count; + ASSERT( n == num_copies*max_value, NULL ); + } + +}; + +//! Counts the number of puts received +template< typename T > +struct harness_mapped_receiver : public tbb::flow::receiver<T>, NoCopy { + + tbb::atomic< size_t > my_count; + T max_value; + size_t num_copies; + typedef tbb::concurrent_unordered_map< T, tbb::atomic< size_t > > map_type; + map_type *my_map; + + harness_mapped_receiver() : my_map(NULL) { + my_count = 0; + } + + ~harness_mapped_receiver() { + if ( my_map ) delete my_map; + } + + void initialize_map( const T& m, size_t c ) { + my_count = 0; + max_value = m; + num_copies = c; + if ( my_map ) delete my_map; + my_map = new map_type; + } + + /* override */ bool try_put( const T &t ) { + if ( my_map ) { + tbb::atomic<size_t> a; + a = 1; + std::pair< typename map_type::iterator, bool > r = (*my_map).insert( typename map_type::value_type( t, a ) ); + if ( r.second == false ) { + size_t v = r.first->second.fetch_and_increment(); + ASSERT( v < num_copies, NULL ); + } + } else { + ++my_count; + } + return true; + } + + void validate() { + if ( my_map ) { + for ( size_t i = 0; i < (size_t)max_value; ++i ) { + size_t n = (*my_map)[(int)i]; + ASSERT( n == num_copies, NULL ); + } + } else { + size_t n = my_count; + ASSERT( n == num_copies*max_value, NULL ); + } + } + +}; + +//! Counts the number of puts received +template< typename T > +struct harness_counting_sender : public tbb::flow::sender<T>, NoCopy { + + typedef tbb::flow::receiver<T> successor_type; + tbb::atomic< successor_type * > my_receiver; + tbb::atomic< size_t > my_count; + tbb::atomic< size_t > my_received; + size_t my_limit; + + harness_counting_sender( ) : my_limit(~size_t(0)) { + my_receiver = NULL; + my_count = 0; + my_received = 0; + } + + harness_counting_sender( size_t limit ) : my_limit(limit) { + my_receiver = NULL; + my_count = 0; + my_received = 0; + } + + /* override */ bool register_successor( successor_type &r ) { + my_receiver = &r; + return true; + } + + /* override */ bool remove_successor( successor_type &r ) { + successor_type *s = my_receiver.fetch_and_store( NULL ); + ASSERT( s == &r, NULL ); + return true; + } + + /* override */ bool try_get( T & v ) { + size_t i = my_count.fetch_and_increment(); + if ( i < my_limit ) { + v = T( i ); + ++my_received; + return true; + } else { + return false; + } + } + + bool try_put_once() { + successor_type *s = my_receiver; + size_t i = my_count.fetch_and_increment(); + if ( s->try_put( T(i) ) ) { + ++my_received; + return true; + } else { + return false; + } + } + + void try_put_until_false() { + successor_type *s = my_receiver; + size_t i = my_count.fetch_and_increment(); + + while ( s->try_put( T(i) ) ) { + ++my_received; + i = my_count.fetch_and_increment(); + } + } + + void try_put_until_limit() { + successor_type *s = my_receiver; + + for ( int i = 0; i < (int)my_limit; ++i ) { + ASSERT( s->try_put( T(i) ), NULL ); + ++my_received; + } + ASSERT( my_received == my_limit, NULL ); + } + +}; + +#endif + + diff --git a/src/tbb/src/test/harness_inject_scheduler.h b/src/tbb/src/test/harness_inject_scheduler.h new file mode 100644 index 0000000..44751b9 --- /dev/null +++ b/src/tbb/src/test/harness_inject_scheduler.h @@ -0,0 +1,69 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Used in tests that work with TBB scheduler but do not link to the TBB library. +// In other words it embeds the TBB library core into the test executable. + +#ifndef harness_inject_scheduler_H +#define harness_inject_scheduler_H + +// Suppress usage of #pragma comment +#define __TBB_NO_IMPLICIT_LINKAGE 1 + +// Enable preview features if any +#define __TBB_BUILD 1 + +#undef DO_ITT_NOTIFY + +#define __TBB_SOURCE_DIRECTLY_INCLUDED 1 +#include "../tbb/tbb_main.cpp" +#include "../tbb/dynamic_link.cpp" +#include "../tbb/tbb_misc_ex.cpp" + +// Tasking subsystem files +#include "../tbb/governor.cpp" +#include "../tbb/market.cpp" +#include "../tbb/arena.cpp" +#include "../tbb/scheduler.cpp" +#include "../tbb/observer_proxy.cpp" +#include "../tbb/task.cpp" +#include "../tbb/task_group_context.cpp" + +// Other dependencies +#include "../tbb/cache_aligned_allocator.cpp" +#include "../tbb/tbb_thread.cpp" +#include "../tbb/mutex.cpp" +#include "../tbb/spin_rw_mutex.cpp" +#include "../tbb/spin_mutex.cpp" +#include "../tbb/private_server.cpp" +#if _WIN32||_WIN64 +#include "../tbb/semaphore.cpp" +#endif +#include "../rml/client/rml_tbb.cpp" + +#endif /* harness_inject_scheduler_H */ diff --git a/src/tbb/src/test/harness_iterator.h b/src/tbb/src/test/harness_iterator.h new file mode 100644 index 0000000..3fc9c69 --- /dev/null +++ b/src/tbb/src/test/harness_iterator.h @@ -0,0 +1,165 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef harness_iterator_H +#define harness_iterator_H + +#include <iterator> +#include <memory> + +namespace Harness { + +template <class T> +class InputIterator { + T * my_ptr; +public: +#if HARNESS_EXTENDED_STD_COMPLIANCE + typedef std::input_iterator_tag iterator_category; + typedef T value_type; + typedef typename std::allocator<T>::difference_type difference_type; + typedef typename std::allocator<T>::pointer pointer; + typedef typename std::allocator<T>::reference reference; +#endif /* HARNESS_EXTENDED_STD_COMPLIANCE */ + + explicit InputIterator( T * ptr): my_ptr(ptr){} + + T& operator* () { return *my_ptr; } + + InputIterator& operator++ () { ++my_ptr; return *this; } + + bool operator== ( const InputIterator& r ) { return my_ptr == r.my_ptr; } +}; + +template <class T> +class ForwardIterator { + T * my_ptr; +public: +#if HARNESS_EXTENDED_STD_COMPLIANCE + typedef std::forward_iterator_tag iterator_category; + typedef T value_type; + typedef typename std::allocator<T>::difference_type difference_type; + typedef typename std::allocator<T>::pointer pointer; + typedef typename std::allocator<T>::reference reference; +#endif /* HARNESS_EXTENDED_STD_COMPLIANCE */ + + explicit ForwardIterator ( T * ptr ) : my_ptr(ptr){} + + ForwardIterator ( const ForwardIterator& r ) : my_ptr(r.my_ptr){} + + T& operator* () { return *my_ptr; } + + ForwardIterator& operator++ () { ++my_ptr; return *this; } + + bool operator== ( const ForwardIterator& r ) { return my_ptr == r.my_ptr; } +}; + +template <class T> +class RandomIterator { + T * my_ptr; +#if !HARNESS_EXTENDED_STD_COMPLIANCE + typedef typename std::allocator<T>::difference_type difference_type; +#endif + +public: +#if HARNESS_EXTENDED_STD_COMPLIANCE + typedef std::random_access_iterator_tag iterator_category; + typedef T value_type; + typedef typename std::allocator<T>::pointer pointer; + typedef typename std::allocator<T>::reference reference; + typedef typename std::allocator<T>::difference_type difference_type; +#endif /* HARNESS_EXTENDED_STD_COMPLIANCE */ + + explicit RandomIterator ( T * ptr ) : my_ptr(ptr){} + RandomIterator ( const RandomIterator& r ) : my_ptr(r.my_ptr){} + T& operator* () { return *my_ptr; } + RandomIterator& operator++ () { ++my_ptr; return *this; } + bool operator== ( const RandomIterator& r ) { return my_ptr == r.my_ptr; } + difference_type operator- (const RandomIterator &r) {return my_ptr - r.my_ptr;} + RandomIterator operator+ (difference_type n) {return RandomIterator(my_ptr + n);} +}; + +template <class T> +class ConstRandomIterator { + const T * my_ptr; +#if !HARNESS_EXTENDED_STD_COMPLIANCE + typedef typename std::allocator<T>::difference_type difference_type; +#endif + +public: +#if HARNESS_EXTENDED_STD_COMPLIANCE + typedef std::random_access_iterator_tag iterator_category; + typedef T value_type; + typedef typename std::allocator<T>::const_pointer pointer; + typedef typename std::allocator<T>::const_reference reference; + typedef typename std::allocator<T>::difference_type difference_type; +#endif /* HARNESS_EXTENDED_STD_COMPLIANCE */ + + explicit ConstRandomIterator ( const T * ptr ) : my_ptr(ptr){} + ConstRandomIterator ( const ConstRandomIterator& r ) : my_ptr(r.my_ptr){} + const T& operator* () { return *my_ptr; } + ConstRandomIterator& operator++ () { ++my_ptr; return *this; } + bool operator== ( const ConstRandomIterator& r ) { return my_ptr == r.my_ptr; } + difference_type operator- (const ConstRandomIterator &r) {return my_ptr - r.my_ptr;} + ConstRandomIterator operator+ (difference_type n) {return ConstRandomIterator(my_ptr + n);} +}; + +} // namespace Harness + +#if !HARNESS_EXTENDED_STD_COMPLIANCE +namespace std { + template<typename T> + struct iterator_traits< Harness::InputIterator<T> > { + typedef std::input_iterator_tag iterator_category; + typedef T value_type; + typedef value_type& reference; + }; + + template<typename T> + struct iterator_traits< Harness::ForwardIterator<T> > { + typedef std::forward_iterator_tag iterator_category; + typedef T value_type; + typedef value_type& reference; + }; + + template<typename T> + struct iterator_traits< Harness::RandomIterator<T> > { + typedef std::random_access_iterator_tag iterator_category; + typedef T value_type; + typedef value_type& reference; + }; + + template<typename T> + struct iterator_traits< Harness::ConstRandomIterator<T> > { + typedef std::random_access_iterator_tag iterator_category; + typedef T value_type; + typedef const value_type& reference; + }; +} // namespace std +#endif /* !HARNESS_EXTENDED_STD_COMPLIANCE */ + +#endif //harness_iterator_H diff --git a/src/tbb/src/test/harness_m128.h b/src/tbb/src/test/harness_m128.h new file mode 100644 index 0000000..5a7a123 --- /dev/null +++ b/src/tbb/src/test/harness_m128.h @@ -0,0 +1,112 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Header that sets HAVE_m128/HAVE_m256 if vector types (__m128/__m256) are available + +//! Class for testing safety of using vector types. +/** Uses circuitous logic forces compiler to put __m128/__m256 objects on stack while + executing various methods, and thus tempt it to use aligned loads and stores + on the stack. */ +// Do not create file-scope objects of the class, because MinGW (as of May 2010) +// did not always provide proper stack alignment in destructors of such objects. + +template<typename __Mvec> +class ClassWithVectorType { + static const int n = 16; + static const int F = sizeof(__Mvec)/sizeof(float); + __Mvec field[n]; + void init( int start ); +public: + ClassWithVectorType() {init(-n);} + ClassWithVectorType( int i ) {init(i);} + void operator=( const ClassWithVectorType& src ) { + __Mvec stack[n]; + for( int i=0; i<n; ++i ) + stack[i^5] = src.field[i]; + for( int i=0; i<n; ++i ) + field[i^5] = stack[i]; + } + ~ClassWithVectorType() {init(-2*n);} + friend bool operator==( const ClassWithVectorType& x, const ClassWithVectorType& y ) { + for( int i=0; i<F*n; ++i ) + if( ((const float*)x.field)[i]!=((const float*)y.field)[i] ) + return false; + return true; + } + friend bool operator!=( const ClassWithVectorType& x, const ClassWithVectorType& y ) { + return !(x==y); + } +}; + +template<typename __Mvec> +void ClassWithVectorType<__Mvec>::init( int start ) { + __Mvec stack[n]; + for( int i=0; i<n; ++i ) { + // Declaring value as a one-element array instead of a scalar quites + // gratuitous warnings about possible use of "value" before it was set. + __Mvec value[1]; + for( int j=0; j<F; ++j ) + ((float*)value)[j] = float(n*start+F*i+j); + stack[i^5] = value[0]; + } + for( int i=0; i<n; ++i ) + field[i^5] = stack[i]; +} + +#if (__AVX__ || (_MSC_VER>=1600 && _M_X64)) && !defined(__sun) +#include <immintrin.h> +#define HAVE_m256 1 +typedef ClassWithVectorType<__m256> ClassWithAVX; +#if _MSC_VER +#include <intrin.h> // for __cpuid +#endif +bool have_AVX() { + bool result = false; + const int avx_mask = 1<<28; +#if _MSC_VER || __INTEL_COMPILER + int info[4] = {0,0,0,0}; + const int ECX = 2; + __cpuid(info, 1); + result = (info[ECX] & avx_mask)!=0; +#elif __GNUC__ + int ECX; + __asm__( "cpuid" + : "=c"(ECX) + : "a" (1) + : "ebx", "edx" ); + result = (ECX & avx_mask); +#endif + return result; +} +#endif /* __AVX__ etc */ + +#if (__SSE__ || _M_IX86_FP || _M_X64) && !defined(__sun) +#include <xmmintrin.h> +#define HAVE_m128 1 +typedef ClassWithVectorType<__m128> ClassWithSSE; +#endif diff --git a/src/tbb/src/test/harness_memory.h b/src/tbb/src/test/harness_memory.h new file mode 100644 index 0000000..8e24a8a --- /dev/null +++ b/src/tbb/src/test/harness_memory.h @@ -0,0 +1,106 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Declarations for simple estimate of the memory being used by a program. +// Not yet implemented for Mac. +// This header is an optional part of the test harness. +// It assumes that "harness_assert.h" has already been included. + +#if __linux__ || __sun +#include <sys/resource.h> +#include <unistd.h> + +#elif __APPLE__ +#include <unistd.h> +#include <mach/mach.h> +#include <AvailabilityMacros.h> +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 +#include <mach/shared_region.h> +#else +#include <mach/shared_memory_server.h> +#endif +#if SHARED_TEXT_REGION_SIZE || SHARED_DATA_REGION_SIZE +const size_t shared_size = SHARED_TEXT_REGION_SIZE+SHARED_DATA_REGION_SIZE; +#else +const size_t shared_size = 0; +#endif + +#elif _WIN32 && !_XBOX +#include <windows.h> +#include <psapi.h> +#if _MSC_VER +#pragma comment(lib, "psapi") +#endif + +#endif /* OS selection */ + +//! Return estimate of number of bytes of memory that this program is currently using. +/* Returns 0 if not implemented on platform. */ +size_t GetMemoryUsage() { +#if _XBOX + return 0; +#elif _WIN32 + PROCESS_MEMORY_COUNTERS mem; + bool status = GetProcessMemoryInfo(GetCurrentProcess(), &mem, sizeof(mem))!=0; + ASSERT(status, NULL); + return mem.PagefileUsage; +#elif __linux__ + FILE* statsfile = fopen("/proc/self/statm","r"); + size_t pagesize = getpagesize(); + ASSERT(statsfile, NULL); + long total_mem; + int n = fscanf(statsfile,"%lu",&total_mem); + if( n!=1 ) { + REPORT("Warning: memory usage statistics wasn't obtained\n"); + return 0; + } + fclose(statsfile); + return total_mem*pagesize; +#elif __APPLE__ + kern_return_t status; + task_basic_info info; + mach_msg_type_number_t msg_type = TASK_BASIC_INFO_COUNT; + status = task_info(mach_task_self(), TASK_BASIC_INFO, reinterpret_cast<task_info_t>(&info), &msg_type); + ASSERT(status==KERN_SUCCESS, NULL); + return info.virtual_size - shared_size; +#else + return 0; +#endif +} + +//! Use approximately a specified amount of stack space. +/** Recursion is used here instead of alloca because some implementations of alloca do not use the stack. */ +void UseStackSpace( size_t amount, char* top=0 ) { + char x[1000]; + memset( x, -1, sizeof(x) ); + if( !top ) + top = x; + ASSERT( x<=top, "test assumes that stacks grow downwards" ); + if( size_t(top-x)<amount ) + UseStackSpace( amount, top ); +} diff --git a/src/tbb/src/test/harness_report.h b/src/tbb/src/test/harness_report.h new file mode 100644 index 0000000..6caf642 --- /dev/null +++ b/src/tbb/src/test/harness_report.h @@ -0,0 +1,178 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Just the tracing portion of the harness. +// +// This header defines TRACE and TRACENL macros, which use REPORT like syntax and +// are useful for duplicating trace output to the standard debug output on Windows. +// It is possible to add the ability of automatic extending messages with additional +// info (file, line, function, time, thread ID, ...). +// +// Macros output nothing when test app runs in non-verbose mode (default). +// + +#ifndef tbb_tests_harness_report_H +#define tbb_tests_harness_report_H + +#if defined(MAX_TRACE_SIZE) && MAX_TRACE_SIZE < 1024 + #undef MAX_TRACE_SIZE +#endif +#ifndef MAX_TRACE_SIZE + #define MAX_TRACE_SIZE 1024 +#endif + +#if __SUNPRO_CC +#include <stdio.h> +#else +#include <cstdio> +#endif + +#include <cstdarg> + +#include "tbb/tbb_config.h" + +#if __TBB_DEFINE_MIC +#include "harness_mic.h" +#endif + +#ifdef HARNESS_INCOMPLETE_SOURCES +#error Source files are not complete. Check the build environment +#endif + +#if _MSC_VER + #define snprintf _snprintf +#if _MSC_VER<=1400 + #define vsnprintf _vsnprintf +#endif +#endif + +namespace Harness { + namespace internal { + +#ifndef TbbHarnessReporter + struct TbbHarnessReporter { + void Report ( const char* msg ) { + printf( "%s", msg ); + fflush(stdout); +#ifdef _WINDOWS_ + OutputDebugStringA(msg); +#endif + } + }; // struct TbbHarnessReporter +#endif /* !TbbHarnessReporter */ + + class Tracer { + int m_flags; + const char *m_file; + const char *m_func; + size_t m_line; + + TbbHarnessReporter m_reporter; + + public: + enum { + prefix = 1, + need_lf = 2 + }; + + Tracer* set_trace_info ( int flags, const char *file, size_t line, const char *func ) { + m_flags = flags; + m_line = line; + m_file = file; + m_func = func; + return this; + } + + void trace ( const char* fmt, ... ) { + char msg[MAX_TRACE_SIZE]; + char msg_fmt_buf[MAX_TRACE_SIZE]; + const char *msg_fmt = fmt; + if ( m_flags & prefix ) { + snprintf (msg_fmt_buf, MAX_TRACE_SIZE, "[%s] %s", m_func, fmt); + msg_fmt = msg_fmt_buf; + } + std::va_list argptr; + va_start (argptr, fmt); + int len = vsnprintf (msg, MAX_TRACE_SIZE, msg_fmt, argptr); + va_end (argptr); + if ( m_flags & need_lf && + len < MAX_TRACE_SIZE - 1 && msg_fmt[len-1] != '\n' ) + { + msg[len] = '\n'; + msg[len + 1] = 0; + } + m_reporter.Report(msg); + } + }; // class Tracer + + static Tracer tracer; + + template<int> + bool not_the_first_call () { + static bool first_call = false; + bool res = first_call; + first_call = true; + return res; + } + + } // namespace internal +} // namespace Harness + +#if defined(_MSC_VER) && _MSC_VER >= 1300 || defined(__GNUC__) || defined(__GNUG__) + #define HARNESS_TRACE_ORIG_INFO __FILE__, __LINE__, __FUNCTION__ +#else + #define HARNESS_TRACE_ORIG_INFO __FILE__, __LINE__, "" + #define __FUNCTION__ "" +#endif + + +//! printf style tracing macro +/** This variant of TRACE adds trailing line-feed (new line) character, if it is absent. **/ +#define TRACE Harness::internal::tracer.set_trace_info(Harness::internal::Tracer::need_lf, HARNESS_TRACE_ORIG_INFO)->trace + +//! printf style tracing macro without automatic new line character adding +#define TRACENL Harness::internal::tracer.set_trace_info(0, HARNESS_TRACE_ORIG_INFO)->trace + +//! printf style tracing macro with additional information prefix (e.g. current function name) +#define TRACEP Harness::internal::tracer.set_trace_info(Harness::internal::Tracer::prefix | \ + Harness::internal::Tracer::need_lf, HARNESS_TRACE_ORIG_INFO)->trace + +//! printf style remark macro +/** Produces output only when the test is run with the -v (verbose) option. **/ +#define REMARK !Verbose ? (void)0 : TRACENL + +//! printf style remark macro +/** Produces output only when invoked first time. + Only one instance of this macro is allowed per source code line. **/ +#define REMARK_ONCE (!Verbose || Harness::internal::not_the_first_call<__LINE__>()) ? (void)0 : TRACE + +//! printf style reporting macro +/** On heterogeneous platforms redirects its output to the host side. **/ +#define REPORT TRACENL + +#endif /* tbb_tests_harness_report_H */ diff --git a/src/tbb/src/test/harness_task.h b/src/tbb/src/test/harness_task.h new file mode 100644 index 0000000..1f7d4d9 --- /dev/null +++ b/src/tbb/src/test/harness_task.h @@ -0,0 +1,63 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/task.h" +#include "harness.h" + +//! Helper for verifying that old use cases of spawn syntax still work. +tbb::task* GetTaskPtr( int& counter ) { + ++counter; + return NULL; +} + +class TaskGenerator: public tbb::task { + int m_ChildCount; + int m_Depth; + +public: + TaskGenerator( int child_count, int _depth ) : m_ChildCount(child_count), m_Depth(_depth) {} + ~TaskGenerator( ) { m_ChildCount = m_Depth = -125; } + + /*override*/ tbb::task* execute() { + ASSERT( m_ChildCount>=0 && m_Depth>=0, NULL ); + if( m_Depth>0 ) { + recycle_as_safe_continuation(); + set_ref_count( m_ChildCount+1 ); + int k=0; + for( int j=0; j<m_ChildCount; ++j ) { + tbb::task& t = *new( allocate_child() ) TaskGenerator(m_ChildCount/2,m_Depth-1); + GetTaskPtr(k)->spawn(t); + } + ASSERT(k==m_ChildCount,NULL); + --m_Depth; + __TBB_Yield(); + ASSERT( state()==recycle && ref_count()>0, NULL); + } + return NULL; + } +}; diff --git a/src/tbb/src/test/harness_tbb_independence.h b/src/tbb/src/test/harness_tbb_independence.h new file mode 100644 index 0000000..d07f0dd --- /dev/null +++ b/src/tbb/src/test/harness_tbb_independence.h @@ -0,0 +1,76 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef harness_tbb_independence_H +#define harness_tbb_independence_H + +#if __linux__ && __ia64__ + +#define __TBB_NO_IMPLICIT_LINKAGE 1 +#include "tbb/tbb_machine.h" + +#include <pthread.h> + +// Can't use Intel compiler intrinsic due to internal error reported by 10.1 compiler +pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER; + +int32_t __TBB_machine_fetchadd4__TBB_full_fence (volatile void *ptr, int32_t value) +{ + pthread_mutex_lock(&counter_mutex); + int32_t result = *(int32_t*)ptr; + *(int32_t*)ptr = result + value; + pthread_mutex_unlock(&counter_mutex); + return result; +} + +int64_t __TBB_machine_fetchadd8__TBB_full_fence (volatile void *ptr, int64_t value) +{ + pthread_mutex_lock(&counter_mutex); + int32_t result = *(int32_t*)ptr; + *(int32_t*)ptr = result + value; + pthread_mutex_unlock(&counter_mutex); + return result; +} + +void __TBB_machine_pause(int32_t /*delay*/) { __TBB_Yield(); } + +pthread_mutex_t cas_mutex = PTHREAD_MUTEX_INITIALIZER; + +extern "C" int64_t __TBB_machine_cmpswp8__TBB_full_fence(volatile void *ptr, int64_t value, int64_t comparand) +{ + pthread_mutex_lock(&cas_mutex); + int64_t result = *(int64_t*)ptr; + if (result == comparand) + *(int64_t*)ptr = value; + pthread_mutex_unlock(&cas_mutex); + return result; +} + +#endif /* __linux__ && __ia64 */ + +#endif // harness_tbb_independence_H diff --git a/src/tbb/src/test/harness_test_cases_framework.h b/src/tbb/src/test/harness_test_cases_framework.h new file mode 100644 index 0000000..e8f673a --- /dev/null +++ b/src/tbb/src/test/harness_test_cases_framework.h @@ -0,0 +1,243 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef tbb_harness_test_cases_framework_H +#define tbb_harness_test_cases_framework_H + +#if defined(_MSC_VER) + #define _SCL_SECURE_NO_WARNINGS +#endif + +#undef DO_ITT_NOTIFY +#undef TBB_DO_ITT_EVENTS + +#include "harness.h" +//#include "harness_report.h" +#include "harness_assert.h" +//#include "harness_allocator.h" +#include "tbb/tbb_stddef.h" + +#include <cstdlib> + +#include <vector> +#include <algorithm> + +#include <string> +#include <sstream> +#include <iostream> + +namespace test_framework{ + template<typename test_class> + void run_test(){ + test_class()(); + } + + struct assertion_failure:std::exception{ + const char* my_filename; + int my_line; + const char* my_expression; + const char * my_comment; + assertion_failure(const char* filename, int line, const char* expression, const char * comment): + my_filename(filename), + my_line(line), + my_expression(expression), + my_comment(comment) + {} + virtual const char* what() const throw(){ + return "test assertion failed"; + } + }; + void throw_assertion_failure(){throw assertion_failure("",0,"","");} + void throw_assertion_failure(const char* filename, int line, const char* expression, const char * comment){ + throw assertion_failure(filename, line, expression, comment); + } + class test_suite{ + typedef void(*run_test_function_pointer_type)(); + typedef std::pair<std::string, run_test_function_pointer_type> tc_record_pair; + std::vector<tc_record_pair > test_cases; + public: + template<class test_class> + void register_test_case(std::string const& name, test_class * ){ + test_cases.push_back(tc_record_pair(name,& run_test<test_class>)); + } + std::string operator()(bool silent=false){ + std::stringstream str; + size_t failed=0; + for (size_t i=0;i<test_cases.size();++i){ + try{ + (test_cases[i].second)(); + }catch(std::exception& e){ + failed++; + str<<"test case \""<<test_cases[i].first<<"\" failed with exception. what():\""<<e.what()<<"\""<<std::endl; + } + } + if (!silent) { + str<<test_cases.size()<<" test cases are run; "<<failed<<" failed"<<std::endl; + } + return str.str(); + } + }; + test_suite& get_suite_ref(){static test_suite ts; return ts;} + void run_all_and_print_results(test_suite& ts,std::ostream& o , bool silent=false){ + o<<ts(silent); + } +} +using test_framework::get_suite_ref; +#define TEST_CASE_WITH_FIXTURE(TC_NAME,FIXTURE_NAME) \ + struct TC_NAME; \ + struct TC_NAME:FIXTURE_NAME { \ + /* explicitly implemented default constructor \ + is need here to please gcc 4.3.2*/ \ + TC_NAME(){} \ + void operator()(); \ + }; \ + bool TC_NAME##_registerd = (get_suite_ref().register_test_case(#TC_NAME,static_cast<TC_NAME*>(0)),true);\ + void TC_NAME::operator()() + +namespace test_framework_unit_tests{ + namespace test_helper{ + template <size_t id> struct tag{}; + template<typename tag> + struct test_case{ + static bool is_run; + void operator()(){ + is_run=true; + } + }; + template<typename tag> bool test_case<tag>::is_run = false; + + } + using namespace test_framework; + namespace test_test_suite_ref{ + void run_all_runs_all_registered_test_cases(){ + test_suite s; + using test_helper::tag; + test_helper::test_case<tag<__LINE__> > tc1; + test_helper::test_case<tag<__LINE__> > tc2; + s.register_test_case("tc1",&tc1); + s.register_test_case("tc2",&tc2); + s(); + ASSERT(tc1.is_run && tc2.is_run,"test_suite::operator() should run all the tests"); + } + + struct silent_switch_fixture{ + test_helper::test_case<test_helper::tag<__LINE__> > do_nothing_tc; + }; + struct run_all_and_print_results_should_respect_silent_mode: silent_switch_fixture{ + void operator()(){ + using test_helper::tag; + test_helper::test_case<tag<__LINE__> > do_nothing_tc; + test_suite ts; + ts.register_test_case("tc_name",&do_nothing_tc); + bool silent =true; + ASSERT(ts(silent).empty(),"in silent mode no message except error should be output"); + } + }; + struct run_all_and_print_results_should_respect_verbose_mode: silent_switch_fixture{ + void operator()(){ + using test_helper::tag; + test_helper::test_case<tag<__LINE__> > do_nothing_tc; + test_suite ts; + ts.register_test_case("tc_name",&do_nothing_tc); + bool silent =true; + ASSERT(!ts(!silent).empty(),"in verbose mode all messages should be outputed"); + } + }; + } + namespace test_test_case_macro{ + test_suite& get_suite_ref(){static test_suite ts; return ts;} + typedef test_helper::test_case<test_helper::tag<__LINE__> > unique_test_type; + TEST_CASE_WITH_FIXTURE(test_auto_registration,unique_test_type){ + unique_test_type::operator()(); + } + void run_test_test_case_macro(){ + get_suite_ref()(); + ASSERT(unique_test_type::is_run,"test case macro should register the test case in suite"); + } + void test_test_case_macro_does_not_create_test_case_object(){ + ASSERT(false,"to implement"); + } + } + namespace internal_assertions_failure_test_cases{ + + test_suite& get_suite_ref(){static test_suite ts; return ts;} + + //TODO: investigate compilation errors regarding tbb::set_assertion_handler +// struct empty_fixture{}; +// TEST_CASE_WITH_FIXTURE(test_internal_assertion_does_not_stop_test_suite,empty_fixture){ +// struct handler{ +// static void _( const char* /*filename*/, int /*line*/, const char* /*expression*/, const char * /*comment*/ ){ +// } +// }; +// +// tbb::assertion_handler_type previous = tbb::set_assertion_handler(handler::_); +// __TBB_ASSERT(false,"this assert should not stop the test suite run"); +// tbb::set_assertion_handler(previous ); +//// ASSERT(assertion_handler::is_called,"__TBB_ASSERT should call installed assertion handler"); +// } +// TEST_CASE_WITH_FIXTURE(test_internal_assertion_does_mark_the_test_as_failed,empty_fixture){ +// test_suite ts; +// struct _{ +//// static +// static void assertion_handler_type( const char* /*filename*/, int /*line*/, const char* /*expression*/, const char * /*comment*/ ){ +// } +// }; +// tbb::assertion_handler_type previous = tbb::set_assertion_handler(_::assertion_handler_type); +// __TBB_ASSERT(false,"this assert should not stop the test suite run"); +// tbb::set_assertion_handler(previous ); +// std::string result = ts(); +// std::size_t test_case_name_begin_pos = result.find("test case \""); +// std::size_t failed_begin_pos = result.find("failed"); +// ASSERT(test_case_name_begin_pos!=std::string::npos && failed_begin_pos!=std::string::npos && test_case_name_begin_pos<failed_begin_pos,"internal assertion should result in test failure"); +// } + + } + void run_all_test(){ + test_test_suite_ref::run_all_runs_all_registered_test_cases(); + test_test_suite_ref::run_all_and_print_results_should_respect_silent_mode()(); + test_test_suite_ref::run_all_and_print_results_should_respect_verbose_mode()(); + test_test_case_macro::run_test_test_case_macro(); + //TODO: uncomment and implement +// test_test_case_macro::test_test_case_macro_does_not_create_test_case_object(); + run_all_and_print_results(internal_assertions_failure_test_cases::get_suite_ref(),std::cout,!Verbose); + } +} + +int TestMain (){ + SetHarnessErrorProcessing(test_framework::throw_assertion_failure); + //TODO: deal with assertions during stack unwinding + //tbb::set_assertion_handler( test_framework::throw_assertion_failure ); + { + test_framework_unit_tests::run_all_test(); + } + bool silent = !Verbose; + run_all_and_print_results(test_framework::get_suite_ref(),std::cout,silent); + return Harness::Done; +} + +#endif //tbb_harness_test_cases_framework_H diff --git a/src/tbb/src/test/test_ScalableAllocator.cpp b/src/tbb/src/test/test_ScalableAllocator.cpp new file mode 100644 index 0000000..7a12496 --- /dev/null +++ b/src/tbb/src/test/test_ScalableAllocator.cpp @@ -0,0 +1,184 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Test whether scalable_allocator complies with the requirements in 20.1.5 of ISO C++ Standard (1998). + +#define __TBB_EXTRA_DEBUG 1 // enables additional checks +#define TBB_PREVIEW_MEMORY_POOL 1 + +#include "harness_assert.h" +#if __linux__ && __ia64__ +// Currently pools high-level interface has dependency to TBB library +// to get atomics. For sake of testing add rudementary implementation of them. +#include "harness_tbb_independence.h" +#endif +#include "tbb/memory_pool.h" +#include "tbb/scalable_allocator.h" + +#if __TBB_SOURCE_DIRECTLY_INCLUDED && (_WIN32||_WIN64) +#include "../tbbmalloc/tbbmalloc_internal_api.h" +#define __TBBMALLOC_CALL_THREAD_SHUTDOWN 1 +#endif +// the actual body of the test is there: +#include "test_allocator.h" +#include "harness_allocator.h" + +#if _MSC_VER +#include "tbb/machine/windows_api.h" +#endif /* _MSC_VER */ + +typedef static_counting_allocator<tbb::memory_pool_allocator<char> > cnt_alloc_t; +typedef local_counting_allocator<std::allocator<char> > cnt_provider_t; +class MinimalAllocator : cnt_provider_t { +public: + typedef char value_type; + MinimalAllocator() { + REMARK("%p::ctor\n", this); + } + MinimalAllocator(const MinimalAllocator&s) : cnt_provider_t(s) { + REMARK("%p::ctor(%p)\n", this, &s); + } + ~MinimalAllocator() { + REMARK("%p::dtor: alloc=%u/%u free=%u/%u\n", this, + unsigned(items_allocated),unsigned(allocations), + unsigned(items_freed), unsigned(frees) ); + ASSERT(allocations==frees && items_allocated==items_freed,0); + if( allocations ) { // non-temporal copy + // TODO: describe consumption requirements + ASSERT(items_allocated>cnt_alloc_t::items_allocated, 0); + } + } + void *allocate(size_t sz) { + void *p = cnt_provider_t::allocate(sz); + REMARK("%p::allocate(%u) = %p\n", this, unsigned(sz), p); + return p; + } + void deallocate(void *p, size_t sz) { + ASSERT(allocations>frees,0); + REMARK("%p::deallocate(%p, %u)\n", this, p, unsigned(sz)); + cnt_provider_t::deallocate(cnt_provider_t::pointer(p), sz); + } +}; + +class NullAllocator { +public: + typedef char value_type; + NullAllocator() { } + NullAllocator(const NullAllocator&) { } + ~NullAllocator() { } + void *allocate(size_t) { return NULL; } + void deallocate(void *, size_t) { ASSERT(0, NULL); } +}; + +void TestZeroSpaceMemoryPool() +{ + try { + tbb::memory_pool<NullAllocator> pool; + ASSERT(0, "Useless allocator with no memory must not be created"); + } catch (std::bad_alloc) { + } catch (...) { + ASSERT(0, "wrong exception type; expected bad_alloc"); + } +} + +/* test that pools in small space are either usable or not created + (i.e., exception raised) */ +void TestSmallFixedSizePool() +{ + char *buf; + bool allocated = false; + + for (size_t sz = 0; sz < 64*1024; sz = sz? 3*sz : 3) { + buf = (char*)malloc(sz); + try { + tbb::fixed_pool pool(buf, sz); + allocated = pool.malloc( 16 ) || pool.malloc( 9*1024 ); + ASSERT(allocated, NULL); + } catch (std::bad_alloc) { + } catch (...) { + ASSERT(0, "wrong exception type; expected bad_alloc"); + } + free(buf); + } + ASSERT(allocated, "Maximal buf size should be enough to create working fixed_pool"); + try { + tbb::fixed_pool pool(NULL, 10*1024*1024); + ASSERT(0, "Useless allocator with no memory must not be created"); + } catch (std::bad_alloc) { + } catch (...) { + ASSERT(0, "wrong exception type; expected bad_alloc"); + } +} + +int TestMain () { +#if _MSC_VER && !__TBBMALLOC_NO_IMPLICIT_LINKAGE + #ifdef _DEBUG + ASSERT(!GetModuleHandle("tbbmalloc.dll") && GetModuleHandle("tbbmalloc_debug.dll"), + "test linked with wrong (non-debug) tbbmalloc library"); + #else + ASSERT(!GetModuleHandle("tbbmalloc_debug.dll") && GetModuleHandle("tbbmalloc.dll"), + "test linked with wrong (debug) tbbmalloc library"); + #endif +#endif /* _MSC_VER && !__TBBMALLOC_NO_IMPLICIT_LINKAGE */ + int result = TestMain<tbb::scalable_allocator<void> >(); + { + tbb::memory_pool<tbb::scalable_allocator<int> > pool; + result += TestMain(tbb::memory_pool_allocator<void>(pool) ); + }{ + tbb::memory_pool<MinimalAllocator> pool; + cnt_alloc_t alloc(( tbb::memory_pool_allocator<char>(pool) )); // double parentheses to avoid function declaration + result += TestMain(alloc); + }{ + static char buf[1024*1024*4]; + tbb::fixed_pool pool(buf, sizeof(buf)); + const char *text = "this is a test";// 15 bytes + char *p1 = (char*)pool.malloc( 16 ); + ASSERT(p1, NULL); + strcpy(p1, text); + char *p2 = (char*)pool.realloc( p1, 15 ); + ASSERT( p2 && !strcmp(p2, text), "realloc broke memory" ); + + result += TestMain(tbb::memory_pool_allocator<void>(pool) ); + + // try allocate almost entire buf keeping some reasonable space for internals + char *p3 = (char*)pool.realloc( p2, sizeof(buf)-128*1024 ); + ASSERT( p3, "defragmentation failed" ); + ASSERT( !strcmp(p3, text), "realloc broke memory" ); + for( size_t sz = 10; sz < sizeof(buf); sz *= 2) { + ASSERT( pool.malloc( sz ), NULL); + pool.recycle(); + } + + result += TestMain(tbb::memory_pool_allocator<void>(pool) ); + } + TestSmallFixedSizePool(); + TestZeroSpaceMemoryPool(); + + ASSERT( !result, NULL ); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_ScalableAllocator_STL.cpp b/src/tbb/src/test/test_ScalableAllocator_STL.cpp new file mode 100644 index 0000000..63e33dc --- /dev/null +++ b/src/tbb/src/test/test_ScalableAllocator_STL.cpp @@ -0,0 +1,55 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Test whether scalable_allocator works with some of the host's STL containers. + +#define HARNESS_NO_PARSE_COMMAND_LINE 1 +#define __TBB_EXTRA_DEBUG 1 // enables additional checks +#define TBB_PREVIEW_MEMORY_POOL 1 + +#include "harness_assert.h" +#if __linux__ && __ia64__ +// Currently pools high-level interface has dependency to TBB library +// to get atomics. For sake of testing add rudementary implementation of them. +#include "harness_tbb_independence.h" +#endif +#include "tbb/memory_pool.h" +#include "tbb/scalable_allocator.h" + +// The actual body of the test is there: +#include "test_allocator_STL.h" + +int TestMain () { + TestAllocatorWithSTL<tbb::scalable_allocator<void> >(); + tbb::memory_pool<tbb::scalable_allocator<int> > mpool; + TestAllocatorWithSTL(tbb::memory_pool_allocator<void>(mpool) ); + static char buf[1024*1024*4]; + tbb::fixed_pool fpool(buf, sizeof(buf)); + TestAllocatorWithSTL(tbb::memory_pool_allocator<void>(fpool) ); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_aggregator.cpp b/src/tbb/src/test/test_aggregator.cpp new file mode 100644 index 0000000..fc9e553 --- /dev/null +++ b/src/tbb/src/test/test_aggregator.cpp @@ -0,0 +1,193 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef TBB_PREVIEW_AGGREGATOR + #define TBB_PREVIEW_AGGREGATOR 1 +#endif + +#include "tbb/aggregator.h" +#include "harness.h" +#include <queue> + +typedef std::priority_queue<int, std::vector<int>, std::less<int> > pq_t; + +int N; +int* shared_data; + +// Code for testing basic interface using function objects +class push_fnobj : NoAssign, Harness::NoAfterlife { + pq_t& pq; + int threadID; +public: + push_fnobj(pq_t& pq_, int tid) : pq(pq_), threadID(tid) {} + void operator()() const { + AssertLive(); + pq.push(threadID); + } +}; + +class pop_fnobj : NoAssign, Harness::NoAfterlife { + pq_t& pq; +public: + pop_fnobj(pq_t& pq_) : pq(pq_) {} + void operator()() const { + AssertLive(); + ASSERT(!pq.empty(), "queue should not be empty yet"); + int elem = pq.top(); + pq.pop(); + shared_data[elem]++; + } +}; + +class BasicBody : NoAssign { + pq_t& pq; + tbb::aggregator& agg; +public: + BasicBody(pq_t& pq_, tbb::aggregator& agg_) : pq(pq_), agg(agg_) {} + void operator()(const int threadID) const { + for (int i=0; i<N; ++i) agg.execute( push_fnobj(pq, threadID) ); + for (int i=0; i<N; ++i) agg.execute( pop_fnobj(pq) ); + } +}; + +void TestBasicInterface(int nThreads) { + pq_t my_pq; + tbb::aggregator agg; + for (int i=0; i<MaxThread; ++i) shared_data[i] = 0; + REMARK("Testing aggregator basic interface.\n"); + NativeParallelFor(nThreads, BasicBody(my_pq, agg)); + for (int i=0; i<nThreads; ++i) + ASSERT(shared_data[i] == N, "wrong number of elements pushed"); + REMARK("Done testing aggregator basic interface.\n"); +} +// End of code for testing basic interface using function objects + + +// Code for testing basic interface using lambda expressions +#if __TBB_LAMBDAS_PRESENT +void TestBasicLambdaInterface(int nThreads) { + pq_t my_pq; + tbb::aggregator agg; + for (int i=0; i<MaxThread; ++i) shared_data[i] = 0; + REMARK("Testing aggregator basic lambda interface.\n"); + NativeParallelFor(nThreads, [&agg, &my_pq](const int threadID) { + for (int i=0; i<N; ++i) + agg.execute( [&, threadID]() { my_pq.push(threadID); } ); + for (int i=0; i<N; ++i) { + agg.execute( [&]() { + ASSERT(!my_pq.empty(), "queue should not be empty yet"); + int elem = my_pq.top(); + my_pq.pop(); + shared_data[elem]++; + } ); + } + } ); + for (int i=0; i<nThreads; ++i) + ASSERT(shared_data[i] == N, "wrong number of elements pushed"); + REMARK("Done testing aggregator basic lambda interface.\n"); +} +#endif /* __TBB_LAMBDAS_PRESENT */ +// End of code for testing basic interface using lambda expressions + +// Code for testing expert interface +class op_data : public tbb::aggregator_operation, NoAssign { +public: + const int tid; + op_data(const int tid_=-1) : tbb::aggregator_operation(), tid(tid_) {} +}; + +class my_handler { + pq_t *pq; +public: + my_handler() {} + my_handler(pq_t *pq_) : pq(pq_) {} + void operator()(tbb::aggregator_operation* op_list) const { + while (op_list) { + op_data& request = static_cast<op_data&>(*op_list); + op_list = op_list->next(); + request.start(); + if (request.tid >= 0) pq->push(request.tid); + else { + ASSERT(!pq->empty(), "queue should not be empty!"); + int elem = pq->top(); + pq->pop(); + shared_data[elem]++; + } + request.finish(); + } + } +}; + +class ExpertBody : NoAssign { + pq_t& pq; + tbb::aggregator_ext<my_handler>& agg; +public: + ExpertBody(pq_t& pq_, tbb::aggregator_ext<my_handler>& agg_) : pq(pq_), agg(agg_) {} + void operator()(const int threadID) const { + for (int i=0; i<N; ++i) { + op_data to_push(threadID); + agg.process( &to_push ); + } + for (int i=0; i<N; ++i) { + op_data to_pop; + agg.process( &to_pop ); + } + } +}; + +void TestExpertInterface(int nThreads) { + pq_t my_pq; + tbb::aggregator_ext<my_handler> agg((my_handler(&my_pq))); + for (int i=0; i<MaxThread; ++i) shared_data[i] = 0; + REMARK("Testing aggregator expert interface.\n"); + NativeParallelFor(nThreads, ExpertBody(my_pq, agg)); + for (int i=0; i<nThreads; ++i) + ASSERT(shared_data[i] == N, "wrong number of elements pushed"); + REMARK("Done testing aggregator expert interface.\n"); +} +// End of code for testing expert interface + +int TestMain() { + if (MinThread < 1) + MinThread = 1; + shared_data = new int[MaxThread]; + for (int p = MinThread; p <= MaxThread; ++p) { + REMARK("Testing on %d threads.\n", p); + N = 0; + while (N <= 100) { + REMARK("Testing with N=%d\n", N); + TestBasicInterface(p); +#if __TBB_LAMBDAS_PRESENT + TestBasicLambdaInterface(p); +#endif /* __TBB_LAMBDAS_PRESENT */ + TestExpertInterface(p); + N = N ? N*10 : 1; + } + } + return Harness::Done; +} diff --git a/src/tbb/src/test/test_aligned_space.cpp b/src/tbb/src/test/test_aligned_space.cpp new file mode 100644 index 0000000..486bd0a --- /dev/null +++ b/src/tbb/src/test/test_aligned_space.cpp @@ -0,0 +1,122 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/tbb_config.h" + +#if __TBB_GCC_WARNING_SUPPRESSION_PRESENT +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif + +//! Wrapper around T where all members are private. +/** Used to prove that aligned_space<T,N> never calls member of T. */ +template<typename T> +class Minimal { + Minimal(); + Minimal( Minimal& min ); + ~Minimal(); + void operator=( const Minimal& ); + T pad; + template<typename U> + friend void AssignToCheckAlignment( Minimal<U>& dst, const Minimal<U>& src ) ; +}; + +template<typename T> +void AssignToCheckAlignment( Minimal<T>& dst, const Minimal<T>& src ) { + dst.pad = src.pad; +} + +#include "tbb/aligned_space.h" +#include "harness_assert.h" + +static bool SpaceWasted; + +template<typename U, size_t N> +void TestAlignedSpaceN() { + typedef Minimal<U> T; + struct { + //! Pad byte increases chance that subsequent member will be misaligned if there is a problem. + char pad; + tbb::aligned_space<T ,N> space; + } x; + AssertSameType( static_cast< T *>(0), x.space.begin() ); + AssertSameType( static_cast< T *>(0), x.space.end() ); + ASSERT( reinterpret_cast<void *>(x.space.begin())==reinterpret_cast< void *>(&x.space), NULL ); + ASSERT( x.space.end()-x.space.begin()==N, NULL ); + ASSERT( reinterpret_cast<void *>(x.space.begin())>=reinterpret_cast< void *>(&x.space), NULL ); + ASSERT( x.space.end()<=reinterpret_cast< T *>(&x.space+1), NULL ); + // Though not required, a good implementation of aligned_space<T,N> does not use any more space than a T[N]. + SpaceWasted |= sizeof(x.space)!=sizeof(T)*N; + for( size_t k=1; k<N; ++k ) + AssignToCheckAlignment( x.space.begin()[k-1], x.space.begin()[k] ); +} + +static void PrintSpaceWastingWarning( const char* type_name ); + +#include <typeinfo> + +template<typename T> +void TestAlignedSpace() { + SpaceWasted = false; + TestAlignedSpaceN<T,1>(); + TestAlignedSpaceN<T,2>(); + TestAlignedSpaceN<T,3>(); + TestAlignedSpaceN<T,4>(); + TestAlignedSpaceN<T,5>(); + TestAlignedSpaceN<T,6>(); + TestAlignedSpaceN<T,7>(); + TestAlignedSpaceN<T,8>(); + if( SpaceWasted ) + PrintSpaceWastingWarning( typeid(T).name() ); +} + +#define HARNESS_NO_PARSE_COMMAND_LINE 1 +#include "harness.h" + +#include "harness_m128.h" + +int TestMain () { + TestAlignedSpace<char>(); + TestAlignedSpace<short>(); + TestAlignedSpace<int>(); + TestAlignedSpace<float>(); + TestAlignedSpace<double>(); + TestAlignedSpace<long double>(); + TestAlignedSpace<size_t>(); +#if HAVE_m128 + TestAlignedSpace<__m128>(); +#endif +#if HAVE_m256 + if (have_AVX()) TestAlignedSpace<__m256>(); +#endif + return Harness::Done; +} + +static void PrintSpaceWastingWarning( const char* type_name ) { + REPORT("Consider rewriting aligned_space<%s,N> to waste less space\n", type_name ); +} + diff --git a/src/tbb/src/test/test_allocator.h b/src/tbb/src/test/test_allocator.h new file mode 100644 index 0000000..0958632 --- /dev/null +++ b/src/tbb/src/test/test_allocator.h @@ -0,0 +1,223 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Basic testing of an allocator +// Tests against requirements in 20.1.5 of ISO C++ Standard (1998). +// Does not check for thread safety or false sharing issues. +// +// Tests for compatibility with the host's STL are in +// test_Allocator_STL.h. Those tests are in a separate file +// because they bring in lots of STL headers, and the tests here +// are supposed to work in the abscense of STL. + +#include "harness.h" + +template<typename A> +struct is_zero_filling { + static const bool value = false; +}; + +int NumberOfFoo; + +template<typename T, size_t N> +struct Foo { + T foo_array[N]; + Foo() { + zero_fill<T>(foo_array, N); + ++NumberOfFoo; + } + Foo( const Foo& x ) { + *this = x; + ++NumberOfFoo; + } + ~Foo() { + --NumberOfFoo; + } +}; + +inline char PseudoRandomValue( size_t j, size_t k ) { + return char(j*3 ^ j>>4 ^ k); +} + +//! T is type and A is allocator for that type +template<typename T, typename A> +void TestBasic( A& a ) { + T x; + const T cx = T(); + + // See Table 32 in ISO ++ Standard + typename A::pointer px = &x; + typename A::const_pointer pcx = &cx; + + typename A::reference rx = x; + ASSERT( &rx==&x, NULL ); + + typename A::const_reference rcx = cx; + ASSERT( &rcx==&cx, NULL ); + + typename A::value_type v = x; + + typename A::size_type size; + size = 0; + --size; + ASSERT( size>0, "not an unsigned integral type?" ); + + typename A::difference_type difference; + difference = 0; + --difference; + ASSERT( difference<0, "not an signed integral type?" ); + + // "rebind" tested by our caller + + ASSERT( a.address(rx)==px, NULL ); + + ASSERT( a.address(rcx)==pcx, NULL ); + + typename A::pointer array[100]; + size_t sizeof_T = sizeof(T); + for( size_t k=0; k<100; ++k ) { + array[k] = k&1 ? a.allocate(k,array[0]) : a.allocate(k); + char* s = reinterpret_cast<char*>(reinterpret_cast<void*>(array[k])); + for( size_t j=0; j<k*sizeof_T; ++j ) + s[j] = PseudoRandomValue(j,k); + } + + // Test hint argument. This can't be compiled when hint is void*, It should be const void* + typename A::pointer a_ptr; + const void * const_hint = NULL; + a_ptr = a.allocate (1, const_hint); + a.deallocate(a_ptr, 1); + + // Test "a.deallocate(p,n) + for( size_t k=0; k<100; ++k ) { + char* s = reinterpret_cast<char*>(reinterpret_cast<void*>(array[k])); + for( size_t j=0; j<k*sizeof_T; ++j ) + ASSERT( s[j] == PseudoRandomValue(j,k), NULL ); + a.deallocate(array[k],k); + } + + // Test "a.max_size()" + AssertSameType( a.max_size(), typename A::size_type(0) ); + // Following assertion catches case where max_size() is so large that computation of + // number of bytes for such an allocation would overflow size_type. + ASSERT( a.max_size()*typename A::size_type(sizeof(T))>=a.max_size(), "max_size larger than reasonable" ); + + // Test "a.construct(p,t)" + int n = NumberOfFoo; + typename A::pointer p = a.allocate(1); + a.construct( p, cx ); + ASSERT( NumberOfFoo==n+1, "constructor for Foo not called?" ); + + // Test "a.destroy(p)" + a.destroy( p ); + ASSERT( NumberOfFoo==n, "destructor for Foo not called?" ); + a.deallocate(p,1); +} + +#include "tbb/blocked_range.h" + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // Workaround for erroneous "conditional expression is constant" warning in method check_allocate. + #pragma warning (disable: 4127) +#endif + +// A is an allocator for some type +template<typename A> +struct Body: NoAssign { + static const size_t max_k = 100000; + A &a; + Body(A &a_) : a(a_) {} + void check_allocate( typename A::pointer array[], size_t i, size_t t ) const + { + ASSERT(array[i] == 0, NULL); + size_t size = i * (i&3); + array[i] = i&1 ? a.allocate(size, array[i>>3]) : a.allocate(size); + ASSERT(array[i] != 0, "allocator returned null"); + char* s = reinterpret_cast<char*>(reinterpret_cast<void*>(array[i])); + for( size_t j=0; j<size*sizeof(typename A::value_type); ++j ) { + if(is_zero_filling<typename A::template rebind<void>::other>::value) + ASSERT( !s[j], NULL); + s[j] = PseudoRandomValue(i, t); + } + } + + void check_deallocate( typename A::pointer array[], size_t i, size_t t ) const + { + ASSERT(array[i] != 0, NULL); + size_t size = i * (i&3); + char* s = reinterpret_cast<char*>(reinterpret_cast<void*>(array[i])); + for( size_t j=0; j<size*sizeof(typename A::value_type); ++j ) + ASSERT( s[j] == PseudoRandomValue(i, t), "Thread safety test failed" ); + a.deallocate(array[i], size); + array[i] = 0; + } + + void operator()( size_t thread_id ) const { + typename A::pointer array[256]; + + for( size_t k=0; k<256; ++k ) + array[k] = 0; + for( size_t k=0; k<max_k; ++k ) { + size_t i = static_cast<unsigned char>(PseudoRandomValue(k,thread_id)); + if(!array[i]) check_allocate(array, i, thread_id); + else check_deallocate(array, i, thread_id); + } + for( size_t k=0; k<256; ++k ) + if(array[k]) + check_deallocate(array, k, thread_id); +#if __TBBMALLOC_CALL_THREAD_SHUTDOWN + __TBB_mallocThreadShutdownNotification(); +#endif + } +}; + +// A is an allocator for some type, and U is another type +template<typename U, typename A> +void Test(A &a) { + typename A::template rebind<U>::other b(a); + TestBasic<U>(b); + TestBasic<typename A::value_type>(a); + + // thread safety + NativeParallelFor( 4, Body<A>(a) ); + ASSERT( NumberOfFoo==0, "Allocate/deallocate count mismatched" ); + + ASSERT( a==b, NULL ); + ASSERT( !(a!=b), NULL ); +} + +template<typename Allocator> +int TestMain(const Allocator &a = Allocator() ) { + NumberOfFoo = 0; + typename Allocator::template rebind<Foo<char,1> >::other a1(a); + typename Allocator::template rebind<Foo<double,1> >::other a2(a); + Test<Foo<int,17> >( a1 ); + Test<Foo<float,23> >( a2 ); + return 0; +} + diff --git a/src/tbb/src/test/test_allocator_STL.h b/src/tbb/src/test/test_allocator_STL.h new file mode 100644 index 0000000..4e9a8fe --- /dev/null +++ b/src/tbb/src/test/test_allocator_STL.h @@ -0,0 +1,116 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Tests for compatibility with the host's STL. + +#include "harness.h" + +template<typename Container> +void TestSequence(const typename Container::allocator_type &a) { + Container c(a); + for( int i=0; i<1000; ++i ) + c.push_back(i*i); + typename Container::const_iterator p = c.begin(); + for( int i=0; i<1000; ++i ) { + ASSERT( *p==i*i, NULL ); + ++p; + } + // regression test against compilation error for GCC 4.6.2 + c.resize(1000); +} + +template<typename Set> +void TestSet(const typename Set::allocator_type &a) { + Set s(typename Set::key_compare(), a); + typedef typename Set::value_type value_type; + for( int i=0; i<100; ++i ) + s.insert(value_type(3*i)); + for( int i=0; i<300; ++i ) { + ASSERT( s.erase(i)==size_t(i%3==0), NULL ); + } +} + +template<typename Map> +void TestMap(const typename Map::allocator_type &a) { + Map m(typename Map::key_compare(), a); + typedef typename Map::value_type value_type; + for( int i=0; i<100; ++i ) + m.insert(value_type(i,i*i)); + for( int i=0; i<100; ++i ) + ASSERT( m.find(i)->second==i*i, NULL ); +} + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include <deque> +#include <list> +#include <map> +#include <set> +#include <vector> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +template<typename Allocator> +void TestAllocatorWithSTL(const Allocator &a = Allocator() ) { + typedef typename Allocator::template rebind<int>::other Ai; + typedef typename Allocator::template rebind<const int>::other Aci; + typedef typename Allocator::template rebind<std::pair<const int, int> >::other Acii; + typedef typename Allocator::template rebind<std::pair<int, int> >::other Aii; + + // Sequenced containers + TestSequence<std::deque <int,Ai> >(a); + TestSequence<std::list <int,Ai> >(a); + TestSequence<std::vector<int,Ai> >(a); + + // Associative containers + TestSet<std::set <int, std::less<int>, Ai> >(a); + TestSet<std::multiset<int, std::less<int>, Ai> >(a); + TestMap<std::map <int, int, std::less<int>, Acii> >(a); + TestMap<std::multimap<int, int, std::less<int>, Acii> >(a); + +#if _MSC_VER + // Test compatibility with Microsoft's implementation of std::allocator for some cases that + // are undefined according to the ISO standard but permitted by Microsoft. + TestSequence<std::deque <const int,Aci> >(a); +#if _CPPLIB_VER>=500 + TestSequence<std::list <const int,Aci> >(a); +#endif + TestSequence<std::vector<const int,Aci> >(a); + TestSet<std::set<const int, std::less<int>, Aci> >(a); + TestMap<std::map<int, int, std::less<int>, Aii> >(a); + TestMap<std::map<const int, int, std::less<int>, Acii> >(a); + TestMap<std::multimap<int, int, std::less<int>, Aii> >(a); + TestMap<std::multimap<const int, int, std::less<int>, Acii> >(a); +#endif /* _MSC_VER */ +} diff --git a/src/tbb/src/test/test_assembly.cpp b/src/tbb/src/test/test_assembly.cpp new file mode 100644 index 0000000..d737dec --- /dev/null +++ b/src/tbb/src/test/test_assembly.cpp @@ -0,0 +1,152 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Program for basic correctness testing of assembly-language routines. +#include "harness_defs.h" + +#if __TBB_TEST_SKIP_BUILTINS_MODE +#include "harness.h" +int TestMain() { + REPORT("Known issue: GCC builtins aren't available\n"); + return Harness::Skipped; +} +#else + +#include "tbb/task.h" + +#include <new> +#include "harness.h" + +using tbb::internal::reference_count; + +//! Test __TBB_CompareAndSwapW +static void TestCompareExchange() { + ASSERT( intptr_t(-10)<10, "intptr_t not a signed integral type?" ); + REMARK("testing __TBB_CompareAndSwapW\n"); + for( intptr_t a=-10; a<10; ++a ) + for( intptr_t b=-10; b<10; ++b ) + for( intptr_t c=-10; c<10; ++c ) { +// Workaround for a bug in GCC 4.3.0; and one more is below. +#if __TBB_GCC_OPTIMIZER_ORDERING_BROKEN + intptr_t x; + __TBB_store_with_release( x, a ); +#else + intptr_t x = a; +#endif + intptr_t y = __TBB_CompareAndSwapW(&x,b,c); + ASSERT( y==a, NULL ); + if( a==c ) + ASSERT( x==b, NULL ); + else + ASSERT( x==a, NULL ); + } +} + +//! Test __TBB___TBB_FetchAndIncrement and __TBB___TBB_FetchAndDecrement +static void TestAtomicCounter() { + // "canary" is a value used to detect illegal overwrites. + const reference_count canary = ~(uintptr_t)0/3; + REMARK("testing __TBB_FetchAndIncrement\n"); + struct { + reference_count prefix, i, suffix; + } x; + x.prefix = canary; + x.i = 0; + x.suffix = canary; + for( int k=0; k<10; ++k ) { + reference_count j = __TBB_FetchAndIncrementWacquire((volatile void *)&x.i); + ASSERT( x.prefix==canary, NULL ); + ASSERT( x.suffix==canary, NULL ); + ASSERT( x.i==k+1, NULL ); + ASSERT( j==k, NULL ); + } + REMARK("testing __TBB_FetchAndDecrement\n"); + x.i = 10; + for( int k=10; k>0; --k ) { + reference_count j = __TBB_FetchAndDecrementWrelease((volatile void *)&x.i); + ASSERT( j==k, NULL ); + ASSERT( x.i==k-1, NULL ); + ASSERT( x.prefix==canary, NULL ); + ASSERT( x.suffix==canary, NULL ); + } +} + +static void TestTinyLock() { + REMARK("testing __TBB_LockByte\n"); + __TBB_atomic_flag flags[16]; + for( unsigned int i=0; i<16; ++i ) + flags[i] = (__TBB_Flag)i; +#if __TBB_GCC_OPTIMIZER_ORDERING_BROKEN + __TBB_store_with_release( flags[8], 0 ); +#else + flags[8] = 0; +#endif + __TBB_LockByte(flags[8]); + for( unsigned int i=0; i<16; ++i ) + #ifdef __sparc + ASSERT( flags[i]==(i==8?0xff:i), NULL ); + #else + ASSERT( flags[i]==(i==8?1:i), NULL ); + #endif + __TBB_UnlockByte(flags[8], 0); + for( unsigned int i=0; i<16; ++i ) + ASSERT( flags[i] == (i==8?0:i), NULL ); +} + +static void TestLog2() { + REMARK("testing __TBB_Log2\n"); + for( uintptr_t i=1; i; i<<=1 ) { + for( uintptr_t j=1; j<1<<16; ++j ) { + if( uintptr_t k = i*j ) { + uintptr_t actual = __TBB_Log2(k); + const uintptr_t ONE = 1; // warning suppression again + ASSERT( k >= ONE<<actual, NULL ); + ASSERT( k>>1 < ONE<<actual, NULL ); + } + } + } +} + +static void TestPause() { + REMARK("testing __TBB_Pause\n"); + __TBB_Pause(1); +} + +int TestMain () { + __TBB_TRY { + TestLog2(); + TestTinyLock(); + TestCompareExchange(); + TestAtomicCounter(); + TestPause(); + } __TBB_CATCH(...) { + ASSERT(0,"unexpected exception"); + } + return Harness::Done; +} +#endif // __TBB_TEST_SKIP_BUILTINS_MODE diff --git a/src/tbb/src/test/test_atomic.cpp b/src/tbb/src/test/test_atomic.cpp new file mode 100644 index 0000000..85949e9 --- /dev/null +++ b/src/tbb/src/test/test_atomic.cpp @@ -0,0 +1,1170 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "harness_defs.h" + +#if __TBB_TEST_SKIP_PIC_MODE || __TBB_TEST_SKIP_BUILTINS_MODE +#include "harness.h" +int TestMain() { + REPORT("Known issue: %s\n", + __TBB_TEST_SKIP_PIC_MODE? "PIC mode is not supported" : "GCC builtins aren't available"); + return Harness::Skipped; +} +#else + +// Put tbb/atomic.h first, so if it is missing a prerequisite header, we find out about it. +// The tests here do *not* test for atomicity, just serial correctness. */ + +#include "tbb/atomic.h" +#include "harness_assert.h" +#include <string.h> // memcmp + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // Unary minus operator applied to unsigned type, result still unsigned + // Constant conditional expression + #pragma warning( disable: 4127 4310 ) +#endif + +enum LoadStoreExpression { + UseOperators, + UseImplicitAcqRel, + UseExplicitFullyFenced, + UseExplicitAcqRel, + UseExplicitRelaxed, + UseGlobalHelperFullyFenced, + UseGlobalHelperAcqRel, + UseGlobalHelperRelaxed +}; + +//! Structure that holds an atomic<T> and some guard bytes around it. +template<typename T, LoadStoreExpression E = UseOperators> +struct TestStruct { + typedef unsigned char byte_type; + T prefix; + tbb::atomic<T> counter; + T suffix; + TestStruct( T i ) { + ASSERT( sizeof(*this)==3*sizeof(T), NULL ); + for (size_t j = 0; j < sizeof(T); ++j) { + reinterpret_cast<byte_type*>(&prefix)[j] = byte_type(0x11*(j+1)); + reinterpret_cast<byte_type*>(&suffix)[sizeof(T)-j-1] = byte_type(0x11*(j+1)); + } + if ( E == UseOperators ) + counter = i; + else if ( E == UseExplicitRelaxed ) + counter.template store<tbb::relaxed>(i); + else + tbb::store<tbb::full_fence>( counter, i ); + } + ~TestStruct() { + // Check for writes outside the counter. + for (size_t j = 0; j < sizeof(T); ++j) { + ASSERT( reinterpret_cast<byte_type*>(&prefix)[j] == byte_type(0x11*(j+1)), NULL ); + ASSERT( reinterpret_cast<byte_type*>(&suffix)[sizeof(T)-j-1] == byte_type(0x11*(j+1)), NULL ); + } + } + static tbb::atomic<T> gCounter; +}; + +// A global variable of type tbb::atomic<> +template<typename T, LoadStoreExpression E> tbb::atomic<T> TestStruct<T, E>::gCounter; + +//! Test compare_and_swap template members of class atomic<T> for memory_semantics=M +template<typename T,tbb::memory_semantics M> +void TestCompareAndSwapWithExplicitOrdering( T i, T j, T k ) { + ASSERT( i!=k, "values must be distinct" ); + // Test compare_and_swap that should fail + TestStruct<T> x(i); + T old = x.counter.template compare_and_swap<M>( j, k ); + ASSERT( old==i, NULL ); + ASSERT( x.counter==i, "old value not retained" ); + // Test compare and swap that should succeed + old = x.counter.template compare_and_swap<M>( j, i ); + ASSERT( old==i, NULL ); + ASSERT( x.counter==j, "value not updated?" ); +} + +//! i, j, k must be different values +template<typename T> +void TestCompareAndSwap( T i, T j, T k ) { + ASSERT( i!=k, "values must be distinct" ); + // Test compare_and_swap that should fail + TestStruct<T> x(i); + T old = x.counter.compare_and_swap( j, k ); + ASSERT( old==i, NULL ); + ASSERT( x.counter==i, "old value not retained" ); + // Test compare and swap that should succeed + old = x.counter.compare_and_swap( j, i ); + ASSERT( old==i, NULL ); + if( x.counter==i ) { + ASSERT( x.counter==j, "value not updated?" ); + } else { + ASSERT( x.counter==j, "value trashed" ); + } + // Check that atomic global variables work + TestStruct<T>::gCounter = i; + old = TestStruct<T>::gCounter.compare_and_swap( j, i ); + ASSERT( old==i, NULL ); + ASSERT( TestStruct<T>::gCounter==j, "value not updated?" ); + TestCompareAndSwapWithExplicitOrdering<T,tbb::full_fence>(i,j,k); + TestCompareAndSwapWithExplicitOrdering<T,tbb::acquire>(i,j,k); + TestCompareAndSwapWithExplicitOrdering<T,tbb::release>(i,j,k); + TestCompareAndSwapWithExplicitOrdering<T,tbb::relaxed>(i,j,k); +} + +//! memory_semantics variation on TestFetchAndStore +template<typename T, tbb::memory_semantics M> +void TestFetchAndStoreWithExplicitOrdering( T i, T j ) { + ASSERT( i!=j, "values must be distinct" ); + TestStruct<T> x(i); + T old = x.counter.template fetch_and_store<M>( j ); + ASSERT( old==i, NULL ); + ASSERT( x.counter==j, NULL ); +} + +//! i and j must be different values +template<typename T> +void TestFetchAndStore( T i, T j ) { + ASSERT( i!=j, "values must be distinct" ); + TestStruct<T> x(i); + T old = x.counter.fetch_and_store( j ); + ASSERT( old==i, NULL ); + ASSERT( x.counter==j, NULL ); + // Check that atomic global variables work + TestStruct<T>::gCounter = i; + old = TestStruct<T>::gCounter.fetch_and_store( j ); + ASSERT( old==i, NULL ); + ASSERT( TestStruct<T>::gCounter==j, "value not updated?" ); + TestFetchAndStoreWithExplicitOrdering<T,tbb::full_fence>(i,j); + TestFetchAndStoreWithExplicitOrdering<T,tbb::acquire>(i,j); + TestFetchAndStoreWithExplicitOrdering<T,tbb::release>(i,j); + TestFetchAndStoreWithExplicitOrdering<T,tbb::relaxed>(i,j); +} + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // conversion from <bigger integer> to <smaller integer>, possible loss of data + // the warning seems a complete nonsense when issued for e.g. short+=short + #pragma warning( disable: 4244 ) +#endif + +//! Test fetch_and_add members of class atomic<T> for memory_semantics=M +template<typename T,tbb::memory_semantics M> +void TestFetchAndAddWithExplicitOrdering( T i ) { + TestStruct<T> x(i); + T actual; + T expected = i; + + // Test fetch_and_add member template + for( int j=0; j<10; ++j ) { + actual = x.counter.fetch_and_add(j); + ASSERT( actual==expected, NULL ); + expected += j; + } + for( int j=0; j<10; ++j ) { + actual = x.counter.fetch_and_add(-j); + ASSERT( actual==expected, NULL ); + expected -= j; + } + + // Test fetch_and_increment member template + ASSERT( x.counter==i, NULL ); + actual = x.counter.template fetch_and_increment<M>(); + ASSERT( actual==i, NULL ); + ASSERT( x.counter==T(i+1), NULL ); + + // Test fetch_and_decrement member template + actual = x.counter.template fetch_and_decrement<M>(); + ASSERT( actual==T(i+1), NULL ); + ASSERT( x.counter==i, NULL ); +} + +//! Test fetch_and_add and related operators +template<typename T> +void TestFetchAndAdd( T i ) { + TestStruct<T> x(i); + T value; + value = ++x.counter; + ASSERT( value==T(i+1), NULL ); + value = x.counter++; + ASSERT( value==T(i+1), NULL ); + value = x.counter--; + ASSERT( value==T(i+2), NULL ); + value = --x.counter; + ASSERT( value==i, NULL ); + T actual; + T expected = i; + for( int j=-100; j<=100; ++j ) { + expected += j; + actual = x.counter += j; + ASSERT( actual==expected, NULL ); + } + for( int j=-100; j<=100; ++j ) { + expected -= j; + actual = x.counter -= j; + ASSERT( actual==expected, NULL ); + } + // Test fetch_and_increment + ASSERT( x.counter==i, NULL ); + actual = x.counter.fetch_and_increment(); + ASSERT( actual==i, NULL ); + ASSERT( x.counter==T(i+1), NULL ); + + // Test fetch_and_decrement + actual = x.counter.fetch_and_decrement(); + ASSERT( actual==T(i+1), NULL ); + ASSERT( x.counter==i, NULL ); + x.counter = i; + ASSERT( x.counter==i, NULL ); + + // Check that atomic global variables work + TestStruct<T>::gCounter = i; + value = TestStruct<T>::gCounter.fetch_and_add( 42 ); + expected = i+42; + ASSERT( value==i, NULL ); + ASSERT( TestStruct<T>::gCounter==expected, "value not updated?" ); + TestFetchAndAddWithExplicitOrdering<T,tbb::full_fence>(i); + TestFetchAndAddWithExplicitOrdering<T,tbb::acquire>(i); + TestFetchAndAddWithExplicitOrdering<T,tbb::release>(i); + TestFetchAndAddWithExplicitOrdering<T,tbb::relaxed>(i); +} + +//! A type with unknown size. +class IncompleteType; + +void TestFetchAndAdd( IncompleteType* ) { + // There are no fetch-and-add operations on a IncompleteType*. +} +void TestFetchAndAdd( void* ) { + // There are no fetch-and-add operations on a void*. +} + +void TestFetchAndAdd( bool ) { + // There are no fetch-and-add operations on a bool. +} + +template<typename T> +void TestConst( T i ) { + // Try const + const TestStruct<T> x(i); + ASSERT( memcmp( &i, &x.counter, sizeof(T) )==0, "write to atomic<T> broken?" ); + ASSERT( x.counter==i, "read of atomic<T> broken?" ); + const TestStruct<T, UseExplicitRelaxed> y(i); + ASSERT( memcmp( &i, &y.counter, sizeof(T) )==0, "relaxed write to atomic<T> broken?" ); + ASSERT( tbb::load<tbb::relaxed>(y.counter) == i, "relaxed read of atomic<T> broken?" ); + const TestStruct<T, UseGlobalHelperFullyFenced> z(i); + ASSERT( memcmp( &i, &z.counter, sizeof(T) )==0, "sequentially consistent write to atomic<T> broken?" ); + ASSERT( z.counter.template load<tbb::full_fence>() == i, "sequentially consistent read of atomic<T> broken?" ); +} + +template<typename T> +void TestOperations( T i, T j, T k ) { + TestConst(i); + TestCompareAndSwap(i,j,k); + TestFetchAndStore(i,k); // Pass i,k instead of i,j, because callee requires two distinct values. +} + +template<typename T> +void TestParallel( const char* name ); + +bool ParallelError; + +template<typename T> +struct AlignmentChecker { + char c; + tbb::atomic<T> i; +}; + +#include "harness.h" + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // unary minus operator applied to unsigned type, result still unsigned + #pragma warning( disable: 4146 ) +#endif + +/** T is an integral type. */ +template<typename T> +void TestAtomicInteger( const char* name ) { + REMARK("testing atomic<%s> (size=%d)\n",name,sizeof(tbb::atomic<T>)); +#if ( __linux__ && __TBB_x86_32 && __GNUC__==3 && __GNUC_MINOR__==3 ) || defined(__SUNPRO_CC) + // gcc 3.3 has known problem for 32-bit Linux, so only warn if there is a problem. + // SUNPRO_CC does have this problem as well + if( sizeof(T)==8 ) { + if( sizeof(AlignmentChecker<T>)!=2*sizeof(tbb::atomic<T>) ) { + REPORT("Known issue: alignment for atomic<%s> is wrong with gcc 3.3 and sunCC 5.9 2008/01/28 for IA32\n",name); + } + } else +#endif /* ( __linux__ && __TBB_x86_32 && __GNUC__==3 && __GNUC_MINOR__==3 ) || defined(__SUNPRO_CC) */ + ASSERT( sizeof(AlignmentChecker<T>)==2*sizeof(tbb::atomic<T>), NULL ); + TestOperations<T>(0L,T(-T(1)),T(1)); + for( int k=0; k<int(sizeof(long))*8-1; ++k ) { + TestOperations<T>(T(1L<<k),T(~(1L<<k)),T(1-(1L<<k))); + TestOperations<T>(T(-1L<<k),T(~(-1L<<k)),T(1-(-1L<<k))); + TestFetchAndAdd<T>(T(-1L<<k)); + } + TestParallel<T>( name ); +} + +template<typename T> +struct Foo { + T x, y, z; +}; + +template<typename T> +void TestIndirection() { + Foo<T> item; + tbb::atomic<Foo<T>*> pointer; + pointer = &item; + for( int k=-10; k<=10; ++k ) { + // Test various syntaxes for indirection to fields with non-zero offset. + T value1=T(), value2=T(); + for( size_t j=0; j<sizeof(T); ++j ) { + *(char*)&value1 = char(k^j); + *(char*)&value2 = char(k^j*j); + } + pointer->y = value1; + (*pointer).z = value2; + T result1 = (*pointer).y; + T result2 = pointer->z; + ASSERT( memcmp(&value1,&result1,sizeof(T))==0, NULL ); + ASSERT( memcmp(&value2,&result2,sizeof(T))==0, NULL ); + } +} + +//! Test atomic<T*> +template<typename T> +void TestAtomicPointer() { + REMARK("testing atomic pointer (%d)\n",int(sizeof(T))); + T array[1000]; + TestOperations<T*>(&array[500],&array[250],&array[750]); + TestFetchAndAdd<T*>(&array[500]); + TestIndirection<T>(); + TestParallel<T*>( "pointer" ); +} + +//! Test atomic<Ptr> where Ptr is a pointer to a type of unknown size +template<typename Ptr> +void TestAtomicPointerToTypeOfUnknownSize( const char* name ) { + REMARK("testing atomic<%s>\n",name); + char array[1000]; + TestOperations<Ptr>((Ptr)(void*)&array[500],(Ptr)(void*)&array[250],(Ptr)(void*)&array[750]); + TestParallel<Ptr>( name ); +} + +void TestAtomicBool() { + REMARK("testing atomic<bool>\n"); + TestOperations<bool>(true,true,false); + TestOperations<bool>(false,false,true); + TestParallel<bool>( "bool" ); +} + +enum Color {Red=0,Green=1,Blue=-1}; + +void TestAtomicEnum() { + REMARK("testing atomic<Color>\n"); + TestOperations<Color>(Red,Green,Blue); + TestParallel<Color>( "Color" ); +} + +template<typename T> +void TestAtomicFloat( const char* name ) { + REMARK("testing atomic<%s>\n", name ); + TestOperations<T>(0.5,3.25,10.75); + TestParallel<T>( name ); +} + +#if __TBB_BIG_ENDIAN!=-1 +namespace masked_cas_helpers { + const int numMaskedOperations = 100000; + const int testSpaceSize = 8; + int prime[testSpaceSize] = {3,5,7,11,13,17,19,23}; + + + template<typename T> + class TestMaskedCAS_Body: NoAssign { + T* test_space_uncontended; + T* test_space_contended; + public: + TestMaskedCAS_Body( T* _space1, T* _space2 ) : test_space_uncontended(_space1), test_space_contended(_space2) {} + void operator()( int my_idx ) const { + using tbb::internal::__TBB_MaskedCompareAndSwap; + const T my_prime = T(prime[my_idx]); + T* const my_ptr = test_space_uncontended+my_idx; + T old_value=0; + for( int i=0; i<numMaskedOperations; ++i, old_value+=my_prime ){ + T result; + // Test uncontended case + T new_value = old_value + my_prime; + // The following CAS should always fail + result = __TBB_MaskedCompareAndSwap<T>(my_ptr,new_value,old_value-1); + ASSERT(result!=old_value-1, "masked CAS succeeded while it should fail"); + ASSERT(result==*my_ptr, "masked CAS result mismatch with real value"); + // The following one should succeed + result = __TBB_MaskedCompareAndSwap<T>(my_ptr,new_value,old_value); + ASSERT(result==old_value && *my_ptr==new_value, "masked CAS failed while it should succeed"); + // The following one should fail again + result = __TBB_MaskedCompareAndSwap<T>(my_ptr,new_value,old_value); + ASSERT(result!=old_value, "masked CAS succeeded while it should fail"); + ASSERT(result==*my_ptr, "masked CAS result mismatch with real value"); + // Test contended case + for( int j=0; j<testSpaceSize; ++j ){ + // try adding my_prime until success + T value; + do { + value = test_space_contended[j]; + result = __TBB_MaskedCompareAndSwap<T>(test_space_contended+j,value+my_prime,value); + } while( result!=value ); + } + } + } + }; + + template<typename T> + struct intptr_as_array_of + { + static const int how_many_Ts = sizeof(intptr_t)/sizeof(T); + union { + intptr_t result; + T space[ how_many_Ts ]; + }; + }; + + template<typename T> + intptr_t getCorrectUncontendedValue(int slot_idx) { + intptr_as_array_of<T> slot; + slot.result = 0; + for( int i=0; i<slot.how_many_Ts; ++i ) { + const T my_prime = T(prime[slot_idx*slot.how_many_Ts + i]); + for( int j=0; j<numMaskedOperations; ++j ) + slot.space[i] += my_prime; + } + return slot.result; + } + + template<typename T> + intptr_t getCorrectContendedValue() { + intptr_as_array_of<T> slot; + slot.result = 0; + for( int i=0; i<slot.how_many_Ts; ++i ) + for( int primes=0; primes<testSpaceSize; ++primes ) + for( int j=0; j<numMaskedOperations; ++j ) + slot.space[i] += prime[primes]; + return slot.result; + } +} // namespace masked_cas_helpers +template<typename T> +void TestMaskedCAS() { + using namespace masked_cas_helpers; + REMARK("testing masked CAS<%d>\n",int(sizeof(T))); + + const int num_slots = sizeof(T)*testSpaceSize/sizeof(intptr_t); + intptr_t arr1[num_slots+2]; // two more "canary" slots at boundaries + intptr_t arr2[num_slots+2]; + for(int i=0; i<num_slots+2; ++i) + arr2[i] = arr1[i] = 0; + T* test_space_uncontended = (T*)(arr1+1); + T* test_space_contended = (T*)(arr2+1); + + NativeParallelFor( testSpaceSize, TestMaskedCAS_Body<T>(test_space_uncontended, test_space_contended) ); + + ASSERT( arr1[0]==0 && arr1[num_slots+1]==0 && arr2[0]==0 && arr2[num_slots+1]==0 , "adjacent memory was overwritten" ); + const intptr_t correctContendedValue = getCorrectContendedValue<T>(); + for(int i=0; i<num_slots; ++i) { + ASSERT( arr1[i+1]==getCorrectUncontendedValue<T>(i), "unexpected value in an uncontended slot" ); + ASSERT( arr2[i+1]==correctContendedValue, "unexpected value in a contended slot" ); + } +} +#endif +template <typename T> +class TestRelaxedLoadStorePlainBody { + static T s_turn, + s_ready; + +public: + static unsigned s_count1, + s_count2; + + void operator() ( int id ) const { + using tbb::internal::__TBB_load_relaxed; + using tbb::internal::__TBB_store_relaxed; + + if ( id == 0 ) { + while ( !__TBB_load_relaxed(s_turn) ) { + ++s_count1; + __TBB_store_relaxed(s_ready, 1); + } + } + else { + while ( !__TBB_load_relaxed(s_ready) ) { + ++s_count2; + continue; + } + __TBB_store_relaxed(s_turn, 1); + } + } +}; // class TestRelaxedLoadStorePlainBody<T> + +template <typename T> T TestRelaxedLoadStorePlainBody<T>::s_turn = 0; +template <typename T> T TestRelaxedLoadStorePlainBody<T>::s_ready = 0; +template <typename T> unsigned TestRelaxedLoadStorePlainBody<T>::s_count1 = 0; +template <typename T> unsigned TestRelaxedLoadStorePlainBody<T>::s_count2 = 0; + +template <typename T> +class TestRelaxedLoadStoreAtomicBody { + static tbb::atomic<T> s_turn, + s_ready; + +public: + static unsigned s_count1, + s_count2; + + void operator() ( int id ) const { + if ( id == 0 ) { + while ( s_turn.template load<tbb::relaxed>() == 0 ) { + ++s_count1; + s_ready.template store<tbb::relaxed>(1); + } + } + else { + while ( s_ready.template load<tbb::relaxed>() == 0 ) { + ++s_count2; + continue; + } + s_turn.template store<tbb::relaxed>(1); + } + } +}; // class TestRelaxedLoadStoreAtomicBody<T> + +template <typename T> tbb::atomic<T> TestRelaxedLoadStoreAtomicBody<T>::s_turn; +template <typename T> tbb::atomic<T> TestRelaxedLoadStoreAtomicBody<T>::s_ready; +template <typename T> unsigned TestRelaxedLoadStoreAtomicBody<T>::s_count1 = 0; +template <typename T> unsigned TestRelaxedLoadStoreAtomicBody<T>::s_count2 = 0; + +template <typename T> +void TestRegisterPromotionSuppression () { + REMARK("testing register promotion suppression (size=%d)\n", (int)sizeof(T)); + NativeParallelFor( 2, TestRelaxedLoadStorePlainBody<T>() ); + NativeParallelFor( 2, TestRelaxedLoadStoreAtomicBody<T>() ); +} + +template<unsigned N> +class ArrayElement { + char item[N]; +}; + +#include "harness_barrier.h" +namespace bit_operation_test_suite{ + struct fixture : NoAssign{ + static const uintptr_t zero = 0; + const uintptr_t random_value ; + const uintptr_t inverted_random_value ; + fixture(): + random_value (tbb::internal::size_t_select(0x9E3779B9,0x9E3779B97F4A7C15ULL)), + inverted_random_value ( ~random_value) + {} + }; + + struct TestAtomicORSerially : fixture { + void operator()(){ + //these additional variable are needed to get more meaningful expression in the assert + uintptr_t initial_value = zero; + uintptr_t atomic_or_result = initial_value; + uintptr_t atomic_or_operand = random_value; + + __TBB_AtomicOR(&atomic_or_result,atomic_or_operand); + + ASSERT(atomic_or_result == (initial_value | atomic_or_operand),"AtomicOR should do the OR operation"); + } + }; + struct TestAtomicANDSerially : fixture { + void operator()(){ + //these additional variable are needed to get more meaningful expression in the assert + uintptr_t initial_value = inverted_random_value; + uintptr_t atomic_and_result = initial_value; + uintptr_t atomic_and_operand = random_value; + + __TBB_AtomicAND(&atomic_and_result,atomic_and_operand); + + ASSERT(atomic_and_result == (initial_value & atomic_and_operand),"AtomicAND should do the AND operation"); + } + }; + + struct TestAtomicORandANDConcurrently : fixture { + static const uintptr_t bit_per_word = sizeof(uintptr_t) * 8; + static const uintptr_t threads_number = bit_per_word; + Harness::SpinBarrier m_barrier; + uintptr_t bitmap; + TestAtomicORandANDConcurrently():bitmap(zero) {} + + struct thread_body{ + TestAtomicORandANDConcurrently* test; + thread_body(TestAtomicORandANDConcurrently* the_test) : test(the_test) {} + void operator()(int thread_index)const{ + const uintptr_t single_bit_mask = ((uintptr_t)1u) << (thread_index % bit_per_word); + test->m_barrier.wait(); + static const char* error_msg = "AtomicOR and AtomicAND should be atomic"; + for (uintptr_t attempts=0; attempts<1000; attempts++ ){ + //Set and clear designated bits in a word. + __TBB_AtomicOR(&test->bitmap,single_bit_mask); + __TBB_Yield(); + bool the_bit_is_set_after_set_via_atomic_or = ((__TBB_load_with_acquire(test->bitmap) & single_bit_mask )== single_bit_mask); + ASSERT(the_bit_is_set_after_set_via_atomic_or,error_msg); + + __TBB_AtomicAND(&test->bitmap,~single_bit_mask); + __TBB_Yield(); + bool the_bit_is_clear_after_clear_via_atomic_and = ((__TBB_load_with_acquire(test->bitmap) & single_bit_mask )== zero); + ASSERT(the_bit_is_clear_after_clear_via_atomic_and,error_msg); + } + } + }; + void operator()(){ + m_barrier.initialize(threads_number); + NativeParallelFor(threads_number,thread_body(this)); + } + }; +} +void TestBitOperations(){ + using namespace bit_operation_test_suite; + TestAtomicORSerially()(); + TestAtomicANDSerially()(); + TestAtomicORandANDConcurrently()(); +} + +int TestMain () { + #if __TBB_64BIT_ATOMICS + TestAtomicInteger<unsigned long long>("unsigned long long"); + TestAtomicInteger<long long>("long long"); + #else + REPORT("64-bit atomics not supported\n"); + ASSERT(sizeof(long long)==8, "type long long is not 64 bits"); + #endif + TestAtomicInteger<unsigned long>("unsigned long"); + TestAtomicInteger<long>("long"); + TestAtomicInteger<unsigned int>("unsigned int"); + TestAtomicInteger<int>("int"); + TestAtomicInteger<unsigned short>("unsigned short"); + TestAtomicInteger<short>("short"); + TestAtomicInteger<signed char>("signed char"); + TestAtomicInteger<unsigned char>("unsigned char"); + TestAtomicInteger<char>("char"); + TestAtomicInteger<wchar_t>("wchar_t"); + TestAtomicInteger<size_t>("size_t"); + TestAtomicInteger<ptrdiff_t>("ptrdiff_t"); + TestAtomicPointer<ArrayElement<1> >(); + TestAtomicPointer<ArrayElement<2> >(); + TestAtomicPointer<ArrayElement<3> >(); + TestAtomicPointer<ArrayElement<4> >(); + TestAtomicPointer<ArrayElement<5> >(); + TestAtomicPointer<ArrayElement<6> >(); + TestAtomicPointer<ArrayElement<7> >(); + TestAtomicPointer<ArrayElement<8> >(); + TestAtomicPointerToTypeOfUnknownSize<IncompleteType*>( "IncompleteType*" ); + TestAtomicPointerToTypeOfUnknownSize<void*>( "void*" ); + TestAtomicBool(); + TestAtomicEnum(); + TestAtomicFloat<float>("float"); + #if __TBB_64BIT_ATOMICS + TestAtomicFloat<double>("double"); + #else + ASSERT(sizeof(double)==8, "type double is not 64 bits"); + #endif + ASSERT( !ParallelError, NULL ); + #if __TBB_BIG_ENDIAN!=-1 + TestMaskedCAS<unsigned char>(); + TestMaskedCAS<unsigned short>(); + #else + REPORT("Generic part-word CAS is not available\n"); + #endif +#if __TBB_64BIT_ATOMICS + TestRegisterPromotionSuppression<tbb::internal::int64_t>(); +#endif + TestRegisterPromotionSuppression<tbb::internal::int32_t>(); + TestRegisterPromotionSuppression<tbb::internal::int16_t>(); + TestRegisterPromotionSuppression<tbb::internal::int8_t>(); + TestBitOperations(); + + return Harness::Done; +} + +template<typename T> +struct FlagAndMessage { + //! 0 if message not set yet, 1 if message is set. + tbb::atomic<T> flag; + /** Force flag and message to be on distinct cache lines for machines with cache line size <= 4096 bytes */ + char pad[4096/sizeof(T)]; + //! Non-zero if message is ready + T message; +}; + +// A special template function used for summation. +// Actually it is only necessary because of its specialization for void* +template<typename T> +T special_sum(intptr_t arg1, intptr_t arg2) { + return (T)((T)arg1 + arg2); +} + +// The specialization for IncompleteType* is required +// because pointer arithmetic (+) is impossible with IncompleteType* +template<> +IncompleteType* special_sum<IncompleteType*>(intptr_t arg1, intptr_t arg2) { + return (IncompleteType*)(arg1 + arg2); +} + +// The specialization for void* is required +// because pointer arithmetic (+) is impossible with void* +template<> +void* special_sum<void*>(intptr_t arg1, intptr_t arg2) { + return (void*)(arg1 + arg2); +} + +// The specialization for bool is required to shut up gratuitous compiler warnings, +// because some compilers warn about casting int to bool. +template<> +bool special_sum<bool>(intptr_t arg1, intptr_t arg2) { + return ((arg1!=0) + arg2)!=0; +} + +volatile int One = 1; + +inline bool IsRelaxed ( LoadStoreExpression e ) { + return e == UseExplicitRelaxed || e == UseGlobalHelperRelaxed; +} + +template <typename T, LoadStoreExpression E> +struct LoadStoreTraits; + +template <typename T> +struct LoadStoreTraits<T, UseOperators> { + static void load ( T& dst, const tbb::atomic<T>& src ) { dst = src; } + static void store ( tbb::atomic<T>& dst, const T& src ) { dst = src; } +}; + +template <typename T> +struct LoadStoreTraits<T, UseImplicitAcqRel> { + static void load ( T& dst, const tbb::atomic<T>& src ) { dst = src.load(); } + static void store ( tbb::atomic<T>& dst, const T& src ) { dst.store(src); } +}; + +template <typename T> +struct LoadStoreTraits<T, UseExplicitFullyFenced> { + static void load ( T& dst, const tbb::atomic<T>& src ) { dst = src.template load<tbb::full_fence>(); } + static void store ( tbb::atomic<T>& dst, const T& src ) { dst.template store<tbb::full_fence>(src); } +}; + +template <typename T> +struct LoadStoreTraits<T, UseExplicitAcqRel> { + static void load ( T& dst, const tbb::atomic<T>& src ) { dst = src.template load<tbb::acquire>(); } + static void store ( tbb::atomic<T>& dst, const T& src ) { dst.template store<tbb::release>(src); } +}; + +template <typename T> +struct LoadStoreTraits<T, UseExplicitRelaxed> { + static void load ( T& dst, const tbb::atomic<T>& src ) { dst = src.template load<tbb::relaxed>(); } + static void store ( tbb::atomic<T>& dst, const T& src ) { dst.template store<tbb::relaxed>(src); } +}; + +template <typename T> +struct LoadStoreTraits<T, UseGlobalHelperFullyFenced> { + static void load ( T& dst, const tbb::atomic<T>& src ) { dst = tbb::load<tbb::full_fence>(src); } + static void store ( tbb::atomic<T>& dst, const T& src ) { tbb::store<tbb::full_fence>(dst, src); } +}; + +template <typename T> +struct LoadStoreTraits<T, UseGlobalHelperAcqRel> { + static void load ( T& dst, const tbb::atomic<T>& src ) { dst = tbb::load<tbb::acquire>(src); } + static void store ( tbb::atomic<T>& dst, const T& src ) { tbb::store<tbb::release>(dst, src); } +}; + +template <typename T> +struct LoadStoreTraits<T, UseGlobalHelperRelaxed> { + static void load ( T& dst, const tbb::atomic<T>& src ) { dst = tbb::load<tbb::relaxed>(src); } + static void store ( tbb::atomic<T>& dst, const T& src ) { tbb::store<tbb::relaxed>(dst, src); } +}; + +template<typename T, LoadStoreExpression E> +class HammerLoadAndStoreFence: NoAssign { + typedef LoadStoreTraits<T, E> trait; + FlagAndMessage<T>* fam; + const int n; + const int p; + const int trial; + const char* name; + mutable T accum; +public: + HammerLoadAndStoreFence( FlagAndMessage<T>* fam_, int n_, int p_, const char* name_, int trial_ ) : fam(fam_), n(n_), p(p_), trial(trial_), name(name_) {} + void operator()( int k ) const { + int one = One; + FlagAndMessage<T>* s = fam+k; + FlagAndMessage<T>* s_next = fam + (k+1)%p; + for( int i=0; i<n; ++i ) { + // The inner for loop is a spin-wait loop, which is normally considered very bad style. + // But we must use it here because we are interested in examining subtle hardware effects. + for(unsigned short cnt=1; ; ++cnt) { + if( !(cnt%1024) ) // to help 1-core or oversubscribed systems complete the test, yield every 2^10 iterations + __TBB_Yield(); + // Compilers typically generate non-trivial sequence for division by a constant. + // The expression here is dependent on the loop index i, so it cannot be hoisted. + #define COMPLICATED_ZERO (i*(one-1)/100) + // Read flag and then the message + T flag, message; + if( trial&1 ) { + // COMPLICATED_ZERO here tempts compiler to hoist load of message above reading of flag. + trait::load( flag, (s+COMPLICATED_ZERO)->flag ); + message = s->message; + } else { + trait::load( flag, s->flag ); + message = s->message; + } + if( flag ) { + if( flag!=(T)-1 ) { + REPORT("ERROR: flag!=(T)-1 k=%d i=%d trial=%x type=%s (atomicity problem?)\n", k, i, trial, name ); + ParallelError = true; + } + if( !IsRelaxed(E) && message!=(T)-1 ) { + REPORT("ERROR: message!=(T)-1 k=%d i=%d trial=%x type=%s mode=%d (memory fence problem?)\n", k, i, trial, name, E ); + ParallelError = true; + } + s->message = T(0); + trait::store( s->flag, T(0) ); + // Prevent deadlock possible in relaxed mode because of store(0) + // to the first thread's flag being reordered after the last + // thread's store(-1) into it. + if ( IsRelaxed(E) ) { + while( s_next->flag.template load<tbb::relaxed>() != 0 ) + __TBB_Yield(); + } + else + ASSERT( s_next->flag == 0, NULL ); + // Set message and then the flag + if( trial&2 ) { + // COMPLICATED_ZERO here tempts compiler to sink store below setting of flag + s_next->message = special_sum<T>(-1, COMPLICATED_ZERO); + trait::store( s_next->flag, (T)-1 ); + } else { + s_next->message = (T)-1; + trait::store( s_next->flag, (T)-1 ); + } + break; + } else { + // Force compiler to use message anyway, so it cannot sink read of s->message below the if. + accum = message; + } + } + } + } +}; + +//! Test that atomic<T> has acquire semantics for loads and release semantics for stores. +/** Test performs round-robin passing of message among p processors, + where p goes from MinThread to MaxThread. */ +template<typename T, LoadStoreExpression E> +void TestLoadAndStoreFences( const char* name ) { + for( int p=MinThread<2 ? 2 : MinThread; p<=MaxThread; ++p ) { + FlagAndMessage<T>* fam = new FlagAndMessage<T>[p]; + // Each of four trials exercise slightly different expression pattern within the test. + // See occurrences of COMPLICATED_ZERO for details. + for( int trial=0; trial<4; ++trial ) { + memset( fam, 0, p*sizeof(FlagAndMessage<T>) ); + fam->message = (T)-1; + fam->flag = (T)-1; + NativeParallelFor( p, HammerLoadAndStoreFence<T, E>( fam, 100, p, name, trial ) ); + if ( !IsRelaxed(E) ) { + for( int k=0; k<p; ++k ) { + ASSERT( fam[k].message==(k==0 ? (T)-1 : 0), "incomplete round-robin?" ); + ASSERT( fam[k].flag==(k==0 ? (T)-1 : 0), "incomplete round-robin?" ); + } + } + } + delete[] fam; + } +} + +//! Sparse set of values of integral type T. +/** Set is designed so that if a value is read or written non-atomically, + the resulting intermediate value is likely to not be a member of the set. */ +template<typename T> +class SparseValueSet { + T factor; +public: + SparseValueSet() { + // Compute factor such that: + // 1. It has at least one 1 in most of its bytes. + // 2. The bytes are typically different. + // 3. When multiplied by any value <=127, the product does not overflow. + factor = T(0); + for( unsigned i=0; i<sizeof(T)*8-7; i+=7 ) + factor = T(factor | T(1)<<i); + } + //! Get ith member of set + T get( int i ) const { + // Create multiple of factor. The & prevents overflow of the product. + return T((i&0x7F)*factor); + } + //! True if set contains x + bool contains( T x ) const { + // True if + return (x%factor)==0; + } +}; + +//! Specialization for pointer types. The pointers are random and should not be dereferenced. +template<typename T> +class SparseValueSet<T*> { + SparseValueSet<ptrdiff_t> my_set; +public: + T* get( int i ) const {return reinterpret_cast<T*>(my_set.get(i));} + bool contains( T* x ) const {return my_set.contains(reinterpret_cast<ptrdiff_t>(x));} +}; + +//! Specialization for bool. +/** Checking bool for atomic read/write is pointless in practice, because + there is no way to *not* atomically read or write a bool value. */ +template<> +class SparseValueSet<bool> { +public: + bool get( int i ) const {return i&1;} + bool contains( bool ) const {return true;} +}; + +#if _MSC_VER==1500 && !defined(__INTEL_COMPILER) + // VS2008/VC9 seems to have an issue; limits pull in math.h + #pragma warning( push ) + #pragma warning( disable: 4985 ) +#endif +#include <limits> /* Need std::numeric_limits */ +#if _MSC_VER==1500 && !defined(__INTEL_COMPILER) + #pragma warning( pop ) +#endif + +//! Commonality inherited by specializations for floating-point types. +template<typename T> +class SparseFloatSet: NoAssign { + const T epsilon; +public: + SparseFloatSet() : epsilon(std::numeric_limits<T>::epsilon()) {} + T get( int i ) const { + return i==0 ? T(0) : 1/T((i&0x7F)+1); + } + bool contains( T x ) const { + if( x==T(0) ) { + return true; + } else { + int j = int(1/x+T(0.5)); + if( 0<j && j<=128 ) { + T error = x*T(j)-T(1); + // In the calculation above, if x was indeed generated by method get, the error should be + // at most epsilon, because x is off by at most 1/2 ulp from its infinitely precise value, + // j is exact, and the multiplication incurs at most another 1/2 ulp of round-off error. + if( -epsilon<=error && error<=epsilon ) { + return true; + } else { + REPORT("Warning: excessive floating-point error encountered j=%d x=%.15g error=%.15g\n",j,x,error); + } + } + return false; + } + }; +}; + +template<> +class SparseValueSet<float>: public SparseFloatSet<float> {}; + +template<> +class SparseValueSet<double>: public SparseFloatSet<double> {}; + +template<typename T> +class HammerAssignment: NoAssign { + tbb::atomic<T>& x; + const char* name; + SparseValueSet<T> set; +public: + HammerAssignment( tbb::atomic<T>& x_, const char* name_ ) : x(x_), name(name_) {} + void operator()( int k ) const { + const int n = 1000000; + if( k ) { + tbb::atomic<T> z; + AssertSameType( z=x, z ); // Check that return type from assignment is correct + for( int i=0; i<n; ++i ) { + // Read x atomically into z. + z = x; + if( !set.contains(z) ) { + REPORT("ERROR: assignment of atomic<%s> is not atomic\n", name); + ParallelError = true; + return; + } + } + } else { + tbb::atomic<T> y; + for( int i=0; i<n; ++i ) { + // Get pseudo-random value. + y = set.get(i); + // Write y atomically into x. + x = y; + } + } + } +}; + +// Compile-time check that a class method has the required signature. +// Intended to check the assignment operator of tbb::atomic. +template<typename T> void TestAssignmentSignature( T& (T::*)(const T&) ) {} + +#if _MSC_VER && !defined(__INTEL_COMPILER) + #pragma warning( disable: 4355 4800 ) +#endif + +template<typename T> +void TestAssignment( const char* name ) { + TestAssignmentSignature( &tbb::atomic<T>::operator= ); + tbb::atomic<T> x; + x = T(0); + NativeParallelFor( 2, HammerAssignment<T>( x, name ) ); +#if __TBB_x86_32 && (__linux__ || __FreeBSD__ || _WIN32) + if( sizeof(T)==8 ) { + // Some compilers for IA-32 fail to provide 8-byte alignment of objects on the stack, + // even if the object specifies 8-byte alignment. On such platforms, the IA-32 implementation + // of atomic<long long> and atomic<unsigned long long> use different tactics depending upon + // whether the object is properly aligned or not. The following abusive test ensures that we + // cover both the proper and improper alignment cases, one with the x above and the other with + // the y below, perhaps not respectively. + + // Allocate space big enough to always contain 8-byte locations that are aligned and misaligned. + char raw_space[15]; + // Set delta to 0 if x is aligned, 4 otherwise. + uintptr_t delta = ((reinterpret_cast<uintptr_t>(&x)&7) ? 0 : 4); + // y crosses 8-byte boundary if and only if x does not cross. + tbb::atomic<T>& y = *reinterpret_cast<tbb::atomic<T>*>((reinterpret_cast<uintptr_t>(&raw_space[7+delta])&~7u) - delta); + // Assertion checks that y really did end up somewhere inside "raw_space". + ASSERT( raw_space<=reinterpret_cast<char*>(&y), "y starts before raw_space" ); + ASSERT( reinterpret_cast<char*>(&y+1) <= raw_space+sizeof(raw_space), "y starts after raw_space" ); + y = T(0); + NativeParallelFor( 2, HammerAssignment<T>( y, name ) ); + } +#endif /* __TBB_x86_32 && (__linux__ || __FreeBSD__ || _WIN32) */ +} + +static const unsigned Primes[] = { + 0x9e3779b1, 0xffe6cc59, 0x2109f6dd, 0x43977ab5, 0xba5703f5, 0xb495a877, 0xe1626741, 0x79695e6b, + 0xbc98c09f, 0xd5bee2b3, 0x287488f9, 0x3af18231, 0x9677cd4d, 0xbe3a6929, 0xadc6a877, 0xdcf0674b, + 0xbe4d6fe9, 0x5f15e201, 0x99afc3fd, 0xf3f16801, 0xe222cfff, 0x24ba5fdb, 0x0620452d, 0x79f149e3, + 0xc8b93f49, 0x972702cd, 0xb07dd827, 0x6c97d5ed, 0x085a3d61, 0x46eb5ea7, 0x3d9910ed, 0x2e687b5b, + 0x29609227, 0x6eb081f1, 0x0954c4e1, 0x9d114db9, 0x542acfa9, 0xb3e6bd7b, 0x0742d917, 0xe9f3ffa7, + 0x54581edb, 0xf2480f45, 0x0bb9288f, 0xef1affc7, 0x85fa0ca7, 0x3ccc14db, 0xe6baf34b, 0x343377f7, + 0x5ca19031, 0xe6d9293b, 0xf0a9f391, 0x5d2e980b, 0xfc411073, 0xc3749363, 0xb892d829, 0x3549366b, + 0x629750ad, 0xb98294e5, 0x892d9483, 0xc235baf3, 0x3d2402a3, 0x6bdef3c9, 0xbec333cd, 0x40c9520f +}; + +class FastRandom { + unsigned x, a; +public: + unsigned short get() { + unsigned short r = (unsigned short)(x>>16); + x = x*a+1; + return r; + } + FastRandom( unsigned seed ) { + x = seed; + a = Primes[seed % (sizeof(Primes)/sizeof(Primes[0]))]; + } +}; + +template <typename T, LoadStoreExpression E> +class ArbitrationBody : NoAssign, Harness::NoAfterlife { + typedef LoadStoreTraits<T, E> trait; + + mutable FastRandom my_rand; + static const unsigned short c_rand_ceil = 10; + + static tbb::atomic<T> s_ready[2]; + static tbb::atomic<T> s_turn; + static volatile bool s_inside; + +public: + void operator() ( int id ) const { + const int me = id; + const T other = (T)(uintptr_t)(1 - id), + cleared = T(0), + signaled = T(1); + for ( int i = 0; i < 100000; ++i ) { + trait::store( s_ready[me], signaled ); + trait::store( s_turn, other ); + T r, t; + for ( int j = 0; ; ++j ) { + trait::load(r, s_ready[(uintptr_t)other]); + trait::load(t, s_turn); + if ( r != signaled || t != other ) + break; + __TBB_Pause(1); + if ( j == 2<<12 ) { + j = 0; + __TBB_Yield(); + } + } + // Entered critical section + ASSERT( !s_inside, "Peterson lock is broken - some fences are missing" ); + s_inside = true; + unsigned short spin = my_rand.get() % c_rand_ceil; + for ( volatile int j = 0; j < spin; ++j ) + continue; + s_inside = false; + ASSERT( !s_inside, "Peterson lock is broken - some fences are missing" ); + // leaving critical section + trait::store( s_ready[me], cleared ); + spin = my_rand.get() % c_rand_ceil; + for ( volatile int j = 0; j < spin; ++j ) + continue; + } + } + + ArbitrationBody () : my_rand((unsigned)(uintptr_t)this) {} +}; + +template<typename T, LoadStoreExpression E> tbb::atomic<T> ArbitrationBody<T, E>::s_ready[2]; +template<typename T, LoadStoreExpression E> tbb::atomic<T> ArbitrationBody<T, E>::s_turn; +template<typename T, LoadStoreExpression E> volatile bool ArbitrationBody<T, E>::s_inside = false; + +template <typename T, LoadStoreExpression E> +void TestDekkerArbitration () { + NativeParallelFor( 2, ArbitrationBody<T, E>() ); +} + +template<typename T> +void TestParallel( const char* name ) { + TestLoadAndStoreFences<T, UseOperators>(name); + TestLoadAndStoreFences<T, UseImplicitAcqRel>(name); + TestLoadAndStoreFences<T, UseExplicitFullyFenced>(name); + TestLoadAndStoreFences<T, UseExplicitAcqRel>(name); + TestLoadAndStoreFences<T, UseExplicitRelaxed>(name); + TestLoadAndStoreFences<T, UseGlobalHelperFullyFenced>(name); + TestLoadAndStoreFences<T, UseGlobalHelperAcqRel>(name); + TestLoadAndStoreFences<T, UseGlobalHelperRelaxed>(name); + TestAssignment<T>(name); + TestDekkerArbitration<T, UseExplicitFullyFenced>(); + TestDekkerArbitration<T, UseGlobalHelperFullyFenced>(); +} + +#endif // __TBB_TEST_SKIP_PIC_MODE || __TBB_TEST_SKIP_BUILTINS_MODE diff --git a/src/tbb/src/test/test_blocked_range.cpp b/src/tbb/src/test/test_blocked_range.cpp new file mode 100644 index 0000000..cf53d78 --- /dev/null +++ b/src/tbb/src/test/test_blocked_range.cpp @@ -0,0 +1,128 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/blocked_range.h" +#include "harness_assert.h" + +// First test as much as we can without including other headers. +// Doing so should catch problems arising from failing to include headers. + +class AbstractValueType { + AbstractValueType() {} + int value; +public: + friend AbstractValueType MakeAbstractValueType( int i ); + friend int GetValueOf( const AbstractValueType& v ) {return v.value;} +}; + +AbstractValueType MakeAbstractValueType( int i ) { + AbstractValueType x; + x.value = i; + return x; +} + +std::size_t operator-( const AbstractValueType& u, const AbstractValueType& v ) { + return GetValueOf(u)-GetValueOf(v); +} + +bool operator<( const AbstractValueType& u, const AbstractValueType& v ) { + return GetValueOf(u)<GetValueOf(v); +} + +AbstractValueType operator+( const AbstractValueType& u, std::size_t offset ) { + return MakeAbstractValueType(GetValueOf(u)+int(offset)); +} + +static void SerialTest() { + for( int x=-10; x<10; ++x ) + for( int y=-10; y<10; ++y ) { + AbstractValueType i = MakeAbstractValueType(x); + AbstractValueType j = MakeAbstractValueType(y); + for( std::size_t k=1; k<10; ++k ) { + typedef tbb::blocked_range<AbstractValueType> range_type; + range_type r( i, j, k ); + AssertSameType( r.empty(), true ); + AssertSameType( range_type::size_type(), std::size_t() ); + AssertSameType( static_cast<range_type::const_iterator*>(0), static_cast<AbstractValueType*>(0) ); + AssertSameType( r.begin(), MakeAbstractValueType(0) ); + AssertSameType( r.end(), MakeAbstractValueType(0) ); + ASSERT( r.empty()==(y<=x), NULL ); + ASSERT( r.grainsize()==k, NULL ); + if( x<=y ) { + AssertSameType( r.is_divisible(), true ); + ASSERT( r.is_divisible()==(std::size_t(y-x)>k), NULL ); + ASSERT( r.size()==std::size_t(y-x), NULL ); + if( r.is_divisible() ) { + tbb::blocked_range<AbstractValueType> r2(r,tbb::split()); + ASSERT( GetValueOf(r.begin())==x, NULL ); + ASSERT( GetValueOf(r.end())==GetValueOf(r2.begin()), NULL ); + ASSERT( GetValueOf(r2.end())==y, NULL ); + ASSERT( r.grainsize()==k, NULL ); + ASSERT( r2.grainsize()==k, NULL ); + } + } + } + } +} + +#include "tbb/parallel_for.h" +#include "harness.h" + +const int N = 1<<22; + +unsigned char Array[N]; + +struct Striker { + // Note: we use <int> here instead of <long> in order to test for Quad 407676 + void operator()( const tbb::blocked_range<int>& r ) const { + for( tbb::blocked_range<int>::const_iterator i=r.begin(); i!=r.end(); ++i ) + ++Array[i]; + } +}; + +void ParallelTest() { + for( int i=0; i<N; i=i<3 ? i+1 : i*3 ) { + const tbb::blocked_range<int> r( 0, i, 10 ); + tbb::parallel_for( r, Striker() ); + for( int k=0; k<N; ++k ) { + ASSERT( Array[k]==(k<i), NULL ); + Array[k] = 0; + } + } +} + +#include "tbb/task_scheduler_init.h" + +int TestMain () { + SerialTest(); + for( int p=MinThread; p<=MaxThread; ++p ) { + tbb::task_scheduler_init init(p); + ParallelTest(); + } + return Harness::Done; +} diff --git a/src/tbb/src/test/test_blocked_range2d.cpp b/src/tbb/src/test/test_blocked_range2d.cpp new file mode 100644 index 0000000..175985f --- /dev/null +++ b/src/tbb/src/test/test_blocked_range2d.cpp @@ -0,0 +1,156 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/blocked_range2d.h" +#include "harness_assert.h" + +// First test as much as we can without including other headers. +// Doing so should catch problems arising from failing to include headers. + +template<typename Tag> +class AbstractValueType { + AbstractValueType() {} + int value; +public: + template<typename OtherTag> + friend AbstractValueType<OtherTag> MakeAbstractValueType( int i ); + + template<typename OtherTag> + friend int GetValueOf( const AbstractValueType<OtherTag>& v ) ; +}; + +template<typename Tag> +AbstractValueType<Tag> MakeAbstractValueType( int i ) { + AbstractValueType<Tag> x; + x.value = i; + return x; +} + +template<typename Tag> +int GetValueOf( const AbstractValueType<Tag>& v ) {return v.value;} + +template<typename Tag> +bool operator<( const AbstractValueType<Tag>& u, const AbstractValueType<Tag>& v ) { + return GetValueOf(u)<GetValueOf(v); +} + +template<typename Tag> +std::size_t operator-( const AbstractValueType<Tag>& u, const AbstractValueType<Tag>& v ) { + return GetValueOf(u)-GetValueOf(v); +} + +template<typename Tag> +AbstractValueType<Tag> operator+( const AbstractValueType<Tag>& u, std::size_t offset ) { + return MakeAbstractValueType<Tag>(GetValueOf(u)+int(offset)); +} + +struct RowTag {}; +struct ColTag {}; + +static void SerialTest() { + typedef AbstractValueType<RowTag> row_type; + typedef AbstractValueType<ColTag> col_type; + typedef tbb::blocked_range2d<row_type,col_type> range_type; + for( int rowx=-10; rowx<10; ++rowx ) { + for( int rowy=rowx; rowy<10; ++rowy ) { + row_type rowi = MakeAbstractValueType<RowTag>(rowx); + row_type rowj = MakeAbstractValueType<RowTag>(rowy); + for( int rowg=1; rowg<10; ++rowg ) { + for( int colx=-10; colx<10; ++colx ) { + for( int coly=colx; coly<10; ++coly ) { + col_type coli = MakeAbstractValueType<ColTag>(colx); + col_type colj = MakeAbstractValueType<ColTag>(coly); + for( int colg=1; colg<10; ++colg ) { + range_type r( rowi, rowj, rowg, coli, colj, colg ); + AssertSameType( r.is_divisible(), true ); + AssertSameType( r.empty(), true ); + AssertSameType( static_cast<range_type::row_range_type::const_iterator*>(0), static_cast<row_type*>(0) ); + AssertSameType( static_cast<range_type::col_range_type::const_iterator*>(0), static_cast<col_type*>(0) ); + AssertSameType( r.rows(), tbb::blocked_range<row_type>( rowi, rowj, 1 )); + AssertSameType( r.cols(), tbb::blocked_range<col_type>( coli, colj, 1 )); + ASSERT( r.empty()==(rowx==rowy||colx==coly), NULL ); + ASSERT( r.is_divisible()==(rowy-rowx>rowg||coly-colx>colg), NULL ); + if( r.is_divisible() ) { + range_type r2(r,tbb::split()); + if( GetValueOf(r2.rows().begin())==GetValueOf(r.rows().begin()) ) { + ASSERT( GetValueOf(r2.rows().end())==GetValueOf(r.rows().end()), NULL ); + ASSERT( GetValueOf(r2.cols().begin())==GetValueOf(r.cols().end()), NULL ); + } else { + ASSERT( GetValueOf(r2.cols().end())==GetValueOf(r.cols().end()), NULL ); + ASSERT( GetValueOf(r2.rows().begin())==GetValueOf(r.rows().end()), NULL ); + } + } + } + } + } + } + } + } +} + +#include "tbb/parallel_for.h" +#include "harness.h" + +const int N = 1<<10; + +unsigned char Array[N][N]; + +struct Striker { + // Note: we use <int> here instead of <long> in order to test for problems similar to Quad 407676 + void operator()( const tbb::blocked_range2d<int>& r ) const { + for( tbb::blocked_range<int>::const_iterator i=r.rows().begin(); i!=r.rows().end(); ++i ) + for( tbb::blocked_range<int>::const_iterator j=r.cols().begin(); j!=r.cols().end(); ++j ) + ++Array[i][j]; + } +}; + +void ParallelTest() { + for( int i=0; i<N; i=i<3 ? i+1 : i*3 ) { + for( int j=0; j<N; j=j<3 ? j+1 : j*3 ) { + const tbb::blocked_range2d<int> r( 0, i, 7, 0, j, 5 ); + tbb::parallel_for( r, Striker() ); + for( int k=0; k<N; ++k ) { + for( int l=0; l<N; ++l ) { + ASSERT( Array[k][l]==(k<i && l<j), NULL ); + Array[k][l] = 0; + } + } + } + } +} + +#include "tbb/task_scheduler_init.h" + +int TestMain () { + SerialTest(); + for( int p=MinThread; p<=MaxThread; ++p ) { + tbb::task_scheduler_init init(p); + ParallelTest(); + } + return Harness::Done; +} diff --git a/src/tbb/src/test/test_blocked_range3d.cpp b/src/tbb/src/test/test_blocked_range3d.cpp new file mode 100644 index 0000000..27b5833 --- /dev/null +++ b/src/tbb/src/test/test_blocked_range3d.cpp @@ -0,0 +1,187 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/blocked_range3d.h" +#include "harness_assert.h" + +// First test as much as we can without including other headers. +// Doing so should catch problems arising from failing to include headers. + +template<typename Tag> +class AbstractValueType { + AbstractValueType() {} + int value; +public: + template<typename OtherTag> + friend AbstractValueType<OtherTag> MakeAbstractValueType( int i ); + + template<typename OtherTag> + friend int GetValueOf( const AbstractValueType<OtherTag>& v ) ; +}; + +template<typename Tag> +AbstractValueType<Tag> MakeAbstractValueType( int i ) { + AbstractValueType<Tag> x; + x.value = i; + return x; +} + +template<typename Tag> +int GetValueOf( const AbstractValueType<Tag>& v ) {return v.value;} + +template<typename Tag> +bool operator<( const AbstractValueType<Tag>& u, const AbstractValueType<Tag>& v ) { + return GetValueOf(u)<GetValueOf(v); +} + +template<typename Tag> +std::size_t operator-( const AbstractValueType<Tag>& u, const AbstractValueType<Tag>& v ) { + return GetValueOf(u)-GetValueOf(v); +} + +template<typename Tag> +AbstractValueType<Tag> operator+( const AbstractValueType<Tag>& u, std::size_t offset ) { + return MakeAbstractValueType<Tag>(GetValueOf(u)+int(offset)); +} + +struct PageTag {}; +struct RowTag {}; +struct ColTag {}; + +static void SerialTest() { + typedef AbstractValueType<PageTag> page_type; + typedef AbstractValueType<RowTag> row_type; + typedef AbstractValueType<ColTag> col_type; + typedef tbb::blocked_range3d<page_type,row_type,col_type> range_type; + for( int pagex=-4; pagex<4; ++pagex ) { + for( int pagey=pagex; pagey<4; ++pagey ) { + page_type pagei = MakeAbstractValueType<PageTag>(pagex); + page_type pagej = MakeAbstractValueType<PageTag>(pagey); + for( int pageg=1; pageg<4; ++pageg ) { + for( int rowx=-4; rowx<4; ++rowx ) { + for( int rowy=rowx; rowy<4; ++rowy ) { + row_type rowi = MakeAbstractValueType<RowTag>(rowx); + row_type rowj = MakeAbstractValueType<RowTag>(rowy); + for( int rowg=1; rowg<4; ++rowg ) { + for( int colx=-4; colx<4; ++colx ) { + for( int coly=colx; coly<4; ++coly ) { + col_type coli = MakeAbstractValueType<ColTag>(colx); + col_type colj = MakeAbstractValueType<ColTag>(coly); + for( int colg=1; colg<4; ++colg ) { + range_type r( pagei, pagej, pageg, rowi, rowj, rowg, coli, colj, colg ); + AssertSameType( r.is_divisible(), true ); + + AssertSameType( r.empty(), true ); + + AssertSameType( static_cast<range_type::page_range_type::const_iterator*>(0), static_cast<page_type*>(0) ); + AssertSameType( static_cast<range_type::row_range_type::const_iterator*>(0), static_cast<row_type*>(0) ); + AssertSameType( static_cast<range_type::col_range_type::const_iterator*>(0), static_cast<col_type*>(0) ); + + AssertSameType( r.pages(), tbb::blocked_range<page_type>( pagei, pagej, 1 )); + AssertSameType( r.rows(), tbb::blocked_range<row_type>( rowi, rowj, 1 )); + AssertSameType( r.cols(), tbb::blocked_range<col_type>( coli, colj, 1 )); + + ASSERT( r.empty()==(pagex==pagey||rowx==rowy||colx==coly), NULL ); + + ASSERT( r.is_divisible()==(pagey-pagex>pageg||rowy-rowx>rowg||coly-colx>colg), NULL ); + + if( r.is_divisible() ) { + range_type r2(r,tbb::split()); + if( (GetValueOf(r2.pages().begin())==GetValueOf(r.pages().begin())) && (GetValueOf(r2.rows().begin())==GetValueOf(r.rows().begin())) ) { + ASSERT( GetValueOf(r2.pages().end())==GetValueOf(r.pages().end()), NULL ); + ASSERT( GetValueOf(r2.rows().end())==GetValueOf(r.rows().end()), NULL ); + ASSERT( GetValueOf(r2.cols().begin())==GetValueOf(r.cols().end()), NULL ); + } else { + if ( (GetValueOf(r2.pages().begin())==GetValueOf(r.pages().begin())) && (GetValueOf(r2.cols().begin())==GetValueOf(r.cols().begin())) ) { + ASSERT( GetValueOf(r2.pages().end())==GetValueOf(r.pages().end()), NULL ); + ASSERT( GetValueOf(r2.cols().end())==GetValueOf(r.cols().end()), NULL ); + ASSERT( GetValueOf(r2.rows().begin())==GetValueOf(r.rows().end()), NULL ); + } else { + ASSERT( GetValueOf(r2.rows().end())==GetValueOf(r.rows().end()), NULL ); + ASSERT( GetValueOf(r2.cols().end())==GetValueOf(r.cols().end()), NULL ); + ASSERT( GetValueOf(r2.pages().begin())==GetValueOf(r.pages().end()), NULL ); + } + } + } + } + } + } + } + } + } + } + } + } +} + +#include "tbb/parallel_for.h" +#include "harness.h" + +const int N = 1<<5; + +unsigned char Array[N][N][N]; + +struct Striker { + // Note: we use <int> here instead of <long> in order to test for problems similar to Quad 407676 + void operator()( const tbb::blocked_range3d<int>& r ) const { + for( tbb::blocked_range<int>::const_iterator i=r.pages().begin(); i!=r.pages().end(); ++i ) + for( tbb::blocked_range<int>::const_iterator j=r.rows().begin(); j!=r.rows().end(); ++j ) + for( tbb::blocked_range<int>::const_iterator k=r.cols().begin(); k!=r.cols().end(); ++k ) + ++Array[i][j][k]; + } +}; + +void ParallelTest() { + for( int i=0; i<N; i=i<3 ? i+1 : i*3 ) { + for( int j=0; j<N; j=j<3 ? j+1 : j*3 ) { + for( int k=0; k<N; k=k<3 ? k+1 : k*3 ) { + const tbb::blocked_range3d<int> r( 0, i, 5, 0, j, 3, 0, k, 1 ); + tbb::parallel_for( r, Striker() ); + for( int l=0; l<N; ++l ) { + for( int m=0; m<N; ++m ) { + for( int n=0; n<N; ++n ) { + ASSERT( Array[l][m][n]==(l<i && m<j && n<k), NULL ); + Array[l][m][n] = 0; + } + } + } + } + } + } +} + +#include "tbb/task_scheduler_init.h" + +int TestMain () { + SerialTest(); + for( int p=MinThread; p<=MaxThread; ++p ) { + tbb::task_scheduler_init init(p); + ParallelTest(); + } + return Harness::Done; +} diff --git a/src/tbb/src/test/test_broadcast_node.cpp b/src/tbb/src/test/test_broadcast_node.cpp new file mode 100644 index 0000000..39f4b43 --- /dev/null +++ b/src/tbb/src/test/test_broadcast_node.cpp @@ -0,0 +1,177 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "harness.h" +#include "tbb/flow_graph.h" + +#include "tbb/atomic.h" + +const int N = 1000; +const int R = 4; + +class int_convertable_type : private NoAssign { + + int my_value; + +public: + + int_convertable_type( int v ) : my_value(v) {} + operator int() const { return my_value; } + +}; + + +template< typename T > +class counting_array_receiver : public tbb::flow::receiver<T> { + + tbb::atomic<size_t> my_counters[N]; + +public: + + counting_array_receiver() { + for (int i = 0; i < N; ++i ) + my_counters[i] = 0; + } + + size_t operator[]( int i ) { + size_t v = my_counters[i]; + return v; + } + + /* override */ bool try_put( const T &v ) { + ++my_counters[(int)v]; + return true; + } + +}; + +template< typename T > +void test_serial_broadcasts() { + + tbb::flow::graph g; + tbb::flow::broadcast_node<T> b(g); + + for ( int num_receivers = 1; num_receivers < R; ++num_receivers ) { + counting_array_receiver<T> *receivers = new counting_array_receiver<T>[num_receivers]; + + for ( int r = 0; r < num_receivers; ++r ) { + tbb::flow::make_edge( b, receivers[r] ); + } + + for (int n = 0; n < N; ++n ) { + ASSERT( b.try_put( (T)n ), NULL ); + } + + for ( int r = 0; r < num_receivers; ++r ) { + for (int n = 0; n < N; ++n ) { + ASSERT( receivers[r][n] == 1, NULL ); + } + tbb::flow::remove_edge( b, receivers[r] ); + } + ASSERT( b.try_put( (T)0 ), NULL ); + for ( int r = 0; r < num_receivers; ++r ) + ASSERT( receivers[0][0] == 1, NULL ) ; + + delete [] receivers; + + } + +} + +template< typename T > +class native_body : private NoAssign { + + tbb::flow::broadcast_node<T> &my_b; + +public: + + native_body( tbb::flow::broadcast_node<T> &b ) : my_b(b) {} + + void operator()(int) const { + for (int n = 0; n < N; ++n ) { + ASSERT( my_b.try_put( (T)n ), NULL ); + } + } + +}; + +template< typename T > +void run_parallel_broadcasts(int p, tbb::flow::broadcast_node<T>& b) { + for ( int num_receivers = 1; num_receivers < R; ++num_receivers ) { + counting_array_receiver<T> *receivers = new counting_array_receiver<T>[num_receivers]; + + for ( int r = 0; r < num_receivers; ++r ) { + tbb::flow::make_edge( b, receivers[r] ); + } + + NativeParallelFor( p, native_body<T>( b ) ); + + for ( int r = 0; r < num_receivers; ++r ) { + for (int n = 0; n < N; ++n ) { + ASSERT( (int)receivers[r][n] == p, NULL ); + } + tbb::flow::remove_edge( b, receivers[r] ); + } + ASSERT( b.try_put( (T)0 ), NULL ); + for ( int r = 0; r < num_receivers; ++r ) + ASSERT( (int)receivers[r][0] == p, NULL ) ; + + delete [] receivers; + + } +} + +template< typename T > +void test_parallel_broadcasts(int p) { + + tbb::flow::graph g; + tbb::flow::broadcast_node<T> b(g); + run_parallel_broadcasts(p, b); + + // test copy constructor + tbb::flow::broadcast_node<T> b_copy(b); + run_parallel_broadcasts(p, b_copy); +} + +int TestMain() { + if( MinThread<1 ) { + REPORT("number of threads must be positive\n"); + exit(1); + } + + test_serial_broadcasts<int>(); + test_serial_broadcasts<float>(); + test_serial_broadcasts<int_convertable_type>(); + + for( int p=MinThread; p<=MaxThread; ++p ) { + test_parallel_broadcasts<int>(p); + test_parallel_broadcasts<float>(p); + test_parallel_broadcasts<int_convertable_type>(p); + } + return Harness::Done; +} diff --git a/src/tbb/src/test/test_buffer_node.cpp b/src/tbb/src/test/test_buffer_node.cpp new file mode 100644 index 0000000..6165078 --- /dev/null +++ b/src/tbb/src/test/test_buffer_node.cpp @@ -0,0 +1,432 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "harness.h" +#include "tbb/flow_graph.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/tick_count.h" + +#include <cstdio> + +#define N 1000 +#define C 10 + +template< typename T > +void spin_try_get( tbb::flow::buffer_node<T> &b, T &value ) { + while ( b.try_get(value) != true ) {} +} + +template< typename T > +void check_item( T* count_value, T &value ) { + count_value[value / N] += value % N; +} + +template< typename T > +struct parallel_puts : NoAssign { + + tbb::flow::buffer_node<T> &my_b; + + parallel_puts( tbb::flow::buffer_node<T> &b ) : my_b(b) {} + + void operator()(int i) const { + for (int j = 0; j < N; ++j) { + bool msg = my_b.try_put( T(N*i + j) ); + ASSERT( msg == true, NULL ); + } + } +}; + +template< typename T > +struct touches { + + bool **my_touches; + int my_num_threads; + + touches( int num_threads ) : my_num_threads(num_threads) { + my_touches = new bool* [my_num_threads]; + for ( int p = 0; p < my_num_threads; ++p) { + my_touches[p] = new bool[N]; + for ( int n = 0; n < N; ++n) + my_touches[p][n] = false; + } + } + + ~touches() { + for ( int p = 0; p < my_num_threads; ++p) { + delete [] my_touches[p]; + } + delete [] my_touches; + } + + bool check( T v ) { + ASSERT ( my_touches[v/N][v%N] == false, NULL); + my_touches[v/N][v%N] = true; + return true; + } + + bool validate_touches() { + for ( int p = 0; p < my_num_threads; ++p) { + for ( int n = 0; n < N; ++n) { + ASSERT ( my_touches[p][n] == true, NULL); + } + } + return true; + } +}; + +template< typename T > +struct parallel_gets : NoAssign { + + tbb::flow::buffer_node<T> &my_b; + touches<T> &my_touches; + + parallel_gets( tbb::flow::buffer_node<T> &b, touches<T> &t) : my_b(b), my_touches(t) {} + + void operator()(int) const { + for (int j = 0; j < N; ++j) { + T v; + spin_try_get( my_b, v ); + my_touches.check( v ); + } + } + +}; + +template< typename T > +struct parallel_put_get : NoAssign { + + tbb::flow::buffer_node<T> &my_b; + touches<T> &my_touches; + + parallel_put_get( tbb::flow::buffer_node<T> &b, touches<T> &t ) : my_b(b), my_touches(t) {} + + void operator()(int tid) const { + + for ( int i = 0; i < N; i+=C ) { + int j_end = ( N < i + C ) ? N : i + C; + // dump about C values into the buffer + for ( int j = i; j < j_end; ++j ) { + ASSERT( my_b.try_put( T (N*tid + j ) ) == true, NULL ); + } + // receiver about C values from the buffer + for ( int j = i; j < j_end; ++j ) { + T v; + spin_try_get( my_b, v ); + my_touches.check( v ); + } + } + } + +}; + +// +// Tests +// +// Item can be reserved, released, consumed ( single serial receiver ) +// +template< typename T > +int test_reservation() { + tbb::flow::graph g; + T bogus_value(-1); + + // Simple tests + tbb::flow::buffer_node<T> b(g); + + b.try_put(T(1)); + b.try_put(T(2)); + b.try_put(T(3)); + + T v, vsum; + ASSERT( b.try_reserve(v) == true, NULL ); + ASSERT( b.try_release() == true, NULL ); + v = bogus_value; + g.wait_for_all(); + ASSERT( b.try_reserve(v) == true, NULL ); + ASSERT( b.try_consume() == true, NULL ); + vsum += v; + v = bogus_value; + g.wait_for_all(); + + ASSERT( b.try_get(v) == true, NULL ); + vsum += v; + v = bogus_value; + g.wait_for_all(); + + ASSERT( b.try_reserve(v) == true, NULL ); + ASSERT( b.try_release() == true, NULL ); + v = bogus_value; + g.wait_for_all(); + ASSERT( b.try_reserve(v) == true, NULL ); + ASSERT( b.try_consume() == true, NULL ); + vsum += v; + ASSERT( vsum == T(6), NULL); + v = bogus_value; + g.wait_for_all(); + + return 0; +} + +// +// Tests +// +// multilpe parallel senders, items in arbitrary order +// multilpe parallel senders, multiple parallel receivers, items in arbitrary order and all items received +// * overlapped puts / gets +// * all puts finished before any getS +// +template< typename T > +int test_parallel(int num_threads) { + tbb::flow::graph g; + tbb::flow::buffer_node<T> b(g); + tbb::flow::buffer_node<T> b2(g); + tbb::flow::buffer_node<T> b3(g); + T bogus_value(-1); + T j = bogus_value; + + NativeParallelFor( num_threads, parallel_puts<T>(b) ); + + T *next_value = new T[num_threads]; + for (int tid = 0; tid < num_threads; ++tid) next_value[tid] = T(0); + + for (int i = 0; i < num_threads * N; ++i ) { + spin_try_get( b, j ); + check_item( next_value, j ); + j = bogus_value; + } + for (int tid = 0; tid < num_threads; ++tid) { + ASSERT( next_value[tid] == T((N*(N-1))/2), NULL ); + } + + j = bogus_value; + g.wait_for_all(); + ASSERT( b.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + NativeParallelFor( num_threads, parallel_puts<T>(b) ); + + { + touches< T > t( num_threads ); + NativeParallelFor( num_threads, parallel_gets<T>(b, t) ); + g.wait_for_all(); + ASSERT( t.validate_touches(), NULL ); + } + j = bogus_value; + ASSERT( b.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + g.wait_for_all(); + { + touches< T > t( num_threads ); + NativeParallelFor( num_threads, parallel_put_get<T>(b, t) ); + g.wait_for_all(); + ASSERT( t.validate_touches(), NULL ); + } + j = bogus_value; + ASSERT( b.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + tbb::flow::make_edge( b, b2 ); + tbb::flow::make_edge( b2, b3 ); + + NativeParallelFor( num_threads, parallel_puts<T>(b) ); + { + touches< T > t( num_threads ); + NativeParallelFor( num_threads, parallel_gets<T>(b3, t) ); + g.wait_for_all(); + ASSERT( t.validate_touches(), NULL ); + } + j = bogus_value; + g.wait_for_all(); + ASSERT( b.try_get( j ) == false, NULL ); + g.wait_for_all(); + ASSERT( b2.try_get( j ) == false, NULL ); + g.wait_for_all(); + ASSERT( b3.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + // test copy constructor + ASSERT( b.remove_successor( b2 ), NULL ); + // fill up b: + NativeParallelFor( num_threads, parallel_puts<T>(b) ); + // copy b: + tbb::flow::buffer_node<T> b_copy(b); + + // b_copy should be empty + j = bogus_value; + g.wait_for_all(); + ASSERT( b_copy.try_get( j ) == false, NULL ); + + // hook them together: + ASSERT( b.register_successor(b_copy) == true, NULL ); + // try to get content from b_copy + { + touches< T > t( num_threads ); + NativeParallelFor( num_threads, parallel_gets<T>(b_copy, t) ); + g.wait_for_all(); + ASSERT( t.validate_touches(), NULL ); + } + // now both should be empty + j = bogus_value; + g.wait_for_all(); + ASSERT( b.try_get( j ) == false, NULL ); + g.wait_for_all(); + ASSERT( b_copy.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + return 0; +} + +// +// Tests +// +// Predecessors cannot be registered +// Empty buffer rejects item requests +// Single serial sender, items in arbitrary order +// Chained buffers ( 2 & 3 ), single sender, items at last buffer in arbitrary order +// + +template< typename T > +int test_serial() { + tbb::flow::graph g; + T bogus_value(-1); + + tbb::flow::buffer_node<T> b(g); + tbb::flow::buffer_node<T> b2(g); + T j = bogus_value; + + // + // Rejects attempts to add / remove predecessor + // Rejects request from empty buffer + // + ASSERT( b.register_predecessor( b2 ) == false, NULL ); + ASSERT( b.remove_predecessor( b2 ) == false, NULL ); + ASSERT( b.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + // + // Simple puts and gets + // + + for (int i = 0; i < N; ++i) { + bool msg = b.try_put( T(i) ); + ASSERT( msg == true, NULL ); + } + + T vsum = T(0); + for (int i = 0; i < N; ++i) { + j = bogus_value; + spin_try_get( b, j ); + vsum += j; + } + ASSERT( vsum == (N*(N-1))/2, NULL); + j = bogus_value; + g.wait_for_all(); + ASSERT( b.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + tbb::flow::make_edge(b, b2); + + vsum = T(0); + for (int i = 0; i < N; ++i) { + bool msg = b.try_put( T(i) ); + ASSERT( msg == true, NULL ); + } + + for (int i = 0; i < N; ++i) { + j = bogus_value; + spin_try_get( b2, j ); + vsum += j; + } + ASSERT( vsum == (N*(N-1))/2, NULL); + j = bogus_value; + g.wait_for_all(); + ASSERT( b.try_get( j ) == false, NULL ); + g.wait_for_all(); + ASSERT( b2.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + tbb::flow::remove_edge(b, b2); + ASSERT( b.try_put( 1 ) == true, NULL ); + g.wait_for_all(); + ASSERT( b2.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + g.wait_for_all(); + ASSERT( b.try_get( j ) == true, NULL ); + ASSERT( j == 1, NULL ); + + tbb::flow::buffer_node<T> b3(g); + tbb::flow::make_edge( b, b2 ); + tbb::flow::make_edge( b2, b3 ); + + vsum = T(0); + for (int i = 0; i < N; ++i) { + bool msg = b.try_put( T(i) ); + ASSERT( msg == true, NULL ); + } + + for (int i = 0; i < N; ++i) { + j = bogus_value; + spin_try_get( b3, j ); + vsum += j; + } + ASSERT( vsum == (N*(N-1))/2, NULL); + j = bogus_value; + g.wait_for_all(); + ASSERT( b.try_get( j ) == false, NULL ); + g.wait_for_all(); + ASSERT( b2.try_get( j ) == false, NULL ); + g.wait_for_all(); + ASSERT( b3.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + tbb::flow::remove_edge(b, b2); + ASSERT( b.try_put( 1 ) == true, NULL ); + g.wait_for_all(); + ASSERT( b2.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + g.wait_for_all(); + ASSERT( b3.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + g.wait_for_all(); + ASSERT( b.try_get( j ) == true, NULL ); + ASSERT( j == 1, NULL ); + + return 0; +} + +int TestMain() { + tbb::tick_count start = tbb::tick_count::now(), stop; + for (int p = 1; p < 4; ++p) { + tbb::task_scheduler_init init(p); + test_serial<int>(); + test_parallel<int>(p); + } + stop = tbb::tick_count::now(); + REMARK("Buffer_Node Time=%6.6f\n", (stop-start).seconds()); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_cache_aligned_allocator.cpp b/src/tbb/src/test/test_cache_aligned_allocator.cpp new file mode 100644 index 0000000..c194cbc --- /dev/null +++ b/src/tbb/src/test/test_cache_aligned_allocator.cpp @@ -0,0 +1,90 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Test whether cache_aligned_allocator works with some of the host's STL containers. + +#include "tbb/cache_aligned_allocator.h" +#include "tbb/tbb_allocator.h" + +#define HARNESS_NO_PARSE_COMMAND_LINE 1 +// the real body of the test is there: +#include "test_allocator.h" + +template<> +struct is_zero_filling<tbb::zero_allocator<void> > { + static const bool value = true; +}; + +// Test that NFS_Allocate() throws bad_alloc if cannot allocate memory. +void Test_NFS_Allocate_Throws() { +#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN + using namespace tbb::internal; + + bool exception_caught = false; + // First, allocate a reasonably big amount of memory, big enough + // to not cause warp around in system allocator after adding object header + // during address2 allocation. + const size_t itemsize = 1024; + const size_t nitems = 1024; + void *address1 = NULL; + try { + address1 = NFS_Allocate( nitems, itemsize, NULL ); + } catch( ... ) { + address1 = NULL; + } + ASSERT( address1, "NFS_Allocate unable to obtain 32*1024 bytes" ); + + void *address2 = NULL; + try { + // Try allocating more memory than left in the address space; should cause std::bad_alloc + address2 = NFS_Allocate( 1, ~size_t(0) - itemsize*nitems + NFS_GetLineSize(), NULL); + } catch( std::bad_alloc ) { + exception_caught = true; + } catch( ... ) { + ASSERT( __TBB_EXCEPTION_TYPE_INFO_BROKEN, "Unexpected exception type (std::bad_alloc was expected)" ); + exception_caught = true; + } + ASSERT( exception_caught, "NFS_Allocate did not throw bad_alloc" ); + ASSERT( !address2, "NFS_Allocate returned garbage?" ); + + try { + NFS_Free( address1 ); + } catch( ... ) { + ASSERT( false, "NFS_Free did not accept the address obtained with NFS_Allocate" ); + } +#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */ +} + +int TestMain () { + int result = TestMain<tbb::cache_aligned_allocator<void> >(); + result += TestMain<tbb::tbb_allocator<void> >(); + result += TestMain<tbb::zero_allocator<void> >(); + ASSERT( !result, NULL ); + Test_NFS_Allocate_Throws(); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_cache_aligned_allocator_STL.cpp b/src/tbb/src/test/test_cache_aligned_allocator_STL.cpp new file mode 100644 index 0000000..1cb6dc4 --- /dev/null +++ b/src/tbb/src/test/test_cache_aligned_allocator_STL.cpp @@ -0,0 +1,43 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Test whether cache_aligned_allocator works with some of the host's STL containers. + +#include "tbb/cache_aligned_allocator.h" +#include "tbb/tbb_allocator.h" + +#define HARNESS_NO_PARSE_COMMAND_LINE 1 +#include "test_allocator_STL.h" + +int TestMain () { + TestAllocatorWithSTL<tbb::cache_aligned_allocator<void> >(); + TestAllocatorWithSTL<tbb::tbb_allocator<void> >(); + TestAllocatorWithSTL<tbb::zero_allocator<void> >(); + return Harness::Done; +} + diff --git a/src/tbb/src/test/test_cilk_common.h b/src/tbb/src/test/test_cilk_common.h new file mode 100644 index 0000000..ce7162b --- /dev/null +++ b/src/tbb/src/test/test_cilk_common.h @@ -0,0 +1,91 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// This file is a common part of test_cilk_interop and test_cilk_dynamic_load tests + +int TBB_Fib( int n ); + +class FibCilkSubtask: public tbb::task { + int n; + int& result; + /*override*/ task* execute() { + if( n<2 ) { + result = n; + } else { + int x, y; + x = cilk_spawn TBB_Fib(n-2); + y = cilk_spawn TBB_Fib(n-1); + cilk_sync; + result = x+y; + } + return NULL; + } +public: + FibCilkSubtask( int& result_, int n_ ) : result(result_), n(n_) {} +}; + +class FibTask: public tbb::task { + int n; + int& result; + /*override*/ task* execute() { + if( !g_sandwich && n<2 ) { + result = n; + } else { + int x,y; + tbb::task_scheduler_init init(P_nested); + task* self0 = &task::self(); + set_ref_count( 3 ); + if ( g_sandwich ) { + spawn (*new( allocate_child() ) FibCilkSubtask(x,n-1)); + spawn (*new( allocate_child() ) FibCilkSubtask(y,n-2)); + } + else { + spawn (*new( allocate_child() ) FibTask(x,n-1)); + spawn (*new( allocate_child() ) FibTask(y,n-2)); + } + wait_for_all(); + task* self1 = &task::self(); + ASSERT( self0 == self1, "failed to preserve TBB TLS" ); + result = x+y; + } + return NULL; + } +public: + FibTask( int& result_, int n_ ) : result(result_), n(n_) {} +}; + +int TBB_Fib( int n ) { + if( n<2 ) { + return n; + } else { + int result; + tbb::task_scheduler_init init(P_nested); + tbb::task::spawn_root_and_wait(*new( tbb::task::allocate_root()) FibTask(result,n) ); + return result; + } +} diff --git a/src/tbb/src/test/test_cilk_dynamic_load.cpp b/src/tbb/src/test/test_cilk_dynamic_load.cpp new file mode 100644 index 0000000..57630e9 --- /dev/null +++ b/src/tbb/src/test/test_cilk_dynamic_load.cpp @@ -0,0 +1,164 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/tbb_config.h" + +// Skip the test if no interoperability with cilkrts +#define __TBB_CILK_INTEROP (__TBB_SURVIVE_THREAD_SWITCH && __INTEL_COMPILER>=1200) +// Skip the test when cilkrts did not have dlopen()/dlclose() start up feature +#define CILK_SYMBOLS_VISIBLE (_WIN32||_WIN64) +// The compiler does not add "-lcilkrts" linker option on some linux systems +#define CILK_LINKAGE_BROKEN (__linux__ && __GNUC__<4 && __INTEL_COMPILER_BUILD_DATE <= 20110427) +// Currently, the interop doesn't support the situation: +//1) TBB is outermost; +//2) Cilk, and it should be dynamically loaded with dlopen/LoadLibrary (possibly via a 3rd party module); +//3) TBB again; +//4) Cilk again. +#define HEAVY_NESTED_INTEROP_SUPPORT __INTEL_COMPILER_BUILD_DATE < 20110427 + +#if __TBB_CILK_INTEROP && CILK_SYMBOLS_VISIBLE && !CILK_LINKAGE_BROKEN && HEAVY_NESTED_INTEROP_SUPPORT + +#include "tbb/task_scheduler_init.h" +#include "tbb/task.h" + +static const int N = 25; +static const int P_outer = 4; +static const int P_nested = 2; + +#ifdef _USRDLL + +#include <cilk/cilk.h> +#define HARNESS_CUSTOM_MAIN 1 +#include "harness.h" +#undef HARNESS_CUSTOM_MAIN + +#if _WIN32 || _WIN64 +#define CILK_TEST_EXPORT extern "C" __declspec(dllexport) +#else +#define CILK_TEST_EXPORT extern "C" +#endif /* _WIN32 || _WIN64 */ + +bool g_sandwich = true; // have to be declare before #include "test_cilk_common.h" +#include "test_cilk_common.h" + +CILK_TEST_EXPORT int CilkFib( int n ) +{ + return TBB_Fib(n); +} + +CILK_TEST_EXPORT void CilkShutdown() +{ + __cilkrts_end_cilk(); +} + +#else /* _USRDLL undefined */ + +#include "harness.h" +#include "harness_dynamic_libs.h" + +int SerialFib( int n ) { + int a=0, b=1; + for( int i=0; i<n; ++i ) { + b += a; + a = b-a; + } + return a; +} + +int F = SerialFib(N); + +typedef int (*CILK_CALL)(int); +CILK_CALL CilkFib = 0; + +typedef void (*CILK_SHUTDOWN)(); +CILK_SHUTDOWN CilkShutdown = 0; + +class FibTask: public tbb::task { + int n; + int& result; + /*override*/ task* execute() { + if( n<2 ) { + result = n; + } else { + + // TODO: why RTLD_LAZY was used here? + Harness::LIBRARY_HANDLE hLib = + Harness::OpenLibrary(TEST_LIBRARY_NAME("test_cilk_dynamic_load_dll")); + CilkFib = (CILK_CALL)Harness::GetAddress(hLib, "CilkFib"); + CilkShutdown = (CILK_SHUTDOWN)Harness::GetAddress(hLib, "CilkShutdown"); + + int x, y; + x = CilkFib(n-2); + y = CilkFib(n-1); + result = x+y; + + CilkShutdown(); + + Harness::CloseLibrary(hLib); + } + return NULL; + } +public: + FibTask( int& result_, int n_ ) : result(result_), n(n_) {} +}; + + +int TBB_Fib( int n ) { + if( n<2 ) { + return n; + } else { + int result; + tbb::task_scheduler_init init(P_nested); + tbb::task::spawn_root_and_wait(*new( tbb::task::allocate_root()) FibTask(result,n) ); + return result; + } +} + +void RunSandwich() { + tbb::task_scheduler_init init(P_outer); + int m = TBB_Fib(N); + ASSERT( m == F, NULL ); +} + +int TestMain () { + for ( int i = 0; i < 20; ++i ) + RunSandwich(); + return Harness::Done; +} + +#endif /* _USRDLL */ + +#else /* !__TBB_CILK_INTEROP */ + +#include "harness.h" + +int TestMain () { + return Harness::Skipped; +} + +#endif /* !__TBB_CILK_INTEROP */ diff --git a/src/tbb/src/test/test_cilk_interop.cpp b/src/tbb/src/test/test_cilk_interop.cpp new file mode 100644 index 0000000..8c68ae9 --- /dev/null +++ b/src/tbb/src/test/test_cilk_interop.cpp @@ -0,0 +1,162 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/tbb_config.h" +#include "harness.h" + +// Skip the test if no interoperability with cilkrts +#define __TBB_CILK_INTEROP (__TBB_SURVIVE_THREAD_SWITCH && __INTEL_COMPILER>=1200) +// The compiler does not add "-lcilkrts" linker option on some linux systems +#define CILK_LINKAGE_BROKEN (__linux__ && __GNUC__<4 && __INTEL_COMPILER_BUILD_DATE <= 20110427) +// In U4, cilkrts incorrectly sends the interop notifications to TBB +#define CILK_NOTIFICATIONS_BROKEN ( __INTEL_COMPILER_BUILD_DATE == 20110427 ) + +#if __TBB_CILK_INTEROP && !CILK_LINKAGE_BROKEN && !CILK_NOTIFICATIONS_BROKEN + +static const int N = 14; +static const int P_outer = 4; +static const int P_nested = 2; + +#include <cilk/cilk.h> +#define private public +#include "tbb/task.h" +#undef private +#include "tbb/task_scheduler_init.h" +#include <cstdio> +#include <cassert> + +enum tbb_sched_injection_mode_t { + tbbsched_none = 0, + tbbsched_explicit_only = 1, + tbbsched_auto_only = 2, + tbbsched_mixed = 3 +}; + +tbb_sched_injection_mode_t g_sim = tbbsched_none; + +bool g_sandwich = false; // have to be declare before #include "test_cilk_common.h" +#include "test_cilk_common.h" + +// A time delay routine +void Delay( int n ) { + static volatile int Global; + for( int k=0; k<10000; ++k ) + for( int i=0; i<n; ++i ) + ++Global; +} + +int SerialFib( int n ) { + int a=0, b=1; + for( int i=0; i<n; ++i ) { + b += a; + a = b-a; + } + return a; +} + +int F = SerialFib(N); + +int Fib ( int n ) { + if( n < 2 ) { + if ( g_sim ) { + tbb::task_scheduler_init tsi(P_nested); + } + return n; + } else { + tbb::task_scheduler_init *tsi = NULL; + tbb::task *cur = NULL; + if ( g_sim ) { + if ( n % 2 == 0 ) { + if ( g_sim == tbbsched_auto_only || (g_sim == tbbsched_mixed && n % 4 == 0) ) { + // Trigger TBB scheduler auto-initialization + cur = &tbb::task::self(); + } + else { + ASSERT ( g_sim == tbbsched_explicit_only || (g_sim == tbbsched_mixed && n % 4 != 0), NULL ); + // Initialize TBB scheduler explicitly + tsi = new tbb::task_scheduler_init(P_nested); + } + } + } + int x, y; + x = cilk_spawn Fib(n-2); + y = cilk_spawn Fib(n-1); + cilk_sync; + if ( tsi ) + delete tsi; + return x+y; + } +} + +void RunCilkOnly ( tbb_sched_injection_mode_t sim ) { + g_sim = sim; + int m = Fib(N); + ASSERT( m == F, NULL ); +} + +struct FibBody : NoAssign, Harness::NoAfterlife { + void operator() ( int ) const { + int m = Fib(N); + ASSERT( m == F, NULL ); + } +}; + +void RunCilkOnlyConcurrently ( tbb_sched_injection_mode_t sim ) { + g_sim = sim; + NativeParallelFor( P_outer, FibBody() ); +} + +void RunSandwich( bool sandwich ) { + g_sandwich = sandwich; + tbb::task_scheduler_init init(P_outer); + int m = TBB_Fib(N); + ASSERT( g_sandwich == sandwich, "Memory corruption detected" ); + ASSERT( m == F, NULL ); +} + +int TestMain () { + for ( int i = 0; i < 100; ++i ) + RunCilkOnlyConcurrently( tbbsched_none ); + RunCilkOnly( tbbsched_none ); + RunCilkOnly( tbbsched_explicit_only ); + RunCilkOnly( tbbsched_auto_only ); + RunCilkOnly( tbbsched_mixed ); + RunSandwich( false ); + for ( int i = 0; i < 10; ++i ) + RunSandwich( true ); + __cilkrts_end_cilk(); + return Harness::Done; +} + +#else /* !__TBB_CILK_INTEROP */ + +int TestMain () { + return Harness::Skipped; +} + +#endif /* !__TBB_CILK_INTEROP */ diff --git a/src/tbb/src/test/test_combinable.cpp b/src/tbb/src/test/test_combinable.cpp new file mode 100644 index 0000000..dad8451 --- /dev/null +++ b/src/tbb/src/test/test_combinable.cpp @@ -0,0 +1,459 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#define __TBB_EXTRA_DEBUG 1 // for concurrent_hash_map +#include "tbb/combinable.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/parallel_for.h" +#include "tbb/blocked_range.h" +#include "tbb/tick_count.h" +#include "tbb/tbb_allocator.h" +#include "tbb/tbb_thread.h" + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include <cstring> +#include <vector> +#include <utility> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +#include "harness_assert.h" +#include "harness.h" + +#if __TBB_GCC_WARNING_SUPPRESSION_PRESENT +#pragma GCC diagnostic ignored "-Wuninitialized" +#endif + +static tbb::atomic<int> construction_counter; +static tbb::atomic<int> destruction_counter; + +const int REPETITIONS = 10; +const int N = 100000; +const int VALID_NUMBER_OF_KEYS = 100; +const double EXPECTED_SUM = (REPETITIONS + 1) * N; + +// +// A minimal class +// Define: default and copy constructor, and allow implicit operator& +// also operator= +// + +class minimal { +private: + int my_value; +public: + minimal(int val=0) : my_value(val) { ++construction_counter; } + minimal( const minimal &m ) : my_value(m.my_value) { ++construction_counter; } + minimal& operator=(const minimal& other) { my_value = other.my_value; return *this; } + minimal& operator+=(const minimal& other) { my_value += other.my_value; return *this; } + operator int() const { return my_value; } + ~minimal() { ++destruction_counter; } + void set_value( const int i ) { my_value = i; } + int value( ) const { return my_value; } +}; + +//// functors for initialization and combine + +// Addition +template <typename T> +struct FunctorAddFinit { + T operator()() { return 0; } +}; + +template <typename T> +struct FunctorAddFinit7 { + T operator()() { return 7; } +}; + +template <typename T> +struct FunctorAddCombine { + T operator()(T left, T right ) const { + return left + right; + } +}; + +template <typename T> +struct FunctorAddCombineRef { + T operator()(const T& left, const T& right ) const { + return left + right; + } +}; + +template <typename T> +T my_finit( ) { return 0; } + +template <typename T> +T my_combine( T left, T right) { return left + right; } + +template <typename T> +T my_combine_ref( const T &left, const T &right) { return left + right; } + +template <typename T> +class CombineEachHelper { +public: + CombineEachHelper(T& _result) : my_result(_result) {} + void operator()(const T& new_bit) { my_result += new_bit; } + CombineEachHelper& operator=(const CombineEachHelper& other) { + my_result = other; + return *this; + } +private: + T& my_result; +}; + +template <typename T> +class CombineEachHelperCnt { +public: + CombineEachHelperCnt(T& _result, int& _nbuckets) : my_result(_result), nBuckets(_nbuckets) {} + void operator()(const T& new_bit) { my_result += new_bit; ++nBuckets; } + CombineEachHelperCnt& operator=(const CombineEachHelperCnt& other) { + my_result = other.my_result; + nBuckets = other.nBuckets; + return *this; + } +private: + T& my_result; + int& nBuckets; +}; + +template <typename T> +class CombineEachVectorHelper { +public: + typedef std::vector<T, tbb::tbb_allocator<T> > ContainerType; + CombineEachVectorHelper(T& _result) : my_result(_result) { } + void operator()(const ContainerType& new_bit) { + for(typename ContainerType::const_iterator ci = new_bit.begin(); ci != new_bit.end(); ++ci) { + my_result += *ci; + } + } + CombineEachVectorHelper& operator=(const CombineEachVectorHelper& other) { my_result=other.my_result; return *this;} +private: + T& my_result; +}; + + + +//// end functors + +template< typename T > +void run_serial_scalar_tests(const char *test_name) { + tbb::tick_count t0; + T sum = 0; + + REMARK("Testing serial %s... ", test_name); + for (int t = -1; t < REPETITIONS; ++t) { + if (Verbose && t == 0) t0 = tbb::tick_count::now(); + for (int i = 0; i < N; ++i) { + sum += 1; + } + } + + double ResultValue = sum; + ASSERT( EXPECTED_SUM == ResultValue, NULL); + REMARK("done\nserial %s, 0, %g, %g\n", test_name, ResultValue, ( tbb::tick_count::now() - t0).seconds()); +} + + +template <typename T> +class ParallelScalarBody: NoAssign { + + tbb::combinable<T> &sums; + +public: + + ParallelScalarBody ( tbb::combinable<T> &_sums ) : sums(_sums) { } + + void operator()( const tbb::blocked_range<int> &r ) const { + for (int i = r.begin(); i != r.end(); ++i) { + bool was_there; + T& my_local = sums.local(was_there); + if(!was_there) my_local = 0; + my_local += 1 ; + } + } + +}; + +// parallel body with no test for first access. +template <typename T> +class ParallelScalarBodyNoInit: NoAssign { + + tbb::combinable<T> &sums; + +public: + + ParallelScalarBodyNoInit ( tbb::combinable<T> &_sums ) : sums(_sums) { } + + void operator()( const tbb::blocked_range<int> &r ) const { + for (int i = r.begin(); i != r.end(); ++i) { + sums.local() += 1 ; + } + } + +}; + +template< typename T > +void RunParallelScalarTests(const char *test_name) { + + tbb::task_scheduler_init init(tbb::task_scheduler_init::deferred); + + for (int p = MinThread; p <= MaxThread; ++p) { + + + if (p == 0) continue; + + REMARK("Testing parallel %s on %d thread(s)... ", test_name, p); + init.initialize(p); + + tbb::tick_count t0; + + T assign_sum(0); + + T combine_sum(0); + + T combine_ref_sum(0); + + T combine_each_sum(0); + + T combine_finit_sum(0); + + for (int t = -1; t < REPETITIONS; ++t) { + if (Verbose && t == 0) t0 = tbb::tick_count::now(); + + tbb::combinable<T> sums; + FunctorAddFinit<T> my_finit_decl; + tbb::combinable<T> finit_combinable(my_finit_decl); + + + tbb::parallel_for( tbb::blocked_range<int>( 0, N, 10000 ), ParallelScalarBodyNoInit<T>( finit_combinable ) ); + tbb::parallel_for( tbb::blocked_range<int>( 0, N, 10000 ), ParallelScalarBody<T>( sums ) ); + + // Use combine + combine_sum += sums.combine(my_combine<T>); + combine_ref_sum += sums.combine(my_combine_ref<T>); + + CombineEachHelper<T> my_helper(combine_each_sum); + sums.combine_each(my_helper); + + // test assignment + tbb::combinable<T> assigned; + assigned = sums; + + assign_sum += assigned.combine(my_combine<T>); + + combine_finit_sum += finit_combinable.combine(my_combine<T>); + } + + ASSERT( EXPECTED_SUM == combine_sum, NULL); + ASSERT( EXPECTED_SUM == combine_ref_sum, NULL); + ASSERT( EXPECTED_SUM == assign_sum, NULL); + ASSERT( EXPECTED_SUM == combine_finit_sum, NULL); + + REMARK("done\nparallel %s, %d, %g, %g\n", test_name, p, static_cast<double>(combine_sum), + ( tbb::tick_count::now() - t0).seconds()); + init.terminate(); + } +} + + +template <typename T> +class ParallelVectorForBody: NoAssign { + + tbb::combinable< std::vector<T, tbb::tbb_allocator<T> > > &locals; + +public: + + ParallelVectorForBody ( tbb::combinable< std::vector<T, tbb::tbb_allocator<T> > > &_locals ) : locals(_locals) { } + + void operator()( const tbb::blocked_range<int> &r ) const { + T one = 1; + + for (int i = r.begin(); i < r.end(); ++i) { + locals.local().push_back( one ); + } + } + +}; + +template< typename T > +void RunParallelVectorTests(const char *test_name) { + tbb::tick_count t0; + tbb::task_scheduler_init init(tbb::task_scheduler_init::deferred); + typedef std::vector<T, tbb::tbb_allocator<T> > ContainerType; + + for (int p = MinThread; p <= MaxThread; ++p) { + + if (p == 0) continue; + REMARK("Testing parallel %s on %d thread(s)... ", test_name, p); + init.initialize(p); + + T sum = 0; + T sum2 = 0; + T sum3 = 0; + + for (int t = -1; t < REPETITIONS; ++t) { + if (Verbose && t == 0) t0 = tbb::tick_count::now(); + typedef typename tbb::combinable< ContainerType > CombinableType; + CombinableType vs; + + tbb::parallel_for ( tbb::blocked_range<int> (0, N, 10000), ParallelVectorForBody<T>( vs ) ); + + // copy construct + CombinableType vs2(vs); // this causes an assertion failure, related to allocators... + + // assign + CombinableType vs3; + vs3 = vs; + + CombineEachVectorHelper<T> MyCombineEach(sum); + vs.combine_each(MyCombineEach); + + CombineEachVectorHelper<T> MyCombineEach2(sum2); + vs2.combine_each(MyCombineEach2); + + CombineEachVectorHelper<T> MyCombineEach3(sum3); + vs2.combine_each(MyCombineEach3); + // combine_each sums all elements of each vector into the result. + } + + double ResultValue = sum; + ASSERT( EXPECTED_SUM == ResultValue, NULL); + ResultValue = sum2; + ASSERT( EXPECTED_SUM == ResultValue, NULL); + ResultValue = sum3; + ASSERT( EXPECTED_SUM == ResultValue, NULL); + REMARK("done\nparallel %s, %d, %g, %g\n", test_name, p, ResultValue, ( tbb::tick_count::now() - t0).seconds()); + init.terminate(); + } +} + +#include "harness_barrier.h" + +Harness::SpinBarrier sBarrier; + +struct Body : NoAssign { + tbb::combinable<int>* locals; + const int nthread; + const int nIters; + Body( int nthread_, int niters_ ) : nthread(nthread_), nIters(niters_) { sBarrier.initialize(nthread_); } + + + void operator()(int thread_id ) const { + bool existed; + sBarrier.wait(); + for(int i = 0; i < nIters; ++i ) { + existed = thread_id & 1; + int oldval = locals->local(existed); + ASSERT(existed == (i > 0), "Error on first reference"); + ASSERT(!existed || (oldval == thread_id), "Error on fetched value"); + existed = thread_id & 1; + locals->local(existed) = thread_id; + ASSERT(existed, "Error on assignment"); + } + } +}; + +void +TestLocalAllocations( int nthread ) { + ASSERT(nthread > 0, "nthread must be positive"); +#define NITERATIONS 1000 + Body myBody(nthread, NITERATIONS); + tbb::combinable<int> myCombinable; + myBody.locals = &myCombinable; + + NativeParallelFor( nthread, myBody ); + + int mySum = 0; + int mySlots = 0; + CombineEachHelperCnt<int> myCountCombine(mySum, mySlots); + myCombinable.combine_each(myCountCombine); + + ASSERT(nthread == mySlots, "Incorrect number of slots"); + ASSERT(mySum == (nthread - 1) * nthread / 2, "Incorrect values in result"); +} + + +void +RunParallelTests() { + RunParallelScalarTests<int>("int"); + RunParallelScalarTests<double>("double"); + RunParallelScalarTests<minimal>("minimal"); + RunParallelVectorTests<int>("std::vector<int, tbb::tbb_allocator<int> >"); + RunParallelVectorTests<double>("std::vector<double, tbb::tbb_allocator<double> >"); +} + +template <typename T> +void +RunAssignmentAndCopyConstructorTest(const char *test_name) { + REMARK("Testing assignment and copy construction for %s\n", test_name); + + // test creation with finit function (combine returns finit return value if no threads have created locals) + FunctorAddFinit7<T> my_finit7_decl; + tbb::combinable<T> create2(my_finit7_decl); + ASSERT(7 == create2.combine(my_combine<T>), NULL); + + // test copy construction with function initializer + tbb::combinable<T> copy2(create2); + ASSERT(7 == copy2.combine(my_combine<T>), NULL); + + // test copy assignment with function initializer + FunctorAddFinit<T> my_finit_decl; + tbb::combinable<T> assign2(my_finit_decl); + assign2 = create2; + ASSERT(7 == assign2.combine(my_combine<T>), NULL); +} + +void +RunAssignmentAndCopyConstructorTests() { + REMARK("Running assignment and copy constructor tests\n"); + RunAssignmentAndCopyConstructorTest<int>("int"); + RunAssignmentAndCopyConstructorTest<double>("double"); + RunAssignmentAndCopyConstructorTest<minimal>("minimal"); +} + +int TestMain () { + if (MaxThread > 0) { + RunParallelTests(); + } + RunAssignmentAndCopyConstructorTests(); + for(int i = 1 <= MinThread ? MinThread : 1; i <= MaxThread; ++i) { + REMARK("Testing local() allocation with nthreads=%d\n", i); + for(int j = 0; j < 100; ++j) { + TestLocalAllocations(i); + } + } + return Harness::Done; +} + diff --git a/src/tbb/src/test/test_concurrent_hash_map.cpp b/src/tbb/src/test/test_concurrent_hash_map.cpp new file mode 100644 index 0000000..50b6915 --- /dev/null +++ b/src/tbb/src/test/test_concurrent_hash_map.cpp @@ -0,0 +1,955 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifndef TBB_USE_PERFORMANCE_WARNINGS +#define TBB_USE_PERFORMANCE_WARNINGS 1 +#endif + +// Our tests usually include the header under test first. But this test needs +// to use the preprocessor to edit the identifier runtime_warning in concurrent_hash_map.h. +// Hence we include a few other headers before doing the abusive edit. +#include "tbb/tbb_stddef.h" /* Defines runtime_warning */ +#include "harness_assert.h" /* Prerequisite for defining hooked_warning */ + +// The symbol internal::runtime_warning is normally an entry point into the TBB library. +// Here for sake of testing, we define it to be hooked_warning, a routine peculiar to this unit test. +#define runtime_warning hooked_warning + +static bool bad_hashing = false; + +namespace tbb { + namespace internal { + static void hooked_warning( const char* /*format*/, ... ) { + ASSERT(bad_hashing, "unexpected runtime_warning: bad hashing"); + } + } // namespace internal +} // namespace tbb +#define __TBB_EXTRA_DEBUG 1 // enables additional checks +#include "tbb/concurrent_hash_map.h" + +// Restore runtime_warning as an entry point into the TBB library. +#undef runtime_warning + +namespace Jungle { + struct Tiger {}; + size_t tbb_hasher( const Tiger& ) {return 0;} +} + +#if !defined(_MSC_VER) || _MSC_VER>=1400 || __INTEL_COMPILER +void test_ADL() { + tbb::tbb_hash_compare<Jungle::Tiger>::hash(Jungle::Tiger()); // Instantiation chain finds tbb_hasher via Argument Dependent Lookup +} +#endif + +struct UserDefinedKeyType { +}; + +namespace tbb { + // Test whether tbb_hash_compare can be partially specialized as stated in Reference manual. + template<> struct tbb_hash_compare<UserDefinedKeyType> { + size_t hash( UserDefinedKeyType ) const {return 0;} + bool equal( UserDefinedKeyType /*x*/, UserDefinedKeyType /*y*/ ) {return true;} + }; +} + +#if HARNESS_USE_PROXY + #define TBB_PREVIEW_RUNTIME_LOADER 1 + #include "tbb/runtime_loader.h" + static char const * test_path[] = { ".", NULL }; + static tbb::runtime_loader test_runtime_loader( test_path ); +#endif // HARNESS_USE_PROXY + +tbb::concurrent_hash_map<UserDefinedKeyType,int> TestInstantiationWithUserDefinedKeyType; + +// Test whether a sufficient set of headers were included to instantiate a concurernt_hash_map. OSS Bug #120 (& #130): +// http://www.threadingbuildingblocks.org/bug_desc.php?id=120 +tbb::concurrent_hash_map<std::pair<std::pair<int,std::string>,const char*>,int> TestInstantiation; + +#include "tbb/parallel_for.h" +#include "tbb/blocked_range.h" +#include "tbb/atomic.h" +#include "tbb/tick_count.h" +#include "harness.h" +#include "harness_allocator.h" + +class MyException : public std::bad_alloc { +public: + virtual const char *what() const throw() { return "out of items limit"; } + virtual ~MyException() throw() {} +}; + +/** Has tightly controlled interface so that we can verify + that concurrent_hash_map uses only the required interface. */ +class MyKey { +private: + void operator=( const MyKey& ); // Deny access + int key; + friend class MyHashCompare; + friend class YourHashCompare; +public: + static MyKey make( int i ) { + MyKey result; + result.key = i; + return result; + } + int value_of() const {return key;} +}; + +tbb::atomic<long> MyDataCount; +long MyDataCountLimit = 0; + +class MyData { +protected: + friend class MyData2; + int data; + enum state_t { + LIVE=0x1234, + DEAD=0x5678 + } my_state; + void operator=( const MyData& ); // Deny access +public: + MyData(int i = 0) { + my_state = LIVE; + data = i; + if(MyDataCountLimit && MyDataCount + 1 >= MyDataCountLimit) + __TBB_THROW( MyException() ); + ++MyDataCount; + } + MyData( const MyData& other ) { + ASSERT( other.my_state==LIVE, NULL ); + my_state = LIVE; + data = other.data; + if(MyDataCountLimit && MyDataCount + 1 >= MyDataCountLimit) + __TBB_THROW( MyException() ); + ++MyDataCount; + } + ~MyData() { + --MyDataCount; + my_state = DEAD; + } + static MyData make( int i ) { + MyData result; + result.data = i; + return result; + } + int value_of() const { + ASSERT( my_state==LIVE, NULL ); + return data; + } + void set_value( int i ) { + ASSERT( my_state==LIVE, NULL ); + data = i; + } + bool operator==( const MyData& other ) const { + ASSERT( other.my_state==LIVE, NULL ); + ASSERT( my_state==LIVE, NULL ); + return data == other.data; + } +}; + +class MyData2 : public MyData { +public: + MyData2( ) {} + MyData2( const MyData& other ) { + ASSERT( other.my_state==LIVE, NULL ); + ASSERT( my_state==LIVE, NULL ); + data = other.data; + } + void operator=( const MyData& other ) { + ASSERT( other.my_state==LIVE, NULL ); + ASSERT( my_state==LIVE, NULL ); + data = other.data; + } + void operator=( const MyData2& other ) { + ASSERT( other.my_state==LIVE, NULL ); + ASSERT( my_state==LIVE, NULL ); + data = other.data; + } + bool operator==( const MyData2& other ) const { + ASSERT( other.my_state==LIVE, NULL ); + ASSERT( my_state==LIVE, NULL ); + return data == other.data; + } +}; + +class MyHashCompare { +public: + bool equal( const MyKey& j, const MyKey& k ) const { + return j.key==k.key; + } + unsigned long hash( const MyKey& k ) const { + return k.key; + } +}; + +class YourHashCompare { +public: + bool equal( const MyKey& j, const MyKey& k ) const { + return j.key==k.key; + } + unsigned long hash( const MyKey& ) const { + return 1; + } +}; + +typedef local_counting_allocator<std::allocator<MyData> > MyAllocator; +typedef tbb::concurrent_hash_map<MyKey,MyData,MyHashCompare,MyAllocator> MyTable; +typedef tbb::concurrent_hash_map<MyKey,MyData2,MyHashCompare> MyTable2; +typedef tbb::concurrent_hash_map<MyKey,MyData,YourHashCompare> YourTable; + +template<typename MyTable> +inline void CheckAllocator(MyTable &table, size_t expected_allocs, size_t expected_frees, bool exact = true) { + size_t items_allocated = table.get_allocator().items_allocated, items_freed = table.get_allocator().items_freed; + size_t allocations = table.get_allocator().allocations, frees = table.get_allocator().frees; + REMARK("checking allocators: items %u/%u, allocs %u/%u\n", + unsigned(items_allocated), unsigned(items_freed), unsigned(allocations), unsigned(frees) ); + ASSERT( items_allocated == allocations, NULL); ASSERT( items_freed == frees, NULL); + if(exact) { + ASSERT( allocations == expected_allocs, NULL); ASSERT( frees == expected_frees, NULL); + } else { + ASSERT( allocations >= expected_allocs, NULL); ASSERT( frees >= expected_frees, NULL); + ASSERT( allocations - frees == expected_allocs - expected_frees, NULL ); + } +} + +inline bool UseKey( size_t i ) { + return (i&3)!=3; +} + +struct Insert { + static void apply( MyTable& table, int i ) { + if( UseKey(i) ) { + if( i&4 ) { + MyTable::accessor a; + table.insert( a, MyKey::make(i) ); + if( i&1 ) + (*a).second.set_value(i*i); + else + a->second.set_value(i*i); + } else + if( i&1 ) { + MyTable::accessor a; + table.insert( a, std::make_pair(MyKey::make(i), MyData(i*i)) ); + ASSERT( (*a).second.value_of()==i*i, NULL ); + } else { + MyTable::const_accessor ca; + table.insert( ca, std::make_pair(MyKey::make(i), MyData(i*i)) ); + ASSERT( ca->second.value_of()==i*i, NULL ); + } + } + } +}; + +struct Find { + static void apply( MyTable& table, int i ) { + MyTable::accessor a; + const MyTable::accessor& ca = a; + bool b = table.find( a, MyKey::make(i) ); + ASSERT( b==!a.empty(), NULL ); + if( b ) { + if( !UseKey(i) ) + REPORT("Line %d: unexpected key %d present\n",__LINE__,i); + AssertSameType( &*a, static_cast<MyTable::value_type*>(0) ); + ASSERT( ca->second.value_of()==i*i, NULL ); + ASSERT( (*ca).second.value_of()==i*i, NULL ); + if( i&1 ) + ca->second.set_value( ~ca->second.value_of() ); + else + (*ca).second.set_value( ~ca->second.value_of() ); + } else { + if( UseKey(i) ) + REPORT("Line %d: key %d missing\n",__LINE__,i); + } + } +}; + +struct FindConst { + static void apply( const MyTable& table, int i ) { + MyTable::const_accessor a; + const MyTable::const_accessor& ca = a; + bool b = table.find( a, MyKey::make(i) ); + ASSERT( b==(table.count(MyKey::make(i))>0), NULL ); + ASSERT( b==!a.empty(), NULL ); + ASSERT( b==UseKey(i), NULL ); + if( b ) { + AssertSameType( &*ca, static_cast<const MyTable::value_type*>(0) ); + ASSERT( ca->second.value_of()==~(i*i), NULL ); + ASSERT( (*ca).second.value_of()==~(i*i), NULL ); + } + } +}; + +tbb::atomic<int> EraseCount; + +struct Erase { + static void apply( MyTable& table, int i ) { + bool b; + if(i&4) { + if(i&8) { + MyTable::const_accessor a; + b = table.find( a, MyKey::make(i) ) && table.erase( a ); + } else { + MyTable::accessor a; + b = table.find( a, MyKey::make(i) ) && table.erase( a ); + } + } else + b = table.erase( MyKey::make(i) ); + if( b ) ++EraseCount; + ASSERT( table.count(MyKey::make(i)) == 0, NULL ); + } +}; + +static const int IE_SIZE = 2; +tbb::atomic<YourTable::size_type> InsertEraseCount[IE_SIZE]; + +struct InsertErase { + static void apply( YourTable& table, int i ) { + if ( i%3 ) { + int key = i%IE_SIZE; + if ( table.insert( std::make_pair(MyKey::make(key), MyData2()) ) ) + ++InsertEraseCount[key]; + } else { + int key = i%IE_SIZE; + if( i&1 ) { + YourTable::accessor res; + if(table.find( res, MyKey::make(key) ) && table.erase( res ) ) + --InsertEraseCount[key]; + } else { + YourTable::const_accessor res; + if(table.find( res, MyKey::make(key) ) && table.erase( res ) ) + --InsertEraseCount[key]; + } + } + } +}; + +// Test for the deadlock discussed at: +// http://softwarecommunity.intel.com/isn/Community/en-US/forums/permalink/30253302/30253302/ShowThread.aspx#30253302 +struct InnerInsert { + static void apply( YourTable& table, int i ) { + YourTable::accessor a1, a2; + if(i&1) __TBB_Yield(); + table.insert( a1, MyKey::make(1) ); + __TBB_Yield(); + table.insert( a2, MyKey::make(1 + (1<<30)) ); // the same chain + table.erase( a2 ); // if erase by key it would lead to deadlock for single thread + } +}; + +#include "harness_barrier.h" +// Test for the misuse of constness +struct FakeExclusive : NoAssign { + Harness::SpinBarrier& barrier; + YourTable& table; + FakeExclusive(Harness::SpinBarrier& b, YourTable&t) : barrier(b), table(t) {} + void operator()( int i ) const { + if(i) { + YourTable::const_accessor real_ca; + // const accessor on non-const table aquired as reader (shared) + ASSERT( table.find(real_ca,MyKey::make(1)), NULL ); + barrier.wait(); // item can be erased + Harness::Sleep(10); // let it enter the erase + real_ca->second.value_of(); // check the state while holding accessor + } else { + YourTable::accessor fake_ca; + const YourTable &const_table = table; + // non-const accessor on const table aquired as reader (shared) + ASSERT( const_table.find(fake_ca,MyKey::make(1)), NULL ); + barrier.wait(); // readers aquired + // can mistakenly remove the item while other readers still refers to it + table.erase( fake_ca ); + } + } +}; + +template<typename Op, typename MyTable> +class TableOperation: NoAssign { + MyTable& my_table; +public: + void operator()( const tbb::blocked_range<int>& range ) const { + for( int i=range.begin(); i!=range.end(); ++i ) + Op::apply(my_table,i); + } + TableOperation( MyTable& table ) : my_table(table) {} +}; + +template<typename Op, typename TableType> +void DoConcurrentOperations( TableType& table, int n, const char* what, int nthread ) { + REMARK("testing %s with %d threads\n",what,nthread); + tbb::tick_count t0 = tbb::tick_count::now(); + tbb::parallel_for( tbb::blocked_range<int>(0,n,100), TableOperation<Op,TableType>(table) ); + tbb::tick_count t1 = tbb::tick_count::now(); + REMARK("time for %s = %g with %d threads\n",what,(t1-t0).seconds(),nthread); +} + +//! Test traversing the table with an iterator. +void TraverseTable( MyTable& table, size_t n, size_t expected_size ) { + REMARK("testing traversal\n"); + size_t actual_size = table.size(); + ASSERT( actual_size==expected_size, NULL ); + size_t count = 0; + bool* array = new bool[n]; + memset( array, 0, n*sizeof(bool) ); + const MyTable& const_table = table; + MyTable::const_iterator ci = const_table.begin(); + for( MyTable::iterator i = table.begin(); i!=table.end(); ++i ) { + // Check iterator + int k = i->first.value_of(); + ASSERT( UseKey(k), NULL ); + ASSERT( (*i).first.value_of()==k, NULL ); + ASSERT( 0<=k && size_t(k)<n, "out of bounds key" ); + ASSERT( !array[k], "duplicate key" ); + array[k] = true; + ++count; + + // Check lower/upper bounds + std::pair<MyTable::iterator, MyTable::iterator> er = table.equal_range(i->first); + std::pair<MyTable::const_iterator, MyTable::const_iterator> cer = const_table.equal_range(i->first); + ASSERT(cer.first == er.first && cer.second == er.second, NULL); + ASSERT(cer.first == i, NULL); + ASSERT(std::distance(cer.first, cer.second) == 1, NULL); + + // Check const_iterator + MyTable::const_iterator cic = ci++; + ASSERT( cic->first.value_of()==k, NULL ); + ASSERT( (*cic).first.value_of()==k, NULL ); + } + ASSERT( ci==const_table.end(), NULL ); + delete[] array; + if( count!=expected_size ) { + REPORT("Line %d: count=%ld but should be %ld\n",__LINE__,long(count),long(expected_size)); + } +} + +typedef tbb::atomic<unsigned char> AtomicByte; + +template<typename RangeType> +struct ParallelTraverseBody: NoAssign { + const size_t n; + AtomicByte* const array; + ParallelTraverseBody( AtomicByte array_[], size_t n_ ) : + n(n_), + array(array_) + {} + void operator()( const RangeType& range ) const { + for( typename RangeType::iterator i = range.begin(); i!=range.end(); ++i ) { + int k = i->first.value_of(); + ASSERT( 0<=k && size_t(k)<n, NULL ); + ++array[k]; + } + } +}; + +void Check( AtomicByte array[], size_t n, size_t expected_size ) { + if( expected_size ) + for( size_t k=0; k<n; ++k ) { + if( array[k] != int(UseKey(k)) ) { + REPORT("array[%d]=%d != %d=UseKey(%d)\n", + int(k), int(array[k]), int(UseKey(k)), int(k)); + ASSERT(false,NULL); + } + } +} + +//! Test travering the tabel with a parallel range +void ParallelTraverseTable( MyTable& table, size_t n, size_t expected_size ) { + REMARK("testing parallel traversal\n"); + ASSERT( table.size()==expected_size, NULL ); + AtomicByte* array = new AtomicByte[n]; + + memset( array, 0, n*sizeof(AtomicByte) ); + MyTable::range_type r = table.range(10); + tbb::parallel_for( r, ParallelTraverseBody<MyTable::range_type>( array, n )); + Check( array, n, expected_size ); + + const MyTable& const_table = table; + memset( array, 0, n*sizeof(AtomicByte) ); + MyTable::const_range_type cr = const_table.range(10); + tbb::parallel_for( cr, ParallelTraverseBody<MyTable::const_range_type>( array, n )); + Check( array, n, expected_size ); + + delete[] array; +} + +void TestInsertFindErase( int nthread ) { + int n=250000; + + // compute m = number of unique keys + int m = 0; + for( int i=0; i<n; ++i ) + m += UseKey(i); + + MyAllocator a; a.items_freed = a.frees = 100; + ASSERT( MyDataCount==0, NULL ); + MyTable table(a); + TraverseTable(table,n,0); + ParallelTraverseTable(table,n,0); + CheckAllocator(table, 0, 100); + + DoConcurrentOperations<Insert,MyTable>(table,n,"insert",nthread); + ASSERT( MyDataCount==m, NULL ); + TraverseTable(table,n,m); + ParallelTraverseTable(table,n,m); + CheckAllocator(table, m, 100); + + DoConcurrentOperations<Find,MyTable>(table,n,"find",nthread); + ASSERT( MyDataCount==m, NULL ); + CheckAllocator(table, m, 100); + + DoConcurrentOperations<FindConst,MyTable>(table,n,"find(const)",nthread); + ASSERT( MyDataCount==m, NULL ); + CheckAllocator(table, m, 100); + + EraseCount=0; + DoConcurrentOperations<Erase,MyTable>(table,n,"erase",nthread); + ASSERT( EraseCount==m, NULL ); + ASSERT( MyDataCount==0, NULL ); + TraverseTable(table,n,0); + CheckAllocator(table, m, m+100); + + bad_hashing = true; + table.clear(); + bad_hashing = false; + + if(nthread > 1) { + YourTable ie_table; + for( int i=0; i<IE_SIZE; ++i ) + InsertEraseCount[i] = 0; + DoConcurrentOperations<InsertErase,YourTable>(ie_table,n/2,"insert_erase",nthread); + for( int i=0; i<IE_SIZE; ++i ) + ASSERT( InsertEraseCount[i]==ie_table.count(MyKey::make(i)), NULL ); + + DoConcurrentOperations<InnerInsert,YourTable>(ie_table,2000,"inner insert",nthread); + Harness::SpinBarrier barrier(nthread); + REMARK("testing erase on fake exclusive accessor\n"); + NativeParallelFor( nthread, FakeExclusive(barrier, ie_table)); + } +} + +volatile int Counter; + +class AddToTable: NoAssign { + MyTable& my_table; + const int my_nthread; + const int my_m; +public: + AddToTable( MyTable& table, int nthread, int m ) : my_table(table), my_nthread(nthread), my_m(m) {} + void operator()( int ) const { + for( int i=0; i<my_m; ++i ) { + // Busy wait to synchronize threads + int j = 0; + while( Counter<i ) { + if( ++j==1000000 ) { + // If Counter<i after a million iterations, then we almost surely have + // more logical threads than physical threads, and should yield in + // order to let suspended logical threads make progress. + j = 0; + __TBB_Yield(); + } + } + // Now all threads attempt to simultaneously insert a key. + int k; + { + MyTable::accessor a; + MyKey key = MyKey::make(i); + if( my_table.insert( a, key ) ) + a->second.set_value( 1 ); + else + a->second.set_value( a->second.value_of()+1 ); + k = a->second.value_of(); + } + if( k==my_nthread ) + Counter=i+1; + } + } +}; + +class RemoveFromTable: NoAssign { + MyTable& my_table; + const int my_nthread; + const int my_m; +public: + RemoveFromTable( MyTable& table, int nthread, int m ) : my_table(table), my_nthread(nthread), my_m(m) {} + void operator()(int) const { + for( int i=0; i<my_m; ++i ) { + bool b; + if(i&4) { + if(i&8) { + MyTable::const_accessor a; + b = my_table.find( a, MyKey::make(i) ) && my_table.erase( a ); + } else { + MyTable::accessor a; + b = my_table.find( a, MyKey::make(i) ) && my_table.erase( a ); + } + } else + b = my_table.erase( MyKey::make(i) ); + if( b ) ++EraseCount; + } + } +}; + +//! Test for memory leak in concurrent_hash_map (TR #153). +void TestConcurrency( int nthread ) { + REMARK("testing multiple insertions/deletions of same key with %d threads\n", nthread); + { + ASSERT( MyDataCount==0, NULL ); + MyTable table; + const int m = 1000; + Counter = 0; + tbb::tick_count t0 = tbb::tick_count::now(); + NativeParallelFor( nthread, AddToTable(table,nthread,m) ); + tbb::tick_count t1 = tbb::tick_count::now(); + REMARK("time for %u insertions = %g with %d threads\n",unsigned(MyDataCount),(t1-t0).seconds(),nthread); + ASSERT( MyDataCount==m, "memory leak detected" ); + + EraseCount = 0; + t0 = tbb::tick_count::now(); + NativeParallelFor( nthread, RemoveFromTable(table,nthread,m) ); + t1 = tbb::tick_count::now(); + REMARK("time for %u deletions = %g with %d threads\n",unsigned(EraseCount),(t1-t0).seconds(),nthread); + ASSERT( MyDataCount==0, "memory leak detected" ); + ASSERT( EraseCount==m, "return value of erase() is broken" ); + + CheckAllocator(table, m, m, /*exact*/nthread <= 1); + } + ASSERT( MyDataCount==0, "memory leak detected" ); +} + +void TestTypes() { + AssertSameType( static_cast<MyTable::key_type*>(0), static_cast<MyKey*>(0) ); + AssertSameType( static_cast<MyTable::mapped_type*>(0), static_cast<MyData*>(0) ); + AssertSameType( static_cast<MyTable::value_type*>(0), static_cast<std::pair<const MyKey,MyData>*>(0) ); + AssertSameType( static_cast<MyTable::accessor::value_type*>(0), static_cast<MyTable::value_type*>(0) ); + AssertSameType( static_cast<MyTable::const_accessor::value_type*>(0), static_cast<const MyTable::value_type*>(0) ); + AssertSameType( static_cast<MyTable::size_type*>(0), static_cast<size_t*>(0) ); + AssertSameType( static_cast<MyTable::difference_type*>(0), static_cast<ptrdiff_t*>(0) ); +} + +template<typename Iterator, typename T> +void TestIteratorTraits() { + AssertSameType( static_cast<typename Iterator::difference_type*>(0), static_cast<ptrdiff_t*>(0) ); + AssertSameType( static_cast<typename Iterator::value_type*>(0), static_cast<T*>(0) ); + AssertSameType( static_cast<typename Iterator::pointer*>(0), static_cast<T**>(0) ); + AssertSameType( static_cast<typename Iterator::iterator_category*>(0), static_cast<std::forward_iterator_tag*>(0) ); + T x; + typename Iterator::reference xr = x; + typename Iterator::pointer xp = &x; + ASSERT( &xr==xp, NULL ); +} + +template<typename Iterator1, typename Iterator2> +void TestIteratorAssignment( Iterator2 j ) { + Iterator1 i(j), k; + ASSERT( i==j, NULL ); ASSERT( !(i!=j), NULL ); + k = j; + ASSERT( k==j, NULL ); ASSERT( !(k!=j), NULL ); +} + +template<typename Range1, typename Range2> +void TestRangeAssignment( Range2 r2 ) { + Range1 r1(r2); r1 = r2; +} +//------------------------------------------------------------------------ +// Test for copy constructor and assignment +//------------------------------------------------------------------------ + +template<typename MyTable> +static void FillTable( MyTable& x, int n ) { + for( int i=1; i<=n; ++i ) { + MyKey key( MyKey::make(-i) ); // hash values must not be specified in direct order + typename MyTable::accessor a; + bool b = x.insert(a,key); + ASSERT(b, NULL); + a->second.set_value( i*i ); + } +} + +template<typename MyTable> +static void CheckTable( const MyTable& x, int n ) { + ASSERT( x.size()==size_t(n), "table is different size than expected" ); + ASSERT( x.empty()==(n==0), NULL ); + ASSERT( x.size()<=x.max_size(), NULL ); + for( int i=1; i<=n; ++i ) { + MyKey key( MyKey::make(-i) ); + typename MyTable::const_accessor a; + bool b = x.find(a,key); + ASSERT( b, NULL ); + ASSERT( a->second.value_of()==i*i, NULL ); + } + int count = 0; + int key_sum = 0; + for( typename MyTable::const_iterator i(x.begin()); i!=x.end(); ++i ) { + ++count; + key_sum += -i->first.value_of(); + } + ASSERT( count==n, NULL ); + ASSERT( key_sum==n*(n+1)/2, NULL ); +} + +static void TestCopy() { + REMARK("testing copy\n"); + MyTable t1; + for( int i=0; i<10000; i=(i<100 ? i+1 : i*3) ) { + MyDataCount = 0; + + FillTable(t1,i); + // Do not call CheckTable(t1,i) before copying, it enforces rehashing + + MyTable t2(t1); + // Check that copy constructor did not mangle source table. + CheckTable(t1,i); + swap(t1, t2); + CheckTable(t1,i); + ASSERT( !(t1 != t2), NULL ); + + // Clear original table + t2.clear(); + swap(t2, t1); + CheckTable(t1,0); + + // Verify that copy of t1 is correct, even after t1 is cleared. + CheckTable(t2,i); + t2.clear(); + t1.swap( t2 ); + CheckTable(t1,0); + CheckTable(t2,0); + ASSERT( MyDataCount==0, "data leak?" ); + } +} + +void TestAssignment() { + REMARK("testing assignment\n"); + for( int i=0; i<1000; i=(i<30 ? i+1 : i*5) ) { + for( int j=0; j<1000; j=(j<30 ? j+1 : j*7) ) { + MyTable t1; + MyTable t2; + FillTable(t1,i); + FillTable(t2,j); + ASSERT( (t1 == t2) == (i == j), NULL ); + CheckTable(t2,j); + + MyTable& tref = t2=t1; + ASSERT( &tref==&t2, NULL ); + ASSERT( t1 == t2, NULL ); + CheckTable(t1,i); + CheckTable(t2,i); + + t1.clear(); + CheckTable(t1,0); + CheckTable(t2,i); + ASSERT( MyDataCount==i, "data leak?" ); + + t2.clear(); + CheckTable(t1,0); + CheckTable(t2,0); + ASSERT( MyDataCount==0, "data leak?" ); + } + } +} + +void TestIteratorsAndRanges() { + REMARK("testing iterators compliance\n"); + TestIteratorTraits<MyTable::iterator,MyTable::value_type>(); + TestIteratorTraits<MyTable::const_iterator,const MyTable::value_type>(); + + MyTable v; + MyTable const &u = v; + + TestIteratorAssignment<MyTable::const_iterator>( u.begin() ); + TestIteratorAssignment<MyTable::const_iterator>( v.begin() ); + TestIteratorAssignment<MyTable::iterator>( v.begin() ); + // doesn't compile as expected: TestIteratorAssignment<typename V::iterator>( u.begin() ); + + // check for non-existing + ASSERT(v.equal_range(MyKey::make(-1)) == std::make_pair(v.end(), v.end()), NULL); + ASSERT(u.equal_range(MyKey::make(-1)) == std::make_pair(u.end(), u.end()), NULL); + + REMARK("testing ranges compliance\n"); + TestRangeAssignment<MyTable::const_range_type>( u.range() ); + TestRangeAssignment<MyTable::const_range_type>( v.range() ); + TestRangeAssignment<MyTable::range_type>( v.range() ); + // doesn't compile as expected: TestRangeAssignment<typename V::range_type>( u.range() ); + + REMARK("testing construction and insertion from iterators range\n"); + FillTable( v, 1000 ); + MyTable2 t(v.begin(), v.end()); + v.rehash(); + CheckTable(t, 1000); + t.insert(v.begin(), v.end()); // do nothing + CheckTable(t, 1000); + t.clear(); + t.insert(v.begin(), v.end()); // restore + CheckTable(t, 1000); + + REMARK("testing comparison\n"); + typedef tbb::concurrent_hash_map<MyKey,MyData2,YourHashCompare,MyAllocator> YourTable1; + typedef tbb::concurrent_hash_map<MyKey,MyData2,YourHashCompare> YourTable2; + YourTable1 t1; + FillTable( t1, 10 ); + CheckTable(t1, 10 ); + YourTable2 t2(t1.begin(), t1.end()); + MyKey key( MyKey::make(-5) ); MyData2 data; + ASSERT(t2.erase(key), NULL); + YourTable2::accessor a; + ASSERT(t2.insert(a, key), NULL); + data.set_value(0); a->second = data; + ASSERT( t1 != t2, NULL); + data.set_value(5*5); a->second = data; + ASSERT( t1 == t2, NULL); +} + +void TestRehash() { + REMARK("testing rehashing\n"); + MyTable w; + w.insert( std::make_pair(MyKey::make(-5), MyData()) ); + w.rehash(); // without this, assertion will fail + MyTable::iterator it = w.begin(); + int i = 0; // check for non-rehashed buckets + for( ; it != w.end(); i++ ) + w.count( (it++)->first ); + ASSERT( i == 1, NULL ); + for( i=0; i<1000; i=(i<29 ? i+1 : i*2) ) { + for( int j=max(256+i, i*2); j<10000; j*=3 ) { + MyTable v; + FillTable( v, i ); + ASSERT(int(v.size()) == i, NULL); + ASSERT(int(v.bucket_count()) <= j, NULL); + v.rehash( j ); + ASSERT(int(v.bucket_count()) >= j, NULL); + CheckTable( v, i ); + } + } +} + +#if TBB_USE_EXCEPTIONS +void TestExceptions() { + typedef local_counting_allocator<tbb::tbb_allocator<MyData2> > allocator_t; + typedef tbb::concurrent_hash_map<MyKey,MyData2,MyHashCompare,allocator_t> ThrowingTable; + enum methods { + zero_method = 0, + ctor_copy, op_assign, op_insert, + all_methods + }; + REMARK("testing exception-safety guarantees\n"); + ThrowingTable src; + FillTable( src, 1000 ); + ASSERT( MyDataCount==1000, NULL ); + + try { + for(int t = 0; t < 2; t++) // exception type + for(int m = zero_method+1; m < all_methods; m++) + { + allocator_t a; + if(t) MyDataCountLimit = 101; + else a.set_limits(101); + ThrowingTable victim(a); + MyDataCount = 0; + + try { + switch(m) { + case ctor_copy: { + ThrowingTable acopy(src, a); + } break; + case op_assign: { + victim = src; + } break; + case op_insert: { + FillTable( victim, 1000 ); + } break; + default:; + } + ASSERT(false, "should throw an exception"); + } catch(std::bad_alloc &e) { + MyDataCountLimit = 0; + size_t size = victim.size(); + switch(m) { + case op_assign: + ASSERT( MyDataCount==100, "data leak?" ); + ASSERT( size>=100, NULL ); + CheckAllocator(victim, 100+t, t); + case ctor_copy: + CheckTable(src, 1000); + break; + case op_insert: + ASSERT( size==size_t(100-t), NULL ); + ASSERT( MyDataCount==100-t, "data leak?" ); + CheckTable(victim, 100-t); + CheckAllocator(victim, 100, t); + break; + + default:; // nothing to check here + } + REMARK("Exception %d: %s\t- ok ()\n", m, e.what()); + } + catch ( ... ) { + ASSERT ( __TBB_EXCEPTION_TYPE_INFO_BROKEN, "Unrecognized exception" ); + } + } + } catch(...) { + ASSERT(false, "unexpected exception"); + } + src.clear(); MyDataCount = 0; +} +#endif /* TBB_USE_EXCEPTIONS */ + +//------------------------------------------------------------------------ +// Test driver +//------------------------------------------------------------------------ + +#include "tbb/task_scheduler_init.h" + +int TestMain () { + if( MinThread<0 ) { + REPORT("ERROR: must use at least one thread\n"); + exit(1); + } + if( MaxThread<2 ) MaxThread=2; + + // Do serial tests + TestTypes(); + TestCopy(); + TestRehash(); + TestAssignment(); + TestIteratorsAndRanges(); +#if TBB_USE_EXCEPTIONS + TestExceptions(); +#endif /* TBB_USE_EXCEPTIONS */ + + // Do concurrency tests. + for( int nthread=MinThread; nthread<=MaxThread; ++nthread ) { + tbb::task_scheduler_init init( nthread ); + TestInsertFindErase( nthread ); + TestConcurrency( nthread ); + } + // check linking + if(bad_hashing) { //should be false + tbb::internal::runtime_warning("none\nERROR: it must not be executed"); + } + + return Harness::Done; +} diff --git a/src/tbb/src/test/test_concurrent_lru_cache.cpp b/src/tbb/src/test/test_concurrent_lru_cache.cpp new file mode 100644 index 0000000..5361fe0 --- /dev/null +++ b/src/tbb/src/test/test_concurrent_lru_cache.cpp @@ -0,0 +1,412 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if _MSC_VER + #pragma warning (disable: 4503) // Suppress "decorated name length exceeded, name was truncated" warning +#endif + +#include "harness_test_cases_framework.h" +#include "harness.h" +#include "harness_barrier.h" + +#include <utility> + +#ifdef TEST_COARSE_GRAINED_LOCK_IMPLEMENTATION + #include "../perf/coarse_grained_raii_lru_cache.h" + #define selected_raii_lru_cache_impl coarse_grained_raii_lru_cache +#else + #define TBB_PREVIEW_CONCURRENT_LRU_CACHE 1 + #include "tbb/concurrent_lru_cache.h" + #define selected_raii_lru_cache_impl tbb::concurrent_lru_cache +#endif + +#include "tbb/task_scheduler_init.h" + +namespace helpers{ + // Busy work and calibration helpers + unsigned int one_us_iters = 345; // default value + + // if user wants to calibrate to microseconds on particular machine, call + // this at beginning of program; sets one_us_iters to number of iters to + // busy_wait for approx. 1 us +// void calibrate_busy_wait() { +// tbb::tick_count t0, t1; +// +// t0 = tbb::tick_count::now(); +// for (volatile unsigned int i=0; i<1000000; ++i) continue; +// t1 = tbb::tick_count::now(); +// +// one_us_iters = (unsigned int)((1000000.0/(t1-t0).seconds())*0.000001); +// printf("one_us_iters: %d\n", one_us_iters); +// } + void busy_wait(int us) + { + unsigned int iter = us*one_us_iters; + for (volatile unsigned int i=0; i<iter; ++i) continue; + } +} +namespace helpers{ + template<class T> void ignore( const T& ) { } + //TODO: add test cases for prevent_optimizng_out function + template<typename type> + void prevent_optimizng_out(type volatile const& s){ + volatile const type* dummy = &s; + ignore(dummy); + } + + struct empty_fixture{}; + + template<typename argument_type> + struct native_for_concurrent_op_repeated:NoAssign{ + typedef void (*test_function_pointer_type)(argument_type&); + + argument_type& m_counter_ref; + test_function_pointer_type m_test_function_pointer_type; + std::size_t m_repeat_number; + native_for_concurrent_op_repeated(argument_type& counter_ref, test_function_pointer_type action, std::size_t repeat_number) + :m_counter_ref(counter_ref), m_test_function_pointer_type(action), m_repeat_number(repeat_number) + {} + template <typename ignored_parameter_type> + void operator()(ignored_parameter_type const&)const{ + for (size_t i=0; i<m_repeat_number;++i){ + m_test_function_pointer_type(m_counter_ref); + } + } + + }; + + template <typename counter_type = size_t> + struct object_instanses_counting_type{ + counter_type * m_p_count; + object_instanses_counting_type(): m_p_count (new counter_type){*m_p_count =1; } //to overcome absense of constructor in tbb::atomic + ~object_instanses_counting_type(){ if (! --(*m_p_count)){delete(m_p_count);}} + object_instanses_counting_type(object_instanses_counting_type const& other): m_p_count(other.m_p_count){ + ++(*m_p_count); + } + object_instanses_counting_type& operator=(object_instanses_counting_type other){ + std::swap(this->m_p_count,other.m_p_count); + return *this; + } + size_t instances_count()const {return *m_p_count;} + }; + typedef object_instanses_counting_type<> object_instanses_counting_serial_type; + typedef object_instanses_counting_type<tbb::atomic<std::size_t> > object_instanses_counting_concurent_type; + + namespace object_instanses_counting_type_test_cases{ + namespace serial_tests{ + TEST_CASE_WITH_FIXTURE(test_object_instanses_counting_type_creation,empty_fixture){ + ASSERT(object_instanses_counting_serial_type().instances_count()==1,"newly created instance by definition has instances_count equal to 1"); + } + TEST_CASE_WITH_FIXTURE(test_object_instanses_counting_type_copy,empty_fixture){ + object_instanses_counting_serial_type source; + ASSERT(object_instanses_counting_serial_type(source).instances_count()==2,"copy should increase ref count"); + } + TEST_CASE_WITH_FIXTURE(test_object_instanses_counting_type_assignment,empty_fixture){ + object_instanses_counting_serial_type source; + object_instanses_counting_serial_type assigned; + assigned = source; + ASSERT(source.instances_count()==2,"assign should increase ref count"); + ASSERT(assigned.instances_count()==2,"assign should increase ref count"); + } + } + namespace concurent_tests{ + typedef native_for_concurrent_op_repeated<object_instanses_counting_concurent_type> native_for_concurrent_op; + + struct native_for_single_op_repeated_fixture{ + object_instanses_counting_concurent_type source; + void run_native_for_and_assert_source_is_unique(native_for_concurrent_op::test_function_pointer_type operation,const char* msg){ + //TODO: refactor number of threads into separate fixture + const size_t number_of_threads = min(4,tbb::task_scheduler_init::default_num_threads()); + const size_t repeats_per_thread = 1000000; + + NativeParallelFor(number_of_threads , native_for_concurrent_op(source,operation,repeats_per_thread)); + ASSERT(source.instances_count()==1,msg); + } + + }; + TEST_CASE_WITH_FIXTURE(test_object_instanses_counting_type_copy,native_for_single_op_repeated_fixture){ + struct _{ static void copy(object_instanses_counting_concurent_type& source){ + object_instanses_counting_concurent_type copy(source); + helpers::prevent_optimizng_out(copy); + }}; + run_native_for_and_assert_source_is_unique(&_::copy,"reference counting during copy construction/destruction is not thread safe ?"); + } + TEST_CASE_WITH_FIXTURE(test_object_instanses_counting_type_assignment,native_for_single_op_repeated_fixture){ + struct _{ static void assign(object_instanses_counting_concurent_type& source){ + object_instanses_counting_concurent_type assigned; + assigned = source; + helpers::prevent_optimizng_out(assigned); + }}; + run_native_for_and_assert_source_is_unique(&_::assign,"reference counting during assigning/destruction is not thread safe ?"); + } + + } +} +} + +struct get_lru_cache_type{ + + template< typename parameter1, typename parameter2, typename parameter3=void> + struct apply{ + typedef selected_raii_lru_cache_impl<parameter1,parameter2,parameter3> type; + }; + template< typename parameter1, typename parameter2> + struct apply<parameter1,parameter2,void>{ + typedef selected_raii_lru_cache_impl<parameter1,parameter2> type; + }; + +}; + +namespace serial_tests{ + using namespace helpers; + namespace usability{ + namespace compilation_only{ + TEST_CASE_WITH_FIXTURE(test_creation_and_use_interface,empty_fixture){ + struct dummy_function{static int _(int key){return key;}}; + typedef get_lru_cache_type::apply<int,int>::type cache_type; + size_t number_of_lru_history_items = 8; + cache_type cache((&dummy_function::_),(number_of_lru_history_items)); + int dummy_key=0; + cache_type::handle h = cache[dummy_key]; + int value = h.value(); + (void)value; + } + } + namespace behaviour{ + namespace helpers{ + template <size_t id> struct tag{}; + template< typename tag, typename value_and_key_type> + struct call_counting_function{ + static int calls_count; + static value_and_key_type _(value_and_key_type key){ + ++calls_count; + return key; + } + }; + template< typename tag, typename value_and_key_type> + int call_counting_function<tag,value_and_key_type>::calls_count = 0; + + + } + TEST_CASE_WITH_FIXTURE(test_cache_returns_only_values_from_value_function,empty_fixture){ + struct dummy_function{static int _(int /*key*/){return 0xDEADBEEF;}}; + typedef get_lru_cache_type::apply<int,int>::type cache_type; + size_t number_of_lru_history_items = 8; + int dummy_key=1; + cache_type cache((&dummy_function::_),(number_of_lru_history_items)); + ASSERT(dummy_function::_(dummy_key)==cache[dummy_key].value(),"cache operator() must return only values obtained from value_function "); + } + + TEST_CASE_WITH_FIXTURE(test_value_function_called_only_on_cache_miss,empty_fixture){ + typedef helpers::tag<__LINE__> tag; + typedef helpers::call_counting_function<tag,int> function; + typedef get_lru_cache_type::apply<int,int>::type cache_type; + size_t number_of_lru_history_items = 8; + cache_type cache((&function::_),(number_of_lru_history_items)); + + int dummy_key=0; + cache[dummy_key]; + cache[dummy_key]; + ASSERT(function::calls_count==1,"value function should be called only on a cache miss"); + } + } + namespace helpers{ + using ::helpers::object_instanses_counting_serial_type; + } + namespace helpers{ + template<typename value_type> + struct clonning_function:NoAssign{ + value_type& m_ref_original; + clonning_function(value_type& ref_original):m_ref_original(ref_original){} + template<typename key_type> + value_type operator()(key_type)const{ return m_ref_original;} + }; + } + struct instance_counting_fixture{ + static const size_t number_of_lru_history_items = 8; + + typedef helpers::clonning_function<helpers::object_instanses_counting_serial_type> cloner_type; + typedef get_lru_cache_type::apply<size_t,helpers::object_instanses_counting_serial_type,cloner_type>::type cache_type; + helpers::object_instanses_counting_serial_type source; + cloner_type cloner; + cache_type cache; + + instance_counting_fixture():cloner((source)),cache(cloner,number_of_lru_history_items){} + }; + + TEST_CASE_WITH_FIXTURE(test_cache_stores_unused_objects,instance_counting_fixture){ + for (size_t i=0;i<number_of_lru_history_items;++i){ + cache[i]; + } + ASSERT(source.instances_count()> 1,"cache should store some unused objects "); + } + + TEST_CASE_WITH_FIXTURE(test_cache_stores_no_more_then_X_number_of_unused_objects,instance_counting_fixture){ + for (size_t i=0;i<number_of_lru_history_items+1;++i){ + cache[i]; + } + ASSERT(source.instances_count()== number_of_lru_history_items+1,"cache should respect number of stored unused objects to number passed in constructor"); + } + + namespace helpers{ + template< typename key_type, typename value_type> + struct map_searcher:NoAssign{ + typedef std::map<key_type,value_type> map_type; + map_type & m_map_ref; + map_searcher(map_type & map_ref): m_map_ref(map_ref) {} + value_type& operator()(key_type k){ + typename map_type::iterator it =m_map_ref.find(k); + if (it==m_map_ref.end()){ + it = m_map_ref.insert(it,std::make_pair(k,value_type())); + } + return it->second; + } + }; + } + + struct filled_instance_counting_fixture_with_external_map{ + static const size_t number_of_lru_history_items = 8; + + typedef helpers::map_searcher<size_t,helpers::object_instanses_counting_serial_type> map_searcher_type; + typedef map_searcher_type::map_type objects_map_type; + typedef get_lru_cache_type::apply<size_t,helpers::object_instanses_counting_serial_type,map_searcher_type>::type cache_type; + map_searcher_type::map_type objects_map; + cache_type cache; + filled_instance_counting_fixture_with_external_map():cache(map_searcher_type(objects_map),number_of_lru_history_items){} + bool is_evicted(size_t k){ + objects_map_type::iterator it =objects_map.find(k); + ASSERT(it!=objects_map.end(),"no value for key - error in test logic ?"); + return it->second.instances_count()==1; + } + void fill_up_cache(size_t lower_bound, size_t upper_bound){ + for (size_t i=lower_bound;i<upper_bound;++i){ + cache[i]; + } + } + }; + + TEST_CASE_WITH_FIXTURE(test_cache_should_evict_unused_objects_lru_order,filled_instance_counting_fixture_with_external_map){ + ASSERT(number_of_lru_history_items > 2,"incorrect test setup"); + fill_up_cache(0,number_of_lru_history_items); + //heat up first element + cache[0]; + //cause eviction + cache[number_of_lru_history_items]; + ASSERT(is_evicted(1) && !is_evicted(0),"cache should evict items in lru order"); + } + + TEST_CASE_WITH_FIXTURE(test_live_handler_object_prevents_item_from_eviction,filled_instance_counting_fixture_with_external_map){ + cache_type::handle h = cache[0]; + //cause eviction + fill_up_cache(1,number_of_lru_history_items+2); + ASSERT(is_evicted(1) && !is_evicted(0),"cache should not evict items in use"); + } + TEST_CASE_WITH_FIXTURE(test_live_handler_object_is_ref_counted,filled_instance_counting_fixture_with_external_map){ + cache_type::handle h = cache[0]; + { + cache_type::handle h = cache[0]; + } + //cause eviction + fill_up_cache(1,number_of_lru_history_items+2); + ASSERT(is_evicted(1) && !is_evicted(0),"cache should not evict items in use"); + } + } +} + + +namespace concurency_tests{ + namespace helpers{ + using namespace ::helpers; + } + namespace helpers{ + //key_type must be convertible to array index + template< typename key_type, typename value_type, size_t array_size> + struct array_searcher:NoAssign{ + typedef value_type array_type[array_size]; + array_type const& m_array_ref; + array_searcher(array_type const& array_ref): m_array_ref(array_ref) {} + const value_type& operator()(key_type k)const{ + size_t index = k; + ASSERT(k < array_size,"incorrect test setup"); + return m_array_ref[index]; + } + }; + } + + struct filled_instance_counting_fixture_with_external_array{ + static const size_t number_of_lru_history_items = 8; + static const size_t array_size = 16*number_of_lru_history_items; + + typedef helpers::array_searcher<size_t,helpers::object_instanses_counting_concurent_type,array_size> array_searcher_type; + typedef array_searcher_type::array_type objects_array_type; + typedef get_lru_cache_type::apply<size_t,helpers::object_instanses_counting_concurent_type,array_searcher_type>::type cache_type; + array_searcher_type::array_type objects_array; + cache_type cache; + filled_instance_counting_fixture_with_external_array():cache(array_searcher_type(objects_array),number_of_lru_history_items){} + bool is_evicted(size_t k)const{ + return array_searcher_type(objects_array)(k).instances_count()==1; + } + void fill_up_cache(size_t lower_bound, size_t upper_bound){ + for (size_t i=lower_bound;i<upper_bound;++i){ + cache[i]; + } + } + size_t number_of_non_evicted_from_cache()const{ + size_t result=0; + for (size_t i=0; i<array_size; ++i){ + if (!this->is_evicted(i)){ + ++result; + } + } + return result; + } + }; + + + //TODO: make this more reproducible + //TODO: split this test case in two parts + TEST_CASE_WITH_FIXTURE(correctness_of_braces_and_hanlde_destructor,filled_instance_counting_fixture_with_external_array){ + typedef correctness_of_braces_and_hanlde_destructor self_type; + struct _{static void use_cache(self_type& tc){ + for (size_t i=0;i<array_size;++i){ + cache_type::handle h=tc.cache[i]; + helpers::prevent_optimizng_out(h.value()); + } + + }}; + static const size_t repeat_number = 2; + static const size_t number_of_threads = 8 * tbb::task_scheduler_init::default_num_threads(); //have 8x over subscription + static const size_t repeats_per_thread = 4; + + for (size_t i=0; i < repeat_number; i++){ + NativeParallelFor(number_of_threads,helpers::native_for_concurrent_op_repeated<self_type>(*this,&_::use_cache,repeats_per_thread)); + fill_up_cache(0,array_size); + ASSERT(number_of_non_evicted_from_cache()==number_of_lru_history_items,"thread safety is broken for cache "); + } + } +} diff --git a/src/tbb/src/test/test_concurrent_monitor.cpp b/src/tbb/src/test/test_concurrent_monitor.cpp new file mode 100644 index 0000000..bb481fb --- /dev/null +++ b/src/tbb/src/test/test_concurrent_monitor.cpp @@ -0,0 +1,374 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/concurrent_monitor.h" +#include "tbb/atomic.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/parallel_for.h" +#include "tbb/blocked_range.h" +#include "harness.h" +#if _WIN32||_WIN64 +#include "tbb/dynamic_link.cpp" +#endif + +#include "tbb/semaphore.cpp" +#include "tbb/concurrent_monitor.cpp" + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // Workaround for overzealous compiler warnings + // Suppress compiler warning about constant conditional expression + #pragma warning (disable: 4127) +#endif + +using namespace tbb; + +//! Queuing lock with concurrent_monitor; to test concurrent_monitor::notify( Predicate p ) +class QueuingMutex { +public: + //! Construct unacquired mutex. + QueuingMutex() { q_tail = NULL; } + + //! The scoped locking pattern + class ScopedLock: internal::no_copy { + void Initialize() { mutex = NULL; } + public: + ScopedLock() {Initialize();} + ScopedLock( QueuingMutex& m, size_t test_mode ) { Initialize(); Acquire(m,test_mode); } + ~ScopedLock() { if( mutex ) Release(); } + void Acquire( QueuingMutex& m, size_t test_mode ); + void Release(); + void SleepPerhaps(); + + private: + QueuingMutex* mutex; + ScopedLock* next; + uintptr_t going; + internal::concurrent_monitor::thread_context thr_ctx; + }; + + friend class ScopedLock; +private: + //! The last competitor requesting the lock + atomic<ScopedLock*> q_tail; + internal::concurrent_monitor waitq; +}; + +struct PredicateEq { + uintptr_t p; + PredicateEq( uintptr_t p_ ) : p(p_) {} + bool operator() ( uintptr_t v ) const {return p==v;} +}; + +struct QueuingMutex_Context { + const QueuingMutex::ScopedLock* lck; + QueuingMutex_Context( QueuingMutex::ScopedLock* l_ ) : lck(l_) {} + uintptr_t operator()() { return uintptr_t(lck); } +}; + +struct QueuingMutex_Until : NoAssign { + uintptr_t& flag; + QueuingMutex_Until( uintptr_t& f_ ) : flag(f_) {} + bool operator()() { return flag!=0ul; } +}; + +//! A method to acquire QueuingMutex lock +void QueuingMutex::ScopedLock::Acquire( QueuingMutex& m, size_t test_mode ) +{ + // Must set all fields before the fetch_and_store, because once the + // fetch_and_store executes, *this becomes accessible to other threads. + mutex = &m; + next = NULL; + going = 0; + + // The fetch_and_store must have release semantics, because we are + // "sending" the fields initialized above to other processors. + ScopedLock* pred = m.q_tail.fetch_and_store<tbb::release>(this); + if( pred ) { +#if TBB_USE_ASSERT + __TBB_control_consistency_helper(); // on "m.q_tail" + ASSERT( !pred->next, "the predecessor has another successor!"); +#endif + pred->next = this; + for( int i=0; i<16; ++i ) { + if( going!=0ul ) break; + __TBB_Yield(); + } + int x = int( test_mode%3 ); + switch( x ) { + case 0: + mutex->waitq.wait( QueuingMutex_Until(going), QueuingMutex_Context(this) ); + break; +#if __TBB_LAMBDAS_PRESENT + case 1: + mutex->waitq.wait( [&](){ return going!=0ul; }, [=]() { return (uintptr_t)this; } ); + break; +#endif + default: + SleepPerhaps(); + break; + } + } + + // Acquire critical section indirectly from previous owner or directly from predecessor. + __TBB_control_consistency_helper(); // on either "m.q_tail" or "going" +} + +//! A method to release QueuingMutex lock +void QueuingMutex::ScopedLock::Release( ) +{ + if( !next ) { + if( this == mutex->q_tail.compare_and_swap<tbb::release>(NULL, this) ) { + // this was the only item in the queue, and the queue is now empty. + goto done; + } + // Someone in the queue + spin_wait_while_eq( next, (ScopedLock*)0 ); + } + __TBB_store_with_release(next->going, 1); + mutex->waitq.notify( PredicateEq(uintptr_t(next)) ); +done: + Initialize(); +} + +//! Yield and block; go to sleep +void QueuingMutex::ScopedLock::SleepPerhaps() +{ + bool slept = false; + internal::concurrent_monitor& mq = mutex->waitq; + mq.prepare_wait( thr_ctx, uintptr_t(this) ); + while( going==0ul ) { + if( (slept=mq.commit_wait( thr_ctx ))==true && going!=0ul ) + break; + slept = false; + mq.prepare_wait( thr_ctx, uintptr_t(this) ); + } + if( !slept ) + mq.cancel_wait( thr_ctx ); +} + +// Spin lock with concurrent_monitor; to test concurrent_monitor::notify_all() and concurrent_monitor::notify() +class SpinMutex { +public: + //! Construct unacquired mutex. + SpinMutex() : toggle(false) { flag = 0; } + + //! The scoped locking pattern + class ScopedLock: internal::no_copy { + void Initialize() { mutex = NULL; } + public: + ScopedLock() {Initialize();} + ScopedLock( SpinMutex& m, size_t test_mode ) { Initialize(); Acquire(m,test_mode); } + ~ScopedLock() { if( mutex ) Release(); } + void Acquire( SpinMutex& m, size_t test_mode ); + void Release(); + void SleepPerhaps(); + + private: + SpinMutex* mutex; + internal::concurrent_monitor::thread_context thr_ctx; + }; + + friend class ScopedLock; + friend struct SpinMutex_Until; +private: + tbb::atomic<unsigned> flag; + bool toggle; + internal::concurrent_monitor waitq; +}; + +struct SpinMutex_Context { + const SpinMutex::ScopedLock* lck; + SpinMutex_Context( SpinMutex::ScopedLock* l_ ) : lck(l_) {} + uintptr_t operator()() { return uintptr_t(lck); } +}; + +struct SpinMutex_Until { + const SpinMutex* mtx; + SpinMutex_Until( SpinMutex* m_ ) : mtx(m_) {} + bool operator()() { return mtx->flag==0; } +}; + +//! A method to acquire SpinMutex lock +void SpinMutex::ScopedLock::Acquire( SpinMutex& m, size_t test_mode ) +{ + mutex = &m; +retry: + if( m.flag.compare_and_swap( 1, 0 )!=0 ) { + int x = int( test_mode%3 ); + switch( x ) { + case 0: + mutex->waitq.wait( SpinMutex_Until(mutex), SpinMutex_Context(this) ); + break; +#if __TBB_LAMBDAS_PRESENT + case 1: + mutex->waitq.wait( [&](){ return mutex->flag==0; }, [=]() { return (uintptr_t)this; } ); + break; +#endif + default: + SleepPerhaps(); + break; + } + goto retry; + } +} + +//! A method to release SpinMutex lock +void SpinMutex::ScopedLock::Release() +{ + bool old_toggle = mutex->toggle; + mutex->toggle = !mutex->toggle; + mutex->flag = 0; + if( old_toggle ) + mutex->waitq.notify_one(); + else + mutex->waitq.notify_all(); +} + +//! Yield and block; go to sleep +void SpinMutex::ScopedLock::SleepPerhaps() +{ + bool slept = false; + internal::concurrent_monitor& mq = mutex->waitq; + mq.prepare_wait( thr_ctx, uintptr_t(this) ); + while( mutex->flag ) { + if( (slept=mq.commit_wait( thr_ctx ))==true ) + break; + mq.prepare_wait( thr_ctx, uintptr_t(this) ); + } + if( !slept ) + mq.cancel_wait( thr_ctx ); +} + +//! A value protected by a mutex. +template<typename M> +struct Counter { + typedef M mutex_type; + M mutex; + long value; +}; + +//! Function object for use with parallel_for.h. +template<typename C, int D> +struct AddOne: NoAssign { + C& counter; + /** Increments counter once for each iteration in the iteration space. */ + void operator()( tbb::blocked_range<size_t>& range ) const { + for( size_t i=range.begin(); i!=range.end(); ++i ) { + typename C::mutex_type::ScopedLock lock(counter.mutex, i); + counter.value = counter.value+1; + if( D>0 ) + for( int j=0; j<D; ++j ) __TBB_Yield(); + } + } + AddOne( C& counter_ ) : counter(counter_) {} +}; + +//! Generic test with TBB mutex type M, max range R, and delay D. +template<typename M,int R, int D> +void Test( int p ) { + Counter<M> counter; + counter.value = 0; + const int n = R; + tbb::task_scheduler_init init(p); + tbb::parallel_for(tbb::blocked_range<size_t>(0,n,n/10),AddOne<Counter<M>,D>(counter)); + if( counter.value!=n ) + REPORT("ERROR : counter.value=%ld (instead of %ld)\n",counter.value,n); +} + +#if TBB_USE_EXCEPTIONS +#define NTHRS_USED_IN_DESTRUCTOR_TEST 8 + +atomic<size_t> n_sleepers; + +#if defined(_MSC_VER) && defined(_Wp64) + // Workaround for overzealous compiler warnings in /Wp64 mode + #pragma warning (disable: 4244 4267) +#endif + +struct AllButOneSleep : NoAssign { + internal::concurrent_monitor*& mon; + static const size_t VLN = 1024*1024; + void operator()( int i ) const { + internal::concurrent_monitor::thread_context thr_ctx; + + if( i==0 ) { + size_t n_expected_sleepers = NTHRS_USED_IN_DESTRUCTOR_TEST-1; + while( n_sleepers<n_expected_sleepers ) + __TBB_Yield(); + while( n_sleepers.compare_and_swap( VLN+NTHRS_USED_IN_DESTRUCTOR_TEST, n_expected_sleepers )!=n_expected_sleepers ) + __TBB_Yield(); + + for( int j=0; j<100; ++j ) + Harness::Sleep( 1 ); + delete mon; + mon = NULL; + } else { + mon->prepare_wait( thr_ctx, uintptr_t(this) ); + while( n_sleepers<VLN ) { + try { + ++n_sleepers; + mon->commit_wait( thr_ctx ); + if( --n_sleepers>VLN ) + break; + } catch( tbb::user_abort& ) { + // can no longer access 'mon' + break; + } + mon->prepare_wait( thr_ctx, uintptr_t(this) ); + } + } + } + AllButOneSleep( internal::concurrent_monitor*& m_ ) : mon(m_) {} +}; +#endif /* TBB_USE_EXCEPTIONS */ + +void TestDestructor() { +#if TBB_USE_EXCEPTIONS + tbb::task_scheduler_init init(NTHRS_USED_IN_DESTRUCTOR_TEST); + internal::concurrent_monitor* my_mon = new internal::concurrent_monitor; + REMARK( "testing the destructor\n" ); + n_sleepers = 0; + NativeParallelFor(NTHRS_USED_IN_DESTRUCTOR_TEST,AllButOneSleep(my_mon)); + ASSERT( my_mon==NULL, "" ); +#endif /* TBB_USE_EXCEPTIONS */ +} + +int TestMain () { + for( int p=MinThread; p<=MaxThread; ++p ) { + REMARK( "testing with %d workers\n", static_cast<int>(p) ); + // test the predicated notify + Test<QueuingMutex,100000,0>( p ); + Test<QueuingMutex,1000,10000>( p ); + // test the notify_all method + Test<SpinMutex,100000,0>( p ); + Test<SpinMutex,1000,10000>( p ); + REMARK( "calling destructor for task_scheduler_init\n" ); + } + TestDestructor(); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_concurrent_priority_queue.cpp b/src/tbb/src/test/test_concurrent_priority_queue.cpp new file mode 100644 index 0000000..8e0334f --- /dev/null +++ b/src/tbb/src/test/test_concurrent_priority_queue.cpp @@ -0,0 +1,471 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/concurrent_priority_queue.h" +#include "tbb/atomic.h" +#include "harness.h" +#include <functional> +#include <vector> + +#if _MSC_VER==1500 && !__INTEL_COMPILER + // VS2008/VC9 seems to have an issue; limits pull in math.h + #pragma warning( push ) + #pragma warning( disable: 4985 ) +#endif +#include <climits> +#if _MSC_VER==1500 && !__INTEL_COMPILER + #pragma warning( pop ) +#endif + +#if __INTEL_COMPILER && (_WIN32 || _WIN64) && TBB_USE_DEBUG && _CPPLIB_VER<520 +// The Intel Compiler has an issue that causes the Microsoft Iterator +// Debugging code to crash in vector::pop_back when it is called after a +// vector::push_back throws an exception. +// #define _HAS_ITERATOR_DEBUGGING 0 // Setting this to 0 doesn't solve the problem + // and also provokes a redefinition warning +#define __TBB_ITERATOR_DEBUGGING_EXCEPTIONS_BROKEN +#endif + +using namespace tbb; + +const size_t MAX_ITER = 10000; +const int MAX_PRIO = 100000000; + +tbb::atomic<unsigned int> counter; + +class my_data_type { +public: + int priority; + char padding[tbb::internal::NFS_MaxLineSize - sizeof(int) % tbb::internal::NFS_MaxLineSize]; + my_data_type() {} + my_data_type(int init_val) : priority(init_val) {} + const my_data_type operator+(const my_data_type& other) const { + return my_data_type(priority+other.priority); + } + bool operator==(const my_data_type& other) const { + return this->priority == other.priority; + } +}; + +const my_data_type DATA_MIN(INT_MIN); +const my_data_type DATA_MAX(INT_MAX); + +class my_less { +public: + bool operator()(const my_data_type d1, const my_data_type d2) const { + return d1.priority<d2.priority; + } +}; + +class my_throwing_type : public my_data_type { +public: + static int throw_flag; + my_throwing_type() : my_data_type() {} + my_throwing_type(const my_throwing_type& src) : my_data_type(src) { + if (my_throwing_type::throw_flag) throw 42; + priority = src.priority; + } +}; + +int my_throwing_type::throw_flag = 0; + +typedef concurrent_priority_queue<my_throwing_type, my_less > cpq_ex_test_type; + +template<typename T, typename C> +class FillBody : NoAssign { + int nThread; + T my_max, my_min; + concurrent_priority_queue<T, C> *q; + C less_than; +public: + FillBody(int nThread_, T max_, T min_, concurrent_priority_queue<T, C> *q_) : nThread(nThread_), my_max(max_), my_min(min_), q(q_) {} + void operator()(const int threadID) const { + T elem = my_min + T(threadID); + for (size_t i=0; i<MAX_ITER; ++i) { + // do some pushes + q->push(elem); + if (elem == my_max) elem = my_min; + elem = elem + T(nThread); + } + } +}; + +template<typename T, typename C> +struct EmptyBody : NoAssign { + int nThread; + T my_max; + concurrent_priority_queue<T, C> *q; + C less_than; +public: + EmptyBody(int nThread_, T max_, concurrent_priority_queue<T, C> *q_) : nThread(nThread_), my_max(max_), q(q_) {} + void operator()(const int /*threadID*/) const { + T elem(my_max), last; + if (q->try_pop(last)) { + ++counter; + while(q->try_pop(elem)) { + ASSERT(!less_than(last, elem), "FAILED pop/priority test in EmptyBody."); + last = elem; + elem = my_max; + ++counter; + } + } + } +}; + +template <typename T, typename C> +class FloggerBody : NoAssign { + int nThread; + concurrent_priority_queue<T, C> *q; +public: + FloggerBody(int nThread_, concurrent_priority_queue<T, C> *q_) : + nThread(nThread_), q(q_) {} + void operator()(const int threadID) const { + T elem = T(threadID); + for (size_t i=0; i<MAX_ITER; ++i) { + q->push(elem); + (void) q->try_pop(elem); + } + } +}; + +void TestConstructorsDestructorsAccessors() { + std::vector<int> v; + std::allocator<int> a; + concurrent_priority_queue<int, std::less<int> > *q, *qo; + concurrent_priority_queue<int, std::less<int>, std::allocator<int> > *qi; + + // Test constructors/destructors + REMARK("Testing default constructor.\n"); + q = new concurrent_priority_queue<int, std::less<int> >(); + REMARK("Default constructor complete.\n"); + ASSERT(q->size()==0, "FAILED size test."); + ASSERT(q->empty(), "FAILED empty test."); + REMARK("Testing destructor.\n"); + delete q; + REMARK("Destruction complete.\n"); + + REMARK("Testing capacity constructor.\n"); + q = new concurrent_priority_queue<int, std::less<int> >(42); + REMARK("Capacity constructor complete.\n"); + ASSERT(q->size()==0, "FAILED size test."); + ASSERT(q->empty(), "FAILED empty test."); + REMARK("Testing destructor.\n"); + delete q; + REMARK("Destruction complete.\n"); + + REMARK("Testing allocator constructor.\n"); + qi = new concurrent_priority_queue<int, std::less<int>, std::allocator<int> >(a); + REMARK("Allocator constructor complete.\n"); + ASSERT(qi->size()==0, "FAILED size test."); + ASSERT(qi->empty(), "FAILED empty test."); + REMARK("Testing destructor.\n"); + delete qi; + REMARK("Destruction complete.\n"); + + REMARK("Testing capacity+allocator constructor.\n"); + qi = new concurrent_priority_queue<int, std::less<int>, std::allocator<int> >(42, a); + REMARK("Capacity+allocator constructor complete.\n"); + ASSERT(qi->size()==0, "FAILED size test."); + ASSERT(qi->empty(), "FAILED empty test."); + REMARK("Testing destructor.\n"); + delete qi; + REMARK("Destruction complete.\n"); + + REMARK("Testing iterator filler constructor.\n"); + for (int i=0; i<42; ++i) + v.push_back(i); + q = new concurrent_priority_queue<int, std::less<int> >(v.begin(), v.end()); + REMARK("Iterator filler constructor complete.\n"); + ASSERT(q->size()==42, "FAILED vector/size test."); + ASSERT(!q->empty(), "FAILED vector/empty test."); + + REMARK("Testing copy constructor.\n"); + qo = new concurrent_priority_queue<int, std::less<int> >(*q); + REMARK("Copy constructor complete.\n"); + ASSERT(qo->size()==42, "FAILED vector/size test."); + ASSERT(!qo->empty(), "FAILED vector/empty test."); + REMARK("Testing destructor.\n"); + delete q; + delete qo; + REMARK("Destruction complete.\n"); +} + +void TestAssignmentClearSwap() { + std::vector<int> v; + concurrent_priority_queue<int, std::less<int> > *q, *qo; + int e; + + for (int i=0; i<42; ++i) + v.push_back(i); + q = new concurrent_priority_queue<int, std::less<int> >(v.begin(), v.end()); + qo = new concurrent_priority_queue<int, std::less<int> >(); + + REMARK("Testing assignment (1).\n"); + *qo = *q; + REMARK("Assignment complete.\n"); + ASSERT(qo->size()==42, "FAILED assignment/size test."); + ASSERT(!qo->empty(), "FAILED assignment/empty test."); + + REMARK("Testing clear.\n"); + q->clear(); + REMARK("Clear complete.\n"); + ASSERT(q->size()==0, "FAILED clear/size test."); + ASSERT(q->empty(), "FAILED clear/empty test."); + + for (size_t i=0; i<5; ++i) + (void) qo->try_pop(e); + + REMARK("Testing assignment (2).\n"); + *q = *qo; + REMARK("Assignment complete.\n"); + ASSERT(q->size()==37, "FAILED assignment/size test."); + ASSERT(!q->empty(), "FAILED assignment/empty test."); + + for (size_t i=0; i<5; ++i) + (void) qo->try_pop(e); + + REMARK("Testing swap.\n"); + q->swap(*qo); + REMARK("Swap complete.\n"); + ASSERT(q->size()==32, "FAILED swap/size test."); + ASSERT(!q->empty(), "FAILED swap/empty test."); + ASSERT(qo->size()==37, "FAILED swap_operand/size test."); + ASSERT(!qo->empty(), "FAILED swap_operand/empty test."); + delete q; + delete qo; +} + +void TestSerialPushPop() { + concurrent_priority_queue<int, std::less<int> > *q; + int e=42, prev=INT_MAX; + size_t count=0; + + q = new concurrent_priority_queue<int, std::less<int> >(MAX_ITER); + REMARK("Testing serial push.\n"); + for (size_t i=0; i<MAX_ITER; ++i) { + q->push(e); + e = e*-1 + int(i); + } + REMARK("Pushing complete.\n"); + ASSERT(q->size()==MAX_ITER, "FAILED push/size test."); + ASSERT(!q->empty(), "FAILED push/empty test."); + + REMARK("Testing serial pop.\n"); + while (!q->empty()) { + ASSERT(q->try_pop(e), "FAILED pop test."); + ASSERT(prev>=e, "FAILED pop/priority test."); + prev = e; + ++count; + ASSERT(q->size()==MAX_ITER-count, "FAILED swap/size test."); + ASSERT(!q->empty() || count==MAX_ITER, "FAILED swap/empty test."); + } + REMARK("Popping complete.\n"); + delete q; +} + +template <typename T, typename C> +void TestParallelPushPop(int nThreads, T t_max, T t_min, C /*compare*/) { + size_t qsize; + + concurrent_priority_queue<T, C> *q = new concurrent_priority_queue<T, C>(0); + FillBody<T, C> filler(nThreads, t_max, t_min, q); + EmptyBody<T, C> emptier(nThreads, t_max, q); + counter = 0; + REMARK("Testing parallel push.\n"); + NativeParallelFor(nThreads, filler); + REMARK("Pushing complete.\n"); + qsize = q->size(); + ASSERT(q->size()==nThreads*MAX_ITER, "FAILED push/size test."); + ASSERT(!q->empty(), "FAILED push/empty test."); + + REMARK("Testing parallel pop.\n"); + NativeParallelFor(nThreads, emptier); + REMARK("Popping complete.\n"); + ASSERT(counter==qsize, "FAILED pop/size test."); + ASSERT(q->size()==0, "FAILED pop/empty test."); + + q->clear(); + delete(q); +} + +void TestExceptions() { + const size_t TOO_LARGE_SZ = 1000000000; + my_throwing_type elem; + + REMARK("Testing basic constructor exceptions.\n"); + // Allocate empty queue should not throw no matter the type + try { + my_throwing_type::throw_flag = 1; + cpq_ex_test_type q; + } catch(...) { + ASSERT(false, "FAILED: allocating empty queue should not throw exception.\n"); + } + // Allocate small queue should not throw for reasonably sized type + try { + my_throwing_type::throw_flag = 1; + cpq_ex_test_type q(42); + } catch(...) { + ASSERT(false, "FAILED: allocating small queue should not throw exception.\n"); + } + // Allocate a queue with too large initial size + try { + my_throwing_type::throw_flag = 0; + cpq_ex_test_type q(TOO_LARGE_SZ); + REMARK("FAILED: Huge queue did not throw exception.\n"); + } catch(...) {} + + cpq_ex_test_type *pq; + try { + my_throwing_type::throw_flag = 0; + pq = NULL; + pq = new cpq_ex_test_type(TOO_LARGE_SZ); + REMARK("FAILED: Huge queue did not throw exception.\n"); + delete pq; + } catch(...) { + ASSERT(!pq, "FAILED: pq should not be touched when constructor throws.\n"); + } + REMARK("Basic constructor exceptions testing complete.\n"); + REMARK("Testing copy constructor exceptions.\n"); + my_throwing_type::throw_flag = 0; + cpq_ex_test_type src_q(42); + elem.priority = 42; + for (size_t i=0; i<42; ++i) src_q.push(elem); + try { + my_throwing_type::throw_flag = 1; + cpq_ex_test_type q(src_q); + REMARK("FAILED: Copy construct did not throw exception.\n"); + } catch(...) {} + try { + my_throwing_type::throw_flag = 1; + pq = NULL; + pq = new concurrent_priority_queue<my_throwing_type, my_less >(src_q); + REMARK("FAILED: Copy construct did not throw exception.\n"); + delete pq; + } catch(...) { + ASSERT(!pq, "FAILED: pq should not be touched when constructor throws.\n"); + } + REMARK("Copy constructor exceptions testing complete.\n"); + REMARK("Testing assignment exceptions.\n"); + // Assignment is copy-swap, so it should be exception safe + my_throwing_type::throw_flag = 0; + cpq_ex_test_type assign_q(24); + try { + my_throwing_type::throw_flag = 1; + assign_q = src_q; + REMARK("FAILED: Assign did not throw exception.\n"); + } catch(...) { + ASSERT(assign_q.empty(), "FAILED: assign_q should be empty.\n"); + } + REMARK("Assignment exceptions testing complete.\n"); +#ifndef __TBB_ITERATOR_DEBUGGING_EXCEPTIONS_BROKEN + REMARK("Testing push exceptions.\n"); + my_throwing_type::throw_flag = 0; + pq = new cpq_ex_test_type(3); + try { + pq->push(elem); + pq->push(elem); + pq->push(elem); + } catch(...) { + ASSERT(false, "FAILED: Push should not throw exception... yet.\n"); + } + try { // should crash on copy during expansion of vector + my_throwing_type::throw_flag = 1; + pq->push(elem); + REMARK("FAILED: Push did not throw exception.\n"); + } catch(...) { + ASSERT(!pq->empty(), "FAILED: pq should not be empty.\n"); + ASSERT(pq->size()==3, "FAILED: pq should be only three elements.\n"); + ASSERT(pq->try_pop(elem), "FAILED: pq is not functional.\n"); + } + delete pq; + + my_throwing_type::throw_flag = 0; + pq = new cpq_ex_test_type(3); + try { + pq->push(elem); + pq->push(elem); + } catch(...) { + ASSERT(false, "FAILED: Push should not throw exception... yet.\n"); + } + try { // should crash on push copy of element + my_throwing_type::throw_flag = 1; + pq->push(elem); + REMARK("FAILED: Push did not throw exception.\n"); + } catch(...) { + ASSERT(!pq->empty(), "FAILED: pq should not be empty.\n"); + ASSERT(pq->size()==2, "FAILED: pq should be only two elements.\n"); + ASSERT(pq->try_pop(elem), "FAILED: pq is not functional.\n"); + } + delete pq; + REMARK("Push exceptions testing complete.\n"); +#endif +} + +template <typename T, typename C> +void TestFlogger(int nThreads, T /*max*/, C /*compare*/) { + REMARK("Testing queue flogger.\n"); + concurrent_priority_queue<T, C> *q = new concurrent_priority_queue<T, C> (0); + NativeParallelFor(nThreads, FloggerBody<T, C >(nThreads, q)); + ASSERT(q->empty(), "FAILED flogger/empty test."); + ASSERT(!q->size(), "FAILED flogger/size test."); + REMARK("Flogging complete.\n"); + delete q; +} + +void TestCpqOnNThreads(int nThreads) { + std::less<int> int_compare; + my_less data_compare; + + TestConstructorsDestructorsAccessors(); + TestAssignmentClearSwap(); + TestSerialPushPop(); + + TestParallelPushPop(nThreads, INT_MAX, INT_MIN, int_compare); + TestParallelPushPop(nThreads, (unsigned char)CHAR_MAX, (unsigned char)CHAR_MIN, int_compare); + TestParallelPushPop(nThreads, DATA_MAX, DATA_MIN, data_compare); + + TestFlogger(nThreads, INT_MAX, int_compare); + TestFlogger(nThreads, (unsigned char)CHAR_MAX, int_compare); + TestFlogger(nThreads, DATA_MAX, data_compare); + +#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN + TestExceptions(); +#else + REPORT("Known issue: exception handling tests are skipped.\n"); +#endif +} + +int TestMain() { + if (MinThread < 1) + MinThread = 1; + for (int p = MinThread; p <= MaxThread; ++p) { + REMARK("Testing on %d threads.\n", p); + TestCpqOnNThreads(p); + } + return Harness::Done; +} diff --git a/src/tbb/src/test/test_concurrent_queue.cpp b/src/tbb/src/test/test_concurrent_queue.cpp new file mode 100644 index 0000000..146d743 --- /dev/null +++ b/src/tbb/src/test/test_concurrent_queue.cpp @@ -0,0 +1,1376 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#define NOMINMAX +#include "test_concurrent_queue.h" +#include "tbb/concurrent_queue.h" +#include "tbb/tick_count.h" +#include "harness.h" +#include "harness_allocator.h" + +#if _MSC_VER==1500 && !__INTEL_COMPILER + // VS2008/VC9 seems to have an issue; limits pull in math.h + #pragma warning( push ) + #pragma warning( disable: 4985 ) +#endif +#include <limits> +#if _MSC_VER==1500 && !__INTEL_COMPILER + #pragma warning( pop ) +#endif + + +static tbb::atomic<long> FooConstructed; +static tbb::atomic<long> FooDestroyed; + +class Foo { + enum state_t{ + LIVE=0x1234, + DEAD=0xDEAD + }; + state_t state; +public: + int thread_id; + int serial; + Foo() : state(LIVE), thread_id(0), serial(0) { + ++FooConstructed; + } + Foo( const Foo& item ) : state(LIVE) { + ASSERT( item.state==LIVE, NULL ); + ++FooConstructed; + thread_id = item.thread_id; + serial = item.serial; + } + ~Foo() { + ASSERT( state==LIVE, NULL ); + ++FooDestroyed; + state=DEAD; + thread_id=0xDEAD; + serial=0xDEAD; + } + void operator=( const Foo& item ) { + ASSERT( item.state==LIVE, NULL ); + ASSERT( state==LIVE, NULL ); + thread_id = item.thread_id; + serial = item.serial; + } + bool is_const() {return false;} + bool is_const() const {return true;} + static void clear_counters() { FooConstructed = 0; FooDestroyed = 0; } + static long get_n_constructed() { return FooConstructed; } + static long get_n_destroyed() { return FooDestroyed; } +}; + +// problem size +static const int N = 50000; // # of bytes + +#if TBB_USE_EXCEPTIONS +//! Exception for concurrent_queue +class Foo_exception : public std::bad_alloc { +public: + virtual const char *what() const throw() { return "out of Foo limit"; } + virtual ~Foo_exception() throw() {} +}; + +static tbb::atomic<long> FooExConstructed; +static tbb::atomic<long> FooExDestroyed; +static tbb::atomic<long> serial_source; +static long MaxFooCount = 0; +static const long Threshold = 400; + +class FooEx { + enum state_t{ + LIVE=0x1234, + DEAD=0xDEAD + }; + state_t state; +public: + int serial; + FooEx() : state(LIVE) { + ++FooExConstructed; + serial = serial_source++; + } + + FooEx( const FooEx& item ) : state(LIVE) { + ++FooExConstructed; + if( MaxFooCount && (FooExConstructed-FooExDestroyed) >= MaxFooCount ) // in push() + throw Foo_exception(); + serial = item.serial; + } + ~FooEx() { + ASSERT( state==LIVE, NULL ); + ++FooExDestroyed; + state=DEAD; + serial=0xDEAD; + } + void operator=( FooEx& item ) { + ASSERT( item.state==LIVE, NULL ); + ASSERT( state==LIVE, NULL ); + serial = item.serial; + if( MaxFooCount==2*Threshold && (FooExConstructed-FooExDestroyed) <= MaxFooCount/4 ) // in pop() + throw Foo_exception(); + } +} ; +#endif /* TBB_USE_EXCEPTIONS */ + +const size_t MAXTHREAD = 256; + +static int Sum[MAXTHREAD]; + +//! Count of various pop operations +/** [0] = pop_if_present that failed + [1] = pop_if_present that succeeded + [2] = pop */ +static tbb::atomic<long> PopKind[3]; + +const int M = 10000; + +#if TBB_DEPRECATED +#define CALL_BLOCKING_POP(q,v) (q)->pop(v) +#define CALL_TRY_POP(q,v,i) (((i)&0x2)?q->try_pop(v):q->pop_if_present(v)) +#else +#define CALL_BLOCKING_POP(q,v) while( !(q)->try_pop(v) ) __TBB_Yield() +#define CALL_TRY_POP(q,v,i) q->try_pop(v) +#endif + +template<typename CQ,typename T> +struct Body: NoAssign { + CQ* queue; + const int nthread; + Body( int nthread_ ) : nthread(nthread_) {} + void operator()( int thread_id ) const { + long pop_kind[3] = {0,0,0}; + int serial[MAXTHREAD+1]; + memset( serial, 0, nthread*sizeof(int) ); + ASSERT( thread_id<nthread, NULL ); + + long sum = 0; + for( long j=0; j<M; ++j ) { + T f; + f.thread_id = 0xDEAD; + f.serial = 0xDEAD; + bool prepopped = false; + if( j&1 ) { + prepopped = CALL_TRY_POP(queue,f,j); + ++pop_kind[prepopped]; + } + T g; + g.thread_id = thread_id; + g.serial = j+1; + queue->push( g ); + if( !prepopped ) { + CALL_BLOCKING_POP(queue,f); + ++pop_kind[2]; + } + ASSERT( f.thread_id<=nthread, NULL ); + ASSERT( f.thread_id==nthread || serial[f.thread_id]<f.serial, "partial order violation" ); + serial[f.thread_id] = f.serial; + sum += f.serial-1; + } + Sum[thread_id] = sum; + for( int k=0; k<3; ++k ) + PopKind[k] += pop_kind[k]; + } +}; + +#if !TBB_DEPRECATED +// Define wrapper classes to test tbb::concurrent_queue<T> +template<typename T, typename A = tbb::cache_aligned_allocator<T> > +class ConcQWithSizeWrapper : public tbb::concurrent_queue<T> { +public: + ConcQWithSizeWrapper() {} + template<typename InputIterator> + ConcQWithSizeWrapper( InputIterator begin, InputIterator end, const A& a = A()) : tbb::concurrent_queue<T>(begin,end,a) {} + size_t size() const { return this->unsafe_size(); } +}; + +template<typename T> +class ConcQPushPopWrapper : public tbb::concurrent_queue<T> { +public: + ConcQPushPopWrapper() : my_capacity( size_t(-1)/(sizeof(void*)+sizeof(T)) ) {} + size_t size() const { return this->unsafe_size(); } + void set_capacity( const ptrdiff_t n ) { my_capacity = n; } + bool try_push( const T& source ) { return this->push( source ); } + bool try_pop( T& dest ) { return this->tbb::concurrent_queue<T>::try_pop( dest ); } + size_t my_capacity; +}; + +template<typename T> +class ConcQWithCapacity : public tbb::concurrent_queue<T> { +public: + ConcQWithCapacity() : my_capacity( size_t(-1)/(sizeof(void*)+sizeof(T)) ) {} + size_t size() const { return this->unsafe_size(); } + size_t capacity() const { return my_capacity; } + void set_capacity( const int n ) { my_capacity = n; } + bool try_push( const T& source ) { this->push( source ); return (size_t)source.serial<my_capacity; } + //bool push_if_not_full( const T& source ) { return try_push(source); } + bool try_pop( T& dest ) { this->tbb::concurrent_queue<T>::try_pop( dest ); return (size_t)dest.serial<my_capacity; } + //void pop( T& dest ) { this->try_pop( dest ); } + size_t my_capacity; +}; +#endif /* !TBB_DEPRECATED */ + +template<typename CQ, typename T> +void TestPushPop( size_t prefill, ptrdiff_t capacity, int nthread ) { + ASSERT( nthread>0, "nthread must be positive" ); + ptrdiff_t signed_prefill = ptrdiff_t(prefill); + if( signed_prefill+1>=capacity ) + return; + bool success = false; + for( int k=0; k<3; ++k ) + PopKind[k] = 0; + for( int trial=0; !success; ++trial ) { + T::clear_counters(); + Body<CQ,T> body(nthread); + CQ queue; + queue.set_capacity( capacity ); + body.queue = &queue; + for( size_t i=0; i<prefill; ++i ) { + T f; + f.thread_id = nthread; + f.serial = 1+int(i); + queue.push(f); + ASSERT( unsigned(queue.size())==i+1, NULL ); + ASSERT( !queue.empty(), NULL ); + } + tbb::tick_count t0 = tbb::tick_count::now(); + NativeParallelFor( nthread, body ); + tbb::tick_count t1 = tbb::tick_count::now(); + double timing = (t1-t0).seconds(); + REMARK("prefill=%d capacity=%d threads=%d time = %g = %g nsec/operation\n", int(prefill), int(capacity), nthread, timing, timing/(2*M*nthread)*1.E9); + int sum = 0; + for( int k=0; k<nthread; ++k ) + sum += Sum[k]; + int expected = int(nthread*((M-1)*M/2) + ((prefill-1)*prefill)/2); + for( int i=int(prefill); --i>=0; ) { + ASSERT( !queue.empty(), NULL ); + T f; + bool result = queue.try_pop(f); + ASSERT( result, NULL ); + ASSERT( int(queue.size())==i, NULL ); + sum += f.serial-1; + } + ASSERT( queue.empty(), NULL ); + ASSERT( queue.size()==0, NULL ); + if( sum!=expected ) + REPORT("sum=%d expected=%d\n",sum,expected); + ASSERT( T::get_n_constructed()==T::get_n_destroyed(), NULL ); + // TODO: checks by counting allocators + + success = true; + if( nthread>1 && prefill==0 ) { + // Check that pop_if_present got sufficient exercise + for( int k=0; k<2; ++k ) { +#if (_WIN32||_WIN64) + // The TBB library on Windows seems to have a tough time generating + // the desired interleavings for pop_if_present, so the code tries longer, and settles + // for fewer desired interleavings. + const int max_trial = 100; + const int min_requirement = 20; +#else + const int min_requirement = 100; + const int max_trial = 20; +#endif /* _WIN32||_WIN64 */ + if( PopKind[k]<min_requirement ) { + if( trial>=max_trial ) { + if( Verbose ) + REPORT("Warning: %d threads had only %ld pop_if_present operations %s after %d trials (expected at least %d). " + "This problem may merely be unlucky scheduling. " + "Investigate only if it happens repeatedly.\n", + nthread, long(PopKind[k]), k==0?"failed":"succeeded", max_trial, min_requirement); + else + REPORT("Warning: the number of %s pop_if_present operations is less than expected for %d threads. Investigate if it happens repeatedly.\n", + k==0?"failed":"succeeded", nthread ); + + } else { + success = false; + } + } + } + } + } +} + +class Bar { + enum state_t { + LIVE=0x1234, + DEAD=0xDEAD + }; + state_t state; +public: + ptrdiff_t my_id; + Bar() : state(LIVE), my_id(-1) {} + Bar(size_t _i) : state(LIVE), my_id(_i) {} + Bar( const Bar& a_bar ) : state(LIVE) { + ASSERT( a_bar.state==LIVE, NULL ); + my_id = a_bar.my_id; + } + ~Bar() { + ASSERT( state==LIVE, NULL ); + state = DEAD; + my_id = DEAD; + } + void operator=( const Bar& a_bar ) { + ASSERT( a_bar.state==LIVE, NULL ); + ASSERT( state==LIVE, NULL ); + my_id = a_bar.my_id; + } + friend bool operator==(const Bar& bar1, const Bar& bar2 ) ; +} ; + +bool operator==(const Bar& bar1, const Bar& bar2) { + ASSERT( bar1.state==Bar::LIVE, NULL ); + ASSERT( bar2.state==Bar::LIVE, NULL ); + return bar1.my_id == bar2.my_id; +} + +class BarIterator +{ + Bar* bar_ptr; + BarIterator(Bar* bp_) : bar_ptr(bp_) {} +public: + ~BarIterator() {} + BarIterator& operator=( const BarIterator& other ) { + bar_ptr = other.bar_ptr; + return *this; + } + Bar& operator*() const { + return *bar_ptr; + } + BarIterator& operator++() { + ++bar_ptr; + return *this; + } + Bar* operator++(int) { + Bar* result = &operator*(); + operator++(); + return result; + } + friend bool operator==(const BarIterator& bia, const BarIterator& bib) ; + friend bool operator!=(const BarIterator& bia, const BarIterator& bib) ; + template<typename CQ, typename T, typename TIter, typename CQ_EX, typename T_EX> + friend void TestConstructors (); +} ; + +bool operator==(const BarIterator& bia, const BarIterator& bib) { + return bia.bar_ptr==bib.bar_ptr; +} + +bool operator!=(const BarIterator& bia, const BarIterator& bib) { + return bia.bar_ptr!=bib.bar_ptr; +} + +#if TBB_USE_EXCEPTIONS +class Bar_exception : public std::bad_alloc { +public: + virtual const char *what() const throw() { return "making the entry invalid"; } + virtual ~Bar_exception() throw() {} +}; + +class BarEx { + enum state_t { + LIVE=0x1234, + DEAD=0xDEAD + }; + static int count; +public: + state_t state; + typedef enum { + PREPARATION, + COPY_CONSTRUCT + } mode_t; + static mode_t mode; + ptrdiff_t my_id; + ptrdiff_t my_tilda_id; + static int button; + BarEx() : state(LIVE), my_id(-1), my_tilda_id(-1) {} + BarEx(size_t _i) : state(LIVE), my_id(_i), my_tilda_id(my_id^(-1)) {} + BarEx( const BarEx& a_bar ) : state(LIVE) { + ASSERT( a_bar.state==LIVE, NULL ); + my_id = a_bar.my_id; + if( mode==PREPARATION ) + if( !( ++count % 100 ) ) + throw Bar_exception(); + my_tilda_id = a_bar.my_tilda_id; + } + ~BarEx() { + ASSERT( state==LIVE, NULL ); + state = DEAD; + my_id = DEAD; + } + static void set_mode( mode_t m ) { mode = m; } + void operator=( const BarEx& a_bar ) { + ASSERT( a_bar.state==LIVE, NULL ); + ASSERT( state==LIVE, NULL ); + my_id = a_bar.my_id; + my_tilda_id = a_bar.my_tilda_id; + } + friend bool operator==(const BarEx& bar1, const BarEx& bar2 ) ; +} ; + +int BarEx::count = 0; +BarEx::mode_t BarEx::mode = BarEx::PREPARATION; + +bool operator==(const BarEx& bar1, const BarEx& bar2) { + ASSERT( bar1.state==BarEx::LIVE, NULL ); + ASSERT( bar2.state==BarEx::LIVE, NULL ); + ASSERT( (bar1.my_id ^ bar1.my_tilda_id) == -1, NULL ); + ASSERT( (bar2.my_id ^ bar2.my_tilda_id) == -1, NULL ); + return bar1.my_id==bar2.my_id && bar1.my_tilda_id==bar2.my_tilda_id; +} +#endif /* TBB_USE_EXCEPTIONS */ + +#if TBB_DEPRECATED + +#if __INTEL_COMPILER==1200 && _MSC_VER==1600 +// A workaround due to ICL 12.0 with /Qvc10 generating buggy code in TestIterator +#define CALL_BEGIN(q,i) q.begin() +#define CALL_END(q,i) q.end() +#else +#define CALL_BEGIN(q,i) (((i)&0x1)?q.begin():q.unsafe_begin()) +#define CALL_END(q,i) (((i)&0x1)?q.end():q.unsafe_end()) +#endif + +#else +#define CALL_BEGIN(q,i) q.unsafe_begin() +#define CALL_END(q,i) q.unsafe_end() +#endif /* TBB_DEPRECATED */ + +template<typename CQ, typename T, typename TIter, typename CQ_EX, typename T_EX> +void TestConstructors () +{ + CQ src_queue; + typename CQ::const_iterator dqb; + typename CQ::const_iterator dqe; + typename CQ::const_iterator iter; + + for( size_t size=0; size<1001; ++size ) { + for( size_t i=0; i<size; ++i ) + src_queue.push(T(i+(i^size))); + typename CQ::const_iterator sqb( CALL_BEGIN(src_queue,size) ); + typename CQ::const_iterator sqe( CALL_END(src_queue,size)); + + CQ dst_queue(sqb, sqe); + + ASSERT(src_queue.size()==dst_queue.size(), "different size"); + + src_queue.clear(); + } + + T bar_array[1001]; + for( size_t size=0; size<1001; ++size ) { + for( size_t i=0; i<size; ++i ) + bar_array[i] = T(i+(i^size)); + + const TIter sab(bar_array+0); + const TIter sae(bar_array+size); + + CQ dst_queue2(sab, sae); + + ASSERT( size==unsigned(dst_queue2.size()), NULL ); + ASSERT( sab==TIter(bar_array+0), NULL ); + ASSERT( sae==TIter(bar_array+size), NULL ); + + dqb = CALL_BEGIN(dst_queue2,size); + dqe = CALL_END(dst_queue2,size); + TIter v_iter(sab); + for( ; dqb != dqe; ++dqb, ++v_iter ) + ASSERT( *dqb == *v_iter, "unexpected element" ); + ASSERT( v_iter==sae, "different size?" ); + } + + src_queue.clear(); + + CQ dst_queue3( src_queue ); + ASSERT( src_queue.size()==dst_queue3.size(), NULL ); + ASSERT( 0==dst_queue3.size(), NULL ); + + int k=0; + for( size_t i=0; i<1001; ++i ) { + T tmp_bar; + src_queue.push(T(++k)); + src_queue.push(T(++k)); + src_queue.try_pop(tmp_bar); + + CQ dst_queue4( src_queue ); + + ASSERT( src_queue.size()==dst_queue4.size(), NULL ); + + dqb = CALL_BEGIN(dst_queue4,i); + dqe = CALL_END(dst_queue4,i); + iter = CALL_BEGIN(src_queue,i); + + for( ; dqb != dqe; ++dqb, ++iter ) + ASSERT( *dqb == *iter, "unexpected element" ); + + ASSERT( iter==CALL_END(src_queue,i), "different size?" ); + } + + CQ dst_queue5( src_queue ); + + ASSERT( src_queue.size()==dst_queue5.size(), NULL ); + dqb = dst_queue5.unsafe_begin(); + dqe = dst_queue5.unsafe_end(); + iter = src_queue.unsafe_begin(); + for( ; dqb != dqe; ++dqb, ++iter ) + ASSERT( *dqb == *iter, "unexpected element" ); + + for( size_t i=0; i<100; ++i) { + T tmp_bar; + src_queue.push(T(i+1000)); + src_queue.push(T(i+1000)); + src_queue.try_pop(tmp_bar); + + dst_queue5.push(T(i+1000)); + dst_queue5.push(T(i+1000)); + dst_queue5.try_pop(tmp_bar); + } + + ASSERT( src_queue.size()==dst_queue5.size(), NULL ); + dqb = dst_queue5.unsafe_begin(); + dqe = dst_queue5.unsafe_end(); + iter = src_queue.unsafe_begin(); + for( ; dqb != dqe; ++dqb, ++iter ) + ASSERT( *dqb == *iter, "unexpected element" ); + ASSERT( iter==src_queue.unsafe_end(), "different size?" ); + +#if __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN || __TBB_PLACEMENT_NEW_EXCEPTION_SAFETY_BROKEN + REPORT("Known issue: part of the constructor test is skipped.\n"); +#elif TBB_USE_EXCEPTIONS + k = 0; + typename CQ_EX::size_type n_elements=0; + CQ_EX src_queue_ex; + for( size_t size=0; size<1001; ++size ) { + T_EX tmp_bar_ex; + typename CQ_EX::size_type n_successful_pushes=0; + T_EX::set_mode( T_EX::PREPARATION ); + try { + src_queue_ex.push(T_EX(k+(k^size))); + ++n_successful_pushes; + } catch (...) { + } + ++k; + try { + src_queue_ex.push(T_EX(k+(k^size))); + ++n_successful_pushes; + } catch (...) { + } + ++k; + src_queue_ex.try_pop(tmp_bar_ex); + n_elements += (n_successful_pushes - 1); + ASSERT( src_queue_ex.size()==n_elements, NULL); + + T_EX::set_mode( T_EX::COPY_CONSTRUCT ); + CQ_EX dst_queue_ex( src_queue_ex ); + + ASSERT( src_queue_ex.size()==dst_queue_ex.size(), NULL ); + + typename CQ_EX::const_iterator dqb_ex = CALL_BEGIN(dst_queue_ex, size); + typename CQ_EX::const_iterator dqe_ex = CALL_END(dst_queue_ex, size); + typename CQ_EX::const_iterator iter_ex = CALL_BEGIN(src_queue_ex, size); + + for( ; dqb_ex != dqe_ex; ++dqb_ex, ++iter_ex ) + ASSERT( *dqb_ex == *iter_ex, "unexpected element" ); + ASSERT( iter_ex==CALL_END(src_queue_ex,size), "different size?" ); + } +#endif /* TBB_USE_EXCEPTIONS */ +} + +template<typename Iterator1, typename Iterator2> +void TestIteratorAux( Iterator1 i, Iterator2 j, int size ) { + // Now test iteration + Iterator1 old_i; + for( int k=0; k<size; ++k ) { + ASSERT( i!=j, NULL ); + ASSERT( !(i==j), NULL ); + Foo f; + if( k&1 ) { + // Test pre-increment + f = *old_i++; + // Test assignment + i = old_i; + } else { + // Test post-increment + f=*i++; + if( k<size-1 ) { + // Test "->" + ASSERT( k+2==i->serial, NULL ); + } + // Test assignment + old_i = i; + } + ASSERT( k+1==f.serial, NULL ); + } + ASSERT( !(i!=j), NULL ); + ASSERT( i==j, NULL ); +} + +template<typename Iterator1, typename Iterator2> +void TestIteratorAssignment( Iterator2 j ) { + Iterator1 i(j); + ASSERT( i==j, NULL ); + ASSERT( !(i!=j), NULL ); + Iterator1 k; + k = j; + ASSERT( k==j, NULL ); + ASSERT( !(k!=j), NULL ); +} + +template<typename Iterator, typename T> +void TestIteratorTraits() { + AssertSameType( static_cast<typename Iterator::difference_type*>(0), static_cast<ptrdiff_t*>(0) ); + AssertSameType( static_cast<typename Iterator::value_type*>(0), static_cast<T*>(0) ); + AssertSameType( static_cast<typename Iterator::pointer*>(0), static_cast<T**>(0) ); + AssertSameType( static_cast<typename Iterator::iterator_category*>(0), static_cast<std::forward_iterator_tag*>(0) ); + T x; + typename Iterator::reference xr = x; + typename Iterator::pointer xp = &x; + ASSERT( &xr==xp, NULL ); +} + +//! Test the iterators for concurrent_queue +template<typename CQ> +void TestIterator() { + CQ queue; + const CQ& const_queue = queue; + for( int j=0; j<500; ++j ) { + TestIteratorAux( CALL_BEGIN(queue,j) , CALL_END(queue,j) , j ); + TestIteratorAux( CALL_BEGIN(const_queue,j), CALL_END(const_queue,j), j ); + TestIteratorAux( CALL_BEGIN(const_queue,j), CALL_END(queue,j) , j ); + TestIteratorAux( CALL_BEGIN(queue,j) , CALL_END(const_queue,j), j ); + Foo f; + f.serial = j+1; + queue.push(f); + } + TestIteratorAssignment<typename CQ::const_iterator>( const_queue.unsafe_begin() ); + TestIteratorAssignment<typename CQ::const_iterator>( queue.unsafe_begin() ); + TestIteratorAssignment<typename CQ::iterator>( queue.unsafe_begin() ); + TestIteratorTraits<typename CQ::const_iterator, const Foo>(); + TestIteratorTraits<typename CQ::iterator, Foo>(); +} + +template<typename CQ> +void TestConcurrentQueueType() { + AssertSameType( typename CQ::value_type(), Foo() ); + Foo f; + const Foo g; + typename CQ::reference r = f; + ASSERT( &r==&f, NULL ); + ASSERT( !r.is_const(), NULL ); + typename CQ::const_reference cr = g; + ASSERT( &cr==&g, NULL ); + ASSERT( cr.is_const(), NULL ); +} + +template<typename CQ, typename T> +void TestEmptyQueue() { + const CQ queue; + ASSERT( queue.size()==0, NULL ); + ASSERT( queue.capacity()>0, NULL ); + ASSERT( size_t(queue.capacity())>=size_t(-1)/(sizeof(void*)+sizeof(T)), NULL ); +} + +#ifdef CALL_TRY_POP +#undef CALL_TRY_POP +#endif +#if TBB_DEPRECATED +#define CALL_TRY_PUSH(q,f,i) (((i)&0x1)?(q).push_if_not_full(f):(q).try_push(f)) +#define CALL_TRY_POP(q,f) (q).pop_if_present(f) +#else +#define CALL_TRY_PUSH(q,f,i) (q).try_push(f) +#define CALL_TRY_POP(q,f) (q).try_pop(f) +#endif + +template<typename CQ,typename T> +void TestFullQueue() { + for( int n=0; n<10; ++n ) { + T::clear_counters(); + CQ queue; + queue.set_capacity(n); + for( int i=0; i<=n; ++i ) { + T f; + f.serial = i; + bool result = CALL_TRY_PUSH( queue, f, i ); + ASSERT( result==(i<n), NULL ); + } + for( int i=0; i<=n; ++i ) { + T f; + bool result = CALL_TRY_POP( queue, f ); + ASSERT( result==(i<n), NULL ); + ASSERT( !result || f.serial==i, NULL ); + } + ASSERT( T::get_n_constructed()==T::get_n_destroyed(), NULL ); + } +} + +#if TBB_DEPRECATED +#define CALL_PUSH_IF_NOT_FULL(q,v,i) (((i)&0x1)?q.push_if_not_full(v):(q.push(v), true)) +#else +#define CALL_PUSH_IF_NOT_FULL(q,v,i) (q.push(v), true) +#endif + +template<typename CQ> +void TestClear() { + FooConstructed = 0; + FooDestroyed = 0; + const unsigned int n=5; + + CQ queue; + const int q_capacity=10; + queue.set_capacity(q_capacity); + for( size_t i=0; i<n; ++i ) { + Foo f; + f.serial = int(i); + bool result = CALL_PUSH_IF_NOT_FULL(queue, f, i); + ASSERT( result, NULL ); + } + ASSERT( unsigned(queue.size())==n, NULL ); + queue.clear(); + ASSERT( queue.size()==0, NULL ); + for( size_t i=0; i<n; ++i ) { + Foo f; + f.serial = int(i); + bool result = CALL_PUSH_IF_NOT_FULL(queue, f, i); + ASSERT( result, NULL ); + } + ASSERT( unsigned(queue.size())==n, NULL ); + queue.clear(); + ASSERT( queue.size()==0, NULL ); + for( size_t i=0; i<n; ++i ) { + Foo f; + f.serial = int(i); + bool result = CALL_PUSH_IF_NOT_FULL(queue, f, i); + ASSERT( result, NULL ); + } + ASSERT( unsigned(queue.size())==n, NULL ); +} + +#if TBB_DEPRECATED +template<typename T> +struct TestNegativeQueueBody: NoAssign { + tbb::concurrent_queue<T>& queue; + const int nthread; + TestNegativeQueueBody( tbb::concurrent_queue<T>& q, int n ) : queue(q), nthread(n) {} + void operator()( int k ) const { + if( k==0 ) { + int number_of_pops = nthread-1; + // Wait for all pops to pend. + while( queue.size()>-number_of_pops ) { + __TBB_Yield(); + } + for( int i=0; ; ++i ) { + ASSERT( queue.size()==i-number_of_pops, NULL ); + ASSERT( queue.empty()==(queue.size()<=0), NULL ); + if( i==number_of_pops ) break; + // Satisfy another pop + queue.push( T() ); + } + } else { + // Pop item from queue + T item; + queue.pop(item); + } + } +}; + +//! Test a queue with a negative size. +template<typename T> +void TestNegativeQueue( int nthread ) { + tbb::concurrent_queue<T> queue; + NativeParallelFor( nthread, TestNegativeQueueBody<T>(queue,nthread) ); +} +#endif /* TBB_DEPRECATED */ + +#if TBB_USE_EXCEPTIONS +template<typename CQ,typename A1,typename A2,typename T> +void TestExceptionBody() { + enum methods { + m_push = 0, + m_pop + }; + + REMARK("Testing exception safety\n"); + MaxFooCount = 5; + // verify 'clear()' on exception; queue's destructor calls its clear() + // Do test on queues of two different types at the same time to + // catch problem with incorrect sharing between templates. + { + CQ queue0; + tbb::concurrent_queue<int,A1> queue1; + for( int i=0; i<2; ++i ) { + bool caught = false; + try { + A2::init_counters(); + A2::set_limits(N/2); + for( int k=0; k<N; k++ ) { + if( i==0 ) + queue0.push( T() ); + else + queue1.push( k ); + } + } catch (...) { + caught = true; + } + ASSERT( caught, "call to push should have thrown exception" ); + } + } + REMARK("... queue destruction test passed\n"); + + try { + int n_pushed=0, n_popped=0; + for(int t = 0; t <= 1; t++)// exception type -- 0 : from allocator(), 1 : from Foo's constructor + { + CQ queue_test; + for( int m=m_push; m<=m_pop; m++ ) { + // concurrent_queue internally rebinds the allocator to one with 'char' + A2::init_counters(); + + if(t) MaxFooCount = MaxFooCount + 400; + else A2::set_limits(N/2); + + try { + switch(m) { + case m_push: + for( int k=0; k<N; k++ ) { + queue_test.push( T() ); + n_pushed++; + } + break; + case m_pop: + n_popped=0; + for( int k=0; k<n_pushed; k++ ) { + T elt; + queue_test.try_pop( elt ); + n_popped++; + } + n_pushed = 0; + A2::set_limits(); + break; + } + if( !t && m==m_push ) ASSERT(false, "should throw an exception"); + } catch ( Foo_exception & ) { + switch(m) { + case m_push: { + ASSERT( ptrdiff_t(queue_test.size())==n_pushed, "incorrect queue size" ); + long tc = MaxFooCount; + MaxFooCount = 0; + for( int k=0; k<(int)tc; k++ ) { + queue_test.push( T() ); + n_pushed++; + } + MaxFooCount = tc; + } + break; + case m_pop: + MaxFooCount = 0; // disable exception + n_pushed -= (n_popped+1); // including one that threw an exception + ASSERT( n_pushed>=0, "n_pushed cannot be less than 0" ); + for( int k=0; k<1000; k++ ) { + queue_test.push( T() ); + n_pushed++; + } + ASSERT( !queue_test.empty(), "queue must not be empty" ); + ASSERT( ptrdiff_t(queue_test.size())==n_pushed, "queue size must be equal to n pushed" ); + for( int k=0; k<n_pushed; k++ ) { + T elt; + queue_test.try_pop( elt ); + } + ASSERT( queue_test.empty(), "queue must be empty" ); + ASSERT( queue_test.size()==0, "queue must be empty" ); + break; + } + } catch ( std::bad_alloc & ) { + A2::set_limits(); // disable exception from allocator + size_t size = queue_test.size(); + switch(m) { + case m_push: + ASSERT( size>0, "incorrect queue size"); + break; + case m_pop: + if( !t ) ASSERT( false, "should not throw an exceptin" ); + break; + } + } + REMARK("... for t=%d and m=%d, exception test passed\n", t, m); + } + } + } catch(...) { + ASSERT(false, "unexpected exception"); + } +} +#endif /* TBB_USE_EXCEPTIONS */ + +void TestExceptions() { +#if __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN + REPORT("Known issue: exception safety test is skipped.\n"); +#elif TBB_USE_EXCEPTIONS + typedef static_counting_allocator<std::allocator<FooEx>, size_t> allocator_t; + typedef static_counting_allocator<std::allocator<char>, size_t> allocator_char_t; +#if !TBB_DEPRECATED + TestExceptionBody<ConcQWithSizeWrapper<FooEx, allocator_t>,allocator_t,allocator_char_t,FooEx>(); + TestExceptionBody<tbb::concurrent_bounded_queue<FooEx, allocator_t>,allocator_t,allocator_char_t,FooEx>(); +#else + TestExceptionBody<tbb::concurrent_queue<FooEx, allocator_t>,allocator_t,allocator_char_t,FooEx>(); +#endif +#endif /* TBB_USE_EXCEPTIONS */ +} + +template<typename CQ, typename T> +struct TestQueueElements: NoAssign { + CQ& queue; + const int nthread; + TestQueueElements( CQ& q, int n ) : queue(q), nthread(n) {} + void operator()( int k ) const { + for( int i=0; i<1000; ++i ) { + if( (i&0x1)==0 ) { + ASSERT( T(k)<T(nthread), NULL ); + queue.push( T(k) ); + } else { + // Pop item from queue + T item = 0; + queue.try_pop(item); + ASSERT( item<=T(nthread), NULL ); + } + } + } +}; + +//! Test concurrent queue with primitive data type +template<typename CQ, typename T> +void TestPrimitiveTypes( int nthread, T exemplar ) +{ + CQ queue; + for( int i=0; i<100; ++i ) + queue.push( exemplar ); + NativeParallelFor( nthread, TestQueueElements<CQ,T>(queue,nthread) ); +} + +#include "harness_m128.h" + +#if HAVE_m128 || HAVE_m256 + +//! Test concurrent queue with vector types +/** Type Queue should be a queue of ClassWithSSE/ClassWithAVX. */ +template<typename ClassWithVectorType, typename Queue> +void TestVectorTypes() { + Queue q1; + for( int i=0; i<100; ++i ) { + // VC8 does not properly align a temporary value; to work around, use explicit variable + ClassWithVectorType bar(i); + q1.push(bar); + } + + // Copy the queue + Queue q2 = q1; + // Check that elements of the copy are correct + typename Queue::const_iterator ci = q2.unsafe_begin(); + for( int i=0; i<100; ++i ) { + ClassWithVectorType foo = *ci; + ClassWithVectorType bar(i); + ASSERT( *ci==bar, NULL ); + ++ci; + } + + for( int i=0; i<101; ++i ) { + ClassWithVectorType tmp; + bool b = q1.try_pop( tmp ); + ASSERT( b==(i<100), NULL ); + ClassWithVectorType bar(i); + ASSERT( !b || tmp==bar, NULL ); + } +} +#endif /* HAVE_m128 || HAVE_m256 */ + +void TestEmptiness() +{ + REMARK(" Test Emptiness\n"); +#if !TBB_DEPRECATED + TestEmptyQueue<ConcQWithCapacity<char>, char>(); + TestEmptyQueue<ConcQWithCapacity<Foo>, Foo>(); + TestEmptyQueue<tbb::concurrent_bounded_queue<char>, char>(); + TestEmptyQueue<tbb::concurrent_bounded_queue<Foo>, Foo>(); +#else + TestEmptyQueue<tbb::concurrent_queue<char>, char>(); + TestEmptyQueue<tbb::concurrent_queue<Foo>, Foo>(); +#endif +} + +void TestFullness() +{ + REMARK(" Test Fullness\n"); +#if !TBB_DEPRECATED + TestFullQueue<ConcQWithCapacity<Foo>,Foo>(); + TestFullQueue<tbb::concurrent_bounded_queue<Foo>,Foo>(); +#else + TestFullQueue<tbb::concurrent_queue<Foo>,Foo>(); +#endif +} + +void TestClearWorks() +{ + REMARK(" Test concurrent_queue::clear() works\n"); +#if !TBB_DEPRECATED + TestClear<ConcQWithCapacity<Foo> >(); + TestClear<tbb::concurrent_bounded_queue<Foo> >(); +#else + TestClear<tbb::concurrent_queue<Foo> >(); +#endif +} + +void TestQueueTypeDeclaration() +{ + REMARK(" Test concurrent_queue's types work\n"); +#if !TBB_DEPRECATED + TestConcurrentQueueType<tbb::concurrent_queue<Foo> >(); + TestConcurrentQueueType<tbb::concurrent_bounded_queue<Foo> >(); +#else + TestConcurrentQueueType<tbb::concurrent_queue<Foo> >(); +#endif +} + +void TestQueueIteratorWorks() +{ + REMARK(" Test concurrent_queue's iterators work\n"); +#if !TBB_DEPRECATED + TestIterator<tbb::concurrent_queue<Foo> >(); + TestIterator<tbb::concurrent_bounded_queue<Foo> >(); +#else + TestIterator<tbb::concurrent_queue<Foo> >(); +#endif +} + +#if TBB_USE_EXCEPTIONS +#define BAR_EX BarEx +#else +#define BAR_EX Empty /* passed as template arg but should not be used */ +#endif +class Empty; + +void TestQueueConstructors() +{ + REMARK(" Test concurrent_queue's constructors work\n"); +#if !TBB_DEPRECATED + TestConstructors<ConcQWithSizeWrapper<Bar>,Bar,BarIterator,ConcQWithSizeWrapper<BAR_EX>,BAR_EX>(); + TestConstructors<tbb::concurrent_bounded_queue<Bar>,Bar,BarIterator,tbb::concurrent_bounded_queue<BAR_EX>,BAR_EX>(); +#else + TestConstructors<tbb::concurrent_queue<Bar>,Bar,BarIterator,tbb::concurrent_queue<BAR_EX>,BAR_EX>(); +#endif +} + +void TestQueueWorksWithPrimitiveTypes() +{ + REMARK(" Test concurrent_queue works with primitive types\n"); +#if !TBB_DEPRECATED + TestPrimitiveTypes<tbb::concurrent_queue<char>, char>( MaxThread, (char)1 ); + TestPrimitiveTypes<tbb::concurrent_queue<int>, int>( MaxThread, (int)-12 ); + TestPrimitiveTypes<tbb::concurrent_queue<float>, float>( MaxThread, (float)-1.2f ); + TestPrimitiveTypes<tbb::concurrent_queue<double>, double>( MaxThread, (double)-4.3 ); + TestPrimitiveTypes<tbb::concurrent_bounded_queue<char>, char>( MaxThread, (char)1 ); + TestPrimitiveTypes<tbb::concurrent_bounded_queue<int>, int>( MaxThread, (int)-12 ); + TestPrimitiveTypes<tbb::concurrent_bounded_queue<float>, float>( MaxThread, (float)-1.2f ); + TestPrimitiveTypes<tbb::concurrent_bounded_queue<double>, double>( MaxThread, (double)-4.3 ); +#else + TestPrimitiveTypes<tbb::concurrent_queue<char>, char>( MaxThread, (char)1 ); + TestPrimitiveTypes<tbb::concurrent_queue<int>, int>( MaxThread, (int)-12 ); + TestPrimitiveTypes<tbb::concurrent_queue<float>, float>( MaxThread, (float)-1.2f ); + TestPrimitiveTypes<tbb::concurrent_queue<double>, double>( MaxThread, (double)-4.3 ); +#endif +} + +void TestQueueWorksWithSSE() +{ + REMARK(" Test concurrent_queue works with SSE data\n"); +#if HAVE_m128 +#if !TBB_DEPRECATED + TestVectorTypes<ClassWithSSE, tbb::concurrent_queue<ClassWithSSE> >(); + TestVectorTypes<ClassWithSSE, tbb::concurrent_bounded_queue<ClassWithSSE> >(); +#else + TestVectorTypes<ClassWithSSE, tbb::concurrent_queue<ClassWithSSE> >(); +#endif +#endif /* HAVE_m128 */ +#if HAVE_m256 + if( have_AVX() ) { +#if !TBB_DEPRECATED + TestVectorTypes<ClassWithAVX, tbb::concurrent_queue<ClassWithAVX> >(); + TestVectorTypes<ClassWithAVX, tbb::concurrent_bounded_queue<ClassWithAVX> >(); +#else + TestVectorTypes<ClassWithAVX, tbb::concurrent_queue<ClassWithAVX> >(); +#endif + } +#endif /* HAVE_m256 */ +} + +void TestConcurrentPushPop() +{ + REMARK(" Test concurrent_queue's concurrent push and pop\n"); + for( int nthread=MinThread; nthread<=MaxThread; ++nthread ) { + REMARK(" Testing with %d thread(s)\n", nthread ); +#if TBB_DEPRECATED + TestNegativeQueue<Foo>(nthread); + for( size_t prefill=0; prefill<64; prefill+=(1+prefill/3) ) { + TestPushPop<tbb::concurrent_queue<Foo>,Foo>(prefill,ptrdiff_t(-1),nthread); + TestPushPop<tbb::concurrent_queue<Foo>,Foo>(prefill,ptrdiff_t(1),nthread); + TestPushPop<tbb::concurrent_queue<Foo>,Foo>(prefill,ptrdiff_t(2),nthread); + TestPushPop<tbb::concurrent_queue<Foo>,Foo>(prefill,ptrdiff_t(10),nthread); + TestPushPop<tbb::concurrent_queue<Foo>,Foo>(prefill,ptrdiff_t(100),nthread); + } +#else + for( size_t prefill=0; prefill<64; prefill+=(1+prefill/3) ) { + TestPushPop<ConcQPushPopWrapper<Foo>,Foo>(prefill,ptrdiff_t(-1),nthread); + TestPushPop<ConcQPushPopWrapper<Foo>,Foo>(prefill,ptrdiff_t(1),nthread); + TestPushPop<ConcQPushPopWrapper<Foo>,Foo>(prefill,ptrdiff_t(2),nthread); + TestPushPop<ConcQPushPopWrapper<Foo>,Foo>(prefill,ptrdiff_t(10),nthread); + TestPushPop<ConcQPushPopWrapper<Foo>,Foo>(prefill,ptrdiff_t(100),nthread); + } + for( size_t prefill=0; prefill<64; prefill+=(1+prefill/3) ) { + TestPushPop<tbb::concurrent_bounded_queue<Foo>,Foo>(prefill,ptrdiff_t(-1),nthread); + TestPushPop<tbb::concurrent_bounded_queue<Foo>,Foo>(prefill,ptrdiff_t(1),nthread); + TestPushPop<tbb::concurrent_bounded_queue<Foo>,Foo>(prefill,ptrdiff_t(2),nthread); + TestPushPop<tbb::concurrent_bounded_queue<Foo>,Foo>(prefill,ptrdiff_t(10),nthread); + TestPushPop<tbb::concurrent_bounded_queue<Foo>,Foo>(prefill,ptrdiff_t(100),nthread); + } +#endif /* !TBB_DEPRECATED */ + } +} + +#if TBB_USE_EXCEPTIONS +tbb::atomic<size_t> num_pushed; +tbb::atomic<size_t> num_popped; +tbb::atomic<size_t> failed_pushes; +tbb::atomic<size_t> failed_pops; + +class SimplePushBody { + tbb::concurrent_bounded_queue<int>* q; + int max; +public: + SimplePushBody(tbb::concurrent_bounded_queue<int>* _q, int hi_thr) : q(_q), max(hi_thr) {} + void operator()(int thread_id) const { + if (thread_id == max) { + Harness::Sleep(50); + q->abort(); + return; + } + try { + q->push(42); + ++num_pushed; + } catch ( tbb::user_abort& ) { + ++failed_pushes; + } + } +}; + +class SimplePopBody { + tbb::concurrent_bounded_queue<int>* q; + int max; +public: + SimplePopBody(tbb::concurrent_bounded_queue<int>* _q, int hi_thr) : q(_q), max(hi_thr) {} + void operator()(int thread_id) const { + int e; + if (thread_id == max) { + Harness::Sleep(50); + q->abort(); + return; + } + try { + q->pop(e); + ++num_popped; + } catch ( tbb::user_abort& ) { + ++failed_pops; + } + } +}; +#endif /* TBB_USE_EXCEPTIONS */ + +void TestAbort() { +#if TBB_USE_EXCEPTIONS + for (int nthreads=MinThread; nthreads<=MaxThread; ++nthreads) { + REMARK("Testing Abort on %d thread(s).\n", nthreads); + + REMARK("...testing pushing to zero-sized queue\n"); + tbb::concurrent_bounded_queue<int> iq1; + iq1.set_capacity(0); + for (int i=0; i<10; ++i) { + num_pushed = num_popped = failed_pushes = failed_pops = 0; + SimplePushBody my_push_body1(&iq1, nthreads); + NativeParallelFor( nthreads+1, my_push_body1 ); + ASSERT(num_pushed == 0, "no elements should have been pushed to zero-sized queue"); + ASSERT((int)failed_pushes == nthreads, "All threads should have failed to push an element to zero-sized queue"); + } + + REMARK("...testing pushing to small-sized queue\n"); + tbb::concurrent_bounded_queue<int> iq2; + iq2.set_capacity(2); + for (int i=0; i<10; ++i) { + num_pushed = num_popped = failed_pushes = failed_pops = 0; + SimplePushBody my_push_body2(&iq2, nthreads); + NativeParallelFor( nthreads+1, my_push_body2 ); + ASSERT(num_pushed <= 2, "at most 2 elements should have been pushed to queue of size 2"); + if (nthreads >= 2) + ASSERT((int)failed_pushes == nthreads-2, "nthreads-2 threads should have failed to push an element to queue of size 2"); + int e; + while (iq2.try_pop(e)) ; + } + + REMARK("...testing popping from small-sized queue\n"); + tbb::concurrent_bounded_queue<int> iq3; + iq3.set_capacity(2); + for (int i=0; i<10; ++i) { + num_pushed = num_popped = failed_pushes = failed_pops = 0; + iq3.push(42); + iq3.push(42); + SimplePopBody my_pop_body(&iq3, nthreads); + NativeParallelFor( nthreads+1, my_pop_body); + ASSERT(num_popped <= 2, "at most 2 elements should have been popped from queue of size 2"); + if (nthreads >= 2) + ASSERT((int)failed_pops == nthreads-2, "nthreads-2 threads should have failed to pop an element from queue of size 2"); + else { + int e; + iq3.pop(e); + } + } + + REMARK("...testing pushing and popping from small-sized queue\n"); + tbb::concurrent_bounded_queue<int> iq4; + int cap = nthreads/2; + if (!cap) cap=1; + iq4.set_capacity(cap); + for (int i=0; i<10; ++i) { + num_pushed = num_popped = failed_pushes = failed_pops = 0; + SimplePushBody my_push_body2(&iq4, nthreads); + NativeParallelFor( nthreads+1, my_push_body2 ); + ASSERT((int)num_pushed <= cap, "at most cap elements should have been pushed to queue of size cap"); + if (nthreads >= cap) + ASSERT((int)failed_pushes == nthreads-cap, "nthreads-cap threads should have failed to push an element to queue of size cap"); + SimplePopBody my_pop_body(&iq4, nthreads); + NativeParallelFor( nthreads+1, my_pop_body); + ASSERT((int)num_popped <= cap, "at most cap elements should have been popped from queue of size cap"); + if (nthreads >= cap) + ASSERT((int)failed_pops == nthreads-cap, "nthreads-cap threads should have failed to pop an element from queue of size cap"); + else { + int e; + while (iq4.try_pop(e)) ; + } + } + } +#endif +} + + +template <typename Q> +class FloggerBody : NoAssign { + Q *q; +public: + FloggerBody(Q *q_) : q(q_) {} + void operator()(const int threadID) const { + typedef typename Q::value_type value_type; + value_type elem = value_type(threadID); + for (size_t i=0; i<275; ++i) { + q->push(elem); + (void) q->try_pop(elem); + } + } +}; + +template <typename HackedQRep, typename Q> +void TestFloggerHelp(HackedQRep* hack_rep, Q* q, size_t items_per_page) { + size_t nq = HackedQRep::n_queue; + size_t hack_val = std::numeric_limits<std::size_t>::max() & ~( nq * items_per_page - 1 ); + hack_rep->head_counter = hack_val; + hack_rep->tail_counter = hack_val; + size_t k = hack_rep->tail_counter & -(ptrdiff_t)nq; + + for (size_t i=0; i<nq; ++i) { + hack_rep->array[i].head_counter = k; + hack_rep->array[i].tail_counter = k; + } + NativeParallelFor(MaxThread, FloggerBody<Q>(q)); + ASSERT(q->empty(), "FAILED flogger/empty test."); + delete q; +} + +template <typename T> +void TestFlogger(T /*max*/) { + { // test strict_ppl::concurrent_queue or deprecated::concurrent_queue + tbb::concurrent_queue<T>* q = new tbb::concurrent_queue<T>; +#if !TBB_DEPRECATED + REMARK("Wraparound on strict_ppl::concurrent_queue..."); + hacked_concurrent_queue_rep* hack_rep = ((hacked_concurrent_queue<T>*)(void*)q)->my_rep; + TestFloggerHelp(hack_rep, q, hack_rep->items_per_page); + REMARK(" works.\n"); +#else + REMARK("Wraparound on deprecated::concurrent_queue..."); + hacked_bounded_concurrent_queue* hack_q = (hacked_bounded_concurrent_queue*)(void*)q; + hacked_bounded_concurrent_queue_rep* hack_rep = hack_q->my_rep; + TestFloggerHelp(hack_rep, q, hack_q->items_per_page); + REMARK(" works.\n"); +#endif + } + { // test tbb::concurrent_bounded_queue + tbb::concurrent_bounded_queue<T>* q = new tbb::concurrent_bounded_queue<T>; + REMARK("Wraparound on tbb::concurrent_bounded_queue..."); + hacked_bounded_concurrent_queue* hack_q = (hacked_bounded_concurrent_queue*)(void*)q; + hacked_bounded_concurrent_queue_rep* hack_rep = hack_q->my_rep; + TestFloggerHelp(hack_rep, q, hack_q->items_per_page); + REMARK(" works.\n"); + } +} + +void TestWraparound() { + REMARK("Testing Wraparound...\n"); + TestFlogger(std::numeric_limits<int>::max()); + TestFlogger(std::numeric_limits<unsigned char>::max()); + REMARK("Done Testing Wraparound.\n"); +} + +int TestMain () { + TestEmptiness(); + + TestFullness(); + + TestClearWorks(); + + TestQueueTypeDeclaration(); + + TestQueueIteratorWorks(); + + TestQueueConstructors(); + + TestQueueWorksWithPrimitiveTypes(); + + TestQueueWorksWithSSE(); + + // Test concurrent operations + TestConcurrentPushPop(); + + TestExceptions(); + + TestAbort(); + + TestWraparound(); + + return Harness::Done; +} diff --git a/src/tbb/src/test/test_concurrent_queue.h b/src/tbb/src/test/test_concurrent_queue.h new file mode 100644 index 0000000..706a9c3 --- /dev/null +++ b/src/tbb/src/test/test_concurrent_queue.h @@ -0,0 +1,98 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/atomic.h" +#include "tbb/cache_aligned_allocator.h" +#include "tbb/spin_mutex.h" +#include "tbb/tbb_machine.h" + +#include "tbb/concurrent_monitor.h" + +struct hacked_micro_queue { + tbb::atomic<uintptr_t> head_page; + tbb::atomic<size_t> head_counter; + + tbb::atomic<uintptr_t> tail_page; + tbb::atomic<size_t> tail_counter; + + tbb::spin_mutex page_mutex; + }; + +// hacks for strict_ppl::concurrent_queue +struct hacked_concurrent_queue_rep { + static const size_t phi = 3; + static const size_t n_queue = 8; + + tbb::atomic<size_t> head_counter; + char pad1[tbb::internal::NFS_MaxLineSize-sizeof(tbb::atomic<size_t>)]; + tbb::atomic<size_t> tail_counter; + char pad2[tbb::internal::NFS_MaxLineSize-sizeof(tbb::atomic<size_t>)]; + + size_t items_per_page; + size_t item_size; + tbb::atomic<size_t> n_invalid_entries; + char pad3[tbb::internal::NFS_MaxLineSize-sizeof(size_t)-sizeof(size_t)-sizeof(tbb::atomic<size_t>)]; + + hacked_micro_queue array[n_queue]; +}; + +struct hacked_concurrent_queue_page_allocator { + size_t foo; +}; + +template <typename T> +struct hacked_concurrent_queue : public hacked_concurrent_queue_page_allocator { + hacked_concurrent_queue_rep* my_rep; + typename tbb::cache_aligned_allocator<T>::template rebind<char>::other my_allocator; +}; + +// hacks for concurrent_bounded_queue and deprecated::concurrent_queue +struct hacked_bounded_concurrent_queue_rep { + static const size_t phi = 3; + static const size_t n_queue = 8; + + tbb::atomic<size_t> head_counter; + char cmon_items_avail[ sizeof(tbb::internal::concurrent_monitor) ]; + tbb::atomic<size_t> n_invalid_entries; + char pad1[tbb::internal::NFS_MaxLineSize-((sizeof(tbb::atomic<size_t>)+sizeof(tbb::internal::concurrent_monitor)+sizeof(tbb::atomic<size_t>))&(tbb::internal::NFS_MaxLineSize-1))]; + + tbb::atomic<size_t> tail_counter; + char cmon_slots_avail[ sizeof(tbb::internal::concurrent_monitor) ]; + char pad2[tbb::internal::NFS_MaxLineSize-((sizeof(tbb::atomic<size_t>)+sizeof(tbb::internal::concurrent_monitor))&(tbb::internal::NFS_MaxLineSize-1))]; + hacked_micro_queue array[n_queue]; + + static const ptrdiff_t infinite_capacity = ptrdiff_t(~size_t(0)/2); +}; + +struct hacked_bounded_concurrent_queue { + size_t foo; + hacked_bounded_concurrent_queue_rep* my_rep; + ptrdiff_t my_capacity; + size_t items_per_page; + size_t item_size; +}; diff --git a/src/tbb/src/test/test_concurrent_unordered.cpp b/src/tbb/src/test/test_concurrent_unordered.cpp new file mode 100644 index 0000000..aafa630 --- /dev/null +++ b/src/tbb/src/test/test_concurrent_unordered.cpp @@ -0,0 +1,499 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* Some tests in this source file are based on PPL tests provided by Microsoft. */ + +#define __TBB_EXTRA_DEBUG 1 +#include "tbb/concurrent_unordered_map.h" +#include "tbb/concurrent_unordered_set.h" +#include "tbb/parallel_for.h" +#include "tbb/tick_count.h" +#include <stdio.h> +#include "harness.h" +#include "harness_allocator.h" + +using namespace std; + +typedef local_counting_allocator<debug_allocator<std::pair<const int,int>,std::allocator> > MyAllocator; +typedef tbb::concurrent_unordered_map<int, int, tbb::tbb_hash<int>, std::equal_to<int>, MyAllocator> MyMap; +typedef tbb::concurrent_unordered_set<int, tbb::tbb_hash<int>, std::equal_to<int>, MyAllocator> MySet; + +#define CheckAllocatorE(t,a,f) CheckAllocator(t,a,f,true,__LINE__) +#define CheckAllocatorA(t,a,f) CheckAllocator(t,a,f,false,__LINE__) +template<typename MyTable> +inline void CheckAllocator(MyTable &table, size_t expected_allocs, size_t expected_frees, bool exact = true, int line = 0) { + typename MyTable::allocator_type a = table.get_allocator(); + REMARK("#%d checking allocators: items %u/%u, allocs %u/%u\n", line, + unsigned(a.items_allocated), unsigned(a.items_freed), unsigned(a.allocations), unsigned(a.frees) ); + ASSERT( a.items_allocated == a.allocations, NULL); ASSERT( a.items_freed == a.frees, NULL); + if(exact) { + ASSERT( a.allocations == expected_allocs, NULL); ASSERT( a.frees == expected_frees, NULL); + } else { + ASSERT( a.allocations >= expected_allocs, NULL); ASSERT( a.frees >= expected_frees, NULL); + ASSERT( a.allocations - a.frees == expected_allocs - expected_frees, NULL ); + } +} + +// value generator for cumap +template <typename K, typename V = std::pair<const K, K> > +struct ValueFactory { + static V make(const K &value) { return V(value, value); } + static K key(const V &value) { return value.first; } + static K get(const V& value) { return value.second; } +}; + +// generator for cuset +template <typename T> +struct ValueFactory<T, T> { + static T make(const T &value) { return value; } + static T key(const T &value) { return value; } + static T get(const T &value) { return value; } +}; + +template <typename T> +struct Value : ValueFactory<typename T::key_type, typename T::value_type> {}; + +#if _MSC_VER +#pragma warning(disable: 4189) // warning 4189 -- local variable is initialized but not referenced +#pragma warning(disable: 4127) // warning 4127 -- while (true) has a constant expression in it +#endif + +template<typename ContainerType, typename Iterator, typename RangeType> +std::pair<int,int> CheckRecursiveRange(RangeType range) { + std::pair<int,int> sum(0, 0); // count, sum + for( Iterator i = range.begin(), e = range.end(); i != e; ++i ) { + ++sum.first; sum.second += Value<ContainerType>::get(*i); + } + if( range.is_divisible() ) { + RangeType range2( range, tbb::split() ); + std::pair<int,int> sum1 = CheckRecursiveRange<ContainerType,Iterator, RangeType>( range ); + std::pair<int,int> sum2 = CheckRecursiveRange<ContainerType,Iterator, RangeType>( range2 ); + sum1.first += sum2.first; sum1.second += sum2.second; + ASSERT( sum == sum1, "Mismatched ranges after division"); + } + return sum; +} + +template <typename T> +struct SpecialTests { + static void Test(const char *str) {REMARK("skipped -- specialized %s tests\n", str);} +}; + +template <> +struct SpecialTests <MyMap> +{ + static void Test(const char *str) + { + MyMap cont(0); + const MyMap &ccont(cont); + + // mapped_type& operator[](const key_type& k); + cont[1] = 2; + + // bool empty() const; + ASSERT(!ccont.empty(), "Concurrent container empty after adding an element"); + + // size_type size() const; + ASSERT(ccont.size() == 1, "Concurrent container size incorrect"); + + ASSERT(cont[1] == 2, "Concurrent container size incorrect"); + + // mapped_type& at( const key_type& k ); + // const mapped_type& at(const key_type& k) const; + ASSERT(cont.at(1) == 2, "Concurrent container size incorrect"); + ASSERT(ccont.at(1) == 2, "Concurrent container size incorrect"); + + // iterator find(const key_type& k); + MyMap::const_iterator it = cont.find(1); + ASSERT(it != cont.end() && Value<MyMap>::get(*(it)) == 2, "Element with key 1 not properly found"); + + REMARK("passed -- specialized %s tests\n", str); + } +}; + +template<typename T> +void test_basic(const char * str) +{ + T cont; + const T &ccont(cont); + + // bool empty() const; + ASSERT(ccont.empty(), "Concurrent container not empty after construction"); + + // size_type size() const; + ASSERT(ccont.size() == 0, "Concurrent container not empty after construction"); + + // size_type max_size() const; + ASSERT(ccont.max_size() > 0, "Concurrent container max size invalid"); + + //iterator begin(); + //iterator end(); + ASSERT(cont.begin() == cont.end(), "Concurrent container iterators invalid after construction"); + ASSERT(ccont.begin() == ccont.end(), "Concurrent container iterators invalid after construction"); + ASSERT(cont.cbegin() == cont.cend(), "Concurrent container iterators invalid after construction"); + + //std::pair<iterator, bool> insert(const value_type& obj); + std::pair<typename T::iterator, bool> ins = cont.insert(Value<T>::make(1)); + ASSERT(ins.second == true && Value<T>::get(*(ins.first)) == 1, "Element 1 not properly inserted"); + + // bool empty() const; + ASSERT(!ccont.empty(), "Concurrent container empty after adding an element"); + + // size_type size() const; + ASSERT(ccont.size() == 1, "Concurrent container size incorrect"); + + std::pair<typename T::iterator, bool> ins2 = cont.insert(Value<T>::make(1)); + + if (T::allow_multimapping) + { + // std::pair<iterator, bool> insert(const value_type& obj); + ASSERT(ins2.second == true && Value<T>::get(*(ins2.first)) == 1, "Element 1 not properly inserted"); + + // size_type size() const; + ASSERT(ccont.size() == 2, "Concurrent container size incorrect"); + + // size_type count(const key_type& k) const; + ASSERT(ccont.count(1) == 2, "Concurrent container count(1) incorrect"); + + // std::pair<iterator, iterator> equal_range(const key_type& k); + std::pair<typename T::iterator, typename T::iterator> range = cont.equal_range(1); + typename T::iterator it = range.first; + ASSERT(it != cont.end() && Value<T>::get(*it) == 1, "Element 1 not properly found"); + unsigned int count = 0; + for (; it != range.second; it++) + { + count++; + ASSERT(Value<T>::get(*it) == 1, "Element 1 not properly found"); + } + + ASSERT(count == 2, "Range doesn't have the right number of elements"); + } + else + { + // std::pair<iterator, bool> insert(const value_type& obj); + ASSERT(ins2.second == false && ins2.first == ins.first, "Element 1 should not be re-inserted"); + + // size_type size() const; + ASSERT(ccont.size() == 1, "Concurrent container size incorrect"); + + // size_type count(const key_type& k) const; + ASSERT(ccont.count(1) == 1, "Concurrent container count(1) incorrect"); + + // std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const; + // std::pair<iterator, iterator> equal_range(const key_type& k); + std::pair<typename T::iterator, typename T::iterator> range = cont.equal_range(1); + typename T::iterator i = range.first; + ASSERT(i != cont.end() && Value<T>::get(*i) == 1, "Element 1 not properly found"); + ASSERT(++i == range.second, "Range doesn't have the right number of elements"); + } + + // const_iterator find(const key_type& k) const; + // iterator find(const key_type& k); + typename T::iterator it = cont.find(1); + ASSERT(it != cont.end() && Value<T>::get(*(it)) == 1, "Element 1 not properly found"); + ASSERT(ccont.find(1) == it, "Element 1 not properly found"); + + // iterator insert(const_iterator hint, const value_type& obj); + typename T::iterator it2 = cont.insert(ins.first, Value<T>::make(2)); + ASSERT(Value<T>::get(*it2) == 2, "Element 2 not properly inserted"); + + // T(const T& _Umap) + T newcont = ccont; + ASSERT(T::allow_multimapping ? (newcont.size() == 3) : (newcont.size() == 2), "Copy construction did not copy the elements properly"); + + // size_type unsafe_erase(const key_type& k); + typename T::size_type size = cont.unsafe_erase(1); + ASSERT(T::allow_multimapping ? (size == 2) : (size == 1), "Erase did not remove the right number of elements"); + + // iterator unsafe_erase(const_iterator position); + typename T::iterator it4 = cont.unsafe_erase(cont.find(2)); + ASSERT(it4 == cont.end() && cont.size() == 0, "Erase did not remove the last element properly"); + + // template<class InputIterator> void insert(InputIterator first, InputIterator last); + cont.insert(newcont.begin(), newcont.end()); + ASSERT(T::allow_multimapping ? (cont.size() == 3) : (cont.size() == 2), "Range insert did not copy the elements properly"); + + // iterator unsafe_erase(const_iterator first, const_iterator last); + std::pair<typename T::iterator, typename T::iterator> range2 = newcont.equal_range(1); + newcont.unsafe_erase(range2.first, range2.second); + ASSERT(newcont.size() == 1, "Range erase did not erase the elements properly"); + + // void clear(); + newcont.clear(); + ASSERT(newcont.begin() == newcont.end() && newcont.size() == 0, "Clear did not clear the container"); + + // T& operator=(const T& _Umap) + newcont = ccont; + ASSERT(T::allow_multimapping ? (newcont.size() == 3) : (newcont.size() == 2), "Assignment operator did not copy the elements properly"); + + // void rehash(size_type n); + newcont.rehash(16); + ASSERT(T::allow_multimapping ? (newcont.size() == 3) : (newcont.size() == 2), "Rehash should not affect the container elements"); + + // float load_factor() const; + // float max_load_factor() const; + ASSERT(ccont.load_factor() <= ccont.max_load_factor(), "Load factor invalid"); + + // void max_load_factor(float z); + cont.max_load_factor(16.0f); + ASSERT(ccont.max_load_factor() == 16.0f, "Max load factor not properly changed"); + + // hasher hash_function() const; + ccont.hash_function(); + + // key_equal key_eq() const; + ccont.key_eq(); + + cont.clear(); + CheckAllocatorA(cont, 1, 0); // one dummy is always allocated + for (int i = 0; i < 256; i++) + { + std::pair<typename T::iterator, bool> ins3 = cont.insert(Value<T>::make(i)); + ASSERT(ins3.second == true && Value<T>::get(*(ins3.first)) == i, "Element 1 not properly inserted"); + } + ASSERT(cont.size() == 256, "Wrong number of elements inserted"); + ASSERT((256 == CheckRecursiveRange<T,typename T::iterator>(cont.range()).first), NULL); + ASSERT((256 == CheckRecursiveRange<T,typename T::const_iterator>(ccont.range()).first), NULL); + + // size_type unsafe_bucket_count() const; + ASSERT(ccont.unsafe_bucket_count() == 16, "Wrong number of buckets"); + + // size_type unsafe_max_bucket_count() const; + ASSERT(ccont.unsafe_max_bucket_count() > 65536, "Wrong max number of buckets"); + + for (unsigned int i = 0; i < 256; i++) + { + typename T::size_type buck = ccont.unsafe_bucket(i); + + // size_type unsafe_bucket(const key_type& k) const; + ASSERT(buck < 16, "Wrong bucket mapping"); + } + + for (unsigned int i = 0; i < 16; i++) + { + // size_type unsafe_bucket_size(size_type n); + ASSERT(cont.unsafe_bucket_size(i) == 16, "Wrong number elements in a bucket"); + + // local_iterator unsafe_begin(size_type n); + // const_local_iterator unsafe_begin(size_type n) const; + // local_iterator unsafe_end(size_type n); + // const_local_iterator unsafe_end(size_type n) const; + // const_local_iterator unsafe_cbegin(size_type n) const; + // const_local_iterator unsafe_cend(size_type n) const; + unsigned int count = 0; + for (typename T::iterator bit = cont.unsafe_begin(i); bit != cont.unsafe_end(i); bit++) + { + count++; + } + ASSERT(count == 16, "Bucket iterators are invalid"); + } + + // void swap(T&); + cont.swap(newcont); + ASSERT(newcont.size() == 256, "Wrong number of elements after swap"); + ASSERT(newcont.count(200) == 1, "Element with key 200 not present after swap"); + ASSERT(newcont.count(16) == 1, "Element with key 16 not present after swap"); + ASSERT(newcont.count(99) == 1, "Element with key 99 not present after swap"); + ASSERT(T::allow_multimapping ? (cont.size() == 3) : (cont.size() == 2), "Wrong number of elements after swap"); + + REMARK("passed -- basic %S tests\n", str); + +#if defined (VERBOSE) + REMARK("container dump debug:\n"); + cont._Dump(); + REMARK("container dump release:\n"); + cont.dump(); + REMARK("\n"); +#endif + + SpecialTests<T>::Test(str); +} + +void test_machine() { + ASSERT(__TBB_ReverseByte(0)==0, NULL ); + ASSERT(__TBB_ReverseByte(1)==0x80, NULL ); + ASSERT(__TBB_ReverseByte(0xFE)==0x7F, NULL ); + ASSERT(__TBB_ReverseByte(0xFF)==0xFF, NULL ); +} + +template<typename T> +class FillTable: NoAssign { + T &table; + const int items; + typedef std::pair<typename T::iterator, bool> pairIB; +public: + FillTable(T &t, int i) : table(t), items(i) { + ASSERT( !(items&1) && items > 100, NULL); + } + void operator()(int threadn) const { + if( threadn == 0 ) { // Fill even keys forward (single thread) + bool last_inserted = true; + for( int i = 0; i < items; i+=2 ) { + pairIB pib = table.insert(Value<T>::make(i)); + ASSERT(Value<T>::get(*(pib.first)) == i, "Element not properly inserted"); + ASSERT( last_inserted || !pib.second, "Previous key was not inserted but this is inserted" ); + last_inserted = pib.second; + } + } else if( threadn == 1 ) { // Fill even keys backward (single thread) + bool last_inserted = true; + for( int i = items-2; i >= 0; i-=2 ) { + pairIB pib = table.insert(Value<T>::make(i)); + ASSERT(Value<T>::get(*(pib.first)) == i, "Element not properly inserted"); + ASSERT( last_inserted || !pib.second, "Previous key was not inserted but this is inserted" ); + last_inserted = pib.second; + } + } else if( !(threadn&1) ) { // Fill odd keys forward (multiple threads) + for( int i = 1; i < items; i+=2 ) { + pairIB pib = table.insert(Value<T>::make(i)); + ASSERT(Value<T>::get(*(pib.first)) == i, "Element not properly inserted"); + } + } else { // Check odd keys backward (multiple threads) + bool last_found = false; + for( int i = items-1; i >= 0; i-=2 ) { + typename T::iterator it = table.find(i); + if( it != table.end() ) { // found + ASSERT(Value<T>::get(*it) == i, "Element not properly inserted"); + last_found = true; + } else ASSERT( !last_found, "Previous key was found but this is not" ); + } + } + } +}; + +typedef tbb::atomic<unsigned char> AtomicByte; + +template<typename ContainerType, typename RangeType> +struct ParallelTraverseBody: NoAssign { + const int n; + AtomicByte* const array; + ParallelTraverseBody( AtomicByte an_array[], int a_n ) : + n(a_n), array(an_array) + {} + void operator()( const RangeType& range ) const { + for( typename RangeType::iterator i = range.begin(); i!=range.end(); ++i ) { + int k = Value<ContainerType>::key(*i); + ASSERT( k == Value<ContainerType>::get(*i), NULL ); + ASSERT( 0<=k && k<n, NULL ); + array[k]++; + } + } +}; + +void CheckRange( AtomicByte array[], int n ) { + for( int k=0; k<n; ++k ) { + if( array[k] != 1 ) { + REPORT("array[%d]=%d\n", k, int(array[k])); + ASSERT(false,NULL); + } + } +} + +template<typename T> +class CheckTable: NoAssign { + T &table; +public: + CheckTable(T &t) : NoAssign(), table(t) {} + void operator()(int i) const { + int c = (int)table.count( i ); + ASSERT( c, "must exist" ); + } +}; + +template<typename T> +class AssignBody: NoAssign { + T &table; +public: + AssignBody(T &t) : NoAssign(), table(t) {} + void operator()(int i) const { + table[i] = i; + } +}; + +template<> +class AssignBody<MySet>: NoAssign { + MySet &table; +public: + AssignBody(MySet &t) : NoAssign(), table(t) {} + void operator()(int i) const { + table.insert(i); + } +}; + +template<typename T> +void test_concurrent(const char *tablename) { +#if TBB_USE_ASSERT + int items = 2000; +#else + int items = 100000; +#endif + T table(items/1000); + tbb::tick_count t0 = tbb::tick_count::now(); + #if __bgp__ + NativeParallelFor( 6/*min 6*/, FillTable<T>(table, items) ); + #else + NativeParallelFor( 16/*min 6*/, FillTable<T>(table, items) ); + #endif + tbb::tick_count t1 = tbb::tick_count::now(); + REMARK( "time for filling '%s' by %d items = %g\n", tablename, items, (t1-t0).seconds() ); + ASSERT( int(table.size()) == items, NULL); + + AtomicByte* array = new AtomicByte[items]; + memset( array, 0, items*sizeof(AtomicByte) ); + + typename T::range_type r = table.range(); + ASSERT((items == CheckRecursiveRange<T,typename T::iterator>(r).first), NULL); + tbb::parallel_for( r, ParallelTraverseBody<T, typename T::const_range_type>( array, items )); + CheckRange( array, items ); + + const T &const_table = table; + memset( array, 0, items*sizeof(AtomicByte) ); + typename T::const_range_type cr = const_table.range(); + ASSERT((items == CheckRecursiveRange<T,typename T::const_iterator>(cr).first), NULL); + tbb::parallel_for( cr, ParallelTraverseBody<T, typename T::const_range_type>( array, items )); + CheckRange( array, items ); + delete[] array; + + tbb::parallel_for( 0, items, CheckTable<T>( table ) ); + + table.clear(); + CheckAllocatorA(table, items+1, items); // one dummy is always allocated + + for(int i=0; i<10000; ++i) { + tbb::parallel_for( 0, 8, AssignBody<T>( table ) ); + table.clear(); + } +} + +int TestMain () { + test_machine(); + test_basic<MyMap>("concurrent unordered map"); + test_concurrent<MyMap>("concurrent unordered map"); + test_basic<MySet>("concurrent unordered set"); + test_concurrent<MySet>("concurrent unordered set"); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_concurrent_vector.cpp b/src/tbb/src/test/test_concurrent_vector.cpp new file mode 100644 index 0000000..e21d7a1 --- /dev/null +++ b/src/tbb/src/test/test_concurrent_vector.cpp @@ -0,0 +1,1025 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/concurrent_vector.h" +#include "tbb/tbb_allocator.h" +#include "tbb/cache_aligned_allocator.h" +#include "tbb/tbb_exception.h" +#include <cstdio> +#include <cstdlib> +#include "harness_report.h" +#include "harness_assert.h" +#include "harness_allocator.h" + +#if TBB_USE_EXCEPTIONS +static bool known_issue_verbose = false; +#define KNOWN_ISSUE(msg) if(!known_issue_verbose) known_issue_verbose = true, REPORT(msg) +#endif /* TBB_USE_EXCEPTIONS */ + +tbb::atomic<long> FooCount; +long MaxFooCount = 0; + +//! Problem size +const size_t N = 500000; + +//! Exception for concurrent_vector +class Foo_exception : public std::bad_alloc { +public: + virtual const char *what() const throw() { return "out of Foo limit"; } + virtual ~Foo_exception() throw() {} +}; + +static const int initial_value_of_bar = 42; +struct Foo { + int my_bar; +public: + enum State { + ZeroInitialized=0, + DefaultInitialized=0xDEFAUL, + CopyInitialized=0xC0314, + Destroyed=0xDEADF00 + } state; + bool is_valid() const { + return state==DefaultInitialized||state==CopyInitialized; + } + bool is_valid_or_zero() const { + return is_valid()||(state==ZeroInitialized && !my_bar); + } + int& zero_bar() { + ASSERT( is_valid_or_zero(), NULL ); + return my_bar; + } + int& bar() { + ASSERT( is_valid(), NULL ); + return my_bar; + } + int bar() const { + ASSERT( is_valid(), NULL ); + return my_bar; + } + Foo( int barr = initial_value_of_bar ) { + my_bar = barr; + if(MaxFooCount && FooCount >= MaxFooCount) + __TBB_THROW( Foo_exception() ); + FooCount++; + state = DefaultInitialized; + } + Foo( const Foo& foo ) { + my_bar = foo.my_bar; + ASSERT( foo.is_valid_or_zero(), "bad source for copy" ); + if(MaxFooCount && FooCount >= MaxFooCount) + __TBB_THROW( Foo_exception() ); + FooCount++; + state = CopyInitialized; + } + ~Foo() { + ASSERT( is_valid_or_zero(), NULL ); + my_bar = ~initial_value_of_bar; + if(state != ZeroInitialized) --FooCount; + state = Destroyed; + } + bool operator==(const Foo &f) const { return my_bar == f.my_bar; } + bool operator<(const Foo &f) const { return my_bar < f.my_bar; } + bool is_const() const {return true;} + bool is_const() {return false;} +protected: + char reserve[1]; + void operator=( const Foo& ) {} +}; + +class FooWithAssign: public Foo { +public: + void operator=( const FooWithAssign& x ) { + my_bar = x.my_bar; + ASSERT( x.is_valid_or_zero(), "bad source for assignment" ); + ASSERT( is_valid(), NULL ); + } + bool operator==(const Foo &f) const { return my_bar == f.my_bar; } + bool operator<(const Foo &f) const { return my_bar < f.my_bar; } +}; + +class FooIterator: public std::iterator<std::input_iterator_tag,FooWithAssign> { + int x_bar; +public: + FooIterator(int x) { + x_bar = x; + } + FooIterator &operator++() { + x_bar++; return *this; + } + FooWithAssign operator*() { + FooWithAssign foo; foo.bar() = x_bar; + return foo; + } + bool operator!=(const FooIterator &i) { return x_bar != i.x_bar; } +}; + +inline void NextSize( int& s ) { + if( s<=32 ) ++s; + else s += s/10; +} + +//! Check vector have expected size and filling +template<typename vector_t> +static void CheckVector( const vector_t& cv, size_t expected_size, size_t old_size ) { + ASSERT( cv.capacity()>=expected_size, NULL ); + ASSERT( cv.size()==expected_size, NULL ); + ASSERT( cv.empty()==(expected_size==0), NULL ); + for( int j=0; j<int(expected_size); ++j ) { + if( cv[j].bar()!=~j ) + REPORT("ERROR on line %d for old_size=%ld expected_size=%ld j=%d\n",__LINE__,long(old_size),long(expected_size),j); + } +} + +//! Test of assign, grow, copying with various sizes +void TestResizeAndCopy() { + typedef static_counting_allocator<debug_allocator<Foo,std::allocator>, std::size_t> allocator_t; + typedef tbb::concurrent_vector<Foo, allocator_t> vector_t; + allocator_t::init_counters(); + for( int old_size=0; old_size<=128; NextSize( old_size ) ) { + for( int new_size=0; new_size<=1280; NextSize( new_size ) ) { + long count = FooCount; + vector_t v; + ASSERT( count==FooCount, NULL ); + v.assign(old_size/2, Foo() ); + ASSERT( count+old_size/2==FooCount, NULL ); + for( int j=0; j<old_size/2; ++j ) + ASSERT( v[j].state == Foo::CopyInitialized, NULL); + v.assign(FooIterator(0), FooIterator(old_size)); + v.resize(new_size, Foo(33) ); + ASSERT( count+new_size==FooCount, NULL ); + for( int j=0; j<new_size; ++j ) { + int expected = j<old_size ? j : 33; + if( v[j].bar()!=expected ) + REPORT("ERROR on line %d for old_size=%ld new_size=%ld v[%ld].bar()=%d != %d\n",__LINE__,long(old_size),long(new_size),long(j),v[j].bar(), expected); + } + ASSERT( v.size()==size_t(new_size), NULL ); + for( int j=0; j<new_size; ++j ) { + v[j].bar() = ~j; + } + const vector_t& cv = v; + // Try copy constructor + vector_t copy_of_v(cv); + CheckVector(cv,new_size,old_size); + ASSERT( !(v != copy_of_v), NULL ); + v.clear(); + ASSERT( v.empty(), NULL ); + swap(v, copy_of_v); + ASSERT( copy_of_v.empty(), NULL ); + CheckVector(v,new_size,old_size); + } + } + ASSERT( allocator_t::items_allocated == allocator_t::items_freed, NULL); + ASSERT( allocator_t::allocations == allocator_t::frees, NULL); +} + +//! Test reserve, compact, capacity +void TestCapacity() { + typedef static_counting_allocator<debug_allocator<Foo,tbb::cache_aligned_allocator>, std::size_t> allocator_t; + typedef tbb::concurrent_vector<Foo, allocator_t> vector_t; + allocator_t::init_counters(); + for( size_t old_size=0; old_size<=11000; old_size=(old_size<5 ? old_size+1 : 3*old_size) ) { + for( size_t new_size=0; new_size<=11000; new_size=(new_size<5 ? new_size+1 : 3*new_size) ) { + long count = FooCount; + { + vector_t v; v.reserve(old_size); + ASSERT( v.capacity()>=old_size, NULL ); + v.reserve( new_size ); + ASSERT( v.capacity()>=old_size, NULL ); + ASSERT( v.capacity()>=new_size, NULL ); + ASSERT( v.empty(), NULL ); + size_t fill_size = 2*new_size; + for( size_t i=0; i<fill_size; ++i ) { + ASSERT( size_t(FooCount)==count+i, NULL ); +#if TBB_DEPRECATED + size_t j = v.grow_by(1); +#else + size_t j = v.grow_by(1) - v.begin(); +#endif + ASSERT( j==i, NULL ); + v[j].bar() = int(~j); + } + vector_t copy_of_v(v); // should allocate first segment with same size as for shrink_to_fit() + if(__TBB_Log2(/*reserved size*/old_size|1) > __TBB_Log2(fill_size|1) ) + ASSERT( v.capacity() != copy_of_v.capacity(), NULL ); + v.shrink_to_fit(); + ASSERT( v.capacity() == copy_of_v.capacity(), NULL ); + CheckVector(v, new_size*2, old_size); // check vector correctness + ASSERT( v==copy_of_v, NULL ); // TODO: check also segments layout equality + } + ASSERT( FooCount==count, NULL ); + } + } + ASSERT( allocator_t::items_allocated == allocator_t::items_freed, NULL); + ASSERT( allocator_t::allocations == allocator_t::frees, NULL); +} + +struct AssignElement { + typedef tbb::concurrent_vector<int>::range_type::iterator iterator; + iterator base; + void operator()( const tbb::concurrent_vector<int>::range_type& range ) const { + for( iterator i=range.begin(); i!=range.end(); ++i ) { + if( *i!=0 ) + REPORT("ERROR for v[%ld]\n", long(i-base)); + *i = int(i-base); + } + } + AssignElement( iterator base_ ) : base(base_) {} +}; + +struct CheckElement { + typedef tbb::concurrent_vector<int>::const_range_type::iterator iterator; + iterator base; + void operator()( const tbb::concurrent_vector<int>::const_range_type& range ) const { + for( iterator i=range.begin(); i!=range.end(); ++i ) + if( *i != int(i-base) ) + REPORT("ERROR for v[%ld]\n", long(i-base)); + } + CheckElement( iterator base_ ) : base(base_) {} +}; + +#include "tbb/tick_count.h" +#include "tbb/parallel_for.h" +#include "harness.h" + +//! Test parallel access by iterators +void TestParallelFor( int nthread ) { + typedef tbb::concurrent_vector<int> vector_t; + vector_t v; + v.resize(N); + tbb::tick_count t0 = tbb::tick_count::now(); + REMARK("Calling parallel_for with %ld threads\n",long(nthread)); + tbb::parallel_for( v.range(10000), AssignElement(v.begin()) ); + tbb::tick_count t1 = tbb::tick_count::now(); + const vector_t& u = v; + tbb::parallel_for( u.range(10000), CheckElement(u.begin()) ); + tbb::tick_count t2 = tbb::tick_count::now(); + REMARK("Time for parallel_for: assign time = %8.5f, check time = %8.5f\n", + (t1-t0).seconds(),(t2-t1).seconds()); + for( long i=0; size_t(i)<v.size(); ++i ) + if( v[i]!=i ) + REPORT("ERROR for v[%ld]\n", i); +} + +template<typename Iterator1, typename Iterator2> +void TestIteratorAssignment( Iterator2 j ) { + Iterator1 i(j); + ASSERT( i==j, NULL ); + ASSERT( !(i!=j), NULL ); + Iterator1 k; + k = j; + ASSERT( k==j, NULL ); + ASSERT( !(k!=j), NULL ); +} + +template<typename Range1, typename Range2> +void TestRangeAssignment( Range2 r2 ) { + Range1 r1(r2); r1 = r2; +} + +template<typename Iterator, typename T> +void TestIteratorTraits() { + AssertSameType( static_cast<typename Iterator::difference_type*>(0), static_cast<ptrdiff_t*>(0) ); + AssertSameType( static_cast<typename Iterator::value_type*>(0), static_cast<T*>(0) ); + AssertSameType( static_cast<typename Iterator::pointer*>(0), static_cast<T**>(0) ); + AssertSameType( static_cast<typename Iterator::iterator_category*>(0), static_cast<std::random_access_iterator_tag*>(0) ); + T x; + typename Iterator::reference xr = x; + typename Iterator::pointer xp = &x; + ASSERT( &xr==xp, NULL ); +} + +template<typename Vector, typename Iterator> +void CheckConstIterator( const Vector& u, int i, const Iterator& cp ) { + typename Vector::const_reference pref = *cp; + if( pref.bar()!=i ) + REPORT("ERROR for u[%ld] using const_iterator\n", long(i)); + typename Vector::difference_type delta = cp-u.begin(); + ASSERT( delta==i, NULL ); + if( u[i].bar()!=i ) + REPORT("ERROR for u[%ld] using subscripting\n", long(i)); + ASSERT( u.begin()[i].bar()==i, NULL ); +} + +template<typename Iterator1, typename Iterator2, typename V> +void CheckIteratorComparison( V& u ) { + V u2 = u; + Iterator1 i = u.begin(); + + for( int i_count=0; i_count<100; ++i_count ) { + Iterator2 j = u.begin(); + Iterator2 i2 = u2.begin(); + for( int j_count=0; j_count<100; ++j_count ) { + ASSERT( (i==j)==(i_count==j_count), NULL ); + ASSERT( (i!=j)==(i_count!=j_count), NULL ); + ASSERT( (i-j)==(i_count-j_count), NULL ); + ASSERT( (i<j)==(i_count<j_count), NULL ); + ASSERT( (i>j)==(i_count>j_count), NULL ); + ASSERT( (i<=j)==(i_count<=j_count), NULL ); + ASSERT( (i>=j)==(i_count>=j_count), NULL ); + ASSERT( !(i==i2), NULL ); + ASSERT( i!=i2, NULL ); + ++j; + ++i2; + } + ++i; + } +} + +//! Test sequential iterators for vector type V. +/** Also does timing. */ +template<typename T> +void TestSequentialFor() { + typedef tbb::concurrent_vector<FooWithAssign> V; + V v(N); + ASSERT(v.grow_by(0) == v.grow_by(0, FooWithAssign()), NULL); + + // Check iterator + tbb::tick_count t0 = tbb::tick_count::now(); + typename V::iterator p = v.begin(); + ASSERT( !(*p).is_const(), NULL ); + ASSERT( !p->is_const(), NULL ); + for( int i=0; size_t(i)<v.size(); ++i, ++p ) { + if( (*p).state!=Foo::DefaultInitialized ) + REPORT("ERROR for v[%ld]\n", long(i)); + typename V::reference pref = *p; + pref.bar() = i; + typename V::difference_type delta = p-v.begin(); + ASSERT( delta==i, NULL ); + ASSERT( -delta<=0, "difference type not signed?" ); + } + tbb::tick_count t1 = tbb::tick_count::now(); + + // Check const_iterator going forwards + const V& u = v; + typename V::const_iterator cp = u.begin(); + ASSERT( cp == v.cbegin(), NULL ); + ASSERT( (*cp).is_const(), NULL ); + ASSERT( cp->is_const(), NULL ); + ASSERT( *cp == v.front(), NULL); + for( int i=0; size_t(i)<u.size(); ++i ) { + CheckConstIterator(u,i,cp); + V::const_iterator &cpr = ++cp; + ASSERT( &cpr == &cp, "preincrement not returning a reference?"); + } + tbb::tick_count t2 = tbb::tick_count::now(); + REMARK("Time for serial for: assign time = %8.5f, check time = %8.5f\n", + (t1-t0).seconds(),(t2-t1).seconds()); + + // Now go backwards + cp = u.end(); + ASSERT( cp == v.cend(), NULL ); + for( int i=int(u.size()); i>0; ) { + --i; + V::const_iterator &cpr = --cp; + ASSERT( &cpr == &cp, "predecrement not returning a reference?"); + if( i>0 ) { + typename V::const_iterator cp_old = cp--; + int here = (*cp_old).bar(); + ASSERT( here==u[i].bar(), NULL ); + typename V::const_iterator cp_new = cp++; + int prev = (*cp_new).bar(); + ASSERT( prev==u[i-1].bar(), NULL ); + } + CheckConstIterator(u,i,cp); + } + + // Now go forwards and backwards + ptrdiff_t k = 0; + cp = u.begin(); + for( size_t i=0; i<u.size(); ++i ) { + CheckConstIterator(u,int(k),cp); + typename V::difference_type delta = i*3 % u.size(); + if( 0<=k+delta && size_t(k+delta)<u.size() ) { + V::const_iterator &cpr = (cp += delta); + ASSERT( &cpr == &cp, "+= not returning a reference?"); + k += delta; + } + delta = i*7 % u.size(); + if( 0<=k-delta && size_t(k-delta)<u.size() ) { + if( i&1 ) { + V::const_iterator &cpr = (cp -= delta); + ASSERT( &cpr == &cp, "-= not returning a reference?"); + } else + cp = cp - delta; // Test operator- + k -= delta; + } + } + + for( int i=0; size_t(i)<u.size(); i=(i<50?i+1:i*3) ) + for( int j=-i; size_t(i+j)<u.size(); j=(j<50?j+1:j*5) ) { + ASSERT( (u.begin()+i)[j].bar()==i+j, NULL ); + ASSERT( (v.begin()+i)[j].bar()==i+j, NULL ); + ASSERT((v.cbegin()+i)[j].bar()==i+j, NULL ); + ASSERT( (i+u.begin())[j].bar()==i+j, NULL ); + ASSERT( (i+v.begin())[j].bar()==i+j, NULL ); + ASSERT((i+v.cbegin())[j].bar()==i+j, NULL ); + } + + CheckIteratorComparison<typename V::iterator, typename V::iterator>(v); + CheckIteratorComparison<typename V::iterator, typename V::const_iterator>(v); + CheckIteratorComparison<typename V::const_iterator, typename V::iterator>(v); + CheckIteratorComparison<typename V::const_iterator, typename V::const_iterator>(v); + + TestIteratorAssignment<typename V::const_iterator>( u.begin() ); + TestIteratorAssignment<typename V::const_iterator>( v.begin() ); + TestIteratorAssignment<typename V::const_iterator>( v.cbegin() ); + TestIteratorAssignment<typename V::iterator>( v.begin() ); + // doesn't compile as expected: TestIteratorAssignment<typename V::iterator>( u.begin() ); + + TestRangeAssignment<typename V::const_range_type>( u.range() ); + TestRangeAssignment<typename V::const_range_type>( v.range() ); + TestRangeAssignment<typename V::range_type>( v.range() ); + // doesn't compile as expected: TestRangeAssignment<typename V::range_type>( u.range() ); + + // Check reverse_iterator + typename V::reverse_iterator rp = v.rbegin(); + for( size_t i=v.size(); i>0; --i, ++rp ) { + typename V::reference pref = *rp; + ASSERT( size_t(pref.bar())==i-1, NULL ); + ASSERT( rp!=v.rend(), NULL ); + } + ASSERT( rp==v.rend(), NULL ); + + // Check const_reverse_iterator + typename V::const_reverse_iterator crp = u.rbegin(); + ASSERT( crp == v.crbegin(), NULL ); + ASSERT( *crp == v.back(), NULL); + for( size_t i=v.size(); i>0; --i, ++crp ) { + typename V::const_reference cpref = *crp; + ASSERT( size_t(cpref.bar())==i-1, NULL ); + ASSERT( crp!=u.rend(), NULL ); + } + ASSERT( crp == u.rend(), NULL ); + ASSERT( crp == v.crend(), NULL ); + + TestIteratorAssignment<typename V::const_reverse_iterator>( u.rbegin() ); + TestIteratorAssignment<typename V::reverse_iterator>( v.rbegin() ); + + // test compliance with C++ Standard 2003, clause 23.1.1p9 + { + tbb::concurrent_vector<int> v1, v2(1, 100); + v1.assign(1, 100); ASSERT(v1 == v2, NULL); + ASSERT(v1.size() == 1 && v1[0] == 100, "used integral iterators"); + } + + // cross-allocator tests +#if !defined(_WIN64) || defined(_CPPLIB_VER) + typedef local_counting_allocator<std::allocator<int>, size_t> allocator1_t; + typedef tbb::cache_aligned_allocator<void> allocator2_t; + typedef tbb::concurrent_vector<FooWithAssign, allocator1_t> V1; + typedef tbb::concurrent_vector<FooWithAssign, allocator2_t> V2; + V1 v1( v ); // checking cross-allocator copying + V2 v2( 10 ); v2 = v1; // checking cross-allocator assignment + ASSERT( (v1 == v) && !(v2 != v), NULL); + ASSERT( !(v1 < v) && !(v2 > v), NULL); + ASSERT( (v1 <= v) && (v2 >= v), NULL); +#endif +} + +static const size_t Modulus = 7; + +template<typename MyVector> +class GrowToAtLeast: NoAssign { + MyVector& my_vector; +public: + void operator()( const tbb::blocked_range<size_t>& range ) const { + for( size_t i=range.begin(); i!=range.end(); ++i ) { + size_t n = my_vector.size(); + size_t req = (i % (2*n+1))+1; +#if TBB_DEPRECATED + my_vector.grow_to_at_least(req); +#else + typename MyVector::iterator p = my_vector.grow_to_at_least(req); + if( p-my_vector.begin() < typename MyVector::difference_type(req) ) + ASSERT( p->state == Foo::DefaultInitialized || p->state == Foo::ZeroInitialized, NULL); +#endif + ASSERT( my_vector.size()>=req, NULL ); + } + } + GrowToAtLeast( MyVector& vector ) : my_vector(vector) {} +}; + +void TestConcurrentGrowToAtLeast() { + typedef static_counting_allocator< tbb::zero_allocator<Foo> > MyAllocator; + typedef tbb::concurrent_vector<Foo, MyAllocator> MyVector; + MyAllocator::init_counters(); + MyVector v(2, Foo(), MyAllocator()); + for( size_t s=1; s<1000; s*=10 ) { + tbb::parallel_for( tbb::blocked_range<size_t>(0,10000*s,s), GrowToAtLeast<MyVector>(v), tbb::simple_partitioner() ); + } + v.clear(); + ASSERT( 0 == v.get_allocator().frees, NULL); + v.shrink_to_fit(); + size_t items_allocated = v.get_allocator().items_allocated, + items_freed = v.get_allocator().items_freed; + size_t allocations = v.get_allocator().allocations, + frees = v.get_allocator().frees; + ASSERT( items_allocated == items_freed, NULL); + ASSERT( allocations == frees, NULL); +} + +//! Test concurrent invocations of method concurrent_vector::grow_by +template<typename MyVector> +class GrowBy: NoAssign { + MyVector& my_vector; +public: + void operator()( const tbb::blocked_range<int>& range ) const { + ASSERT( range.begin() < range.end(), NULL ); +#if TBB_DEPRECATED + for( int i=range.begin(); i!=range.end(); ++i ) +#else + int i = range.begin(), h = (range.end() - i) / 2; + typename MyVector::iterator s = my_vector.grow_by(h); + for( h += i; i < h; ++i, ++s ) + s->bar() = i; + for(; i!=range.end(); ++i ) +#endif + { + if( i&1 ) { +#if TBB_DEPRECATED + typename MyVector::reference element = my_vector[my_vector.grow_by(1)]; + element.bar() = i; +#else + my_vector.grow_by(1)->bar() = i; +#endif + } else { + typename MyVector::value_type f; + f.bar() = i; +#if TBB_DEPRECATED + size_t r; +#else + typename MyVector::iterator r; +#endif + if( i&2 ) + r = my_vector.push_back( f ); + else + r = my_vector.grow_by(1, f); +#if TBB_DEPRECATED + ASSERT( my_vector[r].bar()==i, NULL ); +#else + ASSERT( r->bar()==i, NULL ); +#endif + } + } + } + GrowBy( MyVector& vector ) : my_vector(vector) {} +}; + +//! Test concurrent invocations of method concurrent_vector::grow_by +void TestConcurrentGrowBy( int nthread ) { + + typedef static_counting_allocator<debug_allocator<Foo> > MyAllocator; + typedef tbb::concurrent_vector<Foo, MyAllocator> MyVector; + + MyAllocator::init_counters(); + { + int m = 100000; MyAllocator a; + MyVector v( a ); + tbb::parallel_for( tbb::blocked_range<int>(0,m,100), GrowBy<MyVector>(v), tbb::simple_partitioner() ); + ASSERT( v.size()==size_t(m), NULL ); + + // Verify that v is a permutation of 0..m + int inversions = 0, def_inits = 0, copy_inits = 0; + bool* found = new bool[m]; + memset( found, 0, m ); + for( int i=0; i<m; ++i ) { + if( v[i].state == Foo::DefaultInitialized ) ++def_inits; + else if( v[i].state == Foo::CopyInitialized ) ++copy_inits; + else { + REMARK("i: %d ", i); + ASSERT( false, "v[i] seems not initialized"); + } + int index = v[i].bar(); + ASSERT( !found[index], NULL ); + found[index] = true; + if( i>0 ) + inversions += v[i].bar()<v[i-1].bar(); + } + for( int i=0; i<m; ++i ) { + ASSERT( found[i], NULL ); + ASSERT( nthread>1 || v[i].bar()==i, "sequential execution is wrong" ); + } + delete[] found; + REMARK("Initialization by default constructor: %d, by copy: %d\n", def_inits, copy_inits); + ASSERT( def_inits >= m/2, NULL ); + ASSERT( copy_inits >= m/4, NULL ); + if( nthread>1 && inversions<m/20 ) + REPORT("Warning: not much concurrency in TestConcurrentGrowBy (%d inversions)\n", inversions); + } + size_t items_allocated = MyAllocator::items_allocated, + items_freed = MyAllocator::items_freed; + size_t allocations = MyAllocator::allocations, + frees = MyAllocator::frees; + ASSERT( items_allocated == items_freed, NULL); + ASSERT( allocations == frees, NULL); +} + +//! Test the assignment operator and swap +void TestAssign() { + typedef tbb::concurrent_vector<FooWithAssign, local_counting_allocator<std::allocator<FooWithAssign>, size_t > > vector_t; + local_counting_allocator<std::allocator<FooWithAssign>, size_t > init_alloc; + init_alloc.allocations = 100; + for( int dst_size=1; dst_size<=128; NextSize( dst_size ) ) { + for( int src_size=2; src_size<=128; NextSize( src_size ) ) { + vector_t u(FooIterator(0), FooIterator(src_size), init_alloc); + for( int i=0; i<src_size; ++i ) + ASSERT( u[i].bar()==i, NULL ); + vector_t v(dst_size, FooWithAssign(), init_alloc); + for( int i=0; i<dst_size; ++i ) { + ASSERT( v[i].state==Foo::CopyInitialized, NULL ); + v[i].bar() = ~i; + } + ASSERT( v != u, NULL); + v.swap(u); + CheckVector(u, dst_size, src_size); + u.swap(v); + // using assignment + v = u; + ASSERT( v == u, NULL); + u.clear(); + ASSERT( u.size()==0, NULL ); + ASSERT( v.size()==size_t(src_size), NULL ); + for( int i=0; i<src_size; ++i ) + ASSERT( v[i].bar()==i, NULL ); + ASSERT( 0 == u.get_allocator().frees, NULL); + u.shrink_to_fit(); // deallocate unused memory + size_t items_allocated = u.get_allocator().items_allocated, + items_freed = u.get_allocator().items_freed; + size_t allocations = u.get_allocator().allocations, + frees = u.get_allocator().frees + 100; + ASSERT( items_allocated == items_freed, NULL); + ASSERT( allocations == frees, NULL); + } + } +} + +// Test the comparison operators +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include <string> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +void TestComparison() { + std::string str[3]; str[0] = "abc"; + str[1].assign("cba"); + str[2].assign("abc"); // same as 0th + tbb::concurrent_vector<char> var[3]; + var[0].assign(str[0].begin(), str[0].end()); + var[1].assign(str[0].rbegin(), str[0].rend()); + var[2].assign(var[1].rbegin(), var[1].rend()); // same as 0th + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + ASSERT( (var[i] == var[j]) == (str[i] == str[j]), NULL ); + ASSERT( (var[i] != var[j]) == (str[i] != str[j]), NULL ); + ASSERT( (var[i] < var[j]) == (str[i] < str[j]), NULL ); + ASSERT( (var[i] > var[j]) == (str[i] > str[j]), NULL ); + ASSERT( (var[i] <= var[j]) == (str[i] <= str[j]), NULL ); + ASSERT( (var[i] >= var[j]) == (str[i] >= str[j]), NULL ); + } + } +} + +//------------------------------------------------------------------------ +// Regression test for problem where on oversubscription caused +// concurrent_vector::grow_by to run very slowly (TR#196). +//------------------------------------------------------------------------ + +#include "tbb/task_scheduler_init.h" +#include <math.h> + +typedef unsigned long Number; + +static tbb::concurrent_vector<Number> Primes; + +class FindPrimes { + bool is_prime( Number val ) const { + int limit, factor = 3; + if( val<5u ) + return val==2; + else { + limit = long(sqrtf(float(val))+0.5f); + while( factor<=limit && val % factor ) + ++factor; + return factor>limit; + } + } +public: + void operator()( const tbb::blocked_range<Number>& r ) const { + for( Number i=r.begin(); i!=r.end(); ++i ) { + if( i%2 && is_prime(i) ) { +#if TBB_DEPRECATED + Primes[Primes.grow_by(1)] = i; +#else + Primes.push_back( i ); +#endif + } + } + } +}; + +double TimeFindPrimes( int nthread ) { + Primes.clear(); + Primes.reserve(1000000);// TODO: or compact()? + tbb::task_scheduler_init init(nthread); + tbb::tick_count t0 = tbb::tick_count::now(); + tbb::parallel_for( tbb::blocked_range<Number>(0,1000000,500), FindPrimes() ); + tbb::tick_count t1 = tbb::tick_count::now(); + return (t1-t0).seconds(); +} + +void TestFindPrimes() { + // Time fully subscribed run. + double t2 = TimeFindPrimes( tbb::task_scheduler_init::automatic ); + + // Time parallel run that is very likely oversubscribed. +#if _XBOX + double t128 = TimeFindPrimes(32); //XBOX360 can't handle too many threads +#else + double t128 = TimeFindPrimes(128); +#endif + REMARK("TestFindPrimes: t2==%g t128=%g k=%g\n", t2, t128, t128/t2); + + // We allow the 128-thread run a little extra time to allow for thread overhead. + // Theoretically, following test will fail on machine with >128 processors. + // But that situation is not going to come up in the near future, + // and the generalization to fix the issue is not worth the trouble. + if( t128 > 1.3*t2 ) { + REPORT("Warning: grow_by is pathetically slow: t2==%g t128=%g k=%g\n", t2, t128, t128/t2); + } +} + +//------------------------------------------------------------------------ +// Test compatibility with STL sort. +//------------------------------------------------------------------------ + +#include <algorithm> + +void TestSort() { + for( int n=0; n<100; n=n*3+1 ) { + tbb::concurrent_vector<int> array(n); + for( int i=0; i<n; ++i ) + array.at(i) = (i*7)%n; + std::sort( array.begin(), array.end() ); + for( int i=0; i<n; ++i ) + ASSERT( array[i]==i, NULL ); + } +} + +#if TBB_USE_EXCEPTIONS +//------------------------------------------------------------------------ +// Test exceptions safety (from allocator and items constructors) +//------------------------------------------------------------------------ +void TestExceptions() { + typedef static_counting_allocator<debug_allocator<FooWithAssign>, std::size_t> allocator_t; + typedef tbb::concurrent_vector<FooWithAssign, allocator_t> vector_t; + + enum methods { + zero_method = 0, + ctor_copy, ctor_size, assign_nt, assign_ir, op_equ, reserve, compact, grow, + all_methods + }; + ASSERT( !FooCount, NULL ); + + try { + vector_t src(FooIterator(0), FooIterator(N)); // original data + + for(int t = 0; t < 2; ++t) // exception type + for(int m = zero_method+1; m < all_methods; ++m) + { + ASSERT( FooCount == N, "Previous iteration miss some Foo's de-/initialization" ); + allocator_t::init_counters(); + if(t) MaxFooCount = FooCount + N/4; + else allocator_t::set_limits(N/4); + vector_t victim; + try { + switch(m) { + case ctor_copy: { + vector_t acopy(src); + } break; // auto destruction after exception is checked by ~Foo + case ctor_size: { + vector_t sized(N); + } break; // auto destruction after exception is checked by ~Foo + // Do not test assignment constructor due to reusing of same methods as below + case assign_nt: { + victim.assign(N, FooWithAssign()); + } break; + case assign_ir: { + victim.assign(FooIterator(0), FooIterator(N)); + } break; + case op_equ: { + victim.reserve(2); victim = src; // fragmented assignment + } break; + case reserve: { + try { + victim.reserve(victim.max_size()+1); + } catch(std::length_error &) { + } catch(...) { + KNOWN_ISSUE("ERROR: unrecognized exception - known compiler issue\n"); + } + victim.reserve(N); + } break; + case compact: { + if(t) MaxFooCount = 0; else allocator_t::set_limits(); // reset limits + victim.reserve(2); victim = src; // fragmented assignment + if(t) MaxFooCount = FooCount + 10; else allocator_t::set_limits(1, false); // block any allocation, check NULL return from allocator + victim.shrink_to_fit(); // should start defragmenting first segment + } break; + case grow: { + tbb::task_scheduler_init init(2); + if(t) MaxFooCount = FooCount + 31; // these numbers help to reproduce the live lock for versions < TBB2.2 + try { + tbb::parallel_for( tbb::blocked_range<int>(0, N, 70), GrowBy<vector_t>(victim) ); + } catch(...) { +#if TBB_USE_CAPTURED_EXCEPTION + throw tbb::bad_last_alloc(); +#else + throw; +#endif + } + } break; + default:; + } + if(!t || m != reserve) ASSERT(false, "should throw an exception"); + } catch(std::bad_alloc &e) { + allocator_t::set_limits(); MaxFooCount = 0; + size_t capacity = victim.capacity(); + size_t size = victim.size(); +#if TBB_DEPRECATED + size_t req_size = victim.grow_by(0); +#else + size_t req_size = victim.grow_by(0) - victim.begin(); +#endif + ASSERT( size <= capacity, NULL); + ASSERT( req_size >= size, NULL); + switch(m) { + case reserve: + if(t) ASSERT(false, NULL); + case assign_nt: + case assign_ir: + if(!t) { + ASSERT(capacity < N/2, "unexpected capacity"); + ASSERT(size == 0, "unexpected size"); + break; + } else { + ASSERT(size == N, "unexpected size"); + ASSERT(capacity >= N, "unexpected capacity"); + int i; + for(i = 1; ; ++i) + if(!victim[i].zero_bar()) break; + else ASSERT(victim[i].bar() == (m == assign_ir)? i : initial_value_of_bar, NULL); + for(; size_t(i) < size; ++i) ASSERT(!victim[i].zero_bar(), NULL); + ASSERT(size_t(i) == size, NULL); + break; + } + case grow: + case op_equ: + if(!t) { + ASSERT(capacity > 0, NULL); + ASSERT(capacity < N, "unexpected capacity"); + } + { + vector_t copy_of_victim(victim); + ASSERT(copy_of_victim.size() > 0, NULL); + for(int i = 0; ; ++i) { + try { + FooWithAssign &foo = victim.at(i); + if( !foo.is_valid_or_zero() ) { + std::printf("i: %d size: %u req_size: %u state: %d\n", i, unsigned(size), unsigned(req_size), foo.state); + } + int bar = foo.zero_bar(); + if(m != grow) ASSERT( bar == i || (t && bar == 0), NULL); + if(size_t(i) < copy_of_victim.size()) ASSERT( copy_of_victim[i].bar() == bar, NULL); + } catch(std::range_error &) { // skip broken segment + ASSERT( size_t(i) < req_size, NULL ); + if(m == op_equ) break; + } catch(std::out_of_range &){ + ASSERT( i > 0, NULL ); break; + } catch(...) { + KNOWN_ISSUE("ERROR: unrecognized exception - known compiler issue\n"); break; + } + } + vector_t copy_of_victim2(10); copy_of_victim2 = victim; + ASSERT(copy_of_victim == copy_of_victim2, "assignment doesn't match copying"); + if(m == op_equ) { + try { + victim = copy_of_victim2; + } catch(tbb::bad_last_alloc &) { break; + } catch(...) { + KNOWN_ISSUE("ERROR: unrecognized exception - known compiler issue\n"); break; + } + ASSERT(t, NULL); + } + } break; + case compact: + ASSERT(capacity > 0, "unexpected capacity"); + ASSERT(victim == src, "shrink_to_fit() is broken"); + break; + + default:; // nothing to check here + } + REMARK("Exception %d: %s\t- ok\n", m, e.what()); + } + } + } catch(...) { + ASSERT(false, "unexpected exception"); + } +} +#endif /* TBB_USE_EXCEPTIONS */ + +//------------------------------------------------------------------------ +// Test SSE / AVX +//------------------------------------------------------------------------ +#include "harness_m128.h" + +#if HAVE_m128 | HAVE_m256 + +template<typename ClassWithVectorType> +void TestVectorTypes() { + tbb::concurrent_vector<ClassWithVectorType> v; + for( int i=0; i<100; ++i ) { + // VC8 does not properly align a temporary value; to work around, use explicit variable + ClassWithVectorType foo(i); + v.push_back(foo); + for( int j=0; j<i; ++j ) { + ClassWithVectorType bar(j); + ASSERT( v[j]==bar, NULL ); + } + } +} +#endif /* HAVE_m128 | HAVE_m256 */ + +//------------------------------------------------------------------------ + +int TestMain () { + if( MinThread<1 ) { + REPORT("ERROR: MinThread=%d, but must be at least 1\n",MinThread); MinThread = 1; + } +#if !TBB_DEPRECATED + TestIteratorTraits<tbb::concurrent_vector<Foo>::iterator,Foo>(); + TestIteratorTraits<tbb::concurrent_vector<Foo>::const_iterator,const Foo>(); + TestSequentialFor<FooWithAssign> (); + TestResizeAndCopy(); + TestAssign(); +#if HAVE_m128 + TestVectorTypes<ClassWithSSE>(); +#endif +#if HAVE_m256 + if (have_AVX()) TestVectorTypes<ClassWithAVX>(); +#endif +#endif /* !TBB_DEPRECATED */ + TestCapacity(); + ASSERT( !FooCount, NULL ); + for( int nthread=MinThread; nthread<=MaxThread; ++nthread ) { + tbb::task_scheduler_init init( nthread ); + TestParallelFor( nthread ); + TestConcurrentGrowToAtLeast(); + TestConcurrentGrowBy( nthread ); + } + ASSERT( !FooCount, NULL ); +#if !TBB_DEPRECATED + TestComparison(); + TestFindPrimes(); + TestSort(); +#if __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN + REPORT("Known issue: exception safety test is skipped.\n"); +#elif TBB_USE_EXCEPTIONS + TestExceptions(); +#endif /* TBB_USE_EXCEPTIONS */ +#endif /* !TBB_DEPRECATED */ + ASSERT( !FooCount, NULL ); + REMARK("sizeof(concurrent_vector<int>) == %d\n", (int)sizeof(tbb::concurrent_vector<int>)); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_condition_variable.h b/src/tbb/src/test/test_condition_variable.h new file mode 100644 index 0000000..febd771 --- /dev/null +++ b/src/tbb/src/test/test_condition_variable.h @@ -0,0 +1,695 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/compat/condition_variable" +#include "tbb/mutex.h" +#include "tbb/recursive_mutex.h" +#include "tbb/tick_count.h" +#include "tbb/atomic.h" + +#include "harness.h" + +// This test deliberately avoids a "using tbb" statement, +// so that the error of putting types in the wrong namespace will be caught. + +using namespace std; + +template<typename M> +struct Counter { + typedef M mutex_type; + M mutex; + volatile long value; + void flog_once_lock_guard( size_t mode ); + void flog_once_unique_lock( size_t mode ); +}; + +template<typename M> +void Counter<M>::flog_once_lock_guard(size_t mode) +/** Increments counter once for each iteration in the iteration space. */ +{ + if( mode&1 ) { + // Try acquire and release with implicit lock_guard + // precondition: if mutex_type is not a recursive mutex, the calling thread does not own the mutex m. + // if the prcondition is not met, either dead-lock incorrect 'value' would result in. + lock_guard<M> lg(mutex); + value = value+1; + } else { + // Try acquire and release with adopt lock_quard + // precodition: the calling thread owns the mutex m. + // if the prcondition is not met, incorrect 'value' would result in because the thread unlocks + // mutex that it does not own. + mutex.lock(); + lock_guard<M> lg( mutex, adopt_lock ); + value = value+1; + } +} + +template<typename M> +void Counter<M>::flog_once_unique_lock(size_t mode) +/** Increments counter once for each iteration in the iteration space. */ +{ + switch( mode&7 ) { + case 0: + {// implicitly acquire and release mutex with unique_lock + unique_lock<M> ul( mutex ); + value = value+1; + ASSERT( ul==true, NULL ); + } + break; + case 1: + {// unique_lock with defer_lock + unique_lock<M> ul( mutex, defer_lock ); + ASSERT( ul.owns_lock()==false, NULL ); + ul.lock(); + value = value+1; + ASSERT( ul.owns_lock()==true, NULL ); + } + break; + case 2: + {// unique_lock::try_lock() with try_to_lock + unique_lock<M> ul( mutex, try_to_lock ); + if( !ul ) + while( !ul.try_lock() ) + __TBB_Yield(); + value = value+1; + } + break; + case 3: + {// unique_lock::try_lock_for() with try_to_lock + unique_lock<M> ul( mutex, defer_lock ); + tbb::tick_count::interval_t i(1.0); + while( !ul.try_lock_for( i ) ) + ; + value = value+1; + ASSERT( ul.owns_lock()==true, NULL ); + } + break; + case 4: + { + unique_lock<M> ul_o4; + {// unique_lock with adopt_lock + mutex.lock(); + unique_lock<M> ul( mutex, adopt_lock ); + value = value+1; + ASSERT( ul.owns_lock()==true, NULL ); + ASSERT( ul.mutex()==&mutex, NULL ); + ASSERT( ul_o4.owns_lock()==false, NULL ); + ASSERT( ul_o4.mutex()==NULL, NULL ); + swap( ul, ul_o4 ); + ASSERT( ul.owns_lock()==false, NULL ); + ASSERT( ul.mutex()==NULL, NULL ); + ASSERT( ul_o4.owns_lock()==true, NULL ); + ASSERT( ul_o4.mutex()==&mutex, NULL ); + ul_o4.unlock(); + } + ASSERT( ul_o4.owns_lock()==false, NULL ); + } + break; + case 5: + { + unique_lock<M> ul_o5; + {// unique_lock with adopt_lock + mutex.lock(); + unique_lock<M> ul( mutex, adopt_lock ); + value = value+1; + ASSERT( ul.owns_lock()==true, NULL ); + ASSERT( ul.mutex()==&mutex, NULL ); + ASSERT( ul_o5.owns_lock()==false, NULL ); + ASSERT( ul_o5.mutex()==NULL, NULL ); + ul_o5.swap( ul ); + ASSERT( ul.owns_lock()==false, NULL ); + ASSERT( ul.mutex()==NULL, NULL ); + ASSERT( ul_o5.owns_lock()==true, NULL ); + ASSERT( ul_o5.mutex()==&mutex, NULL ); + ul_o5.unlock(); + } + ASSERT( ul_o5.owns_lock()==false, NULL ); + } + break; + default: + {// unique_lock with adopt_lock, and release() + mutex.lock(); + unique_lock<M> ul( mutex, adopt_lock ); + ASSERT( ul==true, NULL ); + value = value+1; + M* old_m = ul.release(); + old_m->unlock(); + ASSERT( ul.owns_lock()==false, NULL ); + } + break; + } +} + +static tbb::atomic<size_t> Order; + +template<typename State, long TestSize> +struct WorkForLocks: NoAssign { + static const size_t chunk = 100; + State& state; + WorkForLocks( State& state_ ) : state(state_) {} + void operator()( int ) const { + size_t step; + while( (step=Order.fetch_and_add<tbb::acquire>(chunk))<TestSize ) { + for( size_t i=0; i<chunk && step<TestSize; ++i, ++step ) { + state.flog_once_lock_guard(step); + state.flog_once_unique_lock(step); + } + } + } +}; + +template<typename M> +void TestLocks( const char* name, int nthread ) { + REMARK("testing %s in TestLocks\n",name); + Counter<M> counter; + counter.value = 0; + Order = 0; + // use the macro because of a gcc 4.6 bug +#define TEST_SIZE 100000 + NativeParallelFor( nthread, WorkForLocks<Counter<M>, TEST_SIZE>(counter) ); + + if( counter.value!=2*TEST_SIZE ) + REPORT("ERROR for %s in TestLocks: counter.value=%ld != 2 * %ld=test_size\n",name,counter.value,TEST_SIZE); +#undef TEST_SIZE +} + +static tbb::atomic<int> barrier; + +// Test if the constructor works and if native_handle() works +template<typename M> +struct WorkForCondVarCtor: NoAssign { + condition_variable& my_cv; + M& my_mtx; + WorkForCondVarCtor( condition_variable& cv_, M& mtx_ ) : my_cv(cv_), my_mtx(mtx_) {} + void operator()( int tid ) const { + ASSERT( tid<=1, NULL ); // test with 2 threads. + condition_variable::native_handle_type handle = my_cv.native_handle(); + if( tid&1 ) { + my_mtx.lock(); + ++barrier; +#if _WIN32||_WIN64 + if( !tbb::interface5::internal::internal_condition_variable_wait( *handle, &my_mtx ) ) { + int ec = GetLastError(); + ASSERT( ec!=WAIT_TIMEOUT, NULL ); + throw_exception( tbb::internal::eid_condvar_wait_failed ); + } +#else + if( pthread_cond_wait( handle, my_mtx.native_handle() ) ) + throw_exception( tbb::internal::eid_condvar_wait_failed ); +#endif + ++barrier; + my_mtx.unlock(); + } else { + bool res; + while( (res=my_mtx.try_lock())==true && barrier==0 ) { + my_mtx.unlock(); + __TBB_Yield(); + } + if( res ) my_mtx.unlock(); + do { +#if _WIN32||_WIN64 + tbb::interface5::internal::internal_condition_variable_notify_one( *handle ); +#else + pthread_cond_signal( handle ); +#endif + __TBB_Yield(); + } while ( barrier<2 ); + } + } +}; + +static condition_variable* test_cv; +static tbb::atomic<int> n_waiters; + +// Test if the destructor works +template<typename M> +struct WorkForCondVarDtor: NoAssign { + int nthread; + M& my_mtx; + WorkForCondVarDtor( int n, M& mtx_ ) : nthread(n), my_mtx(mtx_) {} + void operator()( int tid ) const { + if( tid==0 ) { + unique_lock<M> ul( my_mtx, defer_lock ); + test_cv = new condition_variable; + + while( n_waiters<nthread-1 ) + __TBB_Yield(); + ul.lock(); + test_cv->notify_all(); + ul.unlock(); + while( n_waiters>0 ) + __TBB_Yield(); + delete test_cv; + } else { + while( test_cv==NULL ) + __TBB_Yield(); + unique_lock<M> ul(my_mtx); + ++n_waiters; + test_cv->wait( ul ); + --n_waiters; + } + } +}; + +static const int max_ticket = 100; +static const int short_delay = 10; +static const int long_delay = 100; + +tbb::atomic<int> n_signaled; +tbb::atomic<int> n_done, n_done_1, n_done_2; +tbb::atomic<int> n_timed_out; + +static bool false_to_true; + +struct TestPredicateFalseToTrue { + TestPredicateFalseToTrue() {} + bool operator()() { return false_to_true; } +}; + +struct TestPredicateFalse { + TestPredicateFalse() {} + bool operator()() { return false; } +}; + +struct TestPredicateTrue { + TestPredicateTrue() {} + bool operator()() { return true; } +}; + +// Test timed wait and timed wait with pred +template<typename M> +struct WorkForCondVarTimedWait: NoAssign { + int nthread; + condition_variable& test_cv; + M& my_mtx; + WorkForCondVarTimedWait( int n_, condition_variable& cv_, M& mtx_ ) : nthread(n_), test_cv(cv_), my_mtx(mtx_) {} + void operator()( int tid ) const { + tbb::tick_count t1, t2; + + unique_lock<M> ul( my_mtx, defer_lock ); + + ASSERT( n_timed_out==0, NULL ); + ++barrier; + while( barrier<nthread ) __TBB_Yield(); + + // test if a thread times out with wait_for() + for( int i=1; i<10; ++i ) { + tbb::tick_count::interval_t intv((double)i*0.0999 /*seconds*/); + ul.lock(); + cv_status st = no_timeout; + __TBB_TRY { + /** Some version of glibc return EINVAL instead 0 when spurious wakeup occurs on pthread_cond_timedwait() **/ + st = test_cv.wait_for( ul, intv ); + } __TBB_CATCH( std::runtime_error& ) {} + ASSERT( ul, "mutex should have been reacquired" ); + ul.unlock(); + if( st==timeout ) + ++n_timed_out; + } + + ASSERT( n_timed_out>0, "should have been timed-out at least once\n" ); + ++n_done_1; + while( n_done_1<nthread ) __TBB_Yield(); + + for( int i=1; i<10; ++i ) { + tbb::tick_count::interval_t intv((double)i*0.0001 /*seconds*/); + ul.lock(); + __TBB_TRY { + /** Some version of glibc return EINVAL instead 0 when spurious wakeup occurs on pthread_cond_timedwait() **/ + ASSERT( false==test_cv.wait_for( ul, intv, TestPredicateFalse()), "incorrect return value" ); + } __TBB_CATCH( std::runtime_error& ) {} + ASSERT( ul, "mutex should have been reacquired" ); + ul.unlock(); + } + + if( tid==0 ) + n_waiters = 0; + // barrier + ++n_done_2; + while( n_done_2<nthread ) __TBB_Yield(); + + // at this point, we know wait_for() successfully times out. + // so test if a thread blocked on wait_for() could receive a signal before its waiting time elapses. + if( tid==0 ) { + // signaler + n_signaled = 0; + ASSERT( n_waiters==0, NULL ); + ++n_done_2; // open gate 1 + + while( n_waiters<(nthread-1) ) __TBB_Yield(); // wait until all other threads block on cv. flag_1 + + ul.lock(); + test_cv.notify_all(); + n_waiters = 0; + ul.unlock(); + + while( n_done_2<2*nthread ) __TBB_Yield(); + ASSERT( n_signaled>0, "too small an interval?" ); + n_signaled = 0; + + } else { + while( n_done_2<nthread+1 ) __TBB_Yield(); // gate 1 + + // sleeper + tbb::tick_count::interval_t intv((double)2.0 /*seconds*/); + ul.lock(); + ++n_waiters; // raise flag 1/(nthread-1) + t1 = tbb::tick_count::now(); + cv_status st = test_cv.wait_for( ul, intv ); // gate 2 + t2 = tbb::tick_count::now(); + ul.unlock(); + if( st==no_timeout ) { + ++n_signaled; + ASSERT( (t2-t1).seconds()<intv.seconds(), "got a signal after timed-out?" ); + } + } + + ASSERT( n_done==0, NULL ); + ++n_done_2; + + if( tid==0 ) { + ASSERT( n_waiters==0, NULL ); + ++n_done; // open gate 3 + + while( n_waiters<(nthread-1) ) __TBB_Yield(); // wait until all other threads block on cv. + for( int i=0; i<2*short_delay; ++i ) __TBB_Yield(); // give some time to waiters so that all of them in the waitq + ul.lock(); + false_to_true = true; + test_cv.notify_all(); // open gate 4 + ul.unlock(); + + while( n_done<nthread ) __TBB_Yield(); // wait until all other threads wake up. + ASSERT( n_signaled>0, "too small an interval?" ); + } else { + + while( n_done<1 ) __TBB_Yield(); // gate 3 + + tbb::tick_count::interval_t intv((double)2.0 /*seconds*/); + ul.lock(); + ++n_waiters; + // wait_for w/ predciate + t1 = tbb::tick_count::now(); + ASSERT( test_cv.wait_for( ul, intv, TestPredicateFalseToTrue())==true, NULL ); // gate 4 + t2 = tbb::tick_count::now(); + ul.unlock(); + if( (t2-t1).seconds()<intv.seconds() ) + ++n_signaled; + ++n_done; + } + } +}; + +tbb::atomic<int> ticket_for_sleep, ticket_for_wakeup, signaled_ticket, wokeup_ticket; +tbb::atomic<unsigned> n_visit_to_waitq; +unsigned max_waitq_length; + +template<typename M> +struct WorkForCondVarWaitAndNotifyOne: NoAssign { + int nthread; + condition_variable& test_cv; + M& my_mtx; + WorkForCondVarWaitAndNotifyOne( int n_, condition_variable& cv_, M& mtx_ ) : nthread(n_), test_cv(cv_), my_mtx(mtx_) {} + void operator()( int tid ) const { + if( tid&1 ) { + // exercise signal part + while( ticket_for_wakeup<max_ticket ) { + int my_ticket = ++ticket_for_wakeup; // atomically grab the next ticket + if( my_ticket>max_ticket ) + break; + + for( ;; ) { + unique_lock<M> ul( my_mtx, defer_lock ); + ul.lock(); + if( n_waiters>0 && my_ticket<=ticket_for_sleep && my_ticket==(wokeup_ticket+1) ) { + signaled_ticket = my_ticket; + test_cv.notify_one(); + ++n_signaled; + ul.unlock(); + break; + } + ul.unlock(); + __TBB_Yield(); + } + + // give waiters time to go to sleep. + for( int m=0; m<short_delay; ++m ) + __TBB_Yield(); + } + } else { + while( ticket_for_sleep<max_ticket ) { + unique_lock<M> ul( my_mtx, defer_lock ); + ul.lock(); + // exercise wait part + int my_ticket = ++ticket_for_sleep; // grab my ticket + if( my_ticket>max_ticket ) break; + + // each waiter should go to sleep at least once + unsigned nw = ++n_waiters; + for( ;; ) { + // update to max_waitq_length + if( nw>max_waitq_length ) max_waitq_length = nw; + ++n_visit_to_waitq; + test_cv.wait( ul ); + // if( ret==false ) ++n_timedout; + ASSERT( ul, "mutex should have been locked" ); + --n_waiters; + if( signaled_ticket==my_ticket ) { + wokeup_ticket = my_ticket; + break; + } + if( n_waiters>0 ) + test_cv.notify_one(); + nw = ++n_waiters; // update to max_waitq_length occurs above + } + + ul.unlock(); + __TBB_Yield(); // give other threads chance to run. + } + } + ++n_done; + spin_wait_until_eq( n_done, nthread ); + ASSERT( n_signaled==max_ticket, "incorrect number of notifications sent" ); + } +}; + +struct TestPredicate1 { + int target; + TestPredicate1( int i_ ) : target(i_) {} + bool operator()( ) { return signaled_ticket==target; } +}; + +template<typename M> +struct WorkForCondVarWaitPredAndNotifyAll: NoAssign { + int nthread; + condition_variable& test_cv; + M& my_mtx; + int multiple; + WorkForCondVarWaitPredAndNotifyAll( int n_, condition_variable& cv_, M& mtx_, int m_ ) : + nthread(n_), test_cv(cv_), my_mtx(mtx_), multiple(m_) {} + void operator()( int tid ) const { + if( tid&1 ) { + while( ticket_for_sleep<max_ticket ) { + unique_lock<M> ul( my_mtx, defer_lock ); + // exercise wait part + int my_ticket = ++ticket_for_sleep; // grab my ticket + if( my_ticket>max_ticket ) + break; + + ul.lock(); + ++n_visit_to_waitq; + unsigned nw = ++n_waiters; + if( nw>max_waitq_length ) max_waitq_length = nw; + test_cv.wait( ul, TestPredicate1( my_ticket ) ); + wokeup_ticket = my_ticket; + --n_waiters; + ASSERT( ul, "mutex should have been locked" ); + ul.unlock(); + + __TBB_Yield(); // give other threads chance to run. + } + } else { + // exercise signal part + while( ticket_for_wakeup<max_ticket ) { + int my_ticket = ++ticket_for_wakeup; // atomically grab the next ticket + if( my_ticket>max_ticket ) + break; + + for( ;; ) { + unique_lock<M> ul( my_mtx ); + if( n_waiters>0 && my_ticket<=ticket_for_sleep && my_ticket==(wokeup_ticket+1) ) { + signaled_ticket = my_ticket; + test_cv.notify_all(); + ++n_signaled; + ul.unlock(); + break; + } + ul.unlock(); + __TBB_Yield(); + } + + // give waiters time to go to sleep. + for( int m=0; m<long_delay*multiple; ++m ) + __TBB_Yield(); + } + } + ++n_done; + spin_wait_until_eq( n_done, nthread ); + ASSERT( n_signaled==max_ticket, "incorrect number of notifications sent" ); + } +}; + +void InitGlobalCounters() +{ + ticket_for_sleep = ticket_for_wakeup = signaled_ticket = wokeup_ticket = 0; + n_waiters = 0; + n_signaled = 0; + n_done = n_done_1 = n_done_2 = 0; + n_visit_to_waitq = 0; + n_timed_out = 0; +} + +template<typename M> +void TestConditionVariable( const char* name, int nthread ) +{ + REMARK("testing %s in TestConditionVariable\n",name); + Counter<M> counter; + M mtx; + + ASSERT( nthread>1, "at least two threads are needed for testing condition_variable" ); + REMARK(" - constructor\n" ); + // Test constructor. + { + condition_variable cv1; +#if _WIN32||_WIN64 + condition_variable::native_handle_type handle = cv1.native_handle(); + ASSERT( uintptr_t(&handle->cv_event)==uintptr_t(&handle->cv_native), NULL ); +#endif + M mtx1; + barrier = 0; + NativeParallelFor( 2, WorkForCondVarCtor<M>( cv1, mtx1 ) ); + } + + REMARK(" - destructor\n" ); + // Test destructor. + { + M mtx2; + test_cv = NULL; + n_waiters = 0; + NativeParallelFor( nthread, WorkForCondVarDtor<M>( nthread, mtx2 ) ); + } + + REMARK(" - timed_wait (i.e., wait_for)\n"); + // Test timed wait. + { + condition_variable cv_tw; + M mtx_tw; + barrier = 0; + InitGlobalCounters(); + int nthr = nthread>4?4:nthread; + NativeParallelFor( nthr, WorkForCondVarTimedWait<M>( nthr, cv_tw, mtx_tw ) ); + } + + REMARK(" - wait with notify_one\n"); + // Test wait and notify_one + do { + condition_variable cv3; + M mtx3; + InitGlobalCounters(); + NativeParallelFor( nthread, WorkForCondVarWaitAndNotifyOne<M>( nthread, cv3, mtx3 ) ); + } while( n_visit_to_waitq==0 || max_waitq_length==0 ); + + REMARK(" - predicated wait with notify_all\n"); + // Test wait_pred and notify_all + int delay_multiple = 1; + do { + condition_variable cv4; + M mtx4; + InitGlobalCounters(); + NativeParallelFor( nthread, WorkForCondVarWaitPredAndNotifyAll<M>( nthread, cv4, mtx4, delay_multiple ) ); + if( max_waitq_length<unsigned(nthread/2) ) + ++delay_multiple; + } while( n_visit_to_waitq<=0 || max_waitq_length<unsigned(nthread/2) ); +} + +#if TBB_USE_EXCEPTIONS +static tbb::atomic<int> err_count; + +#define TRY_AND_CATCH_RUNTIME_ERROR(op,msg) \ + try { \ + op; \ + ++err_count; \ + } catch( std::runtime_error& e ) {ASSERT( strstr(e.what(), msg) , NULL );} catch(...) {++err_count;} + +template<typename M> +void TestUniqueLockException( const char * name ) { + REMARK("testing %s TestUniqueLockException\n",name); + M mtx; + unique_lock<M> ul_0; + err_count = 0; + + TRY_AND_CATCH_RUNTIME_ERROR( ul_0.lock(), "Operation not permitted" ); + TRY_AND_CATCH_RUNTIME_ERROR( ul_0.try_lock(), "Operation not permitted" ); + + unique_lock<M> ul_1( mtx ); + + TRY_AND_CATCH_RUNTIME_ERROR( ul_1.lock(), "Resource deadlock" ); + TRY_AND_CATCH_RUNTIME_ERROR( ul_1.try_lock(), "Resource deadlock" ); + + ul_1.unlock(); + TRY_AND_CATCH_RUNTIME_ERROR( ul_1.unlock(), "Operation not permitted" ); + + ASSERT( !err_count, "Some exceptions are not thrown or incorrect ones are thrown" ); +} + +template<typename M> +void TestConditionVariableException( const char * name ) { + REMARK("testing %s in TestConditionVariableException; yet to be implemented\n",name); +} +#endif /* TBB_USE_EXCEPTIONS */ + +template<typename Mutex, typename RecursiveMutex> +void DoCondVarTest() +{ + for( int p=MinThread; p<=MaxThread; ++p ) { + REMARK( "testing with %d threads\n", p ); + TestLocks<Mutex>( "mutex", p ); + TestLocks<RecursiveMutex>( "recursive_mutex", p ); + + if( p<=1 ) continue; + + // for testing condition_variable, at least one sleeper and one notifier are needed + TestConditionVariable<Mutex>( "mutex", p ); + } +#if __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN + REPORT("Known issue: exception handling tests are skipped.\n"); +#elif TBB_USE_EXCEPTIONS + TestUniqueLockException<Mutex>( "mutex" ); + TestUniqueLockException<RecursiveMutex>( "recursive_mutex" ); + TestConditionVariableException<Mutex>( "mutex" ); +#endif /* TBB_USE_EXCEPTIONS */ +} diff --git a/src/tbb/src/test/test_continue_node.cpp b/src/tbb/src/test/test_continue_node.cpp new file mode 100644 index 0000000..f7f219c --- /dev/null +++ b/src/tbb/src/test/test_continue_node.cpp @@ -0,0 +1,191 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "harness_graph.h" + +#include "tbb/task_scheduler_init.h" +#include "tbb/spin_mutex.h" + +tbb::spin_mutex global_mutex; + +#define N 1000 +#define MAX_NODES 4 +#define C 8 + +struct empty_no_assign : private NoAssign { + empty_no_assign() {} + empty_no_assign( int ) {} + operator int() { return 0; } +}; + +template< typename InputType > +struct parallel_puts : private NoAssign { + + tbb::flow::receiver< InputType > * const my_exe_node; + + parallel_puts( tbb::flow::receiver< InputType > &exe_node ) : my_exe_node(&exe_node) {} + + void operator()( int ) const { + for ( int i = 0; i < N; ++i ) { + // the nodes will accept all puts + ASSERT( my_exe_node->try_put( InputType() ) == true, NULL ); + } + } + +}; + +template< typename OutputType > +void run_continue_nodes( int p, tbb::flow::graph& g, tbb::flow::continue_node< OutputType >& n ) { + for (size_t i = 0; i < N; ++i) { + n.register_predecessor( *reinterpret_cast< tbb::flow::sender< tbb::flow::continue_msg > * >(&n) ); + } + + for (size_t num_receivers = 1; num_receivers <= MAX_NODES; ++num_receivers ) { + harness_counting_receiver<OutputType> *receivers = new harness_counting_receiver<OutputType>[num_receivers]; + harness_graph_executor<tbb::flow::continue_msg, OutputType>::execute_count = 0; + + for (size_t r = 0; r < num_receivers; ++r ) { + tbb::flow::make_edge( n, receivers[r] ); + } + + NativeParallelFor( p, parallel_puts<tbb::flow::continue_msg>(n) ); + g.wait_for_all(); + + // 2) the nodes will receive puts from multiple predecessors simultaneously, + size_t ec = harness_graph_executor<tbb::flow::continue_msg, OutputType>::execute_count; + ASSERT( (int)ec == p, NULL ); + for (size_t r = 0; r < num_receivers; ++r ) { + size_t c = receivers[r].my_count; + // 3) the nodes will send to multiple successors. + ASSERT( (int)c == p, NULL ); + } + } +} + +template< typename OutputType, typename Body > +void continue_nodes( Body body ) { + for (int p = 1; p < 2*MaxThread; ++p) { + tbb::flow::graph g; + tbb::flow::continue_node< OutputType > exe_node( g, body ); + run_continue_nodes( p, g, exe_node); + exe_node.try_put(tbb::flow::continue_msg()); + tbb::flow::continue_node< OutputType > exe_node_copy( exe_node ); + run_continue_nodes( p, g, exe_node_copy); + } +} + +const size_t Offset = 123; +tbb::atomic<size_t> global_execute_count; + +template< typename OutputType > +struct inc_functor { + + tbb::atomic<size_t> local_execute_count; + inc_functor( ) { local_execute_count = 0; } + inc_functor( const inc_functor &f ) { local_execute_count = f.local_execute_count; } + + OutputType operator()( tbb::flow::continue_msg ) { + ++global_execute_count; + ++local_execute_count; + return OutputType(); + } + +}; + +template< typename OutputType > +void continue_nodes_with_copy( ) { + + for (int p = 1; p < 2*MaxThread; ++p) { + tbb::flow::graph g; + inc_functor<OutputType> cf; + cf.local_execute_count = Offset; + global_execute_count = Offset; + + tbb::flow::continue_node< OutputType > exe_node( g, cf ); + for (size_t i = 0; i < N; ++i) { + exe_node.register_predecessor( *reinterpret_cast< tbb::flow::sender< tbb::flow::continue_msg > * >(&exe_node) ); + } + + for (size_t num_receivers = 1; num_receivers <= MAX_NODES; ++num_receivers ) { + harness_counting_receiver<OutputType> *receivers = new harness_counting_receiver<OutputType>[num_receivers]; + + for (size_t r = 0; r < num_receivers; ++r ) { + tbb::flow::make_edge( exe_node, receivers[r] ); + } + + NativeParallelFor( p, parallel_puts<tbb::flow::continue_msg>(exe_node) ); + g.wait_for_all(); + + // 2) the nodes will receive puts from multiple predecessors simultaneously, + for (size_t r = 0; r < num_receivers; ++r ) { + size_t c = receivers[r].my_count; + // 3) the nodes will send to multiple successors. + ASSERT( (int)c == p, NULL ); + } + } + + // validate that the local body matches the global execute_count and both are correct + inc_functor<OutputType> body_copy = tbb::flow::copy_body< inc_functor<OutputType> >( exe_node ); + const size_t expected_count = p*MAX_NODES + Offset; + size_t global_count = global_execute_count; + size_t inc_count = body_copy.local_execute_count; + ASSERT( global_count == expected_count && global_count == inc_count, NULL ); + + } +} + +template< typename OutputType > +void run_continue_nodes() { + harness_graph_executor< tbb::flow::continue_msg, OutputType>::max_executors = 0; + #if __TBB_LAMBDAS_PRESENT + continue_nodes<OutputType>( []( tbb::flow::continue_msg i ) -> OutputType { return harness_graph_executor<tbb::flow::continue_msg, OutputType>::func(i); } ); + #endif + continue_nodes<OutputType>( &harness_graph_executor<tbb::flow::continue_msg, OutputType>::func ); + continue_nodes<OutputType>( typename harness_graph_executor<tbb::flow::continue_msg, OutputType>::functor() ); + continue_nodes_with_copy<OutputType>(); +} + +//! Tests limited concurrency cases for nodes that accept data messages +void test_concurrency(int num_threads) { + tbb::task_scheduler_init init(num_threads); + run_continue_nodes<tbb::flow::continue_msg>(); + run_continue_nodes<int>(); + run_continue_nodes<empty_no_assign>(); +} + +int TestMain() { + if( MinThread<1 ) { + REPORT("number of threads must be positive\n"); + exit(1); + } + for( int p=MinThread; p<=MaxThread; ++p ) { + test_concurrency(p); + } + return Harness::Done; +} + diff --git a/src/tbb/src/test/test_critical_section.cpp b/src/tbb/src/test/test_critical_section.cpp new file mode 100644 index 0000000..59a85b6 --- /dev/null +++ b/src/tbb/src/test/test_critical_section.cpp @@ -0,0 +1,224 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// test critical section +// +#include "tbb/critical_section.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/enumerable_thread_specific.h" +#include "tbb/tick_count.h" +#include "harness_assert.h" +#include "harness.h" +#include <math.h> + +#include "harness_barrier.h" +Harness::SpinBarrier sBarrier; +tbb::critical_section cs; +const int MAX_WORK = 300; + +struct BusyBody : NoAssign { + tbb::enumerable_thread_specific<double> &locals; + const int nThread; + const int WorkRatiox100; + int &unprotected_count; + bool test_throw; + + BusyBody( int nThread_, int workRatiox100_, tbb::enumerable_thread_specific<double> &locals_, int &unprotected_count_, bool test_throw_) : + locals(locals_), + nThread(nThread_), + WorkRatiox100(workRatiox100_), + unprotected_count(unprotected_count_), + test_throw(test_throw_) { + sBarrier.initialize(nThread_); + } + + void operator()(const int /* threadID */ ) const { + int nIters = MAX_WORK/nThread; + sBarrier.wait(); + tbb::tick_count t0 = tbb::tick_count::now(); + for(int j = 0; j < nIters; j++) { + + for(int i = 0; i < MAX_WORK * (100 - WorkRatiox100); i++) { + locals.local() += 1.0; + } + cs.lock(); + ASSERT( !cs.try_lock(), "recursive try_lock must fail" ); +#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN + if(test_throw && j == (nIters / 2)) { + bool was_caught = false, + unknown_exception = false; + try { + cs.lock(); + } + catch(tbb::improper_lock& e) { + ASSERT( e.what(), "Error message is absent" ); + was_caught = true; + } + catch(...) { + was_caught = unknown_exception = true; + } + ASSERT(was_caught, "Recursive lock attempt did not throw"); + ASSERT(!unknown_exception, "tbb::improper_lock exception is expected"); + } +#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */ + for(int i = 0; i < MAX_WORK * WorkRatiox100; i++) { + locals.local() += 1.0; + } + unprotected_count++; + cs.unlock(); + } + locals.local() = (tbb::tick_count::now() - t0).seconds(); + } +}; + +struct BusyBodyScoped : NoAssign { + tbb::enumerable_thread_specific<double> &locals; + const int nThread; + const int WorkRatiox100; + int &unprotected_count; + bool test_throw; + + BusyBodyScoped( int nThread_, int workRatiox100_, tbb::enumerable_thread_specific<double> &locals_, int &unprotected_count_, bool test_throw_) : + locals(locals_), + nThread(nThread_), + WorkRatiox100(workRatiox100_), + unprotected_count(unprotected_count_), + test_throw(test_throw_) { + sBarrier.initialize(nThread_); + } + + void operator()(const int /* threadID */ ) const { + int nIters = MAX_WORK/nThread; + sBarrier.wait(); + tbb::tick_count t0 = tbb::tick_count::now(); + for(int j = 0; j < nIters; j++) { + + for(int i = 0; i < MAX_WORK * (100 - WorkRatiox100); i++) { + locals.local() += 1.0; + } + { + tbb::critical_section::scoped_lock my_lock(cs); + for(int i = 0; i < MAX_WORK * WorkRatiox100; i++) { + locals.local() += 1.0; + } + unprotected_count++; + } + } + locals.local() = (tbb::tick_count::now() - t0).seconds(); + } +}; + +void +RunOneCriticalSectionTest(int nThreads, int csWorkRatio, bool test_throw) { + tbb::task_scheduler_init init(tbb::task_scheduler_init::deferred); + tbb::enumerable_thread_specific<double> test_locals; + int myCount = 0; + BusyBody myBody(nThreads, csWorkRatio, test_locals, myCount, test_throw); + BusyBodyScoped myScopedBody(nThreads, csWorkRatio, test_locals, myCount, test_throw); + init.initialize(nThreads); + tbb::tick_count t0; + { + t0 = tbb::tick_count::now(); + myCount = 0; + NativeParallelFor(nThreads, myBody); + ASSERT(myCount == (MAX_WORK - (MAX_WORK % nThreads)), NULL); + REMARK("%d threads, work ratio %d per cent, time %g", nThreads, csWorkRatio, (tbb::tick_count::now() - t0).seconds()); + if (nThreads > 1) { + double etsSum = 0; + double etsMax = 0; + double etsMin = 0; + double etsSigmaSq = 0; + double etsSigma = 0; + + for(tbb::enumerable_thread_specific<double>::const_iterator ci = test_locals.begin(); ci != test_locals.end(); ci++) { + etsSum += *ci; + if(etsMax==0.0) { + etsMin = *ci; + } + else { + if(etsMin > *ci) etsMin = *ci; + } + if(etsMax < *ci) etsMax = *ci; + } + double etsAvg = etsSum / (double)nThreads; + for(tbb::enumerable_thread_specific<double>::const_iterator ci = test_locals.begin(); ci != test_locals.end(); ci++) { + etsSigma = etsAvg - *ci; + etsSigmaSq += etsSigma * etsSigma; + } + // an attempt to gauge the "fairness" of the scheduling of the threads. We figure + // the standard deviation, and compare it with the maximum deviation from the + // average time. If the difference is 0 that means all threads finished in the same + // amount of time. If non-zero, the difference is divided by the time, and the + // negative log is taken. If > 2, then the difference is on the order of 0.01*t + // where T is the average time. We aritrarily define this as "fair." + etsSigma = sqrt(etsSigmaSq/double(nThreads)); + etsMax -= etsAvg; // max - a == delta1 + etsMin = etsAvg - etsMin; // a - min == delta2 + if(etsMax < etsMin) etsMax = etsMin; + etsMax -= etsSigma; + // ASSERT(etsMax >= 0, NULL); // shouldn't the maximum difference from the mean be > the stddev? + etsMax = (etsMax > 0.0) ? etsMax : 0.0; // possible rounding error + double fairness = etsMax / etsAvg; + if(fairness == 0.0) { + fairness = 100.0; + } + else fairness = - log10(fairness); + if(fairness > 2.0 ) { + REMARK(" Fair (%g)\n", fairness); + } + else { + REMARK(" Unfair (%g)\n", fairness); + } + } + myCount = 0; + NativeParallelFor(nThreads, myScopedBody); + ASSERT(myCount == (MAX_WORK - (MAX_WORK % nThreads)), NULL); + + } + + init.terminate(); +} + +void +RunParallelTests() { + for(int p = MinThread; p <= MaxThread; p++) { + for(int cs_ratio = 1; cs_ratio < 95; cs_ratio *= 2) { + RunOneCriticalSectionTest(p, cs_ratio, /*test_throw*/true); + } + } +} + +int TestMain () { + if(MinThread <= 0) MinThread = 1; + + if(MaxThread > 0) { + RunParallelTests(); + } + + return Harness::Done; +} diff --git a/src/tbb/src/test/test_eh_algorithms.cpp b/src/tbb/src/test/test_eh_algorithms.cpp new file mode 100644 index 0000000..9d5f66b --- /dev/null +++ b/src/tbb/src/test/test_eh_algorithms.cpp @@ -0,0 +1,1295 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "harness.h" + +#if __TBB_TASK_GROUP_CONTEXT + +#include <limits.h> // for INT_MAX +#include "tbb/task_scheduler_init.h" +#include "tbb/tbb_exception.h" +#include "tbb/task.h" +#include "tbb/atomic.h" +#include "tbb/parallel_for.h" +#include "tbb/parallel_reduce.h" +#include "tbb/parallel_do.h" +#include "tbb/pipeline.h" +#include "tbb/parallel_scan.h" +#include "tbb/blocked_range.h" +#include "harness_assert.h" + +#define FLAT_RANGE 100000 +#define FLAT_GRAIN 100 +#define OUTER_RANGE 100 +#define OUTER_GRAIN 10 +#define INNER_RANGE (FLAT_RANGE / OUTER_RANGE) +#define INNER_GRAIN (FLAT_GRAIN / OUTER_GRAIN) + +tbb::atomic<intptr_t> g_FedTasksCount; // number of tasks added by parallel_do feeder + +inline intptr_t Existed () { return INT_MAX; } + +#include "harness_eh.h" + +inline void ResetGlobals ( bool throwException = true, bool flog = false ) { + ResetEhGlobals( throwException, flog ); + g_FedTasksCount = 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// Tests for tbb::parallel_for and tbb::parallel_reduce + +typedef size_t count_type; +typedef tbb::blocked_range<count_type> range_type; + +inline intptr_t NumSubranges ( intptr_t length, intptr_t grain ) { + intptr_t n = 1; + for( ; length > grain; length -= length >> 1 ) + n *= 2; + return n; +} + +template<class Body> +intptr_t TestNumSubrangesCalculation ( intptr_t length, intptr_t grain, intptr_t inner_length, intptr_t inner_grain ) { + ResetGlobals(); + g_ThrowException = false; + intptr_t outerCalls = NumSubranges(length, grain), + innerCalls = NumSubranges(inner_length, inner_grain), + maxExecuted = outerCalls * (innerCalls + 1); + tbb::parallel_for( range_type(0, length, grain), Body() ); + ASSERT (g_CurExecuted == maxExecuted, "Wrong estimation of bodies invocation count"); + return maxExecuted; +} + +class NoThrowParForBody { +public: + void operator()( const range_type& r ) const { + volatile count_type x = 0; + count_type end = r.end(); + for( count_type i=r.begin(); i<end; ++i ) + x += i; + } +}; + +#if TBB_USE_EXCEPTIONS + +void Test0 () { + ResetGlobals(); + tbb::simple_partitioner p; + for( size_t i=0; i<10; ++i ) { + tbb::parallel_for( range_type(0, 0, 1), NoThrowParForBody() ); + tbb::parallel_for( range_type(0, 0, 1), NoThrowParForBody(), p ); + tbb::parallel_for( range_type(0, 128, 8), NoThrowParForBody() ); + tbb::parallel_for( range_type(0, 128, 8), NoThrowParForBody(), p ); + } +} // void Test0 () + +//! Template that creates a functor suitable for parallel_reduce from a functor for parallel_for. +template<typename ParForBody> +class SimpleParReduceBody: NoAssign { + ParForBody m_Body; +public: + void operator()( const range_type& r ) const { m_Body(r); } + SimpleParReduceBody() {} + SimpleParReduceBody( SimpleParReduceBody& left, tbb::split ) : m_Body(left.m_Body) {} + void join( SimpleParReduceBody& /*right*/ ) {} +}; // SimpleParReduceBody + +//! Test parallel_for and parallel_reduce for a given partitioner. +/** The Body need only be suitable for a parallel_for. */ +template<typename ParForBody, typename Partitioner> +void TestParallelLoopAux() { + Partitioner partitioner; + for( int i=0; i<2; ++i ) { + ResetGlobals(); + TRY(); + if( i==0 ) + tbb::parallel_for( range_type(0, FLAT_RANGE, FLAT_GRAIN), ParForBody(), partitioner ); + else { + SimpleParReduceBody<ParForBody> rb; + tbb::parallel_reduce( range_type(0, FLAT_RANGE, FLAT_GRAIN), rb, partitioner ); + } + CATCH_AND_ASSERT(); + ASSERT (exceptionCaught, "No exception thrown from the outer parallel_for"); + ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); + ASSERT (g_Exceptions == 1, "No try_blocks in any body expected in this test"); + if ( !g_SolitaryException ) + ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); + } +} + +//! Test with parallel_for and parallel_reduce, over all three kinds of partitioners. +/** The Body only needs to be suitable for tbb::parallel_for. */ +template<typename Body> +void TestParallelLoop() { + // The simple and auto partitioners should be const, but not the affinity partitioner. + TestParallelLoopAux<Body, const tbb::simple_partitioner >(); + TestParallelLoopAux<Body, const tbb::auto_partitioner >(); +#define __TBB_TEMPORARILY_DISABLED 1 +#if !__TBB_TEMPORARILY_DISABLED + // TODO: Improve the test so that it tolerates delayed start of tasks with affinity_partitioner + TestParallelLoopAux<Body, /***/ tbb::affinity_partitioner>(); +#endif +#undef __TBB_TEMPORARILY_DISABLED +} + +class SimpleParForBody: NoAssign { +public: + void operator()( const range_type& r ) const { + Harness::ConcurrencyTracker ct; + volatile long x = 0; + for( count_type i = r.begin(); i != r.end(); ++i ) + x += 0; + ++g_CurExecuted; + WaitUntilConcurrencyPeaks(); + ThrowTestException(1); + } +}; + +void Test1() { + TestParallelLoop<SimpleParForBody>(); +} // void Test1 () + +class OuterParForBody: NoAssign { +public: + void operator()( const range_type& ) const { + Harness::ConcurrencyTracker ct; + ++g_CurExecuted; + tbb::parallel_for( tbb::blocked_range<size_t>(0, INNER_RANGE, INNER_GRAIN), SimpleParForBody() ); + } +}; + +//! Uses parallel_for body containing an inner parallel_for with the default context not wrapped by a try-block. +/** Inner algorithms are spawned inside the new bound context by default. Since + exceptions thrown from the inner parallel_for are not handled by the caller + (outer parallel_for body) in this test, they will cancel all the sibling inner + algorithms. **/ +void Test2 () { + TestParallelLoop<OuterParForBody>(); +} // void Test2 () + +class OuterParForBodyWithIsolatedCtx { +public: + void operator()( const range_type& ) const { + tbb::task_group_context ctx(tbb::task_group_context::isolated); + ++g_CurExecuted; + tbb::parallel_for( tbb::blocked_range<size_t>(0, INNER_RANGE, INNER_GRAIN), SimpleParForBody(), tbb::simple_partitioner(), ctx ); + } +}; + +//! Uses parallel_for body invoking an inner parallel_for with an isolated context without a try-block. +/** Even though exceptions thrown from the inner parallel_for are not handled + by the caller in this test, they will not affect sibling inner algorithms + already running because of the isolated contexts. However because the first + exception cancels the root parallel_for only the first g_NumThreads subranges + will be processed (which launch inner parallel_fors) **/ +void Test3 () { + ResetGlobals(); + typedef OuterParForBodyWithIsolatedCtx body_type; + intptr_t innerCalls = NumSubranges(INNER_RANGE, INNER_GRAIN), + minExecuted = (g_NumThreads - 1) * innerCalls; + TRY(); + tbb::parallel_for( range_type(0, OUTER_RANGE, OUTER_GRAIN), body_type() ); + CATCH_AND_ASSERT(); + ASSERT (exceptionCaught, "No exception thrown from the outer parallel_for"); + if ( g_SolitaryException ) { + ASSERT (g_CurExecuted > minExecuted, "Too few tasks survived exception"); + ASSERT (g_CurExecuted <= minExecuted + (g_ExecutedAtCatch + g_NumThreads), "Too many tasks survived exception"); + } + ASSERT (g_Exceptions == 1, "No try_blocks in any body expected in this test"); + if ( !g_SolitaryException ) + ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); +} // void Test3 () + +class OuterParForExceptionSafeBody { +public: + void operator()( const range_type& ) const { + tbb::task_group_context ctx(tbb::task_group_context::isolated); + TRY(); + tbb::parallel_for( tbb::blocked_range<size_t>(0, INNER_RANGE, INNER_GRAIN), SimpleParForBody(), tbb::simple_partitioner(), ctx ); + CATCH(); // this macro sets g_ExceptionCaught + } +}; + +//! Uses parallel_for body invoking an inner parallel_for (with default bound context) inside a try-block. +/** Since exception(s) thrown from the inner parallel_for are handled by the caller + in this test, they do not affect neither other tasks of the the root parallel_for + nor sibling inner algorithms. **/ +void Test4 () { + ResetGlobals( true, true ); + intptr_t innerCalls = NumSubranges(INNER_RANGE, INNER_GRAIN), + outerCalls = NumSubranges(OUTER_RANGE, OUTER_GRAIN), + maxExecuted = outerCalls * innerCalls; + TRY(); + tbb::parallel_for( range_type(0, OUTER_RANGE, OUTER_GRAIN), OuterParForExceptionSafeBody() ); + CATCH(); + ASSERT(!exceptionCaught, "All exceptions must have been handled in the parallel_for body"); + intptr_t minExecuted = 0; + if ( g_SolitaryException ) { + minExecuted = maxExecuted - innerCalls; + ASSERT (g_Exceptions == 1, "No exception registered"); + ASSERT (g_CurExecuted >= minExecuted, "Too few tasks executed"); + ASSERT (g_CurExecuted <= minExecuted + g_NumThreads, "Too many tasks survived exception"); + } + else { + minExecuted = g_Exceptions; + ASSERT (g_Exceptions > 1 && g_Exceptions <= outerCalls, "Unexpected actual number of exceptions"); + ASSERT (g_CurExecuted >= minExecuted, "Too many executed tasks reported"); + ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived multiple exceptions"); + ASSERT (g_CurExecuted <= outerCalls * (1 + g_NumThreads), "Too many tasks survived exception"); + } +} // void Test4 () + +#endif /* TBB_USE_EXCEPTIONS */ + +class ParForBodyToCancel { +public: + void operator()( const range_type& ) const { + ++g_CurExecuted; + CancellatorTask::WaitUntilReady(); + } +}; + +template<class B> +class ParForLauncherTask : public tbb::task { + tbb::task_group_context &my_ctx; + + tbb::task* execute () { + tbb::parallel_for( range_type(0, FLAT_RANGE, FLAT_GRAIN), B(), tbb::simple_partitioner(), my_ctx ); + return NULL; + } +public: + ParForLauncherTask ( tbb::task_group_context& ctx ) : my_ctx(ctx) {} +}; + +//! Test for cancelling an algorithm from outside (from a task running in parallel with the algorithm). +void TestCancelation1 () { + ResetGlobals( false ); + RunCancellationTest<ParForLauncherTask<ParForBodyToCancel>, CancellatorTask>( NumSubranges(FLAT_RANGE, FLAT_GRAIN) / 4 ); + ASSERT (g_CurExecuted < g_ExecutedAtCatch + g_NumThreads, "Too many tasks were executed after cancellation"); +} + +class CancellatorTask2 : public tbb::task { + tbb::task_group_context &m_GroupToCancel; + + tbb::task* execute () { + Harness::ConcurrencyTracker ct; + WaitUntilConcurrencyPeaks(); + m_GroupToCancel.cancel_group_execution(); + g_ExecutedAtCatch = g_CurExecuted; + return NULL; + } +public: + CancellatorTask2 ( tbb::task_group_context& ctx, intptr_t ) : m_GroupToCancel(ctx) {} +}; + +class ParForBodyToCancel2 { +public: + void operator()( const range_type& ) const { + ++g_CurExecuted; + Harness::ConcurrencyTracker ct; + // The test will hang (and be timed out by the test system) if is_cancelled() is broken + while( !tbb::task::self().is_cancelled() ) + __TBB_Yield(); + } +}; + +//! Test for cancelling an algorithm from outside (from a task running in parallel with the algorithm). +/** This version also tests task::is_cancelled() method. **/ +void TestCancelation2 () { + ResetGlobals(); + RunCancellationTest<ParForLauncherTask<ParForBodyToCancel2>, CancellatorTask2>(); + ASSERT (g_ExecutedAtCatch < g_NumThreads, "Somehow worker tasks started their execution before the cancellator task"); + ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Some tasks were executed after cancellation"); +} + +//////////////////////////////////////////////////////////////////////////////// +// Regression test based on the contribution by the author of the following forum post: +// http://softwarecommunity.intel.com/isn/Community/en-US/forums/thread/30254959.aspx + +class Worker { + static const int max_nesting = 3; + static const int reduce_range = 1024; + static const int reduce_grain = 256; +public: + int DoWork (int level); + int Validate (int start_level) { + int expected = 1; // identity for multiplication + for(int i=start_level+1; i<max_nesting; ++i) + expected *= reduce_range; + return expected; + } +}; + +class RecursiveParReduceBodyWithSharedWorker { + Worker * m_SharedWorker; + int m_NestingLevel; + int m_Result; +public: + RecursiveParReduceBodyWithSharedWorker ( RecursiveParReduceBodyWithSharedWorker& src, tbb::split ) + : m_SharedWorker(src.m_SharedWorker) + , m_NestingLevel(src.m_NestingLevel) + , m_Result(0) + {} + RecursiveParReduceBodyWithSharedWorker ( Worker *w, int outer ) + : m_SharedWorker(w) + , m_NestingLevel(outer) + , m_Result(0) + {} + + void operator() ( const tbb::blocked_range<size_t>& r ) { + for (size_t i = r.begin (); i != r.end (); ++i) { + m_Result += m_SharedWorker->DoWork (m_NestingLevel); + } + } + void join (const RecursiveParReduceBodyWithSharedWorker & x) { + m_Result += x.m_Result; + } + int result () { return m_Result; } +}; + +int Worker::DoWork ( int level ) { + ++level; + if ( level < max_nesting ) { + RecursiveParReduceBodyWithSharedWorker rt (this, level); + tbb::parallel_reduce (tbb::blocked_range<size_t>(0, reduce_range, reduce_grain), rt); + return rt.result(); + } + else + return 1; +} + +//! Regression test for hanging that occurred with the first version of cancellation propagation +void TestCancelation3 () { + Worker w; + int result = w.DoWork (0); + int expected = w.Validate(0); + ASSERT ( result == expected, "Wrong calculation result"); +} + +void RunParForAndReduceTests () { + REMARK( "parallel for and reduce tests\n" ); + tbb::task_scheduler_init init (g_NumThreads); + g_Master = Harness::CurrentTid(); + +#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN + Test0(); + Test1(); + Test2(); + Test3(); + Test4(); +#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */ + TestCancelation1(); + TestCancelation2(); + TestCancelation3(); +} + +//////////////////////////////////////////////////////////////////////////////// +// Tests for tbb::parallel_do + +#define ITER_RANGE 1000 +#define ITEMS_TO_FEED 50 +#define INNER_ITER_RANGE 100 +#define OUTER_ITER_RANGE 50 + +#define PREPARE_RANGE(Iterator, rangeSize) \ + size_t test_vector[rangeSize + 1]; \ + for (int i =0; i < rangeSize; i++) \ + test_vector[i] = i; \ + Iterator begin(&test_vector[0]); \ + Iterator end(&test_vector[rangeSize]) + +void Feed ( tbb::parallel_do_feeder<size_t> &feeder, size_t val ) { + if (g_FedTasksCount < ITEMS_TO_FEED) { + ++g_FedTasksCount; + feeder.add(val); + } +} + +#include "harness_iterator.h" + +#if TBB_USE_EXCEPTIONS + +// Simple functor object with exception +class SimpleParDoBody { +public: + void operator() ( size_t &value ) const { + ++g_CurExecuted; + Harness::ConcurrencyTracker ct; + value += 1000; + WaitUntilConcurrencyPeaks(); + ThrowTestException(1); + } +}; + +// Simple functor object with exception and feeder +class SimpleParDoBodyWithFeeder : SimpleParDoBody { +public: + void operator() ( size_t &value, tbb::parallel_do_feeder<size_t> &feeder ) const { + Feed(feeder, 0); + SimpleParDoBody::operator()(value); + } +}; + +// Tests exceptions without nesting +template <class Iterator, class simple_body> +void Test1_parallel_do () { + ResetGlobals(); + PREPARE_RANGE(Iterator, ITER_RANGE); + TRY(); + tbb::parallel_do<Iterator, simple_body>(begin, end, simple_body() ); + CATCH_AND_ASSERT(); + ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); + ASSERT (g_Exceptions == 1, "No try_blocks in any body expected in this test"); + if ( !g_SolitaryException ) + ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); + +} // void Test1_parallel_do () + +template <class Iterator> +class OuterParDoBody { +public: + void operator()( size_t& /*value*/ ) const { + ++g_CurExecuted; + PREPARE_RANGE(Iterator, INNER_ITER_RANGE); + tbb::parallel_do<Iterator, SimpleParDoBody>(begin, end, SimpleParDoBody()); + } +}; + +template <class Iterator> +class OuterParDoBodyWithFeeder : OuterParDoBody<Iterator> { +public: + void operator()( size_t& value, tbb::parallel_do_feeder<size_t>& feeder ) const { + Feed(feeder, 0); + OuterParDoBody<Iterator>::operator()(value); + } +}; + +//! Uses parallel_do body containing an inner parallel_do with the default context not wrapped by a try-block. +/** Inner algorithms are spawned inside the new bound context by default. Since + exceptions thrown from the inner parallel_do are not handled by the caller + (outer parallel_do body) in this test, they will cancel all the sibling inner + algorithms. **/ +template <class Iterator, class outer_body> +void Test2_parallel_do () { + ResetGlobals(); + PREPARE_RANGE(Iterator, ITER_RANGE); + TRY(); + tbb::parallel_do<Iterator, outer_body >(begin, end, outer_body() ); + CATCH_AND_ASSERT(); + ASSERT (exceptionCaught, "No exception thrown from the outer parallel_for"); + //if ( g_SolitaryException ) + ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); + ASSERT (g_Exceptions == 1, "No try_blocks in any body expected in this test"); + if ( !g_SolitaryException ) + ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); +} // void Test2_parallel_do () + +template <class Iterator> +class OuterParDoBodyWithIsolatedCtx { +public: + void operator()( size_t& /*value*/ ) const { + tbb::task_group_context ctx(tbb::task_group_context::isolated); + ++g_CurExecuted; + PREPARE_RANGE(Iterator, INNER_ITER_RANGE); + tbb::parallel_do<Iterator, SimpleParDoBody>(begin, end, SimpleParDoBody(), ctx); + } +}; + +template <class Iterator> +class OuterParDoBodyWithIsolatedCtxWithFeeder : OuterParDoBodyWithIsolatedCtx<Iterator> { +public: + void operator()( size_t& value, tbb::parallel_do_feeder<size_t> &feeder ) const { + Feed(feeder, 0); + OuterParDoBodyWithIsolatedCtx<Iterator>::operator()(value); + } +}; + +//! Uses parallel_do body invoking an inner parallel_do with an isolated context without a try-block. +/** Even though exceptions thrown from the inner parallel_do are not handled + by the caller in this test, they will not affect sibling inner algorithms + already running because of the isolated contexts. However because the first + exception cancels the root parallel_do, only the first g_NumThreads subranges + will be processed (which launch inner parallel_dos) **/ +template <class Iterator, class outer_body> +void Test3_parallel_do () { + ResetGlobals(); + PREPARE_RANGE(Iterator, OUTER_ITER_RANGE); + intptr_t innerCalls = INNER_ITER_RANGE, + minExecuted = (g_NumThreads - 1) * innerCalls; + TRY(); + tbb::parallel_do<Iterator, outer_body >(begin, end, outer_body()); + CATCH_AND_ASSERT(); + ASSERT (exceptionCaught, "No exception thrown from the outer parallel_for"); + if ( g_SolitaryException ) { + ASSERT (g_CurExecuted > minExecuted, "Too few tasks survived exception"); + ASSERT (g_CurExecuted <= minExecuted + (g_ExecutedAtCatch + g_NumThreads), "Too many tasks survived exception"); + } + ASSERT (g_Exceptions == 1, "No try_blocks in any body expected in this test"); + if ( !g_SolitaryException ) + ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); +} // void Test3_parallel_do () + +template <class Iterator> +class OuterParDoWithEhBody { +public: + void operator()( size_t& /*value*/ ) const { + tbb::task_group_context ctx(tbb::task_group_context::isolated); + PREPARE_RANGE(Iterator, INNER_ITER_RANGE); + TRY(); + tbb::parallel_do<Iterator, SimpleParDoBody>(begin, end, SimpleParDoBody(), ctx); + CATCH(); + } +}; + +template <class Iterator> +class OuterParDoWithEhBodyWithFeeder : NoAssign, OuterParDoWithEhBody<Iterator> { +public: + void operator()( size_t &value, tbb::parallel_do_feeder<size_t> &feeder ) const { + Feed(feeder, 0); + OuterParDoWithEhBody<Iterator>::operator()(value); + } +}; + +//! Uses parallel_for body invoking an inner parallel_for (with default bound context) inside a try-block. +/** Since exception(s) thrown from the inner parallel_for are handled by the caller + in this test, they do not affect neither other tasks of the the root parallel_for + nor sibling inner algorithms. **/ +template <class Iterator, class outer_body_with_eh> +void Test4_parallel_do () { + ResetGlobals( true, true ); + PREPARE_RANGE(Iterator, OUTER_ITER_RANGE); + TRY(); + tbb::parallel_do<Iterator, outer_body_with_eh>(begin, end, outer_body_with_eh()); + CATCH(); + ASSERT (!exceptionCaught, "All exceptions must have been handled in the parallel_do body"); + intptr_t innerCalls = INNER_ITER_RANGE, + outerCalls = OUTER_ITER_RANGE + g_FedTasksCount, + maxExecuted = outerCalls * innerCalls, + minExecuted = 0; + if ( g_SolitaryException ) { + minExecuted = maxExecuted - innerCalls; + ASSERT (g_Exceptions == 1, "No exception registered"); + ASSERT (g_CurExecuted >= minExecuted, "Too few tasks executed"); + ASSERT (g_CurExecuted <= minExecuted + g_NumThreads, "Too many tasks survived exception"); + } + else { + minExecuted = g_Exceptions; + ASSERT (g_Exceptions > 1 && g_Exceptions <= outerCalls, "Unexpected actual number of exceptions"); + ASSERT (g_CurExecuted >= minExecuted, "Too many executed tasks reported"); + ASSERT (g_CurExecuted < g_ExecutedAtCatch + g_NumThreads + outerCalls, "Too many tasks survived multiple exceptions"); + ASSERT (g_CurExecuted <= outerCalls * (1 + g_NumThreads), "Too many tasks survived exception"); + } +} // void Test4_parallel_do () + +// This body throws an exception only if the task was added by feeder +class ParDoBodyWithThrowingFeederTasks { +public: + //! This form of the function call operator can be used when the body needs to add more work during the processing + void operator() ( size_t &value, tbb::parallel_do_feeder<size_t> &feeder ) const { + ++g_CurExecuted; + Feed(feeder, 1); + if (value == 1) + ThrowTestException(1); + } +}; // class ParDoBodyWithThrowingFeederTasks + +// Test exception in task, which was added by feeder. +template <class Iterator> +void Test5_parallel_do () { + ResetGlobals(); + PREPARE_RANGE(Iterator, ITER_RANGE); + TRY(); + tbb::parallel_do<Iterator, ParDoBodyWithThrowingFeederTasks>(begin, end, ParDoBodyWithThrowingFeederTasks()); + CATCH(); + if (g_SolitaryException) + ASSERT (exceptionCaught, "At least one exception should occur"); +} // void Test5_parallel_do () + +#endif /* TBB_USE_EXCEPTIONS */ + +class ParDoBodyToCancel { +public: + void operator()( size_t& /*value*/ ) const { + ++g_CurExecuted; + CancellatorTask::WaitUntilReady(); + } +}; + +class ParDoBodyToCancelWithFeeder : ParDoBodyToCancel { +public: + void operator()( size_t& value, tbb::parallel_do_feeder<size_t> &feeder ) const { + Feed(feeder, 0); + ParDoBodyToCancel::operator()(value); + } +}; + +template<class B, class Iterator> +class ParDoWorkerTask : public tbb::task { + tbb::task_group_context &my_ctx; + + tbb::task* execute () { + PREPARE_RANGE(Iterator, INNER_ITER_RANGE); + tbb::parallel_do<Iterator, B>( begin, end, B(), my_ctx ); + return NULL; + } +public: + ParDoWorkerTask ( tbb::task_group_context& ctx ) : my_ctx(ctx) {} +}; + +//! Test for cancelling an algorithm from outside (from a task running in parallel with the algorithm). +template <class Iterator, class body_to_cancel> +void TestCancelation1_parallel_do () { + ResetGlobals( false ); + intptr_t threshold = 10; + tbb::task_group_context ctx; + ctx.reset(); + tbb::empty_task &r = *new( tbb::task::allocate_root() ) tbb::empty_task; + r.set_ref_count(3); + r.spawn( *new( r.allocate_child() ) CancellatorTask(ctx, threshold) ); + __TBB_Yield(); + r.spawn( *new( r.allocate_child() ) ParDoWorkerTask<body_to_cancel, Iterator>(ctx) ); + TRY(); + r.wait_for_all(); + CATCH_AND_FAIL(); + ASSERT (g_CurExecuted < g_ExecutedAtCatch + g_NumThreads, "Too many tasks were executed after cancellation"); + r.destroy(r); +} + +class ParDoBodyToCancel2 { +public: + void operator()( size_t& /*value*/ ) const { + ++g_CurExecuted; + Harness::ConcurrencyTracker ct; + // The test will hang (and be timed out by the test system) if is_cancelled() is broken + while( !tbb::task::self().is_cancelled() ) + __TBB_Yield(); + } +}; + +class ParDoBodyToCancel2WithFeeder : ParDoBodyToCancel2 { +public: + void operator()( size_t& value, tbb::parallel_do_feeder<size_t> &feeder ) const { + Feed(feeder, 0); + ParDoBodyToCancel2::operator()(value); + } +}; + +//! Test for cancelling an algorithm from outside (from a task running in parallel with the algorithm). +/** This version also tests task::is_cancelled() method. **/ +template <class Iterator, class body_to_cancel> +void TestCancelation2_parallel_do () { + ResetGlobals(); + RunCancellationTest<ParDoWorkerTask<body_to_cancel, Iterator>, CancellatorTask2>(); + ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Some tasks were executed after cancellation"); +} + +#define RunWithSimpleBody(func, body) \ + func<Harness::RandomIterator<size_t>, body>(); \ + func<Harness::RandomIterator<size_t>, body##WithFeeder>(); \ + func<Harness::ForwardIterator<size_t>, body>(); \ + func<Harness::ForwardIterator<size_t>, body##WithFeeder>() + +#define RunWithTemplatedBody(func, body) \ + func<Harness::RandomIterator<size_t>, body<Harness::RandomIterator<size_t> > >(); \ + func<Harness::RandomIterator<size_t>, body##WithFeeder<Harness::RandomIterator<size_t> > >(); \ + func<Harness::ForwardIterator<size_t>, body<Harness::ForwardIterator<size_t> > >(); \ + func<Harness::ForwardIterator<size_t>, body##WithFeeder<Harness::ForwardIterator<size_t> > >() + +void RunParDoTests() { + REMARK( "parallel do tests\n" ); + tbb::task_scheduler_init init (g_NumThreads); + g_Master = Harness::CurrentTid(); +#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN + RunWithSimpleBody(Test1_parallel_do, SimpleParDoBody); + RunWithTemplatedBody(Test2_parallel_do, OuterParDoBody); + RunWithTemplatedBody(Test3_parallel_do, OuterParDoBodyWithIsolatedCtx); + RunWithTemplatedBody(Test4_parallel_do, OuterParDoWithEhBody); + Test5_parallel_do<Harness::ForwardIterator<size_t> >(); + Test5_parallel_do<Harness::RandomIterator<size_t> >(); +#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */ + RunWithSimpleBody(TestCancelation1_parallel_do, ParDoBodyToCancel); + RunWithSimpleBody(TestCancelation2_parallel_do, ParDoBodyToCancel2); +} + +//////////////////////////////////////////////////////////////////////////////// +// Tests for tbb::pipeline + +#define NUM_ITEMS 100 + +const size_t c_DataEndTag = size_t(~0); + +int g_NumTokens = 0; + +// Simple input filter class, it assigns 1 to all array members +// It stops when it receives item equal to -1 +class InputFilter: public tbb::filter { + tbb::atomic<size_t> m_Item; + size_t m_Buffer[NUM_ITEMS + 1]; +public: + InputFilter() : tbb::filter(parallel) { + m_Item = 0; + for (size_t i = 0; i < NUM_ITEMS; ++i ) + m_Buffer[i] = 1; + m_Buffer[NUM_ITEMS] = c_DataEndTag; + } + + void* operator()( void* ) { + size_t item = m_Item.fetch_and_increment(); + if ( item >= NUM_ITEMS ) + return NULL; + m_Buffer[item] = 1; + return &m_Buffer[item]; + } + + size_t* buffer() { return m_Buffer; } +}; // class InputFilter + +// Pipeline filter, without exceptions throwing +class NoThrowFilter : public tbb::filter { + size_t m_Value; +public: + enum operation { + addition, + subtraction, + multiplication + } m_Operation; + + NoThrowFilter(operation _operation, size_t value, bool is_parallel) + : filter(is_parallel? tbb::filter::parallel : tbb::filter::serial_in_order), + m_Value(value), m_Operation(_operation) + {} + void* operator()(void* item) { + size_t &value = *(size_t*)item; + ASSERT(value != c_DataEndTag, "terminator element is being processed"); + switch (m_Operation){ + case addition: + value += m_Value; + break; + case subtraction: + value -= m_Value; + break; + case multiplication: + value *= m_Value; + break; + default: + ASSERT(0, "Wrong operation parameter passed to NoThrowFilter"); + } // switch (m_Operation) + return item; + } +}; + +// Test pipeline without exceptions throwing +void Test0_pipeline () { + ResetGlobals(); + // Run test when serial filter is the first non-input filter + InputFilter inputFilter; //Emits NUM_ITEMS items + NoThrowFilter filter1(NoThrowFilter::addition, 99, false); + NoThrowFilter filter2(NoThrowFilter::subtraction, 90, true); + NoThrowFilter filter3(NoThrowFilter::multiplication, 5, false); + // Result should be 50 for all items except the last + tbb::pipeline p; + p.add_filter(inputFilter); + p.add_filter(filter1); + p.add_filter(filter2); + p.add_filter(filter3); + p.run(8); + for (size_t i = 0; i < NUM_ITEMS; ++i) + ASSERT(inputFilter.buffer()[i] == 50, "pipeline didn't process items properly"); +} // void Test0_pipeline () + +#if TBB_USE_EXCEPTIONS + +// Simple filter with exception throwing +class SimpleFilter : public tbb::filter { + bool m_canThrow; +public: + SimpleFilter (tbb::filter::mode _mode, bool canThrow ) : filter (_mode), m_canThrow(canThrow) {} + + void* operator()(void* item) { + ++g_CurExecuted; + if ( m_canThrow ) { + if ( !is_serial() ) { + Harness::ConcurrencyTracker ct; + WaitUntilConcurrencyPeaks( min(g_NumTokens, g_NumThreads) ); + } + ThrowTestException(1); + } + return item; + } +}; // class SimpleFilter + +// This enumeration represents filters order in pipeline +struct FilterSet { + tbb::filter::mode mode1, + mode2; + bool throw1, + throw2; + + FilterSet( tbb::filter::mode m1, tbb::filter::mode m2, bool t1, bool t2 ) + : mode1(m1), mode2(m2), throw1(t1), throw2(t2) + {} +}; // struct FilterSet + +FilterSet serial_parallel( tbb::filter::serial, tbb::filter::parallel, /*throw1*/false, /*throw2*/true ); + +template<typename InFilter, typename Filter> +class CustomPipeline : protected tbb::pipeline { + InFilter inputFilter; + Filter filter1; + Filter filter2; +public: + CustomPipeline( const FilterSet& filters ) + : filter1(filters.mode1, filters.throw1), filter2(filters.mode2, filters.throw2) + { + add_filter(inputFilter); + add_filter(filter1); + add_filter(filter2); + } + void run () { tbb::pipeline::run(g_NumTokens); } + void run ( tbb::task_group_context& ctx ) { tbb::pipeline::run(g_NumTokens, ctx); } + + using tbb::pipeline::add_filter; +}; + +typedef CustomPipeline<InputFilter, SimpleFilter> SimplePipeline; + +// Tests exceptions without nesting +void Test1_pipeline ( const FilterSet& filters ) { + ResetGlobals(); + SimplePipeline testPipeline(filters); + TRY(); + testPipeline.run(); + if ( g_CurExecuted == 2 * NUM_ITEMS ) { + // In case of all serial filters they might be all executed in the thread(s) + // where exceptions are not allowed by the common test logic. So we just quit. + return; + } + CATCH_AND_ASSERT(); + ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); + ASSERT (g_Exceptions == 1, "No try_blocks in any body expected in this test"); + if ( !g_SolitaryException ) + ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); + +} // void Test1_pipeline () + +// Filter with nesting +class OuterFilter : public tbb::filter { +public: + OuterFilter (tbb::filter::mode _mode, bool ) : filter (_mode) {} + + void* operator()(void* item) { + ++g_CurExecuted; + SimplePipeline testPipeline(serial_parallel); + testPipeline.run(); + return item; + } +}; // class OuterFilter + +//! Uses pipeline containing an inner pipeline with the default context not wrapped by a try-block. +/** Inner algorithms are spawned inside the new bound context by default. Since + exceptions thrown from the inner pipeline are not handled by the caller + (outer pipeline body) in this test, they will cancel all the sibling inner + algorithms. **/ +void Test2_pipeline ( const FilterSet& filters ) { + ResetGlobals(); + CustomPipeline<InputFilter, OuterFilter> testPipeline(filters); + TRY(); + testPipeline.run(); + CATCH_AND_ASSERT(); + ASSERT (exceptionCaught, "No exception thrown from the outer pipeline"); + ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); + ASSERT (g_Exceptions == 1, "No try_blocks in any body expected in this test"); + if ( !g_SolitaryException ) + ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); +} // void Test2_pipeline () + +//! creates isolated inner pipeline and runs it. +class OuterFilterWithIsolatedCtx : public tbb::filter { +public: + OuterFilterWithIsolatedCtx(tbb::filter::mode m, bool ) : filter(m) {} + + void* operator()(void* item) { + ++g_CurExecuted; + tbb::task_group_context ctx(tbb::task_group_context::isolated); + // create inner pipeline with serial input, parallel output filter, second filter throws + SimplePipeline testPipeline(serial_parallel); + testPipeline.run(ctx); + return item; + } +}; // class OuterFilterWithIsolatedCtx + +//! Uses pipeline invoking an inner pipeline with an isolated context without a try-block. +/** Even though exceptions thrown from the inner pipeline are not handled + by the caller in this test, they will not affect sibling inner algorithms + already running because of the isolated contexts. However because the first + exception cancels the root parallel_do only the first g_NumThreads subranges + will be processed (which launch inner pipelines) **/ +void Test3_pipeline ( const FilterSet& filters ) { + ResetGlobals(); + intptr_t innerCalls = NUM_ITEMS, + minExecuted = (g_NumThreads - 1) * innerCalls; + CustomPipeline<InputFilter, OuterFilterWithIsolatedCtx> testPipeline(filters); + TRY(); + testPipeline.run(); + CATCH_AND_ASSERT(); + ASSERT (exceptionCaught, "No exception thrown from the outer parallel_for"); + if ( g_SolitaryException ) { + ASSERT (g_CurExecuted > minExecuted, "Too few tasks survived exception"); + ASSERT (g_CurExecuted <= minExecuted + (g_ExecutedAtCatch + g_NumThreads), "Too many tasks survived exception"); + } + ASSERT (g_Exceptions == 1, "No try_blocks in any body expected in this test"); + if ( !g_SolitaryException ) + ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived exception"); +} // void Test3_pipeline () + +class OuterFilterWithEhBody : public tbb::filter { +public: + OuterFilterWithEhBody(tbb::filter::mode m, bool ) : filter(m) {} + + void* operator()(void* item) { + tbb::task_group_context ctx(tbb::task_group_context::isolated); + SimplePipeline testPipeline(serial_parallel); + TRY(); + testPipeline.run(ctx); + CATCH(); + return item; + } +}; // class OuterFilterWithEhBody + +//! Uses pipeline body invoking an inner pipeline (with default bound context) inside a try-block. +/** Since exception(s) thrown from the inner pipeline are handled by the caller + in this test, they do not affect other tasks of the the root pipeline + nor sibling inner algorithms. **/ +void Test4_pipeline ( const FilterSet& filters ) { +#if __GNUC__ && !__INTEL_COMPILER + if ( strncmp(__VERSION__, "4.1.0", 5) == 0 ) { + REMARK_ONCE("Known issue: one of exception handling tests is skipped.\n"); + return; + } +#endif + ResetGlobals( true, true ); + intptr_t innerCalls = NUM_ITEMS + 1, + outerCalls = 2 * (NUM_ITEMS + 1), + maxExecuted = outerCalls * innerCalls; // the number of invocations of the inner pipelines + CustomPipeline<InputFilter, OuterFilterWithEhBody> testPipeline(filters); + TRY(); + testPipeline.run(); + CATCH_AND_ASSERT(); + ASSERT (!exceptionCaught, "All exceptions must have been handled in the parallel_do body"); + intptr_t minExecuted = 0; + if ( g_SolitaryException ) { + minExecuted = maxExecuted - innerCalls; // one throwing inner pipeline + ASSERT (g_Exceptions != 0, "No exception registered"); + ASSERT (g_CurExecuted <= minExecuted + g_NumThreads, "Too many tasks survived exception"); + } + else { + minExecuted = g_Exceptions; + ASSERT (g_Exceptions > 1 && g_Exceptions <= outerCalls, "Unexpected actual number of exceptions"); + ASSERT (g_CurExecuted >= minExecuted, "Too many executed tasks reported"); + ASSERT (g_CurExecuted <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks survived multiple exceptions"); + } +} // void Test4_pipeline () + +//! Testing filter::finalize method +#define BUFFER_SIZE 32 +#define NUM_BUFFERS 1024 + +tbb::atomic<size_t> g_AllocatedCount; // Number of currently allocated buffers +tbb::atomic<size_t> g_TotalCount; // Total number of allocated buffers + +//! Base class for all filters involved in finalize method testing +class FinalizationBaseFilter : public tbb::filter { +public: + FinalizationBaseFilter ( tbb::filter::mode m ) : filter(m) {} + + // Deletes buffers if exception occurred + virtual void finalize( void* item ) { + size_t* m_Item = (size_t*)item; + delete[] m_Item; + --g_AllocatedCount; + } +}; + +//! Input filter to test finalize method +class InputFilterWithFinalization: public FinalizationBaseFilter { +public: + InputFilterWithFinalization() : FinalizationBaseFilter(tbb::filter::serial) { + g_TotalCount = 0; + } + void* operator()( void* ){ + if (g_TotalCount == NUM_BUFFERS) + return NULL; + size_t* item = new size_t[BUFFER_SIZE]; + for (int i = 0; i < BUFFER_SIZE; i++) + item[i] = 1; + ++g_TotalCount; + ++g_AllocatedCount; + return item; + } +}; + +// The filter multiplies each buffer item by 10. +class ProcessingFilterWithFinalization : public FinalizationBaseFilter { +public: + ProcessingFilterWithFinalization (tbb::filter::mode _mode, bool) : FinalizationBaseFilter (_mode) {} + + void* operator()( void* item) { + if (g_TotalCount > NUM_BUFFERS / 2) + ThrowTestException(1); + size_t* m_Item = (size_t*)item; + for (int i = 0; i < BUFFER_SIZE; i++) + m_Item[i] *= 10; + return item; + } +}; + +// Output filter deletes previously allocated buffer +class OutputFilterWithFinalization : public FinalizationBaseFilter { +public: + OutputFilterWithFinalization (tbb::filter::mode m) : FinalizationBaseFilter (m) {} + + void* operator()( void* item){ + size_t* m_Item = (size_t*)item; + delete[] m_Item; + --g_AllocatedCount; + return NULL; + } +}; + +//! Tests filter::finalize method +void Test5_pipeline ( const FilterSet& filters ) { + ResetGlobals(); + g_AllocatedCount = 0; + CustomPipeline<InputFilterWithFinalization, ProcessingFilterWithFinalization> testPipeline(filters); + OutputFilterWithFinalization my_output_filter(tbb::filter::parallel); + + testPipeline.add_filter(my_output_filter); + TRY(); + testPipeline.run(); + CATCH(); + ASSERT (g_AllocatedCount == 0, "Memory leak: Some my_object weren't destroyed"); +} // void Test5_pipeline () + +//! Tests pipeline function passed with different combination of filters +template<void testFunc(const FilterSet&)> +void TestWithDifferentFilters() { + const int NumFilterTypes = 3; + const tbb::filter::mode modes[NumFilterTypes] = { + tbb::filter::parallel, + tbb::filter::serial, + tbb::filter::serial_out_of_order + }; + for ( int i = 0; i < NumFilterTypes; ++i ) { + for ( int j = 0; j < NumFilterTypes; ++j ) { + for ( int k = 0; k < 2; ++k ) + testFunc( FilterSet(modes[i], modes[j], k == 0, k != 0) ); + } + } +} + +#endif /* TBB_USE_EXCEPTIONS */ + +class FilterToCancel : public tbb::filter { +public: + FilterToCancel(bool is_parallel) + : filter( is_parallel ? tbb::filter::parallel : tbb::filter::serial_in_order ) + {} + void* operator()(void* item) { + ++g_CurExecuted; + CancellatorTask::WaitUntilReady(); + return item; + } +}; // class FilterToCancel + +template <class Filter_to_cancel> +class PipelineLauncherTask : public tbb::task { + tbb::task_group_context &my_ctx; +public: + PipelineLauncherTask ( tbb::task_group_context& ctx ) : my_ctx(ctx) {} + + tbb::task* execute () { + // Run test when serial filter is the first non-input filter + InputFilter inputFilter; + Filter_to_cancel filterToCancel(true); + tbb::pipeline p; + p.add_filter(inputFilter); + p.add_filter(filterToCancel); + p.run(g_NumTokens, my_ctx); + return NULL; + } +}; + +//! Test for cancelling an algorithm from outside (from a task running in parallel with the algorithm). +void TestCancelation1_pipeline () { + ResetGlobals(); + g_ThrowException = false; + intptr_t threshold = 10; + tbb::task_group_context ctx; + ctx.reset(); + tbb::empty_task &r = *new( tbb::task::allocate_root() ) tbb::empty_task; + r.set_ref_count(3); + r.spawn( *new( r.allocate_child() ) CancellatorTask(ctx, threshold) ); + __TBB_Yield(); + r.spawn( *new( r.allocate_child() ) PipelineLauncherTask<FilterToCancel>(ctx) ); + TRY(); + r.wait_for_all(); + CATCH_AND_FAIL(); + r.destroy(r); + ASSERT (g_CurExecuted < g_ExecutedAtCatch + g_NumThreads, "Too many tasks were executed after cancellation"); +} + +class FilterToCancel2 : public tbb::filter { +public: + FilterToCancel2(bool is_parallel) + : filter ( is_parallel ? tbb::filter::parallel : tbb::filter::serial_in_order) + {} + + void* operator()(void* item) { + ++g_CurExecuted; + Harness::ConcurrencyTracker ct; + // The test will hang (and be timed out by the tesst system) if is_cancelled() is broken + while( !tbb::task::self().is_cancelled() ) + __TBB_Yield(); + return item; + } +}; + +//! Test for cancelling an algorithm from outside (from a task running in parallel with the algorithm). +/** This version also tests task::is_cancelled() method. **/ +void TestCancelation2_pipeline () { + ResetGlobals(); + RunCancellationTest<PipelineLauncherTask<FilterToCancel2>, CancellatorTask2>(); + ASSERT (g_CurExecuted <= g_ExecutedAtCatch, "Some tasks were executed after cancellation"); +} + +void RunPipelineTests() { + REMARK( "pipeline tests\n" ); + tbb::task_scheduler_init init (g_NumThreads); + g_Master = Harness::CurrentTid(); + g_NumTokens = 2 * g_NumThreads; + + Test0_pipeline(); +#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN + TestWithDifferentFilters<Test1_pipeline>(); + TestWithDifferentFilters<Test2_pipeline>(); + TestWithDifferentFilters<Test3_pipeline>(); + TestWithDifferentFilters<Test4_pipeline>(); + TestWithDifferentFilters<Test5_pipeline>(); +#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */ + TestCancelation1_pipeline(); + TestCancelation2_pipeline(); +} + + +#if TBB_USE_EXCEPTIONS + +class MyCapturedException : public tbb::captured_exception { +public: + static int m_refCount; + + MyCapturedException () : tbb::captured_exception("MyCapturedException", "test") { ++m_refCount; } + ~MyCapturedException () throw() { --m_refCount; } + + MyCapturedException* move () throw() { + MyCapturedException* movee = (MyCapturedException*)malloc(sizeof(MyCapturedException)); + return ::new (movee) MyCapturedException; + } + void destroy () throw() { + this->~MyCapturedException(); + free(this); + } + void operator delete ( void* p ) { free(p); } +}; + +int MyCapturedException::m_refCount = 0; + +void DeleteTbbException ( volatile tbb::tbb_exception* pe ) { + delete pe; +} + +void TestTbbExceptionAPI () { + const char *name = "Test captured exception", + *reason = "Unit testing"; + tbb::captured_exception e(name, reason); + ASSERT (strcmp(e.name(), name) == 0, "Setting captured exception name failed"); + ASSERT (strcmp(e.what(), reason) == 0, "Setting captured exception reason failed"); + tbb::captured_exception c(e); + ASSERT (strcmp(c.name(), e.name()) == 0, "Copying captured exception name failed"); + ASSERT (strcmp(c.what(), e.what()) == 0, "Copying captured exception reason failed"); + tbb::captured_exception *m = e.move(); + ASSERT (strcmp(m->name(), name) == 0, "Moving captured exception name failed"); + ASSERT (strcmp(m->what(), reason) == 0, "Moving captured exception reason failed"); + ASSERT (!e.name() && !e.what(), "Moving semantics broken"); + m->destroy(); + + MyCapturedException mce; + MyCapturedException *mmce = mce.move(); + ASSERT( MyCapturedException::m_refCount == 2, NULL ); + DeleteTbbException(mmce); + ASSERT( MyCapturedException::m_refCount == 1, NULL ); +} + +#endif /* TBB_USE_EXCEPTIONS */ + +/** If min and max thread numbers specified on the command line are different, + the test is run only for 2 sizes of the thread pool (MinThread and MaxThread) + to be able to test the high and low contention modes while keeping the test reasonably fast **/ +int TestMain () { + REMARK ("Using %s\n", TBB_USE_CAPTURED_EXCEPTION ? "tbb:captured_exception" : "exact exception propagation"); + MinThread = min(tbb::task_scheduler_init::default_num_threads(), max(2, MinThread)); + MaxThread = max(MinThread, min(tbb::task_scheduler_init::default_num_threads(), MaxThread)); + ASSERT (FLAT_RANGE >= FLAT_GRAIN * MaxThread, "Fix defines"); + int step = max((MaxThread - MinThread + 1)/2, 1); + for ( g_NumThreads = MinThread; g_NumThreads <= MaxThread; g_NumThreads += step ) { + REMARK ("Number of threads %d\n", g_NumThreads); + // Execute in all the possible modes + for ( size_t j = 0; j < 4; ++j ) { + g_ExceptionInMaster = (j & 1) == 1; + g_SolitaryException = (j & 2) == 1; + RunParForAndReduceTests(); + RunParDoTests(); + RunPipelineTests(); + } + } +#if TBB_USE_EXCEPTIONS + TestTbbExceptionAPI(); +#endif +#if __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN + REPORT("Known issue: exception handling tests are skipped.\n"); +#endif + return Harness::Done; +} + +#else /* !__TBB_TASK_GROUP_CONTEXT */ + +int TestMain () { + return Harness::Skipped; +} + +#endif /* !__TBB_TASK_GROUP_CONTEXT */ diff --git a/src/tbb/src/test/test_eh_flow_graph.cpp b/src/tbb/src/test/test_eh_flow_graph.cpp new file mode 100644 index 0000000..7055319 --- /dev/null +++ b/src/tbb/src/test/test_eh_flow_graph.cpp @@ -0,0 +1,113 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "harness.h" + +#if TBB_USE_EXCEPTIONS +#include "tbb/flow_graph.h" +#include "tbb/task_scheduler_init.h" +#include <iostream> +#include <vector> +#include "harness_assert.h" + +tbb::atomic<unsigned> nExceptions; + +class Foo { +private: + // std::vector<int>& m_vec; + std::vector<int>* m_vec; +public: + Foo(std::vector<int>& vec) : m_vec(&vec) { } + void operator() (tbb::flow::continue_msg) const { + ++nExceptions; + m_vec->at(m_vec->size()); // Will throw out_of_range exception + ASSERT(false, "Exception not thrown by invalid access"); + } +}; + +// test from user ahelwer: http://software.intel.com/en-us/forums/showthread.php?t=103786 +// exception thrown in graph node, not caught in wait_for_all() +void +test_flow_graph_exception0() { + // Initializes body + std::vector<int> vec; + vec.push_back(0); + Foo f(vec); + nExceptions = 0; + + // Construct graph and nodes + tbb::flow::graph g; + tbb::flow::broadcast_node<tbb::flow::continue_msg> start(g); + tbb::flow::continue_node<tbb::flow::continue_msg> fooNode(g, f); + + // Construct edge + tbb::flow::make_edge(start, fooNode); + + // Execute graph + ASSERT(!g.exception_thrown(), "exception_thrown flag already set"); + ASSERT(!g.is_cancelled(), "canceled flag already set"); + try { + start.try_put(tbb::flow::continue_msg()); + g.wait_for_all(); + ASSERT(false, "Exception not thrown"); + } + catch(std::out_of_range& ex) { + REMARK("Exception: %s\n", ex.what()); + } + catch(...) { + REMARK("Unknown exception caught\n"); + } + ASSERT(g.exception_thrown(), "Exception not intercepted"); + // if exception set, cancellation also set. + ASSERT(g.is_cancelled(), "Exception cancellation not signaled"); + // in case we got an exception + try { + g.wait_for_all(); // context still signalled canceled, my_exception still set. + } + catch(...) { + ASSERT(false, "Second exception thrown but no task executing"); + } + ASSERT(!g.exception_thrown(), "exception_thrown flag not reset"); + ASSERT(!g.is_cancelled(), "canceled flag not reset"); +} +#endif // TBB_USE_EXCEPTIONS + +#if TBB_USE_EXCEPTIONS +int TestMain() { + for(int nThread=MinThread; nThread<= MaxThread; ++nThread) { + tbb::task_scheduler_init init(nThread); + test_flow_graph_exception0(); + } + return Harness::Done; +} +#else // !TBB_USE_EXCEPTION +int TestMain() { + return Harness::Skipped; +} +#endif + diff --git a/src/tbb/src/test/test_eh_tasks.cpp b/src/tbb/src/test/test_eh_tasks.cpp new file mode 100644 index 0000000..0a6be12 --- /dev/null +++ b/src/tbb/src/test/test_eh_tasks.cpp @@ -0,0 +1,797 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "harness.h" + +#if __TBB_TASK_GROUP_CONTEXT + +#define __TBB_ATOMICS_CODEGEN_BROKEN __SUNPRO_CC + +#define private public +#include "tbb/task.h" +#undef private + +#include "tbb/task_scheduler_init.h" +#include "tbb/spin_mutex.h" +#include "tbb/tick_count.h" + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include <string> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +#define NUM_CHILD_TASKS 256 +#define NUM_ROOT_TASKS 32 +#define NUM_ROOTS_IN_GROUP 8 + +//! Statistics about number of tasks in different states +class TaskStats { + typedef tbb::spin_mutex::scoped_lock lock_t; + //! Number of tasks allocated that was ever allocated + volatile intptr_t m_Existed; + //! Number of tasks executed to the moment + volatile intptr_t m_Executed; + //! Number of tasks allocated but not yet destroyed to the moment + volatile intptr_t m_Existing; + + mutable tbb::spin_mutex m_Mutex; +public: + //! Assumes that assignment is noncontended for the left-hand operand + const TaskStats& operator= ( const TaskStats& rhs ) { + if ( this != &rhs ) { + lock_t lock(rhs.m_Mutex); + m_Existed = rhs.m_Existed; + m_Executed = rhs.m_Executed; + m_Existing = rhs.m_Existing; + } + return *this; + } + intptr_t Existed() const { return m_Existed; } + intptr_t Executed() const { return m_Executed; } + intptr_t Existing() const { return m_Existing; } + void IncExisted() { lock_t lock(m_Mutex); ++m_Existed; ++m_Existing; } + void IncExecuted() { lock_t lock(m_Mutex); ++m_Executed; } + void DecExisting() { lock_t lock(m_Mutex); --m_Existing; } + //! Assumed to be used in uncontended manner only + void Reset() { m_Executed = m_Existing = m_Existed = 0; } +}; + +TaskStats g_CurStat; + +inline intptr_t Existed () { return g_CurStat.Existed(); } + +#include "harness_eh.h" + +bool g_BoostExecutedCount = true; +volatile bool g_TaskWasCancelled = false; + +inline void ResetGlobals () { + ResetEhGlobals(); + g_BoostExecutedCount = true; + g_TaskWasCancelled = false; + g_CurStat.Reset(); +} + +#define ASSERT_TEST_POSTCOND() \ + ASSERT (g_CurStat.Existed() >= g_CurStat.Executed(), "Total number of tasks is less than executed"); \ + ASSERT (!g_CurStat.Existing(), "Not all task objects have been destroyed"); \ + ASSERT (!tbb::task::self().is_cancelled(), "Scheduler's default context has not been cleaned up properly"); + +inline void WaitForException () { + int n = 0; + while ( ++n < c_Timeout && !__TBB_load_with_acquire(g_ExceptionCaught) ) + __TBB_Yield(); + ASSERT_WARNING( n < c_Timeout, "WaitForException failed" ); +} + +class TaskBase : public tbb::task { + tbb::task* execute () { + tbb::task* t = NULL; + __TBB_TRY { + t = do_execute(); + } __TBB_CATCH( ... ) { + g_CurStat.IncExecuted(); + __TBB_RETHROW(); + } + g_CurStat.IncExecuted(); + return t; + } +protected: + TaskBase ( bool throwException = true ) : m_Throw(throwException) { g_CurStat.IncExisted(); } + ~TaskBase () { g_CurStat.DecExisting(); } + + virtual tbb::task* do_execute () = 0; + + bool m_Throw; +}; // class TaskBase + +class LeafTask : public TaskBase { + tbb::task* do_execute () { + Harness::ConcurrencyTracker ct; + WaitUntilConcurrencyPeaks(); + if ( g_BoostExecutedCount ) + ++g_CurExecuted; + if ( m_Throw ) + ThrowTestException(NUM_CHILD_TASKS/2); + if ( !g_ThrowException ) + __TBB_Yield(); + return NULL; + } +public: + LeafTask ( bool throw_exception = true ) : TaskBase(throw_exception) {} +}; + +class SimpleRootTask : public TaskBase { + tbb::task* do_execute () { + set_ref_count(NUM_CHILD_TASKS + 1); + for ( size_t i = 0; i < NUM_CHILD_TASKS; ++i ) + spawn( *new( allocate_child() ) LeafTask(m_Throw) ); + wait_for_all(); + return NULL; + } +public: + SimpleRootTask ( bool throw_exception = true ) : TaskBase(throw_exception) {} +}; + +#if TBB_USE_EXCEPTIONS + +class SimpleThrowingTask : public tbb::task { +public: + tbb::task* execute () { throw 0; } + ~SimpleThrowingTask() {} +}; + +//! Checks if innermost running task information is updated correctly during cancellation processing +void Test0 () { + tbb::task_scheduler_init init (1); + tbb::empty_task &r = *new( tbb::task::allocate_root() ) tbb::empty_task; + tbb::task_list tl; + tl.push_back( *new( r.allocate_child() ) SimpleThrowingTask ); + tl.push_back( *new( r.allocate_child() ) SimpleThrowingTask ); + r.set_ref_count( 3 ); + try { + r.spawn_and_wait_for_all( tl ); + } + catch (...) {} + r.destroy( r ); +} + +//! Default exception behavior test. +/** Allocates a root task that spawns a bunch of children, one or several of which throw + a test exception in a worker or master thread (depending on the global setting). **/ +void Test1 () { + ResetGlobals(); + tbb::empty_task &r = *new( tbb::task::allocate_root() ) tbb::empty_task; + ASSERT (!g_CurStat.Existing() && !g_CurStat.Existed() && !g_CurStat.Executed(), + "something wrong with the task accounting"); + r.set_ref_count(NUM_CHILD_TASKS + 1); + for ( int i = 0; i < NUM_CHILD_TASKS; ++i ) + r.spawn( *new( r.allocate_child() ) LeafTask ); + TRY(); + r.wait_for_all(); + CATCH_AND_ASSERT(); + r.destroy(r); + ASSERT_TEST_POSTCOND(); +} // void Test1 () + +//! Default exception behavior test. +/** Allocates and spawns root task that runs a bunch of children, one of which throws + a test exception in a worker thread. (Similar to Test1, except that the root task + is spawned by the test function, and children are created by the root task instead + of the test function body.) **/ +void Test2 () { + ResetGlobals(); + SimpleRootTask &r = *new( tbb::task::allocate_root() ) SimpleRootTask; + ASSERT (g_CurStat.Existing() == 1 && g_CurStat.Existed() == 1 && !g_CurStat.Executed(), + "something wrong with the task accounting"); + TRY(); + tbb::task::spawn_root_and_wait(r); + CATCH_AND_ASSERT(); + ASSERT (g_ExceptionCaught, "no exception occurred"); + ASSERT_TEST_POSTCOND(); +} // void Test2 () + +//! The same as Test2() except the root task has explicit context. +/** The context is initialized as bound in order to check correctness of its associating + with a root task. **/ +void Test3 () { + ResetGlobals(); + tbb::task_group_context ctx(tbb::task_group_context::bound); + SimpleRootTask &r = *new( tbb::task::allocate_root(ctx) ) SimpleRootTask; + ASSERT (g_CurStat.Existing() == 1 && g_CurStat.Existed() == 1 && !g_CurStat.Executed(), + "something wrong with the task accounting"); + TRY(); + tbb::task::spawn_root_and_wait(r); + CATCH_AND_ASSERT(); + ASSERT (g_ExceptionCaught, "no exception occurred"); + ASSERT_TEST_POSTCOND(); +} // void Test2 () + +class RootLauncherTask : public TaskBase { + tbb::task_group_context::kind_type m_CtxKind; + + tbb::task* do_execute () { + tbb::task_group_context ctx(m_CtxKind); + SimpleRootTask &r = *new( allocate_root() ) SimpleRootTask; + r.change_group(ctx); + TRY(); + spawn_root_and_wait(r); + // Give a child of our siblings a chance to throw the test exception + WaitForException(); + CATCH(); + ASSERT (__TBB_EXCEPTION_TYPE_INFO_BROKEN || !g_UnknownException, "unknown exception was caught"); + return NULL; + } +public: + RootLauncherTask ( tbb::task_group_context::kind_type ctx_kind = tbb::task_group_context::isolated ) : m_CtxKind(ctx_kind) {} +}; + +/** Allocates and spawns a bunch of roots, which allocate and spawn new root with + isolated context, which at last spawns a bunch of children each, one of which + throws a test exception in a worker thread. **/ +void Test4 () { + ResetGlobals(); + tbb::task_list tl; + for ( size_t i = 0; i < NUM_ROOT_TASKS; ++i ) + tl.push_back( *new( tbb::task::allocate_root() ) RootLauncherTask ); + TRY(); + tbb::task::spawn_root_and_wait(tl); + CATCH_AND_ASSERT(); + ASSERT (!exceptionCaught, "exception in this scope is unexpected"); + intptr_t num_tasks_expected = NUM_ROOT_TASKS * (NUM_CHILD_TASKS + 2); + ASSERT (g_CurStat.Existed() == num_tasks_expected, "Wrong total number of tasks"); + if ( g_SolitaryException ) + ASSERT (g_CurStat.Executed() >= num_tasks_expected - NUM_CHILD_TASKS, "Unexpected number of executed tasks"); + ASSERT_TEST_POSTCOND(); +} // void Test4 () + +/** The same as Test4, except the contexts are bound. **/ +void Test4_1 () { + ResetGlobals(); + tbb::task_list tl; + for ( size_t i = 0; i < NUM_ROOT_TASKS; ++i ) + tl.push_back( *new( tbb::task::allocate_root() ) RootLauncherTask(tbb::task_group_context::bound) ); + TRY(); + tbb::task::spawn_root_and_wait(tl); + CATCH_AND_ASSERT(); + ASSERT (!exceptionCaught, "exception in this scope is unexpected"); + intptr_t num_tasks_expected = NUM_ROOT_TASKS * (NUM_CHILD_TASKS + 2); + ASSERT (g_CurStat.Existed() == num_tasks_expected, "Wrong total number of tasks"); + if ( g_SolitaryException ) + ASSERT (g_CurStat.Executed() >= num_tasks_expected - NUM_CHILD_TASKS, "Unexpected number of executed tasks"); + ASSERT_TEST_POSTCOND(); +} // void Test4_1 () + + +class RootsGroupLauncherTask : public TaskBase { + tbb::task* do_execute () { + tbb::task_group_context ctx (tbb::task_group_context::isolated); + tbb::task_list tl; + for ( size_t i = 0; i < NUM_ROOT_TASKS; ++i ) + tl.push_back( *new( allocate_root(ctx) ) SimpleRootTask ); + TRY(); + spawn_root_and_wait(tl); + // Give worker a chance to throw exception + WaitForException(); + CATCH_AND_ASSERT(); + return NULL; + } +}; + +/** Allocates and spawns a bunch of roots, which allocate and spawn groups of roots + with an isolated context shared by all group members, which at last spawn a bunch + of children each, one of which throws a test exception in a worker thread. **/ +void Test5 () { + ResetGlobals(); + tbb::task_list tl; + for ( size_t i = 0; i < NUM_ROOTS_IN_GROUP; ++i ) + tl.push_back( *new( tbb::task::allocate_root() ) RootsGroupLauncherTask ); + TRY(); + tbb::task::spawn_root_and_wait(tl); + CATCH_AND_ASSERT(); + ASSERT (!exceptionCaught, "unexpected exception intercepted"); + if ( g_SolitaryException ) { + intptr_t num_tasks_expected = NUM_ROOTS_IN_GROUP * (1 + NUM_ROOT_TASKS * (1 + NUM_CHILD_TASKS)); + intptr_t min_num_tasks_executed = num_tasks_expected - NUM_ROOT_TASKS * (NUM_CHILD_TASKS + 1); + ASSERT (g_CurStat.Executed() >= min_num_tasks_executed, "Too few tasks executed"); + } + ASSERT_TEST_POSTCOND(); +} // void Test5 () + +class ThrowingRootLauncherTask : public TaskBase { + tbb::task* do_execute () { + tbb::task_group_context ctx (tbb::task_group_context::bound); + SimpleRootTask &r = *new( allocate_root(ctx) ) SimpleRootTask(false); + TRY(); + spawn_root_and_wait(r); + CATCH(); + ASSERT (!exceptionCaught, "unexpected exception intercepted"); + ThrowTestException(NUM_CHILD_TASKS); + g_TaskWasCancelled |= is_cancelled(); + return NULL; + } +}; + +class BoundHierarchyLauncherTask : public TaskBase { + bool m_Recover; + + void alloc_roots ( tbb::task_group_context& ctx, tbb::task_list& tl ) { + for ( size_t i = 0; i < NUM_ROOT_TASKS; ++i ) + tl.push_back( *new( allocate_root(ctx) ) ThrowingRootLauncherTask ); + } + + tbb::task* do_execute () { + tbb::task_group_context ctx (tbb::task_group_context::isolated); + tbb::task_list tl; + alloc_roots(ctx, tl); + TRY(); + spawn_root_and_wait(tl); + CATCH_AND_ASSERT(); + ASSERT (exceptionCaught, "no exception occurred"); + ASSERT (!tl.empty(), "task list was cleared somehow"); + if ( g_SolitaryException ) + ASSERT (g_TaskWasCancelled, "No tasks were cancelled despite of exception"); + if ( m_Recover ) { + // Test task_group_context::unbind and task_group_context::reset methods + g_ThrowException = false; + exceptionCaught = false; + tl.clear(); + alloc_roots(ctx, tl); + ctx.reset(); + try { + spawn_root_and_wait(tl); + } + catch (...) { + exceptionCaught = true; + } + ASSERT (!exceptionCaught, "unexpected exception occurred"); + } + return NULL; + } +public: + BoundHierarchyLauncherTask ( bool recover = false ) : m_Recover(recover) {} + +}; // class BoundHierarchyLauncherTask + +//! Test for bound contexts forming 2 level tree. Exception is thrown on the 1st (root) level. +/** Allocates and spawns a root that spawns a bunch of 2nd level roots sharing + the same isolated context, each of which in their turn spawns a single 3rd level + root with the bound context, and these 3rd level roots spawn bunches of leaves + in the end. Leaves do not generate exceptions. The test exception is generated + by one of the 2nd level roots. **/ +void Test6 () { + ResetGlobals(); + BoundHierarchyLauncherTask &r = *new( tbb::task::allocate_root() ) BoundHierarchyLauncherTask; + TRY(); + tbb::task::spawn_root_and_wait(r); + CATCH_AND_ASSERT(); + ASSERT (!exceptionCaught, "unexpected exception intercepted"); + // After the first of the branches (ThrowingRootLauncherTask) completes, + // the rest of the task tree may be collapsed before having a chance to execute leaves. + // A number of branches running concurrently with the first one will be able to spawn leaves though. + /// \todo: If additional checkpoints are added to scheduler the following assertion must weaken + intptr_t num_tasks_expected = 1 + NUM_ROOT_TASKS * (2 + NUM_CHILD_TASKS); + intptr_t min_num_tasks_created = 1 + g_NumThreads * 2 + NUM_CHILD_TASKS; + // 2 stands for BoundHierarchyLauncherTask and SimpleRootTask + // 1 corresponds to BoundHierarchyLauncherTask + intptr_t min_num_tasks_executed = 2 + 1 + NUM_CHILD_TASKS; + ASSERT (g_CurStat.Existed() <= num_tasks_expected, "Number of expected tasks is calculated incorrectly"); + ASSERT (g_CurStat.Existed() >= min_num_tasks_created, "Too few tasks created"); + ASSERT (g_CurStat.Executed() >= min_num_tasks_executed, "Too few tasks executed"); + ASSERT_TEST_POSTCOND(); +} // void Test6 () + +//! Tests task_group_context::unbind and task_group_context::reset methods. +/** Allocates and spawns a root that spawns a bunch of 2nd level roots sharing + the same isolated context, each of which in their turn spawns a single 3rd level + root with the bound context, and these 3rd level roots spawn bunches of leaves + in the end. Leaves do not generate exceptions. The test exception is generated + by one of the 2nd level roots. **/ +void Test7 () { + ResetGlobals(); + BoundHierarchyLauncherTask &r = *new( tbb::task::allocate_root() ) BoundHierarchyLauncherTask; + TRY(); + tbb::task::spawn_root_and_wait(r); + CATCH_AND_ASSERT(); + ASSERT (!exceptionCaught, "unexpected exception intercepted"); + ASSERT_TEST_POSTCOND(); +} // void Test6 () + +class BoundHierarchyLauncherTask2 : public TaskBase { + tbb::task* do_execute () { + tbb::task_group_context ctx; + tbb::task_list tl; + for ( size_t i = 0; i < NUM_ROOT_TASKS; ++i ) + tl.push_back( *new( allocate_root(ctx) ) RootLauncherTask(tbb::task_group_context::bound) ); + TRY(); + spawn_root_and_wait(tl); + CATCH_AND_ASSERT(); + // Exception must be intercepted by RootLauncherTask + ASSERT (!exceptionCaught, "no exception occurred"); + return NULL; + } +}; // class BoundHierarchyLauncherTask2 + +//! Test for bound contexts forming 2 level tree. Exception is thrown in the 2nd (outer) level. +/** Allocates and spawns a root that spawns a bunch of 2nd level roots sharing + the same isolated context, each of which in their turn spawns a single 3rd level + root with the bound context, and these 3rd level roots spawn bunches of leaves + in the end. The test exception is generated by one of the leaves. **/ +void Test8 () { + ResetGlobals(); + BoundHierarchyLauncherTask2 &r = *new( tbb::task::allocate_root() ) BoundHierarchyLauncherTask2; + TRY(); + tbb::task::spawn_root_and_wait(r); + CATCH_AND_ASSERT(); + ASSERT (!exceptionCaught, "unexpected exception intercepted"); + if ( g_SolitaryException ) { + intptr_t num_tasks_expected = 1 + NUM_ROOT_TASKS * (2 + NUM_CHILD_TASKS); + intptr_t min_num_tasks_created = 1 + g_NumThreads * (2 + NUM_CHILD_TASKS); + intptr_t min_num_tasks_executed = num_tasks_expected - (NUM_CHILD_TASKS + 1); + ASSERT (g_CurStat.Existed() <= num_tasks_expected, "Number of expected tasks is calculated incorrectly"); + ASSERT (g_CurStat.Existed() >= min_num_tasks_created, "Too few tasks created"); + ASSERT (g_CurStat.Executed() >= min_num_tasks_executed, "Too few tasks executed"); + } + ASSERT_TEST_POSTCOND(); +} // void Test8 () + +template<typename T> +void ThrowMovableException ( intptr_t threshold, const T& data ) { + if ( !IsThrowingThread() ) + return; + if ( !g_SolitaryException ) { +#if __TBB_ATOMICS_CODEGEN_BROKEN + g_ExceptionsThrown = g_ExceptionsThrown + 1; +#else + ++g_ExceptionsThrown; +#endif + throw tbb::movable_exception<T>(data); + } + while ( g_CurStat.Existed() < threshold ) + __TBB_Yield(); + if ( g_ExceptionsThrown.compare_and_swap(1, 0) == 0 ) + throw tbb::movable_exception<T>(data); +} + +const int g_IntExceptionData = -375; +const std::string g_StringExceptionData = "My test string"; + +// Exception data class implementing minimal requirements of tbb::movable_exception +class ExceptionData { + const ExceptionData& operator = ( const ExceptionData& src ); + explicit ExceptionData ( int n ) : m_Int(n), m_String(g_StringExceptionData) {} +public: + ExceptionData ( const ExceptionData& src ) : m_Int(src.m_Int), m_String(src.m_String) {} + ~ExceptionData () {} + + int m_Int; + std::string m_String; + + // Simple way to provide an instance when all initializing constructors are private + // and to avoid memory reclamation problems. + static ExceptionData s_data; +}; + +ExceptionData ExceptionData::s_data(g_IntExceptionData); + +typedef tbb::movable_exception<int> SolitaryMovableException; +typedef tbb::movable_exception<ExceptionData> MultipleMovableException; + +class LeafTaskWithMovableExceptions : public TaskBase { + bool m_IntAsData; + + tbb::task* do_execute () { + Harness::ConcurrencyTracker ct; + WaitUntilConcurrencyPeaks(); + if ( g_SolitaryException ) + ThrowMovableException<int>(NUM_CHILD_TASKS/2, g_IntExceptionData); + else + ThrowMovableException<ExceptionData>(NUM_CHILD_TASKS/2, ExceptionData::s_data); + return NULL; + } +}; + +void CheckException ( tbb::tbb_exception& e ) { + ASSERT (strcmp(e.name(), (g_SolitaryException ? typeid(SolitaryMovableException) + : typeid(MultipleMovableException)).name() ) == 0, + "Unexpected original exception name"); + ASSERT (strcmp(e.what(), "tbb::movable_exception") == 0, "Unexpected original exception info "); + if ( g_SolitaryException ) { + SolitaryMovableException& me = dynamic_cast<SolitaryMovableException&>(e); + ASSERT (me.data() == g_IntExceptionData, "Unexpected solitary movable_exception data"); + } + else { + MultipleMovableException& me = dynamic_cast<MultipleMovableException&>(e); + ASSERT (me.data().m_Int == g_IntExceptionData, "Unexpected multiple movable_exception int data"); + ASSERT (me.data().m_String == g_StringExceptionData, "Unexpected multiple movable_exception string data"); + } +} + +void CheckException () { + try { + throw; + } catch ( tbb::tbb_exception& e ) { + CheckException(e); + } + catch ( ... ) { + } +} + +//! Test for movable_exception behavior, and external exception recording. +/** Allocates a root task that spawns a bunch of children, one or several of which throw + a movable exception in a worker or master thread (depending on the global settings). + The test also checks the correctness of multiple rethrowing of the pending exception. **/ +void TestMovableException () { + REMARK( "TestMovableException\n" ); + ResetGlobals(); + bool bUnsupported = false; + tbb::task_group_context ctx; + tbb::empty_task *r = new( tbb::task::allocate_root() ) tbb::empty_task; + ASSERT (!g_CurStat.Existing() && !g_CurStat.Existed() && !g_CurStat.Executed(), + "something wrong with the task accounting"); + r->set_ref_count(NUM_CHILD_TASKS + 1); + for ( int i = 0; i < NUM_CHILD_TASKS; ++i ) + r->spawn( *new( r->allocate_child() ) LeafTaskWithMovableExceptions ); + TRY() + r->wait_for_all(); + } catch ( ... ) { + ASSERT (!ctx.is_group_execution_cancelled(), ""); + CheckException(); + try { + throw; + } catch ( tbb::tbb_exception& e ) { + CheckException(e); + g_ExceptionCaught = exceptionCaught = true; + } + catch ( ... ) { + g_ExceptionCaught = true; + g_UnknownException = unknownException = true; + } + try { + ctx.register_pending_exception(); + } catch ( ... ) { + bUnsupported = true; + REPORT( "Warning: register_pending_exception() failed. This is expected in case of linking with static msvcrt\n" ); + } + ASSERT (ctx.is_group_execution_cancelled() || bUnsupported, "After exception registration the context must be in the cancelled state"); + } + r->destroy(*r); + ASSERT_EXCEPTION(); + ASSERT_TEST_POSTCOND(); + + r = new( tbb::task::allocate_root(ctx) ) tbb::empty_task; + r->set_ref_count(1); + g_ExceptionCaught = g_UnknownException = false; + try { + r->wait_for_all(); + } catch ( tbb::tbb_exception& e ) { + CheckException(e); + g_ExceptionCaught = true; + } + catch ( ... ) { + g_ExceptionCaught = true; + g_UnknownException = true; + } + ASSERT (g_ExceptionCaught || bUnsupported, "no exception occurred"); + ASSERT (__TBB_EXCEPTION_TYPE_INFO_BROKEN || !g_UnknownException || bUnsupported, "unknown exception was caught"); + r->destroy(*r); +} // void Test10 () + +#endif /* TBB_USE_EXCEPTIONS */ + +template<class T> +class CtxLauncherTask : public tbb::task { + tbb::task_group_context &m_Ctx; + + tbb::task* execute () { + spawn_root_and_wait( *new( allocate_root(m_Ctx) ) T ); + return NULL; + } +public: + CtxLauncherTask ( tbb::task_group_context& ctx ) : m_Ctx(ctx) {} +}; + +//! Test for cancelling a task hierarchy from outside (from a task running in parallel with it). +void TestCancelation () { + ResetGlobals(); + g_ThrowException = false; + tbb::task_group_context ctx; + tbb::task_list tl; + tl.push_back( *new( tbb::task::allocate_root() ) CtxLauncherTask<SimpleRootTask>(ctx) ); + tl.push_back( *new( tbb::task::allocate_root() ) CancellatorTask(ctx, NUM_CHILD_TASKS / 4) ); + TRY(); + tbb::task::spawn_root_and_wait(tl); + CATCH_AND_FAIL(); + ASSERT (g_CurStat.Executed() <= g_ExecutedAtCatch + g_NumThreads, "Too many tasks were executed after cancellation"); + ASSERT_TEST_POSTCOND(); +} // void Test9 () + +class CtxDestroyerTask : public tbb::task { + int m_nestingLevel; + + tbb::task* execute () { + ASSERT ( m_nestingLevel >= 0 && m_nestingLevel < MaxNestingDepth, "Wrong nesting level. The test is broken" ); + tbb::task_group_context ctx; + tbb::task *t = new( allocate_root(ctx) ) tbb::empty_task; + int level = ++m_nestingLevel; + if ( level < MaxNestingDepth ) { + execute(); + } + else { + if ( !CancellatorTask::WaitUntilReady() ) + REPORT( "Warning: missing wakeup\n" ); + ++g_CurExecuted; + } + if ( ctx.is_group_execution_cancelled() ) + ++s_numCancelled; + t->destroy(*t); + return NULL; + } +public: + CtxDestroyerTask () : m_nestingLevel(0) { s_numCancelled = 0; } + + static const int MaxNestingDepth = 256; + static int s_numCancelled; +}; + +int CtxDestroyerTask::s_numCancelled = 0; + +//! Test for data race between cancellation propagation and context destruction. +/** If the data race ever occurs, an assertion inside TBB will be triggered. **/ +void TestCtxDestruction () { + REMARK( "TestCtxDestruction\n" ); + for ( size_t i = 0; i < 10; ++i ) { + tbb::task_group_context ctx; + tbb::task_list tl; + ResetGlobals(); + g_BoostExecutedCount = false; + g_ThrowException = false; + CancellatorTask::Reset(); + + tl.push_back( *new( tbb::task::allocate_root() ) CtxLauncherTask<CtxDestroyerTask>(ctx) ); + tl.push_back( *new( tbb::task::allocate_root() ) CancellatorTask(ctx, 1) ); + tbb::task::spawn_root_and_wait(tl); + ASSERT( g_CurExecuted == 1, "Test is broken" ); + ASSERT( CtxDestroyerTask::s_numCancelled <= CtxDestroyerTask::MaxNestingDepth, "Test is broken" ); + } +} // void TestCtxDestruction() + +#include <algorithm> +#include "harness_barrier.h" + +class CtxConcurrentDestroyer : NoAssign, Harness::NoAfterlife { + static const int ContextsPerThread = 512; + + static int s_Concurrency; + static int s_NumContexts; + static tbb::task_group_context** s_Contexts; + static char* s_Buffer; + static Harness::SpinBarrier s_Barrier; + static Harness::SpinBarrier s_ExitBarrier; + + struct Shuffler { + void operator() () const { std::random_shuffle(s_Contexts, s_Contexts + s_NumContexts); } + }; +public: + static void Init ( int p ) { + s_Concurrency = p; + s_NumContexts = p * ContextsPerThread; + s_Contexts = new tbb::task_group_context*[s_NumContexts]; + s_Buffer = new char[s_NumContexts * sizeof(tbb::task_group_context)]; + s_Barrier.initialize( p ); + s_ExitBarrier.initialize( p ); + } + static void Uninit () { + for ( int i = 0; i < s_NumContexts; ++i ) { + tbb::internal::context_list_node_t &node = s_Contexts[i]->my_node; + ASSERT( !node.my_next && !node.my_prev, "Destroyed context was written to during context chain update" ); + } + delete []s_Contexts; + delete []s_Buffer; + } + + void operator() ( int id ) const { + int begin = ContextsPerThread * id, + end = begin + ContextsPerThread; + for ( int i = begin; i < end; ++i ) + s_Contexts[i] = new( s_Buffer + i * sizeof(tbb::task_group_context) ) tbb::task_group_context; + s_Barrier.wait( Shuffler() ); + for ( int i = begin; i < end; ++i ) { + s_Contexts[i]->tbb::task_group_context::~task_group_context(); + memset( s_Contexts[i], 0, sizeof(tbb::task_group_context) ); + } + s_ExitBarrier.wait(); + } +}; // class CtxConcurrentDestroyer + +int CtxConcurrentDestroyer::s_Concurrency; +int CtxConcurrentDestroyer::s_NumContexts; +tbb::task_group_context** CtxConcurrentDestroyer::s_Contexts; +char* CtxConcurrentDestroyer::s_Buffer; +Harness::SpinBarrier CtxConcurrentDestroyer::s_Barrier; +Harness::SpinBarrier CtxConcurrentDestroyer::s_ExitBarrier; + +void TestConcurrentCtxDestruction () { + REMARK( "TestConcurrentCtxDestruction\n" ); + CtxConcurrentDestroyer::Init(g_NumThreads); + NativeParallelFor( g_NumThreads, CtxConcurrentDestroyer() ); + CtxConcurrentDestroyer::Uninit(); +} + +void RunTests () { + REMARK ("Number of threads %d\n", g_NumThreads); + tbb::task_scheduler_init init (g_NumThreads); + g_Master = Harness::CurrentTid(); +#if TBB_USE_EXCEPTIONS + Test1(); + Test2(); + Test3(); + Test4(); + Test4_1(); + Test5(); + Test6(); + Test7(); + Test8(); + TestMovableException(); +#endif /* TBB_USE_EXCEPTIONS */ + TestCancelation(); + TestCtxDestruction(); +#if !RML_USE_WCRM + TestConcurrentCtxDestruction(); +#endif +} + +int TestMain () { + REMARK ("Using %s\n", TBB_USE_CAPTURED_EXCEPTION ? "tbb:captured_exception" : "exact exception propagation"); + MinThread = min(NUM_ROOTS_IN_GROUP, min(tbb::task_scheduler_init::default_num_threads(), max(2, MinThread))); + MaxThread = min(NUM_ROOTS_IN_GROUP, max(MinThread, min(tbb::task_scheduler_init::default_num_threads(), MaxThread))); + ASSERT (NUM_ROOTS_IN_GROUP < NUM_ROOT_TASKS, "Fix defines"); +#if TBB_USE_EXCEPTIONS + // Test0 always runs on one thread + Test0(); +#endif /* TBB_USE_EXCEPTIONS */ + g_SolitaryException = 0; + for ( g_NumThreads = MinThread; g_NumThreads <= MaxThread; ++g_NumThreads ) + RunTests(); + return Harness::Done; +} + +#else /* !__TBB_TASK_GROUP_CONTEXT */ + +int TestMain () { + return Harness::Skipped; +} + +#endif /* !__TBB_TASK_GROUP_CONTEXT */ diff --git a/src/tbb/src/test/test_enumerable_thread_specific.cpp b/src/tbb/src/test/test_enumerable_thread_specific.cpp new file mode 100644 index 0000000..6ae5a00 --- /dev/null +++ b/src/tbb/src/test/test_enumerable_thread_specific.cpp @@ -0,0 +1,1022 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/enumerable_thread_specific.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/parallel_for.h" +#include "tbb/parallel_reduce.h" +#include "tbb/blocked_range.h" +#include "tbb/tick_count.h" +#include "tbb/tbb_allocator.h" +#include "tbb/tbb_thread.h" +#include "tbb/atomic.h" + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include <cstring> +#include <vector> +#include <deque> +#include <list> +#include <map> +#include <utility> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +#include "harness_assert.h" +#include "harness.h" + +#if __TBB_GCC_WARNING_SUPPRESSION_PRESENT +#pragma GCC diagnostic ignored "-Wuninitialized" +#endif + +static tbb::atomic<int> construction_counter; +static tbb::atomic<int> destruction_counter; + +const int REPETITIONS = 10; +const int N = 100000; +const int VALID_NUMBER_OF_KEYS = 100; +const double EXPECTED_SUM = (REPETITIONS + 1) * N; + +//! A minimal class that occupies N bytes. +/** Defines default and copy constructor, and allows implicit operator&. + Hides operator=. */ +template<size_t N=tbb::internal::NFS_MaxLineSize> +class minimal: NoAssign { +private: + int my_value; + bool is_constructed; + char pad[N-sizeof(int) - sizeof(bool)]; +public: + minimal() : NoAssign(), my_value(0) { ++construction_counter; is_constructed = true; } + minimal( const minimal &m ) : NoAssign(), my_value(m.my_value) { ++construction_counter; is_constructed = true; } + ~minimal() { ++destruction_counter; ASSERT(is_constructed, NULL); is_constructed = false; } + void set_value( const int i ) { ASSERT(is_constructed, NULL); my_value = i; } + int value( ) const { ASSERT(is_constructed, NULL); return my_value; } +}; + +// +// A helper class that simplifies writing the tests since minimal does not +// define = or + operators. +// + +template< typename T > +struct test_helper { + static inline void init(T &e) { e = static_cast<T>(0); } + static inline void sum(T &e, const int addend ) { e += static_cast<T>(addend); } + static inline void sum(T &e, const double addend ) { e += static_cast<T>(addend); } + static inline void set(T &e, const int value ) { e = static_cast<T>(value); } + static inline double get(const T &e ) { return static_cast<double>(e); } +}; + +template<size_t N> +struct test_helper<minimal<N> > { + static inline void init(minimal<N> &sum) { sum.set_value( 0 ); } + static inline void sum(minimal<N> &sum, const int addend ) { sum.set_value( sum.value() + addend); } + static inline void sum(minimal<N> &sum, const double addend ) { sum.set_value( sum.value() + static_cast<int>(addend)); } + static inline void sum(minimal<N> &sum, const minimal<N> &addend ) { sum.set_value( sum.value() + addend.value()); } + static inline void set(minimal<N> &v, const int value ) { v.set_value( static_cast<int>(value) ); } + static inline double get(const minimal<N> &sum ) { return static_cast<double>(sum.value()); } +}; + +//! Tag class used to make certain constructors hard to invoke accidentally. +struct SecretTagType {} SecretTag; + +//// functors and routines for initialization and combine + +// Addition + +template <typename T> +struct FunctorAddCombineRef { + T operator()(const T& left, const T& right) const { + return left+right; + } +}; + +template <size_t N> +struct FunctorAddCombineRef<minimal<N> > { + minimal<N> operator()(const minimal<N>& left, const minimal<N>& right) const { + minimal<N> result; + result.set_value( left.value() + right.value() ); + return result; + } +}; + +//! Counts instances of FunctorFinit +static tbb::atomic<int> FinitCounter; + +template <typename T, int Value> +struct FunctorFinit { + FunctorFinit( const FunctorFinit& ) {++FinitCounter;} + FunctorFinit( SecretTagType ) {++FinitCounter;} + ~FunctorFinit() {--FinitCounter;} + T operator()() { return Value; } +}; + +template <size_t N, int Value> +struct FunctorFinit<minimal<N>,Value> { + FunctorFinit( const FunctorFinit& ) {++FinitCounter;} + FunctorFinit( SecretTagType ) {++FinitCounter;} + ~FunctorFinit() {--FinitCounter;} + minimal<N> operator()() { + minimal<N> result; + result.set_value( Value ); + return result; + } +}; + +template <typename T> +struct FunctorAddCombine { + T operator()(T left, T right ) const { + return FunctorAddCombineRef<T>()( left, right ); + } +}; + +template <typename T> +T my_combine_ref( const T &left, const T &right) { + return FunctorAddCombineRef<T>()( left, right ); +} + +template <typename T> +T my_combine( T left, T right) { return my_combine_ref(left,right); } + +template <typename T> +class combine_one_helper { +public: + combine_one_helper(T& _result) : my_result(_result) {} + void operator()(const T& new_bit) { test_helper<T>::sum(my_result, new_bit); } + combine_one_helper& operator=(const combine_one_helper& other) { + test_helper<T>::set(my_result, test_helper<T>::get(other)); + return *this; + } +private: + T& my_result; +}; + +//// end functors and routines + +template< typename T > +void run_serial_scalar_tests(const char *test_name) { + tbb::tick_count t0; + T sum; + test_helper<T>::init(sum); + + REMARK("Testing serial %s... ", test_name); + for (int t = -1; t < REPETITIONS; ++t) { + if (Verbose && t == 0) t0 = tbb::tick_count::now(); + for (int i = 0; i < N; ++i) { + test_helper<T>::sum(sum,1); + } + } + + double result_value = test_helper<T>::get(sum); + ASSERT( EXPECTED_SUM == result_value, NULL); + REMARK("done\nserial %s, 0, %g, %g\n", test_name, result_value, ( tbb::tick_count::now() - t0).seconds()); +} + + +template <typename T> +class parallel_scalar_body: NoAssign { + + tbb::enumerable_thread_specific<T> &sums; + +public: + + parallel_scalar_body ( tbb::enumerable_thread_specific<T> &_sums ) : sums(_sums) { } + + void operator()( const tbb::blocked_range<int> &r ) const { + for (int i = r.begin(); i != r.end(); ++i) + test_helper<T>::sum( sums.local(), 1 ); + } + +}; + +template< typename T > +void run_parallel_scalar_tests_nocombine(const char *test_name) { + + typedef tbb::enumerable_thread_specific<T> ets_type; + + // We assume that static_sums zero-initialized or has a default constructor that zeros it. + static ets_type static_sums = ets_type( T() ); + + T exemplar; + test_helper<T>::init(exemplar); + T exemplar23; + test_helper<T>::set(exemplar23,23); + + for (int p = MinThread; p <= MaxThread; ++p) { + REMARK("Testing parallel %s on %d thread(s)... ", test_name, p); + tbb::task_scheduler_init init(p); + tbb::tick_count t0; + + T iterator_sum; + test_helper<T>::init(iterator_sum); + + T finit_ets_sum; + test_helper<T>::init(finit_ets_sum); + + T const_iterator_sum; + test_helper<T>::init(const_iterator_sum); + + T range_sum; + test_helper<T>::init(range_sum); + + T const_range_sum; + test_helper<T>::init(const_range_sum); + + T cconst_sum; + test_helper<T>::init(cconst_sum); + + T assign_sum; + test_helper<T>::init(assign_sum); + + T cassgn_sum; + test_helper<T>::init(cassgn_sum); + T non_cassgn_sum; + test_helper<T>::init(non_cassgn_sum); + + T static_sum; + test_helper<T>::init(static_sum); + + for (int t = -1; t < REPETITIONS; ++t) { + if (Verbose && t == 0) t0 = tbb::tick_count::now(); + + static_sums.clear(); + + ets_type sums(exemplar); + FunctorFinit<T,0> my_finit(SecretTag); + ets_type finit_ets(my_finit); + + ASSERT( sums.empty(), NULL); + tbb::parallel_for( tbb::blocked_range<int>( 0, N, 10000 ), parallel_scalar_body<T>( sums ) ); + ASSERT( !sums.empty(), NULL); + + ASSERT( finit_ets.empty(), NULL); + tbb::parallel_for( tbb::blocked_range<int>( 0, N, 10000 ), parallel_scalar_body<T>( finit_ets ) ); + ASSERT( !finit_ets.empty(), NULL); + + ASSERT(static_sums.empty(), NULL); + tbb::parallel_for( tbb::blocked_range<int>( 0, N, 10000 ), parallel_scalar_body<T>( static_sums ) ); + ASSERT( !static_sums.empty(), NULL); + + // use iterator + typename ets_type::size_type size = 0; + for ( typename ets_type::iterator i = sums.begin(); i != sums.end(); ++i ) { + ++size; + test_helper<T>::sum(iterator_sum, *i); + } + ASSERT( sums.size() == size, NULL); + + // use const_iterator + for ( typename ets_type::const_iterator i = sums.begin(); i != sums.end(); ++i ) { + test_helper<T>::sum(const_iterator_sum, *i); + } + + // use range_type + typename ets_type::range_type r = sums.range(); + for ( typename ets_type::range_type::const_iterator i = r.begin(); i != r.end(); ++i ) { + test_helper<T>::sum(range_sum, *i); + } + + // use const_range_type + typename ets_type::const_range_type cr = sums.range(); + for ( typename ets_type::const_range_type::iterator i = cr.begin(); i != cr.end(); ++i ) { + test_helper<T>::sum(const_range_sum, *i); + } + + // test copy constructor, with TLS-cached locals + typedef typename tbb::enumerable_thread_specific<T, tbb::cache_aligned_allocator<T>, tbb::ets_key_per_instance> cached_ets_type; + + cached_ets_type cconst(sums); + + for ( typename cached_ets_type::const_iterator i = cconst.begin(); i != cconst.end(); ++i ) { + test_helper<T>::sum(cconst_sum, *i); + } + + // test assignment + ets_type assigned; + assigned = sums; + + for ( typename ets_type::const_iterator i = assigned.begin(); i != assigned.end(); ++i ) { + test_helper<T>::sum(assign_sum, *i); + } + + // test assign to and from cached locals + cached_ets_type cassgn; + cassgn = sums; + for ( typename cached_ets_type::const_iterator i = cassgn.begin(); i != cassgn.end(); ++i ) { + test_helper<T>::sum(cassgn_sum, *i); + } + + ets_type non_cassgn; + non_cassgn = cassgn; + for ( typename ets_type::const_iterator i = non_cassgn.begin(); i != non_cassgn.end(); ++i ) { + test_helper<T>::sum(non_cassgn_sum, *i); + } + + // test finit-initialized ets + for(typename ets_type::const_iterator i = finit_ets.begin(); i != finit_ets.end(); ++i) { + test_helper<T>::sum(finit_ets_sum, *i); + } + + // test static ets + for(typename ets_type::const_iterator i = static_sums.begin(); i != static_sums.end(); ++i) { + test_helper<T>::sum(static_sum, *i); + } + + } + + ASSERT( EXPECTED_SUM == test_helper<T>::get(iterator_sum), NULL); + ASSERT( EXPECTED_SUM == test_helper<T>::get(const_iterator_sum), NULL); + ASSERT( EXPECTED_SUM == test_helper<T>::get(range_sum), NULL); + ASSERT( EXPECTED_SUM == test_helper<T>::get(const_range_sum), NULL); + + ASSERT( EXPECTED_SUM == test_helper<T>::get(cconst_sum), NULL); + ASSERT( EXPECTED_SUM == test_helper<T>::get(assign_sum), NULL); + ASSERT( EXPECTED_SUM == test_helper<T>::get(cassgn_sum), NULL); + ASSERT( EXPECTED_SUM == test_helper<T>::get(non_cassgn_sum), NULL); + ASSERT( EXPECTED_SUM == test_helper<T>::get(finit_ets_sum), NULL); + ASSERT( EXPECTED_SUM == test_helper<T>::get(static_sum), NULL); + + REMARK("done\nparallel %s, %d, %g, %g\n", test_name, p, test_helper<T>::get(iterator_sum), + ( tbb::tick_count::now() - t0).seconds()); + } +} + +template< typename T > +void run_parallel_scalar_tests(const char *test_name) { + + typedef tbb::enumerable_thread_specific<T> ets_type; + + // We assume that static_sums zero-initialized or has a default constructor that zeros it. + static ets_type static_sums = ets_type( T() ); + + T exemplar; + test_helper<T>::init(exemplar); + + run_parallel_scalar_tests_nocombine<T>(test_name); + + for (int p = MinThread; p <= MaxThread; ++p) { + REMARK("Testing parallel %s on %d thread(s)... ", test_name, p); + tbb::task_scheduler_init init(p); + tbb::tick_count t0; + + T combine_sum; + test_helper<T>::init(combine_sum); + + T combine_ref_sum; + test_helper<T>::init(combine_ref_sum); + + T combine_one_sum; + test_helper<T>::init(combine_one_sum); + + T static_sum; + test_helper<T>::init(static_sum); + + for (int t = -1; t < REPETITIONS; ++t) { + if (Verbose && t == 0) t0 = tbb::tick_count::now(); + + static_sums.clear(); + + ets_type sums(exemplar); + + ASSERT( sums.empty(), NULL); + tbb::parallel_for( tbb::blocked_range<int>( 0, N, 10000 ), parallel_scalar_body<T>( sums ) ); + ASSERT( !sums.empty(), NULL); + + ASSERT(static_sums.empty(), NULL); + tbb::parallel_for( tbb::blocked_range<int>( 0, N, 10000 ), parallel_scalar_body<T>( static_sums ) ); + ASSERT( !static_sums.empty(), NULL); + + + // Use combine + test_helper<T>::sum(combine_sum, sums.combine(my_combine<T>)); + test_helper<T>::sum(combine_ref_sum, sums.combine(my_combine_ref<T>)); + test_helper<T>::sum(static_sum, static_sums.combine(my_combine<T>)); + + combine_one_helper<T> my_helper(combine_one_sum); + sums.combine_each(my_helper); + } + + + ASSERT( EXPECTED_SUM == test_helper<T>::get(combine_sum), NULL); + ASSERT( EXPECTED_SUM == test_helper<T>::get(combine_ref_sum), NULL); + ASSERT( EXPECTED_SUM == test_helper<T>::get(static_sum), NULL); + + REMARK("done\nparallel combine %s, %d, %g, %g\n", test_name, p, test_helper<T>::get(combine_sum), + ( tbb::tick_count::now() - t0).seconds()); + } +} + +template <typename T> +class parallel_vector_for_body: NoAssign { + + tbb::enumerable_thread_specific< std::vector<T, tbb::tbb_allocator<T> > > &locals; + +public: + + parallel_vector_for_body ( tbb::enumerable_thread_specific< std::vector<T, tbb::tbb_allocator<T> > > &_locals ) : locals(_locals) { } + + void operator()( const tbb::blocked_range<int> &r ) const { + T one; + test_helper<T>::set(one, 1); + + for (int i = r.begin(); i < r.end(); ++i) { + locals.local().push_back( one ); + } + } + +}; + +template <typename R, typename T> +struct parallel_vector_reduce_body { + + T sum; + size_t count; + + parallel_vector_reduce_body ( ) : count(0) { test_helper<T>::init(sum); } + parallel_vector_reduce_body ( parallel_vector_reduce_body<R, T> &, tbb::split ) : count(0) { test_helper<T>::init(sum); } + + void operator()( const R &r ) { + for (typename R::iterator ri = r.begin(); ri != r.end(); ++ri) { + const std::vector< T, tbb::tbb_allocator<T> > &v = *ri; + ++count; + for (typename std::vector<T, tbb::tbb_allocator<T> >::const_iterator vi = v.begin(); vi != v.end(); ++vi) { + test_helper<T>::sum(sum, *vi); + } + } + } + + void join( const parallel_vector_reduce_body &b ) { + test_helper<T>::sum(sum,b.sum); + count += b.count; + } + +}; + +template< typename T > +void run_parallel_vector_tests(const char *test_name) { + tbb::tick_count t0; + typedef std::vector<T, tbb::tbb_allocator<T> > container_type; + + for (int p = MinThread; p <= MaxThread; ++p) { + REMARK("Testing parallel %s on %d thread(s)... ", test_name, p); + tbb::task_scheduler_init init(p); + + T sum; + test_helper<T>::init(sum); + + for (int t = -1; t < REPETITIONS; ++t) { + if (Verbose && t == 0) t0 = tbb::tick_count::now(); + typedef typename tbb::enumerable_thread_specific< container_type > ets_type; + ets_type vs; + + ASSERT( vs.empty(), NULL); + tbb::parallel_for ( tbb::blocked_range<int> (0, N, 10000), parallel_vector_for_body<T>( vs ) ); + ASSERT( !vs.empty(), NULL); + + // copy construct + ets_type vs2(vs); // this causes an assertion failure, related to allocators... + + // assign + ets_type vs3; + vs3 = vs; + + parallel_vector_reduce_body< typename tbb::enumerable_thread_specific< std::vector< T, tbb::tbb_allocator<T> > >::const_range_type, T > pvrb; + tbb::parallel_reduce ( vs.range(1), pvrb ); + + test_helper<T>::sum(sum, pvrb.sum); + + ASSERT( vs.size() == pvrb.count, NULL); + + tbb::flattened2d<ets_type> fvs = flatten2d(vs); + size_t ccount = fvs.size(); + size_t elem_cnt = 0; + for(typename tbb::flattened2d<ets_type>::const_iterator i = fvs.begin(); i != fvs.end(); ++i) { + ++elem_cnt; + }; + ASSERT(ccount == elem_cnt, NULL); + + elem_cnt = 0; + for(typename tbb::flattened2d<ets_type>::iterator i = fvs.begin(); i != fvs.end(); ++i) { + ++elem_cnt; + }; + ASSERT(ccount == elem_cnt, NULL); + } + + double result_value = test_helper<T>::get(sum); + ASSERT( EXPECTED_SUM == result_value, NULL); + REMARK("done\nparallel %s, %d, %g, %g\n", test_name, p, result_value, ( tbb::tick_count::now() - t0).seconds()); + } +} + +template<typename T> +void run_cross_type_vector_tests(const char *test_name) { + tbb::tick_count t0; + typedef std::vector<T, tbb::tbb_allocator<T> > container_type; + + for (int p = MinThread; p <= MaxThread; ++p) { + REMARK("Testing parallel %s on %d thread(s)... ", test_name, p); + tbb::task_scheduler_init init(p); + + T sum; + test_helper<T>::init(sum); + + for (int t = -1; t < REPETITIONS; ++t) { + if (Verbose && t == 0) t0 = tbb::tick_count::now(); + typedef typename tbb::enumerable_thread_specific< container_type, tbb::cache_aligned_allocator<container_type>, tbb::ets_no_key > ets_nokey_type; + typedef typename tbb::enumerable_thread_specific< container_type, tbb::cache_aligned_allocator<container_type>, tbb::ets_key_per_instance > ets_tlskey_type; + ets_nokey_type vs; + + ASSERT( vs.empty(), NULL); + tbb::parallel_for ( tbb::blocked_range<int> (0, N, 10000), parallel_vector_for_body<T>( vs ) ); + ASSERT( !vs.empty(), NULL); + + // copy construct + ets_tlskey_type vs2(vs); + + // assign + ets_nokey_type vs3; + vs3 = vs2; + + parallel_vector_reduce_body< typename tbb::enumerable_thread_specific< std::vector< T, tbb::tbb_allocator<T> > >::const_range_type, T > pvrb; + tbb::parallel_reduce ( vs3.range(1), pvrb ); + + test_helper<T>::sum(sum, pvrb.sum); + + ASSERT( vs3.size() == pvrb.count, NULL); + + tbb::flattened2d<ets_nokey_type> fvs = flatten2d(vs3); + size_t ccount = fvs.size(); + size_t elem_cnt = 0; + for(typename tbb::flattened2d<ets_nokey_type>::const_iterator i = fvs.begin(); i != fvs.end(); ++i) { + ++elem_cnt; + }; + ASSERT(ccount == elem_cnt, NULL); + + elem_cnt = 0; + for(typename tbb::flattened2d<ets_nokey_type>::iterator i = fvs.begin(); i != fvs.end(); ++i) { + ++elem_cnt; + }; + ASSERT(ccount == elem_cnt, NULL); + } + + double result_value = test_helper<T>::get(sum); + ASSERT( EXPECTED_SUM == result_value, NULL); + REMARK("done\nparallel %s, %d, %g, %g\n", test_name, p, result_value, ( tbb::tick_count::now() - t0).seconds()); + } +} + +template< typename T > +void run_serial_vector_tests(const char *test_name) { + tbb::tick_count t0; + T sum; + test_helper<T>::init(sum); + T one; + test_helper<T>::set(one, 1); + + REMARK("Testing serial %s... ", test_name); + for (int t = -1; t < REPETITIONS; ++t) { + if (Verbose && t == 0) t0 = tbb::tick_count::now(); + std::vector<T, tbb::tbb_allocator<T> > v; + for (int i = 0; i < N; ++i) { + v.push_back( one ); + } + for (typename std::vector<T, tbb::tbb_allocator<T> >::const_iterator i = v.begin(); i != v.end(); ++i) + test_helper<T>::sum(sum, *i); + } + + double result_value = test_helper<T>::get(sum); + ASSERT( EXPECTED_SUM == result_value, NULL); + REMARK("done\nserial %s, 0, %g, %g\n", test_name, result_value, ( tbb::tick_count::now() - t0).seconds()); +} + +const size_t line_size = tbb::internal::NFS_MaxLineSize; + +void +run_serial_tests() { + run_serial_scalar_tests<int>("int"); + run_serial_scalar_tests<double>("double"); + run_serial_scalar_tests<minimal<> >("minimal<>"); + run_serial_vector_tests<int>("std::vector<int, tbb::tbb_allocator<int> >"); + run_serial_vector_tests<double>("std::vector<double, tbb::tbb_allocator<double> >"); +} + +void +run_parallel_tests() { + run_parallel_scalar_tests<int>("int"); + run_parallel_scalar_tests<double>("double"); + run_parallel_scalar_tests_nocombine<minimal<> >("minimal<>"); + run_parallel_vector_tests<int>("std::vector<int, tbb::tbb_allocator<int> >"); + run_parallel_vector_tests<double>("std::vector<double, tbb::tbb_allocator<double> >"); +} + +void +run_cross_type_tests() { + // cross-type scalar tests are part of run_serial_scalar_tests + run_cross_type_vector_tests<int>("std::vector<int, tbb::tbb_allocator<int> >"); + run_parallel_vector_tests<double>("std::vector<double, tbb::tbb_allocator<double> >"); +} + +typedef tbb::enumerable_thread_specific<minimal<line_size> > flogged_ets; + +class set_body { + flogged_ets *a; + +public: + set_body( flogged_ets*_a ) : a(_a) { } + + void operator() ( ) const { + for (int i = 0; i < VALID_NUMBER_OF_KEYS; ++i) { + a[i].local().set_value(i + 1); + } + } + +}; + +void do_tbb_threads( int max_threads, flogged_ets a[] ) { + std::vector< tbb::tbb_thread * > threads; + + for (int p = 0; p < max_threads; ++p) { + threads.push_back( new tbb::tbb_thread ( set_body( a ) ) ); + } + + for (int p = 0; p < max_threads; ++p) { + threads[p]->join(); + } + + for(int p = 0; p < max_threads; ++p) { + delete threads[p]; + } +} + +void +flog_key_creation_and_deletion() { + const int FLOG_REPETITIONS = 100; + + for (int p = MinThread; p <= MaxThread; ++p) { + REMARK("Testing repeated deletes on %d threads... ", p); + + for (int j = 0; j < FLOG_REPETITIONS; ++j) { + construction_counter = 0; + destruction_counter = 0; + + // causes VALID_NUMER_OF_KEYS exemplar instances to be constructed + flogged_ets* a = new flogged_ets[VALID_NUMBER_OF_KEYS]; + ASSERT(int(construction_counter) == 0, NULL); // no exemplars or actual locals have been constructed + ASSERT(int(destruction_counter) == 0, NULL); // and none have been destroyed + + // causes p * VALID_NUMBER_OF_KEYS minimals to be created + do_tbb_threads(p, a); + + for (int i = 0; i < VALID_NUMBER_OF_KEYS; ++i) { + int pcnt = 0; + for ( flogged_ets::iterator tli = a[i].begin(); tli != a[i].end(); ++tli ) { + ASSERT( (*tli).value() == i+1, NULL ); + ++pcnt; + } + ASSERT( pcnt == p, NULL); // should be one local per thread. + } + delete[] a; + } + + ASSERT( int(construction_counter) == (p)*VALID_NUMBER_OF_KEYS, NULL ); + ASSERT( int(destruction_counter) == (p)*VALID_NUMBER_OF_KEYS, NULL ); + + REMARK("done\nTesting repeated clears on %d threads... ", p); + + construction_counter = 0; + destruction_counter = 0; + + // causes VALID_NUMER_OF_KEYS exemplar instances to be constructed + flogged_ets* a = new flogged_ets[VALID_NUMBER_OF_KEYS]; + + for (int j = 0; j < FLOG_REPETITIONS; ++j) { + + // causes p * VALID_NUMBER_OF_KEYS minimals to be created + do_tbb_threads(p, a); + + for (int i = 0; i < VALID_NUMBER_OF_KEYS; ++i) { + for ( flogged_ets::iterator tli = a[i].begin(); tli != a[i].end(); ++tli ) { + ASSERT( (*tli).value() == i+1, NULL ); + } + a[i].clear(); + ASSERT( static_cast<int>(a[i].end() - a[i].begin()) == 0, NULL ); + } + + } + + delete[] a; + + ASSERT( int(construction_counter) == (FLOG_REPETITIONS*p)*VALID_NUMBER_OF_KEYS, NULL ); + ASSERT( int(destruction_counter) == (FLOG_REPETITIONS*p)*VALID_NUMBER_OF_KEYS, NULL ); + + REMARK("done\n"); + } + +} + +template <typename inner_container> +void +flog_segmented_interator() { + + bool found_error = false; + typedef typename inner_container::value_type T; + typedef std::vector< inner_container > nested_vec; + inner_container my_inner_container; + my_inner_container.clear(); + nested_vec my_vec; + + // simple nested vector (neither level empty) + const int maxval = 10; + for(int i=0; i < maxval; i++) { + my_vec.push_back(my_inner_container); + for(int j = 0; j < maxval; j++) { + my_vec.at(i).push_back((T)(maxval * i + j)); + } + } + + tbb::internal::segmented_iterator<nested_vec, T> my_si(my_vec); + + T ii; + for(my_si=my_vec.begin(), ii=0; my_si != my_vec.end(); ++my_si, ++ii) { + if((*my_si) != ii) { + found_error = true; + REMARK( "*my_si=%d\n", int(*my_si)); + } + } + + // outer level empty + my_vec.clear(); + for(my_si=my_vec.begin(); my_si != my_vec.end(); ++my_si) { + found_error = true; + } + + // inner levels empty + my_vec.clear(); + for(int i =0; i < maxval; ++i) { + my_vec.push_back(my_inner_container); + } + for(my_si = my_vec.begin(); my_si != my_vec.end(); ++my_si) { + found_error = true; + } + + // every other inner container is empty + my_vec.clear(); + for(int i=0; i < maxval; ++i) { + my_vec.push_back(my_inner_container); + if(i%2) { + for(int j = 0; j < maxval; ++j) { + my_vec.at(i).push_back((T)(maxval * (i/2) + j)); + } + } + } + for(my_si = my_vec.begin(), ii=0; my_si != my_vec.end(); ++my_si, ++ii) { + if((*my_si) != ii) { + found_error = true; + REMARK("*my_si=%d, ii=%d\n", (int)(*my_si), (int)ii); + } + } + + tbb::internal::segmented_iterator<nested_vec, const T> my_csi(my_vec); + for(my_csi=my_vec.begin(), ii=0; my_csi != my_vec.end(); ++my_csi, ++ii) { + if((*my_csi) != ii) { + found_error = true; + REMARK( "*my_csi=%d\n", int(*my_csi)); + } + } + + // outer level empty + my_vec.clear(); + for(my_csi=my_vec.begin(); my_csi != my_vec.end(); ++my_csi) { + found_error = true; + } + + // inner levels empty + my_vec.clear(); + for(int i =0; i < maxval; ++i) { + my_vec.push_back(my_inner_container); + } + for(my_csi = my_vec.begin(); my_csi != my_vec.end(); ++my_csi) { + found_error = true; + } + + // every other inner container is empty + my_vec.clear(); + for(int i=0; i < maxval; ++i) { + my_vec.push_back(my_inner_container); + if(i%2) { + for(int j = 0; j < maxval; ++j) { + my_vec.at(i).push_back((T)(maxval * (i/2) + j)); + } + } + } + for(my_csi = my_vec.begin(), ii=0; my_csi != my_vec.end(); ++my_csi, ++ii) { + if((*my_csi) != ii) { + found_error = true; + REMARK("*my_csi=%d, ii=%d\n", (int)(*my_csi), (int)ii); + } + } + + + if(found_error) REPORT("segmented_iterator failed\n"); +} + +template <typename Key, typename Val> +void +flog_segmented_iterator_map() { + typedef typename std::map<Key, Val> my_map; + typedef std::vector< my_map > nested_vec; + my_map my_inner_container; + my_inner_container.clear(); + nested_vec my_vec; + my_vec.clear(); + bool found_error = false; + + // simple nested vector (neither level empty) + const int maxval = 4; + for(int i=0; i < maxval; i++) { + my_vec.push_back(my_inner_container); + for(int j = 0; j < maxval; j++) { + my_vec.at(i).insert(std::make_pair<Key,Val>(maxval * i + j, 2*(maxval*i + j))); + } + } + + tbb::internal::segmented_iterator<nested_vec, std::pair<const Key, Val> > my_si(my_vec); + Key ii; + for(my_si=my_vec.begin(), ii=0; my_si != my_vec.end(); ++my_si, ++ii) { + if(((*my_si).first != ii) || ((*my_si).second != 2*ii)) { + found_error = true; + REMARK( "ii=%d, (*my_si).first=%d, second=%d\n",ii, int((*my_si).first), int((*my_si).second)); + } + } + + tbb::internal::segmented_iterator<nested_vec, const std::pair<const Key, Val> > my_csi(my_vec); + for(my_csi=my_vec.begin(), ii=0; my_csi != my_vec.end(); ++my_csi, ++ii) { + if(((*my_csi).first != ii) || ((*my_csi).second != 2*ii)) { + found_error = true; + REMARK( "ii=%d, (*my_csi).first=%d, second=%d\n",ii, int((*my_csi).first), int((*my_csi).second)); + } + } + if(found_error) REPORT("segmented_iterator_map failed\n"); +} + +void +run_segmented_iterator_tests() { + // only the following containers can be used with the segmented iterator. + REMARK("Running Segmented Iterator Tests\n"); + flog_segmented_interator<std::vector< int > >(); + flog_segmented_interator<std::vector< double > >(); + flog_segmented_interator<std::deque< int > >(); + flog_segmented_interator<std::deque< double > >(); + flog_segmented_interator<std::list< int > >(); + flog_segmented_interator<std::list< double > >(); + + flog_segmented_iterator_map<int, int>(); + flog_segmented_iterator_map<int, double>(); +} + +template <typename T> +void +run_assign_and_copy_constructor_test(const char *test_name) { + REMARK("Testing assignment and copy construction for %s\n", test_name); + + // test initializer with exemplar + T initializer0; + test_helper<T>::init(initializer0); + T initializer7; + test_helper<T>::set(initializer7,7); + tbb::enumerable_thread_specific<T> create1(initializer7); + (void) create1.local(); // create an initialized value + ASSERT(7 == test_helper<T>::get(create1.local()), NULL); + + // test copy construction with exemplar initializer + create1.clear(); + tbb::enumerable_thread_specific<T> copy1(create1); + (void) copy1.local(); + ASSERT(7 == test_helper<T>::get(copy1.local()), NULL); + + // test copy assignment with exemplar initializer + create1.clear(); + tbb::enumerable_thread_specific<T> assign1(initializer0); + assign1 = create1; + (void) assign1.local(); + ASSERT(7 == test_helper<T>::get(assign1.local()), NULL); + + // test creation with finit function + FunctorFinit<T,7> my_finit7(SecretTag); + tbb::enumerable_thread_specific<T> create2(my_finit7); + (void) create2.local(); + ASSERT(7 == test_helper<T>::get(create2.local()), NULL); + + // test copy construction with function initializer + create2.clear(); + tbb::enumerable_thread_specific<T> copy2(create2); + (void) copy2.local(); + ASSERT(7 == test_helper<T>::get(copy2.local()), NULL); + + // test copy assignment with function initializer + create2.clear(); + FunctorFinit<T,0> my_finit(SecretTag); + tbb::enumerable_thread_specific<T> assign2(my_finit); + assign2 = create2; + (void) assign2.local(); + ASSERT(7 == test_helper<T>::get(assign2.local()), NULL); +} + +void +run_assignment_and_copy_constructor_tests() { + REMARK("Running assignment and copy constructor tests\n"); + run_assign_and_copy_constructor_test<int>("int"); + run_assign_and_copy_constructor_test<double>("double"); + // Try class sizes that are close to a cache line in size, in order to check padding calculations. + run_assign_and_copy_constructor_test<minimal<line_size-1> >("minimal<line_size-1>"); + run_assign_and_copy_constructor_test<minimal<line_size> >("minimal<line_size>"); + run_assign_and_copy_constructor_test<minimal<line_size+1> >("minimal<line_size+1>"); + ASSERT(FinitCounter==0, NULL); +} + +// Class with no default constructor +class HasNoDefaultConstructor { + HasNoDefaultConstructor(); +public: + HasNoDefaultConstructor( SecretTagType ) {} +}; + +// Initialization functor for a HasNoDefaultConstructor +struct HasNoDefaultConstructorFinit { + HasNoDefaultConstructor operator()() { + return HasNoDefaultConstructor(SecretTag); + } +}; + +struct HasNoDefaultConstructorCombine { + HasNoDefaultConstructor operator()( HasNoDefaultConstructor, HasNoDefaultConstructor ) { + return HasNoDefaultConstructor(SecretTag); + } +}; + +//! Test situations where only default constructor or copy constructor is required. +void TestInstantiation() { + // Test instantiation is possible when copy constructor is not required. + tbb::enumerable_thread_specific<NoCopy> ets1; + + // Test instantiation when default constructor is not required, because exemplar is provided. + HasNoDefaultConstructor x(SecretTag); + tbb::enumerable_thread_specific<HasNoDefaultConstructor> ets2(x); + ets2.combine(HasNoDefaultConstructorCombine()); + + // Test instantiation when default constructor is not required, because init function is provided. + HasNoDefaultConstructorFinit f; + tbb::enumerable_thread_specific<HasNoDefaultConstructor> ets3(f); + ets3.combine(HasNoDefaultConstructorCombine()); +} + +int TestMain () { + TestInstantiation(); + run_segmented_iterator_tests(); + flog_key_creation_and_deletion(); + + if (MinThread == 0) { + run_serial_tests(); + MinThread = 1; + } + if (MaxThread > 0) { + run_parallel_tests(); + run_cross_type_tests(); + } + + run_assignment_and_copy_constructor_tests(); + + return Harness::Done; +} diff --git a/src/tbb/src/test/test_fast_random.cpp b/src/tbb/src/test/test_fast_random.cpp new file mode 100644 index 0000000..6b7d023 --- /dev/null +++ b/src/tbb/src/test/test_fast_random.cpp @@ -0,0 +1,217 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/** + The test checks that for different ranges of random numbers (from 0 to + [MinThread, MaxThread]) generated with different seeds the probability + of each number in the range deviates from the ideal random distribution + by no more than AcceptableDeviation percent. +**/ + +#if HARNESS_USE_PROXY + +// The test includes injects scheduler directly, so skip it when proxy tested. + +#undef HARNESS_USE_PROXY +#include "harness.h" + +int TestMain () { + return Harness::Skipped; +} + +#else // HARNESS_USE_PROXY + +#include "harness_inject_scheduler.h" + +#define HARNESS_DEFAULT_MIN_THREADS 2 +#define HARNESS_DEFAULT_MAX_THREADS 32 + +#define TEST_TOTAL_SEQUENCE 0 + +#include "harness.h" +#include "tbb/atomic.h" + +//! Coefficient defining tolerable deviation from ideal random distribution +const double AcceptableDeviation = 2.1; +//! Tolerable probability of failure to achieve tolerable distribution +const double AcceptableProbabilityOfOutliers = 1e-6; +//! Coefficient defining the length of random numbers series used to estimate the distribution +/** Number of random values generated per each range element. I.e. the larger is + the range, the longer is the series of random values. **/ +const uintptr_t SeriesBaseLen = 100; +//! Number of random numbers series to generate +const uintptr_t NumSeries = 100; +//! Number of random number generation series with different seeds +const uintptr_t NumSeeds = 100; + +tbb::atomic<uintptr_t> NumHighOutliers; +tbb::atomic<uintptr_t> NumLowOutliers; + +inline void CheckProbability ( double probability, double expectedProbability, int index, int numIndices ) { + double lowerBound = expectedProbability / AcceptableDeviation, + upperBound = expectedProbability * AcceptableDeviation; + if ( probability < lowerBound ) { + if ( !NumLowOutliers ) + REMARK( "Warning: Probability %.3f of hitting index %d among %d elements is out of acceptable range (%.3f - %.3f)\n", + probability, index, numIndices, lowerBound, upperBound ); + ++NumLowOutliers; + } + else if ( probability > upperBound ) { + if ( !NumHighOutliers ) + REMARK( "Warning: Probability %.3f of hitting index %d among %d elements is out of acceptable range (%.3f - %.3f)\n", + probability, index, numIndices, lowerBound, upperBound ); + ++NumHighOutliers; + } +} + +struct CheckDistributionBody { + void operator() ( int id ) const { + uintptr_t randomRange = id + MinThread; + uintptr_t *curHits = new uintptr_t[randomRange] +#if TEST_TOTAL_SEQUENCE + , *totalHits = new uintptr_t[randomRange] +#endif + ; + double expectedProbability = 1./randomRange; + // Loop through different seeds + for ( uintptr_t i = 0; i < NumSeeds; ++i ) { + // Seed value is selected in two ways, the first of which mimics + // the one used by the TBB task scheduler + void* seed = i % 2 ? (char*)&curHits + i * 16 : (void*)(i * 8); + tbb::internal::FastRandom random( (unsigned)(uintptr_t)seed ); + memset( curHits, 0, randomRange * sizeof(uintptr_t) ); +#if TEST_TOTAL_SEQUENCE + memset( totalHits, 0, randomRange * sizeof(uintptr_t) ); +#endif + const uintptr_t seriesLen = randomRange * SeriesBaseLen, + experimentLen = NumSeries * seriesLen; + uintptr_t *curSeries = new uintptr_t[seriesLen], // circular buffer + randsGenerated = 0; + // Initialize statistics + while ( randsGenerated < seriesLen ) { + uintptr_t idx = random.get() % randomRange; + ++curHits[idx]; +#if TEST_TOTAL_SEQUENCE + ++totalHits[idx]; +#endif + curSeries[randsGenerated++] = idx; + } + while ( randsGenerated < experimentLen ) { + for ( uintptr_t j = 0; j < randomRange; ++j ) { + CheckProbability( double(curHits[j])/seriesLen, expectedProbability, j, randomRange ); +#if TEST_TOTAL_SEQUENCE + CheckProbability( double(totalHits[j])/randsGenerated, expectedProbability, j, randomRange ); +#endif + } + --curHits[curSeries[randsGenerated % seriesLen]]; + int idx = random.get() % randomRange; + ++curHits[idx]; +#if TEST_TOTAL_SEQUENCE + ++totalHits[idx]; +#endif + curSeries[randsGenerated++ % seriesLen] = idx; + } + delete [] curSeries; + } + delete [] curHits; +#if TEST_TOTAL_SEQUENCE + delete [] totalHits; +#endif + } +}; + +struct rng { + tbb::internal::FastRandom my_fast_random; + rng (unsigned seed):my_fast_random(seed) {} + unsigned short operator()(){return my_fast_random.get();} +}; + +#include <algorithm> + +template <std::size_t seriesLen > +struct SingleCheck{ + bool operator()(unsigned seed)const{ + std::size_t series1[seriesLen]={0}; + std::size_t series2[seriesLen]={0}; + std::generate(series1,series1+seriesLen,rng(seed)); + std::generate(series2,series2+seriesLen,rng(seed)); + return std::equal(series1,series1+seriesLen,series2); + } +}; + +template <std::size_t seriesLen ,size_t seedsNum> +struct CheckReproducibilityBody:NoAssign{ + unsigned short seeds[seedsNum]; + const std::size_t grainSize; + CheckReproducibilityBody(std::size_t GrainSize): grainSize(GrainSize){ + //first generate seeds to check on, and make sure that sequence is reproducible + ASSERT(SingleCheck<seedsNum>()(0),"Series generated by FastRandom must be reproducible"); + std::generate(seeds,seeds+seedsNum,rng(0)); + } + + void operator()(int id)const{ + for (size_t i=id*grainSize; (i<seedsNum)&&(i< ((id+1)*grainSize));++i ){ + ASSERT(SingleCheck<seriesLen>()(i),"Series generated by FastRandom must be reproducible"); + } + } + +}; +#include "tbb/tbb_thread.h" + +int TestMain () { + ASSERT( AcceptableDeviation < 100, NULL ); + MinThread = max(MinThread, 2); + MaxThread = max(MinThread, MaxThread); + double NumChecks = double(NumSeeds) * (MaxThread - MinThread + 1) * (MaxThread + MinThread) / 2.0 * (SeriesBaseLen * NumSeries - SeriesBaseLen); + REMARK( "Number of distribution quality checks %g\n", NumChecks ); + NumLowOutliers = NumHighOutliers = 0; + // Parallelism is used in this test only to speed up the long serial checks + // Essentially it is a loop over random number ranges + // Ideally tbb::parallel_for could be used to parallelize the outermost loop + // in CheckDistributionBody, but it is not used to avoid unit test contamination. + int P = tbb::tbb_thread::hardware_concurrency(); + enum {reproducibilitySeedsToTest=1000}; + enum {reproducibilitySeriesLen=100}; + CheckReproducibilityBody<reproducibilitySeriesLen,reproducibilitySeedsToTest> CheckReproducibility(reproducibilitySeedsToTest/MaxThread); + while ( MinThread <= MaxThread ) { + int ThreadsToRun = min(P, MaxThread - MinThread + 1); + NativeParallelFor( ThreadsToRun, CheckDistributionBody() ); + NativeParallelFor(ThreadsToRun, CheckReproducibility); + MinThread += P; + } + double observedProbabilityOfOutliers = (NumLowOutliers + NumHighOutliers) / NumChecks; + if ( observedProbabilityOfOutliers > AcceptableProbabilityOfOutliers ) { + if ( NumLowOutliers ) + REPORT( "Warning: %d cases of too low probability of a given number detected\n", (int)NumLowOutliers ); + if ( NumHighOutliers ) + REPORT( "Warning: %d cases of too high probability of a given number detected\n", (int)NumHighOutliers ); + ASSERT( observedProbabilityOfOutliers <= AcceptableProbabilityOfOutliers, NULL ); + } + return Harness::Done; +} +#endif // HARNESS_USE_PROXY diff --git a/src/tbb/src/test/test_flow_graph.cpp b/src/tbb/src/test/test_flow_graph.cpp new file mode 100644 index 0000000..1dd44c0 --- /dev/null +++ b/src/tbb/src/test/test_flow_graph.cpp @@ -0,0 +1,232 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "harness_graph.h" +#include "harness_barrier.h" +#include "tbb/task_scheduler_init.h" + +const int T = 4; +const int W = 4; + +struct decrement_wait : NoAssign { + + tbb::flow::graph * const my_graph; + bool * const my_done_flag; + + decrement_wait( tbb::flow::graph &h, bool *done_flag ) : my_graph(&h), my_done_flag(done_flag) {} + + void operator()(int i) const { + Harness::Sleep(10*i); + my_done_flag[i] = true; + my_graph->decrement_wait_count(); + } +}; + +static void test_wait_count() { + tbb::flow::graph h; + for (int i = 0; i < T; ++i ) { + bool done_flag[W]; + for (int j = 0; j < W; ++j ) { + for ( int w = 0; w < W; ++w ) done_flag[w] = false; + for ( int w = 0; w < j; ++w ) h.increment_wait_count(); + + NativeParallelFor( j, decrement_wait(h, done_flag) ); + h.wait_for_all(); + for ( int w = 0; w < W; ++w ) { + if ( w < j ) ASSERT( done_flag[w] == true, NULL ); + else ASSERT( done_flag[w] == false, NULL ); + } + } + } +} + +const int F = 100; + +#if __TBB_LAMBDAS_PRESENT +bool lambda_flag[F]; +#endif +bool functor_flag[F]; + +struct set_functor { + int my_i; + set_functor( int i ) : my_i(i) {} + void operator()() { functor_flag[my_i] = true; } +}; + +struct return_functor { + int my_i; + return_functor( int i ) : my_i(i) {} + int operator()() { return my_i; } +}; + +static void test_run() { + tbb::flow::graph h; + for (int i = 0; i < T; ++i ) { + + // Create receivers and flag arrays + #if __TBB_LAMBDAS_PRESENT + harness_mapped_receiver<int> lambda_r; + lambda_r.initialize_map( F, 1 ); + #endif + harness_mapped_receiver<int> functor_r; + functor_r.initialize_map( F, 1 ); + + // Initialize flag arrays + for (int j = 0; j < F; ++j ) { + #if __TBB_LAMBDAS_PRESENT + lambda_flag[j] = false; + #endif + functor_flag[j] = false; + } + + for ( int j = 0; j < F; ++j ) { + #if __TBB_LAMBDAS_PRESENT + h.run( [=]() { lambda_flag[j] = true; } ); + h.run( lambda_r, [=]() { return j; } ); + #endif + h.run( set_functor(j) ); + h.run( functor_r, return_functor(j) ); + } + h.wait_for_all(); + for ( int j = 0; j < F; ++j ) { + #if __TBB_LAMBDAS_PRESENT + ASSERT( lambda_flag[i] == true, NULL ); + #endif + ASSERT( functor_flag[i] == true, NULL ); + } + #if __TBB_LAMBDAS_PRESENT + lambda_r.validate(); + #endif + functor_r.validate(); + } +} + +// Encapsulate object we want to store in vector (because contained type must have +// copy constructor and assignment operator +class my_int_buffer { + tbb::flow::buffer_node<int> *b; + tbb::flow::graph& my_graph; +public: + my_int_buffer(tbb::flow::graph &g) : my_graph(g) { b = new tbb::flow::buffer_node<int>(my_graph); } + my_int_buffer(const my_int_buffer& other) : my_graph(other.my_graph) { + b = new tbb::flow::buffer_node<int>(my_graph); + } + ~my_int_buffer() { delete b; } + my_int_buffer& operator=(const my_int_buffer& /*other*/) { + return *this; + } +}; + +// test the graph iterator, delete nodes from graph, test again +void test_iterator() { + tbb::flow::graph g; + my_int_buffer a_buffer(g); + my_int_buffer b_buffer(g); + my_int_buffer c_buffer(g); + my_int_buffer *d_buffer = new my_int_buffer(g); + my_int_buffer e_buffer(g); + std::vector< my_int_buffer > my_buffer_vector(10, c_buffer); + + int count = 0; + for (tbb::flow::graph::iterator it = g.begin(); it != g.end(); ++it) { + count++; + } + ASSERT(count==15, "error in iterator count"); + + delete d_buffer; + + count = 0; + for (tbb::flow::graph::iterator it = g.begin(); it != g.end(); ++it) { + count++; + } + ASSERT(count==14, "error in iterator count"); + + my_buffer_vector.clear(); + + count = 0; + for (tbb::flow::graph::iterator it = g.begin(); it != g.end(); ++it) { + count++; + } + ASSERT(count==4, "error in iterator count"); +} + +class AddRemoveBody : NoAssign { + tbb::flow::graph& g; + int nThreads; + Harness::SpinBarrier &barrier; +public: + AddRemoveBody(int nthr, Harness::SpinBarrier &barrier_, tbb::flow::graph& _g) : + g(_g), nThreads(nthr), barrier(barrier_) + {} + void operator()(const int /*threadID*/) const { + my_int_buffer b(g); + { + std::vector<my_int_buffer> my_buffer_vector(100, b); + barrier.wait(); // wait until all nodes are created + // now test that the proper number of nodes were created + int count = 0; + for (tbb::flow::graph::iterator it = g.begin(); it != g.end(); ++it) { + count++; + } + ASSERT(count==101*nThreads, "error in iterator count"); + barrier.wait(); // wait until all threads are done counting + } // all nodes but for the initial node on this thread are deleted + barrier.wait(); // wait until all threads have deleted all nodes in their vectors + // now test that all the nodes were deleted except for the initial node + int count = 0; + for (tbb::flow::graph::iterator it = g.begin(); it != g.end(); ++it) { + count++; + } + ASSERT(count==nThreads, "error in iterator count"); + barrier.wait(); // wait until all threads are done counting + } // initial node gets deleted +}; + +void test_parallel(int nThreads) { + tbb::flow::graph g; + Harness::SpinBarrier barrier(nThreads); + AddRemoveBody body(nThreads, barrier, g); + NativeParallelFor(nThreads, body); +} + +int TestMain() { + current_executors = 0; + if( MinThread<1 ) { + REPORT("number of threads must be positive\n"); + exit(1); + } + for( int p=MinThread; p<=MaxThread; ++p ) { + tbb::task_scheduler_init init(p); + test_wait_count(); + test_run(); + test_iterator(); + test_parallel(p); + } + return Harness::Done; +} + diff --git a/src/tbb/src/test/test_fp.cpp b/src/tbb/src/test/test_fp.cpp new file mode 100644 index 0000000..ca230a6 --- /dev/null +++ b/src/tbb/src/test/test_fp.cpp @@ -0,0 +1,208 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/** This test checks the automatic propagation of master thread FPU settings + into the worker threads. **/ + +#include "harness.h" +#include "tbb/parallel_for.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/tbb_machine.h" + +const int N = 500000; + +#if ( __TBB_x86_32 || __TBB_x86_64 ) && __TBB_CPU_CTL_ENV_PRESENT + +const int FE_TONEAREST = 0x0000, + FE_DOWNWARD = 0x0400, + FE_UPWARD = 0x0800, + FE_TOWARDZERO = 0x0c00, + FE_RND_MODE_MASK = FE_TOWARDZERO, + SSE_RND_MODE_MASK = FE_RND_MODE_MASK << 3, + SSE_DAZ = 0x0040, + SSE_FTZ = 0x8000, + SSE_MODE_MASK = SSE_DAZ | SSE_FTZ; + +const int NumSseModes = 4; +const int SseModes[NumSseModes] = { 0, SSE_DAZ, SSE_FTZ, SSE_DAZ | SSE_FTZ }; + +#if _WIN64 && !__MINGW64__ +// MinGW uses inline implementation from tbb/machine/linux_intel64.h + +#include <float.h> + +inline void __TBB_get_cpu_ctl_env ( __TBB_cpu_ctl_env_t* fe ) { + fe->x87cw = short(_control87(0, 0) & _MCW_RC) << 2; + fe->mxcsr = _mm_getcsr(); +} +inline void __TBB_set_cpu_ctl_env ( const __TBB_cpu_ctl_env_t* fe ) { + ASSERT( (fe->x87cw & FE_RND_MODE_MASK) == ((fe->x87cw & FE_RND_MODE_MASK) >> 2 & _MCW_RC) << 2, "Check float.h constants" ); + _control87( (fe->x87cw & FE_RND_MODE_MASK) >> 6, _MCW_RC ); + _mm_setcsr( fe->mxcsr ); +} + +#endif /* _WIN64 */ + +inline int GetRoundingMode ( bool checkConsistency = true ) { + __TBB_cpu_ctl_env_t ctl = { 0, 0 }; + __TBB_get_cpu_ctl_env(&ctl); + ASSERT( !checkConsistency || (ctl.mxcsr & SSE_RND_MODE_MASK) >> 3 == (ctl.x87cw & FE_RND_MODE_MASK), NULL ); + return ctl.x87cw & FE_RND_MODE_MASK; +} + +inline void SetRoundingMode ( int mode ) { + __TBB_cpu_ctl_env_t ctl = { 0, 0 }; + __TBB_get_cpu_ctl_env(&ctl); + ctl.mxcsr = (ctl.mxcsr & ~SSE_RND_MODE_MASK) | (mode & FE_RND_MODE_MASK) << 3; + ctl.x87cw = short((ctl.x87cw & ~FE_RND_MODE_MASK) | (mode & FE_RND_MODE_MASK)); + __TBB_set_cpu_ctl_env(&ctl); +} + +inline int GetSseMode () { + __TBB_cpu_ctl_env_t ctl = { 0, 0 }; + __TBB_get_cpu_ctl_env(&ctl); + return ctl.mxcsr & SSE_MODE_MASK; +} + +inline void SetSseMode ( int mode ) { + __TBB_cpu_ctl_env_t ctl = { 0, 0 }; + __TBB_get_cpu_ctl_env(&ctl); + ctl.mxcsr = (ctl.mxcsr & ~SSE_MODE_MASK) | (mode & SSE_MODE_MASK); + __TBB_set_cpu_ctl_env(&ctl); +} + + +#else /* Other archs */ + +#include <fenv.h> + +const int RND_MODE_MASK = FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO; + +const int NumSseModes = 1; +const int SseModes[NumSseModes] = { 0 }; + +inline int GetRoundingMode ( bool = true ) { return fegetround(); } +inline void SetRoundingMode ( int rnd ) { fesetround(rnd); } + +inline int GetSseMode () { return 0; } +inline void SetSseMode ( int ) {} + +#endif /* Other archs */ + +const int NumRoundingModes = 4; +const int RoundingModes[NumRoundingModes] = { FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZERO }; + +class RoundingModeCheckBody { + Harness::tid_t m_tidMaster; + int m_masterMode; + int m_workerMode; + int m_masterSseMode; + int m_workerSseMode; +public: + void operator() ( int /*iter*/ ) const { + if ( Harness::CurrentTid() == m_tidMaster ) { + ASSERT( GetRoundingMode() == m_masterMode, "Master's FPU control state was corrupted" ); + ASSERT( GetSseMode() == m_masterSseMode, "Master's SSE control state was corrupted" ); + } + else { + ASSERT( GetRoundingMode() == m_workerMode, "FPU control state has not been propagated to a worker" ); + ASSERT( GetSseMode() == m_workerSseMode, "SSE control state has not been propagated to a worker" ); + } + } + + RoundingModeCheckBody ( Harness::tid_t tidMaster, int masterMode, int workerMode, int masterSseMode, int workerSseMode ) + : m_tidMaster(tidMaster) + , m_masterMode(masterMode) + , m_workerMode(workerMode) + , m_masterSseMode(masterSseMode) + , m_workerSseMode(workerSseMode) + {} +}; + +class LauncherBody { +public: + void operator() ( int id ) const { + Harness::tid_t tid = Harness::CurrentTid(); + // TBB scheduler instance in a master thread captures the FPU control state + // at the moment of its initialization and passes it to the workers toiling + // on its behalf. + for( int k = 0; k < NumSseModes; ++k ) { + int sse_mode = SseModes[(k + id) % NumSseModes]; + SetSseMode( sse_mode ); + for( int i = 0; i < NumRoundingModes; ++i ) { + int mode = RoundingModes[(i + id) % NumRoundingModes]; + SetRoundingMode( mode ); + // New mode must be set before TBB scheduler is initialized + tbb::task_scheduler_init init; + tbb::parallel_for( 0, N, 1, RoundingModeCheckBody(tid, mode, mode, sse_mode, sse_mode) ); + ASSERT( GetRoundingMode() == mode, NULL ); + } + } + // Since the following loop uses auto-initialization, the scheduler instance + // implicitly created by the first parallel_for invocation will persist + // until the thread ends, and thus workers will use the mode set by the + // first iteration. + int captured_mode = RoundingModes[id % NumRoundingModes]; + int captured_sse_mode = SseModes[id % NumSseModes]; + for( int k = 0; k < NumSseModes; ++k ) { + int sse_mode = SseModes[(k + id) % NumSseModes]; + SetSseMode( sse_mode ); + for( int i = 0; i < NumRoundingModes; ++i ) { + int mode = RoundingModes[(i + id) % NumRoundingModes]; + SetRoundingMode( mode ); + tbb::parallel_for( 0, N, 1, RoundingModeCheckBody(tid, mode, captured_mode, sse_mode, captured_sse_mode) ); + ASSERT( GetRoundingMode() == mode, NULL ); + } + } + } +}; + +void TestFpuEnvPropagation () { + NativeParallelFor ( tbb::task_scheduler_init::default_num_threads() * NumRoundingModes, LauncherBody() ); +} + +void TestCpuCtlEnvApi () { + for( int k = 0; k < NumSseModes; ++k ) { + SetSseMode( SseModes[k] ); + for( int i = 0; i < NumRoundingModes; ++i ) { + SetRoundingMode( RoundingModes[i] ); + ASSERT( GetRoundingMode() == RoundingModes[i], NULL ); + ASSERT( GetSseMode() == SseModes[k], NULL ); + } + } +} + +int TestMain () { +#if defined(__TBB_CPU_CTL_ENV_PRESENT) && !__TBB_CPU_CTL_ENV_PRESENT + return Harness::Skipped; +#else + TestCpuCtlEnvApi(); + TestFpuEnvPropagation(); + return Harness::Done; +#endif +} diff --git a/src/tbb/src/test/test_function_node.cpp b/src/tbb/src/test/test_function_node.cpp new file mode 100644 index 0000000..33f29e1 --- /dev/null +++ b/src/tbb/src/test/test_function_node.cpp @@ -0,0 +1,437 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "harness_graph.h" + +#include "tbb/task_scheduler_init.h" +#include "tbb/spin_mutex.h" + +tbb::spin_mutex global_mutex; + +#define N 100 +#define MAX_NODES 4 + +//! Performs test on function nodes with limited concurrency and buffering +/** Theses tests check: + 1) that the number of executing copies never exceed the concurreny limit + 2) that the node never rejects + 3) that no items are lost + and 4) all of this happens even if there are multiple predecessors and successors +*/ + +template< typename InputType > +struct parallel_put_until_limit : private NoAssign { + + harness_counting_sender<InputType> *my_senders; + + parallel_put_until_limit( harness_counting_sender<InputType> *senders ) : my_senders(senders) {} + + void operator()( int i ) const { + if ( my_senders ) { + my_senders[i].try_put_until_limit(); + } + } + +}; + +template< typename InputType, typename OutputType, typename Body > +void buffered_levels( size_t concurrency, Body body ) { + + // Do for lc = 1 to concurrency level + for ( size_t lc = 1; lc <= concurrency; ++lc ) { + tbb::flow::graph g; + + // Set the execute_counter back to zero in the harness + harness_graph_executor<InputType, OutputType>::execute_count = 0; + // Set the max allowed executors to lc. There is a check in the functor to make sure this is never exceeded. + harness_graph_executor<InputType, OutputType>::max_executors = lc; + + // Create the function_node with the appropriate concurreny level, and use default buffering + tbb::flow::function_node< InputType, OutputType > exe_node( g, lc, body ); + + //Create a vector of identical exe_nodes + std::vector< tbb::flow::function_node< InputType, OutputType > > exe_vec(2, exe_node); + + for (size_t node_idx=0; node_idx<exe_vec.size(); ++node_idx) { + // For num_receivers = 1 to MAX_NODES + for (size_t num_receivers = 1; num_receivers <= MAX_NODES; ++num_receivers ) { + // Create num_receivers counting receivers and connect the exe_vec[node_idx] to them. + harness_mapped_receiver<OutputType> *receivers = new harness_mapped_receiver<OutputType>[num_receivers]; + for (size_t r = 0; r < num_receivers; ++r ) { + tbb::flow::make_edge( exe_vec[node_idx], receivers[r] ); + } + + // Do the test with varying numbers of senders + harness_counting_sender<InputType> *senders = NULL; + for (size_t num_senders = 1; num_senders <= MAX_NODES; ++num_senders ) { + // Create num_senders senders, set there message limit each to N, and connect them to the exe_vec[node_idx] + senders = new harness_counting_sender<InputType>[num_senders]; + for (size_t s = 0; s < num_senders; ++s ) { + senders[s].my_limit = N; + tbb::flow::make_edge( senders[s], exe_vec[node_idx] ); + } + + // Initialize the receivers so they know how many senders and messages to check for + for (size_t r = 0; r < num_receivers; ++r ) { + receivers[r].initialize_map( N, num_senders ); + } + + // Do the test + NativeParallelFor( (int)num_senders, parallel_put_until_limit<InputType>(senders) ); + g.wait_for_all(); + + // cofirm that each sender was requested from N times + for (size_t s = 0; s < num_senders; ++s ) { + size_t n = senders[s].my_received; + ASSERT( n == N, NULL ); + ASSERT( senders[s].my_receiver == &exe_vec[node_idx], NULL ); + } + // validate the receivers + for (size_t r = 0; r < num_receivers; ++r ) { + receivers[r].validate(); + } + delete [] senders; + } + for (size_t r = 0; r < num_receivers; ++r ) { + tbb::flow::remove_edge( exe_vec[node_idx], receivers[r] ); + } + ASSERT( exe_vec[node_idx].try_put( InputType() ) == true, NULL ); + g.wait_for_all(); + for (size_t r = 0; r < num_receivers; ++r ) { + // since it's detached, nothing should have changed + receivers[r].validate(); + } + delete [] receivers; + } + } + } +} + +const size_t Offset = 123; +tbb::atomic<size_t> global_execute_count; + +struct inc_functor { + + tbb::atomic<size_t> local_execute_count; + inc_functor( ) { local_execute_count = 0; } + inc_functor( const inc_functor &f ) { local_execute_count = f.local_execute_count; } + + int operator()( int i ) { + ++global_execute_count; + ++local_execute_count; + return i; + } + +}; + +template< typename InputType, typename OutputType > +void buffered_levels_with_copy( size_t concurrency ) { + + // Do for lc = 1 to concurrency level + for ( size_t lc = 1; lc <= concurrency; ++lc ) { + tbb::flow::graph g; + + inc_functor cf; + cf.local_execute_count = Offset; + global_execute_count = Offset; + + tbb::flow::function_node< InputType, OutputType > exe_node( g, lc, cf ); + + for (size_t num_receivers = 1; num_receivers <= MAX_NODES; ++num_receivers ) { + harness_mapped_receiver<OutputType> *receivers = new harness_mapped_receiver<OutputType>[num_receivers]; + for (size_t r = 0; r < num_receivers; ++r ) { + tbb::flow::make_edge( exe_node, receivers[r] ); + } + + harness_counting_sender<InputType> *senders = NULL; + for (size_t num_senders = 1; num_senders <= MAX_NODES; ++num_senders ) { + senders = new harness_counting_sender<InputType>[num_senders]; + for (size_t s = 0; s < num_senders; ++s ) { + senders[s].my_limit = N; + tbb::flow::make_edge( senders[s], exe_node ); + } + + for (size_t r = 0; r < num_receivers; ++r ) { + receivers[r].initialize_map( N, num_senders ); + } + + NativeParallelFor( (int)num_senders, parallel_put_until_limit<InputType>(senders) ); + g.wait_for_all(); + + for (size_t s = 0; s < num_senders; ++s ) { + size_t n = senders[s].my_received; + ASSERT( n == N, NULL ); + ASSERT( senders[s].my_receiver == &exe_node, NULL ); + } + for (size_t r = 0; r < num_receivers; ++r ) { + receivers[r].validate(); + } + delete [] senders; + } + for (size_t r = 0; r < num_receivers; ++r ) { + tbb::flow::remove_edge( exe_node, receivers[r] ); + } + ASSERT( exe_node.try_put( InputType() ) == true, NULL ); + g.wait_for_all(); + for (size_t r = 0; r < num_receivers; ++r ) { + receivers[r].validate(); + } + delete [] receivers; + } + + // validate that the local body matches the global execute_count and both are correct + inc_functor body_copy = tbb::flow::copy_body<inc_functor>( exe_node ); + const size_t expected_count = N/2 * MAX_NODES * MAX_NODES * ( MAX_NODES + 1 ) + MAX_NODES + Offset; + size_t global_count = global_execute_count; + size_t inc_count = body_copy.local_execute_count; + ASSERT( global_count == expected_count && global_count == inc_count, NULL ); + } +} + +template< typename InputType, typename OutputType > +void run_buffered_levels( int c ) { + harness_graph_executor<InputType, OutputType, tbb::spin_mutex>::max_executors = c; + #if __TBB_LAMBDAS_PRESENT + buffered_levels<InputType,OutputType>( c, []( InputType i ) -> OutputType { return harness_graph_executor<InputType, OutputType, tbb::spin_mutex>::func(i); } ); + #endif + buffered_levels<InputType,OutputType>( c, &harness_graph_executor<InputType, OutputType, tbb::spin_mutex>::func ); + buffered_levels<InputType,OutputType>( c, typename harness_graph_executor<InputType, OutputType, tbb::spin_mutex>::functor() ); + buffered_levels_with_copy<InputType,OutputType>( c ); +} + + +//! Performs test on executable nodes with limited concurrency +/** Theses tests check: + 1) that the nodes will accepts puts up to the concurrency limit, + 2) the nodes do not exceed the concurrency limit even when run with more threads (this is checked in the harness_graph_executor), + 3) the nodes will receive puts from multiple successors simultaneously, + and 4) the nodes will send to multiple predecessors. + There is no checking of the contents of the messages for corruption. +*/ + +template< typename InputType, typename OutputType, typename Body > +void concurrency_levels( size_t concurrency, Body body ) { + + for ( size_t lc = 1; lc <= concurrency; ++lc ) { + tbb::flow::graph g; + harness_graph_executor<InputType, OutputType, tbb::spin_mutex>::execute_count = 0; + + tbb::flow::function_node< InputType, OutputType, tbb::flow::rejecting > exe_node( g, lc, body ); + + for (size_t num_receivers = 1; num_receivers <= MAX_NODES; ++num_receivers ) { + + harness_counting_receiver<OutputType> *receivers = new harness_counting_receiver<OutputType>[num_receivers]; + + for (size_t r = 0; r < num_receivers; ++r ) { + tbb::flow::make_edge( exe_node, receivers[r] ); + } + + harness_counting_sender<InputType> *senders = NULL; + + for (size_t num_senders = 1; num_senders <= MAX_NODES; ++num_senders ) { + { + // lock m to prevent exe_node from finishing + tbb::spin_mutex::scoped_lock l( harness_graph_executor< InputType, OutputType, tbb::spin_mutex >::mutex ); + + // put to lc level, it will accept and then block at m + for ( size_t c = 0 ; c < lc ; ++c ) { + ASSERT( exe_node.try_put( InputType() ) == true, NULL ); + } + // it only accepts to lc level + ASSERT( exe_node.try_put( InputType() ) == false, NULL ); + + senders = new harness_counting_sender<InputType>[num_senders]; + for (size_t s = 0; s < num_senders; ++s ) { + // register a sender + senders[s].my_limit = N; + exe_node.register_predecessor( senders[s] ); + } + + } // release lock at end of scope, setting the exe node free to continue + // wait for graph to settle down + g.wait_for_all(); + + // cofirm that each sender was requested from N times + for (size_t s = 0; s < num_senders; ++s ) { + size_t n = senders[s].my_received; + ASSERT( n == N, NULL ); + ASSERT( senders[s].my_receiver == &exe_node, NULL ); + } + // cofirm that each receivers got N * num_senders + the initial lc puts + for (size_t r = 0; r < num_receivers; ++r ) { + size_t n = receivers[r].my_count; + ASSERT( n == num_senders*N+lc, NULL ); + receivers[r].my_count = 0; + } + delete [] senders; + } + for (size_t r = 0; r < num_receivers; ++r ) { + tbb::flow::remove_edge( exe_node, receivers[r] ); + } + ASSERT( exe_node.try_put( InputType() ) == true, NULL ); + g.wait_for_all(); + for (size_t r = 0; r < num_receivers; ++r ) { + ASSERT( int(receivers[r].my_count) == 0, NULL ); + } + delete [] receivers; + } + + } +} + +template< typename InputType, typename OutputType > +void run_concurrency_levels( int c ) { + harness_graph_executor<InputType, OutputType, tbb::spin_mutex>::max_executors = c; + #if __TBB_LAMBDAS_PRESENT + concurrency_levels<InputType,OutputType>( c, []( InputType i ) -> OutputType { return harness_graph_executor<InputType, OutputType, tbb::spin_mutex>::func(i); } ); + #endif + concurrency_levels<InputType,OutputType>( c, &harness_graph_executor<InputType, OutputType, tbb::spin_mutex>::func ); + concurrency_levels<InputType,OutputType>( c, typename harness_graph_executor<InputType, OutputType, tbb::spin_mutex>::functor() ); +} + + +struct empty_no_assign { + empty_no_assign() {} + empty_no_assign( int ) {} + operator int() { return 0; } +}; + +template< typename InputType > +struct parallel_puts : private NoAssign { + + tbb::flow::receiver< InputType > * const my_exe_node; + + parallel_puts( tbb::flow::receiver< InputType > &exe_node ) : my_exe_node(&exe_node) {} + + void operator()( int ) const { + for ( int i = 0; i < N; ++i ) { + // the nodes will accept all puts + ASSERT( my_exe_node->try_put( InputType() ) == true, NULL ); + } + } + +}; + +//! Performs test on executable nodes with unlimited concurrency +/** Theses tests check: + 1) that the nodes will accept all puts + 2) the nodes will receive puts from multiple predecessors simultaneously, + and 3) the nodes will send to multiple successors. + There is no checking of the contents of the messages for corruption. +*/ + +template< typename InputType, typename OutputType, typename Body > +void unlimited_concurrency( Body body ) { + + for (int p = 1; p < 2*MaxThread; ++p) { + tbb::flow::graph g; + tbb::flow::function_node< InputType, OutputType, tbb::flow::rejecting > exe_node( g, tbb::flow::unlimited, body ); + + for (size_t num_receivers = 1; num_receivers <= MAX_NODES; ++num_receivers ) { + + harness_counting_receiver<OutputType> *receivers = new harness_counting_receiver<OutputType>[num_receivers]; + harness_graph_executor<InputType, OutputType>::execute_count = 0; + + for (size_t r = 0; r < num_receivers; ++r ) { + tbb::flow::make_edge( exe_node, receivers[r] ); + } + + NativeParallelFor( p, parallel_puts<InputType>(exe_node) ); + g.wait_for_all(); + + // 2) the nodes will receive puts from multiple predecessors simultaneously, + size_t ec = harness_graph_executor<InputType, OutputType>::execute_count; + ASSERT( (int)ec == p*N, NULL ); + for (size_t r = 0; r < num_receivers; ++r ) { + size_t c = receivers[r].my_count; + // 3) the nodes will send to multiple successors. + ASSERT( (int)c == p*N, NULL ); + } + } + } +} + +template< typename InputType, typename OutputType > +void run_unlimited_concurrency() { + harness_graph_executor<InputType, OutputType>::max_executors = 0; + #if __TBB_LAMBDAS_PRESENT + unlimited_concurrency<InputType,OutputType>( []( InputType i ) -> OutputType { return harness_graph_executor<InputType, OutputType>::func(i); } ); + #endif + unlimited_concurrency<InputType,OutputType>( &harness_graph_executor<InputType, OutputType>::func ); + unlimited_concurrency<InputType,OutputType>( typename harness_graph_executor<InputType, OutputType>::functor() ); +} + +struct continue_msg_to_int : private NoAssign { + int my_int; + continue_msg_to_int(int x) : my_int(x) {} + int operator()(tbb::flow::continue_msg) { return my_int; } +}; + +void test_function_node_with_continue_msg_as_input() { + // If this function terminates, then this test is successful + tbb::flow::graph g; + + tbb::flow::broadcast_node<tbb::flow::continue_msg> Start(g); + + tbb::flow::function_node<tbb::flow::continue_msg, int, tbb::flow::rejecting> FN1( g, tbb::flow::serial, continue_msg_to_int(42)); + tbb::flow::function_node<tbb::flow::continue_msg, int, tbb::flow::rejecting> FN2( g, tbb::flow::serial, continue_msg_to_int(43)); + + tbb::flow::make_edge( Start, FN1 ); + tbb::flow::make_edge( Start, FN2 ); + + Start.try_put( tbb::flow::continue_msg() ); + g.wait_for_all(); +} + +//! Tests limited concurrency cases for nodes that accept data messages +void test_concurrency(int num_threads) { + tbb::task_scheduler_init init(num_threads); + run_concurrency_levels<int,int>(num_threads); + run_concurrency_levels<int,tbb::flow::continue_msg>(num_threads); + run_buffered_levels<int, int>(num_threads); + run_unlimited_concurrency<int,int>(); + run_unlimited_concurrency<int,empty_no_assign>(); + run_unlimited_concurrency<empty_no_assign,int>(); + run_unlimited_concurrency<empty_no_assign,empty_no_assign>(); + run_unlimited_concurrency<int,tbb::flow::continue_msg>(); + run_unlimited_concurrency<empty_no_assign,tbb::flow::continue_msg>(); + test_function_node_with_continue_msg_as_input(); +} + +int TestMain() { + current_executors = 0; + if( MinThread<1 ) { + REPORT("number of threads must be positive\n"); + exit(1); + } + for( int p=MinThread; p<=MaxThread; ++p ) { + test_concurrency(p); + } + return Harness::Done; +} + diff --git a/src/tbb/src/test/test_halt.cpp b/src/tbb/src/test/test_halt.cpp new file mode 100644 index 0000000..69fabf5 --- /dev/null +++ b/src/tbb/src/test/test_halt.cpp @@ -0,0 +1,117 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include <cstdio> +#include <cstdlib> +#include <cassert> +#include <utility> +#include "tbb/task.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/tick_count.h" +#include "tbb/parallel_for.h" +#include "tbb/blocked_range.h" +#include "tbb/mutex.h" +#include "tbb/spin_mutex.h" +#include "tbb/queuing_mutex.h" +#include "harness.h" + +using namespace std; +using namespace tbb; + +///////////////////// Parallel methods //////////////////////// + +// *** Serial shared by mutexes *** // +int SharedI = 1, SharedN; +template<typename M> +class SharedSerialFibBody: NoAssign { + M &mutex; +public: + SharedSerialFibBody( M &m ) : mutex( m ) {} + //! main loop + void operator()( const blocked_range<int>& /*range*/ ) const { + for(;;) { + typename M::scoped_lock lock( mutex ); + if(SharedI >= SharedN) break; + volatile double sum = 7.3; + sum *= 11.17; + ++SharedI; + } + } +}; + +//! Root function +template<class M> +void SharedSerialFib(int n) +{ + SharedI = 1; + SharedN = n; + M mutex; + parallel_for( blocked_range<int>(0,4,1), SharedSerialFibBody<M>( mutex ) ); +} + +/////////////////////////// Main //////////////////////////////////////////////////// + +double Tsum = 0; int Tnum = 0; + +typedef void (*MeasureFunc)(int); +//! Measure ticks count in loop [2..n] +void Measure(const char *name, MeasureFunc func, int n) +{ + tick_count t0; + tick_count::interval_t T; + REMARK("%s",name); + t0 = tick_count::now(); + for(int number = 2; number <= n; number++) + func(number); + T = tick_count::now() - t0; + double avg = Tnum? Tsum/Tnum : 1; + if (avg == 0.0) avg = 1; + if(avg * 100 < T.seconds()) { + REPORT("Warning: halting detected (%g sec, av: %g)\n", T.seconds(), avg); + ASSERT(avg * 1000 > T.seconds(), "Too long halting period"); + } else { + Tsum += T.seconds(); Tnum++; + } + REMARK("\t- in %f msec\n", T.seconds()*1000); +} + +int TestMain () { + MinThread = max(2, MinThread); + int NumbersCount = 100; + short recycle = 100; + do { + for(int threads = MinThread; threads <= MaxThread; threads++) { + task_scheduler_init scheduler_init(threads); + REMARK("Threads number is %d\t", threads); + Measure("Shared serial (wrapper mutex)\t", SharedSerialFib<mutex>, NumbersCount); + //sum = Measure("Shared serial (spin_mutex)", SharedSerialFib<tbb::spin_mutex>, NumbersCount); + //sum = Measure("Shared serial (queuing_mutex)", SharedSerialFib<tbb::queuing_mutex>, NumbersCount); + } + } while(--recycle); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_handle_perror.cpp b/src/tbb/src/test/test_handle_perror.cpp new file mode 100644 index 0000000..6f86fa5 --- /dev/null +++ b/src/tbb/src/test/test_handle_perror.cpp @@ -0,0 +1,77 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Program for basic correctness of handle_perror, which is internal +// to the TBB shared library. + +#include <cerrno> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include <stdexcept> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +#include "../tbb/tbb_misc.h" +#include "harness.h" + +#if TBB_USE_EXCEPTIONS + +static void TestHandlePerror() { + bool caught = false; + try { + tbb::internal::handle_perror( EAGAIN, "apple" ); + } catch( std::runtime_error& e ) { +#if TBB_USE_EXCEPTIONS + REMARK("caught runtime_exception('%s')\n",e.what()); + ASSERT( memcmp(e.what(),"apple: ",7)==0, NULL ); + ASSERT( strstr(e.what(),"unavailable")!=NULL, "bad error message?" ); +#endif /* TBB_USE_EXCEPTIONS */ + caught = true; + } + ASSERT(caught,NULL); +} + +int TestMain () { + TestHandlePerror(); + return Harness::Done; +} + +#else /* !TBB_USE_EXCEPTIONS */ + +int TestMain () { + return Harness::Skipped; +} + +#endif /* TBB_USE_EXCEPTIONS */ diff --git a/src/tbb/src/test/test_hw_concurrency.cpp b/src/tbb/src/test/test_hw_concurrency.cpp new file mode 100644 index 0000000..4e971b9 --- /dev/null +++ b/src/tbb/src/test/test_hw_concurrency.cpp @@ -0,0 +1,104 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "harness.h" + +#include <limits.h> + +#if _WIN32||_WIN64 +#include "tbb/machine/windows_api.h" +#elif __linux__ +#include <unistd.h> +#include <sys/sysinfo.h> +#include <string.h> +#include <sched.h> +#elif __FreeBSD__ +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <sys/param.h> // Required by <sys/cpuset.h> +#include <sys/cpuset.h> +#endif + +#include "tbb/task_scheduler_init.h" +#include "tbb/tbb_thread.h" +#include "tbb/enumerable_thread_specific.h" + +// The declaration of a global ETS object is needed to check that +// it does not initialize the task scheduler, and in particular +// does not set the default thread number. TODO: add other objects +// that should not initialize the scheduler. +tbb::enumerable_thread_specific<std::size_t> ets; + +int TestMain () { +#if _WIN32||_WIN64 || __linux__ || __FreeBSD_version >= 701000 +#if _WIN32||_WIN64 + SYSTEM_INFO si; + GetSystemInfo(&si); + if ( si.dwNumberOfProcessors < 2 ) + return Harness::Skipped; + int availableProcs = (int)si.dwNumberOfProcessors / 2; + DWORD_PTR mask = 1; + for ( int i = 1; i < availableProcs; ++i ) + mask |= mask << 1; + bool err = !SetProcessAffinityMask( GetCurrentProcess(), mask ); +#else /* !WIN */ +#if __linux__ + int maxProcs = get_nprocs(); + typedef cpu_set_t mask_t; +#if __TBB_MAIN_THREAD_AFFINITY_BROKEN + #define setaffinity(mask) sched_setaffinity(0 /*get the mask of the calling thread*/, sizeof(mask_t), &mask) +#else + #define setaffinity(mask) sched_setaffinity(getpid(), sizeof(mask_t), &mask) +#endif +#else /* __FreeBSD__ */ + int maxProcs = sysconf(_SC_NPROCESSORS_ONLN); + typedef cpuset_t mask_t; +#if __TBB_MAIN_THREAD_AFFINITY_BROKEN + #define setaffinity(mask) cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(mask_t), &mask) +#else + #define setaffinity(mask) cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(mask_t), &mask) +#endif +#endif /* __FreeBSD__ */ + if ( maxProcs < 2 ) + return Harness::Skipped; + mask_t newMask; + CPU_ZERO(&newMask); + int availableProcs = min(maxProcs, (int)sizeof(mask_t) * CHAR_BIT) / 2; + for ( int i = 0; i < availableProcs; ++i ) + CPU_SET( i, &newMask ); + int err = setaffinity( newMask ); +#endif /* !WIN */ + ASSERT( !err, "Setting process affinity failed" ); + ASSERT( tbb::task_scheduler_init::default_num_threads() == availableProcs, NULL ); + ASSERT( (int)tbb::tbb_thread::hardware_concurrency() == availableProcs, NULL ); + return Harness::Done; +#else /* !(WIN || LIN || BSD) */ + return Harness::Skipped; +#endif /* !(WIN || LIN || BSD) */ +} diff --git a/src/tbb/src/test/test_inits_loop.cpp b/src/tbb/src/test/test_inits_loop.cpp new file mode 100644 index 0000000..c5a46c9 --- /dev/null +++ b/src/tbb/src/test/test_inits_loop.cpp @@ -0,0 +1,102 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if __APPLE__ + +#define HARNESS_CUSTOM_MAIN 1 +#include "harness.h" +#include <cstdlib> +#include "tbb/task_scheduler_init.h" + +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#include <signal.h> +#include <errno.h> + +bool exec_test(const char *self) { + int status = 1; + pid_t p = fork(); + if(p < 0) { + REPORT("fork error: errno=%d: %s\n", errno, strerror(errno)); + return true; + } + else if(p) { // parent + if(waitpid(p, &status, 0) != p) { + REPORT("wait error: errno=%d: %s\n", errno, strerror(errno)); + return true; + } + if(WIFEXITED(status)) { + if(!WEXITSTATUS(status)) return false; // ok + else REPORT("child has exited with return code 0x%x\n", WEXITSTATUS(status)); + } else { + REPORT("child error 0x%x:%s%s ", status, WIFSIGNALED(status)?" signalled":"", + WIFSTOPPED(status)?" stopped":""); + if(WIFSIGNALED(status)) + REPORT("%s%s", sys_siglist[WTERMSIG(status)], WCOREDUMP(status)?" core dumped":""); + if(WIFSTOPPED(status)) + REPORT("with %d stop-code", WSTOPSIG(status)); + REPORT("\n"); + } + } + else { // child + // reproduces error much often + execl(self, self, "0", NULL); + REPORT("exec fails %s: %d: %s\n", self, errno, strerror(errno)); + exit(2); + } + return true; +} + +HARNESS_EXPORT +int main( int argc, char * argv[] ) { + MinThread = 3000; + ParseCommandLine( argc, argv ); + if( MinThread <= 0 ) { + tbb::task_scheduler_init init( 2 ); // even number required for an error + } else { + for(int i = 0; i<MinThread; i++) { + if(exec_test(argv[0])) { + REPORT("ERROR: execution fails at %d-th iteration!\n", i); + exit(1); + } + } + REPORT("done\n"); + } +} + +#else /* !__APPLE__ */ + +#define HARNESS_NO_PARSE_COMMAND_LINE 1 +#include "harness.h" + +int TestMain () { + return Harness::Skipped; +} + +#endif /* !__APPLE__ */ diff --git a/src/tbb/src/test/test_intrusive_list.cpp b/src/tbb/src/test/test_intrusive_list.cpp new file mode 100644 index 0000000..8c48fc5 --- /dev/null +++ b/src/tbb/src/test/test_intrusive_list.cpp @@ -0,0 +1,149 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#define HARNESS_NO_PARSE_COMMAND_LINE 1 +#include "harness.h" + +#include "../tbb/intrusive_list.h" + +using tbb::internal::intrusive_list_node; + +// Machine word filled with repeated pattern of FC bits +const uintptr_t NoliMeTangere = ~uintptr_t(0)/0xFF*0xFC; + +struct VerificationBase : Harness::NoAfterlife { + uintptr_t m_Canary; + VerificationBase () : m_Canary(NoliMeTangere) {} +}; + +struct DataItemWithInheritedNodeBase : intrusive_list_node { + int m_Data; +public: + DataItemWithInheritedNodeBase ( int value ) : m_Data(value) {} + + int Data() const { return m_Data; } +}; + +class DataItemWithInheritedNode : public VerificationBase, public DataItemWithInheritedNodeBase { + friend class tbb::internal::intrusive_list<DataItemWithInheritedNode>; +public: + DataItemWithInheritedNode ( int value ) : DataItemWithInheritedNodeBase(value) {} +}; + +struct DataItemWithMemberNodeBase { + int m_Data; +public: + // Cannot be used by member_intrusive_list to form lists of objects derived from DataItemBase + intrusive_list_node m_BaseNode; + + DataItemWithMemberNodeBase ( int value ) : m_Data(value) {} + + int Data() const { return m_Data; } +}; + +class DataItemWithMemberNodes : public VerificationBase, public DataItemWithMemberNodeBase { +public: + intrusive_list_node m_Node; + + DataItemWithMemberNodes ( int value ) : DataItemWithMemberNodeBase(value) {} +}; + +typedef tbb::internal::intrusive_list<DataItemWithInheritedNode> IntrusiveList1; +typedef tbb::internal::memptr_intrusive_list<DataItemWithMemberNodes, + DataItemWithMemberNodeBase, &DataItemWithMemberNodeBase::m_BaseNode> IntrusiveList2; +typedef tbb::internal::memptr_intrusive_list<DataItemWithMemberNodes, + DataItemWithMemberNodes, &DataItemWithMemberNodes::m_Node> IntrusiveList3; + +const int NumElements = 256 * 1024; + +//! Iterates through the list forward and backward checking the validity of values stored by the list nodes +template<class List, class Iterator> +void CheckListNodes ( List& il, int valueStep ) { + int i; + Iterator it = il.begin(); + for ( i = valueStep - 1; it != il.end(); ++it, i += valueStep ) { + ASSERT( it->Data() == i, "Unexpected node value while iterating forward" ); + ASSERT( (*it).m_Canary == NoliMeTangere, "Memory corruption" ); + } + ASSERT( i == NumElements + valueStep - 1, "Wrong number of list elements while iterating forward" ); + it = il.end(); + for ( i = NumElements - 1, it--; it != il.end(); --it, i -= valueStep ) { + ASSERT( (*it).Data() == i, "Unexpected node value while iterating backward" ); + ASSERT( it->m_Canary == NoliMeTangere, "Memory corruption" ); + } + ASSERT( i == -1, "Wrong number of list elements while iterating backward" ); +} + +template<class List, class Item> +void TestListOperations () { + typedef typename List::iterator iterator; + List il; + for ( int i = NumElements - 1; i >= 0; --i ) + il.push_front( *new Item(i) ); + CheckListNodes<const List, typename List::const_iterator>( il, 1 ); + iterator it = il.begin(); + for ( ; it != il.end(); ++it ) { + Item &item = *it; + it = il.erase( it ); + delete &item; + } + CheckListNodes<List, iterator>( il, 2 ); + for ( it = il.begin(); it != il.end(); ++it ) { + Item &item = *it; + il.remove( *it++ ); + delete &item; + } + CheckListNodes<List, iterator>( il, 4 ); +} + +#include "harness_bad_expr.h" + +template<class List, class Item> +void TestListAssertions () { +#if TRY_BAD_EXPR_ENABLED + tbb::set_assertion_handler( AssertionFailureHandler ); + List il1, il2; + Item n1(1), n2(2), n3(3); + il1.push_front(n1); + TRY_BAD_EXPR( il2.push_front(n1), "only one intrusive list" ); + TRY_BAD_EXPR( il1.push_front(n1), "only one intrusive list" ); + il2.push_front(n2); + TRY_BAD_EXPR( il1.remove(n3), "not in the list" ); + tbb::set_assertion_handler( NULL ); +#endif /* TRY_BAD_EXPR_ENABLED */ +} + +int TestMain () { + TestListOperations<IntrusiveList1, DataItemWithInheritedNode>(); + TestListOperations<IntrusiveList2, DataItemWithMemberNodes>(); + TestListOperations<IntrusiveList3, DataItemWithMemberNodes>(); + TestListAssertions<IntrusiveList1, DataItemWithInheritedNode>(); + TestListAssertions<IntrusiveList2, DataItemWithMemberNodes>(); + TestListAssertions<IntrusiveList3, DataItemWithMemberNodes>(); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_ittnotify.cpp b/src/tbb/src/test/test_ittnotify.cpp new file mode 100644 index 0000000..79f4ae8 --- /dev/null +++ b/src/tbb/src/test/test_ittnotify.cpp @@ -0,0 +1,98 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if !TBB_USE_THREADING_TOOLS + #define TBB_USE_THREADING_TOOLS 1 +#endif + +#include "harness.h" + +#if DO_ITT_NOTIFY + +#include "tbb/spin_mutex.h" +#include "tbb/spin_rw_mutex.h" +#include "tbb/queuing_rw_mutex.h" +#include "tbb/queuing_mutex.h" +#include "tbb/mutex.h" +#include "tbb/recursive_mutex.h" +#include "tbb/parallel_for.h" +#include "tbb/blocked_range.h" +#include "tbb/task_scheduler_init.h" + + +#include "../tbb/itt_notify.h" + + +template<typename M> +class WorkEmulator: NoAssign { + M& m_mutex; + static volatile size_t s_anchor; +public: + void operator()( tbb::blocked_range<size_t>& range ) const { + for( size_t i=range.begin(); i!=range.end(); ++i ) { + typename M::scoped_lock lock(m_mutex); + for ( size_t j = 0; j!=range.end(); ++j ) + s_anchor = (s_anchor - i) / 2 + (s_anchor + j) / 2; + } + } + WorkEmulator( M& mutex ) : m_mutex(mutex) {} +}; + +template<typename M> +volatile size_t WorkEmulator<M>::s_anchor = 0; + + +template<class M> +void Test( const char * name ) { + REMARK("%s time = ",name); + M mtx; + tbb::profiling::set_name(mtx, name); + + const int n = 10000; + tbb::parallel_for( tbb::blocked_range<size_t>(0,n,n/100), WorkEmulator<M>(mtx) ); +} + + #define TEST_MUTEX(type, name) Test<tbb::type>( name ) + +#endif /* !DO_ITT_NOTIFY */ + +int TestMain () { +#if DO_ITT_NOTIFY + for( int p=MinThread; p<=MaxThread; ++p ) { + REMARK( "testing with %d workers\n", p ); + tbb::task_scheduler_init init( p ); + TEST_MUTEX( spin_mutex, "Spin Mutex" ); + TEST_MUTEX( queuing_mutex, "Queuing Mutex" ); + TEST_MUTEX( queuing_rw_mutex, "Queuing RW Mutex" ); + TEST_MUTEX( spin_rw_mutex, "Spin RW Mutex" ); + } + return Harness::Done; +#else /* !DO_ITT_NOTIFY */ + return Harness::Skipped; +#endif /* !DO_ITT_NOTIFY */ +} diff --git a/src/tbb/src/test/test_join_node.cpp b/src/tbb/src/test/test_join_node.cpp new file mode 100644 index 0000000..8d1c7e2 --- /dev/null +++ b/src/tbb/src/test/test_join_node.cpp @@ -0,0 +1,1254 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if _MSC_VER +// Name length is limited to avoid "decorated name length exceeded, name was truncated" warning. +#define _VARIADIC_MAX 8 +#endif + +#include "harness.h" + +#if !__SUNPRO_CC + +#include "tbb/flow_graph.h" +#include "tbb/task_scheduler_init.h" + +// the tuple-based tests with more inputs take a long time to compile. If changes +// are made to the tuple implementation or any switch that controls it, the test +// should be compiled with COMPREHENSIVE_TEST == 1 to ensure all tuple sizes are tested. +#ifndef COMPREHENSIVE_TEST +#define COMPREHENSIVE_TEST 0 +#endif + +// +// Tests +// + +const int Count = 150; +const int Recirc_count = 1000; // number of tuples to be generated +const int MaxPorts = 10; +const int MaxNSources = 5; // max # of source_nodes to register for each join_node input in parallel test +bool outputCheck[MaxPorts][Count]; // for checking output + +using tbb::flow::NO_TAG; + +void +check_outputCheck( int nUsed, int maxCnt) { + for(int i=0; i < nUsed; ++i) { + for( int j = 0; j < maxCnt; ++j) { + ASSERT(outputCheck[i][j], NULL); + } + } +} + +void +reset_outputCheck( int nUsed, int maxCnt) { + for(int i=0; i < nUsed; ++i) { + for( int j = 0; j < maxCnt; ++j) { + outputCheck[i][j] = false; + } + } +} + +template<typename T> +class name_of { +public: + static const char* name() { return "Unknown"; } +}; +template<> +class name_of<int> { +public: + static const char* name() { return "int"; } +}; +template<> +class name_of<float> { +public: + static const char* name() { return "float"; } +}; +template<> +class name_of<double> { +public: + static const char* name() { return "double"; } +}; +template<> +class name_of<long> { +public: + static const char* name() { return "long"; } +}; +template<> +class name_of<short> { +public: + static const char* name() { return "short"; } +}; + +// for recirculating tags, input is tuple<index,continue_msg> +// output is index*my_mult cast to the right type +template<typename TT> +class recirc_func_body { + TT my_mult; +public: + typedef std::tuple<int, tbb::flow::continue_msg> input_type; + recirc_func_body(TT multiplier ) : my_mult(multiplier) {} + recirc_func_body(const recirc_func_body &other) : my_mult(other.my_mult) { } + void operator=( const recirc_func_body &other) { my_mult = other.my_mult; } + TT operator()(const input_type &v) { + return TT(std::get<0>(v)) * my_mult; + } +}; + +static int input_count; // source_nodes are serial +static tbb::atomic<int> output_count; + +// emit input_count continue_msg +class recirc_source_node_body { +public: + bool operator()(tbb::flow::continue_msg &v ) { + --input_count; + v = tbb::flow::continue_msg(); + return 0 <= input_count; + } +}; + +// T must be arithmetic, and shouldn't wrap around for reasonable sizes of Count (which is now 150, and maxPorts is 10, +// so the max number generated right now is 1500 or so.) Source will generate a series of TT with value +// (init_val + (i-1)*addend) * my_mult, where i is the i-th invocation of the body. We are attaching addend +// source nodes to a join_port, and each will generate part of the numerical series the port is expecting +// to receive. If there is only one source node, the series order will be maintained; if more than one, +// this is not guaranteed. +template<typename TT> +class source_body { + const TT my_mult; + int my_count; + const int addend; + source_body& operator=( const source_body& other); +public: + source_body(TT multiplier, int init_val, int addto) : my_mult(multiplier), my_count(init_val), addend(addto) { } + bool operator()( TT &v) { + int lc = my_count; + v = my_mult * (TT)my_count; + my_count += addend; + return lc < Count; + } +}; + +template<typename TT> +class tag_func { + const TT my_mult; + tag_func& operator=( const tag_func& other); +public: + tag_func(TT multiplier) : my_mult(multiplier) { } + // operator() will return [0 .. Count) + tbb::flow::tag_value operator()( TT v) { + tbb::flow::tag_value t = tbb::flow::tag_value(v / my_mult); + return t; + } +}; + +// allocator for join_node. This is specialized for tag_matching joins because they require a variable number +// of tag_value methods passed to the constructor + +template<int N, typename JType, tbb::flow::graph_buffer_policy JP> +class makeJoin { +public: + static JType *create(tbb::flow::graph& g) { + JType *temp = new JType(g); + return temp; + } + static void destroy(JType *p) { delete p; } +}; + + +template<typename JType> +class makeJoin<2,JType,tbb::flow::tag_matching> { + typedef typename JType::output_type TType; + typedef typename std::tuple_element<0, TType>::type T0; + typedef typename std::tuple_element<1, TType>::type T1; +public: + static JType *create(tbb::flow::graph& g) { + JType *temp = new JType(g, + tag_func<T0>(T0(2)), + tag_func<T1>(T1(3)) + ); + return temp; + } + static void destroy(JType *p) { delete p; } +}; + +template<typename JType> +class makeJoin<3,JType,tbb::flow::tag_matching> { + typedef typename JType::output_type TType; + typedef typename std::tuple_element<0, TType>::type T0; + typedef typename std::tuple_element<1, TType>::type T1; + typedef typename std::tuple_element<2, TType>::type T2; +public: + static JType *create(tbb::flow::graph& g) { + JType *temp = new JType(g, + tag_func<T0>(T0(2)), + tag_func<T1>(T1(3)), + tag_func<T2>(T2(4)) + ); + return temp; + } + static void destroy(JType *p) { delete p; } +}; + +template<typename JType> +class makeJoin<4,JType,tbb::flow::tag_matching> { + typedef typename JType::output_type TType; + typedef typename std::tuple_element<0, TType>::type T0; + typedef typename std::tuple_element<1, TType>::type T1; + typedef typename std::tuple_element<2, TType>::type T2; + typedef typename std::tuple_element<3, TType>::type T3; +public: + static JType *create(tbb::flow::graph& g) { + JType *temp = new JType(g, + tag_func<T0>(T0(2)), + tag_func<T1>(T1(3)), + tag_func<T2>(T2(4)), + tag_func<T3>(T3(5)) + ); + return temp; + } + static void destroy(JType *p) { delete p; } +}; + +template<typename JType> +class makeJoin<5,JType,tbb::flow::tag_matching> { + typedef typename JType::output_type TType; + typedef typename std::tuple_element<0, TType>::type T0; + typedef typename std::tuple_element<1, TType>::type T1; + typedef typename std::tuple_element<2, TType>::type T2; + typedef typename std::tuple_element<3, TType>::type T3; + typedef typename std::tuple_element<4, TType>::type T4; +public: + static JType *create(tbb::flow::graph& g) { + JType *temp = new JType(g, + tag_func<T0>(T0(2)), + tag_func<T1>(T1(3)), + tag_func<T2>(T2(4)), + tag_func<T3>(T3(5)), + tag_func<T4>(T4(6)) + ); + return temp; + } + static void destroy(JType *p) { delete p; } +}; +#if __TBB_VARIADIC_MAX >= 6 +template<typename JType> +class makeJoin<6,JType,tbb::flow::tag_matching> { + typedef typename JType::output_type TType; + typedef typename std::tuple_element<0, TType>::type T0; + typedef typename std::tuple_element<1, TType>::type T1; + typedef typename std::tuple_element<2, TType>::type T2; + typedef typename std::tuple_element<3, TType>::type T3; + typedef typename std::tuple_element<4, TType>::type T4; + typedef typename std::tuple_element<5, TType>::type T5; +public: + static JType *create(tbb::flow::graph& g) { + JType *temp = new JType(g, + tag_func<T0>(T0(2)), + tag_func<T1>(T1(3)), + tag_func<T2>(T2(4)), + tag_func<T3>(T3(5)), + tag_func<T4>(T4(6)), + tag_func<T5>(T5(7)) + ); + return temp; + } + static void destroy(JType *p) { delete p; } +}; +#endif + +#if __TBB_VARIADIC_MAX >= 7 +template<typename JType> +class makeJoin<7,JType,tbb::flow::tag_matching> { + typedef typename JType::output_type TType; + typedef typename std::tuple_element<0, TType>::type T0; + typedef typename std::tuple_element<1, TType>::type T1; + typedef typename std::tuple_element<2, TType>::type T2; + typedef typename std::tuple_element<3, TType>::type T3; + typedef typename std::tuple_element<4, TType>::type T4; + typedef typename std::tuple_element<5, TType>::type T5; + typedef typename std::tuple_element<6, TType>::type T6; +public: + static JType *create(tbb::flow::graph& g) { + JType *temp = new JType(g, + tag_func<T0>(T0(2)), + tag_func<T1>(T1(3)), + tag_func<T2>(T2(4)), + tag_func<T3>(T3(5)), + tag_func<T4>(T4(6)), + tag_func<T5>(T5(7)), + tag_func<T6>(T6(8)) + ); + return temp; + } + static void destroy(JType *p) { delete p; } +}; +#endif + +#if __TBB_VARIADIC_MAX >= 8 +template<typename JType> +class makeJoin<8,JType,tbb::flow::tag_matching> { + typedef typename JType::output_type TType; + typedef typename std::tuple_element<0, TType>::type T0; + typedef typename std::tuple_element<1, TType>::type T1; + typedef typename std::tuple_element<2, TType>::type T2; + typedef typename std::tuple_element<3, TType>::type T3; + typedef typename std::tuple_element<4, TType>::type T4; + typedef typename std::tuple_element<5, TType>::type T5; + typedef typename std::tuple_element<6, TType>::type T6; + typedef typename std::tuple_element<7, TType>::type T7; +public: + static JType *create(tbb::flow::graph& g) { + JType *temp = new JType(g, + tag_func<T0>(T0(2)), + tag_func<T1>(T1(3)), + tag_func<T2>(T2(4)), + tag_func<T3>(T3(5)), + tag_func<T4>(T4(6)), + tag_func<T5>(T5(7)), + tag_func<T6>(T6(8)), + tag_func<T7>(T7(9)) + ); + return temp; + } + static void destroy(JType *p) { delete p; } +}; +#endif + +#if __TBB_VARIADIC_MAX >= 9 +template<typename JType> +class makeJoin<9,JType,tbb::flow::tag_matching> { + typedef typename JType::output_type TType; + typedef typename std::tuple_element<0, TType>::type T0; + typedef typename std::tuple_element<1, TType>::type T1; + typedef typename std::tuple_element<2, TType>::type T2; + typedef typename std::tuple_element<3, TType>::type T3; + typedef typename std::tuple_element<4, TType>::type T4; + typedef typename std::tuple_element<5, TType>::type T5; + typedef typename std::tuple_element<6, TType>::type T6; + typedef typename std::tuple_element<7, TType>::type T7; + typedef typename std::tuple_element<8, TType>::type T8; +public: + static JType *create(tbb::flow::graph& g) { + JType *temp = new JType(g, + tag_func<T0>(T0(2)), + tag_func<T1>(T1(3)), + tag_func<T2>(T2(4)), + tag_func<T3>(T3(5)), + tag_func<T4>(T4(6)), + tag_func<T5>(T5(7)), + tag_func<T6>(T6(8)), + tag_func<T7>(T7(9)), + tag_func<T8>(T8(10)) + ); + return temp; + } + static void destroy(JType *p) { delete p; } +}; +#endif + +#if __TBB_VARIADIC_MAX >= 10 +template<typename JType> +class makeJoin<10,JType,tbb::flow::tag_matching> { + typedef typename JType::output_type TType; + typedef typename std::tuple_element<0, TType>::type T0; + typedef typename std::tuple_element<1, TType>::type T1; + typedef typename std::tuple_element<2, TType>::type T2; + typedef typename std::tuple_element<3, TType>::type T3; + typedef typename std::tuple_element<4, TType>::type T4; + typedef typename std::tuple_element<5, TType>::type T5; + typedef typename std::tuple_element<6, TType>::type T6; + typedef typename std::tuple_element<7, TType>::type T7; + typedef typename std::tuple_element<8, TType>::type T8; + typedef typename std::tuple_element<9, TType>::type T9; +public: + static JType *create(tbb::flow::graph& g) { + JType *temp = new JType(g, + tag_func<T0>(T0(2)), + tag_func<T1>(T1(3)), + tag_func<T2>(T2(4)), + tag_func<T3>(T3(5)), + tag_func<T4>(T4(6)), + tag_func<T5>(T5(7)), + tag_func<T6>(T6(8)), + tag_func<T7>(T7(9)), + tag_func<T8>(T8(10)), + tag_func<T9>(T9(11)) + ); + return temp; + } + static void destroy(JType *p) { delete p; } +}; +#endif + +// holder for source_node pointers for eventual deletion + +static void* all_source_nodes[MaxPorts][MaxNSources]; + +template<int ELEM, typename JNT> +class source_node_helper { +public: + typedef JNT join_node_type; + typedef tbb::flow::join_node<std::tuple<int, tbb::flow::continue_msg>, tbb::flow::reserving> input_join_type; + typedef typename join_node_type::output_type TT; + typedef typename std::tuple_element<ELEM-1,TT>::type IT; + typedef typename tbb::flow::source_node<IT> my_source_node_type; + typedef typename tbb::flow::function_node<std::tuple<int,tbb::flow::continue_msg>, IT> my_recirc_function_type; + static void print_remark(const char * str) { + source_node_helper<ELEM-1,JNT>::print_remark(str); + REMARK(", %s", name_of<IT>::name()); + } + static void add_source_nodes(join_node_type &my_join, tbb::flow::graph &g, int nInputs) { + for(int i=0; i < nInputs; ++i) { + my_source_node_type *new_node = new my_source_node_type(g, source_body<IT>((IT)(ELEM+1), i, nInputs)); + tbb::flow::make_edge( *new_node, tbb::flow::input_port<ELEM-1>(my_join) ); + all_source_nodes[ELEM-1][i] = (void *)new_node; + } + // add the next source_node + source_node_helper<ELEM-1, JNT>::add_source_nodes(my_join, g, nInputs); + } + + static void add_recirc_func_nodes(join_node_type &my_join, input_join_type &my_input, tbb::flow::graph &g) { + my_recirc_function_type *new_node = new my_recirc_function_type(g, tbb::flow::unlimited, recirc_func_body<IT>((IT)(ELEM+1))); + tbb::flow::make_edge(*new_node, tbb::flow::input_port<ELEM-1>(my_join)); + tbb::flow::make_edge(my_input, *new_node); + all_source_nodes[ELEM-1][0] = (void *)new_node; + source_node_helper<ELEM-1, JNT>::add_recirc_func_nodes(my_join, my_input, g); + } + + static void only_check_value(const int i, const TT &v) { + ASSERT( std::get<ELEM-1>(v) == (IT)(i*(ELEM+1)), NULL); + source_node_helper<ELEM-1,JNT>::only_check_value(i, v); + } + + static void check_value(int i, TT &v, bool is_serial) { + // the fetched value will match only if there is only one source_node. + ASSERT(!is_serial || std::get<ELEM-1>(v) == (IT)(i*(ELEM+1)), NULL); + // tally the fetched value. + int ival = (int)std::get<ELEM-1>(v); + ASSERT(!(ival%(ELEM+1)), NULL); + ival /= (ELEM+1); + ASSERT(!outputCheck[ELEM-1][ival], NULL); + outputCheck[ELEM-1][ival] = true; + source_node_helper<ELEM-1,JNT>::check_value(i, v, is_serial); + } + static void remove_source_nodes(join_node_type& my_join, int nInputs) { + for(int i=0; i< nInputs; ++i) { + my_source_node_type *dp = reinterpret_cast<my_source_node_type *>(all_source_nodes[ELEM-1][i]); + tbb::flow::remove_edge( *dp, tbb::flow::input_port<ELEM-1>(my_join) ); + delete dp; + } + source_node_helper<ELEM-1, JNT>::remove_source_nodes(my_join, nInputs); + } + + static void remove_recirc_func_nodes(join_node_type& my_join, input_join_type &my_input) { + my_recirc_function_type *fn = reinterpret_cast<my_recirc_function_type *>(all_source_nodes[ELEM-1][0]); + tbb::flow::remove_edge( *fn, tbb::flow::input_port<ELEM-1>(my_join) ); + tbb::flow::remove_edge( my_input, *fn); + delete fn; + source_node_helper<ELEM-1, JNT>::remove_recirc_func_nodes(my_join,my_input); + } +}; + +template<typename JNT> +class source_node_helper<1, JNT> { + typedef JNT join_node_type; + typedef tbb::flow::join_node<std::tuple<int, tbb::flow::continue_msg>, tbb::flow::reserving> input_join_type; + typedef typename join_node_type::output_type TT; + typedef typename std::tuple_element<0,TT>::type IT; + typedef typename tbb::flow::source_node<IT> my_source_node_type; + typedef typename tbb::flow::function_node<std::tuple<int,tbb::flow::continue_msg>, IT> my_recirc_function_type; +public: + static void print_remark(const char * str) { + REMARK("%s< %s", str, name_of<IT>::name()); + } + static void add_source_nodes(join_node_type &my_join, tbb::flow::graph &g, int nInputs) { + for(int i=0; i < nInputs; ++i) { + my_source_node_type *new_node = new my_source_node_type(g, source_body<IT>((IT)2, i, nInputs)); + tbb::flow::make_edge( *new_node, tbb::flow::input_port<0>(my_join) ); + all_source_nodes[0][i] = (void *)new_node; + } + } + + static void add_recirc_func_nodes(join_node_type &my_join, input_join_type &my_input, tbb::flow::graph &g) { + my_recirc_function_type *new_node = new my_recirc_function_type(g, tbb::flow::unlimited, recirc_func_body<IT>((IT)(2))); + tbb::flow::make_edge(*new_node, tbb::flow::input_port<0>(my_join)); + tbb::flow::make_edge(my_input, *new_node); + all_source_nodes[0][0] = (void *)new_node; + } + + static void only_check_value(const int i, const TT &v) { + ASSERT( std::get<0>(v) == (IT)(i*2), NULL); + } + + static void check_value(int i, TT &v, bool is_serial) { + ASSERT(!is_serial || std::get<0>(v) == (IT)(i*(2)), NULL); + int ival = (int)std::get<0>(v); + ASSERT(!(ival%2), NULL); + ival /= 2; + ASSERT(!outputCheck[0][ival], NULL); + outputCheck[0][ival] = true; + } + static void remove_source_nodes(join_node_type& my_join, int nInputs) { + for(int i=0; i < nInputs; ++i) { + my_source_node_type *dp = reinterpret_cast<my_source_node_type *>(all_source_nodes[0][i]); + tbb::flow::remove_edge( *dp, tbb::flow::input_port<0>(my_join) ); + delete dp; + } + } + + static void remove_recirc_func_nodes(join_node_type& my_join, input_join_type &my_input) { + my_recirc_function_type *fn = reinterpret_cast<my_recirc_function_type *>(all_source_nodes[0][0]); + tbb::flow::remove_edge( *fn, tbb::flow::input_port<0>(my_join) ); + tbb::flow::remove_edge( my_input, *fn); + delete fn; + } +}; + +// get the tag from the output tuple and emit it. +// the first tuple component is tag * 2 cast to the type +template<typename OutputTupleType> +class recirc_output_func_body { +public: + // we only need this to use source_node_helper + typedef typename tbb::flow::join_node<OutputTupleType, tbb::flow::tag_matching> join_node_type; + static const int N = std::tuple_size<OutputTupleType>::value; + int operator()(const OutputTupleType &v) { + int out = int(std::get<0>(v)) / 2; + source_node_helper<N,join_node_type>::only_check_value(out,v); + ++output_count; + return out; + } +}; + +template<typename JType> +class tag_recirculation_test { +public: + typedef typename JType::output_type TType; + typedef typename std::tuple<int, tbb::flow::continue_msg> input_tuple_type; + typedef tbb::flow::join_node<input_tuple_type,tbb::flow::reserving> input_join_type; + static const int N = std::tuple_size<TType>::value; + static void test() { + source_node_helper<N,JType>::print_remark("Recirculation test of tag-matching join"); + REMARK(" >\n"); + for(int maxTag = 1; maxTag <10; maxTag *= 3) { + for(int i=0; i < N; ++i) all_source_nodes[i][0] = NULL; + + tbb::flow::graph g; + // this is the tag-matching join we're testing + JType * my_join = makeJoin<N,JType, tbb::flow::tag_matching>::create(g); + // source_node for continue messages + tbb::flow::source_node<tbb::flow::continue_msg> snode(g, recirc_source_node_body(), false); + // reserving join that matches recirculating tags with continue messages. + input_join_type * my_input_join = makeJoin<2,input_join_type,tbb::flow::reserving>::create(g); + // tbb::flow::make_edge(snode, tbb::flow::input_port<1>(*my_input_join)); + tbb::flow::make_edge(snode, std::get<1>(my_input_join->input_ports())); + // queue to hold the tags + tbb::flow::queue_node<int> tag_queue(g); + tbb::flow::make_edge(tag_queue, tbb::flow::input_port<0>(*my_input_join)); + // add all the function_nodes that are inputs to the tag-matching join + source_node_helper<N,JType>::add_recirc_func_nodes(*my_join, *my_input_join, g); + // add the function_node that accepts the output of the join and emits the int tag it was based on + tbb::flow::function_node<TType, int> recreate_tag(g, tbb::flow::unlimited, recirc_output_func_body<TType>()); + tbb::flow::make_edge(*my_join, recreate_tag); + // now the recirculating part (output back to the queue) + tbb::flow::make_edge(recreate_tag, tag_queue); + + // put the tags into the queue + for(int t = 1; t <= maxTag; ++t) tag_queue.try_put(t); + + input_count = Recirc_count; + output_count = 0; + + // start up the source node to get things going + snode.activate(); + + // wait for everything to stop + g.wait_for_all(); + + ASSERT(output_count == Recirc_count, "not all instances were received"); + + int j; + // grab the tags from the queue, record them + std::vector<bool> out_tally(maxTag, false); + for(int i = 0; i < maxTag; ++i) { + ASSERT(tag_queue.try_get(j), "not enough tags in queue"); + ASSERT(!out_tally.at(j-1), "duplicate tag from queue"); + out_tally[j-1] = true; + } + ASSERT(!tag_queue.try_get(j), "Extra tags in recirculation queue"); + + // deconstruct graph + source_node_helper<N, JType>::remove_recirc_func_nodes(*my_join, *my_input_join); + tbb::flow::remove_edge(*my_join, recreate_tag); + makeJoin<N,JType,tbb::flow::tag_matching>::destroy(my_join); + tbb::flow::remove_edge(tag_queue, tbb::flow::input_port<0>(*my_input_join)); + tbb::flow::remove_edge(snode, tbb::flow::input_port<1>(*my_input_join)); + makeJoin<2,input_join_type,tbb::flow::reserving>::destroy(my_input_join); + } + } +}; + +template<typename JType, tbb::flow::graph_buffer_policy JP> +class parallel_test { +public: + typedef typename JType::output_type TType; + static const int SIZE = std::tuple_size<TType>::value; + static const tbb::flow::graph_buffer_policy jp = JP; + static void test() { + TType v; + source_node_helper<SIZE,JType>::print_remark("Parallel test of join_node"); + REMARK(" >\n"); + for(int i=0; i < MaxPorts; ++i) { + for(int j=0; j < MaxNSources; ++j) { + all_source_nodes[i][j] = NULL; + } + } + for(int nInputs = 1; nInputs <= MaxNSources; ++nInputs) { + tbb::flow::graph g; + // JType my_join(g); + bool not_out_of_order = (nInputs == 1) && (jp != tbb::flow::tag_matching); + JType* my_join = makeJoin<SIZE,JType,JP>::create(g); + tbb::flow::queue_node<TType> outq1(g); + tbb::flow::queue_node<TType> outq2(g); + + tbb::flow::make_edge( *my_join, outq1 ); + tbb::flow::make_edge( *my_join, outq2 ); + + source_node_helper<SIZE, JType>::add_source_nodes((*my_join), g, nInputs); + + g.wait_for_all(); + + reset_outputCheck(SIZE, Count); + for(int i=0; i < Count; ++i) { + ASSERT(outq1.try_get(v), NULL); + source_node_helper<SIZE, JType>::check_value(i, v, not_out_of_order); + } + + check_outputCheck(SIZE, Count); + reset_outputCheck(SIZE, Count); + + for(int i=0; i < Count; i++) { + ASSERT(outq2.try_get(v), NULL);; + source_node_helper<SIZE, JType>::check_value(i, v, not_out_of_order); + } + check_outputCheck(SIZE, Count); + + ASSERT(!outq1.try_get(v), NULL); + ASSERT(!outq2.try_get(v), NULL); + + source_node_helper<SIZE, JType>::remove_source_nodes((*my_join), nInputs); + tbb::flow::remove_edge( *my_join, outq1 ); + tbb::flow::remove_edge( *my_join, outq2 ); + makeJoin<SIZE,JType,JP>::destroy(my_join); + } + } +}; + + +template<int ELEM, typename JType> +class serial_queue_helper { +public: + typedef typename JType::output_type TT; + typedef typename std::tuple_element<ELEM-1,TT>::type IT; + typedef typename tbb::flow::queue_node<IT> my_queue_node_type; + static void print_remark() { + serial_queue_helper<ELEM-1,JType>::print_remark(); + REMARK(", %s", name_of<IT>::name()); + } + static void add_queue_nodes(tbb::flow::graph &g, JType &my_join) { + serial_queue_helper<ELEM-1,JType>::add_queue_nodes(g, my_join); + my_queue_node_type *new_node = new my_queue_node_type(g); + tbb::flow::make_edge( *new_node, std::get<ELEM-1>(my_join.input_ports()) ); + all_source_nodes[ELEM-1][0] = (void *)new_node; + } + static void fill_one_queue(int maxVal) { + // fill queue to "left" of me + my_queue_node_type *qptr = reinterpret_cast<my_queue_node_type *>(all_source_nodes[ELEM-1][0]); + serial_queue_helper<ELEM-1,JType>::fill_one_queue(maxVal); + for(int i = 0; i < maxVal; ++i) { + ASSERT(qptr->try_put((IT)(i*(ELEM+1))), NULL); + } + } + static void put_one_queue_val(int myVal) { + // put this val to my "left". + serial_queue_helper<ELEM-1,JType>::put_one_queue_val(myVal); + my_queue_node_type *qptr = reinterpret_cast<my_queue_node_type *>(all_source_nodes[ELEM-1][0]); + ASSERT(qptr->try_put((IT)(myVal*(ELEM+1))), NULL); + } + static void check_queue_value(int i, TT &v) { + serial_queue_helper<ELEM-1,JType>::check_queue_value(i, v); + ASSERT( std::get<ELEM-1>(v) == (IT)(i * (ELEM+1)), NULL); + } + static void remove_queue_nodes(JType &my_join) { + my_queue_node_type *vptr = reinterpret_cast<my_queue_node_type *>(all_source_nodes[ELEM-1][0]); + tbb::flow::remove_edge( *vptr, std::get<ELEM-1>(my_join.input_ports()) ); + serial_queue_helper<ELEM-1, JType>::remove_queue_nodes(my_join); + delete vptr; + } +}; + +template<typename JType> +class serial_queue_helper<1, JType> { +public: + typedef typename JType::output_type TT; + typedef typename std::tuple_element<0,TT>::type IT; + typedef typename tbb::flow::queue_node<IT> my_queue_node_type; + static void print_remark() { + REMARK("Serial test of join_node< %s", name_of<IT>::name()); + } + static void add_queue_nodes(tbb::flow::graph &g, JType &my_join) { + my_queue_node_type *new_node = new my_queue_node_type(g); + tbb::flow::make_edge( *new_node, tbb::flow::input_port<0>(my_join) ); + all_source_nodes[0][0] = (void *)new_node; + } + static void fill_one_queue(int maxVal) { + my_queue_node_type *qptr = reinterpret_cast<my_queue_node_type *>(all_source_nodes[0][0]); + for(int i = 0; i < maxVal; ++i) { + ASSERT(qptr->try_put((IT)(i*2)), NULL); + } + } + static void put_one_queue_val(int myVal) { + my_queue_node_type *qptr = reinterpret_cast<my_queue_node_type *>(all_source_nodes[0][0]); + ASSERT(qptr->try_put((IT)(myVal*2)), NULL); + } + static void check_queue_value(int i, TT &v) { + ASSERT( std::get<0>(v) == (IT)(i*2), NULL); + } + static void remove_queue_nodes(JType &my_join) { + my_queue_node_type *vptr = reinterpret_cast<my_queue_node_type *>(all_source_nodes[0][0]); + tbb::flow::remove_edge( *vptr, std::get<0>(my_join.input_ports()) ); + delete vptr; + } +}; + +// +// Single reservable predecessor at each port, single accepting successor +// * put to buffer before port0, then put to buffer before port1, ... +// * fill buffer before port0 then fill buffer before port1, ... + +template<typename JType, tbb::flow::graph_buffer_policy JP> +void test_one_serial( JType &my_join, tbb::flow::graph &g) { + typedef typename JType::output_type TType; + static const int SIZE = std::tuple_size<TType>::value; + std::vector<bool> flags; + serial_queue_helper<SIZE, JType>::add_queue_nodes(g,my_join); + typedef TType q3_input_type; + tbb::flow::queue_node< q3_input_type > q3(g); + + tbb::flow::make_edge( my_join, q3 ); + + // fill each queue with its value one-at-a-time + flags.clear(); + for (int i = 0; i < Count; ++i ) { + serial_queue_helper<SIZE,JType>::put_one_queue_val(i); + flags.push_back(false); + } + + g.wait_for_all(); + tbb::flow::graph_buffer_policy jp = JP; + for (int i = 0; i < Count; ++i ) { + q3_input_type v; + g.wait_for_all(); + ASSERT(q3.try_get( v ), "Error in try_get()"); + if(jp == tbb::flow::tag_matching) { + // because we look up tags in the hash table, the output may be out of order. + int j = int(std::get<0>(v)) / 2; // figure what the index should be + serial_queue_helper<SIZE,JType>::check_queue_value(j, v); + flags[j] = true; + } + else { + serial_queue_helper<SIZE,JType>::check_queue_value(i, v); + } + } + + if(jp == tbb::flow::tag_matching) { + for(int i = 0; i < Count; ++i) { + ASSERT(flags[i], NULL); + flags[i] = false; + } + } + + // fill each queue completely before filling the next. + serial_queue_helper<SIZE, JType>::fill_one_queue(Count); + + g.wait_for_all(); + for (int i = 0; i < Count; ++i ) { + q3_input_type v; + g.wait_for_all(); + ASSERT(q3.try_get( v ), "Error in try_get()"); + if(jp == tbb::flow::tag_matching) { + int j = int(std::get<0>(v)) / 2; + serial_queue_helper<SIZE,JType>::check_queue_value(j, v); + flags[i] = true; + } + else { + serial_queue_helper<SIZE,JType>::check_queue_value(i, v); + } + } + + if(jp == tbb::flow::tag_matching) { + for(int i = 0; i < Count; ++i) { + ASSERT(flags[i], NULL); + } + } + + serial_queue_helper<SIZE, JType>::remove_queue_nodes(my_join); + +} + +template<typename JType, tbb::flow::graph_buffer_policy JP> +class serial_test { + typedef typename JType::output_type TType; + static const int SIZE = std::tuple_size<TType>::value; + static const int ELEMS = 3; +public: +static void test() { + tbb::flow::graph g; + std::vector<bool> flags; + flags.reserve(Count); + JType* my_join = makeJoin<SIZE,JType,JP>::create(g); + serial_queue_helper<SIZE, JType>::print_remark(); REMARK(" >\n"); + + test_one_serial<JType,JP>( *my_join, g); + // build the vector with copy construction from the used join node. + std::vector<JType>join_vector(ELEMS, *my_join); + // destroy the tired old join_node in case we're accidentally reusing pieces of it. + makeJoin<SIZE,JType,JP>::destroy(my_join); + + + for(int e = 0; e < ELEMS; ++e) { // exercise each of the vector elements + test_one_serial<JType,JP>( join_vector[e], g); + } +} + +}; // serial_test + +template< + template<typename, tbb::flow::graph_buffer_policy> class TestType, // serial_test or parallel_test + typename OutputTupleType, // type of the output of the join + tbb::flow::graph_buffer_policy J> // graph_buffer_policy (reserving, queueing or tag_matching) +class generate_test { +public: + typedef tbb::flow::join_node<OutputTupleType,J> join_node_type; + static void do_test() { + TestType<join_node_type,J>::test(); + } +}; + +template<typename JType> +class generate_recirc_test { +public: + typedef tbb::flow::join_node<JType, tbb::flow::tag_matching> join_node_type; + static void do_test() { + tag_recirculation_test<join_node_type>::test(); + } +}; + +template<tbb::flow::graph_buffer_policy JP> +void test_input_port_policies(); + +// join_node (reserving) does not consume inputs until an item is available at +// every input. It tries to reserve each input, and if any fails it releases the +// reservation. When it builds a tuple it broadcasts to all its successors and +// consumes all the inputs. +// +// So our test will put an item at one input port, then attach another node to the +// same node (a queue node in this case). The second successor should receive the +// item in the queue, emptying it. +// +// We then place an item in the second input queue, and check the output queues; they +// should still be empty. Then we place an item in the first queue; the output queues +// should then receive a tuple. +// +// we then attach another function node to the second input. It should not receive +// an item, verifying that the item in the queue is consumed. +template<> +void test_input_port_policies<tbb::flow::reserving>() { + tbb::flow::graph g; + typedef tbb::flow::join_node<std::tuple<int, int>, tbb::flow::reserving > JType; // two-phase is the default policy + // create join_node<type0,type1> jn + JType jn(g); + // create output_queue oq0, oq1 + typedef JType::output_type OQType; + tbb::flow::queue_node<OQType> oq0(g); + tbb::flow::queue_node<OQType> oq1(g); + // create iq0, iq1 + typedef tbb::flow::queue_node<int> IQType; + IQType iq0(g); + IQType iq1(g); + // create qnp, qnq + IQType qnp(g); + IQType qnq(g); + REMARK("Testing policies of join_node<reserving> input ports\n"); + // attach jn to oq0, oq1 + tbb::flow::make_edge( jn, oq0 ); + tbb::flow::make_edge( jn, oq1 ); + // attach iq0, iq1 to jn + tbb::flow::make_edge( iq0, std::get<0>(jn.input_ports()) ); + tbb::flow::make_edge( iq1, std::get<1>(jn.input_ports()) ); + for(int loop = 0; loop < 3; ++loop) { + // place one item in iq0 + ASSERT(iq0.try_put(1), "Error putting to iq1"); + // attach iq0 to qnp + tbb::flow::make_edge( iq0, qnp ); + // qnp should have an item in it. + g.wait_for_all(); + { + int i; + ASSERT(qnp.try_get(i) && i == 1, "Error in item fetched by qnp"); + } + // place item in iq1 + ASSERT(iq1.try_put(2), "Error putting to iq1"); + // oq0, oq1 should be empty + g.wait_for_all(); + { + OQType t1; + ASSERT(!oq0.try_get(t1) && !oq1.try_get(t1), "oq0 and oq1 not empty"); + } + // detach qnp from iq0 + tbb::flow::remove_edge( iq0, qnp); // if we don't remove qnp it will gobble any values we put in iq0 + // place item in iq0 + ASSERT(iq0.try_put(3), "Error on second put to iq0"); + // oq0, oq1 should have items in them + g.wait_for_all(); + { + OQType t0; + OQType t1; + ASSERT(oq0.try_get(t0) && std::get<0>(t0) == 3 && std::get<1>(t0) == 2, "Error in oq0 output"); + ASSERT(oq1.try_get(t1) && std::get<0>(t1) == 3 && std::get<1>(t1) == 2, "Error in oq1 output"); + } + // attach qnp to iq0, qnq to iq1 + // qnp and qnq should be empty + tbb::flow::make_edge( iq0, qnp ); + tbb::flow::make_edge( iq1, qnq ); + g.wait_for_all(); + { + int i; + ASSERT(!qnp.try_get(i), "iq0 still had value in it"); + ASSERT(!qnq.try_get(i), "iq1 still had value in it"); + } + tbb::flow::remove_edge( iq0, qnp ); + tbb::flow::remove_edge( iq1, qnq ); + } // for ( int loop ... +} + +// join_node (queueing) consumes inputs as soon as they are available at +// any input. When it builds a tuple it broadcasts to all its successors and +// discards the broadcast values. +// +// So our test will put an item at one input port, then attach another node to the +// same node (a queue node in this case). The second successor should not receive +// an item (because the join consumed it). +// +// We then place an item in the second input queue, and check the output queues; they +// should each have a tuple. +// +// we then attach another function node to the second input. It should not receive +// an item, verifying that the item in the queue is consumed. +template<> +void test_input_port_policies<tbb::flow::queueing>() { + tbb::flow::graph g; + typedef tbb::flow::join_node<std::tuple<int, int>, tbb::flow::queueing > JType; + // create join_node<type0,type1> jn + JType jn(g); + // create output_queue oq0, oq1 + typedef JType::output_type OQType; + tbb::flow::queue_node<OQType> oq0(g); + tbb::flow::queue_node<OQType> oq1(g); + // create iq0, iq1 + typedef tbb::flow::queue_node<int> IQType; + IQType iq0(g); + IQType iq1(g); + // create qnp, qnq + IQType qnp(g); + IQType qnq(g); + REMARK("Testing policies of join_node<queueing> input ports\n"); + // attach jn to oq0, oq1 + tbb::flow::make_edge( jn, oq0 ); + tbb::flow::make_edge( jn, oq1 ); + // attach iq0, iq1 to jn + tbb::flow::make_edge( iq0, std::get<0>(jn.input_ports()) ); + tbb::flow::make_edge( iq1, std::get<1>(jn.input_ports()) ); + for(int loop = 0; loop < 3; ++loop) { + // place one item in iq0 + ASSERT(iq0.try_put(1), "Error putting to iq1"); + // attach iq0 to qnp + tbb::flow::make_edge( iq0, qnp ); + // qnp should have an item in it. + g.wait_for_all(); + { + int i; + ASSERT(!qnp.try_get(i), "Item was received by qnp"); + } + // place item in iq1 + ASSERT(iq1.try_put(2), "Error putting to iq1"); + // oq0, oq1 should have items + g.wait_for_all(); + { + OQType t0; + OQType t1; + ASSERT(oq0.try_get(t0) && std::get<0>(t0) == 1 && std::get<1>(t0) == 2, "Error in oq0 output"); + ASSERT(oq1.try_get(t1) && std::get<0>(t1) == 1 && std::get<1>(t1) == 2, "Error in oq1 output"); + } + // attach qnq to iq1 + // qnp and qnq should be empty + tbb::flow::make_edge( iq1, qnq ); + g.wait_for_all(); + { + int i; + ASSERT(!qnp.try_get(i), "iq0 still had value in it"); + ASSERT(!qnq.try_get(i), "iq1 still had value in it"); + } + tbb::flow::remove_edge( iq0, qnp ); + tbb::flow::remove_edge( iq1, qnq ); + } // for ( int loop ... +} + +tbb::flow::tag_value myTagValue(int i) { return tbb::flow::tag_value(i); } + +// join_node (tag_matching) consumes inputs as soon as they are available at +// any input. When it builds a tuple it broadcasts to all its successors and +// discards the broadcast values. +// +// It chooses the tuple it broadcasts by matching the tag values returned by the +// methods given the constructor of the join, in this case the method just casts +// the value in each port to tag_value. +// +// So our test will put an item at one input port, then attach another node to the +// same node (a queue node in this case). The second successor should not receive +// an item (because the join consumed it). +// +// We then place an item in the second input queue, and check the output queues; they +// should each have a tuple. +// +// we then attach another queue node to the second input. It should not receive +// an item, verifying that the item in the queue is consumed. +// +// We will then exercise the join with a bunch of values, and the output order should +// be determined by the order we insert items into the second queue. (Each tuple set +// corresponding to a tag will be complete when the second item is inserted.) +template<> +void test_input_port_policies<tbb::flow::tag_matching>() { + tbb::flow::graph g; + typedef tbb::flow::join_node<std::tuple<int, int>, tbb::flow::tag_matching > JType; + JType jn(g, myTagValue, myTagValue); + // create output_queue oq0, oq1 + typedef JType::output_type OQType; + tbb::flow::queue_node<OQType> oq0(g); + tbb::flow::queue_node<OQType> oq1(g); + // create iq0, iq1 + typedef tbb::flow::queue_node<int> IQType; + IQType iq0(g); + IQType iq1(g); + // create qnp, qnq + IQType qnp(g); + IQType qnq(g); + + REMARK("Testing policies of join_node<tag_matching> input ports\n"); + // attach jn to oq0, oq1 + tbb::flow::make_edge( jn, oq0 ); + tbb::flow::make_edge( jn, oq1 ); + // attach iq0, iq1 to jn + tbb::flow::make_edge( iq0, tbb::flow::input_port<0>(jn) ); + tbb::flow::make_edge( iq1, tbb::flow::input_port<1>(jn) ); + // we'll put four discrete values in the inputs to the join_node. Each + // set of inputs should result in one output. (NO_TAG is currently defined + // to be tag_value(-1), so zero is an allowed tag_value.) + for(int loop = 0; loop < 4; ++loop) { + // place one item in iq0 + ASSERT(iq0.try_put(loop), "Error putting to iq1"); + // attach iq0 to qnp + tbb::flow::make_edge( iq0, qnp ); + // qnp should not have an item in it. (the join consumed it.) + g.wait_for_all(); + { + int i; + ASSERT(!qnp.try_get(i), "Item was received by qnp"); + } + // place item in iq1 + ASSERT(iq1.try_put(loop), "Error putting to iq1"); + // oq0, oq1 should have items + g.wait_for_all(); + { + OQType t0; + OQType t1; + ASSERT(oq0.try_get(t0) && std::get<0>(t0) == loop && std::get<1>(t0) == loop, "Error in oq0 output"); + ASSERT(oq1.try_get(t1) && std::get<0>(t1) == loop && std::get<1>(t1) == loop, "Error in oq1 output"); + ASSERT(!oq0.try_get(t0), "extra object in output queue oq0"); + ASSERT(!oq1.try_get(t0), "extra object in output queue oq1"); + } + // attach qnq to iq1 + // qnp and qnq should be empty + tbb::flow::make_edge( iq1, qnq ); + g.wait_for_all(); + { + int i; + ASSERT(!qnp.try_get(i), "iq0 still had value in it"); + ASSERT(!qnq.try_get(i), "iq1 still had value in it"); + } + tbb::flow::remove_edge( iq0, qnp ); + tbb::flow::remove_edge( iq1, qnq ); + } // for ( int loop ... + + // Now we'll put [4 .. nValues - 1] in iq0, and then put [4 .. nValues - 1] in iq1 in + // a different order. We should see tuples in the output queues in the order we inserted + // the integers into iq1. + + const int nValues = 100; + const int nIncr = 31; // relatively prime to nValues + + for(int loop = 4; loop < 4+nValues; ++loop) { + // place one item in iq0 + ASSERT(iq0.try_put(loop), "Error putting to iq1"); + g.wait_for_all(); + { + OQType t3; + ASSERT(!oq0.try_get(t3), "Object in output queue"); + ASSERT(!oq1.try_get(t3), "Object in output queue"); + } + } // for ( int loop ... + + for(int loop = 1; loop <= nValues; ++loop) { + int lp1 = 4 + (loop * nIncr)%nValues; + // place item in iq1 + ASSERT(iq1.try_put(lp1), "Error putting to iq1"); + // oq0, oq1 should have items + g.wait_for_all(); + { + OQType t0; + OQType t1; + ASSERT(oq0.try_get(t0) && std::get<0>(t0) == lp1 && std::get<1>(t0) == lp1, "Error in oq0 output"); + ASSERT(oq1.try_get(t1) && std::get<0>(t1) == lp1 && std::get<1>(t1) == lp1, "Error in oq1 output"); + ASSERT(!oq0.try_get(t0), "extra object in output queue oq0"); + ASSERT(!oq1.try_get(t0), "extra object in output queue oq1"); + } + } // for ( int loop ... +} + +int TestMain() { +#if __TBB_USE_TBB_TUPLE + REMARK(" Using TBB tuple\n"); +#else + REMARK(" Using platform tuple\n"); +#endif + test_input_port_policies<tbb::flow::reserving>(); + test_input_port_policies<tbb::flow::queueing>(); + test_input_port_policies<tbb::flow::tag_matching>(); + + for (int p = 0; p < 2; ++p) { + REMARK("reserving\n"); + generate_test<serial_test, std::tuple<float, double>, tbb::flow::reserving >::do_test(); + generate_test<serial_test, std::tuple<float, double, int, long>, tbb::flow::reserving >::do_test(); +#if __TBB_VARIADIC_MAX >= 6 + generate_test<serial_test, std::tuple<double, double, int, long, int, short>, tbb::flow::reserving >::do_test(); +#endif +#if COMPREHENSIVE_TEST +#if __TBB_VARIADIC_MAX >= 8 + generate_test<serial_test, std::tuple<float, double, double, double, float, int, float, long>, tbb::flow::reserving >::do_test(); +#endif +#if __TBB_VARIADIC_MAX >= 10 + generate_test<serial_test, std::tuple<float, double, int, double, double, float, long, int, float, long>, tbb::flow::reserving >::do_test(); +#endif +#endif + generate_test<parallel_test, std::tuple<float, double>, tbb::flow::reserving >::do_test(); + generate_test<parallel_test, std::tuple<float, int, long>, tbb::flow::reserving >::do_test(); + generate_test<parallel_test, std::tuple<double, double, int, int, short>, tbb::flow::reserving >::do_test(); +#if COMPREHENSIVE_TEST +#if __TBB_VARIADIC_MAX >= 7 + generate_test<parallel_test, std::tuple<float, int, double, float, long, float, long>, tbb::flow::reserving >::do_test(); +#endif +#if __TBB_VARIADIC_MAX >= 9 + generate_test<parallel_test, std::tuple<float, double, int, double, double, long, int, float, long>, tbb::flow::reserving >::do_test(); +#endif +#endif + REMARK("queueing\n"); + generate_test<serial_test, std::tuple<float, double>, tbb::flow::queueing >::do_test(); + generate_test<serial_test, std::tuple<float, double, int, long>, tbb::flow::queueing >::do_test(); +#if __TBB_VARIADIC_MAX >= 6 + generate_test<serial_test, std::tuple<double, double, int, long, int, short>, tbb::flow::queueing >::do_test(); +#endif +#if COMPREHENSIVE_TEST +#if __TBB_VARIADIC_MAX >= 8 + generate_test<serial_test, std::tuple<float, double, double, double, float, int, float, long>, tbb::flow::queueing >::do_test(); +#endif +#if __TBB_VARIADIC_MAX >= 10 + generate_test<serial_test, std::tuple<float, double, int, double, double, float, long, int, float, long>, tbb::flow::queueing >::do_test(); +#endif +#endif + generate_test<parallel_test, std::tuple<float, double>, tbb::flow::queueing >::do_test(); + generate_test<parallel_test, std::tuple<float, int, long>, tbb::flow::queueing >::do_test(); + generate_test<parallel_test, std::tuple<double, double, int, int, short>, tbb::flow::queueing >::do_test(); +#if COMPREHENSIVE_TEST +#if __TBB_VARIADIC_MAX >= 7 + generate_test<parallel_test, std::tuple<float, int, double, float, long, float, long>, tbb::flow::queueing >::do_test(); +#endif +#if __TBB_VARIADIC_MAX >= 9 + generate_test<parallel_test, std::tuple<float, double, int, double, double, long, int, float, long>, tbb::flow::queueing >::do_test(); +#endif +#endif + REMARK("tag_matching\n"); + generate_test<serial_test, std::tuple<float, double>, tbb::flow::tag_matching >::do_test(); + generate_test<serial_test, std::tuple<float, double, int, long>, tbb::flow::tag_matching >::do_test(); +#if __TBB_VARIADIC_MAX >= 6 + generate_test<serial_test, std::tuple<double, double, int, long, int, short>, tbb::flow::tag_matching >::do_test(); +#endif +#if COMPREHENSIVE_TEST +#if __TBB_VARIADIC_MAX >= 8 + generate_test<serial_test, std::tuple<float, double, double, double, float, int, float, long>, tbb::flow::tag_matching >::do_test(); +#endif +#if __TBB_VARIADIC_MAX >= 10 + generate_test<serial_test, std::tuple<float, double, int, double, double, float, long, int, float, long>, tbb::flow::tag_matching >::do_test(); +#endif +#endif + generate_test<parallel_test, std::tuple<float, double>, tbb::flow::tag_matching >::do_test(); + generate_test<parallel_test, std::tuple<float, int, long>, tbb::flow::tag_matching >::do_test(); + generate_test<parallel_test, std::tuple<double, double, int, int, short>, tbb::flow::tag_matching >::do_test(); +#if COMPREHENSIVE_TEST +#if __TBB_VARIADIC_MAX >= 7 + generate_test<parallel_test, std::tuple<float, int, double, float, long, float, long>, tbb::flow::tag_matching >::do_test(); +#endif +#if __TBB_VARIADIC_MAX >= 9 + generate_test<parallel_test, std::tuple<float, double, int, double, double, long, int, float, long>, tbb::flow::tag_matching >::do_test(); +#endif +#endif + + generate_recirc_test<std::tuple<float,double> >::do_test(); + generate_recirc_test<std::tuple<double, double, int, int, short> >::do_test(); + } + return Harness::Done; +} +#else // __SUNPRO_CC + +int TestMain() { + return Harness::Skipped; +} + +#endif // SUNPRO_CC diff --git a/src/tbb/src/test/test_lambda.cpp b/src/tbb/src/test/test_lambda.cpp new file mode 100644 index 0000000..90d95cb --- /dev/null +++ b/src/tbb/src/test/test_lambda.cpp @@ -0,0 +1,251 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#define NOMINMAX +#include "tbb/tbb.h" +#include "tbb/combinable.h" +#include <cstdio> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include <list> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +using namespace std; +using namespace tbb; + +typedef pair<int,int> max_element_t; + +void f(int val, int *arr, int start, int stop) { + for (int i=start; i<=stop; ++i) { + arr[i] = val; + } +} + +#include "harness.h" + +#if __TBB_TASK_GROUP_CONTEXT +int Fib(int n) { + if( n<2 ) { + return n; + } else { + int x=0, y=0; + task_group g; +#if __TBB_LAMBDAS_PRESENT + g.run( [&]{x=Fib(n-1);} ); // spawn a task + g.run( [&]{y=Fib(n-2);} ); // spawn another task + g.wait(); // wait for both tasks to complete +#endif + return x+y; + } +} +#endif /* !__TBB_TASK_GROUP_CONTEXT */ + +#include "harness_report.h" +#include "harness_assert.h" + +int TestMain () { +#if __TBB_LAMBDAS_PRESENT + const int N = 1000; + const int Grainsize = N/1000; + int a[N]; + int max_sum; + ASSERT( MinThread>=1, "Error: Number of threads must be positive.\n"); + + for(int p=MinThread; p<=MaxThread; ++p) { + task_scheduler_init init(p); + + REMARK("Running lambda expression tests on %d threads...\n", p); + + //test parallel_for + REMARK("Testing parallel_for... "); + parallel_for(blocked_range<int>(0,N,Grainsize), + [&] (blocked_range<int>& r) { + for (int i=r.begin(); i!=r.end(); ++i) a[i] = i; + }); + ASSERT(a[0]==0 && a[N-1]==N-1, "parallel_for w/lambdas failed.\n"); + REMARK("passed.\n"); + + //test parallel_reduce + REMARK("Testing parallel_reduce... "); + int sum = parallel_reduce(blocked_range<int>(0,N,Grainsize), int(0), + [&] (blocked_range<int>& r, int current_sum) -> int { + for (int i=r.begin(); i!=r.end(); ++i) + current_sum += a[i]*(1000-i); + return current_sum; + }, + [] (const int x1, const int x2) { + return x1+x2; + } ); + + max_element_t max_el = + parallel_reduce(blocked_range<int>(0,N,Grainsize), make_pair(a[0], 0), + [&] (blocked_range<int>& r, max_element_t current_max) + -> max_element_t { + for (int i=r.begin(); i!=r.end(); ++i) + if (a[i]>current_max.first) + current_max = make_pair(a[i], i); + return current_max; + }, + [] (const max_element_t x1, const max_element_t x2) { + return (x1.first>x2.first)?x1:x2; + }); + ASSERT(sum==166666500 && max_el.first==999 && max_el.second==999, + "parallel_reduce w/lambdas failed.\n"); + REMARK("passed.\n"); + + //test parallel_do + REMARK("Testing parallel_do... "); + list<int> s; + s.push_back(0); + + parallel_do(s.begin(), s.end(), + [&](int foo, parallel_do_feeder<int>& feeder) { + if (foo == 42) return; + else if (foo>42) { + s.push_back(foo-3); + feeder.add(foo-3); + } else { + s.push_back(foo+5); + feeder.add(foo+5); + } + }); + ASSERT(s.back()==42, "parallel_do w/lambda failed.\n"); + REMARK("passed.\n"); + + //test parallel_invoke + REMARK("Testing parallel_invoke... "); + parallel_invoke([&]{ f(2, a, 0, N/3); }, + [&]{ f(1, a, N/3+1, 2*(N/3)); }, + [&]{ f(0, a, 2*(N/3)+1, N-1); }); + ASSERT(a[0]==2.0 && a[N-1]==0.0, "parallel_invoke w/lambda failed.\n"); + REMARK("passed.\n"); + + //test tbb_thread + REMARK("Testing tbb_thread... "); + tbb_thread::id myId; + tbb_thread myThread([](int x, int y) { + ASSERT(x==42 && y==64, "tbb_thread w/lambda failed.\n"); + REMARK("passed.\n"); + }, 42, 64); + myThread.join(); + +#if __TBB_TASK_GROUP_CONTEXT + // test task_group + REMARK("Testing task_group... "); + int result; + result = Fib(32); + ASSERT(result==2178309, "task_group w/lambda failed.\n"); + REMARK("passed.\n"); +#endif /* __TBB_TASK_GROUP_CONTEXT */ + + // Reset array a to index values + parallel_for(blocked_range<int>(0,N,Grainsize), + [&] (blocked_range<int>& r) { + for (int i=r.begin(); i!=r.end(); ++i) a[i] = i; + }); + // test parallel_sort + REMARK("Testing parallel_sort... "); + int pivot = 42; + + // sort nearest by increasing distance from pivot + parallel_sort(a, a+N, + [&](int x, int y) { return(abs(pivot-x) < abs(pivot-y)); }); + ASSERT(a[0]==42 && a[N-1]==N-1, "parallel_sort w/lambda failed.\n"); + REMARK("passed.\n"); + + //test combinable + REMARK("Testing combinable... "); + combinable<std::pair<int,int> > minmax_c([&]() { return std::make_pair(a[0], a[0]); } ); + + parallel_for(blocked_range<int>(0,N), + [&] (const blocked_range<int> &r) { + std::pair<int,int>& mmr = minmax_c.local(); + for(int i=r.begin(); i!=r.end(); ++i) { + if (mmr.first > a[i]) mmr.first = a[i]; + if (mmr.second < a[i]) mmr.second = a[i]; + } + }); + max_sum = 0; + minmax_c.combine_each([&max_sum](std::pair<int,int> x) { + int tsum = x.first + x.second; + if( tsum>max_sum ) max_sum = tsum; + }); + ASSERT( (N-1)<=max_sum && max_sum<=a[0]+N-1, "combinable::combine_each /w lambda failed." ); + + std::pair<int,int> minmax_result_c; + minmax_result_c = + minmax_c.combine([](std::pair<int,int> x, std::pair<int,int> y) { + return std::make_pair(x.first<y.first?x.first:y.first, + x.second>y.second?x.second:y.second); + }); + ASSERT(minmax_result_c.first==0 && minmax_result_c.second==999, + "combinable w/lambda failed.\n"); + REMARK("passed.\n"); + + //test enumerable_thread_specific + REMARK("Testing enumerable_thread_specific... "); + enumerable_thread_specific< std::pair<int,int> > minmax_ets([&]() { return std::make_pair(a[0], a[0]); } ); + + max_sum = 0; + parallel_for(blocked_range<int>(0,N), + [&] (const blocked_range<int> &r) { + std::pair<int,int>& mmr = minmax_ets.local(); + for(int i=r.begin(); i!=r.end(); ++i) { + if (mmr.first > a[i]) mmr.first = a[i]; + if (mmr.second < a[i]) mmr.second = a[i]; + } + }); + minmax_ets.combine_each([&max_sum](std::pair<int,int> x) { + int tsum = x.first + x.second; + if( tsum>max_sum ) max_sum = tsum; + }); + ASSERT( (N-1)<=max_sum && max_sum<=a[0]+N-1, "enumerable_thread_specific::combine_each /w lambda failed." ); + + std::pair<int,int> minmax_result_ets; + minmax_result_ets = + minmax_ets.combine([](std::pair<int,int> x, std::pair<int,int> y) { + return std::make_pair(x.first<y.first?x.first:y.first, + x.second>y.second?x.second:y.second); + }); + ASSERT(minmax_result_ets.first==0 && minmax_result_ets.second==999, + "enumerable_thread_specific w/lambda failed.\n"); + REMARK("passed.\n"); + } + return Harness::Done; +#else + return Harness::Skipped; +#endif /* !__TBB_LAMBDAS_PRESENT */ +} diff --git a/src/tbb/src/test/test_limiter_node.cpp b/src/tbb/src/test/test_limiter_node.cpp new file mode 100644 index 0000000..3f34b6e --- /dev/null +++ b/src/tbb/src/test/test_limiter_node.cpp @@ -0,0 +1,212 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "harness.h" +#include "tbb/flow_graph.h" +#include "tbb/atomic.h" +#include "tbb/task_scheduler_init.h" + +const int L = 10; +const int N = 1000; + +template< typename T > +struct serial_receiver : public tbb::flow::receiver<T> { + T next_value; + + serial_receiver() : next_value(T(0)) {} + + /* override */ bool try_put( const T &v ) { + ASSERT( next_value++ == v, NULL ); + return true; + } +}; + +template< typename T > +struct parallel_receiver : public tbb::flow::receiver<T> { + + tbb::atomic<int> my_count; + + parallel_receiver() { my_count = 0; } + + /* override */ bool try_put( const T & ) { + ++my_count; + return true; + } +}; + +template< typename T > +struct empty_sender : public tbb::flow::sender<T> { + /* override */ bool register_successor( tbb::flow::receiver<T> & ) { return false; } + /* override */ bool remove_successor( tbb::flow::receiver<T> & ) { return false; } +}; + + +template< typename T > +struct put_body : NoAssign { + + tbb::flow::limiter_node<T> &my_lim; + tbb::atomic<int> &my_accept_count; + + put_body( tbb::flow::limiter_node<T> &lim, tbb::atomic<int> &accept_count ) : + my_lim(lim), my_accept_count(accept_count) {} + + void operator()( int ) const { + for ( int i = 0; i < L; ++i ) { + bool msg = my_lim.try_put( T(i) ); + if ( msg == true ) + ++my_accept_count; + } + } +}; + +template< typename T > +struct put_dec_body : NoAssign { + + tbb::flow::limiter_node<T> &my_lim; + tbb::atomic<int> &my_accept_count; + + put_dec_body( tbb::flow::limiter_node<T> &lim, tbb::atomic<int> &accept_count ) : + my_lim(lim), my_accept_count(accept_count) {} + + void operator()( int ) const { + int local_accept_count = 0; + while ( local_accept_count < N ) { + bool msg = my_lim.try_put( T(local_accept_count) ); + if ( msg == true ) { + ++local_accept_count; + ++my_accept_count; + my_lim.decrement.try_put( tbb::flow::continue_msg() ); + } + } + } + +}; + +template< typename T > +void test_puts_with_decrements( int num_threads, tbb::flow::limiter_node< T >& lim ) { + parallel_receiver<T> r; + empty_sender< tbb::flow::continue_msg > s; + tbb::atomic<int> accept_count; + accept_count = 0; + tbb::flow::make_edge( lim, r ); + lim.decrement.register_predecessor( s ); + // test puts with decrements + NativeParallelFor( num_threads, put_dec_body<T>(lim, accept_count) ); + int c = accept_count; + ASSERT( c == N*num_threads, NULL ); + ASSERT( r.my_count == N*num_threads, NULL ); +} + +// +// Tests +// +// limiter only forwards below the limit, multiple parallel senders / single receiver +// mutiple parallel senders that put to decrement at each accept, limiter accepts new messages +// +// +template< typename T > +int test_parallel(int num_threads) { + + // test puts with no decrements + for ( int i = 0; i < L; ++i ) { + tbb::flow::graph g; + tbb::flow::limiter_node< T > lim(g, i); + parallel_receiver<T> r; + tbb::atomic<int> accept_count; + accept_count = 0; + tbb::flow::make_edge( lim, r ); + // test puts with no decrements + NativeParallelFor( num_threads, put_body<T>(lim, accept_count) ); + g.wait_for_all(); + int c = accept_count; + ASSERT( c == i, NULL ); + } + + // test puts with decrements + for ( int i = 1; i < L; ++i ) { + tbb::flow::graph g; + tbb::flow::limiter_node< T > lim(g, i); + test_puts_with_decrements(num_threads, lim); + tbb::flow::limiter_node< T > lim_copy( lim ); + test_puts_with_decrements(num_threads, lim_copy); + } + + return 0; +} + +// +// Tests +// +// limiter only forwards below the limit, single sender / single receiver +// at reject, a put to decrement, will cause next message to be accepted +// +template< typename T > +int test_serial() { + + // test puts with no decrements + for ( int i = 0; i < L; ++i ) { + tbb::flow::graph g; + tbb::flow::limiter_node< T > lim(g, i); + serial_receiver<T> r; + tbb::flow::make_edge( lim, r ); + for ( int j = 0; j < L; ++j ) { + bool msg = lim.try_put( T(j) ); + ASSERT( ( j < i && msg == true ) || ( j >= i && msg == false ), NULL ); + } + g.wait_for_all(); + } + + // test puts with decrements + for ( int i = 1; i < L; ++i ) { + tbb::flow::graph g; + tbb::flow::limiter_node< T > lim(g, i); + serial_receiver<T> r; + empty_sender< tbb::flow::continue_msg > s; + tbb::flow::make_edge( lim, r ); + lim.decrement.register_predecessor( s ); + for ( int j = 0; j < N; ++j ) { + bool msg = lim.try_put( T(j) ); + ASSERT( ( j < i && msg == true ) || ( j >= i && msg == false ), NULL ); + if ( msg == false ) { + lim.decrement.try_put( tbb::flow::continue_msg() ); + msg = lim.try_put( T(j) ); + ASSERT( msg == true, NULL ); + } + } + } + return 0; +} + +int TestMain() { + for (int i = 1; i <= 8; ++i) { + tbb::task_scheduler_init init(i); + test_serial<int>(); + test_parallel<int>(i); + } + return Harness::Done; +} diff --git a/src/tbb/src/test/test_malloc_atexit.cpp b/src/tbb/src/test/test_malloc_atexit.cpp new file mode 100644 index 0000000..0baa32a --- /dev/null +++ b/src/tbb/src/test/test_malloc_atexit.cpp @@ -0,0 +1,94 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* Regression test against bug in TBB allocator, manifested when + dynamic library calls atexit or register dtors of static objects. + If the allocator is not initialized yet, we can got deadlock, + because allocator library has static object dtors as well, they + registred during allocator initialization, and atexit is protected + by non-recursive mutex in some GLIBCs. + */ + +#if _USRDLL + +#include <stdlib.h> + +#if _WIN32||_WIN64 +// isMallocOverloaded must be defined in DLL to linker not drop the dependence +// to the DLL. +extern __declspec(dllexport) bool isMallocOverloaded(); + +bool isMallocOverloaded() +{ + return true; +} + +#else + +#include <dlfcn.h> + +bool isMallocOverloaded() +{ + return dlsym(RTLD_DEFAULT, "__TBB_malloc_proxy"); +} + +#endif + +#ifndef _PGO_INSTRUMENT +void dummyFunction() {} + +class Foo { +public: + Foo() { + // add a lot of exit handlers to cause memory allocation + for (int i=0; i<1024; i++) + atexit(dummyFunction); + } +}; + +static Foo f; +#endif + +#else // _USRDLL +#include "harness.h" + +#if _WIN32||_WIN64 +extern __declspec(dllimport) +#endif +bool isMallocOverloaded(); + +int TestMain () { +#ifdef _PGO_INSTRUMENT + REPORT("Known issue: test_malloc_atexit hangs if compiled with -prof-genx\n"); + return Harness::Skipped; +#else + return isMallocOverloaded()? Harness::Done : Harness::Skipped; +#endif +} + +#endif // _USRDLL diff --git a/src/tbb/src/test/test_malloc_compliance.cpp b/src/tbb/src/test/test_malloc_compliance.cpp new file mode 100644 index 0000000..d2272f9 --- /dev/null +++ b/src/tbb/src/test/test_malloc_compliance.cpp @@ -0,0 +1,1008 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +const unsigned MByte = 1024*1024; +bool __tbb_test_errno = false; + +/* _WIN32_WINNT should be defined at the very beginning, + because other headers might include <windows.h> +*/ + +#if _WIN32 || _WIN64 +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0500 +#include "tbb/machine/windows_api.h" +#include <stdio.h> +#include "harness_report.h" + +#if _MSC_VER && defined(_MT) && defined(_DLL) + #pragma comment(lib, "version.lib") // to use GetFileVersionInfo* +#endif + +void limitMem( size_t limit ) +{ + static HANDLE hJob = NULL; + JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobInfo; + + jobInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY; + jobInfo.ProcessMemoryLimit = limit? limit*MByte : 2*MByte*1024; + if (NULL == hJob) { + if (NULL == (hJob = CreateJobObject(NULL, NULL))) { + REPORT("Can't assign create job object: %ld\n", GetLastError()); + exit(1); + } + if (0 == AssignProcessToJobObject(hJob, GetCurrentProcess())) { + REPORT("Can't assign process to job object: %ld\n", GetLastError()); + exit(1); + } + } + if (0 == SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, + &jobInfo, sizeof(jobInfo))) { + REPORT("Can't set limits: %ld\n", GetLastError()); + exit(1); + } +} +// Do not test errno with static VC runtime +#else +#include <sys/resource.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> // uint64_t on FreeBSD, needed for rlim_t +#include "harness_report.h" + +void limitMem( size_t limit ) +{ + rlimit rlim; + rlim.rlim_cur = limit? limit*MByte : (rlim_t)RLIM_INFINITY; + rlim.rlim_max = (rlim_t)RLIM_INFINITY; + int ret = setrlimit(RLIMIT_AS,&rlim); + if (0 != ret) { + REPORT("Can't set limits: errno %d\n", errno); + exit(1); + } +} +#endif + +#define ASSERT_ERRNO(cond, msg) ASSERT( !__tbb_test_errno || (cond), msg ) +#define CHECK_ERRNO(cond) (__tbb_test_errno && (cond)) + +#include <time.h> +#include <errno.h> +#define __TBB_NO_IMPLICIT_LINKAGE 1 +#include "tbb/scalable_allocator.h" + +#define HARNESS_CUSTOM_MAIN 1 +#include "harness.h" +#include "harness_barrier.h" +#include "harness_tbb_independence.h" +#if __linux__ +#include <stdint.h> // uintptr_t +#endif +#if _WIN32 || _WIN64 +#include <malloc.h> // _aligned_(malloc|free|realloc) +#if __MINGW64__ +// Workaround a bug in MinGW64 headers with _aligned_(malloc|free) not declared by default +extern "C" void __cdecl _aligned_free(void *); +extern "C" void *__cdecl _aligned_malloc(size_t,size_t); +#endif +#endif + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include <vector> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +const size_t COUNT_ELEM_CALLOC = 2; +const int COUNT_TESTS = 1000; +const int COUNT_ELEM = 25000; +const size_t MAX_SIZE = 1000; +const int COUNTEXPERIMENT = 10000; + +const char strError[]="failed"; +const char strOk[]="done"; + +typedef unsigned int UINT; +typedef unsigned char UCHAR; +typedef unsigned long DWORD; +typedef unsigned char BYTE; + + +typedef void* TestMalloc(size_t size); +typedef void* TestCalloc(size_t num, size_t size); +typedef void* TestRealloc(void* memblock, size_t size); +typedef void TestFree(void* memblock); +typedef int TestPosixMemalign(void **memptr, size_t alignment, size_t size); +typedef void* TestAlignedMalloc(size_t size, size_t alignment); +typedef void* TestAlignedRealloc(void* memblock, size_t size, size_t alignment); +typedef void TestAlignedFree(void* memblock); + +TestMalloc* Tmalloc; +TestCalloc* Tcalloc; +TestRealloc* Trealloc; +TestFree* Tfree; +TestAlignedFree* Taligned_free; +// call alignment-related function via pointer and check result's alignment +int Tposix_memalign(void **memptr, size_t alignment, size_t size); +void* Taligned_malloc(size_t size, size_t alignment); +void* Taligned_realloc(void* memblock, size_t size, size_t alignment); + +// pointers to alignment-related functions used while testing +TestPosixMemalign* Rposix_memalign; +TestAlignedMalloc* Raligned_malloc; +TestAlignedRealloc* Raligned_realloc; + +bool error_occurred = false; + +#if __APPLE__ +// Tests that use the variable are skipped on Mac OS* X +#else +static bool perProcessLimits = true; +#endif + +const size_t POWERS_OF_2 = 20; + +struct MemStruct +{ + void* Pointer; + UINT Size; + + MemStruct() : Pointer(NULL), Size(0) {} + MemStruct(void* ptr, UINT sz) : Pointer(ptr), Size(sz) {} +}; + +class CMemTest: NoAssign +{ + UINT CountErrors; + bool FullLog; + Harness::SpinBarrier *limitBarrier; + static bool firstTime; + +public: + CMemTest(Harness::SpinBarrier *barrier, bool isVerbose=false) : + CountErrors(0), limitBarrier(barrier) + { + srand((UINT)time(NULL)); + FullLog=isVerbose; + rand(); + } + void InvariantDataRealloc(bool aligned); //realloc does not change data + void NULLReturn(UINT MinSize, UINT MaxSize, int total_threads); // NULL pointer + check errno + void UniquePointer(); // unique pointer - check with padding + void AddrArifm(); // unique pointer - check with pointer arithmetic + bool ShouldReportError(); + void Free_NULL(); // + void Zerofilling(); // check if arrays are zero-filled + void TestAlignedParameters(); + void RunAllTests(int total_threads); + ~CMemTest() {} +}; + +class Limit { + size_t limit; +public: + Limit(size_t a_limit) : limit(a_limit) {} + void operator() () const { + limitMem(limit); + } +}; + +int argC; +char** argV; + +struct RoundRobin: NoAssign { + const long number_of_threads; + mutable CMemTest test; + + RoundRobin( long p, Harness::SpinBarrier *limitBarrier, bool verbose ) : + number_of_threads(p), test(limitBarrier, verbose) {} + void operator()( int /*id*/ ) const + { + test.RunAllTests(number_of_threads); + } +}; + +bool CMemTest::firstTime = true; + +static void setSystemAllocs() +{ + Tmalloc=malloc; + Trealloc=realloc; + Tcalloc=calloc; + Tfree=free; +#if _WIN32 || _WIN64 + Raligned_malloc=_aligned_malloc; + Raligned_realloc=_aligned_realloc; + Taligned_free=_aligned_free; + Rposix_memalign=0; +#elif __APPLE__ || __sun // Mac OS* X and Solaris don't have posix_memalign + Raligned_malloc=0; + Raligned_realloc=0; + Taligned_free=0; + Rposix_memalign=0; +#else + Raligned_malloc=0; + Raligned_realloc=0; + Taligned_free=0; + Rposix_memalign=posix_memalign; +#endif +} + +// check that realloc works as free and as malloc +void ReallocParam() +{ + const int ITERS = 1000; + int i; + void *bufs[ITERS]; + + bufs[0] = Trealloc(NULL, 30*MByte); + ASSERT(bufs[0], "Can't get memory to start the test."); + + for (i=1; i<ITERS; i++) + { + bufs[i] = Trealloc(NULL, 30*MByte); + if (NULL == bufs[i]) + break; + } + ASSERT(i<ITERS, "Limits should be decreased for the test to work."); + + Trealloc(bufs[0], 0); + /* There is a race for the free space between different threads at + this point. So, have to run the test sequentially. + */ + bufs[0] = Trealloc(NULL, 30*MByte); + ASSERT(bufs[0], NULL); + + for (int j=0; j<i; j++) + Trealloc(bufs[j], 0); +} + +HARNESS_EXPORT +int main(int argc, char* argv[]) { + argC=argc; + argV=argv; + MaxThread = MinThread = 1; + Tmalloc=scalable_malloc; + Trealloc=scalable_realloc; + Tcalloc=scalable_calloc; + Tfree=scalable_free; + Rposix_memalign=scalable_posix_memalign; + Raligned_malloc=scalable_aligned_malloc; + Raligned_realloc=scalable_aligned_realloc; + Taligned_free=scalable_aligned_free; + + // check if we were called to test standard behavior + for (int i=1; i< argc; i++) { + if (strcmp((char*)*(argv+i),"-s")==0) + { + setSystemAllocs(); + argC--; + break; + } + } + + ParseCommandLine( argC, argV ); +#if __linux__ + /* According to man pthreads + "NPTL threads do not share resource limits (fixed in kernel 2.6.10)". + Use per-threads limits for affected systems. + */ + if ( LinuxKernelVersion() < 2*1000000 + 6*1000 + 10) + perProcessLimits = false; +#endif + //------------------------------------- +#if __APPLE__ + /* Skip due to lack of memory limit enforcing under Mac OS X. */ +#else + limitMem(200); + ReallocParam(); + limitMem(0); +#endif + +//for linux and dynamic runtime errno is used to check allocator functions +//check if library compiled with /MD(d) and we can use errno +#if _MSC_VER +#if defined(_MT) && defined(_DLL) //check errno if test itself compiled with /MD(d) only + char* version_info_block = NULL; + int version_info_block_size; + LPVOID comments_block = NULL; + UINT comments_block_size; +#ifdef _DEBUG +#define __TBBMALLOCDLL "tbbmalloc_debug.dll" +#else //_DEBUG +#define __TBBMALLOCDLL "tbbmalloc.dll" +#endif //_DEBUG + version_info_block_size = GetFileVersionInfoSize( __TBBMALLOCDLL, (LPDWORD)&version_info_block_size ); + if( version_info_block_size + && ((version_info_block = (char*)malloc(version_info_block_size)) != NULL) + && GetFileVersionInfo( __TBBMALLOCDLL, NULL, version_info_block_size, version_info_block ) + && VerQueryValue( version_info_block, "\\StringFileInfo\\000004b0\\Comments", &comments_block, &comments_block_size ) + && strstr( (char*)comments_block, "/MD" ) + ){ + __tbb_test_errno = true; + } + if( version_info_block ) free( version_info_block ); +#endif // defined(_MT) && defined(_DLL) +#else // _MSC_VER + __tbb_test_errno = true; +#endif // _MSC_VER + + for( int p=MaxThread; p>=MinThread; --p ) { + REMARK("testing with %d threads\n", p ); + Harness::SpinBarrier *barrier = new Harness::SpinBarrier(p); + NativeParallelFor( p, RoundRobin(p, barrier, Verbose) ); + delete barrier; + } + if( !error_occurred ) + REPORT("done\n"); + return 0; +} + +// if non-zero byte found, returns bad value address plus 1 +size_t NonZero(void *ptr, size_t size) +{ + size_t words = size / sizeof(intptr_t); + size_t tailSz = size % sizeof(intptr_t); + intptr_t *buf =(intptr_t*)ptr; + char *bufTail =(char*)(buf+words); + + for (size_t i=0; i<words; i++) + if (buf[i]) { + for (unsigned b=0; b<sizeof(intptr_t); b++) + if (((char*)(buf+i))[b]) + return sizeof(intptr_t)*i + b + 1; + } + for (size_t i=0; i<tailSz; i++) + if (bufTail[i]) { + return words*sizeof(intptr_t)+i+1; + } + return 0; +} + +struct TestStruct +{ + DWORD field1:2; + DWORD field2:6; + double field3; + UCHAR field4[100]; + TestStruct* field5; + std::vector<int> field7; + double field8; +}; + +int Tposix_memalign(void **memptr, size_t alignment, size_t size) +{ + int ret = Rposix_memalign(memptr, alignment, size); + if (0 == ret) + ASSERT(0==((uintptr_t)*memptr & (alignment-1)), + "allocation result should be aligned"); + return ret; +} +void* Taligned_malloc(size_t size, size_t alignment) +{ + void *ret = Raligned_malloc(size, alignment); + if (0 != ret) + ASSERT(0==((uintptr_t)ret & (alignment-1)), + "allocation result should be aligned"); + return ret; +} +void* Taligned_realloc(void* memblock, size_t size, size_t alignment) +{ + void *ret = Raligned_realloc(memblock, size, alignment); + if (0 != ret) + ASSERT(0==((uintptr_t)ret & (alignment-1)), + "allocation result should be aligned"); + return ret; +} + +inline size_t choose_random_alignment() { + return sizeof(void*)<<(rand() % POWERS_OF_2); +} + +void CMemTest::InvariantDataRealloc(bool aligned) +{ + size_t size, sizeMin; + CountErrors=0; + if (FullLog) REPORT("\nInvariant data by realloc...."); + UCHAR* pchar; + sizeMin=size=rand()%MAX_SIZE+10; + pchar = aligned? + (UCHAR*)Taligned_realloc(NULL,size,choose_random_alignment()) + : (UCHAR*)Trealloc(NULL,size); + if (NULL == pchar) + return; + for (size_t k=0; k<size; k++) + pchar[k]=(UCHAR)k%255+1; + for (int i=0; i<COUNTEXPERIMENT; i++) + { + size=rand()%MAX_SIZE+10; + UCHAR *pcharNew = aligned? + (UCHAR*)Taligned_realloc(pchar,size, choose_random_alignment()) + : (UCHAR*)Trealloc(pchar,size); + if (NULL == pcharNew) + continue; + pchar = pcharNew; + sizeMin=size<sizeMin ? size : sizeMin; + for (size_t k=0; k<sizeMin; k++) + if (pchar[k] != (UCHAR)k%255+1) + { + CountErrors++; + if (ShouldReportError()) + { + REPORT("stand '%c', must stand '%c'\n",pchar[k],(UCHAR)k%255+1); + REPORT("error: data changed (at %llu, SizeMin=%llu)\n", + (long long unsigned)k,(long long unsigned)sizeMin); + } + } + } + if (aligned) + Taligned_realloc(pchar,0,choose_random_alignment()); + else + Trealloc(pchar,0); + if (CountErrors) REPORT("%s\n",strError); + else if (FullLog) REPORT("%s\n",strOk); + error_occurred |= ( CountErrors>0 ) ; + //REPORT("end check\n"); +} + +struct PtrSize { + void *ptr; + size_t size; +}; + +static int cmpAddrs(const void *p1, const void *p2) +{ + const PtrSize *a = (const PtrSize *)p1; + const PtrSize *b = (const PtrSize *)p2; + + return a->ptr < b->ptr ? -1 : ( a->ptr == b->ptr ? 0 : 1); +} + +void CMemTest::AddrArifm() +{ + PtrSize *arr = (PtrSize*)Tmalloc(COUNT_ELEM*sizeof(PtrSize)); + + if (FullLog) REPORT("\nUnique pointer using Address arithmetics\n"); + if (FullLog) REPORT("malloc...."); + ASSERT(arr, NULL); + for (int i=0; i<COUNT_ELEM; i++) + { + arr[i].size=rand()%MAX_SIZE; + arr[i].ptr=Tmalloc(arr[i].size); + } + qsort(arr, COUNT_ELEM, sizeof(PtrSize), cmpAddrs); + + for (int i=0; i<COUNT_ELEM-1; i++) + { + if (NULL!=arr[i].ptr && NULL!=arr[i+1].ptr) + ASSERT((uintptr_t)arr[i].ptr+arr[i].size <= (uintptr_t)arr[i+1].ptr, + "intersection detected"); + } + //---------------------------------------------------------------- + if (FullLog) REPORT("realloc...."); + for (int i=0; i<COUNT_ELEM; i++) + { + size_t count=arr[i].size*2; + void *tmpAddr=Trealloc(arr[i].ptr,count); + if (NULL!=tmpAddr) { + arr[i].ptr = tmpAddr; + arr[i].size = count; + } else if (count==0) { // becasue realloc(..., 0) works as free + arr[i].ptr = NULL; + arr[i].size = 0; + } + } + qsort(arr, COUNT_ELEM, sizeof(PtrSize), cmpAddrs); + + for (int i=0; i<COUNT_ELEM-1; i++) + { + if (NULL!=arr[i].ptr && NULL!=arr[i+1].ptr) + ASSERT((uintptr_t)arr[i].ptr+arr[i].size <= (uintptr_t)arr[i+1].ptr, + "intersection detected"); + } + for (int i=0; i<COUNT_ELEM; i++) + { + Tfree(arr[i].ptr); + } + //------------------------------------------- + if (FullLog) REPORT("calloc...."); + for (int i=0; i<COUNT_ELEM; i++) + { + arr[i].size=rand()%MAX_SIZE; + arr[i].ptr=Tcalloc(arr[i].size,1); + } + qsort(arr, COUNT_ELEM, sizeof(PtrSize), cmpAddrs); + + for (int i=0; i<COUNT_ELEM-1; i++) + { + if (NULL!=arr[i].ptr && NULL!=arr[i+1].ptr) + ASSERT((uintptr_t)arr[i].ptr+arr[i].size <= (uintptr_t)arr[i+1].ptr, + "intersection detected"); + } + for (int i=0; i<COUNT_ELEM; i++) + { + Tfree(arr[i].ptr); + } + Tfree(arr); +} + +void CMemTest::Zerofilling() +{ + TestStruct* TSMas; + size_t CountElement; + CountErrors=0; + if (FullLog) REPORT("\nzeroings elements of array...."); + //test struct + for (int i=0; i<COUNTEXPERIMENT; i++) + { + CountElement=rand()%MAX_SIZE; + TSMas=(TestStruct*)Tcalloc(CountElement,sizeof(TestStruct)); + if (NULL == TSMas) + continue; + for (size_t j=0; j<CountElement; j++) + { + if (NonZero(TSMas+j, sizeof(TestStruct))) + { + CountErrors++; + if (ShouldReportError()) REPORT("detect nonzero element at TestStruct\n"); + } + } + Tfree(TSMas); + } + if (CountErrors) REPORT("%s\n",strError); + else if (FullLog) REPORT("%s\n",strOk); + error_occurred |= ( CountErrors>0 ) ; +} + +#if !__APPLE__ + +void myMemset(void *ptr, int c, size_t n) +{ +#if __linux__ && __i386__ +// memset in Fedora 13 not always correctly sets memory to required values. + char *p = (char*)ptr; + for (size_t i=0; i<n; i++) + p[i] = c; +#else + memset(ptr, c, n); +#endif +} + +// This test requires 200 MB per thread, i.e. for standard 1:4 run +// more then 800 MB of RAM is required. +void CMemTest::NULLReturn(UINT MinSize, UINT MaxSize, int total_threads) +{ + // find size to guarantee getting NULL for 1024 B allocations + const int MAXNUM_1024 = (200+50)*1024; + + std::vector<MemStruct> PointerList; + void *tmp; + CountErrors=0; + int CountNULL, num_1024; + if (FullLog) REPORT("\nNULL return & check errno:\n"); + UINT Size; + Limit limit_200M(200*total_threads), no_limit(0); + void **buf_1024 = (void**)Tmalloc(MAXNUM_1024*sizeof(void*)); + + ASSERT(buf_1024, NULL); + /* We must have space for pointers when memory limit is hit. + Reserve enough for the worst case, taking into account race for + limited space between threads. + */ + PointerList.reserve(200*total_threads*MByte/MinSize); + + /* There is a bug in the specific version of GLIBC (2.5-12) shipped + with RHEL5 that leads to erroneous working of the test + on Intel64 and IPF systems when setrlimit-related part is enabled. + Switching to GLIBC 2.5-18 from RHEL5.1 resolved the issue. + */ + if (perProcessLimits) + limitBarrier->wait(limit_200M); + else + limitMem(200); + + /* regression test against the bug in allocator when it dereference NULL + while lack of memory + */ + for (num_1024=0; num_1024<MAXNUM_1024; num_1024++) { + buf_1024[num_1024] = Tcalloc(1024, 1); + if (! buf_1024[num_1024]) { + ASSERT_ERRNO(errno == ENOMEM, NULL); + break; + } + } + for (int i=0; i<num_1024; i++) + Tfree(buf_1024[i]); + Tfree(buf_1024); + + do { + Size=rand()%(MaxSize-MinSize)+MinSize; + tmp=Tmalloc(Size); + if (tmp != NULL) + { + myMemset(tmp, 0, Size); + PointerList.push_back(MemStruct(tmp, Size)); + } + } while(tmp != NULL); + ASSERT_ERRNO(errno == ENOMEM, NULL); + if (FullLog) REPORT("\n"); + + // preparation complete, now running tests + // malloc + if (FullLog) REPORT("malloc...."); + CountNULL = 0; + while (CountNULL==0) + for (int j=0; j<COUNT_TESTS; j++) + { + Size=rand()%(MaxSize-MinSize)+MinSize; + errno = ENOMEM+j+1; + tmp=Tmalloc(Size); + if (tmp == NULL) + { + CountNULL++; + if ( CHECK_ERRNO(errno != ENOMEM) ) { + CountErrors++; + if (ShouldReportError()) REPORT("NULL returned, error: errno (%d) != ENOMEM\n", errno); + } + } + else + { + // Technically, if malloc returns a non-NULL pointer, it is allowed to set errno anyway. + // However, on most systems it does not set errno. + bool known_issue = false; +#if __linux__ + if( CHECK_ERRNO(errno==ENOMEM) ) known_issue = true; +#endif /* __linux__ */ + if ( CHECK_ERRNO(errno != ENOMEM+j+1) && !known_issue) { + CountErrors++; + if (ShouldReportError()) REPORT("error: errno changed to %d though valid pointer was returned\n", errno); + } + myMemset(tmp, 0, Size); + PointerList.push_back(MemStruct(tmp, Size)); + } + } + if (FullLog) REPORT("end malloc\n"); + if (CountErrors) REPORT("%s\n",strError); + else if (FullLog) REPORT("%s\n",strOk); + error_occurred |= ( CountErrors>0 ) ; + + CountErrors=0; + //calloc + if (FullLog) REPORT("calloc...."); + CountNULL = 0; + while (CountNULL==0) + for (int j=0; j<COUNT_TESTS; j++) + { + Size=rand()%(MaxSize-MinSize)+MinSize; + errno = ENOMEM+j+1; + tmp=Tcalloc(COUNT_ELEM_CALLOC,Size); + if (tmp == NULL) + { + CountNULL++; + if ( CHECK_ERRNO(errno != ENOMEM) ){ + CountErrors++; + if (ShouldReportError()) REPORT("NULL returned, error: errno(%d) != ENOMEM\n", errno); + } + } + else + { + // Technically, if calloc returns a non-NULL pointer, it is allowed to set errno anyway. + // However, on most systems it does not set errno. + bool known_issue = false; +#if __linux__ + if( CHECK_ERRNO(errno==ENOMEM) ) known_issue = true; +#endif /* __linux__ */ + if ( CHECK_ERRNO(errno != ENOMEM+j+1) && !known_issue ) { + CountErrors++; + if (ShouldReportError()) REPORT("error: errno changed to %d though valid pointer was returned\n", errno); + } + PointerList.push_back(MemStruct(tmp, Size)); + } + } + if (FullLog) REPORT("end calloc\n"); + if (CountErrors) REPORT("%s\n",strError); + else if (FullLog) REPORT("%s\n",strOk); + error_occurred |= ( CountErrors>0 ) ; + CountErrors=0; + if (FullLog) REPORT("realloc...."); + CountNULL = 0; + if (PointerList.size() > 0) + while (CountNULL==0) + for (size_t i=0; i<(size_t)COUNT_TESTS && i<PointerList.size(); i++) + { + errno = 0; + tmp=Trealloc(PointerList[i].Pointer,PointerList[i].Size*2); + if (PointerList[i].Pointer == tmp) // the same place + { + bool known_issue = false; +#if __linux__ + if( errno==ENOMEM ) known_issue = true; +#endif /* __linux__ */ + if (errno != 0 && !known_issue) { + CountErrors++; + if (ShouldReportError()) REPORT("valid pointer returned, error: errno not kept\n"); + } + PointerList[i].Size *= 2; + } + else if (tmp != PointerList[i].Pointer && tmp != NULL) // another place + { + bool known_issue = false; +#if __linux__ + if( errno==ENOMEM ) known_issue = true; +#endif /* __linux__ */ + if (errno != 0 && !known_issue) { + CountErrors++; + if (ShouldReportError()) REPORT("valid pointer returned, error: errno not kept\n"); + } + // newly allocated area have to be zeroed + myMemset((char*)tmp + PointerList[i].Size, 0, PointerList[i].Size); + PointerList[i].Pointer = tmp; + PointerList[i].Size *= 2; + } + else if (tmp == NULL) + { + CountNULL++; + if ( CHECK_ERRNO(errno != ENOMEM) ) + { + CountErrors++; + if (ShouldReportError()) REPORT("NULL returned, error: errno(%d) != ENOMEM\n", errno); + } + // check data integrity + if (NonZero(PointerList[i].Pointer, PointerList[i].Size)) { + CountErrors++; + if (ShouldReportError()) REPORT("NULL returned, error: data changed\n"); + } + } + } + if (FullLog) REPORT("realloc end\n"); + if (CountErrors) REPORT("%s\n",strError); + else if (FullLog) REPORT("%s\n",strOk); + error_occurred |= ( CountErrors>0 ) ; + for (UINT i=0; i<PointerList.size(); i++) + { + Tfree(PointerList[i].Pointer); + } + + if (perProcessLimits) + limitBarrier->wait(no_limit); + else + limitMem(0); +} +#endif /* #if __APPLE__ */ + +void CMemTest::UniquePointer() +{ + CountErrors=0; + int **MasPointer = (int **)Tmalloc(sizeof(int*)*COUNT_ELEM); + size_t *MasCountElem = (size_t*)Tmalloc(sizeof(size_t)*COUNT_ELEM); + if (FullLog) REPORT("\nUnique pointer using 0\n"); + ASSERT(MasCountElem && MasPointer, NULL); + // + //------------------------------------------------------- + //malloc + for (int i=0; i<COUNT_ELEM; i++) + { + MasCountElem[i]=rand()%MAX_SIZE; + MasPointer[i]=(int*)Tmalloc(MasCountElem[i]*sizeof(int)); + if (NULL == MasPointer[i]) + MasCountElem[i]=0; + memset(MasPointer[i], 0, sizeof(int)*MasCountElem[i]); + } + if (FullLog) REPORT("malloc...."); + for (UINT i=0; i<COUNT_ELEM-1; i++) + { + if (size_t badOff = NonZero(MasPointer[i], sizeof(int)*MasCountElem[i])) { + CountErrors++; + if (ShouldReportError()) + REPORT("error, detect non-zero at %p\n", (char*)MasPointer[i]+badOff-1); + } + memset(MasPointer[i], 1, sizeof(int)*MasCountElem[i]); + } + if (CountErrors) REPORT("%s\n",strError); + else if (FullLog) REPORT("%s\n",strOk); + error_occurred |= ( CountErrors>0 ) ; + //---------------------------------------------------------- + //calloc + for (int i=0; i<COUNT_ELEM; i++) + Tfree(MasPointer[i]); + CountErrors=0; + for (long i=0; i<COUNT_ELEM; i++) + { + MasPointer[i]=(int*)Tcalloc(MasCountElem[i]*sizeof(int),2); + if (NULL == MasPointer[i]) + MasCountElem[i]=0; + } + if (FullLog) REPORT("calloc...."); + for (int i=0; i<COUNT_ELEM-1; i++) + { + if (size_t badOff = NonZero(MasPointer[i], sizeof(int)*MasCountElem[i])) { + CountErrors++; + if (ShouldReportError()) + REPORT("error, detect non-zero at %p\n", (char*)MasPointer[i]+badOff-1); + } + memset(MasPointer[i], 1, sizeof(int)*MasCountElem[i]); + } + if (CountErrors) REPORT("%s\n",strError); + else if (FullLog) REPORT("%s\n",strOk); + error_occurred |= ( CountErrors>0 ) ; + //--------------------------------------------------------- + //realloc + CountErrors=0; + for (int i=0; i<COUNT_ELEM; i++) + { + MasCountElem[i]*=2; + *(MasPointer+i)= + (int*)Trealloc(*(MasPointer+i),MasCountElem[i]*sizeof(int)); + if (NULL == MasPointer[i]) + MasCountElem[i]=0; + memset(MasPointer[i], 0, sizeof(int)*MasCountElem[i]); + } + if (FullLog) REPORT("realloc...."); + for (int i=0; i<COUNT_ELEM-1; i++) + { + if (NonZero(MasPointer[i], sizeof(int)*MasCountElem[i])) + CountErrors++; + memset(MasPointer[i], 1, sizeof(int)*MasCountElem[i]); + } + if (CountErrors) REPORT("%s\n",strError); + else if (FullLog) REPORT("%s\n",strOk); + error_occurred |= ( CountErrors>0 ) ; + for (int i=0; i<COUNT_ELEM; i++) + Tfree(MasPointer[i]); + Tfree(MasCountElem); + Tfree(MasPointer); +} + +bool CMemTest::ShouldReportError() +{ + if (FullLog) + return true; + else + if (firstTime) { + firstTime = false; + return true; + } else + return false; +} + +void CMemTest::Free_NULL() +{ + CountErrors=0; + if (FullLog) REPORT("\ncall free with parameter NULL...."); + errno = 0; + for (int i=0; i<COUNTEXPERIMENT; i++) + { + Tfree(NULL); + if (errno != 0) + { + CountErrors++; + if (ShouldReportError()) REPORT("error is found by a call free with parameter NULL\n"); + } + } + if (CountErrors) REPORT("%s\n",strError); + else if (FullLog) REPORT("%s\n",strOk); + error_occurred |= ( CountErrors>0 ) ; +} + +void CMemTest::TestAlignedParameters() +{ + void *memptr; + int ret; + + if (Rposix_memalign) { + // alignment isn't power of 2 + for (int bad_align=3; bad_align<16; bad_align++) + if (bad_align&(bad_align-1)) { + ret = Tposix_memalign(NULL, bad_align, 100); + ASSERT(EINVAL==ret, NULL); + } + + memptr = &ret; + ret = Tposix_memalign(&memptr, 5*sizeof(void*), 100); + ASSERT(memptr == &ret, + "memptr should not be changed after unsuccessful call"); + ASSERT(EINVAL==ret, NULL); + + // alignment is power of 2, but not a multiple of sizeof(void *), + // we expect that sizeof(void*) > 2 + ret = Tposix_memalign(NULL, 2, 100); + ASSERT(EINVAL==ret, NULL); + } + if (Raligned_malloc) { + // alignment isn't power of 2 + for (int bad_align=3; bad_align<16; bad_align++) + if (bad_align&(bad_align-1)) { + memptr = Taligned_malloc(100, bad_align); + ASSERT(NULL==memptr, NULL); + ASSERT_ERRNO(EINVAL==errno, NULL); + } + + // size is zero + memptr = Taligned_malloc(0, 16); + ASSERT(NULL==memptr, "size is zero, so must return NULL"); + ASSERT_ERRNO(EINVAL==errno, NULL); + } + if (Taligned_free) { + // NULL pointer is OK to free + errno = 0; + Taligned_free(NULL); + /* As there is no return value for free, strictly speaking we can't + check errno here. But checked implementations obey the assertion. + */ + ASSERT_ERRNO(0==errno, NULL); + } + if (Raligned_realloc) { + for (int i=1; i<20; i++) { + // checks that calls work correctly in presence of non-zero errno + errno = i; + void *ptr = Taligned_malloc(i*10, 128); + ASSERT(NULL!=ptr, NULL); + ASSERT_ERRNO(0!=errno, NULL); + // if size is zero and pointer is not NULL, works like free + memptr = Taligned_realloc(ptr, 0, 64); + ASSERT(NULL==memptr, NULL); + ASSERT_ERRNO(0!=errno, NULL); + } + // alignment isn't power of 2 + for (int bad_align=3; bad_align<16; bad_align++) + if (bad_align&(bad_align-1)) { + void *ptr = &bad_align; + memptr = Taligned_realloc(&ptr, 100, bad_align); + ASSERT(NULL==memptr, NULL); + ASSERT(&bad_align==ptr, NULL); + ASSERT_ERRNO(EINVAL==errno, NULL); + } + } +} + +void CMemTest::RunAllTests(int total_threads) +{ + Zerofilling(); + Free_NULL(); + InvariantDataRealloc(/*aligned=*/false); + if (Raligned_realloc) + InvariantDataRealloc(/*aligned=*/true); + TestAlignedParameters(); +#if __APPLE__ + REPORT("Known issue: some tests are skipped on Mac OS* X\n"); +#else + UniquePointer(); + AddrArifm(); +#if !__TBB_MIC_NATIVE + NULLReturn(1*MByte,100*MByte,total_threads); +#endif +#endif + if (FullLog) REPORT("Tests for %d threads ended\n", total_threads); +} diff --git a/src/tbb/src/test/test_malloc_init_shutdown.cpp b/src/tbb/src/test/test_malloc_init_shutdown.cpp new file mode 100644 index 0000000..a3cda97 --- /dev/null +++ b/src/tbb/src/test/test_malloc_init_shutdown.cpp @@ -0,0 +1,175 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/scalable_allocator.h" +#include "tbb/atomic.h" +#include "tbb/aligned_space.h" + +#include "harness.h" +#include "harness_barrier.h" +#include "harness_tbb_independence.h" + +tbb::atomic<int> FinishedTasks; +const int MaxTasks = 16; + +/*--------------------------------------------------------------------*/ +// The regression test against a bug triggered when malloc initialization +// and thread shutdown were called simultaneously, in which case +// Windows dynamic loader lock and allocator initialization/termination lock +// were taken in different order. + +class TestFunc1 { + Harness::SpinBarrier* my_barr; +public: + TestFunc1 (Harness::SpinBarrier& barr) : my_barr(&barr) {} + void operator() (bool do_malloc) const { + my_barr->wait(); + if (do_malloc) scalable_malloc(10); + ++FinishedTasks; + } +}; + +typedef NativeParallelForTask<bool,TestFunc1> TestTask1; + +void Test1 () { + int NTasks = min(MaxTasks, max(2, MaxThread)); + Harness::SpinBarrier barr(NTasks); + TestFunc1 tf(barr); + FinishedTasks = 0; + tbb::aligned_space<TestTask1,MaxTasks> tasks; + + for(int i=0; i<NTasks; ++i) { + TestTask1* t = tasks.begin()+i; + new(t) TestTask1(i%2==0, tf); + t->start(); + } + + Harness::Sleep(1000); // wait a second :) + ASSERT( FinishedTasks==NTasks, "Some threads appear to deadlock" ); + + for(int i=0; i<NTasks; ++i) { + TestTask1* t = tasks.begin()+i; + t->wait_to_finish(); + t->~TestTask1(); + } +} + +/*--------------------------------------------------------------------*/ +// The regression test against a bug when cross-thread deallocation +// caused livelock at thread shutdown. + +void* gPtr = NULL; + +class TestFunc2a { + Harness::SpinBarrier* my_barr; +public: + TestFunc2a (Harness::SpinBarrier& barr) : my_barr(&barr) {} + void operator() (int) const { + gPtr = scalable_malloc(8); + my_barr->wait(); + ++FinishedTasks; + } +}; + +typedef NativeParallelForTask<int,TestFunc2a> TestTask2a; + +class TestFunc2b: NoAssign { + Harness::SpinBarrier* my_barr; + TestTask2a& my_ward; +public: + TestFunc2b (Harness::SpinBarrier& barr, TestTask2a& t) : my_barr(&barr), my_ward(t) {} + void operator() (int) const { + tbb::internal::spin_wait_while_eq(gPtr, (void*)NULL); + scalable_free(gPtr); + my_barr->wait(); + my_ward.wait_to_finish(); + ++FinishedTasks; + } +}; +void Test2() { + Harness::SpinBarrier barr(2); + TestFunc2a func2a(barr); + TestTask2a t2a(0, func2a); + TestFunc2b func2b(barr, t2a); + NativeParallelForTask<int,TestFunc2b> t2b(1, func2b); + FinishedTasks = 0; + t2a.start(); t2b.start(); + Harness::Sleep(1000); // wait a second :) + ASSERT( FinishedTasks==2, "Threads appear to deadlock" ); + t2b.wait_to_finish(); // t2a is monitored by t2b +} + +#if _WIN32||_WIN64 + +void TestKeyDtor() {} + +#else + +void *currSmall, *prevSmall, *currLarge, *prevLarge; + +extern "C" void threadDtor(void*) { + // First, release memory that was allocated before; + // it will not re-initialize the thread-local data if already deleted + prevSmall = currSmall; + scalable_free(currSmall); + prevLarge = currLarge; + scalable_free(currLarge); + // Then, allocate more memory. + // It will re-initialize the allocator data in the thread. + scalable_free(scalable_malloc(8)); +} + +struct TestThread: NoAssign { + TestThread(int ) {} + + void operator()( int /*id*/ ) const { + pthread_key_t key; + + currSmall = scalable_malloc(8); + ASSERT(!prevSmall || currSmall==prevSmall, "Possible memory leak"); + currLarge = scalable_malloc(32*1024); + ASSERT(!prevLarge || currLarge==prevLarge, "Possible memory leak"); + pthread_key_create( &key, &threadDtor ); + pthread_setspecific(key, (const void*)42); + } +}; + +// test releasing memory from pthread key destructor +void TestKeyDtor() { + for (int i=0; i<4; i++) + NativeParallelFor( 1, TestThread(1) ); +} + +#endif // _WIN32||_WIN64 + +int TestMain () { + Test1(); // requires malloc initialization so should be first + Test2(); + TestKeyDtor(); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_malloc_lib_unload.cpp b/src/tbb/src/test/test_malloc_lib_unload.cpp new file mode 100644 index 0000000..40c2ec5 --- /dev/null +++ b/src/tbb/src/test/test_malloc_lib_unload.cpp @@ -0,0 +1,241 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if _USRDLL + +#include <stdlib.h> // for NULL +#include "harness_assert.h" +#define HARNESS_CUSTOM_MAIN 1 +#define HARNESS_NO_PARSE_COMMAND_LINE 1 +#include "harness.h" + +const char *globalCallMsg = "A TBB allocator function call is resolved into wrong implementation."; + +#if _WIN32||_WIN64 +// must be defined in DLL to linker not drop the dependence to the DLL. +extern "C" { + extern __declspec(dllexport) void *scalable_malloc(size_t); + extern __declspec(dllexport) void scalable_free (void *); + extern __declspec(dllexport) void safer_scalable_free (void *, void (*)(void*)); + extern __declspec(dllexport) void *scalable_realloc(void *, size_t); + extern __declspec(dllexport) void *safer_scalable_realloc(void *, size_t, void *); + extern __declspec(dllexport) void *scalable_calloc(size_t, size_t); + extern __declspec(dllexport) int scalable_posix_memalign(void **, size_t, size_t); + extern __declspec(dllexport) void *scalable_aligned_malloc(size_t, size_t); + extern __declspec(dllexport) void *scalable_aligned_realloc(void *, size_t, size_t); + extern __declspec(dllexport) void *safer_scalable_aligned_realloc(void *, size_t, size_t, void *); + extern __declspec(dllexport) void scalable_aligned_free(void *); + extern __declspec(dllexport) size_t scalable_msize(void *); + extern __declspec(dllexport) size_t safer_scalable_msize (void *, size_t (*)(void*)); +} +#endif + +// Those functions must not be called instead of presented in dynamic library. +extern "C" void *scalable_malloc(size_t) +{ + ASSERT(0, globalCallMsg); + return NULL; +} +extern "C" void scalable_free (void *) +{ + ASSERT(0, globalCallMsg); +} +extern "C" void safer_scalable_free (void *, void (*)(void*)) +{ + ASSERT(0, globalCallMsg); +} +extern "C" void *scalable_realloc(void *, size_t) +{ + ASSERT(0, globalCallMsg); + return NULL; +} +extern "C" void *safer_scalable_realloc(void *, size_t, void *) +{ + ASSERT(0, globalCallMsg); + return NULL; +} +extern "C" void *scalable_calloc(size_t, size_t) +{ + ASSERT(0, globalCallMsg); + return NULL; +} +extern "C" int scalable_posix_memalign(void **, size_t, size_t) +{ + ASSERT(0, globalCallMsg); + return 0; +} +extern "C" void *scalable_aligned_malloc(size_t, size_t) +{ + ASSERT(0, globalCallMsg); + return NULL; +} +extern "C" void *scalable_aligned_realloc(void *, size_t, size_t) +{ + ASSERT(0, globalCallMsg); + return NULL; +} +extern "C" void *safer_scalable_aligned_realloc(void *, size_t, size_t, void *) +{ + ASSERT(0, globalCallMsg); + return NULL; +} +extern "C" void scalable_aligned_free(void *) +{ + ASSERT(0, globalCallMsg); +} +extern "C" size_t scalable_msize(void *) +{ + ASSERT(0, globalCallMsg); + return 0; +} +extern "C" size_t safer_scalable_msize (void *, size_t (*)(void*)) +{ + ASSERT(0, globalCallMsg); + return 0; +} + +#else // _USRDLL + +#include <cstdlib> +#include "tbb/tbb_stddef.h" +#define HARNESS_NO_PARSE_COMMAND_LINE 1 +#include "harness.h" +#include "harness_memory.h" +#include "harness_dynamic_libs.h" + +#if TBB_USE_DEBUG +#define SUFFIX1 "_debug" +#define SUFFIX2 +#else +#define SUFFIX1 +#define SUFFIX2 "_debug" +#endif /* TBB_USE_DEBUG */ + +#if _WIN32||_WIN64 +#define PREFIX +#define EXT ".dll" +#else +#define PREFIX "lib" +#if __APPLE__ +#define EXT ".dylib" +#elif __linux__ +#define EXT __TBB_STRING(.so.TBB_COMPATIBLE_INTERFACE_VERSION) +#elif __FreeBSD__ || __NetBSD__ || __sun || _AIX +#define EXT ".so" +#else +#error Unknown OS +#endif +#endif + +// Form the names of the TBB memory allocator binaries. +#define MALLOCLIB_NAME1 PREFIX "tbbmalloc" SUFFIX1 EXT +#define MALLOCLIB_NAME2 PREFIX "tbbmalloc" SUFFIX2 EXT + +extern "C" { +#if _WIN32||_WIN64 +extern __declspec(dllimport) +#endif +void *scalable_malloc(size_t); +} + +struct Run { + void operator()( int /*id*/ ) const { + using namespace Harness; + + void* (*malloc_ptr)(std::size_t); + void (*free_ptr)(void*); + + void* (*aligned_malloc_ptr)(size_t size, size_t alignment); + void (*aligned_free_ptr)(void*); + + const char* actual_name; + LIBRARY_HANDLE lib = OpenLibrary(actual_name = MALLOCLIB_NAME1); + if (!lib) lib = OpenLibrary(actual_name = MALLOCLIB_NAME2); + if (!lib) { + REPORT("Can't load " MALLOCLIB_NAME1 " or " MALLOCLIB_NAME2 "\n"); + exit(1); + } + (FunctionAddress&)malloc_ptr = GetAddress(lib, "scalable_malloc"); + (FunctionAddress&)free_ptr = GetAddress(lib, "scalable_free"); + (FunctionAddress&)aligned_malloc_ptr = GetAddress(lib, "scalable_aligned_malloc"); + (FunctionAddress&)aligned_free_ptr = GetAddress(lib, "scalable_aligned_free"); + + for (size_t sz = 1024; sz <= 10*1024 ; sz*=10) { + void *p1 = aligned_malloc_ptr(sz, 16); + memset(p1, 0, sz); + aligned_free_ptr(p1); + } + + void *p = malloc_ptr(100); + memset(p, 1, 100); + free_ptr(p); + + CloseLibrary(lib); +#if _WIN32 || _WIN64 + ASSERT(GetModuleHandle(actual_name), + "allocator library must not be unloaded"); +#else + ASSERT(dlsym(RTLD_DEFAULT, "scalable_malloc"), + "allocator library must not be unloaded"); +#endif + } +}; + +int TestMain () { + int i; + std::ptrdiff_t memory_leak; + + // warm-up run + NativeParallelFor( 1, Run() ); + /* 1st call to GetMemoryUsage() allocate some memory, + but it seems memory consumption stabilized after this. + */ + GetMemoryUsage(); + std::size_t memory_in_use = GetMemoryUsage(); + ASSERT(memory_in_use == GetMemoryUsage(), + "Memory consumption should not increase after 1st GetMemoryUsage() call"); + + // expect that memory consumption stabilized after several runs + for (i=0; i<3; i++) { + std::size_t memory_in_use = GetMemoryUsage(); + for (int j=0; j<10; j++) + NativeParallelFor( 1, Run() ); + memory_leak = GetMemoryUsage() - memory_in_use; + if (memory_leak == 0) // possibly too strong? + break; + } + if(3==i) { + // not stabilized, could be leak + REPORT( "Error: memory leak of up to %ld bytes\n", static_cast<long>(memory_leak)); + exit(1); + } + + return Harness::Done; +} + +#endif // _USRDLL diff --git a/src/tbb/src/test/test_malloc_overload.cpp b/src/tbb/src/test/test_malloc_overload.cpp new file mode 100644 index 0000000..3509b69 --- /dev/null +++ b/src/tbb/src/test/test_malloc_overload.cpp @@ -0,0 +1,296 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + + +#if __linux__ +#define MALLOC_REPLACEMENT_AVAILABLE 1 +#elif _WIN32 && !__MINGW32__ && !__MINGW64__ +#define MALLOC_REPLACEMENT_AVAILABLE 2 +#include "tbb/tbbmalloc_proxy.h" +#endif + +#if MALLOC_REPLACEMENT_AVAILABLE + +#if _WIN32 || _WIN64 +// As the test is intentionally build with /EHs-, suppress multiple VS2005's +// warnings like C4530: C++ exception handler used, but unwind semantics are not enabled +#if defined(_MSC_VER) && !__INTEL_COMPILER +/* ICC 10.1 and 11.0 generates code that uses std::_Raise_handler, + but it's only defined in libcpmt(d), which the test doesn't linked with. + */ +#define _HAS_EXCEPTIONS 0 +#endif +// to use strdup and putenv w/o warnings +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif +#include "harness_report.h" +#include "harness_assert.h" +#include <stdlib.h> +#include <string.h> +#include <malloc.h> +#include <stdio.h> +#include <new> + +#if __linux__ +#include <dlfcn.h> +#include <unistd.h> // for sysconf +#include <stdint.h> // for uintptr_t + +#elif _WIN32 +#include <stddef.h> +#if __MINGW32__ +#include <unistd.h> +#else +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +#endif + +#endif /* OS selection */ + +#if _WIN32 +// On Windows, the tricky way to print "done" is necessary to create +// dependence on msvcpXX.dll, for sake of a regression test. +// On Linux, C++ RTL headers are undesirable because of breaking strict ANSI mode. +#if defined(_MSC_VER) && _MSC_VER >= 1300 && _MSC_VER <= 1310 && !defined(__INTEL_COMPILER) +/* Fixing compilation error reported by VS2003 for exception class + when _HAS_EXCEPTIONS is 0: + bad_cast that inherited from exception is not in std namespace. +*/ +using namespace std; +#endif +#include <string> +#endif + + +template<typename T> +static inline T alignDown(T arg, uintptr_t alignment) { + return T( (uintptr_t)arg & ~(alignment-1)); +} +template<typename T> +static inline bool isAligned(T arg, uintptr_t alignment) { + return 0==((uintptr_t)arg & (alignment-1)); +} + +/* start of code replicated from src/tbbmalloc */ + +class BackRefIdx { // composite index to backreference array +private: + uint16_t master; // index in BackRefMaster + uint16_t largeObj:1; // is this object "large"? + uint16_t offset :15; // offset from beginning of BackRefBlock +public: + BackRefIdx() : master((uint16_t)-1) {} + bool isInvalid() { return master == (uint16_t)-1; } + bool isLargeObject() const { return largeObj; } + uint16_t getMaster() const { return master; } + uint16_t getOffset() const { return offset; } + + // only newBackRef can modify BackRefIdx + static BackRefIdx newBackRef(bool largeObj); +}; + +class ExtMemoryPool; + +class BlockI { + intptr_t blockState[2]; +}; + +struct LargeMemoryBlock : public BlockI { + LargeMemoryBlock *next, // ptrs in list of cached blocks + *prev, + *gPrev, // in pool's global list + *gNext; + uintptr_t age; // age of block while in cache + size_t objectSize; // the size requested by a client + size_t unalignedSize; // the size requested from getMemory + bool fromMapMemory; + BackRefIdx backRefIdx; // cached here, used copy is in LargeObjectHdr + void registerInPool(ExtMemoryPool *extMemPool); + void unregisterFromPool(ExtMemoryPool *extMemPool); +}; + +struct LargeObjectHdr { + LargeMemoryBlock *memoryBlock; + /* Have to duplicate it here from CachedObjectHdr, + as backreference must be checked without further pointer dereference. + Points to LargeObjectHdr. */ + BackRefIdx backRefIdx; +}; + +/* + * Objects of size minLargeObjectSize and larger are considered large objects. + */ +const uintptr_t blockSize = 16*1024; +#if __powerpc64__ || __ppc64__ || __bgp__ +const int estimatedCacheLineSize = 128; +#else +const int estimatedCacheLineSize = 64; +#endif +const uint32_t fittingAlignment = estimatedCacheLineSize; +#define SET_FITTING_SIZE(N) ( (blockSize-2*estimatedCacheLineSize)/N ) & ~(fittingAlignment-1) +const uint32_t fittingSize5 = SET_FITTING_SIZE(2); // 8128/8064 +#undef SET_FITTING_SIZE +const uint32_t minLargeObjectSize = fittingSize5 + 1; + +/* end of code replicated from src/tbbmalloc */ + +/* Correct only for large blocks, i.e. not smaller then minLargeObjectSize */ +static bool scalableMallocLargeBlock(void *object, size_t size) +{ + ASSERT(size >= minLargeObjectSize, NULL); +#if MALLOC_REPLACEMENT_AVAILABLE == 2 + // Check that _msize works correctly + ASSERT(_msize(object) >= size, NULL); +#endif + + LargeMemoryBlock *lmb = ((LargeObjectHdr*)object-1)->memoryBlock; + return uintptr_t(lmb)<uintptr_t(((LargeObjectHdr*)object-1)) && lmb->objectSize==size; +} + +struct BigStruct { + char f[minLargeObjectSize]; +}; + +int main(int , char *[]) { + void *ptr, *ptr1; + +#if MALLOC_REPLACEMENT_AVAILABLE == 1 + if (NULL == dlsym(RTLD_DEFAULT, "scalable_malloc")) { + REPORT("libtbbmalloc not found\nfail\n"); + return 1; + } +#endif + +/* On Windows, memory block size returned by _msize() is sometimes used + to calculate the size for an extended block. Substituting _msize, + scalable_msize initially returned 0 for regions not allocated by the scalable + allocator, which led to incorrect memory reallocation and subsequent crashes. + It was found that adding a new environment variable triggers the error. +*/ + ASSERT(getenv("PATH"), "We assume that PATH is set everywhere."); + char *pathCopy = strdup(getenv("PATH")); + const char *newEnvName = "__TBBMALLOC_OVERLOAD_REGRESSION_TEST_FOR_REALLOC_AND_MSIZE"; + char *newEnv = (char*)malloc(3 + strlen(newEnvName)); + + ASSERT(!getenv(newEnvName), "Environment variable should not be used before."); + strcpy(newEnv, newEnvName); + strcat(newEnv, "=1"); + int r = putenv(newEnv); + ASSERT(!r, NULL); + char *path = getenv("PATH"); + ASSERT(path && 0==strcmp(path, pathCopy), "Environment was changed erroneously."); + free(pathCopy); + free(newEnv); + + ptr = malloc(minLargeObjectSize); + ASSERT(ptr!=NULL && scalableMallocLargeBlock(ptr, minLargeObjectSize), NULL); + free(ptr); + + ptr = calloc(minLargeObjectSize, 2); + ASSERT(ptr!=NULL && scalableMallocLargeBlock(ptr, minLargeObjectSize*2), NULL); + ptr1 = realloc(ptr, minLargeObjectSize*10); + ASSERT(ptr1!=NULL && scalableMallocLargeBlock(ptr1, minLargeObjectSize*10), NULL); + free(ptr1); + +#if MALLOC_REPLACEMENT_AVAILABLE == 1 + + int ret = posix_memalign(&ptr, 1024, 3*minLargeObjectSize); + ASSERT(0==ret && ptr!=NULL && scalableMallocLargeBlock(ptr, 3*minLargeObjectSize), NULL); + free(ptr); + + ptr = memalign(128, 4*minLargeObjectSize); + ASSERT(ptr!=NULL && scalableMallocLargeBlock(ptr, 4*minLargeObjectSize), NULL); + free(ptr); + + ptr = valloc(minLargeObjectSize); + ASSERT(ptr!=NULL && scalableMallocLargeBlock(ptr, minLargeObjectSize), NULL); + free(ptr); + + long memoryPageSize = sysconf(_SC_PAGESIZE); + int sz = 1024*minLargeObjectSize; + ptr = pvalloc(sz); + ASSERT(ptr!=NULL && // align size up to the page size + scalableMallocLargeBlock(ptr, ((sz-1) | (memoryPageSize-1)) + 1), NULL); + free(ptr); + + struct mallinfo info = mallinfo(); + // right now mallinfo initialized by zero + ASSERT(!info.arena && !info.ordblks && !info.smblks && !info.hblks + && !info.hblkhd && !info.usmblks && !info.fsmblks + && !info.uordblks && !info.fordblks && !info.keepcost, NULL); + +#elif MALLOC_REPLACEMENT_AVAILABLE == 2 + + ptr = _aligned_malloc(minLargeObjectSize,16); + ASSERT(ptr!=NULL && scalableMallocLargeBlock(ptr, minLargeObjectSize), NULL); + + ptr1 = _aligned_realloc(ptr, minLargeObjectSize*10,16); + ASSERT(ptr1!=NULL && scalableMallocLargeBlock(ptr1, minLargeObjectSize*10), NULL); + _aligned_free(ptr1); + +#endif + + BigStruct *f = new BigStruct; + ASSERT(f!=NULL && scalableMallocLargeBlock(f, sizeof(BigStruct)), NULL); + delete f; + + f = new BigStruct[10]; + ASSERT(f!=NULL && scalableMallocLargeBlock(f, 10*sizeof(BigStruct)), NULL); + delete []f; + + f = new(std::nothrow) BigStruct; + ASSERT(f!=NULL && scalableMallocLargeBlock(f, sizeof(BigStruct)), NULL); + delete f; + + f = new(std::nothrow) BigStruct[2]; + ASSERT(f!=NULL && scalableMallocLargeBlock(f, 2*sizeof(BigStruct)), NULL); + delete []f; + +#if _WIN32 + std::string stdstring = "done"; + const char* s = stdstring.c_str(); +#else + const char* s = "done"; +#endif + REPORT("%s\n", s); + return 0; +} + +#define HARNESS_NO_PARSE_COMMAND_LINE 1 +#define HARNESS_CUSTOM_MAIN 1 +#include "harness.h" + +#else /* !MALLOC_REPLACEMENT_AVAILABLE */ +#include <stdio.h> + +int main(int , char *[]) { + printf("skip\n"); + return 0; +} +#endif /* !MALLOC_REPLACEMENT_AVAILABLE */ diff --git a/src/tbb/src/test/test_malloc_pools.cpp b/src/tbb/src/test/test_malloc_pools.cpp new file mode 100644 index 0000000..7fc3b6a --- /dev/null +++ b/src/tbb/src/test/test_malloc_pools.cpp @@ -0,0 +1,491 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/scalable_allocator.h" +#include "tbb/atomic.h" +#include "harness.h" +#include "harness_barrier.h" +#include "harness_tbb_independence.h" + +template<typename T> +static inline T alignUp (T arg, uintptr_t alignment) { + return T(((uintptr_t)arg+(alignment-1)) & ~(alignment-1)); +} + +struct PoolSpace: NoCopy { + size_t pos; + int regions; + size_t bufSize; + char *space; + + static const size_t BUF_SIZE = 8*1024*1024; + + PoolSpace(size_t bufSz = BUF_SIZE) : + pos(0), regions(0), + bufSize(bufSz), space(new char[bufSize]) { + memset(space, 0, bufSize); + } + ~PoolSpace() { + delete []space; + } +}; + +static PoolSpace *poolSpace; + +struct MallocPoolHeader { + void *rawPtr; + size_t userSize; +}; + +static tbb::atomic<int> liveRegions; + +static void *getMallocMem(intptr_t /*pool_id*/, size_t &bytes) +{ + void *rawPtr = malloc(bytes+sizeof(MallocPoolHeader)); + if (!rawPtr) + return NULL; + void *ret = (void *)((uintptr_t)rawPtr+sizeof(MallocPoolHeader)); + + MallocPoolHeader *hdr = (MallocPoolHeader*)ret-1; + hdr->rawPtr = rawPtr; + hdr->userSize = bytes; + + liveRegions++; + + return ret; +} + +static int putMallocMem(intptr_t /*pool_id*/, void *ptr, size_t bytes) +{ + MallocPoolHeader *hdr = (MallocPoolHeader*)ptr-1; + ASSERT(bytes == hdr->userSize, "Invalid size in pool callback."); + free(hdr->rawPtr); + + liveRegions--; + + return 0; +} + +void TestPoolReset() +{ + rml::MemPoolPolicy pol(getMallocMem, putMallocMem); + rml::MemoryPool *pool; + + pool_create_v1(0, &pol, &pool); + for (int i=0; i<100; i++) { + ASSERT(pool_malloc(pool, 8), NULL); + ASSERT(pool_malloc(pool, 50*1024), NULL); + } + int regionsBeforeReset = liveRegions; + pool_reset(pool); + for (int i=0; i<100; i++) { + ASSERT(pool_malloc(pool, 8), NULL); + ASSERT(pool_malloc(pool, 50*1024), NULL); + } + ASSERT(regionsBeforeReset == liveRegions, + "Expected no new regions allocation."); + pool_destroy(pool); + ASSERT(!liveRegions, "Expected all regions were released."); +} + +class SharedPoolRun: NoAssign { + static long threadNum; + static Harness::SpinBarrier startB, + mallocDone; + static rml::MemoryPool *pool; + static void **crossThread, + **afterTerm; +public: + static const int OBJ_CNT = 100; + + static void init(int num, rml::MemoryPool *pl, void **crThread, void **aTerm) { + threadNum = num; + pool = pl; + crossThread = crThread; + afterTerm = aTerm; + startB.initialize(threadNum); + mallocDone.initialize(threadNum); + } + + void operator()( int id ) const { + const int ITERS = 1000; + void *local[ITERS]; + + startB.wait(); + for (int i=id*OBJ_CNT; i<(id+1)*OBJ_CNT; i++) { + afterTerm[i] = pool_malloc(pool, i%2? 8*1024 : 9*1024); + memset(afterTerm[i], i, i%2? 8*1024 : 9*1024); + crossThread[i] = pool_malloc(pool, i%2? 9*1024 : 8*1024); + memset(crossThread[i], i, i%2? 9*1024 : 8*1024); + } + + for (int i=1; i<ITERS; i+=2) { + local[i-1] = pool_malloc(pool, 6*1024); + memset(local[i-1], i, 6*1024); + local[i] = pool_malloc(pool, 16*1024); + memset(local[i], i, 16*1024); + } + mallocDone.wait(); + int myVictim = threadNum-id-1; + for (int i=myVictim*OBJ_CNT; i<(myVictim+1)*OBJ_CNT; i++) + pool_free(pool, crossThread[i]); + for (int i=0; i<ITERS; i++) + pool_free(pool, local[i]); + } +}; + +long SharedPoolRun::threadNum; +Harness::SpinBarrier SharedPoolRun::startB, + SharedPoolRun::mallocDone; +rml::MemoryPool *SharedPoolRun::pool; +void **SharedPoolRun::crossThread, + **SharedPoolRun::afterTerm; + +// single pool shared by different threads +void TestSharedPool() +{ + rml::MemPoolPolicy pol(getMallocMem, putMallocMem); + rml::MemoryPool *pool; + + pool_create_v1(0, &pol, &pool); + void **crossThread = new void*[MaxThread * SharedPoolRun::OBJ_CNT]; + void **afterTerm = new void*[MaxThread * SharedPoolRun::OBJ_CNT]; + + for (int p=MinThread; p<=MaxThread; p++) { + SharedPoolRun::init(p, pool, crossThread, afterTerm); + SharedPoolRun thr; + + void *hugeObj = pool_malloc(pool, 10*1024*1024); + ASSERT(hugeObj, NULL); + + NativeParallelFor( p, thr ); + + pool_free(pool, hugeObj); + for (int i=0; i<p*SharedPoolRun::OBJ_CNT; i++) + pool_free(pool, afterTerm[i]); + } + delete []afterTerm; + delete []crossThread; + + pool_destroy(pool); + ASSERT(!liveRegions, "Expected all regions were released."); +} + +void *CrossThreadGetMem(intptr_t pool_id, size_t &bytes) +{ + if (poolSpace[pool_id].pos + bytes > poolSpace[pool_id].bufSize) + return NULL; + + void *ret = poolSpace[pool_id].space + poolSpace[pool_id].pos; + poolSpace[pool_id].pos += bytes; + poolSpace[pool_id].regions++; + + return ret; +} + +int CrossThreadPutMem(intptr_t pool_id, void* /*raw_ptr*/, size_t /*raw_bytes*/) +{ + poolSpace[pool_id].regions--; + return 0; +} + +class CrossThreadRun: NoAssign { + static long number_of_threads; + static Harness::SpinBarrier barrier; + static rml::MemoryPool **pool; + static char **obj; +public: + static void initBarrier(unsigned thrds) { barrier.initialize(thrds); } + static void init(long num) { + number_of_threads = num; + pool = new rml::MemoryPool*[number_of_threads]; + poolSpace = new PoolSpace[number_of_threads]; + obj = new char*[number_of_threads]; + } + static void destroy() { + for (long i=0; i<number_of_threads; i++) + ASSERT(!poolSpace[i].regions, "Memory leak detected"); + delete []pool; + delete []poolSpace; + delete []obj; + } + CrossThreadRun() {} + void operator()( int id ) const { + rml::MemPoolPolicy pol(CrossThreadGetMem, CrossThreadPutMem); + const int objLen = 10*id; + + pool_create_v1(id, &pol, &pool[id]); + obj[id] = (char*)pool_malloc(pool[id], objLen); + ASSERT(obj[id], NULL); + memset(obj[id], id, objLen); + + { + const size_t lrgSz = 2*16*1024; + void *ptrLarge = pool_malloc(pool[id], lrgSz); + ASSERT(ptrLarge, NULL); + memset(ptrLarge, 1, lrgSz); + + // consume all small objects + while (pool_malloc(pool[id], 5*1024)) + ; + // releasing of large object can give a chance to allocate more + pool_free(pool[id], ptrLarge); + + ASSERT(pool_malloc(pool[id], 5*1024), NULL); + } + + barrier.wait(); + int myPool = number_of_threads-id-1; + for (int i=0; i<10*myPool; i++) + ASSERT(myPool==obj[myPool][i], NULL); + pool_free(pool[myPool], obj[myPool]); + pool_destroy(pool[myPool]); + } +}; + +long CrossThreadRun::number_of_threads; +Harness::SpinBarrier CrossThreadRun::barrier; +rml::MemoryPool **CrossThreadRun::pool; +char **CrossThreadRun::obj; + +// pools created, used and destored by different threads +void TestCrossThreadPools() +{ + for (int p=MinThread; p<=MaxThread; p++) { + CrossThreadRun::initBarrier(p); + CrossThreadRun::init(p); + NativeParallelFor( p, CrossThreadRun() ); + for (int i=0; i<p; i++) + ASSERT(!poolSpace[i].regions, "Region leak detected"); + CrossThreadRun::destroy(); + } +} + +// buffer is too small to pool be created, but must not leak resourses +void TestTooSmallBuffer() +{ + poolSpace = new PoolSpace(8*1024); + + rml::MemPoolPolicy pol(CrossThreadGetMem, CrossThreadPutMem); + rml::MemoryPool *pool; + pool_create_v1(0, &pol, &pool); + pool_destroy(pool); + ASSERT(!poolSpace[0].regions, "No leaks."); + + delete poolSpace; +} + +static void *fixedBufGetMem(intptr_t /*pool_id*/, size_t &bytes) +{ + static const size_t BUF_SZ = 8*1024*1024; + static char buf[BUF_SZ]; + static bool used; + + if (used) + return NULL; + used = true; + bytes = BUF_SZ; + return buf; +} + +void TestFixedBufferPool() +{ + void *ptrs[7]; + rml::MemPoolPolicy pol(fixedBufGetMem, NULL, 0, /*fixedSizePool=*/true, + /*keepMemTillDestroy=*/false); + rml::MemoryPool *pool; + + pool_create_v1(0, &pol, &pool); + void *largeObj = pool_malloc(pool, 7*1024*1024); + ASSERT(largeObj, NULL); + pool_free(pool, largeObj); + + for (int i=0; i<7; i++) { + ptrs[i] = pool_malloc(pool, 1024*1024); + ASSERT(ptrs[i], NULL); + } + for (int i=0; i<7; i++) + pool_free(pool, ptrs[i]); + + largeObj = pool_malloc(pool, 7*1024*1024); + ASSERT(largeObj, NULL); + pool_free(pool, largeObj); + + pool_destroy(pool); +} + +static size_t currGranularity; + +static void *getGranMem(intptr_t /*pool_id*/, size_t &bytes) +{ + ASSERT(!(bytes%currGranularity), "Region size mismatch granularity."); + return malloc(bytes); +} + +static int putGranMem(intptr_t /*pool_id*/, void *ptr, size_t bytes) +{ + ASSERT(!(bytes%currGranularity), "Region size mismatch granularity."); + free(ptr); + return 0; +} + +static void TestPoolGranularity() +{ + rml::MemPoolPolicy pol(getGranMem, putGranMem); + const size_t grans[] = {4*1024, 2*1024*1024, 6*1024*1024, 10*1024*1024}; + + for (unsigned i=0; i<sizeof(grans)/sizeof(grans[0]); i++) { + pol.granularity = currGranularity = grans[i]; + rml::MemoryPool *pool; + + pool_create_v1(0, &pol, &pool); + for (int sz=500*1024; sz<16*1024*1024; sz+=101*1024) { + void *p = pool_malloc(pool, sz); + ASSERT(p, "Can't allocate memory in pool."); + pool_free(pool, p); + } + pool_destroy(pool); + } +} + +static size_t putMemCalls, getMemCalls; + +static void *getMemPolicy(intptr_t /*pool_id*/, size_t &bytes) +{ + getMemCalls++; + return malloc(bytes); +} + +static int putMemPolicy(intptr_t /*pool_id*/, void *ptr, size_t /*bytes*/) +{ + putMemCalls++; + free(ptr); + return 0; +} + +static void TestPoolKeepTillDestroy() +{ + const int ITERS = 50*1024; + void *ptrs[2*ITERS+1]; + rml::MemPoolPolicy pol(getMemPolicy, putMemPolicy); + rml::MemoryPool *pool; + + // 1st create default pool that returns memory back to callback, + // then use keepMemTillDestroy policy + for (int keep=0; keep<2; keep++) { + getMemCalls = putMemCalls = 0; + if (keep) + pol.keepAllMemory = 1; + pool_create_v1(0, &pol, &pool); + for (int i=0; i<2*ITERS; i+=2) { + ptrs[i] = pool_malloc(pool, 7*1024); + ptrs[i+1] = pool_malloc(pool, 10*1024); + } + ptrs[2*ITERS] = pool_malloc(pool, 8*1024*1024); + ASSERT(!putMemCalls, NULL); + for (int i=0; i<2*ITERS; i++) + pool_free(pool, ptrs[i]); + pool_free(pool, ptrs[2*ITERS]); + size_t totalPutMemCalls = putMemCalls; + if (keep) + ASSERT(!putMemCalls, NULL); + else { + ASSERT(putMemCalls, NULL); + putMemCalls = 0; + } + size_t currGetCalls = getMemCalls; + pool_malloc(pool, 8*1024*1024); + if (keep) + ASSERT(currGetCalls == getMemCalls, "Must not lead to new getMem call"); + pool_reset(pool); + ASSERT(!putMemCalls, "Pool is not releasing memory during reset."); + pool_destroy(pool); + ASSERT(putMemCalls, NULL); + totalPutMemCalls += putMemCalls; + ASSERT(getMemCalls == totalPutMemCalls, "Memory leak detected."); + } + +} + +static bool memEqual(char *buf, size_t size, int val) +{ + bool memEq = true; + for (size_t k=0; k<size; k++) + if (buf[k] != val) + memEq = false; + return memEq; +} + +static void TestEntries() +{ + const int SZ = 4; + const int ALGN = 4; + size_t size[SZ] = {8, 8000, 9000, 100*1024}; + size_t algn[ALGN] = {8, 64, 4*1024, 8*1024*1024}; + + rml::MemPoolPolicy pol(getGranMem, putGranMem); + currGranularity = 1; // not check granularity in the test + rml::MemoryPool *pool; + + pool_create_v1(0, &pol, &pool); + for (int i=0; i<SZ; i++) + for (int j=0; j<ALGN; j++) { + char *p = (char*)pool_aligned_malloc(pool, size[i], algn[j]); + ASSERT(p && 0==((uintptr_t)p & (algn[j]-1)), NULL); + memset(p, j, size[i]); + + size_t curr_algn = algn[rand() % ALGN]; + size_t curr_sz = size[rand() % SZ]; + char *p1 = (char*)pool_aligned_realloc(pool, p, curr_sz, curr_algn); + ASSERT(p1 && 0==((uintptr_t)p1 & (curr_algn-1)), NULL); + ASSERT(memEqual(p1, min(size[i], curr_sz), j), NULL); + + memset(p1, j+1, curr_sz); + size_t curr_sz1 = size[rand() % SZ]; + char *p2 = (char*)pool_realloc(pool, p1, curr_sz1); + ASSERT(p2, NULL); + ASSERT(memEqual(p2, min(curr_sz1, curr_sz), j+1), NULL); + + pool_free(pool, p2); + } + + pool_destroy(pool); +} + +int TestMain () { + TestTooSmallBuffer(); + TestPoolReset(); + TestSharedPool(); + TestCrossThreadPools(); + TestFixedBufferPool(); + TestPoolGranularity(); + TestPoolKeepTillDestroy(); + TestEntries(); + + return Harness::Done; +} diff --git a/src/tbb/src/test/test_malloc_pure_c.c b/src/tbb/src/test/test_malloc_pure_c.c new file mode 100644 index 0000000..4c40eb9 --- /dev/null +++ b/src/tbb/src/test/test_malloc_pure_c.c @@ -0,0 +1,80 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#ifdef __cplusplus +#error For testing purpose, this file should be compiled with a C compiler, not C++ +#endif /*__cplusplus */ + +#include "tbb/scalable_allocator.h" +#include <stdio.h> +#include <assert.h> + +/* + * The test is to check if the scalable_allocator.h and its functions + * can be used from pure C programs; also some regression checks are done + */ + +int main(void) { + size_t i, j; + void *p1, *p2; + for( i=0; i<=1<<16; ++i) { + p1 = scalable_malloc(i); + if( !p1 ) + printf("Warning: there should be memory but scalable_malloc returned NULL\n"); + scalable_free(p1); + } + p1 = p2 = NULL; + for( i=1024*1024; ; i/=2 ) + { + scalable_free(p1); + p1 = scalable_realloc(p2, i); + p2 = scalable_calloc(i, 32); + if (p2) { + if (i<sizeof(size_t)) { + for (j=0; j<i; j++) + assert(0==*((char*)p2+j)); + } else { + for (j=0; j<i; j+=sizeof(size_t)) + assert(0==*((size_t*)p2+j)); + } + } + scalable_free(p2); + p2 = scalable_malloc(i); + if (i==0) break; + } + for( i=1; i<1024*1024; i*=2 ) + { + scalable_free(p1); + p1 = scalable_realloc(p2, i); + p2 = scalable_malloc(i); + } + scalable_free(p1); + scalable_free(p2); + printf("done\n"); + return 0; +} diff --git a/src/tbb/src/test/test_malloc_regression.cpp b/src/tbb/src/test/test_malloc_regression.cpp new file mode 100644 index 0000000..4671bd4 --- /dev/null +++ b/src/tbb/src/test/test_malloc_regression.cpp @@ -0,0 +1,150 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#define HARNESS_NO_PARSE_COMMAND_LINE 1 + +#include <stdio.h> +#include "tbb/scalable_allocator.h" + +class minimalAllocFree { +public: + void operator()(int size) const { + tbb::scalable_allocator<char> a; + char* str = a.allocate( size ); + a.deallocate( str, size ); + } +}; + +#include "harness.h" + +template<typename Body, typename Arg> +void RunThread(const Body& body, const Arg& arg) { + NativeParallelForTask<Arg,Body> job(arg, body); + job.start(); + job.wait_to_finish(); +} + +/*--------------------------------------------------------------------*/ +// The regression test against bug #1518 where thread bootstrap allocations "leaked" + +#include "harness_memory.h" + +bool TestBootstrapLeak() { + /* In the bug 1518, each thread leaked ~384 bytes. + Initially, scalable allocator maps 1MB. Thus it is necessary to take out most of this space. + 1MB is chunked into 16K blocks; of those, one block is for thread bootstrap, and one more + should be reserved for the test body. 62 blocks left, each can serve 15 objects of 1024 bytes. + */ + const int alloc_size = 1024; + const int take_out_count = 15*62; + + tbb::scalable_allocator<char> a; + char* array[take_out_count]; + for( int i=0; i<take_out_count; ++i ) + array[i] = a.allocate( alloc_size ); + + RunThread( minimalAllocFree(), alloc_size ); // for threading library to take some memory + size_t memory_in_use = GetMemoryUsage(); + // Wait for memory usage data to "stabilize". The test number (1000) has nothing underneath. + for( int i=0; i<1000; i++) { + if( GetMemoryUsage()!=memory_in_use ) { + memory_in_use = GetMemoryUsage(); + i = -1; + } + } + + ptrdiff_t memory_leak = 0; + // Note that 16K bootstrap memory block is enough to serve 42 threads. + const int num_thread_runs = 200; + for (int run=0; run<3; run++) { + memory_in_use = GetMemoryUsage(); + for( int i=0; i<num_thread_runs; ++i ) + RunThread( minimalAllocFree(), alloc_size ); + + memory_leak = GetMemoryUsage() - memory_in_use; + if (!memory_leak) + break; + } + if( memory_leak>0 ) { // possibly too strong? + REPORT( "Error: memory leak of up to %ld bytes\n", static_cast<long>(memory_leak)); + } + + for( int i=0; i<take_out_count; ++i ) + a.deallocate( array[i], alloc_size ); + + return memory_leak<=0; +} + +/*--------------------------------------------------------------------*/ +// The regression test against a bug with incompatible semantics of msize and realloc + +bool TestReallocMsize(size_t startSz) { + bool passed = true; + + char *buf = (char*)scalable_malloc(startSz); + ASSERT(buf, ""); + size_t realSz = scalable_msize(buf); + ASSERT(realSz>=startSz, "scalable_msize must be not less then allocated size"); + memset(buf, 'a', realSz-1); + buf[realSz-1] = 0; + char *buf1 = (char*)scalable_realloc(buf, 2*realSz); + ASSERT(buf1, ""); + ASSERT(scalable_msize(buf1)>=2*realSz, + "scalable_msize must be not less then allocated size"); + buf1[2*realSz-1] = 0; + if ( strspn(buf1, "a") < realSz-1 ) { + REPORT( "Error: data broken for %d Bytes object.\n", startSz); + passed = false; + } + scalable_free(buf1); + + return passed; +} + +/*--------------------------------------------------------------------*/ +// The main test function + +int TestMain () { + bool passed = true; + // Check whether memory usage data can be obtained; if not, skip test_bootstrap_leak. + if( GetMemoryUsage() ) + passed &= TestBootstrapLeak(); + + // TestReallocMsize runs for each power of 2 and each Fibonacci number below 64K + for (size_t a=1, b=1, sum=1; sum<=64*1024; ) { + passed &= TestReallocMsize(sum); + a = b; + b = sum; + sum = a+b; + } + for (size_t a=2; a<=64*1024; a*=2) + passed &= TestReallocMsize(a); + + ASSERT( passed, "Test failed" ); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_malloc_used_by_lib.cpp b/src/tbb/src/test/test_malloc_used_by_lib.cpp new file mode 100644 index 0000000..f53a7f2 --- /dev/null +++ b/src/tbb/src/test/test_malloc_used_by_lib.cpp @@ -0,0 +1,173 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if _USRDLL + +#include <stdlib.h> +#include "tbb/scalable_allocator.h" +#if __TBB_SOURCE_DIRECTLY_INCLUDED +#include "../tbbmalloc/tbbmalloc_internal_api.h" +#endif + +#define HARNESS_CUSTOM_MAIN 1 +#define HARNESS_NO_PARSE_COMMAND_LINE 1 +#include "harness.h" +#include "harness_assert.h" + +#if _WIN32||_WIN64 +extern "C" { + extern __declspec(dllexport) void callDll(); +} +#endif + +extern "C" void callDll() +{ + static const int NUM = 20; + void *ptrs[NUM]; + + for (int i=0; i<NUM; i++) { + ptrs[i] = scalable_malloc(i*1024); + ASSERT(ptrs[i], NULL); + } + for (int i=0; i<NUM; i++) + scalable_free(ptrs[i]); +#if __TBB_SOURCE_DIRECTLY_INCLUDED && (_WIN32||_WIN64) + __TBB_mallocThreadShutdownNotification(); +#endif +} + +#if __TBB_SOURCE_DIRECTLY_INCLUDED + +struct RegisterProcessShutdownNotification { + ~RegisterProcessShutdownNotification() { + __TBB_mallocProcessShutdownNotification(); + } +}; + +static RegisterProcessShutdownNotification reg; + +#endif + +#else // _USRDLL + +#define __TBB_NO_IMPLICIT_LINKAGE 1 +#define HARNESS_NO_PARSE_COMMAND_LINE 1 +#include "harness.h" +#include "harness_memory.h" +#include "harness_tbb_independence.h" +#include "harness_barrier.h" +#include "harness_dynamic_libs.h" + +class UseDll { + Harness::FunctionAddress run; +public: + UseDll(Harness::FunctionAddress runPtr) : run(runPtr) { } + void operator()( int /*id*/ ) const { + (*run)(); + } +}; + +void LoadThreadsUnload() +{ + Harness::LIBRARY_HANDLE lib = + Harness::OpenLibrary(TEST_LIBRARY_NAME("test_malloc_used_by_lib")); + ASSERT(lib, "Can't load " TEST_LIBRARY_NAME("test_malloc_used_by_lib")); + NativeParallelFor( 4, UseDll( Harness::GetAddress(lib, "callDll") ) ); + Harness::CloseLibrary(lib); +} + +struct UnloadCallback { + Harness::LIBRARY_HANDLE lib; + + void operator() () const { + Harness::CloseLibrary(lib); + } +}; + +struct RunWithLoad : NoAssign { + static Harness::SpinBarrier startBarr, endBarr; + static UnloadCallback unloadCallback; + static Harness::FunctionAddress runPtr; + + void operator()(int id) const { + if (!id) { + Harness::LIBRARY_HANDLE lib = + Harness::OpenLibrary(TEST_LIBRARY_NAME("test_malloc_used_by_lib")); + ASSERT(lib, "Can't load "TEST_LIBRARY_NAME("test_malloc_used_by_lib")); + runPtr = Harness::GetAddress(lib, "callDll"); + unloadCallback.lib = lib; + } + startBarr.wait(); + (*runPtr)(); + endBarr.wait(unloadCallback); + } +}; + +Harness::SpinBarrier RunWithLoad::startBarr, RunWithLoad::endBarr; +UnloadCallback RunWithLoad::unloadCallback; +Harness::FunctionAddress RunWithLoad::runPtr; + +void ThreadsLoadUnload() +{ + const int threads = 4; + + RunWithLoad::startBarr.initialize(threads); + RunWithLoad::endBarr.initialize(threads); + NativeParallelFor(threads, RunWithLoad()); +} + +int TestMain () { + const int ITERS = 20; + int i; + std::ptrdiff_t memory_leak = 0; + + GetMemoryUsage(); + + for (int run = 0; run<2; run++) { + // expect that memory consumption stabilized after several runs + for (i=0; i<ITERS; i++) { + std::size_t memory_in_use = GetMemoryUsage(); + if (run) + LoadThreadsUnload(); + else + ThreadsLoadUnload(); + memory_leak = GetMemoryUsage() - memory_in_use; + if (memory_leak == 0) // possibly too strong? + break; + } + if(i==ITERS) { + // not stabilized, could be leak + REPORT( "Error: memory leak of up to %ld bytes\n", static_cast<long>(memory_leak)); + exit(1); + } + } + + return Harness::Done; +} + +#endif // _USRDLL diff --git a/src/tbb/src/test/test_malloc_whitebox.cpp b/src/tbb/src/test/test_malloc_whitebox.cpp new file mode 100644 index 0000000..95f9936 --- /dev/null +++ b/src/tbb/src/test/test_malloc_whitebox.cpp @@ -0,0 +1,606 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* to prevent loading dynamic TBBmalloc at startup, that is not needed + for the whitebox test */ +#define __TBB_SOURCE_DIRECTLY_INCLUDED 1 + +// According to C99 standard INTPTR_MIN defined for C++ +// iff __STDC_LIMIT_MACROS pre-defined +#define __STDC_LIMIT_MACROS 1 + +#include "harness.h" +#include "harness_barrier.h" + +// To not depends on ITT support stuff +#ifdef DO_ITT_NOTIFY +#undef DO_ITT_NOTIFY +#endif + +#define protected public +#define private public +#include "../tbbmalloc/frontend.cpp" +#undef protected +#undef private +#include "../tbbmalloc/backend.cpp" +#include "../tbbmalloc/backref.cpp" +#include "../tbbmalloc/large_objects.cpp" +#include "../tbbmalloc/tbbmalloc.cpp" + +const int LARGE_MEM_SIZES_NUM = 10; +const size_t MByte = 1024*1024; + +class AllocInfo { + int *p; + int val; + int size; +public: + AllocInfo() : p(NULL), val(0), size(0) {} + explicit AllocInfo(int sz) : p((int*)scalable_malloc(sz*sizeof(int))), + val(rand()), size(sz) { + ASSERT(p, NULL); + for (int k=0; k<size; k++) + p[k] = val; + } + void check() const { + for (int k=0; k<size; k++) + ASSERT(p[k] == val, NULL); + } + void clear() { + scalable_free(p); + } +}; + +class SimpleBarrier: NoAssign { +protected: + static Harness::SpinBarrier barrier; +public: + static void initBarrier(unsigned thrds) { barrier.initialize(thrds); } +}; + +Harness::SpinBarrier SimpleBarrier::barrier; + +class TestLargeObjCache: public SimpleBarrier { +public: + static int largeMemSizes[LARGE_MEM_SIZES_NUM]; + + TestLargeObjCache( ) {} + + void operator()( int /*mynum*/ ) const { + AllocInfo allocs[LARGE_MEM_SIZES_NUM]; + + // push to maximal cache limit + for (int i=0; i<2; i++) { + const int sizes[] = { MByte/sizeof(int), + (MByte-2*largeBlockCacheStep)/sizeof(int) }; + for (int q=0; q<2; q++) { + size_t curr = 0; + for (int j=0; j<LARGE_MEM_SIZES_NUM; j++, curr++) + new (allocs+curr) AllocInfo(sizes[q]); + + for (size_t j=0; j<curr; j++) { + allocs[j].check(); + allocs[j].clear(); + } + } + } + + barrier.wait(); + + // check caching correctness + for (int i=0; i<1000; i++) { + size_t curr = 0; + for (int j=0; j<LARGE_MEM_SIZES_NUM-1; j++, curr++) + new (allocs+curr) AllocInfo(largeMemSizes[j]); + + new (allocs+curr) + AllocInfo((int)(4*minLargeObjectSize + + 2*minLargeObjectSize*(1.*rand()/RAND_MAX))); + curr++; + + for (size_t j=0; j<curr; j++) { + allocs[j].check(); + allocs[j].clear(); + } + } + } +}; + +int TestLargeObjCache::largeMemSizes[LARGE_MEM_SIZES_NUM]; + +#if MALLOC_CHECK_RECURSION + +class TestStartupAlloc: public SimpleBarrier { + struct TestBlock { + void *ptr; + size_t sz; + }; + static const int ITERS = 100; +public: + TestStartupAlloc() {} + void operator()(int) const { + TestBlock blocks1[ITERS], blocks2[ITERS]; + + barrier.wait(); + + for (int i=0; i<ITERS; i++) { + blocks1[i].sz = rand() % minLargeObjectSize; + blocks1[i].ptr = StartupBlock::allocate(blocks1[i].sz); + ASSERT(blocks1[i].ptr && StartupBlock::msize(blocks1[i].ptr)>=blocks1[i].sz + && 0==(uintptr_t)blocks1[i].ptr % sizeof(void*), NULL); + memset(blocks1[i].ptr, i, blocks1[i].sz); + } + for (int i=0; i<ITERS; i++) { + blocks2[i].sz = rand() % minLargeObjectSize; + blocks2[i].ptr = StartupBlock::allocate(blocks2[i].sz); + ASSERT(blocks2[i].ptr && StartupBlock::msize(blocks2[i].ptr)>=blocks2[i].sz + && 0==(uintptr_t)blocks2[i].ptr % sizeof(void*), NULL); + memset(blocks2[i].ptr, i, blocks2[i].sz); + + for (size_t j=0; j<blocks1[i].sz; j++) + ASSERT(*((char*)blocks1[i].ptr+j) == i, NULL); + Block *block = (Block *)alignDown(blocks1[i].ptr, blockSize); + ((StartupBlock *)block)->free(blocks1[i].ptr); + } + for (int i=ITERS-1; i>=0; i--) { + for (size_t j=0; j<blocks2[i].sz; j++) + ASSERT(*((char*)blocks2[i].ptr+j) == i, NULL); + Block *block = (Block *)alignDown(blocks2[i].ptr, blockSize); + ((StartupBlock *)block)->free(blocks2[i].ptr); + } + } +}; + +#endif /* MALLOC_CHECK_RECURSION */ + +class BackRefWork: NoAssign { + struct TestBlock { + intptr_t data; + BackRefIdx idx; + }; + static const int ITERS = 2*BR_MAX_CNT+2; +public: + BackRefWork() {} + void operator()(int) const { + TestBlock blocks[ITERS]; + + for (int i=0; i<ITERS; i++) { + blocks[i].idx = BackRefIdx::newBackRef(/*largeObj=*/false); + setBackRef(blocks[i].idx, &blocks[i].data); + } + for (int i=0; i<ITERS; i++) + ASSERT((Block*)&blocks[i].data == getBackRef(blocks[i].idx), NULL); + for (int i=ITERS-1; i>=0; i--) + removeBackRef(blocks[i].idx); + } +}; + +class FreeBlockPoolHit: NoAssign { + // to trigger possible leak for both cleanup on pool overflow + // and on thread termination + static const int ITERS = 2*FreeBlockPool::POOL_HIGH_MARK; +public: + FreeBlockPoolHit() {} + void operator()(int) const { + void *objs[ITERS]; + + for (int i=0; i<ITERS; i++) + objs[i] = scalable_malloc(minLargeObjectSize-1); + for (int i=0; i<ITERS; i++) + scalable_free(objs[i]); + +#ifdef USE_WINTHREAD + // Under Windows DllMain is used for mallocThreadShutdownNotification + // calling. As DllMain is not used during whitebox testing, + // we have to call the callback manually. + __TBB_mallocThreadShutdownNotification(); +#endif + } +}; + +static size_t allocatedBackRefCount() +{ + size_t cnt = 0; + for (int i=0; i<=backRefMaster->lastUsed; i++) + cnt += backRefMaster->backRefBl[i]->allocatedCount; + return cnt; +} + +static void cleanObjectCache() +{ + defaultMemPool->extMemPool.hardCachesCleanup(); +} + +class TestInvalidBackrefs: public SimpleBarrier { + static const int BACKREF_GROWTH_ITERS = 200*1024; + + static tbb::atomic<bool> backrefGrowthDone; + static void *ptrs[BACKREF_GROWTH_ITERS]; +public: + TestInvalidBackrefs() {} + void operator()(int id) const { + + if (!id) { + backrefGrowthDone = false; + barrier.wait(); + + for (int i=0; i<BACKREF_GROWTH_ITERS; i++) + ptrs[i] = scalable_malloc(minLargeObjectSize); + backrefGrowthDone = true; + for (int i=0; i<BACKREF_GROWTH_ITERS; i++) + scalable_free(ptrs[i]); + } else { + void *p2 = scalable_malloc(minLargeObjectSize-1); + char *p1 = (char*)scalable_malloc(minLargeObjectSize-1); + LargeObjectHdr *hdr = + (LargeObjectHdr*)(p1+minLargeObjectSize-1 - sizeof(LargeObjectHdr)); + hdr->backRefIdx.master = 7; + hdr->backRefIdx.largeObj = 1; + hdr->backRefIdx.offset = 2000; + + barrier.wait(); + + while (!backrefGrowthDone) { + scalable_free(p2); + p2 = scalable_malloc(minLargeObjectSize-1); + } + scalable_free(p1); + scalable_free(p2); + } + } +}; + +tbb::atomic<bool> TestInvalidBackrefs::backrefGrowthDone; +void *TestInvalidBackrefs::ptrs[BACKREF_GROWTH_ITERS]; + +void TestBackRef() { + size_t beforeNumBackRef, afterNumBackRef; + + beforeNumBackRef = allocatedBackRefCount(); + for( int p=MaxThread; p>=MinThread; --p ) + NativeParallelFor( p, BackRefWork() ); + afterNumBackRef = allocatedBackRefCount(); + ASSERT(beforeNumBackRef==afterNumBackRef, "backreference leak detected"); + + // lastUsed marks peak resource consumption. As we allocate below the mark, + // it must not move up, otherwise there is a resource leak. + int sustLastUsed = backRefMaster->lastUsed; + NativeParallelFor( 1, BackRefWork() ); + ASSERT(sustLastUsed == backRefMaster->lastUsed, "backreference leak detected"); + + // check leak of back references while per-thread small object pool is in use + // warm up need to cover bootStrapMalloc call + NativeParallelFor( 1, FreeBlockPoolHit() ); + beforeNumBackRef = allocatedBackRefCount(); + NativeParallelFor( 1, FreeBlockPoolHit() ); + afterNumBackRef = allocatedBackRefCount(); + ASSERT(beforeNumBackRef==afterNumBackRef, "backreference leak detected"); + + // This is a regression test against race condition between backreference + // extension and checking invalid BackRefIdx. + // While detecting is object large or small, scalable_free 1st check for + // large objects, so there is a chance to prepend small object with + // seems valid BackRefIdx for large objects, and thus trigger the bug. + TestInvalidBackrefs::initBarrier(MaxThread); + NativeParallelFor( MaxThread, TestInvalidBackrefs() ); +} + +void *getMem(intptr_t /*pool_id*/, size_t &bytes) +{ + const size_t BUF_SIZE = 8*1024*1024; + static char space[BUF_SIZE]; + static size_t pos; + + if (pos + bytes > BUF_SIZE) + return NULL; + + void *ret = space + pos; + pos += bytes; + + return ret; +} + +int putMem(intptr_t /*pool_id*/, void* /*raw_ptr*/, size_t /*raw_bytes*/) +{ + return 0; +} + +struct MallocPoolHeader { + void *rawPtr; + size_t userSize; +}; + +void *getMallocMem(intptr_t /*pool_id*/, size_t &bytes) +{ + void *rawPtr = malloc(bytes+sizeof(MallocPoolHeader)); + void *ret = (void *)((uintptr_t)rawPtr+sizeof(MallocPoolHeader)); + + MallocPoolHeader *hdr = (MallocPoolHeader*)ret-1; + hdr->rawPtr = rawPtr; + hdr->userSize = bytes; + + return ret; +} + +int putMallocMem(intptr_t /*pool_id*/, void *ptr, size_t bytes) +{ + MallocPoolHeader *hdr = (MallocPoolHeader*)ptr-1; + ASSERT(bytes == hdr->userSize, "Invalid size in pool callback."); + free(hdr->rawPtr); + + return 0; +} + +void TestPools() { + rml::MemPoolPolicy pol(getMem, putMem); + size_t beforeNumBackRef, afterNumBackRef; + + rml::MemoryPool *pool1; + rml::MemoryPool *pool2; + pool_create_v1(0, &pol, &pool1); + pool_create_v1(0, &pol, &pool2); + pool_destroy(pool1); + pool_destroy(pool2); + + cleanObjectCache(); + beforeNumBackRef = allocatedBackRefCount(); + rml::MemoryPool *fixedPool; + + pool_create_v1(0, &pol, &fixedPool); + pol.pAlloc = getMallocMem; + pol.pFree = putMallocMem; + pol.granularity = 8; + rml::MemoryPool *mallocPool; + + pool_create_v1(0, &pol, &mallocPool); +/* check that large object cache (LOC) returns correct size for cached objects + passBackendSz Byte objects are cached in LOC, but bypassed the backend, so + memory requested directly from allocation callback. + nextPassBackendSz Byte objects must fit to another LOC bin, + so that their allocation/realeasing leads to cache cleanup. + All this is expecting to lead to releasing of passBackendSz Byte object + from LOC during LOC cleanup, and putMallocMem checks that returned size + is correct. +*/ + const size_t passBackendSz = Backend::maxBinedSize+1, + anotherLOCBinSz = minLargeObjectSize+1; + for (int i=0; i<10; i++) { // run long enough to be cached + void *p = pool_malloc(mallocPool, passBackendSz); + ASSERT(p, "Memory was not allocated"); + pool_free(mallocPool, p); + } + // run long enough to passBackendSz allocation was cleaned from cache + // and returned back to putMallocMem for size checking + for (int i=0; i<1000; i++) { + void *p = pool_malloc(mallocPool, anotherLOCBinSz); + ASSERT(p, "Memory was not allocated"); + pool_free(mallocPool, p); + } + + void *smallObj = pool_malloc(fixedPool, 10); + ASSERT(smallObj, "Memory was not allocated"); + memset(smallObj, 1, 10); + void *ptr = pool_malloc(fixedPool, 1024); + ASSERT(ptr, "Memory was not allocated"); + memset(ptr, 1, 1024); + void *largeObj = pool_malloc(fixedPool, minLargeObjectSize); + ASSERT(largeObj, "Memory was not allocated"); + memset(largeObj, 1, minLargeObjectSize); + ptr = pool_malloc(fixedPool, minLargeObjectSize); + ASSERT(ptr, "Memory was not allocated"); + memset(ptr, minLargeObjectSize, minLargeObjectSize); + pool_malloc(fixedPool, 10*minLargeObjectSize); // no leak for unsuccesful allocations + pool_free(fixedPool, smallObj); + pool_free(fixedPool, largeObj); + + // provoke large object cache cleanup and hope no leaks occurs + for (size_t sz=minLargeObjectSize; sz<1*1024*1024; sz+=largeBlockCacheStep) { + ptr = pool_malloc(mallocPool, sz); + ASSERT(ptr, "Memory was not allocated"); + memset(ptr, sz, sz); + pool_free(mallocPool, ptr); + } + pool_destroy(mallocPool); + pool_destroy(fixedPool); + + cleanObjectCache(); + afterNumBackRef = allocatedBackRefCount(); + ASSERT(beforeNumBackRef==afterNumBackRef, "backreference leak detected"); +} + +void TestObjectRecognition() { + size_t headersSize = sizeof(LargeMemoryBlock)+sizeof(LargeObjectHdr); + unsigned falseObjectSize = 113; // unsigned is the type expected by getObjectSize + size_t obtainedSize; + + ASSERT(sizeof(BackRefIdx)==4, "Unexpected size of BackRefIdx"); + ASSERT(getObjectSize(falseObjectSize)!=falseObjectSize, "Error in test: bad choice for false object size"); + + void* mem = scalable_malloc(2*blockSize); + ASSERT(mem, "Memory was not allocated"); + Block* falseBlock = (Block*)alignUp((uintptr_t)mem, blockSize); + falseBlock->objectSize = falseObjectSize; + char* falseSO = (char*)falseBlock + falseObjectSize*7; + ASSERT(alignDown(falseSO, blockSize)==(void*)falseBlock, "Error in test: false object offset is too big"); + + void* bufferLOH = scalable_malloc(2*blockSize + headersSize); + ASSERT(bufferLOH, "Memory was not allocated"); + LargeObjectHdr* falseLO = + (LargeObjectHdr*)alignUp((uintptr_t)bufferLOH + headersSize, blockSize); + LargeObjectHdr* headerLO = (LargeObjectHdr*)falseLO-1; + headerLO->memoryBlock = (LargeMemoryBlock*)bufferLOH; + headerLO->memoryBlock->unalignedSize = 2*blockSize + headersSize; + headerLO->memoryBlock->objectSize = blockSize + headersSize; + headerLO->backRefIdx = BackRefIdx::newBackRef(/*largeObj=*/true); + setBackRef(headerLO->backRefIdx, headerLO); + ASSERT(scalable_msize(falseLO) == blockSize + headersSize, + "Error in test: LOH falsification failed"); + removeBackRef(headerLO->backRefIdx); + + const int NUM_OF_IDX = BR_MAX_CNT+2; + BackRefIdx idxs[NUM_OF_IDX]; + for (int cnt=0; cnt<2; cnt++) { + for (int master = -10; master<10; master++) { + falseBlock->backRefIdx.master = (uint16_t)master; + headerLO->backRefIdx.master = (uint16_t)master; + + for (int bl = -10; bl<BR_MAX_CNT+10; bl++) { + falseBlock->backRefIdx.offset = (uint16_t)bl; + headerLO->backRefIdx.offset = (uint16_t)bl; + + for (int largeObj = 0; largeObj<2; largeObj++) { + falseBlock->backRefIdx.largeObj = largeObj; + headerLO->backRefIdx.largeObj = largeObj; + + obtainedSize = safer_scalable_msize(falseSO, NULL); + ASSERT(obtainedSize==0, "Incorrect pointer accepted"); + obtainedSize = safer_scalable_msize(falseLO, NULL); + ASSERT(obtainedSize==0, "Incorrect pointer accepted"); + } + } + } + if (cnt == 1) { + for (int i=0; i<NUM_OF_IDX; i++) + removeBackRef(idxs[i]); + break; + } + for (int i=0; i<NUM_OF_IDX; i++) { + idxs[i] = BackRefIdx::newBackRef(/*largeObj=*/false); + setBackRef(idxs[i], NULL); + } + } + char *smallPtr = (char*)scalable_malloc(falseObjectSize); + obtainedSize = safer_scalable_msize(smallPtr, NULL); + ASSERT(obtainedSize==getObjectSize(falseObjectSize), "Correct pointer not accepted?"); + scalable_free(smallPtr); + + obtainedSize = safer_scalable_msize(mem, NULL); + ASSERT(obtainedSize>=2*blockSize, "Correct pointer not accepted?"); + scalable_free(mem); + scalable_free(bufferLOH); +} + +class TestBackendWork: public SimpleBarrier { + struct TestBlock { + intptr_t data; + BackRefIdx idx; + }; + static const int ITERS = 100; + + rml::internal::Backend *backend; +public: + TestBackendWork(rml::internal::Backend *bknd) : backend(bknd) {} + void operator()(int) const { + barrier.wait(); + + for (int i=0; i<ITERS; i++) { + BlockI *block16K = backend->get16KBlock(1); + ASSERT(block16K, "Memory was not allocated"); + LargeMemoryBlock *lmb = backend->getLargeBlock(16*1024); + backend->put16KBlock(block16K); + backend->putLargeBlock(lmb); + } + } +}; + +void TestBackend() +{ + rml::MemPoolPolicy pol(getMallocMem, putMallocMem); + rml::MemoryPool *mPool; + pool_create_v1(0, &pol, &mPool); + rml::internal::ExtMemoryPool *ePool = + &((rml::internal::MemoryPool*)mPool)->extMemPool; + rml::internal::Backend *backend = &ePool->backend; + + for( int p=MaxThread; p>=MinThread; --p ) { + TestBackendWork::initBarrier(p); + NativeParallelFor( p, TestBackendWork(backend) ); + } + + BlockI *block = backend->get16KBlock(1); + ASSERT(block, "Memory was not allocated"); + backend->put16KBlock(block); + + pool_destroy(mPool); +} + +void TestBitMask() +{ + BitMask<256> mask; + + mask.reset(); + mask.set(10, 1); + mask.set(5, 1); + mask.set(1, 1); + ASSERT(mask.getMinTrue(2) == 5, NULL); + + mask.reset(); + mask.set(0, 1); + mask.set(64, 1); + mask.set(63, 1); + mask.set(200, 1); + mask.set(255, 1); + ASSERT(mask.getMinTrue(0) == 0, NULL); + ASSERT(mask.getMinTrue(1) == 63, NULL); + ASSERT(mask.getMinTrue(63) == 63, NULL); + ASSERT(mask.getMinTrue(64) == 64, NULL); + ASSERT(mask.getMinTrue(101) == 200, NULL); + ASSERT(mask.getMinTrue(201) == 255, NULL); + mask.set(255, 0); + ASSERT(mask.getMinTrue(201) == -1, NULL); +} + +int TestMain () { + // backreference requires that initialization was done + if(!isMallocInitialized()) doInitialization(); + // to succeed, leak detection must be the 1st memory-intensive test + TestBackRef(); + TestPools(); + TestBackend(); + +#if MALLOC_CHECK_RECURSION + for( int p=MaxThread; p>=MinThread; --p ) { + TestStartupAlloc::initBarrier( p ); + NativeParallelFor( p, TestStartupAlloc() ); + ASSERT(!firstStartupBlock, "Startup heap memory leak detected"); + } +#endif + + for (int i=0; i<LARGE_MEM_SIZES_NUM; i++) + TestLargeObjCache::largeMemSizes[i] = + (int)(minLargeObjectSize + 2*minLargeObjectSize*(1.*rand()/RAND_MAX)); + + for( int p=MaxThread; p>=MinThread; --p ) { + TestLargeObjCache::initBarrier( p ); + NativeParallelFor( p, TestLargeObjCache() ); + } + + TestObjectRecognition(); + TestBitMask(); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_model_plugin.cpp b/src/tbb/src/test/test_model_plugin.cpp new file mode 100644 index 0000000..39facd8 --- /dev/null +++ b/src/tbb/src/test/test_model_plugin.cpp @@ -0,0 +1,254 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/tbb_config.h" + +#if __TBB_DEFINE_MIC + +#ifndef _USRDLL +#define HARNESS_NO_PARSE_COMMAND_LINE 1 +#include "harness.h" +int TestMain() { + return Harness::Skipped; +} +#endif + +#else /* !__MIC__ */ + +#if _WIN32 || _WIN64 +#include "tbb/machine/windows_api.h" +#else +#include <dlfcn.h> +#endif + +#include <stdlib.h> +#include <stdio.h> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include <stdexcept> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +#if TBB_USE_EXCEPTIONS + #include "harness_report.h" +#endif + +#ifdef _USRDLL +#include "tbb/task_scheduler_init.h" + +class CModel { +public: + CModel(void) {}; + static tbb::task_scheduler_init tbb_init; + + void init_and_terminate( int ); +}; + +tbb::task_scheduler_init CModel::tbb_init(1); + +//! Test that task::initialize and task::terminate work when doing nothing else. +/** maxthread is treated as the "maximum" number of worker threads. */ +void CModel::init_and_terminate( int maxthread ) { + for( int i=0; i<200; ++i ) { + switch( i&3 ) { + default: { + tbb::task_scheduler_init init( rand() % maxthread + 1 ); + break; + } + case 0: { + tbb::task_scheduler_init init; + break; + } + case 1: { + tbb::task_scheduler_init init( tbb::task_scheduler_init::automatic ); + break; + } + case 2: { + tbb::task_scheduler_init init( tbb::task_scheduler_init::deferred ); + init.initialize( rand() % maxthread + 1 ); + init.terminate(); + break; + } + } + } +} + +extern "C" +#if _WIN32 || _WIN64 +__declspec(dllexport) +#endif +void plugin_call(int maxthread) +{ + srand(2); + __TBB_TRY { + CModel model; + model.init_and_terminate(maxthread); + } __TBB_CATCH( std::runtime_error& error ) { +#if TBB_USE_EXCEPTIONS + REPORT("ERROR: %s\n", error.what()); +#endif /* TBB_USE_EXCEPTIONS */ + } +} + +#else /* _USRDLL undefined */ + +#define HARNESS_NO_ASSERT 1 +#include "harness.h" +#include "harness_dynamic_libs.h" + +extern "C" void plugin_call(int); + +void report_error_in(const char* function_name) +{ +#if _WIN32 || _WIN64 + char* message; + int code = GetLastError(); + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, code,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (char*)&message, 0, NULL ); +#else + char* message = (char*)dlerror(); + int code = 0; +#endif + REPORT( "%s failed with error %d: %s\n", function_name, code, message); + +#if _WIN32 || _WIN64 + LocalFree(message); +#endif +} + +int use_lot_of_tls() { + int count = 0; +#if _WIN32 || _WIN64 + DWORD last_handles[10]; + DWORD result; + result = TlsAlloc(); + while( result!=TLS_OUT_OF_INDEXES ) { + last_handles[++count%10] = result; + result = TlsAlloc(); + } + for( int i=0; i<10; ++i ) + TlsFree(last_handles[i]); +#else + pthread_key_t last_handles[10]; + pthread_key_t result; + int setspecific_dummy=10; + while( pthread_key_create(&result, NULL)==0 + && count < 4096 ) // Sun Solaris doesn't have any built-in limit, so we set something big enough + { + last_handles[++count%10] = result; + pthread_setspecific(result,&setspecific_dummy); + } + REMARK("Created %d keys\n", count); + for( int i=0; i<10; ++i ) + pthread_key_delete(last_handles[i]); +#endif + return count-10; +} + +typedef void (*PLUGIN_CALL)(int); + +#if __linux__ + #define RML_LIBRARY_NAME(base) TEST_LIBRARY_NAME(base) ".1" +#else + #define RML_LIBRARY_NAME(base) TEST_LIBRARY_NAME(base) +#endif + +int TestMain () { +#if !RML_USE_WCRM + PLUGIN_CALL my_plugin_call; + + int tls_key_count = use_lot_of_tls(); + REMARK("%d thread local objects allocated in advance\n", tls_key_count); + + Harness::LIBRARY_HANDLE hLib; +#if _WIN32 || _WIN64 + hLib = LoadLibrary("irml.dll"); + if ( !hLib ) + hLib = LoadLibrary("irml_debug.dll"); + if ( !hLib ) + return Harness::Skipped; // No shared RML, skip the test + FreeLibrary(hLib); +#else /* !WIN */ +#if __TBB_ARENA_PER_MASTER + hLib = dlopen(RML_LIBRARY_NAME("libirml"), RTLD_LAZY); + if ( !hLib ) + hLib = dlopen(RML_LIBRARY_NAME("libirml_debug"), RTLD_LAZY); + if ( !hLib ) + return Harness::Skipped; + dlclose(hLib); +#endif /* __TBB_ARENA_PER_MASTER */ +#endif /* OS */ + for( int i=1; i<100; ++i ) { + REMARK("Iteration %d, loading plugin library...\n", i); + hLib = Harness::OpenLibrary(TEST_LIBRARY_NAME("test_model_plugin_dll")); + if ( !hLib ) { +#if !__TBB_NO_IMPLICIT_LINKAGE +#if _WIN32 || _WIN64 + report_error_in("LoadLibrary"); +#else + report_error_in("dlopen"); +#endif + return -1; +#else + return Harness::Skipped; +#endif + } + my_plugin_call = (PLUGIN_CALL)Harness::GetAddress(hLib, "plugin_call"); + if (my_plugin_call==NULL) { +#if _WIN32 || _WIN64 + report_error_in("GetProcAddress"); +#else + report_error_in("dlsym"); +#endif + return -1; + } + REMARK("Calling plugin method...\n"); + my_plugin_call(MaxThread); + + REMARK("Unloading plugin library...\n"); + Harness::CloseLibrary(hLib); + } // end for(1,100) + + return Harness::Done; +#else + return Harness::Skipped; +#endif /* !RML_USE_WCRM */ +} + +#endif//_USRDLL +#endif//__MIC__ diff --git a/src/tbb/src/test/test_multifunction_node.cpp b/src/tbb/src/test/test_multifunction_node.cpp new file mode 100644 index 0000000..9e2935d --- /dev/null +++ b/src/tbb/src/test/test_multifunction_node.cpp @@ -0,0 +1,470 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "harness_graph.h" + +#include "tbb/task_scheduler_init.h" +#include "tbb/spin_mutex.h" + +#if !__SUNPRO_CC + +tbb::spin_mutex global_mutex; + +#define N 100 +#define MAX_NODES 4 + +//! Performs test on function nodes with limited concurrency and buffering +/** Theses tests check: + 1) that the number of executing copies never exceed the concurreny limit + 2) that the node never rejects + 3) that no items are lost + and 4) all of this happens even if there are multiple predecessors and successors +*/ + +template< typename InputType > +struct parallel_put_until_limit : private NoAssign { + + harness_counting_sender<InputType> *my_senders; + + parallel_put_until_limit( harness_counting_sender<InputType> *senders ) : my_senders(senders) {} + + void operator()( int i ) const { + if ( my_senders ) { + my_senders[i].try_put_until_limit(); + } + } + +}; + +//! exercise buffered multifunction_node. +template< typename InputType, typename OutputTuple, typename Body > +void buffered_levels( size_t concurrency, Body body ) { + typedef typename std::tuple_element<0,OutputTuple>::type OutputType; + // Do for lc = 1 to concurrency level + for ( size_t lc = 1; lc <= concurrency; ++lc ) { + tbb::flow::graph g; + + // Set the execute_counter back to zero in the harness + harness_graph_multifunction_executor<InputType, OutputTuple,tbb::spin_mutex>::execute_count = 0; + // Set the max allowed executors to lc. There is a check in the functor to make sure this is never exceeded. + harness_graph_multifunction_executor<InputType, OutputTuple,tbb::spin_mutex>::max_executors = lc; + + // Create the function_node with the appropriate concurreny level, and use default buffering + tbb::flow::multifunction_node< InputType, OutputTuple > exe_node( g, lc, body ); + + //Create a vector of identical exe_nodes + std::vector< tbb::flow::multifunction_node< InputType, OutputTuple > > exe_vec(2, exe_node); + + // exercise each of the copied nodes + for (size_t node_idx=0; node_idx<exe_vec.size(); ++node_idx) { + for (size_t num_receivers = 1; num_receivers <= MAX_NODES; ++num_receivers ) { + // Create num_receivers counting receivers and connect the exe_vec[node_idx] to them. + harness_mapped_receiver<OutputType> *receivers = new harness_mapped_receiver<OutputType>[num_receivers]; + for (size_t r = 0; r < num_receivers; ++r ) { + tbb::flow::make_edge( tbb::flow::output_port<0>(exe_vec[node_idx]), receivers[r] ); + } + + // Do the test with varying numbers of senders + harness_counting_sender<InputType> *senders = NULL; + for (size_t num_senders = 1; num_senders <= MAX_NODES; ++num_senders ) { + // Create num_senders senders, set there message limit each to N, and connect them to the exe_vec[node_idx] + senders = new harness_counting_sender<InputType>[num_senders]; + for (size_t s = 0; s < num_senders; ++s ) { + senders[s].my_limit = N; + tbb::flow::make_edge( senders[s], exe_vec[node_idx] ); + } + + // Initialize the receivers so they know how many senders and messages to check for + for (size_t r = 0; r < num_receivers; ++r ) { + receivers[r].initialize_map( N, num_senders ); + } + + // Do the test + NativeParallelFor( (int)num_senders, parallel_put_until_limit<InputType>(senders) ); + g.wait_for_all(); + + // cofirm that each sender was requested from N times + for (size_t s = 0; s < num_senders; ++s ) { + size_t n = senders[s].my_received; + ASSERT( n == N, NULL ); + ASSERT( senders[s].my_receiver == &exe_vec[node_idx], NULL ); + } + // validate the receivers + for (size_t r = 0; r < num_receivers; ++r ) { + receivers[r].validate(); + } + delete [] senders; + } + for (size_t r = 0; r < num_receivers; ++r ) { + tbb::flow::remove_edge( tbb::flow::output_port<0>(exe_vec[node_idx]), receivers[r] ); + } + ASSERT( exe_vec[node_idx].try_put( InputType() ) == true, NULL ); + g.wait_for_all(); + for (size_t r = 0; r < num_receivers; ++r ) { + // since it's detached, nothing should have changed + receivers[r].validate(); + } + delete [] receivers; + } + } + } +} + +const size_t Offset = 123; +tbb::atomic<size_t> global_execute_count; + +struct inc_functor { + + tbb::atomic<size_t> local_execute_count; + inc_functor( ) { local_execute_count = 0; } + inc_functor( const inc_functor &f ) { local_execute_count = f.local_execute_count; } + + template<typename output_ports_type> + void operator()( int i, output_ports_type &p ) { + ++global_execute_count; + ++local_execute_count; + (void)std::get<0>(p).try_put(i); + } + +}; + +template< typename InputType, typename OutputTuple > +void buffered_levels_with_copy( size_t concurrency ) { + typedef typename std::tuple_element<0,OutputTuple>::type OutputType; + // Do for lc = 1 to concurrency level + for ( size_t lc = 1; lc <= concurrency; ++lc ) { + tbb::flow::graph g; + + inc_functor cf; + cf.local_execute_count = Offset; + global_execute_count = Offset; + + tbb::flow::multifunction_node< InputType, OutputTuple > exe_node( g, lc, cf ); + + for (size_t num_receivers = 1; num_receivers <= MAX_NODES; ++num_receivers ) { + harness_mapped_receiver<OutputType> *receivers = new harness_mapped_receiver<OutputType>[num_receivers]; + for (size_t r = 0; r < num_receivers; ++r ) { + tbb::flow::make_edge( tbb::flow::output_port<0>(exe_node), receivers[r] ); + } + + harness_counting_sender<InputType> *senders = NULL; + for (size_t num_senders = 1; num_senders <= MAX_NODES; ++num_senders ) { + senders = new harness_counting_sender<InputType>[num_senders]; + for (size_t s = 0; s < num_senders; ++s ) { + senders[s].my_limit = N; + tbb::flow::make_edge( senders[s], exe_node ); + } + + for (size_t r = 0; r < num_receivers; ++r ) { + receivers[r].initialize_map( N, num_senders ); + } + + NativeParallelFor( (int)num_senders, parallel_put_until_limit<InputType>(senders) ); + g.wait_for_all(); + + for (size_t s = 0; s < num_senders; ++s ) { + size_t n = senders[s].my_received; + ASSERT( n == N, NULL ); + ASSERT( senders[s].my_receiver == &exe_node, NULL ); + } + for (size_t r = 0; r < num_receivers; ++r ) { + receivers[r].validate(); + } + delete [] senders; + } + for (size_t r = 0; r < num_receivers; ++r ) { + tbb::flow::remove_edge( tbb::flow::output_port<0>(exe_node), receivers[r] ); + } + ASSERT( exe_node.try_put( InputType() ) == true, NULL ); + g.wait_for_all(); + for (size_t r = 0; r < num_receivers; ++r ) { + receivers[r].validate(); + } + delete [] receivers; + } + + // validate that the local body matches the global execute_count and both are correct + inc_functor body_copy = tbb::flow::copy_body<inc_functor>( exe_node ); + const size_t expected_count = N/2 * MAX_NODES * MAX_NODES * ( MAX_NODES + 1 ) + MAX_NODES + Offset; + size_t global_count = global_execute_count; + size_t inc_count = body_copy.local_execute_count; + ASSERT( global_count == expected_count && global_count == inc_count, NULL ); + } +} + +template< typename InputType, typename OutputTuple > +void run_buffered_levels( int c ) { + typedef typename tbb::flow::multifunction_node<InputType,OutputTuple>::output_ports_type output_ports_type; + harness_graph_multifunction_executor<InputType, OutputTuple, tbb::spin_mutex>::max_executors = c; + #if __TBB_LAMBDAS_PRESENT + buffered_levels<InputType,OutputTuple>( c, []( InputType i, output_ports_type &p ) { harness_graph_multifunction_executor<InputType, OutputTuple, tbb::spin_mutex>::func(i,p); } ); + #endif + buffered_levels<InputType,OutputTuple>( c, &harness_graph_multifunction_executor<InputType, OutputTuple, tbb::spin_mutex>::func ); + buffered_levels<InputType,OutputTuple>( c, typename harness_graph_multifunction_executor<InputType, OutputTuple, tbb::spin_mutex>::functor() ); + buffered_levels_with_copy<InputType,OutputTuple>( c ); +} + + +//! Performs test on executable nodes with limited concurrency +/** Theses tests check: + 1) that the nodes will accepts puts up to the concurrency limit, + 2) the nodes do not exceed the concurrency limit even when run with more threads (this is checked in the harness_graph_executor), + 3) the nodes will receive puts from multiple successors simultaneously, + and 4) the nodes will send to multiple predecessors. + There is no checking of the contents of the messages for corruption. +*/ + +template< typename InputType, typename OutputTuple, typename Body > +void concurrency_levels( size_t concurrency, Body body ) { + typedef typename std::tuple_element<0,OutputTuple>::type OutputType; + for ( size_t lc = 1; lc <= concurrency; ++lc ) { + tbb::flow::graph g; + harness_graph_multifunction_executor<InputType, OutputTuple, tbb::spin_mutex>::execute_count = 0; + + tbb::flow::multifunction_node< InputType, OutputTuple, tbb::flow::rejecting > exe_node( g, lc, body ); + + for (size_t num_receivers = 1; num_receivers <= MAX_NODES; ++num_receivers ) { + + harness_counting_receiver<OutputType> *receivers = new harness_counting_receiver<OutputType>[num_receivers]; + + for (size_t r = 0; r < num_receivers; ++r ) { + tbb::flow::make_edge( tbb::flow::output_port<0>(exe_node), receivers[r] ); + } + + harness_counting_sender<InputType> *senders = NULL; + + for (size_t num_senders = 1; num_senders <= MAX_NODES; ++num_senders ) { + { + // lock m to prevent exe_node from finishing + tbb::spin_mutex::scoped_lock l( harness_graph_multifunction_executor< InputType, OutputTuple, tbb::spin_mutex >::mutex ); + + // put to lc level, it will accept and then block at m + for ( size_t c = 0 ; c < lc ; ++c ) { + ASSERT( exe_node.try_put( InputType() ) == true, NULL ); + } + // it only accepts to lc level + ASSERT( exe_node.try_put( InputType() ) == false, NULL ); + + senders = new harness_counting_sender<InputType>[num_senders]; + for (size_t s = 0; s < num_senders; ++s ) { + // register a sender + senders[s].my_limit = N; + exe_node.register_predecessor( senders[s] ); + } + + } // release lock at end of scope, setting the exe node free to continue + // wait for graph to settle down + g.wait_for_all(); + + // confirm that each sender was requested from N times + for (size_t s = 0; s < num_senders; ++s ) { + size_t n = senders[s].my_received; + ASSERT( n == N, NULL ); + ASSERT( senders[s].my_receiver == &exe_node, NULL ); + } + // confirm that each receivers got N * num_senders + the initial lc puts + for (size_t r = 0; r < num_receivers; ++r ) { + size_t n = receivers[r].my_count; + ASSERT( n == num_senders*N+lc, NULL ); + receivers[r].my_count = 0; + } + delete [] senders; + } + for (size_t r = 0; r < num_receivers; ++r ) { + tbb::flow::remove_edge( tbb::flow::output_port<0>(exe_node), receivers[r] ); + } + ASSERT( exe_node.try_put( InputType() ) == true, NULL ); + g.wait_for_all(); + for (size_t r = 0; r < num_receivers; ++r ) { + ASSERT( int(receivers[r].my_count) == 0, NULL ); + } + delete [] receivers; + } + } +} + +template< typename InputType, typename OutputTuple > +void run_concurrency_levels( int c ) { + harness_graph_multifunction_executor<InputType, OutputTuple, tbb::spin_mutex>::max_executors = c; + typedef typename tbb::flow::multifunction_node<InputType,OutputTuple>::output_ports_type output_ports_type; + #if __TBB_LAMBDAS_PRESENT + concurrency_levels<InputType,OutputTuple>( c, []( InputType i, output_ports_type &p ) { harness_graph_multifunction_executor<InputType, OutputTuple, tbb::spin_mutex>::func(i,p); } ); + #endif + concurrency_levels<InputType,OutputTuple>( c, &harness_graph_multifunction_executor<InputType, OutputTuple, tbb::spin_mutex>::func ); + concurrency_levels<InputType,OutputTuple>( c, typename harness_graph_multifunction_executor<InputType, OutputTuple, tbb::spin_mutex>::functor() ); +} + + +struct empty_no_assign { + empty_no_assign() {} + empty_no_assign( int ) {} + operator int() { return 0; } + operator int() const { return 0; } +}; + +template< typename InputType > +struct parallel_puts : private NoAssign { + + tbb::flow::receiver< InputType > * const my_exe_node; + + parallel_puts( tbb::flow::receiver< InputType > &exe_node ) : my_exe_node(&exe_node) {} + + void operator()( int ) const { + for ( int i = 0; i < N; ++i ) { + // the nodes will accept all puts + ASSERT( my_exe_node->try_put( InputType() ) == true, NULL ); + } + } + +}; + +//! Performs test on executable nodes with unlimited concurrency +/** These tests check: + 1) that the nodes will accept all puts + 2) the nodes will receive puts from multiple predecessors simultaneously, + and 3) the nodes will send to multiple successors. + There is no checking of the contents of the messages for corruption. +*/ + +template< typename InputType, typename OutputTuple, typename Body > +void unlimited_concurrency( Body body ) { + typedef typename std::tuple_element<0,OutputTuple>::type OutputType; + + for (int p = 1; p < 2*MaxThread; ++p) { + tbb::flow::graph g; + tbb::flow::multifunction_node< InputType, OutputTuple, tbb::flow::rejecting > exe_node( g, tbb::flow::unlimited, body ); + + for (size_t num_receivers = 1; num_receivers <= MAX_NODES; ++num_receivers ) { + harness_counting_receiver<OutputType> *receivers = new harness_counting_receiver<OutputType>[num_receivers]; + harness_graph_multifunction_executor<InputType, OutputTuple>::execute_count = 0; + + for (size_t r = 0; r < num_receivers; ++r ) { + tbb::flow::make_edge( tbb::flow::output_port<0>(exe_node), receivers[r] ); + } + + NativeParallelFor( p, parallel_puts<InputType>(exe_node) ); + g.wait_for_all(); + + // 2) the nodes will receive puts from multiple predecessors simultaneously, + size_t ec = harness_graph_multifunction_executor<InputType, OutputTuple>::execute_count; + ASSERT( (int)ec == p*N, NULL ); + for (size_t r = 0; r < num_receivers; ++r ) { + size_t c = receivers[r].my_count; + // 3) the nodes will send to multiple successors. + ASSERT( (int)c == p*N, NULL ); + } + } + } +} + +template< typename InputType, typename OutputTuple > +void run_unlimited_concurrency() { + typedef typename tbb::flow::multifunction_node<InputType,OutputTuple>::output_ports_type output_ports_type; + harness_graph_multifunction_executor<InputType, OutputTuple>::max_executors = 0; + #if __TBB_LAMBDAS_PRESENT + unlimited_concurrency<InputType,OutputTuple>( []( InputType i, output_ports_type &p ) { harness_graph_multifunction_executor<InputType, OutputTuple>::func(i,p); } ); + #endif + unlimited_concurrency<InputType,OutputTuple>( &harness_graph_multifunction_executor<InputType, OutputTuple>::func ); + unlimited_concurrency<InputType,OutputTuple>( typename harness_graph_multifunction_executor<InputType, OutputTuple>::functor() ); +} + +template<typename InputType, typename OutputTuple> +struct oddEvenBody { + typedef typename tbb::flow::multifunction_node<InputType,OutputTuple>::output_ports_type output_ports_type; + typedef typename std::tuple_element<0,OutputTuple>::type EvenType; + typedef typename std::tuple_element<1,OutputTuple>::type OddType; + void operator() (const InputType &i, output_ports_type &p) { + if((int)i % 2) { + (void)std::get<1>(p).try_put(OddType(i)); + } + else { + (void)std::get<0>(p).try_put(EvenType(i)); + } + } +}; + +template<typename InputType, typename OutputTuple > +void run_multiport_test(int num_threads) { + typedef typename tbb::flow::multifunction_node<InputType, OutputTuple> mo_node_type; + typedef typename std::tuple_element<0,OutputTuple>::type EvenType; + typedef typename std::tuple_element<1,OutputTuple>::type OddType; + tbb::task_scheduler_init init(num_threads); + tbb::flow::graph g; + mo_node_type mo_node(g, tbb::flow::unlimited, oddEvenBody<InputType, OutputTuple>() ); + + tbb::flow::queue_node<EvenType> q0(g); + tbb::flow::queue_node<OddType> q1(g); + + tbb::flow::make_edge(tbb::flow::output_port<0>(mo_node), q0); + tbb::flow::make_edge(tbb::flow::output_port<1>(mo_node), q1); + + for(InputType i = 0; i < N; ++i) { + mo_node.try_put(i); + } + + g.wait_for_all(); + for(int i = 0; i < N/2; ++i) { + EvenType e; + OddType o; + ASSERT(q0.try_get(e) && (int)e % 2 == 0, NULL); + ASSERT(q1.try_get(o) && (int)o % 2 == 1, NULL); + } +} + +//! Tests limited concurrency cases for nodes that accept data messages +void test_concurrency(int num_threads) { + tbb::task_scheduler_init init(num_threads); + run_concurrency_levels<int,std::tuple<int> >(num_threads); + run_concurrency_levels<int,std::tuple<tbb::flow::continue_msg> >(num_threads); + run_buffered_levels<int, std::tuple<int> >(num_threads); + run_unlimited_concurrency<int, std::tuple<int> >(); + run_unlimited_concurrency<int,std::tuple<empty_no_assign> >(); + run_unlimited_concurrency<empty_no_assign,std::tuple<int> >(); + run_unlimited_concurrency<empty_no_assign,std::tuple<empty_no_assign> >(); + run_unlimited_concurrency<int,std::tuple<tbb::flow::continue_msg> >(); + run_unlimited_concurrency<empty_no_assign,std::tuple<tbb::flow::continue_msg> >(); + run_multiport_test<int, std::tuple<int, int> >(num_threads); + run_multiport_test<float, std::tuple<int, double> >(num_threads); +} + +int TestMain() { + current_executors = 0; + if( MinThread<1 ) { + REPORT("number of threads must be positive\n"); + exit(1); + } + for( int p=MinThread; p<=MaxThread; ++p ) { + test_concurrency(p); + } + return Harness::Done; +} +#else // __SUNPRO_CC +int TestMain() { + return Harness::Skipped; +} +#endif // __SUNPRO_CC diff --git a/src/tbb/src/test/test_mutex.cpp b/src/tbb/src/test/test_mutex.cpp new file mode 100644 index 0000000..cb3cc26 --- /dev/null +++ b/src/tbb/src/test/test_mutex.cpp @@ -0,0 +1,616 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +//------------------------------------------------------------------------ +// Test TBB mutexes when used with parallel_for.h +// +// Usage: test_Mutex.exe [-v] nthread +// +// The -v option causes timing information to be printed. +// +// Compile with _OPENMP and -openmp +//------------------------------------------------------------------------ +#include "tbb/spin_mutex.h" +#include "tbb/critical_section.h" +#include "tbb/spin_rw_mutex.h" +#include "tbb/queuing_rw_mutex.h" +#include "tbb/queuing_mutex.h" +#include "tbb/mutex.h" +#include "tbb/recursive_mutex.h" +#include "tbb/null_mutex.h" +#include "tbb/null_rw_mutex.h" +#include "tbb/parallel_for.h" +#include "tbb/blocked_range.h" +#include "tbb/tick_count.h" +#include "tbb/atomic.h" +#include "harness.h" +#include <cstdlib> +#include <cstdio> +#if _OPENMP +#include "test/OpenMP_Mutex.h" +#endif /* _OPENMP */ +#include "tbb/tbb_profiling.h" + +#ifndef TBB_TEST_LOW_WORKLOAD + #define TBB_TEST_LOW_WORKLOAD TBB_USE_THREADING_TOOLS +#endif + +// This test deliberately avoids a "using tbb" statement, +// so that the error of putting types in the wrong namespace will be caught. + +template<typename M> +struct Counter { + typedef M mutex_type; + M mutex; + volatile long value; +}; + +//! Function object for use with parallel_for.h. +template<typename C> +struct AddOne: NoAssign { + C& counter; + /** Increments counter once for each iteration in the iteration space. */ + void operator()( tbb::blocked_range<size_t>& range ) const { + for( size_t i=range.begin(); i!=range.end(); ++i ) { + if( i&1 ) { + // Try implicit acquire and explicit release + typename C::mutex_type::scoped_lock lock(counter.mutex); + counter.value = counter.value+1; + lock.release(); + } else { + // Try explicit acquire and implicit release + typename C::mutex_type::scoped_lock lock; + lock.acquire(counter.mutex); + counter.value = counter.value+1; + } + } + } + AddOne( C& counter_ ) : counter(counter_) {} +}; + +//! Adaptor for using ISO C++0x style mutex as a TBB-style mutex. +template<typename M> +class TBB_MutexFromISO_Mutex { + M my_iso_mutex; +public: + typedef TBB_MutexFromISO_Mutex mutex_type; + + class scoped_lock; + friend class scoped_lock; + + class scoped_lock { + mutex_type* my_mutex; + public: + scoped_lock() : my_mutex(NULL) {} + scoped_lock( mutex_type& m ) : my_mutex(NULL) { + acquire(m); + } + scoped_lock( mutex_type& m, bool is_writer ) : my_mutex(NULL) { + acquire(m,is_writer); + } + void acquire( mutex_type& m ) { + m.my_iso_mutex.lock(); + my_mutex = &m; + } + bool try_acquire( mutex_type& m ) { + if( m.my_iso_mutex.try_lock() ) { + my_mutex = &m; + return true; + } else { + return false; + } + } + void release() { + my_mutex->my_iso_mutex.unlock(); + my_mutex = NULL; + } + + // Methods for reader-writer mutex + // These methods can be instantiated only if M supports lock_read() and try_lock_read(). + + void acquire( mutex_type& m, bool is_writer ) { + if( is_writer ) m.my_iso_mutex.lock(); + else m.my_iso_mutex.lock_read(); + my_mutex = &m; + } + bool try_acquire( mutex_type& m, bool is_writer ) { + if( is_writer ? m.my_iso_mutex.try_lock() : m.my_iso_mutex.try_lock_read() ) { + my_mutex = &m; + return true; + } else { + return false; + } + } + bool upgrade_to_writer() { + my_mutex->my_iso_mutex.unlock(); + my_mutex->my_iso_mutex.lock(); + return false; + } + bool downgrade_to_reader() { + my_mutex->my_iso_mutex.unlock(); + my_mutex->my_iso_mutex.lock_read(); + return false; + } + ~scoped_lock() { + if( my_mutex ) + release(); + } + }; + + static const bool is_recursive_mutex = M::is_recursive_mutex; + static const bool is_rw_mutex = M::is_rw_mutex; +}; + +namespace tbb { + namespace profiling { + template<typename M> + void set_name( const TBB_MutexFromISO_Mutex<M>&, const char* ) {} + } +} + +//! Generic test of a TBB mutex type M. +/** Does not test features specific to reader-writer locks. */ +template<typename M> +void Test( const char * name ) { + REMARK("%s time = ",name); + Counter<M> counter; + counter.value = 0; + tbb::profiling::set_name(counter.mutex, name); +#if TBB_TEST_LOW_WORKLOAD + const int n = 10000; +#else + const int n = 100000; +#endif /* TBB_TEST_LOW_WORKLOAD */ + tbb::tick_count t0 = tbb::tick_count::now(); + tbb::parallel_for(tbb::blocked_range<size_t>(0,n,n/10),AddOne<Counter<M> >(counter)); + tbb::tick_count t1 = tbb::tick_count::now(); + REMARK("%g usec\n",(t1-t0).seconds()); + if( counter.value!=n ) + REPORT("ERROR for %s: counter.value=%ld\n",name,counter.value); +} + +template<typename M, size_t N> +struct Invariant { + typedef M mutex_type; + M mutex; + const char* mutex_name; + volatile long value[N]; + volatile long single_value; + Invariant( const char* mutex_name_ ) : + mutex_name(mutex_name_) + { + single_value = 0; + for( size_t k=0; k<N; ++k ) + value[k] = 0; + tbb::profiling::set_name(mutex, mutex_name_); + } + void update() { + for( size_t k=0; k<N; ++k ) + ++value[k]; + } + bool value_is( long expected_value ) const { + long tmp; + for( size_t k=0; k<N; ++k ) + if( (tmp=value[k])!=expected_value ) { + REPORT("ERROR: %ld!=%ld\n", tmp, expected_value); + return false; + } + return true; + } + bool is_okay() { + return value_is( value[0] ); + } +}; + +//! Function object for use with parallel_for.h. +template<typename I> +struct TwiddleInvariant: NoAssign { + I& invariant; + TwiddleInvariant( I& invariant_ ) : invariant(invariant_) {} + + /** Increments counter once for each iteration in the iteration space. */ + void operator()( tbb::blocked_range<size_t>& range ) const { + for( size_t i=range.begin(); i!=range.end(); ++i ) { + //! Every 8th access is a write access + const bool write = (i%8)==7; + bool okay = true; + bool lock_kept = true; + if( (i/8)&1 ) { + // Try implicit acquire and explicit release + typename I::mutex_type::scoped_lock lock(invariant.mutex,write); + execute_aux(lock, i, write, /*ref*/okay, /*ref*/lock_kept); + lock.release(); + } else { + // Try explicit acquire and implicit release + typename I::mutex_type::scoped_lock lock; + lock.acquire(invariant.mutex,write); + execute_aux(lock, i, write, /*ref*/okay, /*ref*/lock_kept); + } + if( !okay ) { + REPORT( "ERROR for %s at %ld: %s %s %s %s\n",invariant.mutex_name, long(i), + write ? "write," : "read,", + write ? (i%16==7?"downgrade,":"") : (i%8==3?"upgrade,":""), + lock_kept ? "lock kept," : "lock not kept,", // TODO: only if downgrade/upgrade + (i/8)&1 ? "impl/expl" : "expl/impl" ); + } + } + } +private: + void execute_aux(typename I::mutex_type::scoped_lock & lock, const size_t i, const bool write, bool & okay, bool & lock_kept) const { + if( write ) { + long my_value = invariant.value[0]; + invariant.update(); + if( i%16==7 ) { + lock_kept = lock.downgrade_to_reader(); + if( !lock_kept ) + my_value = invariant.value[0] - 1; + okay = invariant.value_is(my_value+1); + } + } else { + okay = invariant.is_okay(); + if( i%8==3 ) { + long my_value = invariant.value[0]; + lock_kept = lock.upgrade_to_writer(); + if( !lock_kept ) + my_value = invariant.value[0]; + invariant.update(); + okay = invariant.value_is(my_value+1); + } + } + } +}; + +/** This test is generic so that we can test any other kinds of ReaderWriter locks we write later. */ +template<typename M> +void TestReaderWriterLock( const char * mutex_name ) { + REMARK( "%s readers & writers time = ", mutex_name ); + Invariant<M,8> invariant(mutex_name); +#if TBB_TEST_LOW_WORKLOAD + const size_t n = 10000; +#else + const size_t n = 500000; +#endif /* TBB_TEST_LOW_WORKLOAD */ + tbb::tick_count t0 = tbb::tick_count::now(); + tbb::parallel_for(tbb::blocked_range<size_t>(0,n,n/100),TwiddleInvariant<Invariant<M,8> >(invariant)); + tbb::tick_count t1 = tbb::tick_count::now(); + // There is either a writer or a reader upgraded to a writer for each 4th iteration + long expected_value = n/4; + if( !invariant.value_is(expected_value) ) + REPORT("ERROR for %s: final invariant value is wrong\n",mutex_name); + REMARK( "%g usec\n", (t1-t0).seconds() ); +} + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // Suppress "conditional expression is constant" warning. + #pragma warning( push ) + #pragma warning( disable: 4127 ) +#endif + +/** Test try_acquire_reader functionality of a non-reenterable reader-writer mutex */ +template<typename M> +void TestTryAcquireReader_OneThread( const char * mutex_name ) { + M tested_mutex; + typename M::scoped_lock lock1; + if( M::is_rw_mutex ) { + if( lock1.try_acquire(tested_mutex, false) ) + lock1.release(); + else + REPORT("ERROR for %s: try_acquire failed though it should not\n", mutex_name); + { + typename M::scoped_lock lock2(tested_mutex, false); + if( lock1.try_acquire(tested_mutex) ) + REPORT("ERROR for %s: try_acquire succeeded though it should not\n", mutex_name); + lock2.release(); + lock2.acquire(tested_mutex, true); + if( lock1.try_acquire(tested_mutex, false) ) + REPORT("ERROR for %s: try_acquire succeeded though it should not\n", mutex_name); + } + if( lock1.try_acquire(tested_mutex, false) ) + lock1.release(); + else + REPORT("ERROR for %s: try_acquire failed though it should not\n", mutex_name); + } +} + +/** Test try_acquire functionality of a non-reenterable mutex */ +template<typename M> +void TestTryAcquire_OneThread( const char * mutex_name ) { + M tested_mutex; + typename M::scoped_lock lock1; + if( lock1.try_acquire(tested_mutex) ) + lock1.release(); + else + REPORT("ERROR for %s: try_acquire failed though it should not\n", mutex_name); + { + if( M::is_recursive_mutex ) { + typename M::scoped_lock lock2(tested_mutex); + if( lock1.try_acquire(tested_mutex) ) + lock1.release(); + else + REPORT("ERROR for %s: try_acquire on recursive lock failed though it should not\n", mutex_name); + //windows.. -- both are recursive + } else { + typename M::scoped_lock lock2(tested_mutex); + if( lock1.try_acquire(tested_mutex) ) + REPORT("ERROR for %s: try_acquire succeeded though it should not\n", mutex_name); + } + } + if( lock1.try_acquire(tested_mutex) ) + lock1.release(); + else + REPORT("ERROR for %s: try_acquire failed though it should not\n", mutex_name); +} + +#if _MSC_VER && !defined(__INTEL_COMPILER) + #pragma warning( pop ) +#endif + +const int RecurN = 4; +int RecurArray[ RecurN ]; +tbb::recursive_mutex RecurMutex[ RecurN ]; + +struct RecursiveAcquisition { + /** x = number being decoded in base N + max_lock = index of highest lock acquired so far + mask = bit mask; ith bit set if lock i has been acquired. */ + void Body( size_t x, int max_lock=-1, unsigned int mask=0 ) const + { + int i = (int) (x % RecurN); + bool first = (mask&1U<<i)==0; + if( first ) { + // first time to acquire lock + if( i<max_lock ) + // out of order acquisition might lead to deadlock, so stop + return; + max_lock = i; + } + + if( (i&1)!=0 ) { + // acquire lock on location RecurArray[i] using explict acquire + tbb::recursive_mutex::scoped_lock r_lock; + r_lock.acquire( RecurMutex[i] ); + int a = RecurArray[i]; + ASSERT( (a==0)==first, "should be either a==0 if it is the first time to acquire the lock or a!=0 otherwise" ); + ++RecurArray[i]; + if( x ) + Body( x/RecurN, max_lock, mask|1U<<i ); + --RecurArray[i]; + ASSERT( a==RecurArray[i], "a is not equal to RecurArray[i]" ); + + // release lock on location RecurArray[i] using explicit release; otherwise, use implicit one + if( (i&2)!=0 ) r_lock.release(); + } else { + // acquire lock on location RecurArray[i] using implicit acquire + tbb::recursive_mutex::scoped_lock r_lock( RecurMutex[i] ); + int a = RecurArray[i]; + + ASSERT( (a==0)==first, "should be either a==0 if it is the first time to acquire the lock or a!=0 otherwise" ); + + ++RecurArray[i]; + if( x ) + Body( x/RecurN, max_lock, mask|1U<<i ); + --RecurArray[i]; + + ASSERT( a==RecurArray[i], "a is not equal to RecurArray[i]" ); + + // release lock on location RecurArray[i] using explicit release; otherwise, use implicit one + if( (i&2)!=0 ) r_lock.release(); + } + } + + void operator()( const tbb::blocked_range<size_t> &r ) const + { + for( size_t x=r.begin(); x<r.end(); x++ ) { + Body( x ); + } + } +}; + +/** This test is generic so that we may test other kinds of recursive mutexes.*/ +template<typename M> +void TestRecursiveMutex( const char * mutex_name ) +{ + for ( int i = 0; i < RecurN; ++i ) { + tbb::profiling::set_name(RecurMutex[i], mutex_name); + } + tbb::tick_count t0 = tbb::tick_count::now(); + tbb::parallel_for(tbb::blocked_range<size_t>(0,10000,500), RecursiveAcquisition()); + tbb::tick_count t1 = tbb::tick_count::now(); + REMARK( "%s recursive mutex time = %g usec\n", mutex_name, (t1-t0).seconds() ); +} + +template<typename C> +struct NullRecursive: NoAssign { + void recurse_till( size_t i, size_t till ) const { + if( i==till ) { + counter.value = counter.value+1; + return; + } + if( i&1 ) { + typename C::mutex_type::scoped_lock lock2(counter.mutex); + recurse_till( i+1, till ); + lock2.release(); + } else { + typename C::mutex_type::scoped_lock lock2; + lock2.acquire(counter.mutex); + recurse_till( i+1, till ); + } + } + + void operator()( tbb::blocked_range<size_t>& range ) const { + typename C::mutex_type::scoped_lock lock(counter.mutex); + recurse_till( range.begin(), range.end() ); + } + NullRecursive( C& counter_ ) : counter(counter_) { + ASSERT( C::mutex_type::is_recursive_mutex, "Null mutex should be a recursive mutex." ); + } + C& counter; +}; + +template<typename M> +struct NullUpgradeDowngrade: NoAssign { + void operator()( tbb::blocked_range<size_t>& range ) const { + typename M::scoped_lock lock2; + for( size_t i=range.begin(); i!=range.end(); ++i ) { + if( i&1 ) { + typename M::scoped_lock lock1(my_mutex, true) ; + if( lock1.downgrade_to_reader()==false ) + REPORT("ERROR for %s: downgrade should always succeed\n", name); + } else { + lock2.acquire( my_mutex, false ); + if( lock2.upgrade_to_writer()==false ) + REPORT("ERROR for %s: upgrade should always succeed\n", name); + lock2.release(); + } + } + } + + NullUpgradeDowngrade( M& m_, const char* n_ ) : my_mutex(m_), name(n_) {} + M& my_mutex; + const char* name; +} ; + +template<typename M> +void TestNullMutex( const char * name ) { + Counter<M> counter; + counter.value = 0; + const int n = 100; + REMARK("%s ",name); + { + tbb::parallel_for(tbb::blocked_range<size_t>(0,n,10),AddOne<Counter<M> >(counter)); + } + counter.value = 0; + { + tbb::parallel_for(tbb::blocked_range<size_t>(0,n,10),NullRecursive<Counter<M> >(counter)); + } + +} + +template<typename M> +void TestNullRWMutex( const char * name ) { + REMARK("%s ",name); + const int n = 100; + M m; + tbb::parallel_for(tbb::blocked_range<size_t>(0,n,10),NullUpgradeDowngrade<M>(m, name)); +} + +//! Test ISO C++0x compatibility portion of TBB mutex +template<typename M> +void TestISO( const char * name ) { + typedef TBB_MutexFromISO_Mutex<M> tbb_from_iso; + Test<tbb_from_iso>( name ); +} + +//! Test ISO C++0x try_lock functionality of a non-reenterable mutex */ +template<typename M> +void TestTryAcquire_OneThreadISO( const char * name ) { + typedef TBB_MutexFromISO_Mutex<M> tbb_from_iso; + TestTryAcquire_OneThread<tbb_from_iso>( name ); +} + +//! Test ISO-like C++0x compatibility portion of TBB reader-writer mutex +template<typename M> +void TestReaderWriterLockISO( const char * name ) { + typedef TBB_MutexFromISO_Mutex<M> tbb_from_iso; + TestReaderWriterLock<tbb_from_iso>( name ); + TestTryAcquireReader_OneThread<tbb_from_iso>( name ); +} + +//! Test ISO C++0x compatibility portion of TBB recursive mutex +template<typename M> +void TestRecursiveMutexISO( const char * name ) { + typedef TBB_MutexFromISO_Mutex<M> tbb_from_iso; + TestRecursiveMutex<tbb_from_iso>(name); +} + +#include "tbb/task_scheduler_init.h" + +int TestMain () { + for( int p=MinThread; p<=MaxThread; ++p ) { + tbb::task_scheduler_init init( p ); + REMARK( "testing with %d workers\n", static_cast<int>(p) ); +#if TBB_TEST_LOW_WORKLOAD + // The amount of work is decreased in this mode to bring the length + // of the runs under tools into the tolerable limits. + const int n = 1; +#else + const int n = 3; +#endif + // Run each test several times. + for( int i=0; i<n; ++i ) { + TestNullMutex<tbb::null_mutex>( "Null Mutex" ); + TestNullMutex<tbb::null_rw_mutex>( "Null RW Mutex" ); + TestNullRWMutex<tbb::null_rw_mutex>( "Null RW Mutex" ); + Test<tbb::spin_mutex>( "Spin Mutex" ); +#if _OPENMP + Test<OpenMP_Mutex>( "OpenMP_Mutex" ); +#endif /* _OPENMP */ + Test<tbb::queuing_mutex>( "Queuing Mutex" ); + Test<tbb::mutex>( "Wrapper Mutex" ); + Test<tbb::recursive_mutex>( "Recursive Mutex" ); + Test<tbb::queuing_rw_mutex>( "Queuing RW Mutex" ); + Test<tbb::spin_rw_mutex>( "Spin RW Mutex" ); + + TestTryAcquire_OneThread<tbb::spin_mutex>("Spin Mutex"); + TestTryAcquire_OneThread<tbb::queuing_mutex>("Queuing Mutex"); +#if USE_PTHREAD + // under ifdef because on Windows tbb::mutex is reenterable and the test will fail + TestTryAcquire_OneThread<tbb::mutex>("Wrapper Mutex"); +#endif /* USE_PTHREAD */ + TestTryAcquire_OneThread<tbb::recursive_mutex>( "Recursive Mutex" ); + TestTryAcquire_OneThread<tbb::spin_rw_mutex>("Spin RW Mutex"); // only tests try_acquire for writers + TestTryAcquire_OneThread<tbb::queuing_rw_mutex>("Queuing RW Mutex"); // only tests try_acquire for writers + TestTryAcquireReader_OneThread<tbb::spin_rw_mutex>("Spin RW Mutex"); + TestTryAcquireReader_OneThread<tbb::queuing_rw_mutex>("Queuing RW Mutex"); + + TestReaderWriterLock<tbb::queuing_rw_mutex>( "Queuing RW Mutex" ); + TestReaderWriterLock<tbb::spin_rw_mutex>( "Spin RW Mutex" ); + + TestRecursiveMutex<tbb::recursive_mutex>( "Recursive Mutex" ); + + // Test ISO C++0x interface + TestISO<tbb::spin_mutex>( "ISO Spin Mutex" ); + TestISO<tbb::mutex>( "ISO Mutex" ); + TestISO<tbb::spin_rw_mutex>( "ISO Spin RW Mutex" ); + TestISO<tbb::recursive_mutex>( "ISO Recursive Mutex" ); + TestISO<tbb::critical_section>( "ISO Critical Section" ); + TestTryAcquire_OneThreadISO<tbb::spin_mutex>( "ISO Spin Mutex" ); +#if USE_PTHREAD + // under ifdef because on Windows tbb::mutex is reenterable and the test will fail + TestTryAcquire_OneThreadISO<tbb::mutex>( "ISO Mutex" ); +#endif /* USE_PTHREAD */ + TestTryAcquire_OneThreadISO<tbb::spin_rw_mutex>( "ISO Spin RW Mutex" ); + TestTryAcquire_OneThreadISO<tbb::recursive_mutex>( "ISO Recursive Mutex" ); + TestTryAcquire_OneThreadISO<tbb::critical_section>( "ISO Critical Section" ); + TestReaderWriterLockISO<tbb::spin_rw_mutex>( "ISO Spin RW Mutex" ); + TestRecursiveMutexISO<tbb::recursive_mutex>( "ISO Recursive Mutex" ); + } + REMARK( "calling destructor for task_scheduler_init\n" ); + } + return Harness::Done; +} diff --git a/src/tbb/src/test/test_mutex_native_threads.cpp b/src/tbb/src/test/test_mutex_native_threads.cpp new file mode 100644 index 0000000..c198383 --- /dev/null +++ b/src/tbb/src/test/test_mutex_native_threads.cpp @@ -0,0 +1,228 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/spin_mutex.h" +#include "tbb/queuing_mutex.h" +#include "tbb/queuing_rw_mutex.h" +#include "tbb/spin_rw_mutex.h" +#include "tbb/tick_count.h" +#include "tbb/atomic.h" + +#include "harness.h" + +// This test deliberately avoids a "using tbb" statement, +// so that the error of putting types in the wrong namespace will be caught. + +template<typename M> +struct Counter { + typedef M mutex_type; + M mutex; + volatile long value; + void flog_once( size_t mode ); +}; + +template<typename M> +void Counter<M>::flog_once(size_t mode) +/** Increments counter once for each iteration in the iteration space. */ +{ + if( mode&1 ) { + // Try implicit acquire and explicit release + typename mutex_type::scoped_lock lock(mutex); + value = value+1; + lock.release(); + } else { + // Try explicit acquire and implicit release + typename mutex_type::scoped_lock lock; + lock.acquire(mutex); + value = value+1; + } +} + +template<typename M, long N> +struct Invariant { + typedef M mutex_type; + M mutex; + const char* mutex_name; + volatile long value[N]; + volatile long single_value; + Invariant( const char* mutex_name_ ) : + mutex_name(mutex_name_) + { + single_value = 0; + for( long k=0; k<N; ++k ) + value[k] = 0; + } + void update() { + for( long k=0; k<N; ++k ) + ++value[k]; + } + bool value_is( long expected_value ) const { + long tmp; + for( long k=0; k<N; ++k ) + if( (tmp=value[k])!=expected_value ) { + REPORT("ERROR: %ld!=%ld\n", tmp, expected_value); + return false; + } + return true; + } + bool is_okay() { + return value_is( value[0] ); + } + void flog_once( size_t mode ); +}; + +template<typename M, long N> +void Invariant<M,N>::flog_once( size_t mode ) +{ + //! Every 8th access is a write access + bool write = (mode%8)==7; + bool okay = true; + bool lock_kept = true; + if( (mode/8)&1 ) { + // Try implicit acquire and explicit release + typename mutex_type::scoped_lock lock(mutex,write); + if( write ) { + long my_value = value[0]; + update(); + if( mode%16==7 ) { + lock_kept = lock.downgrade_to_reader(); + if( !lock_kept ) + my_value = value[0] - 1; + okay = value_is(my_value+1); + } + } else { + okay = is_okay(); + if( mode%8==3 ) { + long my_value = value[0]; + lock_kept = lock.upgrade_to_writer(); + if( !lock_kept ) + my_value = value[0]; + update(); + okay = value_is(my_value+1); + } + } + lock.release(); + } else { + // Try explicit acquire and implicit release + typename mutex_type::scoped_lock lock; + lock.acquire(mutex,write); + if( write ) { + long my_value = value[0]; + update(); + if( mode%16==7 ) { + lock_kept = lock.downgrade_to_reader(); + if( !lock_kept ) + my_value = value[0] - 1; + okay = value_is(my_value+1); + } + } else { + okay = is_okay(); + if( mode%8==3 ) { + long my_value = value[0]; + lock_kept = lock.upgrade_to_writer(); + if( !lock_kept ) + my_value = value[0]; + update(); + okay = value_is(my_value+1); + } + } + } + if( !okay ) { + REPORT( "ERROR for %s at %ld: %s %s %s %s\n",mutex_name, long(mode), + write?"write,":"read,", write?(mode%16==7?"downgrade,":""):(mode%8==3?"upgrade,":""), + lock_kept?"lock kept,":"lock not kept,", (mode/8)&1?"imp/exp":"exp/imp" ); + } +} + +static tbb::atomic<size_t> Order; + +template<typename State, long TestSize> +struct Work: NoAssign { + static const size_t chunk = 100; + State& state; + Work( State& state_ ) : state(state_) {} + void operator()( int ) const { + size_t step; + while( (step=Order.fetch_and_add<tbb::acquire>(chunk))<TestSize ) + for( size_t i=0; i<chunk && step<TestSize; ++i, ++step ) + state.flog_once(step); + } +}; + +//! Generic test of a TBB Mutex type M. +/** Does not test features specific to reader-writer locks. */ +template<typename M> +void Test( const char * name, int nthread ) { + REMARK("testing %s\n",name); + Counter<M> counter; + counter.value = 0; + Order = 0; + // use the macro because of a gcc 4.6 bug +#define TEST_SIZE 100000 + tbb::tick_count t0 = tbb::tick_count::now(); + NativeParallelFor( nthread, Work<Counter<M>, TEST_SIZE>(counter) ); + tbb::tick_count t1 = tbb::tick_count::now(); + + REMARK("%s time = %g usec\n",name, (t1-t0).seconds() ); + if( counter.value!=TEST_SIZE ) + REPORT("ERROR for %s: counter.value=%ld != %ld=test_size\n",name,counter.value,TEST_SIZE); +#undef TEST_SIZE +} + + +//! Generic test of TBB ReaderWriterMutex type M +template<typename M> +void TestReaderWriter( const char * mutex_name, int nthread ) { + REMARK("testing %s\n",mutex_name); + Invariant<M,8> invariant(mutex_name); + Order = 0; + // use the macro because of a gcc 4.6 bug +#define TEST_SIZE 1000000 + tbb::tick_count t0 = tbb::tick_count::now(); + NativeParallelFor( nthread, Work<Invariant<M,8>, TEST_SIZE>(invariant) ); + tbb::tick_count t1 = tbb::tick_count::now(); + // There is either a writer or a reader upgraded to a writer for each 4th iteration + long expected_value = TEST_SIZE/4; + if( !invariant.value_is(expected_value) ) + REPORT("ERROR for %s: final invariant value is wrong\n",mutex_name); + REMARK("%s readers & writers time = %g usec\n",mutex_name,(t1-t0).seconds()); +#undef TEST_SIZE +} + +int TestMain () { + for( int p=MinThread; p<=MaxThread; ++p ) { + REMARK( "testing with %d threads\n", p ); + Test<tbb::spin_mutex>( "spin_mutex", p ); + Test<tbb::queuing_mutex>( "queuing_mutex", p ); + Test<tbb::queuing_rw_mutex>( "queuing_rw_mutex", p ); + Test<tbb::spin_rw_mutex>( "spin_rw_mutex", p ); + TestReaderWriter<tbb::queuing_rw_mutex>( "queuing_rw_mutex", p ); + TestReaderWriter<tbb::spin_rw_mutex>( "spin_rw_mutex", p ); + } + return Harness::Done; +} diff --git a/src/tbb/src/test/test_openmp.cpp b/src/tbb/src/test/test_openmp.cpp new file mode 100644 index 0000000..531c1f3 --- /dev/null +++ b/src/tbb/src/test/test_openmp.cpp @@ -0,0 +1,230 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Test mixing OpenMP and TBB + +/* SCR #471 + Bellow is workaround to compile test within enviroment of Intel Compiler + but by Microsoft Compiler. So, there is wrong "omp.h" file included and + manifest section is missed from .exe file - restoring here. + + As of Visual Studio 2010, crtassem.h is no longer shipped. + */ +#if !defined(__INTEL_COMPILER) && _MSC_VER >= 1400 && _MSC_VER < 1600 + #include <crtassem.h> + #if !defined(_OPENMP) + #define _OPENMP + #if defined(_DEBUG) + #pragma comment(lib, "vcompd") + #else // _DEBUG + #pragma comment(lib, "vcomp") + #endif // _DEBUG + #endif // _OPENMP + + #if defined(_DEBUG) + #if defined(_M_IX86) + #pragma comment(linker,"/manifestdependency:\"type='win32' " \ + "name='" __LIBRARIES_ASSEMBLY_NAME_PREFIX ".DebugOpenMP' " \ + "version='" _CRT_ASSEMBLY_VERSION "' " \ + "processorArchitecture='x86' " \ + "publicKeyToken='" _VC_ASSEMBLY_PUBLICKEYTOKEN "'\"") + #elif defined(_M_X64) + #pragma comment(linker,"/manifestdependency:\"type='win32' " \ + "name='" __LIBRARIES_ASSEMBLY_NAME_PREFIX ".DebugOpenMP' " \ + "version='" _CRT_ASSEMBLY_VERSION "' " \ + "processorArchitecture='amd64' " \ + "publicKeyToken='" _VC_ASSEMBLY_PUBLICKEYTOKEN "'\"") + #elif defined(_M_IA64) + #pragma comment(linker,"/manifestdependency:\"type='win32' " \ + "name='" __LIBRARIES_ASSEMBLY_NAME_PREFIX ".DebugOpenMP' " \ + "version='" _CRT_ASSEMBLY_VERSION "' " \ + "processorArchitecture='ia64' " \ + "publicKeyToken='" _VC_ASSEMBLY_PUBLICKEYTOKEN "'\"") + #endif + #else // _DEBUG + #if defined(_M_IX86) + #pragma comment(linker,"/manifestdependency:\"type='win32' " \ + "name='" __LIBRARIES_ASSEMBLY_NAME_PREFIX ".OpenMP' " \ + "version='" _CRT_ASSEMBLY_VERSION "' " \ + "processorArchitecture='x86' " \ + "publicKeyToken='" _VC_ASSEMBLY_PUBLICKEYTOKEN "'\"") + #elif defined(_M_X64) + #pragma comment(linker,"/manifestdependency:\"type='win32' " \ + "name='" __LIBRARIES_ASSEMBLY_NAME_PREFIX ".OpenMP' " \ + "version='" _CRT_ASSEMBLY_VERSION "' " \ + "processorArchitecture='amd64' " \ + "publicKeyToken='" _VC_ASSEMBLY_PUBLICKEYTOKEN "'\"") + #elif defined(_M_IA64) + #pragma comment(linker,"/manifestdependency:\"type='win32' " \ + "name='" __LIBRARIES_ASSEMBLY_NAME_PREFIX ".OpenMP' " \ + "version='" _CRT_ASSEMBLY_VERSION "' " \ + "processorArchitecture='ia64' " \ + "publicKeyToken='" _VC_ASSEMBLY_PUBLICKEYTOKEN "'\"") + #endif + #endif // _DEBUG + #define _OPENMP_NOFORCE_MANIFEST +#endif + +#include <omp.h> + + +typedef short T; + +void SerialConvolve( T c[], const T a[], int m, const T b[], int n ) { + for( int i=0; i<m+n-1; ++i ) { + int start = i<n ? 0 : i-n+1; + int finish = i<m ? i+1 : m; + T sum = 0; + for( int j=start; j<finish; ++j ) + sum += a[j]*b[i-j]; + c[i] = sum; + } +} + +#include "tbb/blocked_range.h" +#include "tbb/parallel_for.h" +#include "tbb/parallel_reduce.h" +#include "tbb/task_scheduler_init.h" +#include "harness.h" + +using namespace tbb; + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // Suppress overzealous warning about short+=short + #pragma warning( push ) + #pragma warning( disable: 4244 ) +#endif + +class InnerBody: NoAssign { + const T* my_a; + const T* my_b; + const int i; +public: + T sum; + InnerBody( T /*c*/[], const T a[], const T b[], int i ) : + my_a(a), my_b(b), i(i), sum(0) + {} + InnerBody( InnerBody& x, split ) : + my_a(x.my_a), my_b(x.my_b), i(x.i), sum(0) + { + } + void join( InnerBody& x ) {sum += x.sum;} + void operator()( const blocked_range<int>& range ) { + for( int j=range.begin(); j!=range.end(); ++j ) + sum += my_a[j]*my_b[i-j]; + } +}; + +#if _MSC_VER && !defined(__INTEL_COMPILER) + #pragma warning( pop ) +#endif + +//! Test OpenMMP loop around TBB loop +void OpenMP_TBB_Convolve( T c[], const T a[], int m, const T b[], int n ) { + REMARK("testing OpenMP loop around TBB loop\n"); +#pragma omp parallel + { + task_scheduler_init init; +#pragma omp for + for( int i=0; i<m+n-1; ++i ) { + int start = i<n ? 0 : i-n+1; + int finish = i<m ? i+1 : m; + InnerBody body(c,a,b,i); + parallel_reduce( blocked_range<int>(start,finish,10), body ); + c[i] = body.sum; + } + } +} + +class OuterBody: NoAssign { + const T* my_a; + const T* my_b; + T* my_c; + const int m; + const int n; +public: + T sum; + OuterBody( T c[], const T a[], int m_, const T b[], int n_ ) : + my_a(a), my_b(b), my_c(c), m(m_), n(n_) + {} + void operator()( const blocked_range<int>& range ) const { + for( int i=range.begin(); i!=range.end(); ++i ) { + int start = i<n ? 0 : i-n+1; + int finish = i<m ? i+1 : m; + T sum = 0; +#pragma omp parallel for reduction(+:sum) + for( int j=start; j<finish; ++j ) + sum += my_a[j]*my_b[i-j]; + my_c[i] = sum; + } + } +}; + +//! Test TBB loop around OpenMP loop +void TBB_OpenMP_Convolve( T c[], const T a[], int m, const T b[], int n ) { + REMARK("testing TBB loop around OpenMP loop\n"); + parallel_for( blocked_range<int>(0,m+n-1,10), OuterBody( c, a, m, b, n ) ); +} + +#include <stdio.h> + +const int M = 17*17; +const int N = 13*13; + +int TestMain () { + MinThread = 1; + for( int p=MinThread; p<=MaxThread; ++p ) { + T a[M]; + T b[N]; + for( int m=1; m<=M; m*=17 ) { + for( int n=1; n<=M; n*=13 ) { + for( int i=0; i<m; ++i ) a[i] = T(1+i/5); + for( int i=0; i<n; ++i ) b[i] = T(1+i/7); + T expected[M+N]; + SerialConvolve( expected, a, m, b, n ); + task_scheduler_init init(p); + T actual[M+N]; + for( int k = 0; k<2; ++k ) { + memset( actual, -1, sizeof(actual) ); + switch(k) { + case 0: + TBB_OpenMP_Convolve( actual, a, m, b, n ); + break; + case 1: + OpenMP_TBB_Convolve( actual, a, m, b, n ); + break; + } + for( int i=0; i<m+n-1; ++i ) { + ASSERT( actual[i]==expected[i], NULL ); + } + } + } + } + } + return Harness::Done; +} diff --git a/src/tbb/src/test/test_or_node.cpp b/src/tbb/src/test/test_or_node.cpp new file mode 100644 index 0000000..76406bb --- /dev/null +++ b/src/tbb/src/test/test_or_node.cpp @@ -0,0 +1,458 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "harness.h" +#define TBB_PREVIEW_GRAPH_NODES 1 +#include "tbb/flow_graph.h" + +#if !__SUNPRO_CC +// +// Tests +// + +const int Count = 150; +const int MaxPorts = 10; +const int MaxNSources = 5; // max # of source_nodes to register for each or_node input in parallel test +bool outputCheck[MaxPorts][Count]; // for checking output + +void +check_outputCheck( int nUsed, int maxCnt) { + for(int i=0; i < nUsed; ++i) { + for( int j = 0; j < maxCnt; ++j) { + ASSERT(outputCheck[i][j], NULL); + } + } +} + +void +reset_outputCheck( int nUsed, int maxCnt) { + for(int i=0; i < nUsed; ++i) { + for( int j = 0; j < maxCnt; ++j) { + outputCheck[i][j] = false; + } + } +} + +class test_class { + public: + test_class() { my_val = 0; } + test_class(int i) { my_val = i; } + operator int() { return my_val; } + private: + int my_val; +}; + +template<typename T> +class name_of { +public: + static const char* name() { return "Unknown"; } +}; +template<> +class name_of<int> { +public: + static const char* name() { return "int"; } +}; +template<> +class name_of<float> { +public: + static const char* name() { return "float"; } +}; +template<> +class name_of<double> { +public: + static const char* name() { return "double"; } +}; +template<> +class name_of<long> { +public: + static const char* name() { return "long"; } +}; +template<> +class name_of<short> { +public: + static const char* name() { return "short"; } +}; +template<> +class name_of<test_class> { +public: + static const char* name() { return "test_class"; } +}; + +// TT must be arithmetic, and shouldn't wrap around for reasonable sizes of Count (which is now 150, and maxPorts is 10, +// so the max number generated right now is 1500 or so.) Source will generate a series of TT with value +// (init_val + (i-1)*addend) * my_mult, where i is the i-th invocation of the body. We are attaching addend +// source nodes to a or_port, and each will generate part of the numerical series the port is expecting +// to receive. If there is only one source node, the series order will be maintained; if more than one, +// this is not guaranteed. +template<typename TT> +class source_body { + const TT my_mult; + int my_count; + const int addend; + source_body& operator=( const source_body& other); +public: + source_body(TT multiplier, int init_val, int addto) : my_mult(multiplier), my_count(init_val), addend(addto) { } + bool operator()( TT &v) { + int lc = my_count; + v = my_mult * (TT)my_count; + my_count += addend; + return lc < Count; + } +}; + +// allocator for or_node. + +template<typename OType> +class makeOr { +public: + static OType *create() { + OType *temp = new OType(); + return temp; + } + static void destroy(OType *p) { delete p; } +}; + +template<int ELEM, typename ONT> +struct getval_helper { + + typedef typename ONT::output_type OT; + static int get_integer_val(OT &o) { + return int(std::get<ELEM-1>(o.result)); + } +}; + +// holder for source_node pointers for eventual deletion + +static void* all_source_nodes[MaxPorts][MaxNSources]; + +template<int ELEM, typename ONT> +class source_node_helper { +public: + typedef ONT or_node_type; + typedef typename or_node_type::output_type TT; + typedef typename std::tuple_element<ELEM-1,typename ONT::tuple_types>::type IT; + typedef typename tbb::flow::source_node<IT> my_source_node_type; + static void print_remark() { + source_node_helper<ELEM-1,ONT>::print_remark(); + REMARK(", %s", name_of<IT>::name()); + } + static void add_source_nodes(or_node_type &my_or, tbb::flow::graph &g, int nInputs) { + for(int i=0; i < nInputs; ++i) { + my_source_node_type *new_node = new my_source_node_type(g, source_body<IT>((IT)(ELEM+1), i, nInputs)); + ASSERT(new_node->register_successor(tbb::flow::input_port<ELEM-1>(my_or)), NULL); + all_source_nodes[ELEM-1][i] = (void *)new_node; + } + // add the next source_node + source_node_helper<ELEM-1, ONT>::add_source_nodes(my_or, g, nInputs); + } + static void check_value(TT &v) { + if(v.indx == ELEM-1) { + int ival = getval_helper<ELEM,ONT>::get_integer_val(v); + ASSERT(!(ival%(ELEM+1)), NULL); + ival /= (ELEM+1); + ASSERT(!outputCheck[ELEM-1][ival], NULL); + outputCheck[ELEM-1][ival] = true; + } + else { + source_node_helper<ELEM-1,ONT>::check_value(v); + } + } + + static void remove_source_nodes(or_node_type& my_or, int nInputs) { + for(int i=0; i< nInputs; ++i) { + my_source_node_type *dp = reinterpret_cast<my_source_node_type *>(all_source_nodes[ELEM-1][i]); + dp->remove_successor(tbb::flow::input_port<ELEM-1>(my_or)); + delete dp; + } + source_node_helper<ELEM-1, ONT>::remove_source_nodes(my_or, nInputs); + } +}; + +template<typename ONT> +class source_node_helper<1, ONT> { + typedef ONT or_node_type; + typedef typename or_node_type::output_type TT; + typedef typename std::tuple_element<0, typename ONT::tuple_types>::type IT; + typedef typename tbb::flow::source_node<IT> my_source_node_type; +public: + static void print_remark() { + REMARK("Parallel test of or_node< %s", name_of<IT>::name()); + } + static void add_source_nodes(or_node_type &my_or, tbb::flow::graph &g, int nInputs) { + for(int i=0; i < nInputs; ++i) { + my_source_node_type *new_node = new my_source_node_type(g, source_body<IT>((IT)2, i, nInputs)); + ASSERT(new_node->register_successor(tbb::flow::input_port<0>(my_or)), NULL); + all_source_nodes[0][i] = (void *)new_node; + } + } + static void check_value(TT &v) { + int ival = getval_helper<1,ONT>::get_integer_val(v); + ASSERT(!(ival%2), NULL); + ival /= 2; + ASSERT(!outputCheck[0][ival], NULL); + outputCheck[0][ival] = true; + } + static void remove_source_nodes(or_node_type& my_or, int nInputs) { + for(int i=0; i < nInputs; ++i) { + my_source_node_type *dp = reinterpret_cast<my_source_node_type *>(all_source_nodes[0][i]); + dp->remove_successor(tbb::flow::input_port<0>(my_or)); + delete dp; + } + } +}; + +template<typename OType> +class parallel_test { +public: + typedef typename OType::output_type TType; + typedef typename OType::tuple_types union_types; + static const int SIZE = std::tuple_size<union_types>::value; + static void test() { + TType v; + source_node_helper<SIZE,OType>::print_remark(); + REMARK(" >\n"); + for(int i=0; i < MaxPorts; ++i) { + for(int j=0; j < MaxNSources; ++j) { + all_source_nodes[i][j] = NULL; + } + } + for(int nInputs = 1; nInputs <= MaxNSources; ++nInputs) { + tbb::flow::graph g; + OType* my_or = new OType(g); //makeOr<OType>::create(); + tbb::flow::queue_node<TType> outq1(g); + tbb::flow::queue_node<TType> outq2(g); + + ASSERT((*my_or).register_successor(outq1), NULL); // register outputs first, so they both get all + ASSERT((*my_or).register_successor(outq2), NULL); // the results + + source_node_helper<SIZE, OType>::add_source_nodes((*my_or), g, nInputs); + + g.wait_for_all(); + + reset_outputCheck(SIZE, Count); + for(int i=0; i < Count*SIZE; ++i) { + ASSERT(outq1.try_get(v), NULL); + source_node_helper<SIZE, OType>::check_value(v); + } + + check_outputCheck(SIZE, Count); + reset_outputCheck(SIZE, Count); + + for(int i=0; i < Count*SIZE; i++) { + ASSERT(outq2.try_get(v), NULL);; + source_node_helper<SIZE, OType>::check_value(v); + } + check_outputCheck(SIZE, Count); + + ASSERT(!outq1.try_get(v), NULL); + ASSERT(!outq2.try_get(v), NULL); + + source_node_helper<SIZE, OType>::remove_source_nodes((*my_or), nInputs); + (*my_or).remove_successor(outq1); + (*my_or).remove_successor(outq2); + makeOr<OType>::destroy(my_or); + } + } +}; + +std::vector<int> last_index_seen; + +template<int ELEM, typename OType> +class serial_queue_helper { +public: + typedef typename OType::output_type OT; + typedef typename OType::tuple_types TT; + typedef typename std::tuple_element<ELEM-1,TT>::type IT; + static void print_remark() { + serial_queue_helper<ELEM-1,OType>::print_remark(); + REMARK(", %s", name_of<IT>::name()); + } + static void fill_one_queue(int maxVal, OType &my_or) { + // fill queue to "left" of me + serial_queue_helper<ELEM-1,OType>::fill_one_queue(maxVal,my_or); + for(int i = 0; i < maxVal; ++i) { + ASSERT(tbb::flow::input_port<ELEM-1>(my_or).try_put((IT)(i*(ELEM+1))), NULL); + } + } + static void put_one_queue_val(int myVal, OType &my_or) { + // put this val to my "left". + serial_queue_helper<ELEM-1,OType>::put_one_queue_val(myVal, my_or); + ASSERT(tbb::flow::input_port<ELEM-1>(my_or).try_put((IT)(myVal*(ELEM+1))), NULL); + } + static void check_queue_value(OT &v) { + if(ELEM - 1 == v.indx) { + // this assumes each or node input is queueing. + int rval = getval_helper<ELEM,OType>::get_integer_val(v); + ASSERT( rval == (last_index_seen[ELEM-1]+1)*(ELEM+1), NULL); + last_index_seen[ELEM-1] = rval / (ELEM+1); + } + else { + serial_queue_helper<ELEM-1,OType>::check_queue_value(v); + } + } +}; + +template<typename OType> +class serial_queue_helper<1, OType> { +public: + typedef typename OType::output_type OT; + typedef typename OType::tuple_types TT; + typedef typename std::tuple_element<0,TT>::type IT; + static void print_remark() { + REMARK("Serial test of or_node< %s", name_of<IT>::name()); + } + static void fill_one_queue(int maxVal, OType &my_or) { + for(int i = 0; i < maxVal; ++i) { + ASSERT(tbb::flow::input_port<0>(my_or).try_put((IT)(i*2)), NULL); + } + } + static void put_one_queue_val(int myVal, OType &my_or) { + ASSERT(tbb::flow::input_port<0>(my_or).try_put((IT)(myVal*2)), NULL); + } + static void check_queue_value(OT &v) { + ASSERT(v.indx == 0, NULL); // won't get here unless true + int rval = getval_helper<1,OType>::get_integer_val(v); + ASSERT( rval == (last_index_seen[0]+1)*2, NULL); + last_index_seen[0] = rval / 2; + } +}; + +template<typename OType, typename TType, int SIZE> +void test_one_serial( OType &my_or, tbb::flow::graph &g) { + last_index_seen.clear(); + for(int ii=0; ii < SIZE; ++ii) last_index_seen.push_back(-1); + + typedef TType q3_input_type; + tbb::flow::queue_node< q3_input_type > q3(g); + q3_input_type v; + + ASSERT((my_or).register_successor( q3 ), NULL); + + // fill each queue with its value one-at-a-time + for (int i = 0; i < Count; ++i ) { + serial_queue_helper<SIZE,OType>::put_one_queue_val(i,my_or); + } + + g.wait_for_all(); + for (int i = 0; i < Count * SIZE; ++i ) { + g.wait_for_all(); + ASSERT(q3.try_get( v ), "Error in try_get()"); + { + serial_queue_helper<SIZE,OType>::check_queue_value(v); + } + } + ASSERT(!q3.try_get( v ), "extra values in output queue"); + for(int ii=0; ii < SIZE; ++ii) last_index_seen[ii] = -1; + + // fill each queue completely before filling the next. + serial_queue_helper<SIZE, OType>::fill_one_queue(Count,my_or); + + g.wait_for_all(); + for (int i = 0; i < Count*SIZE; ++i ) { + g.wait_for_all(); + ASSERT(q3.try_get( v ), "Error in try_get()"); + { + serial_queue_helper<SIZE,OType>::check_queue_value(v); + } + } + ASSERT(!q3.try_get( v ), "extra values in output queue"); +} + +// +// Single predecessor at each port, single accepting successor +// * put to buffer before port0, then put to buffer before port1, ... +// * fill buffer before port0 then fill buffer before port1, ... + +template<typename OType> +class serial_test { + typedef typename OType::output_type TType; // this is the union + typedef typename OType::tuple_types union_types; + static const int SIZE = std::tuple_size<union_types>::value; +public: +static void test() { + tbb::flow::graph g; + static const int ELEMS = 3; + OType* my_or = new OType(g); //makeOr<OType>::create(g); + + serial_queue_helper<SIZE, OType>::print_remark(); REMARK(" >\n"); + + test_one_serial<OType,TType,SIZE>(*my_or, g); + + std::vector<OType> or_vector(ELEMS, *my_or); + + makeOr<OType>::destroy(my_or); + + for(int e = 0; e < ELEMS; ++e) { + test_one_serial<OType,TType,SIZE>(or_vector[e], g); + } +} + +}; // serial_test + +template< + template<typename> class TestType, // serial_test or parallel_test + typename InputTupleType> // type of the inputs to the or_node +class generate_test { +public: + typedef tbb::flow::or_node<InputTupleType> or_node_type; + static void do_test() { + TestType<or_node_type>::test(); + } +}; + +int TestMain() { + REMARK("Testing or_node, "); +#if __TBB_USE_TBB_TUPLE + REMARK("using TBB tuple\n"); +#else + REMARK("using platform tuple\n"); +#endif + + for (int p = 0; p < 2; ++p) { + generate_test<serial_test, std::tuple<float, test_class> >::do_test(); + generate_test<serial_test, std::tuple<float, double, int, long> >::do_test(); + generate_test<serial_test, std::tuple<double, double, int, long, int, short> >::do_test(); +#if COMPREHENSIVE_TEST + generate_test<serial_test, std::tuple<float, double, double, double, float, int, float, long> >::do_test(); + generate_test<serial_test, std::tuple<float, double, int, double, double, float, long, int, float, long> >::do_test(); +#endif + generate_test<parallel_test, std::tuple<float, double> >::do_test(); + generate_test<parallel_test, std::tuple<float, int, long> >::do_test(); + generate_test<parallel_test, std::tuple<double, double, int, int, short> >::do_test(); +#if COMPREHENSIVE_TEST + generate_test<parallel_test, std::tuple<float, int, double, float, long, float, long> >::do_test(); + generate_test<parallel_test, std::tuple<float, double, int, double, double, long, int, float, long> >::do_test(); +#endif + } + return Harness::Done; +} +#else // __SUNPRO_CC +int TestMain() { + return Harness::Skipped; +} +#endif // __SUNPRO_CC diff --git a/src/tbb/src/test/test_overwrite_node.cpp b/src/tbb/src/test/test_overwrite_node.cpp new file mode 100644 index 0000000..4227979 --- /dev/null +++ b/src/tbb/src/test/test_overwrite_node.cpp @@ -0,0 +1,155 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "harness_graph.h" + +#include "tbb/task_scheduler_init.h" + +#define N 300 +#define T 4 +#define M 4 + +template< typename R > +void simple_read_write_tests() { + tbb::flow::graph g; + tbb::flow::overwrite_node<R> n(g); + + for ( int t = 0; t < T; ++t ) { + R v0(N+1); + harness_counting_receiver<R> r[M]; + + ASSERT( n.is_valid() == false, NULL ); + ASSERT( n.try_get( v0 ) == false, NULL ); + if ( t % 2 ) { + ASSERT( n.try_put( static_cast<R>(N) ), NULL ); + ASSERT( n.is_valid() == true, NULL ); + ASSERT( n.try_get( v0 ) == true, NULL ); + ASSERT( v0 == R(N), NULL ); + } + + for (int i = 0; i < M; ++i) { + tbb::flow::make_edge( n, r[i] ); + } + + for (int i = 0; i < N; ++i ) { + R v1(static_cast<R>(i)); + ASSERT( n.try_put( v1 ), NULL ); + ASSERT( n.is_valid() == true, NULL ); + for (int j = 0; j < N; ++j ) { + R v2(0); + ASSERT( n.try_get( v2 ), NULL ); + ASSERT( v1 == v2, NULL ); + } + } + for (int i = 0; i < M; ++i) { + size_t c = r[i].my_count; + ASSERT( int(c) == N+t%2, NULL ); + } + for (int i = 0; i < M; ++i) { + tbb::flow::remove_edge( n, r[i] ); + } + ASSERT( n.try_put( R(0) ), NULL ); + for (int i = 0; i < M; ++i) { + size_t c = r[i].my_count; + ASSERT( int(c) == N+t%2, NULL ); + } + n.clear(); + ASSERT( n.is_valid() == false, NULL ); + ASSERT( n.try_get( v0 ) == false, NULL ); + } +} + +template< typename R > +class native_body : NoAssign { + tbb::flow::overwrite_node<R> &my_node; + +public: + + native_body( tbb::flow::overwrite_node<R> &n ) : my_node(n) {} + + void operator()( int i ) const { + R v1(static_cast<R>(i)); + ASSERT( my_node.try_put( v1 ), NULL ); + ASSERT( my_node.is_valid() == true, NULL ); + } +}; + +template< typename R > +void parallel_read_write_tests() { + tbb::flow::graph g; + tbb::flow::overwrite_node<R> n(g); + //Create a vector of identical nodes + std::vector< tbb::flow::overwrite_node<R> > ow_vec(2, n); + + for (size_t node_idx=0; node_idx<ow_vec.size(); ++node_idx) { + for ( int t = 0; t < T; ++t ) { + harness_counting_receiver<R> r[M]; + + for (int i = 0; i < M; ++i) { + tbb::flow::make_edge( ow_vec[node_idx], r[i] ); + } + R v0; + ASSERT( ow_vec[node_idx].is_valid() == false, NULL ); + ASSERT( ow_vec[node_idx].try_get( v0 ) == false, NULL ); + + NativeParallelFor( N, native_body<R>( ow_vec[node_idx] ) ); + + for (int i = 0; i < M; ++i) { + size_t c = r[i].my_count; + ASSERT( int(c) == N, NULL ); + } + for (int i = 0; i < M; ++i) { + tbb::flow::remove_edge( ow_vec[node_idx], r[i] ); + } + ASSERT( ow_vec[node_idx].try_put( R(0) ), NULL ); + for (int i = 0; i < M; ++i) { + size_t c = r[i].my_count; + ASSERT( int(c) == N, NULL ); + } + ow_vec[node_idx].clear(); + ASSERT( ow_vec[node_idx].is_valid() == false, NULL ); + ASSERT( ow_vec[node_idx].try_get( v0 ) == false, NULL ); + } + } +} + +int TestMain() { + if( MinThread<1 ) { + REPORT("number of threads must be positive\n"); + exit(1); + } + simple_read_write_tests<int>(); + simple_read_write_tests<float>(); + for( int p=MinThread; p<=MaxThread; ++p ) { + tbb::task_scheduler_init init(p); + parallel_read_write_tests<int>(); + parallel_read_write_tests<float>(); + } + return Harness::Done; +} + diff --git a/src/tbb/src/test/test_parallel_do.cpp b/src/tbb/src/test/test_parallel_do.cpp new file mode 100644 index 0000000..fa7c4bf --- /dev/null +++ b/src/tbb/src/test/test_parallel_do.cpp @@ -0,0 +1,237 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/parallel_do.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/atomic.h" +#include "harness.h" +#include "harness_cpu.h" + +#if defined(_MSC_VER) && defined(_Wp64) + // Workaround for overzealous compiler warnings in /Wp64 mode + #pragma warning (disable: 4267) +#endif /* _MSC_VER && _Wp64 */ + +#define N_DEPTHS 20 + +static tbb::atomic<int> g_values_counter; + +class value_t { + size_t x; + value_t& operator= ( const value_t& ); +public: + value_t ( size_t xx ) : x(xx) { ++g_values_counter; } + value_t ( const value_t& v ) : x(v.value()) { ++g_values_counter; } + ~value_t () { --g_values_counter; } + size_t value() const volatile { return x; } +}; + +#include "harness_iterator.h" + +static size_t g_tasks_expected = 0; +static tbb::atomic<size_t> g_tasks_observed; + +size_t FindNumOfTasks ( size_t max_depth ) { + if( max_depth == 0 ) + return 1; + return max_depth * FindNumOfTasks( max_depth - 1 ) + 1; +} + +//! Simplest form of the parallel_do functor object. +class FakeTaskGeneratorBody { +public: + //! The simplest form of the function call operator + /** It does not allow adding new tasks during its execution. **/ + void operator() ( value_t depth ) const { + g_tasks_observed += FindNumOfTasks(depth.value()); + } +}; + +/** Work item is passed by reference here. **/ +class FakeTaskGeneratorBody_RefVersion { +public: + void operator() ( value_t& depth ) const { + g_tasks_observed += FindNumOfTasks(depth.value()); + } +}; + +/** Work item is passed by reference to const here. **/ +class FakeTaskGeneratorBody_ConstRefVersion { +public: + void operator() ( const value_t& depth ) const { + g_tasks_observed += FindNumOfTasks(depth.value()); + } +}; + +/** Work item is passed by reference to volatile here. **/ +class FakeTaskGeneratorBody_VolatileRefVersion { +public: + void operator() ( volatile value_t& depth, tbb::parallel_do_feeder<value_t>& ) const { + g_tasks_observed += FindNumOfTasks(depth.value()); + } +}; + +void do_work ( const value_t& depth, tbb::parallel_do_feeder<value_t>& feeder ) { + ++g_tasks_observed; + size_t d=depth.value(); + --d; + for( size_t i = 0; i < depth.value(); ++i) + feeder.add(value_t(d)); +} + +//! Standard form of the parallel_do functor object. +/** Allows adding new work items on the fly. **/ +class TaskGeneratorBody +{ +public: + //! This form of the function call operator can be used when the body needs to add more work during the processing + void operator() ( value_t depth, tbb::parallel_do_feeder<value_t>& feeder ) const { + do_work(depth, feeder); + } +private: + // Assert that parallel_do does not ever access body constructors + TaskGeneratorBody () {} + TaskGeneratorBody ( const TaskGeneratorBody& ); + // TestBody() needs access to the default constructor + template<class Body, class Iterator> friend void TestBody( size_t ); +}; // class TaskGeneratorBody + +/** Work item is passed by reference here. **/ +class TaskGeneratorBody_RefVersion +{ +public: + void operator() ( value_t& depth, tbb::parallel_do_feeder<value_t>& feeder ) const { + do_work(depth, feeder); + } +}; // class TaskGeneratorBody + +/** Work item is passed as const here. Compilers must ignore the const qualifier. **/ +class TaskGeneratorBody_ConstVersion +{ +public: + void operator() ( const value_t depth, tbb::parallel_do_feeder<value_t>& feeder ) const { + do_work(depth, feeder); + } +}; // class TaskGeneratorBody + +/** Work item is passed by reference to const here. **/ +class TaskGeneratorBody_ConstRefVersion +{ +public: + void operator() ( const value_t& depth, tbb::parallel_do_feeder<value_t>& feeder ) const { + do_work(depth, feeder); + } +}; // class TaskGeneratorBody + +/** Work item is passed by reference to volatile here. **/ +class TaskGeneratorBody_VolatileRefVersion +{ +public: + void operator() ( volatile value_t& depth, tbb::parallel_do_feeder<value_t>& feeder ) const { + do_work(const_cast<value_t&>(depth), feeder); + } +}; // class TaskGeneratorBody + +/** Work item is passed by reference to volatile here. **/ +class TaskGeneratorBody_ConstVolatileRefVersion +{ +public: + void operator() ( const volatile value_t& depth, tbb::parallel_do_feeder<value_t>& feeder ) const { + do_work(const_cast<value_t&>(depth), feeder); + } +}; // class TaskGeneratorBody + + +static value_t g_depths[N_DEPTHS] = {0, 1, 2, 3, 4, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 0, 1, 2}; + +template<class Body, class Iterator> +void TestBody ( size_t depth ) { + typedef typename std::iterator_traits<Iterator>::value_type value_type; + value_type a_depths[N_DEPTHS] = {0, 1, 2, 3, 4, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 0, 1, 2}; + Body body; + Iterator begin(a_depths); + Iterator end(a_depths + depth); + g_tasks_observed = 0; + tbb::parallel_do(begin, end, body); + ASSERT (g_tasks_observed == g_tasks_expected, NULL); +} + +template<class Iterator> +void TestIterator_RvalueOnly ( int /*nthread*/, size_t depth ) { + g_values_counter = 0; + TestBody<FakeTaskGeneratorBody, Iterator> (depth); + TestBody<FakeTaskGeneratorBody_ConstRefVersion, Iterator> (depth); + TestBody<TaskGeneratorBody, Iterator> (depth); + TestBody<TaskGeneratorBody_ConstVersion, Iterator> (depth); + TestBody<TaskGeneratorBody_ConstRefVersion, Iterator> (depth); +} + +template<class Iterator> +void TestIterator ( int nthread, size_t depth ) { + TestIterator_RvalueOnly<Iterator>(nthread, depth); + TestBody<FakeTaskGeneratorBody_RefVersion, Iterator> (depth); + TestBody<FakeTaskGeneratorBody_VolatileRefVersion, Iterator> (depth); + TestBody<TaskGeneratorBody_RefVersion, Iterator> (depth); + TestBody<TaskGeneratorBody_VolatileRefVersion, Iterator> (depth); + TestBody<TaskGeneratorBody_ConstVolatileRefVersion, Iterator> (depth); +} + +void Run( int nthread ) { + for( size_t depth = 0; depth <= N_DEPTHS; ++depth ) { + g_tasks_expected = 0; + for ( size_t i=0; i < depth; ++i ) + g_tasks_expected += FindNumOfTasks( g_depths[i].value() ); + // Test for iterators over values convertible to work item type + TestIterator_RvalueOnly<size_t*>(nthread, depth); + // Test for random access iterators + TestIterator<value_t*>(nthread, depth); + // Test for input iterators + TestIterator<Harness::InputIterator<value_t> >(nthread, depth); + // Test for forward iterators + TestIterator<Harness::ForwardIterator<value_t> >(nthread, depth); + // Test for const random access iterators + TestIterator_RvalueOnly<Harness::ConstRandomIterator<value_t> >(nthread, depth); + } +} + +int TestMain () { + if( MinThread<1 ) { + REPORT("number of threads must be positive\n"); + exit(1); + } + for( int p=MinThread; p<=MaxThread; ++p ) { + tbb::task_scheduler_init init( p ); + Run(p); + // Test that all workers sleep when no work + TestCPUUserTime(p); + } + // This check must be performed after the scheduler terminated because only in this + // case there is a guarantee that the workers already destroyed their last tasks. + ASSERT( g_values_counter == 0, "Value objects were leaked" ); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_parallel_for.cpp b/src/tbb/src/test/test_parallel_for.cpp new file mode 100644 index 0000000..9605408 --- /dev/null +++ b/src/tbb/src/test/test_parallel_for.cpp @@ -0,0 +1,487 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Test for function template parallel_for.h + +// Enable testing of serial subset. +#define TBB_PREVIEW_SERIAL_SUBSET 1 + +#if _MSC_VER +#pragma warning (push) +#if !defined(__INTEL_COMPILER) + // Suppress pointless "unreachable code" warning. + #pragma warning (disable: 4702) +#endif +#if defined(_Wp64) + // Workaround for overzealous compiler warnings in /Wp64 mode + #pragma warning (disable: 4267) +#endif + +#define _SCL_SECURE_NO_WARNINGS +#endif //#if _MSC_VER + +#include "tbb/parallel_for.h" +#include "tbb/atomic.h" +#include "harness_assert.h" +#include "harness.h" + +static tbb::atomic<int> FooBodyCount; + +//! A range object whose only public members are those required by the Range concept. +template<size_t Pad> +class FooRange { + //! Start of range + int start; + + //! Size of range + int size; + FooRange( int start_, int size_ ) : start(start_), size(size_) { + zero_fill<char>(pad, Pad); + pad[Pad-1] = 'x'; + } + template<typename Flavor_, size_t Pad_> friend void Flog( int nthread ); + template<size_t Pad_> friend class FooBody; + void operator&(); + + char pad[Pad]; +public: + bool empty() const {return size==0;} + bool is_divisible() const {return size>1;} + FooRange( FooRange& original, tbb::split ) : size(original.size/2) { + original.size -= size; + start = original.start+original.size; + ASSERT( original.pad[Pad-1]=='x', NULL ); + pad[Pad-1] = 'x'; + } +}; + +//! A range object whose only public members are those required by the parallel_for.h body concept. +template<size_t Pad> +class FooBody { + static const int LIVE = 0x1234; + tbb::atomic<int>* array; + int state; + friend class FooRange<Pad>; + template<typename Flavor_, size_t Pad_> friend void Flog( int nthread ); + FooBody( tbb::atomic<int>* array_ ) : array(array_), state(LIVE) {} +public: + ~FooBody() { + --FooBodyCount; + for( size_t i=0; i<sizeof(*this); ++i ) + reinterpret_cast<char*>(this)[i] = -1; + } + //! Copy constructor + FooBody( const FooBody& other ) : array(other.array), state(other.state) { + ++FooBodyCount; + ASSERT( state==LIVE, NULL ); + } + void operator()( FooRange<Pad>& r ) const { + for( int k=0; k<r.size; ++k ) { + const int i = array[r.start+k]++; + ASSERT( i==0, NULL ); + } + } +}; + +#include "tbb/tick_count.h" + +static const int N = 500; +static tbb::atomic<int> Array[N]; + +struct serial_tag {}; +struct parallel_tag {}; + +template <typename Flavor, typename Range, typename Body> +struct Invoker; + +template <typename Range, typename Body> +struct Invoker<serial_tag, Range, Body> { + void operator()( const Range& r, const Body& body, const tbb::simple_partitioner& p ) { + tbb::serial:: parallel_for( r, body, p ); + } + void operator()( const Range& r, const Body& body, const tbb::auto_partitioner& p ) { + tbb::serial:: parallel_for( r, body, p ); + } + void operator()( const Range& r, const Body& body, tbb::affinity_partitioner& p ) { + tbb::serial:: parallel_for( r, body, p ); + } + void operator()( const Range& r, const Body& body ) { + tbb::serial:: parallel_for( r, body, tbb::auto_partitioner() ); + } +}; + +template <typename Range, typename Body> +struct Invoker<parallel_tag, Range, Body> { + void operator()( const Range& r, const Body& body, const tbb::simple_partitioner& p ) { + tbb:: parallel_for( r, body, p ); + } + void operator()( const Range& r, const Body& body, const tbb::auto_partitioner& p ) { + tbb:: parallel_for( r, body, p ); + } + void operator()( const Range& r, const Body& body, tbb::affinity_partitioner& p ) { + tbb:: parallel_for( r, body, p ); + } + void operator()( const Range& r, const Body& body ) { + tbb:: parallel_for( r, body, tbb::auto_partitioner() ); + } +}; + +template <typename Flavor, typename T, typename Body> +struct InvokerStep; + +template <typename T, typename Body> +struct InvokerStep<serial_tag, T, Body> { + void operator()( const T& first, const T& last, const Body& f ) { + tbb::serial:: parallel_for( first, last, f ); + } + void operator()( const T& first, const T& last, const T& step, const Body& f ) { + tbb::serial:: parallel_for( first, last, step, f ); + } +}; + +template <typename T, typename Body> +struct InvokerStep<parallel_tag, T, Body> { + void operator()( const T& first, const T& last, const Body& f ) { + tbb:: parallel_for( first, last, f ); + } + void operator()( const T& first, const T& last, const T& step, const Body& f ) { + tbb:: parallel_for( first, last, step, f ); + } +}; + +template<typename Flavor, size_t Pad> +void Flog( int nthread ) { + tbb::tick_count T0 = tbb::tick_count::now(); + for( int i=0; i<N; ++i ) { + for ( int mode = 0; mode < 4; ++mode) { + FooRange<Pad> r( 0, i ); + const FooRange<Pad> rc = r; + FooBody<Pad> f( Array ); + const FooBody<Pad> fc = f; + memset( Array, 0, sizeof(Array) ); + FooBodyCount = 1; + Invoker< Flavor, FooRange<Pad>, FooBody<Pad> > invoke_for; + switch (mode) { + case 0: + invoke_for( rc, fc ); + break; + case 1: + invoke_for( rc, fc, tbb::simple_partitioner() ); + break; + case 2: + invoke_for( rc, fc, tbb::auto_partitioner() ); + break; + case 3: { + static tbb::affinity_partitioner affinity; + invoke_for( rc, fc, affinity ); + } + break; + } + for( int j=0; j<i; ++j ) + ASSERT( Array[j]==1, NULL ); + for( int j=i; j<N; ++j ) + ASSERT( Array[j]==0, NULL ); + ASSERT( FooBodyCount==1, NULL ); + } + } + tbb::tick_count T1 = tbb::tick_count::now(); + REMARK("time=%g\tnthread=%d\tpad=%d\n",(T1-T0).seconds(),nthread,int(Pad)); +} + +// Testing parallel_for with step support +const size_t PFOR_BUFFER_TEST_SIZE = 1024; +// test_buffer has some extra items beyond its right bound +const size_t PFOR_BUFFER_ACTUAL_SIZE = PFOR_BUFFER_TEST_SIZE + 1024; +size_t pfor_buffer[PFOR_BUFFER_ACTUAL_SIZE]; + +template<typename T> +class TestFunctor{ +public: + void operator ()(T index) const { + pfor_buffer[index]++; + } +}; + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include <stdexcept> // std::invalid_argument + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +template <typename Flavor, typename T> +void TestParallelForWithStepSupport() +{ + const T pfor_buffer_test_size = static_cast<T>(PFOR_BUFFER_TEST_SIZE); + const T pfor_buffer_actual_size = static_cast<T>(PFOR_BUFFER_ACTUAL_SIZE); + // Testing parallel_for with different step values + InvokerStep< Flavor, T, TestFunctor<T> > invoke_for; + for (T begin = 0; begin < pfor_buffer_test_size - 1; begin += pfor_buffer_test_size / 10 + 1) { + T step; + for (step = 1; step < pfor_buffer_test_size; step++) { + memset(pfor_buffer, 0, pfor_buffer_actual_size * sizeof(size_t)); + if (step == 1){ + invoke_for(begin, pfor_buffer_test_size, TestFunctor<T>()); + } else { + invoke_for(begin, pfor_buffer_test_size, step, TestFunctor<T>()); + } + // Verifying that parallel_for processed all items it should + for (T i = begin; i < pfor_buffer_test_size; i = i + step) { + ASSERT(pfor_buffer[i] == 1, "parallel_for didn't process all required elements"); + pfor_buffer[i] = 0; + } + // Verifying that no extra items were processed and right bound of array wasn't crossed + for (T i = 0; i < pfor_buffer_actual_size; i++) { + ASSERT(pfor_buffer[i] == 0, "parallel_for processed an extra element"); + } + } + } + + // Testing some corner cases + tbb::parallel_for(static_cast<T>(2), static_cast<T>(1), static_cast<T>(1), TestFunctor<T>()); +#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN + try{ + tbb::parallel_for(static_cast<T>(1), static_cast<T>(100), static_cast<T>(0), TestFunctor<T>()); // should cause std::invalid_argument + }catch(std::invalid_argument){ + return; + } + catch ( ... ) { + ASSERT ( __TBB_EXCEPTION_TYPE_INFO_BROKEN, "Unrecognized exception. std::invalid_argument is expected" ); + } +#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */ +} + +#if __TBB_TASK_GROUP_CONTEXT +// Exception support test +#define HARNESS_EH_SIMPLE_MODE 1 +#include "tbb/tbb_exception.h" +#include "harness_eh.h" + +#if TBB_USE_EXCEPTIONS +class test_functor_with_exception { +public: + void operator ()(size_t) const { ThrowTestException(); } +}; + +void TestExceptionsSupport() { + REMARK (__FUNCTION__); + { // Tests version with a step provided + ResetEhGlobals(); + TRY(); + tbb::parallel_for((size_t)0, (size_t)PFOR_BUFFER_TEST_SIZE, (size_t)1, test_functor_with_exception()); + CATCH_AND_ASSERT(); + } + { // Tests version without a step + ResetEhGlobals(); + TRY(); + tbb::parallel_for((size_t)0, (size_t)PFOR_BUFFER_TEST_SIZE, test_functor_with_exception()); + CATCH_AND_ASSERT(); + } +} +#endif /* TBB_USE_EXCEPTIONS */ + +// Cancellation support test +class functor_to_cancel { +public: + void operator()(size_t) const { + ++g_CurExecuted; + CancellatorTask::WaitUntilReady(); + } +}; + +size_t g_worker_task_step = 0; + +class my_worker_pfor_step_task : public tbb::task +{ + tbb::task_group_context &my_ctx; + + tbb::task* execute () { + if (g_worker_task_step == 0){ + tbb::parallel_for((size_t)0, (size_t)PFOR_BUFFER_TEST_SIZE, functor_to_cancel(), my_ctx); + }else{ + tbb::parallel_for((size_t)0, (size_t)PFOR_BUFFER_TEST_SIZE, g_worker_task_step, functor_to_cancel(), my_ctx); + } + return NULL; + } +public: + my_worker_pfor_step_task ( tbb::task_group_context &context_) : my_ctx(context_) { } +}; + +void TestCancellation() +{ + // tests version without a step + g_worker_task_step = 0; + ResetEhGlobals(); + RunCancellationTest<my_worker_pfor_step_task, CancellatorTask>(); + + // tests version with step + g_worker_task_step = 1; + ResetEhGlobals(); + RunCancellationTest<my_worker_pfor_step_task, CancellatorTask>(); +} +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +#include "harness_m128.h" + +#if (HAVE_m128 || HAVE_m256) && !__TBB_SSE_STACK_ALIGNMENT_BROKEN +template<typename ClassWithVectorType> +struct SSE_Functor { + ClassWithVectorType* Src, * Dst; + SSE_Functor( ClassWithVectorType* src, ClassWithVectorType* dst ) : Src(src), Dst(dst) {} + + void operator()( tbb::blocked_range<int>& r ) const { + for( int i=r.begin(); i!=r.end(); ++i ) + Dst[i] = Src[i]; + } +}; + +//! Test that parallel_for works with stack-allocated __m128 +template<typename ClassWithVectorType> +void TestVectorTypes() { + ClassWithVectorType Array1[N], Array2[N]; + for( int i=0; i<N; ++i ) { + // VC8 does not properly align a temporary value; to work around, use explicit variable + ClassWithVectorType foo(i); + Array1[i] = foo; + } + tbb::parallel_for( tbb::blocked_range<int>(0,N), SSE_Functor<ClassWithVectorType>(Array1, Array2) ); + for( int i=0; i<N; ++i ) { + ClassWithVectorType foo(i); + ASSERT( Array2[i]==foo, NULL ) ; + } +} +#endif /* HAVE_m128 || HAVE_m256 */ + +#include <vector> +#include <tbb/blocked_range.h> +#include <sstream> +struct TestSimplePartitionerStabilityFunctor:NoAssign{ + std::vector<int> & ranges; + TestSimplePartitionerStabilityFunctor(std::vector<int> & theRanges):ranges(theRanges){} + void operator()(tbb::blocked_range<size_t>& r)const{ + ranges.at(r.begin())=true; + } +}; +void TestSimplePartitionerStability(){ + const std::size_t repeat_count= 10; + const std::size_t rangeToSplitSize=1000000; + const std::size_t grainsizeStep=rangeToSplitSize/repeat_count; + typedef TestSimplePartitionerStabilityFunctor FunctorType; + + for (std::size_t i=0 , grainsize=grainsizeStep; i<repeat_count;i++, grainsize+=grainsizeStep){ + std::vector<int> firstSeries(rangeToSplitSize,0); + std::vector<int> secondSeries(rangeToSplitSize,0); + + tbb::parallel_for(tbb::blocked_range<size_t>(0,rangeToSplitSize,grainsize),FunctorType(firstSeries),tbb::simple_partitioner()); + tbb::parallel_for(tbb::blocked_range<size_t>(0,rangeToSplitSize,grainsize),FunctorType(secondSeries),tbb::simple_partitioner()); + std::stringstream str; str<<i; + ASSERT(firstSeries==secondSeries,("splitting range with tbb::simple_partitioner must be reproducible; i=" +str.str()).c_str() ); + } +} +#include <cstdio> +#include "tbb/task_scheduler_init.h" +#include "harness_cpu.h" + +int TestMain () { + if( MinThread<1 ) { + REPORT("number of threads must be positive\n"); + exit(1); + } + for( int p=MinThread; p<=MaxThread; ++p ) { + if( p>0 ) { + tbb::task_scheduler_init init( p ); + Flog<parallel_tag,1>(p); + Flog<parallel_tag,10>(p); + Flog<parallel_tag,100>(p); + Flog<parallel_tag,1000>(p); + Flog<parallel_tag,10000>(p); + + // Testing with different integer types + TestParallelForWithStepSupport<parallel_tag,short>(); + TestParallelForWithStepSupport<parallel_tag,unsigned short>(); + TestParallelForWithStepSupport<parallel_tag,int>(); + TestParallelForWithStepSupport<parallel_tag,unsigned int>(); + TestParallelForWithStepSupport<parallel_tag,long>(); + TestParallelForWithStepSupport<parallel_tag,unsigned long>(); + TestParallelForWithStepSupport<parallel_tag,long long>(); + TestParallelForWithStepSupport<parallel_tag,unsigned long long>(); + TestParallelForWithStepSupport<parallel_tag,size_t>(); + + // This is for testing serial implementation. + if( p == MaxThread ) { + Flog<serial_tag,1>(p); + Flog<serial_tag,10>(p); + Flog<serial_tag,100>(p); + TestParallelForWithStepSupport<serial_tag,short>(); + TestParallelForWithStepSupport<serial_tag,unsigned short>(); + TestParallelForWithStepSupport<serial_tag,int>(); + TestParallelForWithStepSupport<serial_tag,unsigned int>(); + TestParallelForWithStepSupport<serial_tag,long>(); + TestParallelForWithStepSupport<serial_tag,unsigned long>(); + TestParallelForWithStepSupport<serial_tag,long long>(); + TestParallelForWithStepSupport<serial_tag,unsigned long long>(); + TestParallelForWithStepSupport<serial_tag,size_t>(); + } + +#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN + TestExceptionsSupport(); +#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */ +#if __TBB_TASK_GROUP_CONTEXT + if ( p > 1 ) + TestCancellation(); +#endif /* __TBB_TASK_GROUP_CONTEXT */ +#if !__TBB_SSE_STACK_ALIGNMENT_BROKEN + #if HAVE_m128 + TestVectorTypes<ClassWithSSE>(); + #endif + #if HAVE_m256 + if (have_AVX()) TestVectorTypes<ClassWithAVX>(); + #endif +#endif /*!__TBB_SSE_STACK_ALIGNMENT_BROKEN*/ + // Test that all workers sleep when no work + TestCPUUserTime(p); + TestSimplePartitionerStability(); + } + } +#if __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN + REPORT("Known issue: exception handling tests are skipped.\n"); +#endif +#if (HAVE_m128 || HAVE_m256) && __TBB_SSE_STACK_ALIGNMENT_BROKEN + REPORT("Known issue: stack alignment for SSE/AVX not tested.\n"); +#endif + return Harness::Done; +} + +#if _MSC_VER +#pragma warning (pop) +#endif diff --git a/src/tbb/src/test/test_parallel_for_each.cpp b/src/tbb/src/test/test_parallel_for_each.cpp new file mode 100644 index 0000000..8cdb52e --- /dev/null +++ b/src/tbb/src/test/test_parallel_for_each.cpp @@ -0,0 +1,200 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if _MSC_VER && !defined(__INTEL_COMPILER) +#pragma warning(disable: 4180) // "qualifier applied to function type has no meaning; ignored" +#endif + +#include "tbb/parallel_for_each.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/atomic.h" +#include "harness.h" +#include "harness_iterator.h" + +// Some old compilers can't deduce template paremeter type for parallel_for_each +// if the function name is passed without explicit cast to function pointer. +typedef void (*TestFunctionType)(size_t); + +tbb::atomic<size_t> sum; + +// This function is called via parallel_for_each +void TestFunction (size_t value) { + sum += (unsigned int)value; +} + +const size_t NUMBER_OF_ELEMENTS = 1000; + +// Tests tbb::parallel_for_each functionality +template <typename Iterator> +void RunPForEachTests() +{ + size_t test_vector[NUMBER_OF_ELEMENTS + 1]; + + sum = 0; + size_t test_sum = 0; + + for (size_t i =0; i < NUMBER_OF_ELEMENTS; i++) { + test_vector[i] = i; + test_sum += i; + } + test_vector[NUMBER_OF_ELEMENTS] = 1000000; // parallel_for_each shouldn't touch this element + + Iterator begin(&test_vector[0]); + Iterator end(&test_vector[NUMBER_OF_ELEMENTS]); + + tbb::parallel_for_each(begin, end, (TestFunctionType)TestFunction); + ASSERT(sum == test_sum, "Not all items of test vector were processed by parallel_for_each"); + ASSERT(test_vector[NUMBER_OF_ELEMENTS] == 1000000, "parallel_for_each processed an extra element"); +} + +typedef void (*TestMutatorType)(size_t&); + +void TestMutator(size_t& value) { + ASSERT(value==0,NULL); + ++sum; + ++value; +} + +//! Test that tbb::parallel_for_each works for mutable iterators. +template <typename Iterator> +void RunMutablePForEachTests() { + size_t test_vector[NUMBER_OF_ELEMENTS]; + for( size_t i=0; i<NUMBER_OF_ELEMENTS; ++i ) + test_vector[i] = 0; + sum = 0; + tbb::parallel_for_each( Iterator(test_vector), Iterator(test_vector+NUMBER_OF_ELEMENTS), (TestMutatorType)TestMutator ); + ASSERT( sum==NUMBER_OF_ELEMENTS, "parallel_for_each called function wrong number of times" ); + for( size_t i=0; i<NUMBER_OF_ELEMENTS; ++i ) + ASSERT( test_vector[i]==1, "parallel_for_each did not process each element exactly once" ); +} + +#if __TBB_TASK_GROUP_CONTEXT +#define HARNESS_EH_SIMPLE_MODE 1 +#include "tbb/tbb_exception.h" +#include "harness_eh.h" + +#if TBB_USE_EXCEPTIONS +void test_function_with_exception(size_t) { + ThrowTestException(); +} + +template <typename Iterator> +void TestExceptionsSupport() +{ + REMARK (__FUNCTION__); + size_t test_vector[NUMBER_OF_ELEMENTS + 1]; + + for (size_t i = 0; i < NUMBER_OF_ELEMENTS; i++) { + test_vector[i] = i; + } + + Iterator begin(&test_vector[0]); + Iterator end(&test_vector[NUMBER_OF_ELEMENTS]); + + TRY(); + tbb::parallel_for_each(begin, end, (TestFunctionType)test_function_with_exception); + CATCH_AND_ASSERT(); +} +#endif /* TBB_USE_EXCEPTIONS */ + +// Cancelation support test +void function_to_cancel(size_t ) { + ++g_CurExecuted; + CancellatorTask::WaitUntilReady(); +} + +template <typename Iterator> +class my_worker_pforeach_task : public tbb::task +{ + tbb::task_group_context &my_ctx; + + tbb::task* execute () { + size_t test_vector[NUMBER_OF_ELEMENTS + 1]; + for (size_t i = 0; i < NUMBER_OF_ELEMENTS; i++) { + test_vector[i] = i; + } + Iterator begin(&test_vector[0]); + Iterator end(&test_vector[NUMBER_OF_ELEMENTS]); + + tbb::parallel_for_each(begin, end, (TestFunctionType)function_to_cancel); + + return NULL; + } +public: + my_worker_pforeach_task ( tbb::task_group_context &ctx) : my_ctx(ctx) { } +}; + +template <typename Iterator> +void TestCancellation() +{ + REMARK (__FUNCTION__); + ResetEhGlobals(); + RunCancellationTest<my_worker_pforeach_task<Iterator>, CancellatorTask>(); +} +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +#include "harness_cpu.h" + +int TestMain () { + if( MinThread<1 ) { + REPORT("number of threads must be positive\n"); + exit(1); + } + for( int p=MinThread; p<=MaxThread; ++p ) { + tbb::task_scheduler_init init( p ); + + RunPForEachTests<Harness::RandomIterator<size_t> >(); + RunPForEachTests<Harness::ConstRandomIterator<size_t> >(); + RunPForEachTests<Harness::InputIterator<size_t> >(); + RunPForEachTests<Harness::ForwardIterator<size_t> >(); + + RunMutablePForEachTests<Harness::RandomIterator<size_t> >(); + RunMutablePForEachTests<Harness::ForwardIterator<size_t> >(); + +#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN + TestExceptionsSupport<Harness::RandomIterator<size_t> >(); + TestExceptionsSupport<Harness::InputIterator<size_t> >(); + TestExceptionsSupport<Harness::ForwardIterator<size_t> >(); +#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */ + +#if __TBB_TASK_GROUP_CONTEXT + if (p > 1) { + TestCancellation<Harness::RandomIterator<size_t> >(); + TestCancellation<Harness::InputIterator<size_t> >(); + TestCancellation<Harness::ForwardIterator<size_t> >(); + } +#endif /* __TBB_TASK_GROUP_CONTEXT */ + + // Test that all workers sleep when no work + TestCPUUserTime(p); + } +#if __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN + REPORT("Known issue: exception handling tests are skipped.\n"); +#endif + return Harness::Done; +} diff --git a/src/tbb/src/test/test_parallel_invoke.cpp b/src/tbb/src/test/test_parallel_invoke.cpp new file mode 100644 index 0000000..12a3616 --- /dev/null +++ b/src/tbb/src/test/test_parallel_invoke.cpp @@ -0,0 +1,326 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if _MSC_VER && !defined(__INTEL_COMPILER) +#pragma warning(disable: 4180) // "qualifier applied to function type has no meaning; ignored" +#endif + +#include "tbb/parallel_invoke.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/atomic.h" +#include "tbb/tbb_exception.h" +#include "harness.h" + +#if !__INTEL_COMPILER && (_MSC_VER && _MSC_VER <= 1400 || __GNUC__==3 && __GNUC_MINOR__<=3 || __SUNPRO_CC) + #define __TBB_FUNCTION_BY_CONSTREF_IN_TEMPLATE_BROKEN 1 +#endif + +static const size_t MAX_NUMBER_OF_PINVOKE_ARGS = 10; +tbb::atomic<size_t> function_counter; + +// Some macros to make the test easier to read + +// 10 functions test0 ... test9 are defined +// pointer to each function is also defined + +#define TEST_FUNCTION(value) void test##value () \ +{ \ + ASSERT(!(function_counter & (1 << value)), "Test function has already been called"); \ + function_counter += 1 << value; \ +} \ +void (*test_pointer##value)(void) = test##value; + +TEST_FUNCTION(0) +TEST_FUNCTION(1) +TEST_FUNCTION(2) +TEST_FUNCTION(3) +TEST_FUNCTION(4) +TEST_FUNCTION(5) +TEST_FUNCTION(6) +TEST_FUNCTION(7) +TEST_FUNCTION(8) +TEST_FUNCTION(9) + +// The same with functors +#define TEST_FUNCTOR(value) class test_functor##value \ +{ \ +public: \ + void operator() () const { \ + function_counter += 1 << value; \ + } \ +} functor##value; + +TEST_FUNCTOR(0) +TEST_FUNCTOR(1) +TEST_FUNCTOR(2) +TEST_FUNCTOR(3) +TEST_FUNCTOR(4) +TEST_FUNCTOR(5) +TEST_FUNCTOR(6) +TEST_FUNCTOR(7) +TEST_FUNCTOR(8) +TEST_FUNCTOR(9) + +#define INIT_TEST function_counter = 0; + +#define VALIDATE_INVOKE_RUN(number_of_args, test_type) \ + ASSERT( (size_t)function_counter == (size_t)(1 << number_of_args) - 1, "parallel_invoke called with " #number_of_args " arguments didn't process all " #test_type); + +// Calls parallel_invoke for different number of arguments +// It can be called with and without user context +template <typename F0, typename F1, typename F2, typename F3, typename F4, typename F5, + typename F6, typename F7, typename F8, typename F9> +void call_parallel_invoke( size_t n, F0& f0, F1& f1, F2& f2, F3& f3, F4 &f4, F5 &f5, + F6& f6, F7 &f7, F8 &f8, F9 &f9, tbb::task_group_context* context) { + switch(n) { + default: + ASSERT(false, "number of arguments must be between 2 and 10"); + case 2: + if (context) + tbb::parallel_invoke (f0, f1, *context); + else + tbb::parallel_invoke (f0, f1); + break; + case 3: + if (context) + tbb::parallel_invoke (f0, f1, f2, *context); + else + tbb::parallel_invoke (f0, f1, f2); + break; + case 4: + if(context) + tbb::parallel_invoke (f0, f1, f2, f3, *context); + else + tbb::parallel_invoke (f0, f1, f2, f3); + break; + case 5: + if(context) + tbb::parallel_invoke (f0, f1, f2, f3, f4, *context); + else + tbb::parallel_invoke (f0, f1, f2, f3, f4); + break; + case 6: + if(context) + tbb::parallel_invoke (f0, f1, f2, f3, f4, f5, *context); + else + tbb::parallel_invoke (f0, f1, f2, f3, f4, f5); + break; + case 7: + if(context) + tbb::parallel_invoke (f0, f1, f2, f3, f4, f5, f6, *context); + else + tbb::parallel_invoke (f0, f1, f2, f3, f4, f5, f6); + break; + case 8: + if(context) + tbb::parallel_invoke (f0, f1, f2, f3, f4, f5, f6, f7, *context); + else + tbb::parallel_invoke (f0, f1, f2, f3, f4, f5, f6, f7); + break; + case 9: + if(context) + tbb::parallel_invoke (f0, f1, f2, f3, f4, f5, f6, f7, f8, *context); + else + tbb::parallel_invoke (f0, f1, f2, f3, f4, f5, f6, f7, f8); + break; + case 10: + if(context) + tbb::parallel_invoke (f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, *context); + else + tbb::parallel_invoke (f0, f1, f2, f3, f4, f5, f6, f7, f8, f9); + break; + } +} + +#if !__TBB_FUNCTION_BY_CONSTREF_IN_TEMPLATE_BROKEN +template<typename function> void aux_invoke(const function& f) { + f(); +} + +bool function_by_constref_in_template_codegen_broken() { + function_counter = 0; + aux_invoke(test1); + return function_counter==0; +} +#endif /* !__TBB_FUNCTION_BY_CONSTREF_IN_TEMPLATE_BROKEN */ + +void test_parallel_invoke() +{ + REMARK (__FUNCTION__); + // Testing with pointers to functions + for (int n = 2; n <=10; n++) + { + INIT_TEST; + call_parallel_invoke(n, test_pointer0, test_pointer1, test_pointer2, test_pointer3, test_pointer4, + test_pointer5, test_pointer6, test_pointer7, test_pointer8, test_pointer9, NULL); + VALIDATE_INVOKE_RUN(n, "pointers to function"); + } + + // Testing parallel_invoke with functors + for (int n = 2; n <=10; n++) + { + INIT_TEST; + call_parallel_invoke(n, functor0, functor1, functor2, functor3, functor4, + functor5, functor6, functor7, functor8, functor9, NULL); + VALIDATE_INVOKE_RUN(n, "functors"); + } + +#if __TBB_FUNCTION_BY_CONSTREF_IN_TEMPLATE_BROKEN + // some old compilers can't cope with passing function name into parallel_invoke +#else + // and some compile but generate broken code that does not call the function + if (function_by_constref_in_template_codegen_broken()) + return; + + // Testing parallel_invoke with functions + for (int n = 2; n <=10; n++) + { + INIT_TEST; + call_parallel_invoke(n, test0, test1, test2, test3, test4, test5, test6, test7, test8, test9, NULL); + VALIDATE_INVOKE_RUN(n, "functions"); + } +#endif +} + +// Exception handling support test + +#if __TBB_TASK_GROUP_CONTEXT +#define HARNESS_EH_SIMPLE_MODE 1 +#include "harness_eh.h" + +#if TBB_USE_EXCEPTIONS +volatile size_t exception_mask; // each bit represents whether the function should throw exception or not + +// throws exception if corresponding exception_mask bit is set +#define TEST_FUNCTOR_WITH_THROW(value) \ +struct throwing_functor##value { \ + void operator() () const { \ + if (exception_mask & (1 << value)) \ + ThrowTestException(); \ + } \ +} test_with_throw##value; + +TEST_FUNCTOR_WITH_THROW(0) +TEST_FUNCTOR_WITH_THROW(1) +TEST_FUNCTOR_WITH_THROW(2) +TEST_FUNCTOR_WITH_THROW(3) +TEST_FUNCTOR_WITH_THROW(4) +TEST_FUNCTOR_WITH_THROW(5) +TEST_FUNCTOR_WITH_THROW(6) +TEST_FUNCTOR_WITH_THROW(7) +TEST_FUNCTOR_WITH_THROW(8) +TEST_FUNCTOR_WITH_THROW(9) + +void TestExceptionHandling() +{ + REMARK (__FUNCTION__); + for( size_t n = 2; n <= 10; ++n ) { + for( exception_mask = 1; exception_mask < (size_t) (1 << n); ++exception_mask ) { + ResetEhGlobals(); + TRY(); + REMARK("Calling parallel_invoke, number of functions = %d, exception_mask = %d\n", n, exception_mask); + call_parallel_invoke(n, test_with_throw0, test_with_throw1, test_with_throw2, test_with_throw3, + test_with_throw4, test_with_throw5, test_with_throw6, test_with_throw7, test_with_throw8, test_with_throw9, NULL); + CATCH_AND_ASSERT(); + } + } +} +#endif /* TBB_USE_EXCEPTIONS */ + +// Cancelation support test +void function_to_cancel() { + ++g_CurExecuted; + CancellatorTask::WaitUntilReady(); +} + +// The function is used to test cancellation +void simple_test_nothrow (){ + ++g_CurExecuted; +} + +size_t g_numFunctions, + g_functionToCancel; + +class ParInvokeLauncherTask : public tbb::task +{ + tbb::task_group_context &my_ctx; + void(*func_array[10])(void); + + tbb::task* execute () { + func_array[g_functionToCancel] = &function_to_cancel; + call_parallel_invoke(g_numFunctions, func_array[0], func_array[1], func_array[2], func_array[3], + func_array[4], func_array[5], func_array[6], func_array[7], func_array[8], func_array[9], &my_ctx); + return NULL; + } +public: + ParInvokeLauncherTask ( tbb::task_group_context& ctx ) : my_ctx(ctx) { + for (int i = 0; i <=9; ++i) + func_array[i] = &simple_test_nothrow; + } +}; + +void TestCancellation () +{ + REMARK (__FUNCTION__); + for ( int n = 2; n <= 10; ++n ) { + for ( int m = 0; m <= n - 1; ++m ) { + g_numFunctions = n; + g_functionToCancel = m; + ResetEhGlobals(); + RunCancellationTest<ParInvokeLauncherTask, CancellatorTask>(); + } + } +} +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +//------------------------------------------------------------------------ +// Entry point +//------------------------------------------------------------------------ + +#include "harness_cpu.h" + +int TestMain () { + MinThread = min(MinThread, MaxThread); + ASSERT (MinThread>=1, "Minimal number of threads must be 1 or more"); + for ( int p = MinThread; p <= MaxThread; ++p ) { + tbb::task_scheduler_init init(p); + test_parallel_invoke(); + if (p > 1) { +#if __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN + REPORT("Known issue: exception handling tests are skipped.\n"); +#elif TBB_USE_EXCEPTIONS + TestExceptionHandling(); +#endif /* TBB_USE_EXCEPTIONS */ +#if __TBB_TASK_GROUP_CONTEXT + TestCancellation(); +#endif /* __TBB_TASK_GROUP_CONTEXT */ + } + TestCPUUserTime(p); + } + return Harness::Done; +} diff --git a/src/tbb/src/test/test_parallel_pipeline.cpp b/src/tbb/src/test/test_parallel_pipeline.cpp new file mode 100644 index 0000000..6713148 --- /dev/null +++ b/src/tbb/src/test/test_parallel_pipeline.cpp @@ -0,0 +1,716 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Before including pipeline.h, set up the variable to count heap allocated +// filter_node objects, and make it known for the header. +int filter_node_count = 0; +#define __TBB_TEST_FILTER_NODE_COUNT filter_node_count +#include "tbb/pipeline.h" + +#include "tbb/atomic.h" +#include "harness.h" +#include <string.h> + +#include "tbb/tbb_allocator.h" + +const unsigned n_tokens = 8; +// we can conceivably have two buffers used in the middle filter for every token in flight, so +// we must allocate two buffers for every token. Unlikely, but possible. +const unsigned n_buffers = 2*n_tokens; +const unsigned max_counter = 16; +static tbb::atomic<int> output_counter; +static tbb::atomic<int> input_counter; +static tbb::atomic<int> check_type_counter; +static tbb::atomic<int> non_pointer_specialized_calls; +static tbb::atomic<int> pointer_specialized_calls; +static tbb::atomic<int> first_pointer_specialized_calls; +static tbb::atomic<int> second_pointer_specialized_calls; + +static int intbuffer[max_counter]; // store results for <int,int> parallel pipeline test +static bool check_intbuffer; + +static void* buffers[n_buffers]; +static bool buf_available[n_buffers]; +static tbb::atomic<size_t> nextBuffer; + +void *fetchNextBuffer() { + for(size_t icnt = 0; icnt < n_buffers; ++icnt) { + size_t indx = ++nextBuffer; + if(buf_available[indx%n_buffers]) { + buf_available[indx%n_buffers] = false; + return buffers[indx%n_buffers]; + } + } + ASSERT(0, "Ran out of buffers"); + return 0; +} +void freeBuffer(void *buf) { + for(size_t i=0; i < n_buffers;++i) { + if(buffers[i] == buf) { + buf_available[i] = true; + return; + } + } + ASSERT(0, "Tried to free a buffer not in our list"); +} + +template<typename T> +class free_on_scope_exit { +public: + free_on_scope_exit(T *p) : my_p(p) {} + ~free_on_scope_exit() { if(!my_p) return; my_p->~T(); freeBuffer(my_p); } +private: + T *my_p; +}; + +template<class Counter> +class check_type : Harness::NoAfterlife { + Counter id; + bool am_ready; +public: + check_type( ) : id(0), am_ready(false) { + ++check_type_counter; + } + + check_type(const check_type& other) : Harness::NoAfterlife(other) { + other.AssertLive(); + AssertLive(); + id = other.id; + am_ready = other.am_ready; + ++check_type_counter; + } + + ~check_type() { + AssertLive(); + --check_type_counter; + ASSERT(check_type_counter >= 0, "too many destructions"); + } + + unsigned int my_id() { AssertLive(); return id; } + bool is_ready() { AssertLive(); return am_ready; } + void function() { + AssertLive(); + if( id == 0 ) { + id = 1; + am_ready = true; + } + } +}; + +// methods for testing check_type< >, that return okay values for other types. +template<typename T> +bool middle_is_ready(T &/*p*/) { return false; } + +template<typename U> +bool middle_is_ready(check_type<U> &p) { return p.is_ready(); } + +template<typename T> +bool output_is_ready(T &/*p*/) { return true; } + +template<typename U> +bool output_is_ready(check_type<U> &p) { return p.is_ready(); } + +template<typename T> +int middle_my_id( T &/*p*/) { return 0; } + +template<typename U> +int middle_my_id(check_type<U> &p) { return p.my_id(); } + +template<typename T> +int output_my_id( T &/*p*/) { return 1; } + +template<typename U> +int output_my_id(check_type<U> &p) { return p.my_id(); } + +template<typename T> +void my_function(T &p) { p = 0; } + +template<typename U> +void my_function(check_type<U> &p) { p.function(); } + +// Filters must be copy-constructible, and be const-qualifiable. +template<typename U> +class input_filter : Harness::NoAfterlife { +public: + U operator()( tbb::flow_control& control ) const { + AssertLive(); + if( --input_counter < 0 ) { + control.stop(); + } + else // only count successful reads + ++non_pointer_specialized_calls; + return U(); // default constructed + } + +}; + +// specialization for pointer +template<typename U> +class input_filter<U*> : Harness::NoAfterlife { +public: + U* operator()(tbb::flow_control& control) const { + AssertLive(); + int ival = --input_counter; + if(ival < 0) { + control.stop(); + return NULL; + } + ++pointer_specialized_calls; + if(ival == max_counter / 2) { + return NULL; // non-stop NULL + } + U* myReturn = new(fetchNextBuffer()) U(); + return myReturn; + } +}; + +template<> +class input_filter<void> : Harness::NoAfterlife { +public: + void operator()( tbb::flow_control& control ) const { + AssertLive(); + if( --input_counter < 0 ) { + control.stop(); + } + else + ++non_pointer_specialized_calls; + } + +}; + +// specialization for int that passes back a sequence of integers +template<> +class input_filter<int> : Harness::NoAfterlife { +public: + int + operator()(tbb::flow_control& control ) const { + AssertLive(); + int oldval = --input_counter; + if( oldval < 0 ) { + control.stop(); + } + else + ++non_pointer_specialized_calls; + return oldval+1; + } +}; + +template<typename T, typename U> +class middle_filter : Harness::NoAfterlife { +public: + U operator()(T t) const { + AssertLive(); + ASSERT(!middle_my_id(t), "bad id value"); + ASSERT(!middle_is_ready(t), "Already ready" ); + U out; + my_function(out); + ++non_pointer_specialized_calls; + return out; + } +}; + +template<typename T, typename U> +class middle_filter<T*,U> : Harness::NoAfterlife { +public: + U operator()(T* my_storage) const { + free_on_scope_exit<T> my_ptr(my_storage); // free_on_scope_exit marks the buffer available + AssertLive(); + if(my_storage) { // may have been passed in a NULL + ASSERT(!middle_my_id(*my_storage), "bad id value"); + ASSERT(!middle_is_ready(*my_storage), "Already ready" ); + } + ++first_pointer_specialized_calls; + U out; + my_function(out); + return out; + } +}; + +template<typename T, typename U> +class middle_filter<T,U*> : Harness::NoAfterlife { +public: + U* operator()(T my_storage) const { + AssertLive(); + ASSERT(!middle_my_id(my_storage), "bad id value"); + ASSERT(!middle_is_ready(my_storage), "Already ready" ); + // allocate new space from buffers + U* my_return = new(fetchNextBuffer()) U(); + my_function(*my_return); + ++second_pointer_specialized_calls; + return my_return; + } +}; + +template<typename T, typename U> +class middle_filter<T*,U*> : Harness::NoAfterlife { +public: + U* operator()(T* my_storage) const { + free_on_scope_exit<T> my_ptr(my_storage); // free_on_scope_exit marks the buffer available + AssertLive(); + if(my_storage) { + ASSERT(!middle_my_id(*my_storage), "bad id value"); + ASSERT(!middle_is_ready(*my_storage), "Already ready" ); + } + // may have been passed a NULL + ++pointer_specialized_calls; + if(!my_storage) return NULL; + ASSERT(!middle_my_id(*my_storage), "bad id value"); + ASSERT(!middle_is_ready(*my_storage), "Already ready" ); + U* my_return = new(fetchNextBuffer()) U(); + my_function(*my_return); + return my_return; + } +}; + +// specialization for int that squares the input and returns that. +template<> +class middle_filter<int,int> : Harness::NoAfterlife { +public: + int operator()(int my_input) const { + AssertLive(); + ++non_pointer_specialized_calls; + return my_input*my_input; + } +}; + +// --------------------------------- +template<typename T> +class output_filter : Harness::NoAfterlife { +public: + void operator()(T c) const { + AssertLive(); + ASSERT(output_my_id(c), "unset id value"); + ASSERT(output_is_ready(c), "not yet ready"); + ++non_pointer_specialized_calls; + output_counter++; + } +}; + +// specialization for int that puts the received value in an array +template<> +class output_filter<int> : Harness::NoAfterlife { +public: + void operator()(int my_input) const { + AssertLive(); + ++non_pointer_specialized_calls; + int myindx = output_counter++; + intbuffer[myindx] = my_input; + } +}; + + +template<typename T> +class output_filter<T*> : Harness::NoAfterlife { +public: + void operator()(T* c) const { + free_on_scope_exit<T> my_ptr(c); + AssertLive(); + if(c) { + ASSERT(output_my_id(*c), "unset id value"); + ASSERT(output_is_ready(*c), "not yet ready"); + } + output_counter++; + ++pointer_specialized_calls; + } +}; + +typedef enum { + no_pointer_counts, + assert_nonpointer, + assert_firstpointer, + assert_secondpointer, + assert_allpointer +} final_assert_type; + +void resetCounters() { + output_counter = 0; + input_counter = max_counter; + nextBuffer = 0; + non_pointer_specialized_calls = 0; + pointer_specialized_calls = 0; + first_pointer_specialized_calls = 0; + second_pointer_specialized_calls = 0; + // we have to reset the buffer flags because our input filters return allocated space on end-of-input, + // (on eof a default-constructed object is returned) and they do not pass through the filter further. + for(size_t i = 0; i < n_buffers; ++i) + buf_available[i] = true; +} + +void checkCounters(final_assert_type my_t) { + ASSERT(output_counter == max_counter, "not all tokens were passed through pipeline"); + switch(my_t) { + case assert_nonpointer: + ASSERT(pointer_specialized_calls+first_pointer_specialized_calls+second_pointer_specialized_calls == 0, "non-pointer filters specialized to pointer"); + ASSERT(non_pointer_specialized_calls == 3*max_counter, "bad count for non-pointer filters"); + if(check_intbuffer) { + for(int i = 1; i <= (int)max_counter; ++i) { + int j = i*i; + bool found_val = false; + for(int k = 0; k < (int)max_counter; ++k) { + if(intbuffer[k] == j) { + found_val = true; + break; + } + } + ASSERT(found_val, "Missing value in output array" ); + } + } + break; + case assert_firstpointer: + ASSERT(pointer_specialized_calls == max_counter && // input filter extra invocation + first_pointer_specialized_calls == max_counter && + non_pointer_specialized_calls == max_counter && + second_pointer_specialized_calls == 0, "incorrect specialization for firstpointer"); + break; + case assert_secondpointer: + ASSERT(pointer_specialized_calls == max_counter && + first_pointer_specialized_calls == 0 && + non_pointer_specialized_calls == max_counter && // input filter + second_pointer_specialized_calls == max_counter, "incorrect specialization for firstpointer"); + break; + case assert_allpointer: + ASSERT(non_pointer_specialized_calls+first_pointer_specialized_calls+second_pointer_specialized_calls == 0, "pointer filters specialized to non-pointer"); + ASSERT(pointer_specialized_calls == 3*max_counter, "bad count for pointer filters"); + break; + case no_pointer_counts: + break; + } + if(check_type_counter > 0) { + REMARK("check_type_counter == %lu\n", (unsigned long)check_type_counter); + } + ASSERT(!check_type_counter, "Error in check_type creation/destruction"); +} + +static const tbb::filter::mode filter_table[] = { tbb::filter::parallel, tbb::filter::serial_in_order, tbb::filter::serial_out_of_order}; +const unsigned number_of_filter_types = sizeof(filter_table)/sizeof(filter_table[0]); + +typedef tbb::filter_t<void, void> filter_chain; +typedef tbb::filter::mode mode_array; + +// The filters are passed by value, which forces a temporary copy to be created. This is +// to reproduce the bug where a filter_chain uses refs to filters, which after a call +// would be references to destructed temporaries. +template<typename type1, typename type2> +void fill_chain( filter_chain &my_chain, mode_array *filter_type, input_filter<type1> i_filter, + middle_filter<type1, type2> m_filter, output_filter<type2> o_filter ) { + my_chain = tbb::make_filter<void, type1>(filter_type[0], i_filter) & + tbb::make_filter<type1, type2>(filter_type[1], m_filter) & + tbb::make_filter<type2, void>(filter_type[2], o_filter); +} + +void run_function_spec() { + ASSERT(!filter_node_count, NULL); + REMARK("Testing < void, void > (single filter in pipeline)"); +#if __TBB_LAMBDAS_PRESENT + REMARK( " ( + lambdas)"); +#endif + REMARK("\n"); + input_filter<void> i_filter; + // Test pipeline that contains only one filter + for( unsigned i = 0; i<number_of_filter_types; i++) { + tbb::filter_t<void, void> one_filter( filter_table[i], i_filter ); + ASSERT(filter_node_count==1, "some filter nodes left after previous iteration?"); + resetCounters(); + tbb::parallel_pipeline( n_tokens, one_filter ); + // no need to check counters +#if __TBB_LAMBDAS_PRESENT + tbb::atomic<int> counter; + counter = max_counter; + // Construct filter using lambda-syntax when parallel_pipeline() is being run; + tbb::parallel_pipeline( n_tokens, + tbb::make_filter<void, void>(filter_table[i], [&counter]( tbb::flow_control& control ) { + if( counter-- == 0 ) + control.stop(); + } + ) + ); +#endif + } + ASSERT(!filter_node_count, "filter_node objects leaked"); +} + +template<typename t1, typename t2> +void run_filter_set( + input_filter<t1>& i_filter, + middle_filter<t1,t2>& m_filter, + output_filter<t2>& o_filter, + mode_array *filter_type, + final_assert_type my_t) { + tbb::filter_t<void, t1> filter1( filter_type[0], i_filter ); + tbb::filter_t<t1, t2> filter2( filter_type[1], m_filter ); + tbb::filter_t<t2, void> filter3( filter_type[2], o_filter ); + ASSERT(filter_node_count==3, "some filter nodes left after previous iteration?"); + resetCounters(); + // Create filters sequence when parallel_pipeline() is being run + tbb::parallel_pipeline( n_tokens, filter1 & filter2 & filter3 ); + checkCounters(my_t); + + // Create filters sequence partially outside parallel_pipeline() and also when parallel_pipeline() is being run + tbb::filter_t<void, t2> filter12; + filter12 = filter1 & filter2; + resetCounters(); + tbb::parallel_pipeline( n_tokens, filter12 & filter3 ); + checkCounters(my_t); + + tbb::filter_t<void, void> filter123 = filter12 & filter3; + // Run pipeline twice with the same filter sequence + for( unsigned i = 0; i<2; i++ ) { + resetCounters(); + tbb::parallel_pipeline( n_tokens, filter123 ); + checkCounters(my_t); + } + + // Now copy-construct another filter_t instance, and use it to run pipeline + { + tbb::filter_t<void, void> copy123( filter123 ); + resetCounters(); + tbb::parallel_pipeline( n_tokens, copy123 ); + checkCounters(my_t); + } + + // Construct filters and create the sequence when parallel_pipeline() is being run + resetCounters(); + tbb::parallel_pipeline( n_tokens, + tbb::make_filter<void, t1>(filter_type[0], i_filter) & + tbb::make_filter<t1, t2>(filter_type[1], m_filter) & + tbb::make_filter<t2, void>(filter_type[2], o_filter) ); + checkCounters(my_t); + + // Construct filters, make a copy, destroy the original filters, and run with the copy + int cnt = filter_node_count; + { + tbb::filter_t<void, void>* p123 = new tbb::filter_t<void,void> ( + tbb::make_filter<void, t1>(filter_type[0], i_filter) & + tbb::make_filter<t1, t2>(filter_type[1], m_filter) & + tbb::make_filter<t2, void>(filter_type[2], o_filter) ); + ASSERT(filter_node_count==cnt+5, "filter node accounting error?"); + tbb::filter_t<void, void> copy123( *p123 ); + delete p123; + ASSERT(filter_node_count==cnt+5, "filter nodes deleted prematurely?"); + resetCounters(); + tbb::parallel_pipeline( n_tokens, copy123 ); + checkCounters(my_t); + } + + // construct a filter with temporaries + { + tbb::filter_t<void, void> my_filter; + fill_chain<t1,t2>( my_filter, filter_type, i_filter, m_filter, o_filter ); + resetCounters(); + tbb::parallel_pipeline( n_tokens, my_filter ); + checkCounters(my_t); + } + ASSERT(filter_node_count==cnt, "scope ended but filter nodes not deleted?"); +} + +#if __TBB_LAMBDAS_PRESENT +template <typename t1, typename t2> +void run_lambdas_test( mode_array *filter_type ) { + tbb::atomic<int> counter; + counter = max_counter; + // Construct filters using lambda-syntax and create the sequence when parallel_pipeline() is being run; + resetCounters(); // only need the output_counter reset. + tbb::parallel_pipeline( n_tokens, + tbb::make_filter<void, t1>(filter_type[0], [&counter]( tbb::flow_control& control ) -> t1 { + if( --counter < 0 ) + control.stop(); + return t1(); } + ) & + tbb::make_filter<t1, t2>(filter_type[1], []( t1 /*my_storage*/ ) -> t2 { + return t2(); } + ) & + tbb::make_filter<t2, void>(filter_type[2], [] ( t2 ) -> void { + output_counter++; } + ) + ); + checkCounters(no_pointer_counts); // don't have to worry about specializations + counter = max_counter; + // pointer filters + resetCounters(); + tbb::parallel_pipeline( n_tokens, + tbb::make_filter<void, t1*>(filter_type[0], [&counter]( tbb::flow_control& control ) -> t1* { + if( --counter < 0 ) { + control.stop(); + return NULL; + } + return new(fetchNextBuffer()) t1(); } + ) & + tbb::make_filter<t1*, t2*>(filter_type[1], []( t1* my_storage ) -> t2* { + tbb::tbb_allocator<t1>().destroy(my_storage); // my_storage->~t1(); + return new(my_storage) t2(); } + ) & + tbb::make_filter<t2*, void>(filter_type[2], [] ( t2* my_storage ) -> void { + tbb::tbb_allocator<t2>().destroy(my_storage); // my_storage->~t2(); + freeBuffer(my_storage); + output_counter++; } + ) + ); + checkCounters(no_pointer_counts); + // first filter outputs pointer + counter = max_counter; + resetCounters(); + tbb::parallel_pipeline( n_tokens, + tbb::make_filter<void, t1*>(filter_type[0], [&counter]( tbb::flow_control& control ) -> t1* { + if( --counter < 0 ) { + control.stop(); + return NULL; + } + return new(fetchNextBuffer()) t1(); } + ) & + tbb::make_filter<t1*, t2>(filter_type[1], []( t1* my_storage ) -> t2 { + tbb::tbb_allocator<t1>().destroy(my_storage); // my_storage->~t1(); + freeBuffer(my_storage); + return t2(); } + ) & + tbb::make_filter<t2, void>(filter_type[2], [] ( t2 /*my_storage*/) -> void { + output_counter++; } + ) + ); + checkCounters(no_pointer_counts); + // second filter outputs pointer + counter = max_counter; + resetCounters(); + tbb::parallel_pipeline( n_tokens, + tbb::make_filter<void, t1>(filter_type[0], [&counter]( tbb::flow_control& control ) -> t1 { + if( --counter < 0 ) { + control.stop(); + } + return t1(); } + ) & + tbb::make_filter<t1, t2*>(filter_type[1], []( t1 /*my_storage*/ ) -> t2* { + return new(fetchNextBuffer()) t2(); } + ) & + tbb::make_filter<t2*, void>(filter_type[2], [] ( t2* my_storage) -> void { + tbb::tbb_allocator<t2>().destroy(my_storage); // my_storage->~t2(); + freeBuffer(my_storage); + output_counter++; } + ) + ); + checkCounters(no_pointer_counts); +} +#endif + +template<typename type1, typename type2> +void run_function(const char *l1, const char *l2) { + ASSERT(!filter_node_count, NULL); + REMARK("Testing < %s, %s >", l1, l2 ); +#if __TBB_LAMBDAS_PRESENT + REMARK( " ( + lambdas)"); +#endif + check_intbuffer = (!strcmp(l1,"int") && !strcmp(l2,"int")); + if(check_intbuffer) REMARK(", check output of filters"); + REMARK("\n"); + + const size_t number_of_filters = 3; + + input_filter<type1> i_filter; + input_filter<type1*> p_i_filter; + + middle_filter<type1, type2> m_filter; + middle_filter<type1*, type2> pr_m_filter; + middle_filter<type1, type2*> rp_m_filter; + middle_filter<type1*, type2*> pp_m_filter; + + output_filter<type2> o_filter; + output_filter<type2*> p_o_filter; + + // allocate the buffers for the filters + unsigned max_size = (sizeof(type1) > sizeof(type2) ) ? sizeof(type1) : sizeof(type2); + for(unsigned i = 0; i < (unsigned)n_buffers; ++i) { + buffers[i] = malloc(max_size); + buf_available[i] = true; + } + + unsigned limit = 1; + // Test pipeline that contains number_of_filters filters + for( unsigned i=0; i<number_of_filters; ++i) + limit *= number_of_filter_types; + // Iterate over possible filter sequences + for( unsigned numeral=0; numeral<limit; ++numeral ) { + unsigned temp = numeral; + tbb::filter::mode filter_type[number_of_filter_types]; + for( unsigned i=0; i<number_of_filters; ++i, temp/=number_of_filter_types ) + filter_type[i] = filter_table[temp%number_of_filter_types]; + + run_filter_set<type1,type2>(i_filter, m_filter, o_filter, filter_type, assert_nonpointer ); + run_filter_set<type1*,type2>(p_i_filter, pr_m_filter, o_filter, filter_type, assert_firstpointer); + run_filter_set<type1,type2*>(i_filter, rp_m_filter, p_o_filter, filter_type, assert_secondpointer); + run_filter_set<type1*,type2*>(p_i_filter, pp_m_filter, p_o_filter, filter_type, assert_allpointer); + +#if __TBB_LAMBDAS_PRESENT + run_lambdas_test<type1,type2>(filter_type); +#endif + } + ASSERT(!filter_node_count, "filter_node objects leaked"); + + for(unsigned i = 0; i < (unsigned)n_buffers; ++i) { + free(buffers[i]); + } +} + +#include "tbb/task_scheduler_init.h" + +int TestMain() { +#if TBB_USE_DEBUG + // size and copyability. + REMARK("is_large_object<int>::value=%d\n", tbb::interface6::internal::is_large_object<int>::value); + REMARK("is_large_object<double>::value=%d\n", tbb::interface6::internal::is_large_object<double>::value); + REMARK("is_large_object<int *>::value=%d\n", tbb::interface6::internal::is_large_object<int *>::value); + REMARK("is_large_object<check_type<int> >::value=%d\n", tbb::interface6::internal::is_large_object<check_type<int> >::value); + REMARK("is_large_object<check_type<int>* >::value=%d\n", tbb::interface6::internal::is_large_object<check_type<int>* >::value); + REMARK("is_large_object<check_type<short> >::value=%d\n\n", tbb::interface6::internal::is_large_object<check_type<short> >::value); +#endif + // Test with varying number of threads. + for( int nthread=MinThread; nthread<=MaxThread; ++nthread ) { + // Initialize TBB task scheduler + REMARK("\nTesting with nthread=%d\n", nthread); + tbb::task_scheduler_init init(nthread); + + // Run test several times with different types + run_function_spec(); + run_function<size_t,int>("size_t", "int"); + run_function<int,double>("int", "double"); + run_function<size_t,double>("size_t", "double"); + run_function<size_t,bool>("size_t", "bool"); + run_function<int,int>("int","int"); + check_type_counter = 0; + run_function<check_type<unsigned int>,size_t>("check_type<unsigned int>", "size_t"); + ASSERT(!check_type_counter, "Error in check_type<unsigned int> creation/destruction"); + run_function<check_type<unsigned short>,size_t>("check_type<unsigned short>", "size_t"); + ASSERT(!check_type_counter, "Error in check_type<unsigned short> creation/destruction"); + run_function<check_type<unsigned int>, check_type<unsigned int> >("check_type<unsigned int>", "check_type<unsigned int>"); + run_function<check_type<unsigned int>, check_type<unsigned short> >("check_type<unsigned int>", "check_type<unsigned short>"); + ASSERT(!check_type_counter, "Error in check_type<unsigned int> creation/destruction"); + run_function<check_type<unsigned short>, check_type<unsigned short> >("check_type<unsigned short>", "check_type<unsigned short>"); + ASSERT(!check_type_counter, "Error in check_type<unsigned short> creation/destruction"); + run_function<double, check_type<unsigned short> >("double", "check_type<unsigned short>"); + ASSERT(!check_type_counter, "Error in check_type<unsigned short> creation/destruction"); + } + return Harness::Done; +} + diff --git a/src/tbb/src/test/test_parallel_reduce.cpp b/src/tbb/src/test/test_parallel_reduce.cpp new file mode 100644 index 0000000..854d59f --- /dev/null +++ b/src/tbb/src/test/test_parallel_reduce.cpp @@ -0,0 +1,342 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#define TBB_PREVIEW_DETERMINISTIC_REDUCE 1 +#include "tbb/parallel_reduce.h" +#include "tbb/atomic.h" +#include "harness_assert.h" + +using namespace std; + +static tbb::atomic<long> ForkCount; +static tbb::atomic<long> FooBodyCount; + +//! Class with public interface that is exactly minimal requirements for Range concept +class MinimalRange { + size_t begin, end; + friend class FooBody; + explicit MinimalRange( size_t i ) : begin(0), end(i) {} + friend void Flog( int nthread, bool inteference ); +public: + MinimalRange( MinimalRange& r, tbb::split ) : end(r.end) { + begin = r.end = (r.begin+r.end)/2; + } + bool is_divisible() const {return end-begin>=2;} + bool empty() const {return begin==end;} +}; + +//! Class with public interface that is exactly minimal requirements for Body of a parallel_reduce +class FooBody { +private: + FooBody( const FooBody& ); // Deny access + void operator=( const FooBody& ); // Deny access + friend void Flog( int nthread, bool interference ); + //! Parent that created this body via split operation. NULL if original body. + FooBody* parent; + //! Total number of index values processed by body and its children. + size_t sum; + //! Number of join operations done so far on this body and its children. + long join_count; + //! Range that has been processed so far by this body and its children. + size_t begin, end; + //! True if body has not yet been processed at least once by operator(). + bool is_new; + //! 1 if body was created by split; 0 if original body. + int forked; + FooBody() {++FooBodyCount;} +public: + ~FooBody() { + forked = 0xDEADBEEF; + sum=0xDEADBEEF; + join_count=0xDEADBEEF; + --FooBodyCount; + } + FooBody( FooBody& other, tbb::split ) { + ++FooBodyCount; + ++ForkCount; + sum = 0; + parent = &other; + join_count = 0; + is_new = true; + forked = 1; + } + void join( FooBody& s ) { + ASSERT( s.forked==1, NULL ); + ASSERT( this!=&s, NULL ); + ASSERT( this==s.parent, NULL ); + ASSERT( end==s.begin, NULL ); + end = s.end; + sum += s.sum; + join_count += s.join_count + 1; + s.forked = 2; + } + void operator()( const MinimalRange& r ) { + for( size_t k=r.begin; k<r.end; ++k ) + ++sum; + if( is_new ) { + is_new = false; + begin = r.begin; + } else + ASSERT( end==r.begin, NULL ); + end = r.end; + } +}; + +#include <cstdio> +#include "harness.h" +#include "tbb/tick_count.h" + +void Flog( int nthread, bool interference=false ) { + for (int mode = 0; mode < 4; mode++) { + tbb::tick_count T0 = tbb::tick_count::now(); + long join_count = 0; + tbb::affinity_partitioner ap; + for( size_t i=0; i<=1000; ++i ) { + FooBody f; + f.sum = 0; + f.parent = NULL; + f.join_count = 0; + f.is_new = true; + f.forked = 0; + f.begin = ~size_t(0); + f.end = ~size_t(0); + ASSERT( FooBodyCount==1, NULL ); + switch (mode) { + case 0: + tbb::parallel_reduce( MinimalRange(i), f ); + break; + case 1: + tbb::parallel_reduce( MinimalRange(i), f, tbb::simple_partitioner() ); + break; + case 2: + tbb::parallel_reduce( MinimalRange(i), f, tbb::auto_partitioner() ); + break; + case 3: + tbb::parallel_reduce( MinimalRange(i), f, ap ); + break; + } + join_count += f.join_count; + ASSERT( FooBodyCount==1, NULL ); + ASSERT( f.sum==i, NULL ); + ASSERT( f.begin==(i==0 ? ~size_t(0) : 0), NULL ); + ASSERT( f.end==(i==0 ? ~size_t(0) : i), NULL ); + } + tbb::tick_count T1 = tbb::tick_count::now(); + REMARK("time=%g join_count=%ld ForkCount=%ld nthread=%d%s\n", + (T1-T0).seconds(),join_count,long(ForkCount), nthread, interference ? " with interference":""); + } +} + +class DeepThief: public tbb::task { + /*override*/tbb::task* execute() { + if( !is_stolen_task() ) + spawn(*child); + wait_for_all(); + return NULL; + } + task* child; + friend void FlogWithInterference(int); +public: + DeepThief() : child() {} +}; + +//! Test for problem in TBB 2.1 parallel_reduce where middle of a range is stolen. +/** Warning: this test is a somewhat abusive use of TBB because + it requires two or more threads to avoid deadlock. */ +void FlogWithInterference( int nthread ) { + ASSERT( nthread>=2, "requires too or more threads" ); + + // Build linear chain of tasks. + // The purpose is to drive up "task depth" in TBB 2.1. + // An alternative would be to use add_to_depth, but that method is deprecated in TBB 2.2, + // and this way we generalize to catching problems with implicit depth calculations. + tbb::task* root = new( tbb::task::allocate_root() ) tbb::empty_task; + root->set_ref_count(2); + tbb::task* t = root; + for( int i=0; i<3; ++i ) { + t = new( t->allocate_child() ) tbb::empty_task; + t->set_ref_count(1); + } + + // Append a DeepThief to the chain. + DeepThief* deep_thief = new( t->allocate_child() ) DeepThief; + deep_thief->set_ref_count(2); + + // Append a leaf to the chain. + tbb::task* leaf = new( deep_thief->allocate_child() ) tbb::empty_task; + deep_thief->child = leaf; + + root->spawn(*deep_thief); + + Flog(nthread,true); + + if( root->ref_count()==2 ) { + // Spawn leaf, which when it finishes, cause the DeepThief and rest of the chain to finish. + root->spawn( *leaf ); + } + // Wait for all tasks in the chain from root to leaf to finish. + root->wait_for_all(); + tbb::task::destroy( *root ); +} + +#include "tbb/blocked_range.h" + +#if _MSC_VER + typedef tbb::internal::uint64_t ValueType; +#else + typedef uint64_t ValueType; +#endif + +struct Sum { + template<typename T> + T operator() ( const T& v1, const T& v2 ) const { + return v1 + v2; + } +}; + +struct Accumulator { + ValueType operator() ( const tbb::blocked_range<ValueType*>& r, ValueType value ) const { + for ( ValueType* pv = r.begin(); pv != r.end(); ++pv ) + value += *pv; + return value; + } +}; + +void ParallelSum () { + const ValueType I = 0, + N = 1000000, + R = N * (N + 1) / 2; + ValueType *array = new ValueType[N + 1]; + for ( ValueType i = 0; i < N; ++i ) + array[i] = i + 1; + tbb::blocked_range<ValueType*> range(array, array + N); + ValueType r1 = tbb::parallel_reduce( range, I, Accumulator(), Sum() ); + ASSERT( r1 == R, NULL ); +#if __TBB_LAMBDAS_PRESENT + ValueType r2 = tbb::parallel_reduce( range, I, + [](const tbb::blocked_range<ValueType*>& r, ValueType value) -> ValueType { + for ( ValueType* pv = r.begin(); pv != r.end(); ++pv ) + value += *pv; + return value; + }, + Sum() + ); + ASSERT( r2 == R, NULL ); +#endif /* LAMBDAS */ + delete[] array; +} + +const int N = 1000; + +#include "harness_concurrency_tracker.h" + +template <class Op> +struct ReduceBody { + typename Op::Type my_value; + + ReduceBody() : my_value() {} + ReduceBody( ReduceBody &, tbb::split ) : my_value() {} + + void operator() ( const tbb::blocked_range<int>& r ) { + Harness::ConcurrencyTracker ct; + for ( int i = r.begin(); i != r.end(); ++i ) { + Op op; + my_value = op(my_value, i); + } + } + + void join( const ReduceBody& y ) { + Op op; + my_value = op.join(my_value, y.my_value); + } +}; + +template <class Op> +void TestDeterministicReduction () { + typedef typename Op::Type Type; + const tbb::blocked_range<int> range(0, N); + ReduceBody<Op> body; + tbb::parallel_deterministic_reduce( range,body ); + Type R = body.my_value; + for ( int i=0; i<100; ++i ) { + ReduceBody<Op> body2; + tbb::parallel_deterministic_reduce( range,body2 ); + ASSERT( body2.my_value == R, NULL ); +#if __TBB_LAMBDAS_PRESENT + Type r = tbb::parallel_deterministic_reduce( range, Type(), + [](const tbb::blocked_range<int>& br, Type value) -> Type { + Harness::ConcurrencyTracker ct; + for ( int ii = br.begin(); ii != br.end(); ++ii ) { + Op op; + value = op(value, ii); + } + return value; + }, + [](const Type& v1, const Type& v2) -> Type { + Op op; + return op.join(v1,v2); + } + ); + ASSERT( r == R, NULL ); +#endif /* LAMBDAS */ + } + ASSERT_WARNING((Harness::ConcurrencyTracker::PeakParallelism() > 1), "no parallel execution\n"); +} + +class RotOp { +public: + typedef int Type; + int operator() ( int x, int i ) const { + return ( x<<1 ) ^ i; + } + int join( int x, int y ) const { + return operator()( x, y ); + } +}; + +#include "tbb/task_scheduler_init.h" +#include "harness_cpu.h" + +int TestMain () { + if( MinThread<0 ) { + REPORT("Usage: nthread must be positive\n"); + exit(1); + } + for( int p=MinThread; p<=MaxThread; ++p ) { + tbb::task_scheduler_init init( p ); + Flog(p); + if( p>=2 ) + FlogWithInterference(p); + ParallelSum(); + if ( p>=2 ) + TestDeterministicReduction<RotOp>(); + // Test that all workers sleep when no work + TestCPUUserTime(p); + } + return Harness::Done; +} diff --git a/src/tbb/src/test/test_parallel_scan.cpp b/src/tbb/src/test/test_parallel_scan.cpp new file mode 100644 index 0000000..cd0d880 --- /dev/null +++ b/src/tbb/src/test/test_parallel_scan.cpp @@ -0,0 +1,270 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/parallel_scan.h" +#include "tbb/blocked_range.h" +#include "harness_assert.h" + +typedef tbb::blocked_range<long> Range; + +static volatile bool ScanIsRunning = false; + +//! Sum of 0..i with wrap around on overflow. +inline int TriangularSum( int i ) { + return i&1 ? ((i>>1)+1)*i : (i>>1)*(i+1); +} + +//! Verify that sum is sum of integers in closed interval [start_index..finish_index]. +/** line should be the source line of the caller */ +static void VerifySum( long start_index, long finish_index, int sum, int line ); + +const int MAXN = 2000; + +enum AddendFlag { + UNUSED=0, + USED_NONFINAL=1, + USED_FINAL=2 +}; + +//! Array recording how each addend was used. +/** 'unsigned char' instead of AddendFlag for sake of compactness. */ +static unsigned char AddendHistory[MAXN]; + +//! Set to 1 for debugging output +#define PRINT_DEBUG 0 + +#include "tbb/atomic.h" +#if PRINT_DEBUG +#include <stdio.h> +tbb::atomic<long> NextBodyId; +#endif /* PRINT_DEBUG */ + +struct BodyId { +#if PRINT_DEBUG + const int id; + BodyId() : id(NextBodyId++) {} +#endif /* PRINT_DEBUG */ +}; + +tbb::atomic<long> NumberOfLiveAccumulator; + +static void Snooze( bool scan_should_be_running ) { + ASSERT( ScanIsRunning==scan_should_be_running, NULL ); +} + +template<typename T> +class Accumulator: BodyId { + T my_total; + const T* my_array; + T* my_sum; + Range my_range; + //! Equals this while object is fully constructed, NULL otherwise. + /** Used to detect premature destruction and accidental bitwise copy. */ + Accumulator* self; + Accumulator( const T array[], T sum[] ) : + my_total(), my_array(array), my_sum(sum), my_range(-1,-1,1) + { + ++NumberOfLiveAccumulator; + // Set self as last action of constructor, to indicate that object is fully constructed. + self = this; + } + friend void TestAccumulator( int mode, int nthread ); +public: +#if PRINT_DEBUG + void print() const { + REPORT("%d [%ld..%ld)\n", id,my_range.begin(),my_range.end() ); + } +#endif /* PRINT_DEBUG */ + ~Accumulator() { +#if PRINT_DEBUG + REPORT("%d [%ld..%ld) destroyed\n",id,my_range.begin(),my_range.end() ); +#endif /* PRINT_DEBUG */ + // Clear self as first action of destructor, to indicate that object is not fully constructed. + self = 0; + --NumberOfLiveAccumulator; + } + Accumulator( Accumulator& a, tbb::split ) : + my_total(0), my_array(a.my_array), my_sum(a.my_sum), my_range(-1,-1,1) + { + ++NumberOfLiveAccumulator; +#if PRINT_DEBUG + REPORT("%d forked from %d\n",id,a.id); +#endif /* PRINT_DEBUG */ + Snooze(true); + // Set self as last action of constructor, to indicate that object is fully constructed. + self = this; + } + template<typename Tag> + void operator()( const Range& r, Tag /*tag*/ ) { + Snooze(true); +#if PRINT_DEBUG + if( my_range.empty() ) + REPORT("%d computing %s [%ld..%ld)\n",id,Tag::is_final_scan()?"final":"lookahead",r.begin(),r.end() ); + else + REPORT("%d computing %s [%ld..%ld) [%ld..%ld)\n",id,Tag::is_final_scan()?"final":"lookahead",my_range.begin(),my_range.end(),r.begin(),r.end()); +#endif /* PRINT_DEBUG */ + ASSERT( !Tag::is_final_scan() || (my_range.begin()==0 && my_range.end()==r.begin()) || (my_range.empty() && r.begin()==0), NULL ); + for( long i=r.begin(); i<r.end(); ++i ) { + my_total += my_array[i]; + if( Tag::is_final_scan() ) { + ASSERT( AddendHistory[i]<USED_FINAL, "addend used 'finally' twice?" ); + AddendHistory[i] |= USED_FINAL; + my_sum[i] = my_total; + VerifySum( 0L, i, int(my_sum[i]), __LINE__ ); + } else { + ASSERT( AddendHistory[i]==UNUSED, "addend used too many times" ); + AddendHistory[i] |= USED_NONFINAL; + } + } + if( my_range.empty() ) + my_range = r; + else + my_range = Range(my_range.begin(), r.end(), 1 ); + Snooze(true); + ASSERT( self==this, "this Accumulator corrupted or prematurely destroyed" ); + } + void reverse_join( const Accumulator& left ) { +#if PRINT_DEBUG + REPORT("reverse join %d [%ld..%ld) %d [%ld..%ld)\n", + left.id,left.my_range.begin(),left.my_range.end(), + id,my_range.begin(),my_range.end()); +#endif /* PRINT_DEBUG */ + Snooze(true); + ASSERT( ScanIsRunning, NULL ); + ASSERT( left.my_range.end()==my_range.begin(), NULL ); + my_total += left.my_total; + my_range = Range( left.my_range.begin(), my_range.end(), 1 ); + ASSERT( ScanIsRunning, NULL ); + Snooze(true); + ASSERT( ScanIsRunning, NULL ); + ASSERT( self==this, NULL ); + ASSERT( left.self==&left, NULL ); + } + void assign( const Accumulator& other ) { + my_total = other.my_total; + my_range = other.my_range; + ASSERT( self==this, NULL ); + ASSERT( other.self==&other, "other Accumulator corrupted or prematurely destroyed" ); + } +}; + +#include "tbb/tick_count.h" +#include "harness.h" + +static void VerifySum( long start_index, long finish_index, int sum, int line ) { + int expected = TriangularSum( finish_index ) - TriangularSum( start_index ); + if( expected!=sum ) { + REPORT( "line %d: sum[%ld..%ld] should be = %d, but was computed as %d\n", + line, start_index, finish_index, expected, sum ); + abort(); + } +} + +void TestAccumulator( int mode, int nthread ) { + typedef int T; + T* addend = new T[MAXN]; + T* sum = new T[MAXN]; + for( long n=0; n<=MAXN; ++n ) { + for( long i=0; i<MAXN; ++i ) { + addend[i] = -1; + sum[i] = -2; + AddendHistory[i] = UNUSED; + } + for( long i=0; i<n; ++i ) + addend[i] = i; + Accumulator<T> acc( addend, sum ); + tbb::tick_count t0 = tbb::tick_count::now(); +#if PRINT_DEBUG + REPORT("--------- mode=%d range=[0..%ld)\n",mode,n); +#endif /* PRINT_DEBUG */ + ScanIsRunning = true; + + switch (mode) { + case 0: + tbb::parallel_scan( Range( 0, n, 1 ), acc ); + break; + case 1: + tbb::parallel_scan( Range( 0, n, 1 ), acc, tbb::simple_partitioner() ); + break; + case 2: + tbb::parallel_scan( Range( 0, n, 1 ), acc, tbb::auto_partitioner() ); + break; + } + + ScanIsRunning = false; +#if PRINT_DEBUG + REPORT("=========\n"); +#endif /* PRINT_DEBUG */ + Snooze(false); + tbb::tick_count t1 = tbb::tick_count::now(); + long used_once_count = 0; + for( long i=0; i<n; ++i ) + if( !(AddendHistory[i]&USED_FINAL) ) { + REPORT("failed to use addend[%ld] %s\n",i,AddendHistory[i]&USED_NONFINAL?"(but used nonfinal)":""); + } + for( long i=0; i<n; ++i ) { + VerifySum( 0, i, sum[i], __LINE__ ); + used_once_count += AddendHistory[i]==USED_FINAL; + } + if( n ) + ASSERT( acc.my_total==sum[n-1], NULL ); + else + ASSERT( acc.my_total==0, NULL ); + REMARK("time [n=%ld] = %g\tused_once%% = %g\tnthread=%d\n",n,(t1-t0).seconds(), n==0 ? 0 : 100.0*used_once_count/n,nthread); + } + delete[] addend; + delete[] sum; +} + +static void TestScanTags() { + ASSERT( tbb::pre_scan_tag::is_final_scan()==false, NULL ); + ASSERT( tbb::final_scan_tag::is_final_scan()==true, NULL ); +} + +#include "tbb/task_scheduler_init.h" +#include "harness_cpu.h" + +int TestMain () { + TestScanTags(); + for( int p=MinThread; p<=MaxThread; ++p ) { + for (int mode = 0; mode < 3; mode++) { + tbb::task_scheduler_init init(p); + NumberOfLiveAccumulator = 0; + TestAccumulator(mode, p); + + // Test that all workers sleep when no work + TestCPUUserTime(p); + + // Checking has to be done late, because when parallel_scan makes copies of + // the user's "Body", the copies might be destroyed slightly after parallel_scan + // returns. + ASSERT( NumberOfLiveAccumulator==0, NULL ); + } + } + return Harness::Done; +} diff --git a/src/tbb/src/test/test_parallel_sort.cpp b/src/tbb/src/test/test_parallel_sort.cpp new file mode 100644 index 0000000..709bb02 --- /dev/null +++ b/src/tbb/src/test/test_parallel_sort.cpp @@ -0,0 +1,531 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/parallel_sort.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/concurrent_vector.h" +#include "harness.h" +#include <math.h> +#include <exception> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include <algorithm> +#include <iterator> +#include <functional> +#include <string> +#include <cstring> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +/** Has tightly controlled interface so that we can verify + that parallel_sort uses only the required interface. */ +class Minimal { + int val; +public: + Minimal() {} + void set_val(int i) { val = i; } + static bool CompareWith (const Minimal &a, const Minimal &b) { + return (a.val < b.val); + } + static bool AreEqual( Minimal &a, Minimal &b) { + return a.val == b.val; + } +}; + +//! Defines a comparison function object for Minimal +class MinimalCompare { +public: + bool operator() (const Minimal &a, const Minimal &b) const { + return Minimal::CompareWith(a,b); + } +}; + +//! The default validate; but it uses operator== which is not required +template<typename RandomAccessIterator> +bool Validate(RandomAccessIterator a, RandomAccessIterator b, size_t n) { + for (size_t i = 0; i < n; i++) { + ASSERT( a[i] == b[i], NULL ); + } + return true; +} + +//! A Validate specialized to string for debugging-only +template<> +bool Validate<std::string *>(std::string * a, std::string * b, size_t n) { + for (size_t i = 0; i < n; i++) { + if ( Verbose && a[i] != b[i]) { + for (size_t j = 0; j < n; j++) { + REPORT("a[%llu] == %s and b[%llu] == %s\n", static_cast<unsigned long long>(j), a[j].c_str(), static_cast<unsigned long long>(j), b[j].c_str()); + } + } + ASSERT( a[i] == b[i], NULL ); + } + return true; +} + +//! A Validate specialized to Minimal since it does not define an operator== +template<> +bool Validate<Minimal *>(Minimal *a, Minimal *b, size_t n) { + for (size_t i = 0; i < n; i++) { + ASSERT( Minimal::AreEqual(a[i],b[i]), NULL ); + } + return true; +} + +//! A Validate specialized to concurrent_vector<Minimal> since it does not define an operator== +template<> +bool Validate<tbb::concurrent_vector<Minimal>::iterator>(tbb::concurrent_vector<Minimal>::iterator a, + tbb::concurrent_vector<Minimal>::iterator b, size_t n) { + for (size_t i = 0; i < n; i++) { + ASSERT( Minimal::AreEqual(a[i],b[i]), NULL ); + } + return true; +} + +//! used in Verbose mode for identifying which data set is being used +static std::string test_type; + +//! The default initialization routine. +/*! This routine assumes that you can assign to the elements from a float. + It assumes that iter and sorted_list have already been allocated. It fills + them according to the current data set (tracked by a local static variable). + Returns true if a valid test has been setup, or false if there is no test to + perform. +*/ + +template < typename RandomAccessIterator, typename Compare > +bool init_iter(RandomAccessIterator iter, RandomAccessIterator sorted_list, size_t n, const Compare &compare, bool reset) { + static char test_case = 0; + const char num_cases = 3; + + if (reset) test_case = 0; + + if (test_case < num_cases) { + // switch on the current test case, filling the iter and sorted_list appropriately + switch(test_case) { + case 0: + /* use sin to generate the values */ + test_type = "sin"; + for (size_t i = 0; i < n; i++) + iter[i] = sorted_list[i] = static_cast<typename std::iterator_traits< RandomAccessIterator >::value_type>(sin(float(i))); + break; + case 1: + /* presorted list */ + test_type = "pre-sorted"; + for (size_t i = 0; i < n; i++) + iter[i] = sorted_list[i] = static_cast<typename std::iterator_traits< RandomAccessIterator >::value_type>(i); + break; + case 2: + /* reverse-sorted list */ + test_type = "reverse-sorted"; + for (size_t i = 0; i < n; i++) + iter[i] = sorted_list[i] = static_cast<typename std::iterator_traits< RandomAccessIterator >::value_type>(n - i); + break; + } + + // pre-sort sorted_list for later validity testing + std::sort(sorted_list, sorted_list + n, compare); + test_case++; + return true; + } + return false; +} + +template < typename T, typename Compare > +bool init_iter(T * iter, T * sorted_list, size_t n, const Compare &compare, bool reset) { + static char test_case = 0; + const char num_cases = 3; + + if (reset) test_case = 0; + + if (test_case < num_cases) { + // switch on the current test case, filling the iter and sorted_list appropriately + switch(test_case) { + case 0: + /* use sin to generate the values */ + test_type = "sin"; + for (size_t i = 0; i < n; i++) + iter[i] = sorted_list[i] = T(sin(float(i))); + break; + case 1: + /* presorted list */ + test_type = "pre-sorted"; + for (size_t i = 0; i < n; i++) + iter[i] = sorted_list[i] = T(i); + break; + case 2: + /* reverse-sorted list */ + test_type = "reverse-sorted"; + for (size_t i = 0; i < n; i++) + iter[i] = sorted_list[i] = T(n - i); + break; + } + + // pre-sort sorted_list for later validity testing + std::sort(sorted_list, sorted_list + n, compare); + test_case++; + return true; + } + return false; +} + + +//! The initialization routine specialized to the class Minimal +/*! Minimal cannot have floats assigned to it. This function uses the set_val method +*/ + +template < > +bool init_iter(Minimal* iter, Minimal * sorted_list, size_t n, const MinimalCompare &compare, bool reset) { + static char test_case = 0; + const char num_cases = 3; + + if (reset) test_case = 0; + + if (test_case < num_cases) { + switch(test_case) { + case 0: + /* use sin to generate the values */ + test_type = "sin"; + for (size_t i = 0; i < n; i++) { + iter[i].set_val( int( sin( float(i) ) * 1000.f) ); + sorted_list[i].set_val( int ( sin( float(i) ) * 1000.f) ); + } + break; + case 1: + /* presorted list */ + test_type = "pre-sorted"; + for (size_t i = 0; i < n; i++) { + iter[i].set_val( int(i) ); + sorted_list[i].set_val( int(i) ); + } + break; + case 2: + /* reverse-sorted list */ + test_type = "reverse-sorted"; + for (size_t i = 0; i < n; i++) { + iter[i].set_val( int(n-i) ); + sorted_list[i].set_val( int(n-i) ); + } + break; + } + std::sort(sorted_list, sorted_list + n, compare); + test_case++; + return true; + } + return false; +} + +//! The initialization routine specialized to the class concurrent_vector<Minimal> +/*! Minimal cannot have floats assigned to it. This function uses the set_val method +*/ + +template < > +bool init_iter(tbb::concurrent_vector<Minimal>::iterator iter, tbb::concurrent_vector<Minimal>::iterator sorted_list, + size_t n, const MinimalCompare &compare, bool reset) { + static char test_case = 0; + const char num_cases = 3; + + if (reset) test_case = 0; + + if (test_case < num_cases) { + switch(test_case) { + case 0: + /* use sin to generate the values */ + test_type = "sin"; + for (size_t i = 0; i < n; i++) { + iter[i].set_val( int( sin( float(i) ) * 1000.f) ); + sorted_list[i].set_val( int ( sin( float(i) ) * 1000.f) ); + } + break; + case 1: + /* presorted list */ + test_type = "pre-sorted"; + for (size_t i = 0; i < n; i++) { + iter[i].set_val( int(i) ); + sorted_list[i].set_val( int(i) ); + } + break; + case 2: + /* reverse-sorted list */ + test_type = "reverse-sorted"; + for (size_t i = 0; i < n; i++) { + iter[i].set_val( int(n-i) ); + sorted_list[i].set_val( int(n-i) ); + } + break; + } + std::sort(sorted_list, sorted_list + n, compare); + test_case++; + return true; + } + return false; +} + +//! The initialization routine specialized to the class string +/*! strings are created from floats. +*/ + +template<> +bool init_iter(std::string *iter, std::string *sorted_list, size_t n, const std::less<std::string> &compare, bool reset) { + static char test_case = 0; + const char num_cases = 1; + + if (reset) test_case = 0; + + if (test_case < num_cases) { + switch(test_case) { + case 0: + /* use sin to generate the values */ + test_type = "sin"; + for (size_t i = 0; i < n; i++) { + char buffer[20]; +// Getting rid of secure warning issued by C++ 14.00 and newer +// sprintf_s is not defined in msvcrt.dll in windows XP and windows 2003 (used by MinGW gcc 4.5.2 with default spec) +#if __STDC_SECURE_LIB__>=200411 && !__MINGW64__ + sprintf_s(buffer, sizeof(buffer), "%f", float(sin(float(i)))); +#else + sprintf(buffer, "%f", float(sin(float(i)))); +#endif /* __STDC_SECURE_LIB__>=200411 || && !__MINGW64__ */ + sorted_list[i] = iter[i] = std::string(buffer); + } + break; + } + std::sort(sorted_list, sorted_list + n, compare); + test_case++; + return true; + } + return false; +} + +//! The current number of threads in use (for Verbose only) +static size_t current_p; + +//! The current data type being sorted (for Verbose only) +static std::string current_type; + +//! The default test routine. +/*! Tests all data set sizes from 0 to N, all grainsizes from 0 to G=10, and selects from + all possible interfaces to parallel_sort depending on whether a scratch space and + compare have been provided. +*/ +template<typename RandomAccessIterator, typename Compare> +bool parallel_sortTest(size_t n, RandomAccessIterator iter, RandomAccessIterator sorted_list, const Compare *comp) { + bool passed = true; + + Compare local_comp; + + init_iter(iter, sorted_list, n, local_comp, true); + do { + REMARK("%s %s p=%llu n=%llu :",current_type.c_str(), test_type.c_str(), + static_cast<unsigned long long>(current_p), static_cast<unsigned long long>(n)); + if (comp != NULL) { + tbb::parallel_sort(iter, iter + n, local_comp ); + } else { + tbb::parallel_sort(iter, iter + n ); + } + if (!Validate(iter, sorted_list, n)) + passed = false; + REMARK("passed\n"); + } while (init_iter(iter, sorted_list, n, local_comp, false)); + return passed; +} + +//! The test routine specialize to Minimal, since it does not have a less defined for it +template<> +bool parallel_sortTest(size_t n, Minimal * iter, Minimal * sorted_list, const MinimalCompare *compare) { + bool passed = true; + + if (compare == NULL) return passed; + + init_iter(iter, sorted_list, n, *compare, true); + do { + REMARK("%s %s p=%llu n=%llu :",current_type.c_str(), test_type.c_str(), + static_cast<unsigned long long>(current_p), static_cast<unsigned long long>(n)); + + tbb::parallel_sort(iter, iter + n, *compare ); + + if (!Validate(iter, sorted_list, n)) + passed = false; + REMARK("passed\n"); + } while (init_iter(iter, sorted_list, n, *compare, false)); + return passed; +} + +//! The test routine specialize to concurrent_vector of Minimal, since it does not have a less defined for it +template<> +bool parallel_sortTest(size_t n, tbb::concurrent_vector<Minimal>::iterator iter, + tbb::concurrent_vector<Minimal>::iterator sorted_list, const MinimalCompare *compare) { + bool passed = true; + + if (compare == NULL) return passed; + + init_iter(iter, sorted_list, n, *compare, true); + do { + REMARK("%s %s p=%llu n=%llu :",current_type.c_str(), test_type.c_str(), + static_cast<unsigned long long>(current_p), static_cast<unsigned long long>(n)); + + tbb::parallel_sort(iter, iter + n, *compare ); + + if (!Validate(iter, sorted_list, n)) + passed = false; + REMARK("passed\n"); + } while (init_iter(iter, sorted_list, n, *compare, false)); + return passed; +} + +//! The main driver for the tests. +/*! Minimal, float and string types are used. All interfaces to parallel_sort that are usable + by each type are tested. +*/ +void Flog() { + // For each type create: + // the list to be sorted by parallel_sort (array) + // the list to be sort by STL sort (array_2) + // and a less function object + + const size_t N = 50000; + + Minimal *minimal_array = new Minimal[N]; + Minimal *minimal_array_2 = new Minimal[N]; + MinimalCompare minimal_less; + + float *float_array = new float[N]; + float *float_array_2 = new float[N]; + std::less<float> float_less; + + tbb::concurrent_vector<float> float_cv1; + tbb::concurrent_vector<float> float_cv2; + float_cv1.grow_to_at_least(N); + float_cv2.grow_to_at_least(N); + + std::string *string_array = new std::string[N]; + std::string *string_array_2 = new std::string[N]; + std::less<std::string> string_less; + + tbb::concurrent_vector<Minimal> minimal_cv1; + tbb::concurrent_vector<Minimal> minimal_cv2; + minimal_cv1.grow_to_at_least(N); + minimal_cv2.grow_to_at_least(N); + + + // run the appropriate tests for each type + + current_type = "Minimal(less)"; + parallel_sortTest(0, minimal_array, minimal_array_2, &minimal_less); + parallel_sortTest(1, minimal_array, minimal_array_2, &minimal_less); + parallel_sortTest(10, minimal_array, minimal_array_2, &minimal_less); + parallel_sortTest(9999, minimal_array, minimal_array_2, &minimal_less); + parallel_sortTest(50000, minimal_array, minimal_array_2, &minimal_less); + + current_type = "float (no less)"; + parallel_sortTest(0, float_array, float_array_2, static_cast<std::less<float> *>(NULL)); + parallel_sortTest(1, float_array, float_array_2, static_cast<std::less<float> *>(NULL)); + parallel_sortTest(10, float_array, float_array_2, static_cast<std::less<float> *>(NULL)); + parallel_sortTest(9999, float_array, float_array_2, static_cast<std::less<float> *>(NULL)); + parallel_sortTest(50000, float_array, float_array_2, static_cast<std::less<float> *>(NULL)); + + current_type = "float (less)"; + parallel_sortTest(0, float_array, float_array_2, &float_less); + parallel_sortTest(1, float_array, float_array_2, &float_less); + parallel_sortTest(10, float_array, float_array_2, &float_less); + parallel_sortTest(9999, float_array, float_array_2, &float_less); + parallel_sortTest(50000, float_array, float_array_2, &float_less); + + current_type = "concurrent_vector<float> (no less)"; + parallel_sortTest(0, float_cv1.begin(), float_cv2.begin(), static_cast<std::less<float> *>(NULL)); + parallel_sortTest(1, float_cv1.begin(), float_cv2.begin(), static_cast<std::less<float> *>(NULL)); + parallel_sortTest(10, float_cv1.begin(), float_cv2.begin(), static_cast<std::less<float> *>(NULL)); + parallel_sortTest(9999, float_cv1.begin(), float_cv2.begin(), static_cast<std::less<float> *>(NULL)); + parallel_sortTest(50000, float_cv1.begin(), float_cv2.begin(), static_cast<std::less<float> *>(NULL)); + + current_type = "concurrent_vector<float> (less)"; + parallel_sortTest(0, float_cv1.begin(), float_cv2.begin(), &float_less); + parallel_sortTest(1, float_cv1.begin(), float_cv2.begin(), &float_less); + parallel_sortTest(10, float_cv1.begin(), float_cv2.begin(), &float_less); + parallel_sortTest(9999, float_cv1.begin(), float_cv2.begin(), &float_less); + parallel_sortTest(50000, float_cv1.begin(), float_cv2.begin(), &float_less); + + current_type = "string (no less)"; + parallel_sortTest(0, string_array, string_array_2, static_cast<std::less<std::string> *>(NULL)); + parallel_sortTest(1, string_array, string_array_2, static_cast<std::less<std::string> *>(NULL)); + parallel_sortTest(10, string_array, string_array_2, static_cast<std::less<std::string> *>(NULL)); + parallel_sortTest(9999, string_array, string_array_2, static_cast<std::less<std::string> *>(NULL)); + parallel_sortTest(50000, string_array, string_array_2, static_cast<std::less<std::string> *>(NULL)); + + current_type = "string (less)"; + parallel_sortTest(0, string_array, string_array_2, &string_less); + parallel_sortTest(1, string_array, string_array_2, &string_less); + parallel_sortTest(10, string_array, string_array_2, &string_less); + parallel_sortTest(9999, string_array, string_array_2, &string_less); + parallel_sortTest(50000, string_array, string_array_2, &string_less); + + current_type = "concurrent_vector<Minimal> (less)"; + parallel_sortTest(0, minimal_cv1.begin(), minimal_cv2.begin(), &minimal_less); + parallel_sortTest(1, minimal_cv1.begin(), minimal_cv2.begin(), &minimal_less); + parallel_sortTest(10, minimal_cv1.begin(), minimal_cv2.begin(), &minimal_less); + parallel_sortTest(9999, minimal_cv1.begin(), minimal_cv2.begin(), &minimal_less); + parallel_sortTest(50000, minimal_cv1.begin(), minimal_cv2.begin(), &minimal_less); + + delete [] minimal_array; + delete [] minimal_array_2; + + delete [] float_array; + delete [] float_array_2; + + delete [] string_array; + delete [] string_array_2; +} + +#include <cstdio> +#include "harness_cpu.h" + +int TestMain () { + if( MinThread<1 ) { + REPORT("Usage: number of threads must be positive\n"); + exit(1); + } + for( int p=MinThread; p<=MaxThread; ++p ) { + if( p>0 ) { + tbb::task_scheduler_init init( p ); + current_p = p; + Flog(); + + // Test that all workers sleep when no work + TestCPUUserTime(p); + } + } + return Harness::Done; +} + diff --git a/src/tbb/src/test/test_parallel_while.cpp b/src/tbb/src/test/test_parallel_while.cpp new file mode 100644 index 0000000..1fe5790 --- /dev/null +++ b/src/tbb/src/test/test_parallel_while.cpp @@ -0,0 +1,179 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/parallel_while.h" +#include "harness.h" + +const int N = 200; + +typedef int Element; + +//! Representation of an array index with only those signatures required by parallel_while. +class MinimalArgumentType { + void operator=( const MinimalArgumentType& ); + long my_value; + enum { + DEAD=0xDEAD, + LIVE=0x2718, + INITIALIZED=0x3141 + } my_state; +public: + ~MinimalArgumentType() { + ASSERT( my_state==LIVE||my_state==INITIALIZED, NULL ); + my_state = DEAD; + } + MinimalArgumentType() { + my_state = LIVE; + } + void set_value( long i ) { + ASSERT( my_state==LIVE||my_state==INITIALIZED, NULL ); + my_value = i; + my_state = INITIALIZED; + } + long get_value() const { + ASSERT( my_state==INITIALIZED, NULL ); + return my_value; + } +}; + +class IntegerStream { + long my_limit; + long my_index; +public: + IntegerStream( long n ) : my_limit(n), my_index(0) {} + bool pop_if_present( MinimalArgumentType& v ) { + if( my_index>=my_limit ) + return false; + v.set_value( my_index ); + my_index+=2; + return true; + } +}; + +class MatrixMultiplyBody: NoAssign { + Element (*a)[N]; + Element (*b)[N]; + Element (*c)[N]; + const int n; + tbb::parallel_while<MatrixMultiplyBody>& my_while; +public: + typedef MinimalArgumentType argument_type; + void operator()( argument_type i_arg ) const { + long i = i_arg.get_value(); + if( (i&1)==0 && i+1<N ) { + MinimalArgumentType value; + value.set_value(i+1); + my_while.add( value ); + } + for( int j=0; j<n; ++j ) + c[i][j] = 0; + for( int k=0; k<n; ++k ) { + Element aik = a[i][k]; + for( int j=0; j<n; ++j ) + c[i][j] += aik*b[k][j]; + } + } + MatrixMultiplyBody( tbb::parallel_while<MatrixMultiplyBody>& w, Element c_[N][N], Element a_[N][N], Element b_[N][N], int n_ ) : + a(a_), b(b_), c(c_), n(n_), my_while(w) + {} +}; + +void WhileMatrixMultiply( Element c[N][N], Element a[N][N], Element b[N][N], int n ) { + IntegerStream stream( N ); + tbb::parallel_while<MatrixMultiplyBody> w; + MatrixMultiplyBody body(w,c,a,b,n); + w.run( stream, body ); +} + +#include "tbb/tick_count.h" +#include <cstdlib> +#include <cstdio> +using namespace std; + +static long Iterations = 5; + +static void SerialMatrixMultiply( Element c[N][N], Element a[N][N], Element b[N][N], int n ) { + for( int i=0; i<n; ++i ) { + for( int j=0; j<n; ++j ) + c[i][j] = 0; + for( int k=0; k<n; ++k ) { + Element aik = a[i][k]; + for( int j=0; j<n; ++j ) + c[i][j] += aik*b[k][j]; + } + } +} + +static void InitializeMatrix( Element x[N][N], int n, int salt ) { + for( int i=0; i<n; ++i ) + for( int j=0; j<n; ++j ) + x[i][j] = (i*n+j)^salt; +} + +static Element A[N][N], B[N][N], C[N][N], D[N][N]; + +static void Run( int nthread, int n ) { + /* Initialize matrices */ + InitializeMatrix(A,n,5); + InitializeMatrix(B,n,10); + InitializeMatrix(C,n,0); + InitializeMatrix(D,n,15); + + tbb::tick_count t0 = tbb::tick_count::now(); + for( long i=0; i<Iterations; ++i ) { + WhileMatrixMultiply( C, A, B, n ); + } + tbb::tick_count t1 = tbb::tick_count::now(); + SerialMatrixMultiply( D, A, B, n ); + + // Check result + for( int i=0; i<n; ++i ) + for( int j=0; j<n; ++j ) + ASSERT( C[i][j]==D[i][j], NULL ); + REMARK("time=%g\tnthread=%d\tn=%d\n",(t1-t0).seconds(),nthread,n); +} + +#include "tbb/task_scheduler_init.h" +#include "harness_cpu.h" + +int TestMain () { + if( MinThread<1 ) { + REPORT("number of threads must be positive\n"); + exit(1); + } + for( int p=MinThread; p<=MaxThread; ++p ) { + tbb::task_scheduler_init init( p ); + for( int n=N/4; n<=N; n+=N/4 ) + Run(p,n); + + // Test that all workers sleep when no work + TestCPUUserTime(p); + } + return Harness::Done; +} + diff --git a/src/tbb/src/test/test_pipeline.cpp b/src/tbb/src/test/test_pipeline.cpp new file mode 100644 index 0000000..974d490 --- /dev/null +++ b/src/tbb/src/test/test_pipeline.cpp @@ -0,0 +1,321 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/tbb_stddef.h" +#include "tbb/pipeline.h" +#include "tbb/spin_mutex.h" +#include "tbb/atomic.h" +#include <cstdlib> +#include <cstdio> +#include "harness.h" + +// In the test, variables related to token counting are declared +// as unsigned long to match definition of tbb::internal::Token. + +struct Buffer { + //! Indicates that the buffer is not used. + static const unsigned long unused = ~0ul; + unsigned long id; + //! True if Buffer is in use. + bool is_busy; + unsigned long sequence_number; + Buffer() : id(unused), is_busy(false), sequence_number(unused) {} +}; + +class waiting_probe { + size_t check_counter; +public: + waiting_probe() : check_counter(0) {} + bool required( ) { + ++check_counter; + return !((check_counter+1)&size_t(0x7FFF)); + } + void probe( ); // defined below +}; + +static const unsigned MaxStreamSize = 8000; +static const unsigned MaxStreamItemsPerThread = 1000; +//! Maximum number of filters allowed +static const unsigned MaxFilters = 5; +static unsigned StreamSize; +static const unsigned MaxBuffer = 8; +static bool Done[MaxFilters][MaxStreamSize]; +static waiting_probe WaitTest; +static unsigned out_of_order_count; + +#include "harness_concurrency_tracker.h" + +class BaseFilter: public tbb::filter { + bool* const my_done; + const bool my_is_last; + bool my_is_running; +public: + tbb::atomic<tbb::internal::Token> current_token; + BaseFilter( tbb::filter::mode type, bool done[], bool is_last ) : + filter(type), + my_done(done), + my_is_last(is_last), + my_is_running(false), + current_token() + {} + virtual Buffer* get_buffer( void* item ) { + current_token++; + return static_cast<Buffer*>(item); + } + /*override*/void* operator()( void* item ) { + Harness::ConcurrencyTracker ct; + if( is_serial() ) + ASSERT( !my_is_running, "premature entry to serial stage" ); + my_is_running = true; + Buffer* b = get_buffer(item); + if( b ) { + if( is_ordered() ) { + if( b->sequence_number == Buffer::unused ) + b->sequence_number = current_token-1; + else + ASSERT( b->sequence_number==current_token-1, "item arrived out of order" ); + } else if( is_serial() ) { + if( b->sequence_number != current_token-1 && b->sequence_number != Buffer::unused ) + out_of_order_count++; + } + ASSERT( b->id < StreamSize, NULL ); + ASSERT( !my_done[b->id], "duplicate processing of token?" ); + ASSERT( b->is_busy, NULL ); + my_done[b->id] = true; + if( my_is_last ) { + b->id = Buffer::unused; + b->sequence_number = Buffer::unused; + __TBB_store_with_release(b->is_busy, false); + } + } + my_is_running = false; + return b; + } +}; + +class InputFilter: public BaseFilter { + tbb::spin_mutex input_lock; + Buffer buffer[MaxBuffer]; + const tbb::internal::Token my_number_of_tokens; +public: + InputFilter( tbb::filter::mode type, tbb::internal::Token ntokens, bool done[], bool is_last ) : + BaseFilter(type, done, is_last), + my_number_of_tokens(ntokens) + {} + /*override*/Buffer* get_buffer( void* ) { + unsigned long next_input; + unsigned free_buffer = 0; + { // lock protected scope + tbb::spin_mutex::scoped_lock lock(input_lock); + if( current_token>=StreamSize ) + return NULL; + next_input = current_token++; + // once in a while, emulate waiting for input; this only makes sense for serial input + if( is_serial() && WaitTest.required() ) + WaitTest.probe( ); + while( free_buffer<MaxBuffer ) + if( __TBB_load_with_acquire(buffer[free_buffer].is_busy) ) + ++free_buffer; + else { + buffer[free_buffer].is_busy = true; + break; + } + } + ASSERT( free_buffer<my_number_of_tokens, "premature reuse of buffer" ); + Buffer* b = &buffer[free_buffer]; + ASSERT( &buffer[0] <= b, NULL ); + ASSERT( b <= &buffer[MaxBuffer-1], NULL ); + ASSERT( b->id == Buffer::unused, NULL); + b->id = next_input; + ASSERT( b->sequence_number == Buffer::unused, NULL); + return b; + } +}; + +//! The struct below repeats layout of tbb::pipeline. +struct hacked_pipeline { + tbb::filter* filter_list; + tbb::filter* filter_end; + tbb::empty_task* end_counter; + tbb::atomic<tbb::internal::Token> input_tokens; + tbb::atomic<tbb::internal::Token> token_counter; + bool end_of_input; + bool has_thread_bound_filters; + + virtual ~hacked_pipeline(); +}; + +//! The struct below repeats layout of tbb::internal::input_buffer. +struct hacked_input_buffer { + void* array; // This should be changed to task_info* if ever used + void* my_sem; // This should be changed to semaphore* if ever used + tbb::internal::Token array_size; + tbb::internal::Token low_token; + tbb::spin_mutex array_mutex; + tbb::internal::Token high_token; + bool is_ordered; + bool is_bound; +}; + +//! The struct below repeats layout of tbb::filter. +struct hacked_filter { + tbb::filter* next_filter_in_pipeline; + hacked_input_buffer* my_input_buffer; + unsigned char my_filter_mode; + tbb::filter* prev_filter_in_pipeline; + tbb::pipeline* my_pipeline; + tbb::filter* next_segment; + + virtual ~hacked_filter(); +}; + +bool do_hacking_tests = true; +const tbb::internal::Token tokens_before_wraparound = 0xF; + +void TestTrivialPipeline( unsigned nthread, unsigned number_of_filters ) { + // There are 3 filter types: parallel, serial_in_order and serial_out_of_order + static const tbb::filter::mode filter_table[] = { tbb::filter::parallel, tbb::filter::serial_in_order, tbb::filter::serial_out_of_order}; + const unsigned number_of_filter_types = sizeof(filter_table)/sizeof(filter_table[0]); + REMARK( "testing with %lu threads and %lu filters\n", nthread, number_of_filters ); + ASSERT( number_of_filters<=MaxFilters, "too many filters" ); + ASSERT( sizeof(hacked_pipeline) == sizeof(tbb::pipeline), "layout changed for tbb::pipeline?" ); + ASSERT( sizeof(hacked_filter) == sizeof(tbb::filter), "layout changed for tbb::filter?" ); + tbb::internal::Token ntokens = nthread<MaxBuffer ? nthread : MaxBuffer; + // Count maximum iterations number + unsigned limit = 1; + for( unsigned i=0; i<number_of_filters; ++i) + limit *= number_of_filter_types; + // Iterate over possible filter sequences + for( unsigned numeral=0; numeral<limit; ++numeral ) { + // Build pipeline + tbb::pipeline pipeline; + if( do_hacking_tests ) { + // A private member of pipeline is hacked there for sake of testing wrap-around immunity. + tbb::internal::punned_cast<hacked_pipeline*>(&pipeline)->token_counter = ~tokens_before_wraparound; + } + tbb::filter* filter[MaxFilters]; + unsigned temp = numeral; + // parallelism_limit is the upper bound on the possible parallelism + unsigned parallelism_limit = 0; + for( unsigned i=0; i<number_of_filters; ++i, temp/=number_of_filter_types ) { + tbb::filter::mode filter_type = filter_table[temp%number_of_filter_types]; + const bool is_last = i==number_of_filters-1; + if( i==0 ) + filter[i] = new InputFilter(filter_type,ntokens,Done[i],is_last); + else + filter[i] = new BaseFilter(filter_type,Done[i],is_last); + pipeline.add_filter(*filter[i]); + // The ordered buffer of serial filters is hacked as well. + if ( filter[i]->is_serial() ) { + if( do_hacking_tests ) { + ((hacked_filter*)(void*)filter[i])->my_input_buffer->low_token = ~tokens_before_wraparound; + ((hacked_filter*)(void*)filter[i])->my_input_buffer->high_token = ~tokens_before_wraparound; + } + parallelism_limit += 1; + } else { + parallelism_limit = nthread; + } + } + // Account for clipping of parallelism. + if( parallelism_limit>nthread ) + parallelism_limit = nthread; + if( parallelism_limit>ntokens ) + parallelism_limit = (unsigned)ntokens; + Harness::ConcurrencyTracker::Reset(); + unsigned streamSizeLimit = min( MaxStreamSize, nthread * MaxStreamItemsPerThread ); + for( StreamSize=0; StreamSize<=streamSizeLimit; ) { + memset( Done, 0, sizeof(Done) ); + for( unsigned i=0; i<number_of_filters; ++i ) { + static_cast<BaseFilter*>(filter[i])->current_token=0; + } + pipeline.run( ntokens ); + ASSERT( !Harness::ConcurrencyTracker::InstantParallelism(), "filter still running?" ); + for( unsigned i=0; i<number_of_filters; ++i ) + ASSERT( static_cast<BaseFilter*>(filter[i])->current_token==StreamSize, NULL ); + for( unsigned i=0; i<MaxFilters; ++i ) + for( unsigned j=0; j<StreamSize; ++j ) { + ASSERT( Done[i][j]==(i<number_of_filters), NULL ); + } + if( StreamSize < min(nthread*8, 32u) ) { + ++StreamSize; + } else { + StreamSize = StreamSize*8/3; + } + } + if( Harness::ConcurrencyTracker::PeakParallelism() < parallelism_limit ) + REMARK( "nthread=%lu ntokens=%lu MaxParallelism=%lu parallelism_limit=%lu\n", + nthread, ntokens, Harness::ConcurrencyTracker::PeakParallelism(), parallelism_limit ); + for( unsigned i=0; i < number_of_filters; ++i ) { + delete filter[i]; + filter[i] = NULL; + } + pipeline.clear(); + } +} + +#include "harness_cpu.h" + +static int nthread; // knowing number of threads is necessary to call TestCPUUserTime + +void waiting_probe::probe( ) { + if( nthread==1 ) return; + REMARK("emulating wait for input\n"); + // Test that threads sleep while no work. + // The master doesn't sleep so there could be 2 active threads if a worker is waiting for input + TestCPUUserTime(nthread, 2); +} + +#include "tbb/task_scheduler_init.h" + +int TestMain () { + out_of_order_count = 0; + if( MinThread<1 ) { + REPORT("must have at least one thread"); + exit(1); + } + if( tbb::TBB_runtime_interface_version()>TBB_INTERFACE_VERSION) { + REMARK("Warning: implementation dependent tests disabled\n"); + do_hacking_tests = false; + } + + // Test with varying number of threads. + for( nthread=MinThread; nthread<=MaxThread; ++nthread ) { + // Initialize TBB task scheduler + tbb::task_scheduler_init init(nthread); + + // Test pipelines with n filters + for( unsigned n=0; n<=MaxFilters; ++n ) + TestTrivialPipeline(nthread,n); + + // Test that all workers sleep when no work + TestCPUUserTime(nthread); + } + if( !out_of_order_count ) + REPORT("Warning: out of order serial filter received tokens in order\n"); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_pipeline_with_tbf.cpp b/src/tbb/src/test/test_pipeline_with_tbf.cpp new file mode 100644 index 0000000..3e45cc3 --- /dev/null +++ b/src/tbb/src/test/test_pipeline_with_tbf.cpp @@ -0,0 +1,493 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/pipeline.h" +#include "tbb/spin_mutex.h" +#include "tbb/atomic.h" +#include "tbb/tbb_thread.h" +#include <cstdlib> +#include <cstdio> +#include "harness.h" + +// In the test, variables related to token counting are declared +// as unsigned long to match definition of tbb::internal::Token. + +//! Id of thread that first executes work on non-thread-bound stages +tbb::tbb_thread::id thread_id; +//! Zero thread id +tbb::tbb_thread::id id0; +//! True if non-thread-bound stages must be executed on one thread +bool is_serial_execution; +double sleeptime; // how long is a non-thread-bound stage to sleep? + +struct Buffer { + //! Indicates that the buffer is not used. + static const unsigned long unused = ~0ul; + unsigned long id; + //! True if Buffer is in use. + bool is_busy; + unsigned long sequence_number; + Buffer() : id(unused), is_busy(false), sequence_number(unused) {} +}; + +class waiting_probe { + size_t check_counter; +public: + waiting_probe() : check_counter(0) {} + bool required( ) { + ++check_counter; + return !((check_counter+1)&size_t(0x7FFF)); + } + void probe( ); // defined below +}; + +static const unsigned MaxStreamSize = 8000; +static const unsigned MaxStreamItemsPerThread = 1000; +//! Maximum number of filters allowed +static const unsigned MaxFilters = 4; +static unsigned StreamSize; +static const unsigned MaxBuffer = 8; +static bool Done[MaxFilters][MaxStreamSize]; +static waiting_probe WaitTest; +static unsigned out_of_order_count; + +#include "harness_concurrency_tracker.h" + +template<typename T> +class BaseFilter: public T { + bool* const my_done; + const bool my_is_last; + bool my_is_running; +public: + tbb::atomic<tbb::internal::Token> current_token; + BaseFilter( tbb::filter::mode type, bool done[], bool is_last ) : + T(type), + my_done(done), + my_is_last(is_last), + my_is_running(false), + current_token() + {} + virtual Buffer* get_buffer( void* item ) { + current_token++; + return static_cast<Buffer*>(item); + } + /*override*/void* operator()( void* item ) { + // Check if work is done only on one thread when ntokens==1 or + // when pipeline has only one filter that is serial and non-thread-bound + if( is_serial_execution && !this->is_bound() ) { + // Get id of current thread + tbb::tbb_thread::id id = tbb::this_tbb_thread::get_id(); + // At first execution, set thread_id to current thread id. + // Serialized execution is expected, so there should be no race. + if( thread_id == id0 ) + thread_id = id; + // Check if work is done on one thread + ASSERT( thread_id == id, "non-thread-bound stages executed on different threads when must be executed on a single one"); + } + Harness::ConcurrencyTracker ct; + if( this->is_serial() ) + ASSERT( !my_is_running, "premature entry to serial stage" ); + my_is_running = true; + Buffer* b = get_buffer(item); + if( b ) { + if(!this->is_bound() && sleeptime > 0) { + Harness::Sleep((int)sleeptime); + } + if( this->is_ordered() ) { + if( b->sequence_number == Buffer::unused ) + b->sequence_number = current_token-1; + else + ASSERT( b->sequence_number==current_token-1, "item arrived out of order" ); + } else if( this->is_serial() ) { + if( b->sequence_number != current_token-1 && b->sequence_number != Buffer::unused ) + out_of_order_count++; + } + ASSERT( b->id < StreamSize, NULL ); + ASSERT( !my_done[b->id], "duplicate processing of token?" ); + ASSERT( b->is_busy, NULL ); + my_done[b->id] = true; + if( my_is_last ) { + b->id = Buffer::unused; + b->sequence_number = Buffer::unused; + __TBB_store_with_release(b->is_busy, false); + } + } + my_is_running = false; + return b; + } +}; + +template<typename T> +class InputFilter: public BaseFilter<T> { + tbb::spin_mutex input_lock; + Buffer buffer[MaxBuffer]; + const tbb::internal::Token my_number_of_tokens; +public: + InputFilter( tbb::filter::mode type, tbb::internal::Token ntokens, bool done[], bool is_last ) : + BaseFilter<T>(type, done, is_last), + my_number_of_tokens(ntokens) + {} + /*override*/Buffer* get_buffer( void* ) { + unsigned long next_input; + unsigned free_buffer = 0; + { // lock protected scope + tbb::spin_mutex::scoped_lock lock(input_lock); + if( this->current_token>=StreamSize ) + return NULL; + next_input = this->current_token++; + // once in a while, emulate waiting for input; this only makes sense for serial input + if( this->is_serial() && WaitTest.required() ) + WaitTest.probe( ); + while( free_buffer<MaxBuffer ) + if( __TBB_load_with_acquire(buffer[free_buffer].is_busy) ) + ++free_buffer; + else { + buffer[free_buffer].is_busy = true; + break; + } + } + ASSERT( free_buffer<my_number_of_tokens, "premature reuse of buffer" ); + Buffer* b = &buffer[free_buffer]; + ASSERT( &buffer[0] <= b, NULL ); + ASSERT( b <= &buffer[MaxBuffer-1], NULL ); + ASSERT( b->id == Buffer::unused, NULL); + b->id = next_input; + ASSERT( b->sequence_number == Buffer::unused, NULL); + return b; + } +}; + +class process_loop { +public: + void operator()( tbb::thread_bound_filter* tbf ) { + tbb::thread_bound_filter::result_type flag; + do + flag = tbf->process_item(); + while( flag != tbb::thread_bound_filter::end_of_stream ); + } +}; + +//! The struct below repeats layout of tbb::pipeline. +struct hacked_pipeline { + tbb::filter* filter_list; + tbb::filter* filter_end; + tbb::empty_task* end_counter; + tbb::atomic<tbb::internal::Token> input_tokens; + tbb::atomic<tbb::internal::Token> global_token_counter; + bool end_of_input; + bool has_thread_bound_filters; + + virtual ~hacked_pipeline(); +}; + +//! The struct below repeats layout of tbb::internal::ordered_buffer. +struct hacked_ordered_buffer { + void* array; // This should be changed to task_info* if ever used + tbb::internal::Token array_size; + tbb::internal::Token low_token; + tbb::spin_mutex array_mutex; + tbb::internal::Token high_token; + bool is_ordered; + bool is_bound; +}; + +//! The struct below repeats layout of tbb::filter. +struct hacked_filter { + tbb::filter* next_filter_in_pipeline; + hacked_ordered_buffer* input_buffer; + unsigned char my_filter_mode; + tbb::filter* prev_filter_in_pipeline; + tbb::pipeline* my_pipeline; + tbb::filter* next_segment; + + virtual ~hacked_filter(); +}; + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // Workaround for overzealous compiler warnings + // Suppress compiler warning about constant conditional expression + #pragma warning (disable: 4127) +#endif + +void clear_global_state() { + Harness::ConcurrencyTracker::Reset(); + memset( Done, 0, sizeof(Done) ); + thread_id = id0; + is_serial_execution = false; +} + + +class PipelineTest { + // There are 3 non-thread-bound filter types: serial_in_order and serial_out_of_order, parallel + static const tbb::filter::mode non_tb_filters_table[3]; // = { tbb::filter::serial_in_order, tbb::filter::serial_out_of_order, tbb::filter::parallel}; + // There are 2 thread-bound filter types: serial_in_order and serial_out_of_order + static const tbb::filter::mode tb_filters_table[2]; // = { tbb::filter::serial_in_order, tbb::filter::serial_out_of_order }; + + static const unsigned number_of_non_tb_filter_types = sizeof(non_tb_filters_table)/sizeof(non_tb_filters_table[0]); + static const unsigned number_of_tb_filter_types = sizeof(tb_filters_table)/sizeof(tb_filters_table[0]); + static const unsigned number_of_filter_types = number_of_non_tb_filter_types + number_of_tb_filter_types; + // static unsigned my_nthread; + public: + static double TestOneConfiguration( unsigned numeral, unsigned nthread, unsigned number_of_filters, tbb::internal::Token ntokens); + static void TestTrivialPipeline( unsigned nthread, unsigned number_of_filters ); + static void TestIdleSpinning(unsigned nthread); +}; + +const tbb::filter::mode PipelineTest::non_tb_filters_table[3] = { tbb::filter::serial_in_order, tbb::filter::serial_out_of_order, tbb::filter::parallel}; +const tbb::filter::mode PipelineTest::tb_filters_table[2] = { tbb::filter::serial_in_order, tbb::filter::serial_out_of_order }; + +#include "harness_cpu.h" + +double PipelineTest::TestOneConfiguration(unsigned numeral, unsigned nthread, unsigned number_of_filters, tbb::internal::Token ntokens) +{ + // Build pipeline + tbb::pipeline pipeline; + tbb::filter* filter[MaxFilters]; + unsigned temp = numeral; + // parallelism_limit is the upper bound on the possible parallelism + unsigned parallelism_limit = 0; + // number of thread-bound-filters in the current sequence + unsigned number_of_tb_filters = 0; + // ordinal numbers of thread-bound-filters in the current sequence + unsigned array_of_tb_filter_numbers[MaxFilters]; + for( unsigned i=0; i<number_of_filters; ++i, temp/=number_of_filter_types ) { + bool is_bound = temp%number_of_filter_types&0x1; + tbb::filter::mode filter_type; + if( is_bound ) { + filter_type = tb_filters_table[temp%number_of_filter_types/number_of_non_tb_filter_types]; + } else + filter_type = non_tb_filters_table[temp%number_of_filter_types/number_of_tb_filter_types]; + const bool is_last = i==number_of_filters-1; + if( is_bound ) { + if( i == 0 ) + filter[i] = new InputFilter<tbb::thread_bound_filter>(filter_type,ntokens,Done[i],is_last); + else + filter[i] = new BaseFilter<tbb::thread_bound_filter>(filter_type,Done[i],is_last); + array_of_tb_filter_numbers[number_of_tb_filters] = i; + number_of_tb_filters++; + } else { + if( i == 0 ) + filter[i] = new InputFilter<tbb::filter>(filter_type,ntokens,Done[i],is_last); + else + filter[i] = new BaseFilter<tbb::filter>(filter_type,Done[i],is_last); + } + pipeline.add_filter(*filter[i]); + if ( filter[i]->is_serial() ) { + parallelism_limit += 1; + } else { + parallelism_limit = nthread; + } + } + clear_global_state(); + // Account for clipping of parallelism. + if( parallelism_limit>nthread ) + parallelism_limit = nthread; + if( parallelism_limit>ntokens ) + parallelism_limit = (unsigned)ntokens; + StreamSize = nthread; // min( MaxStreamSize, nthread * MaxStreamItemsPerThread ); + + for( unsigned i=0; i<number_of_filters; ++i ) { + static_cast<BaseFilter<tbb::filter>*>(filter[i])->current_token=0; + } + tbb::tbb_thread* t[MaxFilters]; + for( unsigned j = 0; j<number_of_tb_filters; j++) + t[j] = new tbb::tbb_thread(process_loop(), static_cast<tbb::thread_bound_filter*>(filter[array_of_tb_filter_numbers[j]])); + if( ntokens == 1 || ( number_of_filters == 1 && number_of_tb_filters == 0 && filter[0]->is_serial() )) + is_serial_execution = true; + double strttime = GetCPUUserTime(); + pipeline.run( ntokens ); + double endtime = GetCPUUserTime(); + for( unsigned j = 0; j<number_of_tb_filters; j++) + t[j]->join(); + ASSERT( !Harness::ConcurrencyTracker::InstantParallelism(), "filter still running?" ); + for( unsigned i=0; i<number_of_filters; ++i ) + ASSERT( static_cast<BaseFilter<tbb::filter>*>(filter[i])->current_token==StreamSize, NULL ); + for( unsigned i=0; i<MaxFilters; ++i ) + for( unsigned j=0; j<StreamSize; ++j ) { + ASSERT( Done[i][j]==(i<number_of_filters), NULL ); + } + if( Harness::ConcurrencyTracker::PeakParallelism() < parallelism_limit ) + REMARK( "nthread=%lu ntokens=%lu MaxParallelism=%lu parallelism_limit=%lu\n", + nthread, ntokens, Harness::ConcurrencyTracker::PeakParallelism(), parallelism_limit ); + for( unsigned i=0; i < number_of_filters; ++i ) { + delete filter[i]; + filter[i] = NULL; + } + for( unsigned j = 0; j<number_of_tb_filters; j++) + delete t[j]; + pipeline.clear(); + return endtime - strttime; +} // TestOneConfiguration + +void PipelineTest::TestTrivialPipeline( unsigned nthread, unsigned number_of_filters ) { + + REMARK( "testing with %lu threads and %lu filters\n", nthread, number_of_filters ); + ASSERT( number_of_filters<=MaxFilters, "too many filters" ); + tbb::internal::Token max_tokens = nthread < MaxBuffer ? nthread : MaxBuffer; + // The loop has 1 iteration if max_tokens=1 and 2 iterations if max_tokens>1: + // one iteration for ntokens=1 and second for ntokens=max_tokens + // Iteration for ntokens=1 is required in each test case to check if pipeline run only on one thread + unsigned max_iteration = max_tokens > 1 ? 2 : 1; + tbb::internal::Token ntokens = 1; + for( unsigned iteration = 0; iteration < max_iteration; iteration++) { + if( iteration > 0 ) + ntokens = max_tokens; + // Count maximum iterations number + unsigned limit = 1; + for( unsigned i=0; i<number_of_filters; ++i) + limit *= number_of_filter_types; + // Iterate over possible filter sequences + for( unsigned numeral=0; numeral<limit; ++numeral ) { + REMARK( "testing configuration %lu of %lu\n", numeral, limit ); + (void)TestOneConfiguration(numeral, nthread, number_of_filters, ntokens); + } + } +} + +// varying times for sleep result in different user times for all pipelines. +// So we compare the running time of an all non-TBF pipeline with different (with +// luck representative) TBF configurations. +// +// We run the tests multiple times and compare the average runtimes for those cases +// that don't return 0 user time. configurations that exceed the allowable extra +// time are reported. +void PipelineTest::TestIdleSpinning( unsigned nthread) { + unsigned sample_setups[] = { + // in the comments below, s == serial, B == thread bound serial, p == parallel + 1, // B s s s + 5, // s B s s + 25, // s s B s + 125, // s s s B + 6, // B B s s + 26, // B s B s + 126, // B s s B + 30, // s B B s + 130, // s B s B + 150, // s s B B + 31, // B B B s + 131, // B B s B + 155, // s B B B + 21, // B p s s + 105, // s B p s + 45, // s p B s + 225, // s s p B + }; + const int nsetups = sizeof(sample_setups) / sizeof(unsigned); + const int ntests = 4; + const double bignum = 1000000000.0; + const double allowable_slowdown = 3.5; + unsigned zero_count = 0; + + REMARK( "testing idle spinning with %lu threads\n", nthread ); + tbb::internal::Token max_tokens = nthread < MaxBuffer ? nthread : MaxBuffer; + for( int i=0; i<nsetups; ++i ) { + unsigned numeral = sample_setups[i]; + unsigned temp = numeral; + unsigned nbound = 0; + while(temp) { + if((temp%number_of_filter_types)&0x01) nbound++; + temp /= number_of_filter_types; + } + sleeptime = 20.0; + double s0 = bignum; + double s1 = bignum; + int v0cnt = 0; + int v1cnt = 0; + double s0sum = 0.0; + double s1sum = 0.0; + for(int j = 0; j < ntests; ++j) { + double s1a = TestOneConfiguration(numeral, nthread, MaxFilters, max_tokens); + double s0a = TestOneConfiguration((unsigned)0, nthread, MaxFilters, max_tokens); + s1sum += s1a; + s0sum += s0a; + if(s0a > 0.0) { + ++v0cnt; + s0 = (s0a < s0) ? s0a : s0; + } + else { + ++zero_count; + } + if(s1a > 0.0) { + ++v1cnt; + s1 = (s1a < s1) ? s1a : s1; + } + else { + ++zero_count; + } + } + if(s0 == bignum || s1 == bignum) continue; + s0sum /= (double)v0cnt; + s1sum /= (double)v1cnt; + double slowdown = (s1sum-s0sum)/s0sum; + if(slowdown > allowable_slowdown) + REMARK( "with %lu threads configuration %lu has slowdown > %g (%g)\n", nthread, numeral, allowable_slowdown, slowdown ); + } + REMARK("Total of %lu zero times\n", zero_count); +} + +static int nthread; // knowing number of threads is necessary to call TestCPUUserTime + +void waiting_probe::probe( ) { + if( nthread==1 ) return; + REMARK("emulating wait for input\n"); + // Test that threads sleep while no work. + // The master doesn't sleep so there could be 2 active threads if a worker is waiting for input + TestCPUUserTime(nthread, 2); +} + +#include "tbb/task_scheduler_init.h" + +int TestMain () { + out_of_order_count = 0; + if( MinThread<1 ) { + REPORT("must have at least one thread"); + exit(1); + } + + sleeptime = 0.0; // msec : 0 == no_timing, > 0, each filter stage sleeps for sleeptime + // Test with varying number of threads. + for( nthread=MinThread; nthread<=MaxThread; ++nthread ) { + // Initialize TBB task scheduler + tbb::task_scheduler_init init(nthread); + + // Test pipelines with 1 and maximal number of filters + for( unsigned n=1; n<=MaxFilters; n*=MaxFilters ) { + // Thread-bound stages are serviced by user-created threads those + // don't run the pipeline and don't service non-thread-bound stages + PipelineTest::TestTrivialPipeline(nthread,n); + } + + // Test that all workers sleep when no work + TestCPUUserTime(nthread); + if((unsigned)nthread >= MaxFilters) // test works when number of threads >= number of stages + PipelineTest::TestIdleSpinning(nthread); + } + if( !out_of_order_count ) + REPORT("Warning: out of order serial filter received tokens in order\n"); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_priority_queue_node.cpp b/src/tbb/src/test/test_priority_queue_node.cpp new file mode 100644 index 0000000..999a965 --- /dev/null +++ b/src/tbb/src/test/test_priority_queue_node.cpp @@ -0,0 +1,347 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// TO DO: Add overlapping put / receive tests + +#include "tbb/flow_graph.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/tick_count.h" +#include "harness.h" + +#include <cstdio> + +#define N 10 +#define C 10 + +template< typename T > +void spin_try_get( tbb::flow::priority_queue_node<T> &q, T &value ) { + while ( q.try_get(value) != true ) ; +} + +template< typename T > +void check_item( T* next_value, T &value ) { + int tid = value / N; + int offset = value % N; + ASSERT( next_value[tid] == T(offset), NULL ); + ++next_value[tid]; +} + +template< typename T > +struct parallel_puts : NoAssign { + tbb::flow::priority_queue_node<T> &my_q; + parallel_puts( tbb::flow::priority_queue_node<T> &q ) : my_q(q) {} + void operator()(int i) const { + for (int j = 0; j < N; ++j) { + bool msg = my_q.try_put( T(N*i + j) ); + ASSERT( msg == true, NULL ); + } + } +}; + +template< typename T > +struct parallel_gets : NoAssign { + tbb::flow::priority_queue_node<T> &my_q; + parallel_gets( tbb::flow::priority_queue_node<T> &q) : my_q(q) {} + void operator()(int) const { + T prev; + spin_try_get( my_q, prev ); + for (int j = 0; j < N-1; ++j) { + T v; + spin_try_get( my_q, v ); + ASSERT(v < prev, NULL); + } + } +}; + +template< typename T > +struct parallel_put_get : NoAssign { + tbb::flow::priority_queue_node<T> &my_q; + parallel_put_get( tbb::flow::priority_queue_node<T> &q ) : my_q(q) {} + void operator()(int tid) const { + for ( int i = 0; i < N; i+=C ) { + int j_end = ( N < i + C ) ? N : i + C; + // dump about C values into the Q + for ( int j = i; j < j_end; ++j ) { + ASSERT( my_q.try_put( T (N*tid + j ) ) == true, NULL ); + } + // receive about C values from the Q + for ( int j = i; j < j_end; ++j ) { + T v; + spin_try_get( my_q, v ); + } + } + } +}; + +// +// Tests +// +// Item can be reserved, released, consumed ( single serial receiver ) +// +template< typename T > +int test_reservation(int) { + tbb::flow::graph g; + T bogus_value(-1); + + // Simple tests + tbb::flow::priority_queue_node<T> q(g); + + q.try_put(T(1)); + q.try_put(T(2)); + q.try_put(T(3)); + g.wait_for_all(); + + T v=bogus_value, w=bogus_value; + ASSERT( q.try_reserve(v) == true, NULL ); + ASSERT( v == T(3), NULL ); + ASSERT( q.try_release() == true, NULL ); + v = bogus_value; + g.wait_for_all(); + ASSERT( q.try_reserve(v) == true, NULL ); + ASSERT( v == T(3), NULL ); + ASSERT( q.try_consume() == true, NULL ); + v = bogus_value; + g.wait_for_all(); + + ASSERT( q.try_get(v) == true, NULL ); + ASSERT( v == T(2), NULL ); + v = bogus_value; + g.wait_for_all(); + + ASSERT( q.try_reserve(v) == true, NULL ); + ASSERT( v == T(1), NULL ); + ASSERT( q.try_reserve(w) == false, NULL ); + ASSERT( w == bogus_value, NULL ); + ASSERT( q.try_get(w) == false, NULL ); + ASSERT( w == bogus_value, NULL ); + ASSERT( q.try_release() == true, NULL ); + v = bogus_value; + g.wait_for_all(); + ASSERT( q.try_reserve(v) == true, NULL ); + ASSERT( v == T(1), NULL ); + ASSERT( q.try_consume() == true, NULL ); + v = bogus_value; + g.wait_for_all(); + ASSERT( q.try_get(v) == false, NULL ); + return 0; +} + +// +// Tests +// +// multilpe parallel senders, items in FIFO (relatively to sender) order +// multilpe parallel senders, multiple parallel receivers, items in FIFO order (relative to sender/receiver) and all items received +// * overlapped puts / gets +// * all puts finished before any getS +// +template< typename T > +int test_parallel(int num_threads) { + tbb::flow::graph g; + tbb::flow::priority_queue_node<T> q(g); + tbb::flow::priority_queue_node<T> q2(g); + tbb::flow::priority_queue_node<T> q3(g); + T bogus_value(-1); + T j = bogus_value; + + NativeParallelFor( num_threads, parallel_puts<T>(q) ); + for (int i = num_threads*N -1; i>=0; --i) { + spin_try_get( q, j ); + ASSERT(j == i, NULL); + j = bogus_value; + } + g.wait_for_all(); + ASSERT( q.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + NativeParallelFor( num_threads, parallel_puts<T>(q) ); + g.wait_for_all(); + NativeParallelFor( num_threads, parallel_gets<T>(q) ); + g.wait_for_all(); + j = bogus_value; + ASSERT( q.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + NativeParallelFor( num_threads, parallel_put_get<T>(q) ); + g.wait_for_all(); + j = bogus_value; + ASSERT( q.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + tbb::flow::make_edge( q, q2 ); + tbb::flow::make_edge( q2, q3 ); + NativeParallelFor( num_threads, parallel_puts<T>(q) ); + g.wait_for_all(); + NativeParallelFor( num_threads, parallel_gets<T>(q3) ); + g.wait_for_all(); + j = bogus_value; + ASSERT( q.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + ASSERT( q2.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + ASSERT( q3.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + // test copy constructor + ASSERT( q.remove_successor( q2 ) == true, NULL ); + NativeParallelFor( num_threads, parallel_puts<T>(q) ); + tbb::flow::priority_queue_node<T> q_copy(q); + g.wait_for_all(); + j = bogus_value; + ASSERT( q_copy.try_get( j ) == false, NULL ); + ASSERT( q.register_successor( q_copy ) == true, NULL ); + for (int i = num_threads*N -1; i>=0; --i) { + spin_try_get( q_copy, j ); + ASSERT(j == i, NULL); + j = bogus_value; + } + g.wait_for_all(); + ASSERT( q.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + ASSERT( q_copy.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + return 0; +} + +// +// Tests +// +// Predecessors cannot be registered +// Empty Q rejects item requests +// Single serial sender, items in FIFO order +// Chained Qs ( 2 & 3 ), single sender, items at last Q in FIFO order +// + +template< typename T > +int test_serial() { + tbb::flow::graph g; + T bogus_value(-1); + + tbb::flow::priority_queue_node<T> q(g); + tbb::flow::priority_queue_node<T> q2(g); + T j = bogus_value; + + // + // Rejects attempts to add / remove predecessor + // Rejects request from empty Q + // + ASSERT( q.register_predecessor( q2 ) == false, NULL ); + ASSERT( q.remove_predecessor( q2 ) == false, NULL ); + ASSERT( q.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + // + // Simple puts and gets + // + + for (int i = 0; i < N; ++i) + ASSERT( q.try_put( T(i) ), NULL ); + for (int i = N-1; i >=0; --i) { + j = bogus_value; + spin_try_get( q, j ); + ASSERT( i == j, NULL ); + } + j = bogus_value; + g.wait_for_all(); + ASSERT( q.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + tbb::flow::make_edge( q, q2 ); + + for (int i = 0; i < N; ++i) + ASSERT( q.try_put( T(i) ), NULL ); + g.wait_for_all(); + for (int i = N-1; i >= 0; --i) { + j = bogus_value; + spin_try_get( q2, j ); + ASSERT( i == j, NULL ); + } + j = bogus_value; + g.wait_for_all(); + ASSERT( q.try_get( j ) == false, NULL ); + g.wait_for_all(); + ASSERT( q2.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + tbb::flow::remove_edge( q, q2 ); + ASSERT( q.try_put( 1 ) == true, NULL ); + g.wait_for_all(); + ASSERT( q2.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + g.wait_for_all(); + ASSERT( q.try_get( j ) == true, NULL ); + ASSERT( j == 1, NULL ); + + tbb::flow::priority_queue_node<T> q3(g); + tbb::flow::make_edge( q, q2 ); + tbb::flow::make_edge( q2, q3 ); + + for (int i = 0; i < N; ++i) + ASSERT( q.try_put( T(i) ), NULL ); + g.wait_for_all(); + for (int i = N-1; i >= 0; --i) { + j = bogus_value; + spin_try_get( q3, j ); + ASSERT( i == j, NULL ); + } + j = bogus_value; + g.wait_for_all(); + ASSERT( q.try_get( j ) == false, NULL ); + g.wait_for_all(); + ASSERT( q2.try_get( j ) == false, NULL ); + g.wait_for_all(); + ASSERT( q3.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + tbb::flow::remove_edge( q, q2 ); + ASSERT( q.try_put( 1 ) == true, NULL ); + g.wait_for_all(); + ASSERT( q2.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + g.wait_for_all(); + ASSERT( q3.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + g.wait_for_all(); + ASSERT( q.try_get( j ) == true, NULL ); + ASSERT( j == 1, NULL ); + + return 0; +} + +int TestMain() { + tbb::tick_count start = tbb::tick_count::now(), stop; + for (int p = 1; p < 4; ++p) { + tbb::task_scheduler_init init(p); + test_serial<int>(); + test_reservation<int>(p); + test_parallel<int>(p); + } + stop = tbb::tick_count::now(); + REMARK("Priority_Queue_Node Time=%6.6f\n", (stop-start).seconds()); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_queue_node.cpp b/src/tbb/src/test/test_queue_node.cpp new file mode 100644 index 0000000..058232a --- /dev/null +++ b/src/tbb/src/test/test_queue_node.cpp @@ -0,0 +1,459 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// TO DO: Add overlapping put / receive tests + +#include "tbb/flow_graph.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/tick_count.h" +#include "harness.h" + +#include <cstdio> + +#define N 1000 +#define C 10 + +template< typename T > +void spin_try_get( tbb::flow::queue_node<T> &q, T &value ) { + while ( q.try_get(value) != true ) ; +} + +template< typename T > +void check_item( T* next_value, T &value ) { + int tid = value / N; + int offset = value % N; + ASSERT( next_value[tid] == T(offset), NULL ); + ++next_value[tid]; +} + +template< typename T > +struct parallel_puts : NoAssign { + + tbb::flow::queue_node<T> &my_q; + + parallel_puts( tbb::flow::queue_node<T> &q ) : my_q(q) {} + + void operator()(int i) const { + for (int j = 0; j < N; ++j) { + bool msg = my_q.try_put( T(N*i + j) ); + ASSERT( msg == true, NULL ); + } + } + +}; + + + +template< typename T > +struct touches { + + bool **my_touches; + T **my_last_touch; + int my_num_threads; + + touches( int num_threads ) : my_num_threads(num_threads) { + my_last_touch = new T* [my_num_threads]; + my_touches = new bool* [my_num_threads]; + for ( int p = 0; p < my_num_threads; ++p) { + my_last_touch[p] = new T[my_num_threads]; + for ( int p2 = 0; p2 < my_num_threads; ++p2) + my_last_touch[p][p2] = -1; + + my_touches[p] = new bool[N*my_num_threads]; + for ( int n = 0; n < N*my_num_threads; ++n) + my_touches[p][n] = false; + } + } + + ~touches() { + for ( int p = 0; p < my_num_threads; ++p) { + delete [] my_touches[p]; + delete [] my_last_touch[p]; + } + delete [] my_touches; + delete [] my_last_touch; + } + + bool check( int tid, T v ) { + int v_tid = v / N; + if ( my_touches[tid][v] != false ) { + printf("Error: value seen twice by local thread\n"); + return false; + } + if ( v <= my_last_touch[tid][v_tid] ) { + printf("Error: value seen in wrong order by local thread\n"); + return false; + } + my_last_touch[tid][v_tid] = v; + my_touches[tid][v] = true; + return true; + } + + bool validate_touches() { + bool *all_touches = new bool[N*my_num_threads]; + for ( int n = 0; n < N*my_num_threads; ++n) + all_touches[n] = false; + + for ( int p = 0; p < my_num_threads; ++p) { + for ( int n = 0; n < N*my_num_threads; ++n) { + if ( my_touches[p][n] == true ) { + ASSERT( all_touches[n] == false, "value see by more than one thread\n" ); + all_touches[n] = true; + } + } + } + for ( int n = 0; n < N*my_num_threads; ++n) { + if ( !all_touches[n] ) + printf("No touch at %d, my_num_threads = %d\n", n, my_num_threads); + //ASSERT( all_touches[n] == true, "value not seen by any thread\n" ); + } + delete all_touches; + return true; + } + +}; + +template< typename T > +struct parallel_gets : NoAssign { + + tbb::flow::queue_node<T> &my_q; + touches<T> &my_touches; + + parallel_gets( tbb::flow::queue_node<T> &q, touches<T> &t) : my_q(q), my_touches(t) {} + + void operator()(int tid) const { + for (int j = 0; j < N; ++j) { + T v; + spin_try_get( my_q, v ); + my_touches.check( tid, v ); + } + } + +}; + +template< typename T > +struct parallel_put_get : NoAssign { + + tbb::flow::queue_node<T> &my_q; + touches<T> &my_touches; + + parallel_put_get( tbb::flow::queue_node<T> &q, touches<T> &t ) : my_q(q), my_touches(t) {} + + void operator()(int tid) const { + + for ( int i = 0; i < N; i+=C ) { + int j_end = ( N < i + C ) ? N : i + C; + // dump about C values into the Q + for ( int j = i; j < j_end; ++j ) { + ASSERT( my_q.try_put( T (N*tid + j ) ) == true, NULL ); + } + // receiver about C values from the Q + for ( int j = i; j < j_end; ++j ) { + T v; + spin_try_get( my_q, v ); + my_touches.check( tid, v ); + } + } + } + +}; + +// +// Tests +// +// Item can be reserved, released, consumed ( single serial receiver ) +// +template< typename T > +int test_reservation() { + tbb::flow::graph g; + T bogus_value(-1); + + // Simple tests + tbb::flow::queue_node<T> q(g); + + q.try_put(T(1)); + q.try_put(T(2)); + q.try_put(T(3)); + + T v; + ASSERT( q.reserve_item(v) == true, NULL ); + ASSERT( v == T(1), NULL ); + ASSERT( q.release_reservation() == true, NULL ); + v = bogus_value; + g.wait_for_all(); + ASSERT( q.reserve_item(v) == true, NULL ); + ASSERT( v == T(1), NULL ); + ASSERT( q.consume_reservation() == true, NULL ); + v = bogus_value; + g.wait_for_all(); + + ASSERT( q.try_get(v) == true, NULL ); + ASSERT( v == T(2), NULL ); + v = bogus_value; + g.wait_for_all(); + + ASSERT( q.reserve_item(v) == true, NULL ); + ASSERT( v == T(3), NULL ); + ASSERT( q.release_reservation() == true, NULL ); + v = bogus_value; + g.wait_for_all(); + ASSERT( q.reserve_item(v) == true, NULL ); + ASSERT( v == T(3), NULL ); + ASSERT( q.consume_reservation() == true, NULL ); + v = bogus_value; + g.wait_for_all(); + + return 0; +} + +// +// Tests +// +// multilpe parallel senders, items in FIFO (relatively to sender) order +// multilpe parallel senders, multiple parallel receivers, items in FIFO order (relative to sender/receiver) and all items received +// * overlapped puts / gets +// * all puts finished before any getS +// +template< typename T > +int test_parallel(int num_threads) { + tbb::flow::graph g; + tbb::flow::queue_node<T> q(g); + tbb::flow::queue_node<T> q2(g); + tbb::flow::queue_node<T> q3(g); + T bogus_value(-1); + T j = bogus_value; + + NativeParallelFor( num_threads, parallel_puts<T>(q) ); + + T *next_value = new T[num_threads]; + for (int tid = 0; tid < num_threads; ++tid) next_value[tid] = T(0); + + for (int i = 0; i < num_threads * N; ++i ) { + spin_try_get( q, j ); + check_item( next_value, j ); + j = bogus_value; + } + for (int tid = 0; tid < num_threads; ++tid) { + ASSERT( next_value[tid] == T(N), NULL ); + } + + j = bogus_value; + g.wait_for_all(); + ASSERT( q.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + NativeParallelFor( num_threads, parallel_puts<T>(q) ); + + { + touches< T > t( num_threads ); + NativeParallelFor( num_threads, parallel_gets<T>(q, t) ); + g.wait_for_all(); + ASSERT( t.validate_touches(), NULL ); + } + j = bogus_value; + ASSERT( q.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + g.wait_for_all(); + { + touches< T > t2( num_threads ); + NativeParallelFor( num_threads, parallel_put_get<T>(q, t2) ); + g.wait_for_all(); + ASSERT( t2.validate_touches(), NULL ); + } + j = bogus_value; + ASSERT( q.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + tbb::flow::make_edge( q, q2 ); + tbb::flow::make_edge( q2, q3 ); + + NativeParallelFor( num_threads, parallel_puts<T>(q) ); + { + touches< T > t3( num_threads ); + NativeParallelFor( num_threads, parallel_gets<T>(q3, t3) ); + g.wait_for_all(); + ASSERT( t3.validate_touches(), NULL ); + } + j = bogus_value; + g.wait_for_all(); + ASSERT( q.try_get( j ) == false, NULL ); + g.wait_for_all(); + ASSERT( q2.try_get( j ) == false, NULL ); + g.wait_for_all(); + ASSERT( q3.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + // test copy constructor + ASSERT( q.remove_successor( q2 ), NULL ); + NativeParallelFor( num_threads, parallel_puts<T>(q) ); + tbb::flow::queue_node<T> q_copy(q); + j = bogus_value; + g.wait_for_all(); + ASSERT( q_copy.try_get( j ) == false, NULL ); + ASSERT( q.register_successor( q_copy ) == true, NULL ); + { + touches< T > t( num_threads ); + NativeParallelFor( num_threads, parallel_gets<T>(q_copy, t) ); + g.wait_for_all(); + ASSERT( t.validate_touches(), NULL ); + } + j = bogus_value; + ASSERT( q.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + ASSERT( q_copy.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + return 0; +} + +// +// Tests +// +// Predecessors cannot be registered +// Empty Q rejects item requests +// Single serial sender, items in FIFO order +// Chained Qs ( 2 & 3 ), single sender, items at last Q in FIFO order +// + +template< typename T > +int test_serial() { + tbb::flow::graph g; + T bogus_value(-1); + + tbb::flow::queue_node<T> q(g); + tbb::flow::queue_node<T> q2(g); + T j = bogus_value; + + // + // Rejects attempts to add / remove predecessor + // Rejects request from empty Q + // + ASSERT( q.register_predecessor( q2 ) == false, NULL ); + ASSERT( q.remove_predecessor( q2 ) == false, NULL ); + ASSERT( q.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + // + // Simple puts and gets + // + + for (int i = 0; i < N; ++i) { + bool msg = q.try_put( T(i) ); + ASSERT( msg == true, NULL ); + } + + + for (int i = 0; i < N; ++i) { + j = bogus_value; + spin_try_get( q, j ); + ASSERT( i == j, NULL ); + } + j = bogus_value; + g.wait_for_all(); + ASSERT( q.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + tbb::flow::make_edge( q, q2 ); + + for (int i = 0; i < N; ++i) { + bool msg = q.try_put( T(i) ); + ASSERT( msg == true, NULL ); + } + + + for (int i = 0; i < N; ++i) { + j = bogus_value; + spin_try_get( q2, j ); + ASSERT( i == j, NULL ); + } + j = bogus_value; + g.wait_for_all(); + ASSERT( q.try_get( j ) == false, NULL ); + g.wait_for_all(); + ASSERT( q2.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + tbb::flow::remove_edge( q, q2 ); + ASSERT( q.try_put( 1 ) == true, NULL ); + g.wait_for_all(); + ASSERT( q2.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + g.wait_for_all(); + ASSERT( q.try_get( j ) == true, NULL ); + ASSERT( j == 1, NULL ); + + tbb::flow::queue_node<T> q3(g); + tbb::flow::make_edge( q, q2 ); + tbb::flow::make_edge( q2, q3 ); + + for (int i = 0; i < N; ++i) { + bool msg = q.try_put( T(i) ); + ASSERT( msg == true, NULL ); + } + + for (int i = 0; i < N; ++i) { + j = bogus_value; + spin_try_get( q3, j ); + ASSERT( i == j, NULL ); + } + j = bogus_value; + g.wait_for_all(); + ASSERT( q.try_get( j ) == false, NULL ); + g.wait_for_all(); + ASSERT( q2.try_get( j ) == false, NULL ); + g.wait_for_all(); + ASSERT( q3.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + tbb::flow::remove_edge( q, q2 ); + ASSERT( q.try_put( 1 ) == true, NULL ); + g.wait_for_all(); + ASSERT( q2.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + g.wait_for_all(); + ASSERT( q3.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + g.wait_for_all(); + ASSERT( q.try_get( j ) == true, NULL ); + ASSERT( j == 1, NULL ); + + return 0; +} + +int TestMain() { + tbb::tick_count start = tbb::tick_count::now(), stop; + for (int p = 1; p < 4; ++p) { + tbb::task_scheduler_init init(p); + test_serial<int>(); + test_parallel<int>(p); + } + stop = tbb::tick_count::now(); + REMARK("Queue_Node Time=%6.6f\n", (stop-start).seconds()); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_reader_writer_lock.cpp b/src/tbb/src/test/test_reader_writer_lock.cpp new file mode 100644 index 0000000..bb5e002 --- /dev/null +++ b/src/tbb/src/test/test_reader_writer_lock.cpp @@ -0,0 +1,221 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// test reader_writer_lock +#include "tbb/reader_writer_lock.h" +#include "tbb/atomic.h" +#include "tbb/tbb_exception.h" +#include "harness_assert.h" +#include "harness.h" + +tbb::reader_writer_lock the_mutex; +const int MAX_WORK = 10000; + +tbb::atomic<size_t> active_readers, active_writers; +tbb::atomic<bool> sim_readers; + + +int BusyWork(int percentOfMaxWork) { + int iters = 0; + for (int i=0; i<MAX_WORK*((double)percentOfMaxWork/100.0); ++i) { + iters++; + } + return iters; +} + +struct StressRWLBody : NoAssign { + const int nThread; + const int percentMax; + + StressRWLBody(int nThread_, int percentMax_) : nThread(nThread_), percentMax(percentMax_) {} + + void operator()(const int /* threadID */ ) const { + int nIters = 100; + int r_result=0, w_result=0; + for(int i=0; i<nIters; ++i) { + // test unscoped blocking write lock + the_mutex.lock(); + w_result += BusyWork(percentMax); +#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN + // test exception for recursive write lock + bool was_caught = false; + try { + the_mutex.lock(); + } + catch(tbb::improper_lock& ex) { + REMARK("improper_lock: %s\n", ex.what()); + was_caught = true; + } + catch(...) { + REPORT("Wrong exception caught during recursive lock attempt."); + } + ASSERT(was_caught, "Recursive lock attempt exception not caught properly."); + // test exception for recursive read lock + was_caught = false; + try { + the_mutex.lock_read(); + } + catch(tbb::improper_lock& ex) { + REMARK("improper_lock: %s\n", ex.what()); + was_caught = true; + } + catch(...) { + REPORT("Wrong exception caught during recursive lock attempt."); + } + ASSERT(was_caught, "Recursive lock attempt exception not caught properly."); +#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */ + the_mutex.unlock(); + // test unscoped non-blocking write lock + if (the_mutex.try_lock()) { + w_result += BusyWork(percentMax); + the_mutex.unlock(); + } + // test unscoped blocking read lock + the_mutex.lock_read(); + r_result += BusyWork(percentMax); + the_mutex.unlock(); + // test unscoped non-blocking read lock + if(the_mutex.try_lock_read()) { + r_result += BusyWork(percentMax); + the_mutex.unlock(); + } + { // test scoped blocking write lock + tbb::reader_writer_lock::scoped_lock my_lock(the_mutex); + w_result += BusyWork(percentMax); + } + { // test scoped blocking read lock + tbb::reader_writer_lock::scoped_lock_read my_lock(the_mutex); + r_result += BusyWork(percentMax); + } + } + REMARK(" R%d/W%d", r_result, w_result); // reader/writer iterations of busy work completed + } +}; + +struct CorrectRWLScopedBody : NoAssign { + const int nThread; + + CorrectRWLScopedBody(int nThread_) : nThread(nThread_) {} + + void operator()(const int /* threadID */ ) const { + for (int i=0; i<50; i++) { + const bool is_reader = i%5==0; // 1 writer for every 4 readers + + if (is_reader) { + tbb::reader_writer_lock::scoped_lock_read my_lock(the_mutex); + active_readers++; + if (active_readers > 1) sim_readers = true; + ASSERT(active_writers==0, "Active writers in read-locked region."); + Harness::Sleep(10); + active_readers--; + } + else { // is writer + tbb::reader_writer_lock::scoped_lock my_lock(the_mutex); + active_writers++; + ASSERT(active_readers==0, "Active readers in write-locked region."); + ASSERT(active_writers<=1, "More than one active writer in write-locked region."); + Harness::Sleep(10); + active_writers--; + } + } + } +}; + +struct CorrectRWLBody : NoAssign { + const int nThread; + + CorrectRWLBody(int nThread_) : nThread(nThread_) {} + + void operator()(const int /* threadID */ ) const { + for (int i=0; i<50; i++) { + const bool is_reader = i%5==0; // 1 writer for every 4 readers + + if (is_reader) { + the_mutex.lock_read(); + active_readers++; + if (active_readers > 1) sim_readers = true; + ASSERT(active_writers==0, "Active writers in read-locked region."); + } + else { // is writer + the_mutex.lock(); + active_writers++; + ASSERT(active_readers==0, "Active readers in write-locked region."); + ASSERT(active_writers<=1, "More than one active writer in write-locked region."); + } + Harness::Sleep(10); + if (is_reader) { + active_readers--; + } + else { // is writer + active_writers--; + } + the_mutex.unlock(); + } + } +}; + +void TestReaderWriterLockOnNThreads(int nThreads) { + // Stress-test all interfaces + for (int pc=0; pc<=100; pc+=20) { + REMARK("Testing with %d threads, percent of MAX_WORK=%d...", nThreads, pc); + StressRWLBody myStressBody(nThreads, pc); + NativeParallelFor(nThreads, myStressBody); + REMARK(" OK.\n"); + } + + REMARK("Testing with %d threads, direct/unscoped locking mode...", nThreads); // TODO: choose direct or unscoped? + CorrectRWLBody myCorrectBody(nThreads); + active_writers = active_readers = 0; + sim_readers = false; + NativeParallelFor(nThreads, myCorrectBody); + ASSERT(sim_readers || nThreads<2, "There were no simultaneous readers."); + REMARK(" OK.\n"); + + REMARK("Testing with %d threads, scoped locking mode...", nThreads); + CorrectRWLScopedBody myCorrectScopedBody(nThreads); + active_writers = active_readers = 0; + sim_readers = false; + NativeParallelFor(nThreads, myCorrectScopedBody); + ASSERT(sim_readers || nThreads<2, "There were no simultaneous readers."); + REMARK(" OK.\n"); +} + +void TestReaderWriterLock() { + for(int p = MinThread; p <= MaxThread; p++) { + TestReaderWriterLockOnNThreads(p); + } +} + + +int TestMain() { + if(MinThread <= 0) MinThread = 1; + if(MaxThread > 0) { + TestReaderWriterLock(); + } + return Harness::Done; +} diff --git a/src/tbb/src/test/test_runtime_loader.cpp b/src/tbb/src/test/test_runtime_loader.cpp new file mode 100644 index 0000000..8b1c61d --- /dev/null +++ b/src/tbb/src/test/test_runtime_loader.cpp @@ -0,0 +1,300 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if !(_WIN32||_WIN64) + +#include "harness.h" + +int TestMain () { + return Harness::Skipped; +} + +#else // !(_WIN32||_WIN64) + +#define TBB_PREVIEW_RUNTIME_LOADER 1 +#include "tbb/runtime_loader.h" +#include "tbb/tbb_stddef.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/tbb_exception.h" + +#include <cstdio> +#include <cstdlib> +#include <cerrno> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include <vector> +#include <string> +#include <utility> +#include <typeinfo> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +#ifdef HARNESS_USE_RUNTIME_LOADER + #undef HARNESS_USE_RUNTIME_LOADER // We do not want harness to preload tbb. +#endif +#include "harness.h" + +static int errors = 0; + +#define CHECK( cond ) { \ + if ( ! (cond) ) { \ + ++ errors; \ + REPORT( "%s:%d: --- TEST FAILED ---\n", __FILE__, __LINE__ ); \ + }; \ +} + +#define SAY( msg ) \ + REMARK( "%s:%d: %s\n", __FILE__, __LINE__, msg ) + +typedef int (*int_func_t)(); + +namespace tbb { +namespace interface6 { +namespace internal { +namespace runtime_loader { + extern tbb::runtime_loader::error_mode stub_mode; +} } } } // namespaces runtime_loader, internal, interface6, tbb + +using tbb::interface6::internal::runtime_loader::stub_mode; + +#define _CHECK_TBB( code ) { \ + stub_mode = tbb::runtime_loader::em_status; \ + int ver = tbb::TBB_runtime_interface_version(); \ + stub_mode = tbb::runtime_loader::em_abort; \ + CHECK( ver == code ); \ +} + +#define CHECK_TBB_IS_LOADED() \ + _CHECK_TBB( TBB_INTERFACE_VERSION ) + +#define CHECK_TBB_IS_NOT_LOADED() \ + _CHECK_TBB( tbb::runtime_loader::ec_no_lib ) + +int TestMain() { + + + __TBB_TRY { + + { + SAY( "Call a function when library is not yet loaded, stub should return a error." ); + CHECK_TBB_IS_NOT_LOADED(); + } + + { + SAY( "Create a runtime_loader object, do not load library but make some bad calls." ); + tbb::runtime_loader rtl( tbb::runtime_loader::em_status ); + SAY( "After creating status should be ok." ); + CHECK( rtl.status() == tbb::runtime_loader::ec_ok ); + SAY( "Call a function, stub should return a error." ); + CHECK_TBB_IS_NOT_LOADED(); + } + + { + SAY( "Create a runtime_loader object and call load() with bad arguments." ); + char const * path[] = { ".", NULL }; + tbb::runtime_loader rtl( tbb::runtime_loader::em_status ); + SAY( "Min version is bad." ); + rtl.load( path, -1 ); + CHECK( rtl.status() == tbb::runtime_loader::ec_bad_arg ); + SAY( "Max version is bad." ); + rtl.load( path, TBB_INTERFACE_VERSION, -1 ); + CHECK( rtl.status() == tbb::runtime_loader::ec_bad_arg ); + SAY( "Both versions are bad." ); + rtl.load( path, -1, -1 ); + CHECK( rtl.status() == tbb::runtime_loader::ec_bad_arg ); + SAY( "Min is bigger than max." ); + rtl.load( path, TBB_INTERFACE_VERSION + 1, TBB_INTERFACE_VERSION - 1 ); + CHECK( rtl.status() == tbb::runtime_loader::ec_bad_arg ); + } + + { + SAY( "Create a proxy object and call load() with good arguments but not availabe version." ); + char const * path[] = { ".", NULL }; + tbb::runtime_loader rtl( tbb::runtime_loader::em_status ); + SAY( "Min version too big." ); + rtl.load( path, TBB_INTERFACE_VERSION + 1, TBB_INTERFACE_VERSION + 1 ); + CHECK( rtl.status() == tbb::runtime_loader::ec_no_lib ); + SAY( "Max version is too small." ); + rtl.load( path, TBB_INTERFACE_VERSION - 1, TBB_INTERFACE_VERSION - 1 ); + CHECK( rtl.status() == tbb::runtime_loader::ec_no_lib ); + } + + { + SAY( "Test em_throw mode." ); + char const * path[] = { ".", NULL }; + tbb::runtime_loader rtl( tbb::runtime_loader::em_throw ); + tbb::runtime_loader::error_code code = tbb::runtime_loader::ec_ok; + __TBB_TRY { + rtl.load( path, -1 ); + } __TBB_CATCH ( tbb::runtime_loader::error_code c ) { + code = c; + }; // __TBB_TRY + CHECK( code == tbb::runtime_loader::ec_bad_arg ); + __TBB_TRY { + rtl.load( path, TBB_INTERFACE_VERSION + 1 ); + } __TBB_CATCH ( tbb::runtime_loader::error_code c ) { + code = c; + }; // __TBB_TRY + CHECK( code == tbb::runtime_loader::ec_no_lib ); + } + + { + SAY( "Load current version, but specify wrong directories." ); + tbb::runtime_loader rtl( tbb::runtime_loader::em_status ); + SAY( "Specify no directories." ); + char const * path0[] = { NULL }; + rtl.load( path0 ); + CHECK( rtl.status() == tbb::runtime_loader::ec_no_lib ); + SAY( "Specify directories without library." ); + char const * path1[] = { "..", "/", NULL }; + rtl.load( path1 ); + CHECK( rtl.status() == tbb::runtime_loader::ec_no_lib ); + } + + { + SAY( "Now really load library and do various tests." ); + char const * path[] = { ".", NULL }; + tbb::runtime_loader rtl( tbb::runtime_loader::em_status ); + SAY( "Load current version." ); + rtl.load( path, TBB_INTERFACE_VERSION, TBB_INTERFACE_VERSION ); + CHECK( rtl.status() == tbb::runtime_loader::ec_ok ); + if ( rtl.status() == tbb::runtime_loader::ec_ok ) { + { + SAY( "Make sure the library really loaded." ); + CHECK_TBB_IS_LOADED(); + } + SAY( "Call load() again, it should return a error." ); + rtl.load( path, TBB_INTERFACE_VERSION, TBB_INTERFACE_VERSION ); + CHECK( rtl.status() == tbb::runtime_loader::ec_bad_call ); + { + SAY( "Initialize task_scheduler." ); + tbb::task_scheduler_init init( 1 ); + // Check what? + } + + // There was a problem on Linux, and still a problem on Mac OS X. + SAY( "Throw an exception." ); + // Iterate thru all the ids first. + for ( int id = 1; id < tbb::internal::eid_max; ++ id ) { + bool ex_caught = false; + __TBB_TRY { + tbb::internal::throw_exception( tbb::internal::exception_id( id ) ); + } __TBB_CATCH ( std::exception const & ) { + SAY( "Expected exception caught." ); + ex_caught = true; + } __TBB_CATCH ( ... ) { + SAY( "Unexpected exception caught." ); + }; // try + CHECK( ex_caught ); + }; // for + // Now try to catch exceptions of specific types. + #define CHECK_EXCEPTION( id, type ) \ + { \ + SAY( "Trowing " #id " exception of " #type " type..." ); \ + bool ex_caught = false; \ + __TBB_TRY { \ + tbb::internal::throw_exception( tbb::internal::id ); \ + } __TBB_CATCH ( type const & ) { \ + SAY( #type " exception caught." ); \ + ex_caught = true; \ + } __TBB_CATCH ( ... ) { \ + SAY( "Unexpected exception caught." ); \ + }; /* try */ \ + CHECK( ex_caught ); \ + } + CHECK_EXCEPTION( eid_bad_alloc, std::bad_alloc ); + CHECK_EXCEPTION( eid_bad_last_alloc, tbb::bad_last_alloc ); + CHECK_EXCEPTION( eid_nonpositive_step, std::invalid_argument ); + CHECK_EXCEPTION( eid_out_of_range, std::out_of_range ); + CHECK_EXCEPTION( eid_segment_range_error, std::range_error ); + CHECK_EXCEPTION( eid_missing_wait, tbb::missing_wait ); + CHECK_EXCEPTION( eid_invalid_multiple_scheduling, tbb::invalid_multiple_scheduling ); + CHECK_EXCEPTION( eid_improper_lock, tbb::improper_lock ); + CHECK_EXCEPTION( eid_possible_deadlock, std::runtime_error ); + CHECK_EXCEPTION( eid_reservation_length_error, std::length_error ); + #undef CHECK_EXCEPTION + { + bool ex_caught = false; + __TBB_TRY { + tbb::internal::handle_perror( EAGAIN, "apple" ); + } __TBB_CATCH ( std::runtime_error const & ) { + SAY( "Expected exception caught." ); + ex_caught = true; + } __TBB_CATCH ( ... ) { + SAY( "Unexpected exception caught." ); + }; // try + CHECK( ex_caught ); + } + }; // if + } + + { + SAY( "Test multiple proxies." ); + char const * path[] = { ".", NULL }; + tbb::runtime_loader rtl0( tbb::runtime_loader::em_status ); + tbb::runtime_loader rtl1( tbb::runtime_loader::em_status ); + CHECK( rtl0.status() == tbb::runtime_loader::ec_ok ); + CHECK( rtl1.status() == tbb::runtime_loader::ec_ok ); + SAY( "Load current version with the first rtl." ); + rtl0.load( path ); + CHECK( rtl0.status() == tbb::runtime_loader::ec_ok ); + CHECK_TBB_IS_LOADED(); + SAY( "Load another version with the second proxy, it should return a error." ); + rtl1.load( path, TBB_INTERFACE_VERSION + 1 ); + CHECK( rtl1.status() == tbb::runtime_loader::ec_bad_ver ); + SAY( "Load the same version with the second proxy, it should return ok." ); + rtl1.load( path ); + CHECK( rtl1.status() == tbb::runtime_loader::ec_ok ); + CHECK_TBB_IS_LOADED(); + } + + } __TBB_CATCH( ... ) { + + ASSERT( 0, "unexpected exception" ); + + }; // __TBB_TRY + + if ( errors > 0 ) { + REPORT( "Some tests failed.\n" ); + exit( 1 ); + }; // if + + return Harness::Done; + +} // main + +#endif // !(_WIN32||_WIN64) + +// end of file // diff --git a/src/tbb/src/test/test_rwm_upgrade_downgrade.cpp b/src/tbb/src/test/test_rwm_upgrade_downgrade.cpp new file mode 100644 index 0000000..4525fe1 --- /dev/null +++ b/src/tbb/src/test/test_rwm_upgrade_downgrade.cpp @@ -0,0 +1,79 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/queuing_rw_mutex.h" +#include "tbb/spin_rw_mutex.h" +#include "harness.h" + +using namespace tbb; + +volatile int Count; + +template<typename RWMutex> +struct Hammer: NoAssign { + RWMutex &MutexProtectingCount; + mutable volatile int dummy; + + Hammer(RWMutex &m): MutexProtectingCount(m) {} + void operator()( int /*thread_id*/ ) const { + for( int j=0; j<100000; ++j ) { + typename RWMutex::scoped_lock lock(MutexProtectingCount,false); + int c = Count; + for( int k=0; k<10; ++k ) { + ++dummy; + } + if( lock.upgrade_to_writer() ) { + // The upgrade succeeded without any intervening writers + ASSERT( c==Count, "another thread modified Count while I held a read lock" ); + } else { + c = Count; + } + for( int k=0; k<10; ++k ) { + ++Count; + } + lock.downgrade_to_reader(); + for( int k=0; k<10; ++k ) { + ++dummy; + } + } + } +}; + +queuing_rw_mutex QRW_mutex; +spin_rw_mutex SRW_mutex; + +int TestMain () { + for( int p=MinThread; p<=MaxThread; ++p ) { + REMARK("Testing on %d threads", p); + Count = 0; + NativeParallelFor( p, Hammer<queuing_rw_mutex>(QRW_mutex) ); + Count = 0; + NativeParallelFor( p, Hammer<spin_rw_mutex>(SRW_mutex) ); + } + return Harness::Done; +} diff --git a/src/tbb/src/test/test_semaphore.cpp b/src/tbb/src/test/test_semaphore.cpp new file mode 100644 index 0000000..5cb520b --- /dev/null +++ b/src/tbb/src/test/test_semaphore.cpp @@ -0,0 +1,297 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// +// Test for counting semaphore. +// +// set semaphore to N +// create N + M threads +// have each thread +// A. P() +// B. increment atomic count +// C. spin for awhile checking the value of the count; make sure it doesn't exceed N +// D. decrement atomic count +// E. V() +// + +#include "../tbb/semaphore.h" +#include "tbb/atomic.h" +#include "tbb/blocked_range.h" + +#include <vector> +using std::vector; + +#include "harness_assert.h" +#include "harness.h" + +using tbb::internal::semaphore; + +#include "harness_barrier.h" + +tbb::atomic<int> pCount; + +Harness::SpinBarrier sBarrier; + +#include "tbb/tick_count.h" +// semaphore basic function: +// set semaphore to initial value +// see that semaphore only allows that number of threads to be active +class Body: NoAssign { + const int nThreads; + const int nIters; + tbb::internal::semaphore &mySem; + vector<int> &ourCounts; + vector<double> &tottime; + static const int tickCounts = 1; // millisecond + static const int innerWait = 5; // millisecond +public: + Body(int nThread_, int nIter_, semaphore &mySem_, + vector<int>& ourCounts_, + vector<double>& tottime_ + ) : nThreads(nThread_), nIters(nIter_), mySem(mySem_), ourCounts(ourCounts_), tottime(tottime_) { sBarrier.initialize(nThread_); pCount = 0; } +void operator()(const int tid) const { + sBarrier.wait(); + for(int i=0; i < nIters; ++i) { + Harness::Sleep( tid * tickCounts ); + tbb::tick_count t0 = tbb::tick_count::now(); + mySem.P(); + tbb::tick_count t1 = tbb::tick_count::now(); + tottime[tid] += (t1-t0).seconds(); + int curval = ++pCount; + if(curval > ourCounts[tid]) ourCounts[tid] = curval; + Harness::Sleep( innerWait ); + --pCount; + ASSERT((int)pCount >= 0, NULL); + mySem.V(); + } +} +}; + + +void testSemaphore( int semInitCnt, int extraThreads ) { + semaphore my_sem(semInitCnt); + // tbb::task_scheduler_init init(tbb::task_scheduler_init::deferred); + int nThreads = semInitCnt + extraThreads; + vector<int> maxVals(nThreads); + vector<double> totTimes(nThreads); + int nIters = 10; + Body myBody(nThreads, nIters, my_sem, maxVals, totTimes); + + REMARK( " sem(%d) with %d extra threads\n", semInitCnt, extraThreads); + pCount = 0; + NativeParallelFor(nThreads, myBody); + if(extraThreads == 0) { + double allPWaits = 0; + for(vector<double>::const_iterator j = totTimes.begin(); j != totTimes.end(); ++j) { + allPWaits += *j; + } + allPWaits /= static_cast<double>(nThreads * nIters); + REMARK("Average wait for P() in uncontested case for nThreads = %d is %g\n", nThreads, allPWaits); + } + ASSERT(!pCount, "not all threads decremented pCount"); + int maxCount = -1; + for(vector<int>::const_iterator i=maxVals.begin(); i!= maxVals.end();++i) { + maxCount = max(maxCount,*i); + } + ASSERT(maxCount <= semInitCnt,"too many threads in semaphore-protected increment"); + if(maxCount < semInitCnt) { + REMARK("Not enough threads in semaphore-protected region (%d < %d)\n", static_cast<int>(maxCount), semInitCnt); + } +} + +#include "../tbb/semaphore.cpp" +#if _WIN32||_WIN64 +#include "../tbb/dynamic_link.cpp" +#endif + +#define N_TIMES 1000 + +template<typename S> +struct Counter { + volatile long value; + S my_sem; + Counter() : value(0) {} +}; + +//! Function object for use with parallel_for.h. +template<typename C> +struct AddOne: NoAssign { + C& my_counter; + /** Increments counter once for each iteration in the iteration space. */ + void operator()( int /*tid*/ ) const { + for( size_t i=0; i<N_TIMES; ++i ) { + my_counter.my_sem.P(); + my_counter.value = my_counter.value + 1; + my_counter.my_sem.V(); + } + } + AddOne( C& c_ ) : my_counter(c_) { my_counter.my_sem.V(); } +}; + +void testBinarySemaphore( int nThreads ) { + REMARK("Testing binary semaphore\n"); + Counter<tbb::internal::binary_semaphore> counter; + AddOne<Counter<tbb::internal::binary_semaphore> > myAddOne(counter); + NativeParallelFor( nThreads, myAddOne ); + ASSERT( nThreads*N_TIMES==counter.value, "Binary semaphore operations P()/V() have a race"); +} + +// Power of 2, the most tokens that can be in flight. +#define MAX_TOKENS 32 +enum FilterType { imaProducer, imaConsumer }; +class FilterBase : NoAssign { +protected: + FilterType ima; + unsigned totTokens; // total number of tokens to be emitted, only used by producer + tbb::atomic<unsigned>& myTokens; + tbb::atomic<unsigned>& otherTokens; + unsigned myWait; + semaphore &mySem; + semaphore &nextSem; + unsigned* myBuffer; + unsigned* nextBuffer; + unsigned curToken; +public: + FilterBase( FilterType ima_ + ,unsigned totTokens_ + ,tbb::atomic<unsigned>& myTokens_ + ,tbb::atomic<unsigned>& otherTokens_ + ,unsigned myWait_ + ,semaphore &mySem_ + ,semaphore &nextSem_ + ,unsigned* myBuffer_ + ,unsigned* nextBuffer_ + ) + : ima(ima_),totTokens(totTokens_),myTokens(myTokens_),otherTokens(otherTokens_),myWait(myWait_),mySem(mySem_), + nextSem(nextSem_),myBuffer(myBuffer_),nextBuffer(nextBuffer_) + { + curToken = 0; + } + void Produce(const int tid); + void Consume(const int tid); + void operator()(const int tid) { if(ima == imaConsumer) Consume(tid); else Produce(tid); } +}; + +class ProduceConsumeBody { + FilterBase** myFilters; + public: + ProduceConsumeBody(FilterBase** myFilters_) : myFilters(myFilters_) {} + void operator()(const int tid) const { + myFilters[tid]->operator()(tid); + } +}; + +// send a bunch of non-Null "tokens" to consumer, then a NULL. +void FilterBase::Produce(const int /*tid*/) { + nextBuffer[0] = 0; // just in case we provide no tokens + sBarrier.wait(); + while(totTokens) { + while(!myTokens) + mySem.P(); + // we have a slot available. + --myTokens; // moving this down reduces spurious wakeups + --totTokens; + if(totTokens) + nextBuffer[curToken&(MAX_TOKENS-1)] = curToken*3+1; + else + nextBuffer[curToken&(MAX_TOKENS-1)] = (unsigned)NULL; + ++curToken; + Harness::Sleep(myWait); + unsigned temp = ++otherTokens; + if(temp == 1) + nextSem.V(); + } + nextSem.V(); // final wakeup +} + +void FilterBase::Consume(const int /*tid*/) { + unsigned myToken; + sBarrier.wait(); + do { + while(!myTokens) + mySem.P(); + // we have a slot available. + --myTokens; // moving this down reduces spurious wakeups + myToken = myBuffer[curToken&(MAX_TOKENS-1)]; + if(myToken) { + ASSERT(myToken == curToken*3+1, "Error in received token"); + ++curToken; + Harness::Sleep(myWait); + unsigned temp = ++otherTokens; + if(temp == 1) + nextSem.V(); + } + } while(myToken); + // end of processing + ASSERT(curToken + 1 == totTokens, "Didn't receive enough tokens"); +} + +// -- test of producer/consumer with atomic buffer cnt and semaphore +// nTokens are total number of tokens through the pipe +// pWait is the wait time for the producer +// cWait is the wait time for the consumer +void testProducerConsumer( unsigned totTokens, unsigned nTokens, unsigned pWait, unsigned cWait) { + semaphore pSem; + semaphore cSem; + tbb::atomic<unsigned> pTokens; + tbb::atomic<unsigned> cTokens; + cTokens = 0; + unsigned cBuffer[MAX_TOKENS]; + FilterBase* myFilters[2]; // one producer, one consumer + REMARK("Testing producer/consumer with %lu total tokens, %lu tokens at a time, producer wait(%lu), consumer wait (%lu)\n", totTokens, nTokens, pWait, cWait); + ASSERT(nTokens <= MAX_TOKENS, "Not enough slots for tokens"); + myFilters[0] = new FilterBase(imaProducer, totTokens, pTokens, cTokens, pWait, cSem, pSem, (unsigned *)NULL, &(cBuffer[0])); + myFilters[1] = new FilterBase(imaConsumer, totTokens, cTokens, pTokens, cWait, pSem, cSem, cBuffer, (unsigned *)NULL); + pTokens = nTokens; + ProduceConsumeBody myBody(myFilters); + sBarrier.initialize(2); + NativeParallelFor(2, myBody); + delete myFilters[0]; + delete myFilters[1]; +} + +int TestMain() { + REMARK("Started\n"); + if(MaxThread > 0) { + testBinarySemaphore( MaxThread ); + for(int semSize = 1; semSize <= MaxThread; ++semSize) { + for(int exThreads = 0; exThreads <= MaxThread - semSize; ++exThreads) { + testSemaphore( semSize, exThreads ); + } + } + } + // Test producer/consumer with varying execution times and buffer sizes + // ( total tokens, tokens in buffer, sleep for producer, sleep for consumer ) + testProducerConsumer( 10, 2, 5, 5 ); + testProducerConsumer( 10, 2, 20, 5 ); + testProducerConsumer( 10, 2, 5, 20 ); + testProducerConsumer( 10, 1, 5, 5 ); + testProducerConsumer( 20, 10, 5, 20 ); + testProducerConsumer( 64, 32, 1, 20 ); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_sequencer_node.cpp b/src/tbb/src/test/test_sequencer_node.cpp new file mode 100644 index 0000000..8444d32 --- /dev/null +++ b/src/tbb/src/test/test_sequencer_node.cpp @@ -0,0 +1,404 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "harness.h" +#include "tbb/flow_graph.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/tick_count.h" +#include "tbb/atomic.h" + +#include <cstdio> + +#define N 1000 +#define C 10 + +template< typename T > +struct seq_inspector { + size_t operator()(const T &v) const { return size_t(v); } +}; + +template< typename T > +bool wait_try_get( tbb::flow::graph &g, tbb::flow::sequencer_node<T> &q, T &value ) { + g.wait_for_all(); + return q.try_get(value); +} + +template< typename T > +void spin_try_get( tbb::flow::queue_node<T> &q, T &value ) { + while ( q.try_get(value) != true ) ; +} + +template< typename T > +struct parallel_puts : NoAssign { + + tbb::flow::sequencer_node<T> &my_q; + int my_num_threads; + + parallel_puts( tbb::flow::sequencer_node<T> &q, int num_threads ) : my_q(q), my_num_threads(num_threads) {} + + void operator()(int tid) const { + for (int j = tid; j < N; j+=my_num_threads) { + bool msg = my_q.try_put( T(j) ); + ASSERT( msg == true, NULL ); + } + } + +}; + +template< typename T > +struct touches { + + bool **my_touches; + T *my_last_touch; + int my_num_threads; + + touches( int num_threads ) : my_num_threads(num_threads) { + my_last_touch = new T[my_num_threads]; + my_touches = new bool* [my_num_threads]; + for ( int p = 0; p < my_num_threads; ++p) { + my_last_touch[p] = T(-1); + my_touches[p] = new bool[N]; + for ( int n = 0; n < N; ++n) + my_touches[p][n] = false; + } + } + + ~touches() { + for ( int p = 0; p < my_num_threads; ++p) { + delete [] my_touches[p]; + } + delete [] my_touches; + delete [] my_last_touch; + } + + bool check( int tid, T v ) { + if ( my_touches[tid][v] != false ) { + printf("Error: value seen twice by local thread\n"); + return false; + } + if ( v <= my_last_touch[tid] ) { + printf("Error: value seen in wrong order by local thread\n"); + return false; + } + my_last_touch[tid] = v; + my_touches[tid][v] = true; + return true; + } + + bool validate_touches() { + bool *all_touches = new bool[N]; + for ( int n = 0; n < N; ++n) + all_touches[n] = false; + + for ( int p = 0; p < my_num_threads; ++p) { + for ( int n = 0; n < N; ++n) { + if ( my_touches[p][n] == true ) { + ASSERT( all_touches[n] == false, "value see by more than one thread\n" ); + all_touches[n] = true; + } + } + } + for ( int n = 0; n < N; ++n) { + if ( !all_touches[n] ) + printf("No touch at %d, my_num_threads = %d\n", n, my_num_threads); + //ASSERT( all_touches[n] == true, "value not seen by any thread\n" ); + } + delete all_touches; + return true; + } + +}; + +template< typename T > +struct parallel_gets : NoAssign { + + tbb::flow::sequencer_node<T> &my_q; + int my_num_threads; + touches<T> &my_touches; + + parallel_gets( tbb::flow::sequencer_node<T> &q, int num_threads, touches<T> &t ) : my_q(q), my_num_threads(num_threads), my_touches(t) {} + + void operator()(int tid) const { + for (int j = tid; j < N; j+=my_num_threads) { + T v; + spin_try_get( my_q, v ); + my_touches.check( tid, v ); + } + } + +}; + +template< typename T > +struct parallel_put_get : NoAssign { + + tbb::flow::sequencer_node<T> &my_s1; + tbb::flow::sequencer_node<T> &my_s2; + int my_num_threads; + tbb::atomic< int > &my_counter; + touches<T> &my_touches; + + parallel_put_get( tbb::flow::sequencer_node<T> &s1, tbb::flow::sequencer_node<T> &s2, int num_threads, + tbb::atomic<int> &counter, touches<T> &t ) : my_s1(s1), my_s2(s2), my_num_threads(num_threads), my_counter(counter), my_touches(t) {} + + void operator()(int tid) const { + int i_start = 0; + + while ( (i_start = my_counter.fetch_and_add(C)) < N ) { + int i_end = ( N < i_start + C ) ? N : i_start + C; + for (int i = i_start; i < i_end; ++i) { + bool msg = my_s1.try_put( T(i) ); + ASSERT( msg == true, NULL ); + } + + for (int i = i_start; i < i_end; ++i) { + T v; + spin_try_get( my_s2, v ); + my_touches.check( tid, v ); + } + } + } + +}; + +// +// Tests +// +// multiple parallel senders, multiple receivers, properly sequenced (relative to receiver) at output +// chained sequencers, multiple parallel senders, multiple receivers, properly sequenced (relative to receiver) at output +// + +template< typename T > +int test_parallel(int num_threads) { + tbb::flow::graph g; + + tbb::flow::sequencer_node<T> s(g, seq_inspector<T>()); + NativeParallelFor( num_threads, parallel_puts<T>(s, num_threads) ); + { + touches<T> t( num_threads ); + NativeParallelFor( num_threads, parallel_gets<T>(s, num_threads, t) ); + g.wait_for_all(); + ASSERT( t.validate_touches(), NULL ); + } + T bogus_value(-1); + T j = bogus_value; + ASSERT( s.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + g.wait_for_all(); + + tbb::flow::sequencer_node<T> s1(g, seq_inspector<T>()); + tbb::flow::sequencer_node<T> s2(g, seq_inspector<T>()); + tbb::flow::sequencer_node<T> s3(g, seq_inspector<T>()); + tbb::flow::make_edge( s1, s2 ); + tbb::flow::make_edge( s2, s3 ); + + { + touches<T> t( num_threads ); + tbb::atomic<int> counter; + counter = 0; + NativeParallelFor( num_threads, parallel_put_get<T>(s1, s3, num_threads, counter, t) ); + g.wait_for_all(); + t.validate_touches(); + } + g.wait_for_all(); + ASSERT( s1.try_get( j ) == false, NULL ); + g.wait_for_all(); + ASSERT( s2.try_get( j ) == false, NULL ); + g.wait_for_all(); + ASSERT( s3.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + // test copy constructor + tbb::flow::sequencer_node<T> s_copy(s); + NativeParallelFor( num_threads, parallel_puts<T>(s_copy, num_threads) ); + for (int i = 0; i < N; ++i) { + j = bogus_value; + spin_try_get( s_copy, j ); + ASSERT( i == j, NULL ); + } + j = bogus_value; + g.wait_for_all(); + ASSERT( s_copy.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + return 0; +} + + +// +// Tests +// +// No predecessors can be registered +// Request from empty buffer fails +// In-order puts, single sender, single receiver, properly sequenced at output +// Reverse-order puts, single sender, single receiver, properly sequenced at output +// Chained sequencers (3), in-order and reverse-order tests, properly sequenced at output +// + +template< typename T > +int test_serial() { + tbb::flow::graph g; + T bogus_value(-1); + + tbb::flow::sequencer_node<T> s(g, seq_inspector<T>()); + tbb::flow::sequencer_node<T> s2(g, seq_inspector<T>()); + T j = bogus_value; + + // + // Rejects attempts to add / remove predecessor + // Rejects request from empty Q + // + ASSERT( s.register_predecessor( s2 ) == false, NULL ); + ASSERT( s.remove_predecessor( s2 ) == false, NULL ); + ASSERT( s.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + // + // In-order simple puts and gets + // + + for (int i = 0; i < N; ++i) { + bool msg = s.try_put( T(i) ); + ASSERT( msg == true, NULL ); + } + + + for (int i = 0; i < N; ++i) { + j = bogus_value; + ASSERT(wait_try_get( g, s, j ) == true, NULL); + ASSERT( i == j, NULL ); + } + j = bogus_value; + g.wait_for_all(); + ASSERT( s.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + // + // Reverse-order simple puts and gets + // + + for (int i = N-1; i >= 0; --i) { + bool msg = s2.try_put( T(i) ); + ASSERT( msg == true, NULL ); + } + + for (int i = 0; i < N; ++i) { + j = bogus_value; + ASSERT(wait_try_get( g, s2, j ) == true, NULL); + ASSERT( i == j, NULL ); + } + j = bogus_value; + g.wait_for_all(); + ASSERT( s2.try_get( j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + // + // Chained in-order simple puts and gets + // + + tbb::flow::sequencer_node<T> s3(g, seq_inspector<T>()); + tbb::flow::sequencer_node<T> s4(g, seq_inspector<T>()); + tbb::flow::sequencer_node<T> s5(g, seq_inspector<T>()); + tbb::flow::make_edge( s3, s4 ); + tbb::flow::make_edge( s4, s5 ); + + for (int i = 0; i < N; ++i) { + bool msg = s3.try_put( T(i) ); + ASSERT( msg == true, NULL ); + } + + for (int i = 0; i < N; ++i) { + j = bogus_value; + ASSERT(wait_try_get( g, s5, j ) == true, NULL); + ASSERT( i == j, NULL ); + } + j = bogus_value; + ASSERT( wait_try_get( g, s3, j ) == false, NULL ); + ASSERT( wait_try_get( g, s4, j ) == false, NULL ); + ASSERT( wait_try_get( g, s5, j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + g.wait_for_all(); + tbb::flow::remove_edge( s3, s4 ); + ASSERT( s3.try_put( N ) == true, NULL ); + ASSERT( wait_try_get( g, s4, j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + ASSERT( wait_try_get( g, s5, j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + ASSERT( wait_try_get( g, s3, j ) == true, NULL ); + ASSERT( j == N, NULL ); + + // + // Chained reverse-order simple puts and gets + // + + tbb::flow::sequencer_node<T> s6(g, seq_inspector<T>()); + tbb::flow::sequencer_node<T> s7(g, seq_inspector<T>()); + tbb::flow::sequencer_node<T> s8(g, seq_inspector<T>()); + tbb::flow::make_edge( s6, s7 ); + tbb::flow::make_edge( s7, s8 ); + + for (int i = N-1; i >= 0; --i) { + bool msg = s6.try_put( T(i) ); + ASSERT( msg == true, NULL ); + } + + for (int i = 0; i < N; ++i) { + j = bogus_value; + ASSERT( wait_try_get( g, s8, j ) == true, NULL ); + ASSERT( i == j, NULL ); + } + j = bogus_value; + ASSERT( wait_try_get( g, s6, j ) == false, NULL ); + ASSERT( wait_try_get( g, s7, j ) == false, NULL ); + ASSERT( wait_try_get( g, s8, j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + + g.wait_for_all(); + tbb::flow::remove_edge( s6, s7 ); + ASSERT( s6.try_put( N ) == true, NULL ); + ASSERT( wait_try_get( g, s7, j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + ASSERT( wait_try_get( g, s8, j ) == false, NULL ); + ASSERT( j == bogus_value, NULL ); + ASSERT( wait_try_get( g, s6, j ) == true, NULL ); + ASSERT( j == N, NULL ); + + return 0; +} + +int TestMain() { + tbb::tick_count start = tbb::tick_count::now(), stop; + for (int p = 1; p < 4; ++p) { + tbb::task_scheduler_init init(p); + test_serial<int>(); + test_parallel<int>(p); + } + stop = tbb::tick_count::now(); + REMARK("Sequencer_Node Time=%6.6f\n", (stop-start).seconds()); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_source_node.cpp b/src/tbb/src/test/test_source_node.cpp new file mode 100644 index 0000000..b9c0b1b --- /dev/null +++ b/src/tbb/src/test/test_source_node.cpp @@ -0,0 +1,157 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "harness_graph.h" + +#include "tbb/task_scheduler_init.h" + +const int N = 1000; + +template< typename T > +class test_push_receiver : public tbb::flow::receiver<T> { + + tbb::atomic<int> my_counters[N]; + +public: + + test_push_receiver() { + for (int i = 0; i < N; ++i ) + my_counters[i] = 0; + } + + int get_count( int i ) { + int v = my_counters[i]; + return v; + } + + bool try_put( const T &v ) { + int i = (int)v; + ++my_counters[i]; + return true; + } + +}; + +template< typename T > +class source_body { + + tbb::atomic<int> my_count; + +public: + + source_body() { my_count = 0; } + + bool operator()( T &v ) { + v = (T)my_count.fetch_and_increment(); + if ( (int)v < N ) + return true; + else + return false; + } + +}; + +template< typename T > +class function_body { + + tbb::atomic<int> *my_counters; + +public: + + function_body( tbb::atomic<int> *counters ) : my_counters(counters) { + for (int i = 0; i < N; ++i ) + my_counters[i] = 0; + } + + bool operator()( T v ) { + ++my_counters[(int)v]; + return true; + } + +}; + +template< typename T > +void test_single_dest() { + + // push only + tbb::flow::graph g; + tbb::flow::source_node<T> src(g, source_body<T>() ); + test_push_receiver<T> dest; + tbb::flow::make_edge( src, dest ); + g.wait_for_all(); + for (int i = 0; i < N; ++i ) { + ASSERT( dest.get_count(i) == 1, NULL ); + } + + // push only + tbb::atomic<int> counters3[N]; + tbb::flow::source_node<T> src3(g, source_body<T>() ); + function_body<T> b3( counters3 ); + tbb::flow::function_node<T,bool> dest3(g, tbb::flow::unlimited, b3 ); + tbb::flow::make_edge( src3, dest3 ); + g.wait_for_all(); + for (int i = 0; i < N; ++i ) { + int v = counters3[i]; + ASSERT( v == 1, NULL ); + } + + // push & pull + tbb::flow::source_node<T> src2(g, source_body<T>() ); + tbb::atomic<int> counters2[N]; + function_body<T> b2( counters2 ); + tbb::flow::function_node<T,bool> dest2(g, tbb::flow::serial, b2 ); + tbb::flow::make_edge( src2, dest2 ); + g.wait_for_all(); + for (int i = 0; i < N; ++i ) { + int v = counters2[i]; + ASSERT( v == 1, NULL ); + } + + // test copy constructor + tbb::flow::source_node<T> src_copy(src); + test_push_receiver<T> dest_c; + ASSERT( src_copy.register_successor(dest_c), NULL ); + g.wait_for_all(); + for (int i = 0; i < N; ++i ) { + ASSERT( dest_c.get_count(i) == 1, NULL ); + } +} + +int TestMain() { + if( MinThread<1 ) { + REPORT("number of threads must be positive\n"); + exit(1); + } + for ( int p = MinThread; p < MaxThread; ++p ) { + tbb::task_scheduler_init init(p); + test_single_dest<int>(); + test_single_dest<float>(); + } + return Harness::Done; +} + diff --git a/src/tbb/src/test/test_split_node.cpp b/src/tbb/src/test/test_split_node.cpp new file mode 100644 index 0000000..e7853c6 --- /dev/null +++ b/src/tbb/src/test/test_split_node.cpp @@ -0,0 +1,363 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if _MSC_VER +#pragma warning (disable : 4503) // decorated name length exceeded, name was truncated +#endif + +#include "harness.h" +#define TBB_PREVIEW_GRAPH_NODES 1 +#include "tbb/flow_graph.h" +#include "tbb/task_scheduler_init.h" + +#if !__SUNPRO_CC + +// +// Tests +// + +const int Count = 300; +const int MaxPorts = 10; +const int MaxNSources = 5; // max # of source_nodes to register for each split_node input in parallel test + +std::vector<bool> flags; // for checking output + +template<typename T> +class name_of { +public: + static const char* name() { return "Unknown"; } +}; +template<> +class name_of<int> { +public: + static const char* name() { return "int"; } +}; +template<> +class name_of<float> { +public: + static const char* name() { return "float"; } +}; +template<> +class name_of<double> { +public: + static const char* name() { return "double"; } +}; +template<> +class name_of<long> { +public: + static const char* name() { return "long"; } +}; +template<> +class name_of<short> { +public: + static const char* name() { return "short"; } +}; + +// T must be arithmetic, and shouldn't wrap around for reasonable sizes of Count (which is now 150, and maxPorts is 10, +// so the max number generated right now is 1500 or so.) Source will generate a series of TT with value +// (init_val + (i-1)*addend) * my_mult, where i is the i-th invocation of the body. We are attaching addend +// source nodes to a join_port, and each will generate part of the numerical series the port is expecting +// to receive. If there is only one source node, the series order will be maintained; if more than one, +// this is not guaranteed. + +template<int N> +struct tuple_helper { + template<typename TupleType> + static void set_element( TupleType &t, int i) { + std::get<N-1>(t) = (typename std::tuple_element<N-1,TupleType>::type)(i * (N+1)); + tuple_helper<N-1>::set_element(t, i); + } +}; + +template<> +struct tuple_helper<1> { + template<typename TupleType> + static void set_element(TupleType &t, int i) { + std::get<0>(t) = (typename std::tuple_element<0,TupleType>::type)(i * 2); + } +}; + +// if we start N source_bodys they will all have the addend N, and my_count should be initialized to 0 .. N-1. +// the output tuples should have all the sequence, but the order will in general vary. +template<typename TupleType> +class source_body { + typedef TupleType TT; + static const int N = std::tuple_size<TT>::value; + int my_count; + const int addend; + source_body& operator=( const source_body& other); +public: + source_body(int init_val, int addto) : my_count(init_val), addend(addto) { } + bool operator()( TT &v) { + if(my_count >= Count) return false; + tuple_helper<N>::set_element(v, my_count); + my_count += addend; + return true; + } +}; + +// allocator for split_node. + +template<int N, typename SType> +class makeSplit { +public: + static SType *create(tbb::flow::graph& g) { + SType *temp = new SType(g); + return temp; + } + static void destroy(SType *p) { delete p; } +}; + +// holder for sink_node pointers for eventual deletion + +static void* all_sink_nodes[MaxPorts]; + + +template<int ELEM, typename SType> +class sink_node_helper { +public: + typedef typename SType::input_type TT; + typedef typename std::tuple_element<ELEM-1,TT>::type IT; + typedef typename tbb::flow::queue_node<IT> my_sink_node_type; + static void print_parallel_remark() { + sink_node_helper<ELEM-1,SType>::print_parallel_remark(); + REMARK(", %s", name_of<IT>::name()); + } + static void print_serial_remark() { + sink_node_helper<ELEM-1,SType>::print_serial_remark(); + REMARK(", %s", name_of<IT>::name()); + } + static void add_sink_nodes(SType &my_split, tbb::flow::graph &g) { + my_sink_node_type *new_node = new my_sink_node_type(g); + tbb::flow::make_edge( tbb::flow::output_port<ELEM-1>(my_split) , *new_node); + all_sink_nodes[ELEM-1] = (void *)new_node; + sink_node_helper<ELEM-1, SType>::add_sink_nodes(my_split, g); + } + + static void check_sink_values() { + my_sink_node_type *dp = reinterpret_cast<my_sink_node_type *>(all_sink_nodes[ELEM-1]); + for(int i = 0; i < Count; ++i) { + IT v; + ASSERT(dp->try_get(v), NULL); + flags[((int)v) / (ELEM+1)] = true; + } + for(int i = 0; i < Count; ++i) { + ASSERT(flags[i], NULL); + flags[i] = false; // reset for next test + } + sink_node_helper<ELEM-1,SType>::check_sink_values(); + } + static void remove_sink_nodes(SType& my_split) { + my_sink_node_type *dp = reinterpret_cast<my_sink_node_type *>(all_sink_nodes[ELEM-1]); + tbb::flow::remove_edge( tbb::flow::output_port<ELEM-1>(my_split) , *dp); + delete dp; + sink_node_helper<ELEM-1, SType>::remove_sink_nodes(my_split); + } +}; + +template<typename SType> +class sink_node_helper<1, SType> { + typedef typename SType::input_type TT; + typedef typename std::tuple_element<0,TT>::type IT; + typedef typename tbb::flow::queue_node<IT> my_sink_node_type; +public: + static void print_parallel_remark() { + REMARK("Parallel test of split_node< %s", name_of<IT>::name()); + } + static void print_serial_remark() { + REMARK("Serial test of split_node< %s", name_of<IT>::name()); + } + static void add_sink_nodes(SType &my_split, tbb::flow::graph &g) { + my_sink_node_type *new_node = new my_sink_node_type(g); + tbb::flow::make_edge( tbb::flow::output_port<0>(my_split) , *new_node); + all_sink_nodes[0] = (void *)new_node; + } + static void check_sink_values() { + my_sink_node_type *dp = reinterpret_cast<my_sink_node_type *>(all_sink_nodes[0]); + for(int i = 0; i < Count; ++i) { + IT v; + ASSERT(dp->try_get(v), NULL); + flags[((int)v) / 2] = true; + } + for(int i = 0; i < Count; ++i) { + ASSERT(flags[i], NULL); + flags[i] = false; // reset for next test + } + } + static void remove_sink_nodes(SType& my_split) { + my_sink_node_type *dp = reinterpret_cast<my_sink_node_type *>(all_sink_nodes[0]); + tbb::flow::remove_edge( tbb::flow::output_port<0>(my_split) , *dp); + delete dp; + } +}; + +// parallel_test: create source_nodes that feed tuples into the split node +// and queue_nodes that receive the output. +template<typename SType> +class parallel_test { +public: + typedef typename SType::input_type TType; + typedef tbb::flow::source_node<TType> source_type; + static const int N = std::tuple_size<TType>::value; + static void test() { + TType v; + source_type* all_source_nodes[MaxNSources]; + sink_node_helper<N,SType>::print_parallel_remark(); + REMARK(" >\n"); + for(int i=0; i < MaxPorts; ++i) { + all_sink_nodes[i] = NULL; + } + // try test for # sources 1 .. MaxNSources + for(int nInputs = 1; nInputs <= MaxNSources; ++nInputs) { + tbb::flow::graph g; + SType* my_split = makeSplit<N,SType>::create(g); + + // add sinks first so when sources start spitting out values they are there to catch them + sink_node_helper<N, SType>::add_sink_nodes((*my_split), g); + + // now create nInputs source_nodes, each spitting out i, i+nInputs, i+2*nInputs ... + // each element of the tuple is i*(n+1), where n is the tuple element index (1-N) + for(int i = 0; i < nInputs; ++i) { + // create source node + source_type *s = new source_type(g, source_body<TType>(i, nInputs) ); + tbb::flow::make_edge(*s, *my_split); + all_source_nodes[i] = s; + } + + g.wait_for_all(); + + // check that we got Count values in each output queue, and all the index values + // are there. + sink_node_helper<N, SType>::check_sink_values(); + + sink_node_helper<N, SType>::remove_sink_nodes(*my_split); + for(int i = 0; i < nInputs; ++i) { + delete all_source_nodes[i]; + } + makeSplit<N,SType>::destroy(my_split); + } + } +}; + +// +// Single predecessor, single accepting successor at each port + +template<typename SType> +void test_one_serial( SType &my_split, tbb::flow::graph &g) { + typedef typename SType::input_type TType; + static const int SIZE = std::tuple_size<TType>::value; + sink_node_helper<SIZE, SType>::add_sink_nodes(my_split,g); + typedef TType q3_input_type; + tbb::flow::queue_node< q3_input_type > q3(g); + + tbb::flow::make_edge( q3, my_split ); + + // fill the queue with its value one-at-a-time + flags.clear(); + for (int i = 0; i < Count; ++i ) { + TType v; + tuple_helper<SIZE>::set_element(v, i); + ASSERT(my_split.try_put(v), NULL); + flags.push_back(false); + } + + g.wait_for_all(); + + sink_node_helper<SIZE,SType>::check_sink_values(); + + sink_node_helper<SIZE, SType>::remove_sink_nodes(my_split); + +} + +template<typename SType> +class serial_test { + typedef typename SType::input_type TType; + static const int SIZE = std::tuple_size<TType>::value; + static const int ELEMS = 3; +public: +static void test() { + tbb::flow::graph g; + flags.reserve(Count); + SType* my_split = makeSplit<SIZE,SType>::create(g); + sink_node_helper<SIZE, SType>::print_serial_remark(); REMARK(" >\n"); + + test_one_serial<SType>( *my_split, g); + // build the vector with copy construction from the used split node. + std::vector<SType>split_vector(ELEMS, *my_split); + // destroy the tired old split_node in case we're accidentally reusing pieces of it. + makeSplit<SIZE,SType>::destroy(my_split); + + + for(int e = 0; e < ELEMS; ++e) { // exercise each of the vector elements + test_one_serial<SType>( split_vector[e], g); + } +} + +}; // serial_test + +template< + template<typename> class TestType, // serial_test or parallel_test + typename TupleType > // type of the input of the split +struct generate_test { + typedef tbb::flow::split_node<TupleType> split_node_type; + static void do_test() { + TestType<split_node_type>::test(); + } +}; // generate_test + +int TestMain() { +#if __TBB_USE_TBB_TUPLE + REMARK(" Using TBB tuple\n"); +#else + REMARK(" Using platform tuple\n"); +#endif + for (int p = 0; p < 2; ++p) { + generate_test<serial_test, std::tuple<float, double> >::do_test(); + generate_test<serial_test, std::tuple<float, double, int, long> >::do_test(); + generate_test<serial_test, std::tuple<double, double, int, long, int, short> >::do_test(); +#if COMPREHENSIVE_TEST + generate_test<serial_test, std::tuple<float, double, double, double, float, int, float, long> >::do_test(); + generate_test<serial_test, std::tuple<float, double, int, double, double, float, long, int, float, long> >::do_test(); +#endif + generate_test<parallel_test, std::tuple<float, double> >::do_test(); + generate_test<parallel_test, std::tuple<float, int, long> >::do_test(); + generate_test<parallel_test, std::tuple<double, double, int, int, short> >::do_test(); +#if COMPREHENSIVE_TEST + generate_test<parallel_test, std::tuple<float, int, double, float, long, float, long> >::do_test(); + generate_test<parallel_test, std::tuple<float, double, int, double, double, long, int, float, long> >::do_test(); +#endif + } + return Harness::Done; +} +#else // __SUNPRO_CC + +int TestMain() { + return Harness::Skipped; +} + +#endif // SUNPRO_CC diff --git a/src/tbb/src/test/test_std_thread.cpp b/src/tbb/src/test/test_std_thread.cpp new file mode 100644 index 0000000..f8626c1 --- /dev/null +++ b/src/tbb/src/test/test_std_thread.cpp @@ -0,0 +1,41 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#define TBB_IMPLEMENT_CPP0X 1 +#include "tbb/compat/thread" +#define THREAD std::thread +#define THIS_THREAD std::this_thread +#define THIS_THREAD_SLEEP THIS_THREAD::sleep_for +#include "test_thread.h" +#include "harness.h" + +int TestMain () { + CheckSignatures(); + RunTests(); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_task.cpp b/src/tbb/src/test/test_task.cpp new file mode 100644 index 0000000..a3ee377 --- /dev/null +++ b/src/tbb/src/test/test_task.cpp @@ -0,0 +1,809 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "harness_task.h" +#include "tbb/atomic.h" +#include "tbb/tbb_thread.h" +#include "tbb/task_scheduler_init.h" +#include <cstdlib> + +//------------------------------------------------------------------------ +// Test for task::spawn_children and task_list +//------------------------------------------------------------------------ + +class UnboundedlyRecursiveOnUnboundedStealingTask : public tbb::task { + typedef UnboundedlyRecursiveOnUnboundedStealingTask this_type; + + this_type *m_Parent; + const int m_Depth; + volatile bool m_GoAhead; + + // Well, virtually unboundedly, for any practical purpose + static const int max_depth = 1000000; + +public: + UnboundedlyRecursiveOnUnboundedStealingTask( this_type *parent_ = NULL, int depth_ = max_depth ) + : m_Parent(parent_) + , m_Depth(depth_) + , m_GoAhead(true) + {} + + /*override*/ + tbb::task* execute() { + // Using large padding array speeds up reaching stealing limit + const int paddingSize = 16 * 1024; + volatile char padding[paddingSize]; + if( !m_Parent || (m_Depth > 0 && m_Parent->m_GoAhead) ) { + if ( m_Parent ) { + // We are stolen, let our parent start waiting for us + m_Parent->m_GoAhead = false; + } + tbb::task &t = *new( allocate_child() ) this_type(this, m_Depth - 1); + set_ref_count( 2 ); + spawn( t ); + // Give a willing thief a chance to steal + for( int i = 0; i < 1000000 && m_GoAhead; ++i ) { + ++padding[i % paddingSize]; + __TBB_Yield(); + } + // If our child has not been stolen yet, then prohibit it siring ones + // of its own (when this thread executes it inside the next wait_for_all) + m_GoAhead = false; + wait_for_all(); + } + return NULL; + } +}; // UnboundedlyRecursiveOnUnboundedStealingTask + +tbb::atomic<int> Count; + +class RecursiveTask: public tbb::task { + const int m_ChildCount; + const int m_Depth; + //! Spawn tasks in list. Exact method depends upon m_Depth&bit_mask. + void SpawnList( tbb::task_list& list, int bit_mask ) { + if( m_Depth&bit_mask ) { + // Take address to check that signature of spawn(task_list&) is static. + void (*s)(tbb::task_list&) = &tbb::task::spawn; + (*s)(list); + ASSERT( list.empty(), NULL ); + wait_for_all(); + } else { + spawn_and_wait_for_all(list); + ASSERT( list.empty(), NULL ); + } + } +public: + RecursiveTask( int child_count, int depth_ ) : m_ChildCount(child_count), m_Depth(depth_) {} + /*override*/ tbb::task* execute() { + ++Count; + if( m_Depth>0 ) { + tbb::task_list list; + ASSERT( list.empty(), NULL ); + for( int k=0; k<m_ChildCount; ++k ) { + list.push_back( *new( allocate_child() ) RecursiveTask(m_ChildCount/2,m_Depth-1 ) ); + ASSERT( !list.empty(), NULL ); + } + set_ref_count( m_ChildCount+1 ); + SpawnList( list, 1 ); + // Now try reusing this as the parent. + set_ref_count(2); + list.push_back( *new ( allocate_child() ) tbb::empty_task() ); + SpawnList( list, 2 ); + } + return NULL; + } +}; + +//! Compute what Count should be after RecursiveTask(child_count,depth) runs. +static int Expected( int child_count, int depth ) { + return depth<=0 ? 1 : 1+child_count*Expected(child_count/2,depth-1); +} + +void TestStealLimit( int nthread ) { +#if __TBB_DEFINE_MIC + REMARK( "skipping steal limiting heuristics for %d threads\n", nthread ); +#else// !_TBB_DEFINE_MIC + REMARK( "testing steal limiting heuristics for %d threads\n", nthread ); + tbb::task_scheduler_init init(nthread); + tbb::task &t = *new( tbb::task::allocate_root() ) UnboundedlyRecursiveOnUnboundedStealingTask(); + tbb::task::spawn_root_and_wait(t); +#endif// _TBB_DEFINE_MIC +} + +//! Test task::spawn( task_list& ) +void TestSpawnChildren( int nthread ) { + REMARK("testing task::spawn(task_list&) for %d threads\n",nthread); + tbb::task_scheduler_init init(nthread); + for( int j=0; j<50; ++j ) { + Count = 0; + RecursiveTask& p = *new( tbb::task::allocate_root() ) RecursiveTask(j,4); + tbb::task::spawn_root_and_wait(p); + int expected = Expected(j,4); + ASSERT( Count==expected, NULL ); + } +} + +//! Test task::spawn_root_and_wait( task_list& ) +void TestSpawnRootList( int nthread ) { + REMARK("testing task::spawn_root_and_wait(task_list&) for %d threads\n",nthread); + tbb::task_scheduler_init init(nthread); + for( int j=0; j<5; ++j ) + for( int k=0; k<10; ++k ) { + Count = 0; + tbb::task_list list; + for( int i=0; i<k; ++i ) + list.push_back( *new( tbb::task::allocate_root() ) RecursiveTask(j,4) ); + tbb::task::spawn_root_and_wait(list); + int expected = k*Expected(j,4); + ASSERT( Count==expected, NULL ); + } +} + +//------------------------------------------------------------------------ +// Test for task::recycle_as_safe_continuation +//------------------------------------------------------------------------ + +void TestSafeContinuation( int nthread ) { + REMARK("testing task::recycle_as_safe_continuation for %d threads\n",nthread); + tbb::task_scheduler_init init(nthread); + for( int j=8; j<33; ++j ) { + TaskGenerator& p = *new( tbb::task::allocate_root() ) TaskGenerator(j,5); + tbb::task::spawn_root_and_wait(p); + } +} + +//------------------------------------------------------------------------ +// Test affinity interface +//------------------------------------------------------------------------ +tbb::atomic<int> TotalCount; + +struct AffinityTask: public tbb::task { + const affinity_id expected_affinity_id; + bool noted; + /** Computing affinities is NOT supported by TBB, and may disappear in the future. + It is done here for sake of unit testing. */ + AffinityTask( int expected_affinity_id_ ) : + expected_affinity_id(affinity_id(expected_affinity_id_)), + noted(false) + { + set_affinity(expected_affinity_id); + ASSERT( 0u-expected_affinity_id>0u, "affinity_id not an unsigned integral type?" ); + ASSERT( affinity()==expected_affinity_id, NULL ); + } + /*override*/ tbb::task* execute() { + ++TotalCount; + return NULL; + } + /*override*/ void note_affinity( affinity_id id ) { + // There is no guarantee in TBB that a task runs on its affinity thread. + // However, the current implementation does accidentally guarantee it + // under certain conditions, such as the conditions here. + // We exploit those conditions for sake of unit testing. + ASSERT( id!=expected_affinity_id, NULL ); + ASSERT( !noted, "note_affinity_id called twice!" ); + ASSERT ( &self() == (tbb::task*)this, "Wrong innermost running task" ); + noted = true; + } +}; + +/** Note: This test assumes a lot about the internal implementation of affinity. + Do NOT use this as an example of good programming practice with TBB */ +void TestAffinity( int nthread ) { + TotalCount = 0; + int n = tbb::task_scheduler_init::default_num_threads(); + if( n>nthread ) + n = nthread; + tbb::task_scheduler_init init(n); + tbb::empty_task* t = new( tbb::task::allocate_root() ) tbb::empty_task; + tbb::task::affinity_id affinity_id = t->affinity(); + ASSERT( affinity_id==0, NULL ); + // Set ref_count for n-1 children, plus 1 for the wait. + t->set_ref_count(n); + // Spawn n-1 affinitized children. + for( int i=1; i<n; ++i ) + tbb::task::spawn( *new(t->allocate_child()) AffinityTask(i) ); + if( n>1 ) { + // Keep master from stealing + while( TotalCount!=n-1 ) + __TBB_Yield(); + } + // Wait for the children + t->wait_for_all(); + int k = 0; + GetTaskPtr(k)->destroy(*t); + ASSERT(k==1,NULL); +} + +struct NoteAffinityTask: public tbb::task { + bool noted; + NoteAffinityTask( int id ) : noted(false) + { + set_affinity(affinity_id(id)); + } + ~NoteAffinityTask () { + ASSERT (noted, "note_affinity has not been called"); + } + /*override*/ tbb::task* execute() { + return NULL; + } + /*override*/ void note_affinity( affinity_id /*id*/ ) { + noted = true; + ASSERT ( &self() == (tbb::task*)this, "Wrong innermost running task" ); + } +}; + +// This test checks one of the paths inside the scheduler by affinitizing the child task +// to non-existent thread so that it is proxied in the local task pool but not retrieved +// by another thread. +// If no workers requested, the extra slot #2 is allocated for a worker thread to serve +// "enqueued" tasks. In this test, it is used only for the affinity purpose. +void TestNoteAffinityContext() { + tbb::task_scheduler_init init(1); + tbb::empty_task* t = new( tbb::task::allocate_root() ) tbb::empty_task; + t->set_ref_count(2); + // This master in the absence of workers will have an affinity id of 1. + // So use another number to make the task get proxied. + tbb::task::spawn( *new(t->allocate_child()) NoteAffinityTask(2) ); + t->wait_for_all(); + tbb::task::destroy(*t); +} + +//------------------------------------------------------------------------ +// Test that recovery actions work correctly for task::allocate_* methods +// when a task's constructor throws an exception. +//------------------------------------------------------------------------ + +#if TBB_USE_EXCEPTIONS +static int TestUnconstructibleTaskCount; + +struct ConstructionFailure { +}; + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // Suppress pointless "unreachable code" warning. + #pragma warning (push) + #pragma warning (disable: 4702) +#endif + +//! Task that cannot be constructed. +template<size_t N> +struct UnconstructibleTask: public tbb::empty_task { + char space[N]; + UnconstructibleTask() { + throw ConstructionFailure(); + } +}; + +#if _MSC_VER && !defined(__INTEL_COMPILER) + #pragma warning (pop) +#endif + +#define TRY_BAD_CONSTRUCTION(x) \ + { \ + try { \ + new(x) UnconstructibleTask<N>; \ + } catch( const ConstructionFailure& ) { \ + ASSERT( parent()==original_parent, NULL ); \ + ASSERT( ref_count()==original_ref_count, "incorrectly changed ref_count" );\ + ++TestUnconstructibleTaskCount; \ + } \ + } + +template<size_t N> +struct RootTaskForTestUnconstructibleTask: public tbb::task { + tbb::task* execute() { + tbb::task* original_parent = parent(); + ASSERT( original_parent!=NULL, NULL ); + int original_ref_count = ref_count(); + TRY_BAD_CONSTRUCTION( allocate_root() ); + TRY_BAD_CONSTRUCTION( allocate_child() ); + TRY_BAD_CONSTRUCTION( allocate_continuation() ); + TRY_BAD_CONSTRUCTION( allocate_additional_child_of(*this) ); + return NULL; + } +}; + +template<size_t N> +void TestUnconstructibleTask() { + TestUnconstructibleTaskCount = 0; + tbb::task_scheduler_init init; + tbb::task* t = new( tbb::task::allocate_root() ) RootTaskForTestUnconstructibleTask<N>; + tbb::task::spawn_root_and_wait(*t); + ASSERT( TestUnconstructibleTaskCount==4, NULL ); +} +#endif /* TBB_USE_EXCEPTIONS */ + +//------------------------------------------------------------------------ +// Test for alignment problems with task objects. +//------------------------------------------------------------------------ + +#if _MSC_VER && !defined(__INTEL_COMPILER) + // Workaround for pointless warning "structure was padded due to __declspec(align()) + #pragma warning (push) + #pragma warning (disable: 4324) +#endif + +//! Task with members of type T. +/** The task recursively creates tasks. */ +template<typename T> +class TaskWithMember: public tbb::task { + T x; + T y; + unsigned char count; + /*override*/ tbb::task* execute() { + x = y; + if( count>0 ) { + set_ref_count(2); + tbb::task* t = new( allocate_child() ) TaskWithMember<T>(count-1); + spawn_and_wait_for_all(*t); + } + return NULL; + } +public: + TaskWithMember( unsigned char n ) : count(n) {} +}; + +#if _MSC_VER && !defined(__INTEL_COMPILER) + #pragma warning (pop) +#endif + +template<typename T> +void TestAlignmentOfOneClass() { + typedef TaskWithMember<T> task_type; + tbb::task* t = new( tbb::task::allocate_root() ) task_type(10); + tbb::task::spawn_root_and_wait(*t); +} + +#include "harness_m128.h" + +void TestAlignment() { + REMARK("testing alignment\n"); + tbb::task_scheduler_init init; + // Try types that have variety of alignments + TestAlignmentOfOneClass<char>(); + TestAlignmentOfOneClass<short>(); + TestAlignmentOfOneClass<int>(); + TestAlignmentOfOneClass<long>(); + TestAlignmentOfOneClass<void*>(); + TestAlignmentOfOneClass<float>(); + TestAlignmentOfOneClass<double>(); +#if HAVE_m128 + TestAlignmentOfOneClass<__m128>(); +#endif +#if HAVE_m256 + if (have_AVX()) TestAlignmentOfOneClass<__m256>(); +#endif +} + +//------------------------------------------------------------------------ +// Test for recursing on left while spawning on right +//------------------------------------------------------------------------ + +int Fib( int n ); + +struct RightFibTask: public tbb::task { + int* y; + const int n; + RightFibTask( int* y_, int n_ ) : y(y_), n(n_) {} + task* execute() { + *y = Fib(n-1); + return 0; + } +}; + +int Fib( int n ) { + if( n<2 ) { + return n; + } else { + // y actually does not need to be initialized. It is initialized solely to suppress + // a gratuitous warning "potentially uninitialized local variable". + int y=-1; + tbb::task* root_task = new( tbb::task::allocate_root() ) tbb::empty_task; + root_task->set_ref_count(2); + tbb::task::spawn( *new( root_task->allocate_child() ) RightFibTask(&y,n) ); + int x = Fib(n-2); + root_task->wait_for_all(); + tbb::task::destroy(*root_task); + return y+x; + } +} + +void TestLeftRecursion( int p ) { + REMARK("testing non-spawned roots for %d threads\n",p); + tbb::task_scheduler_init init(p); + int sum = 0; + for( int i=0; i<100; ++i ) + sum +=Fib(10); + ASSERT( sum==5500, NULL ); +} + +//------------------------------------------------------------------------ +// Test for computing with DAG of tasks. +//------------------------------------------------------------------------ + +class DagTask: public tbb::task { + typedef unsigned long long number_t; + const int i, j; + number_t sum_from_left, sum_from_above; + void check_sum( number_t sum ) { + number_t expected_sum = 1; + for( int k=i+1; k<=i+j; ++k ) + expected_sum *= k; + for( int k=1; k<=j; ++k ) + expected_sum /= k; + ASSERT(sum==expected_sum, NULL); + } +public: + DagTask *successor_to_below, *successor_to_right; + DagTask( int i_, int j_ ) : i(i_), j(j_), sum_from_left(0), sum_from_above(0) {} + task* execute() { + ASSERT( ref_count()==0, NULL ); + number_t sum = i==0 && j==0 ? 1 : sum_from_left+sum_from_above; + check_sum(sum); + ++execution_count; + if( DagTask* t = successor_to_right ) { + t->sum_from_left = sum; + if( t->decrement_ref_count()==0 ) + // Test using spawn to evaluate DAG + spawn( *t ); + } + if( DagTask* t = successor_to_below ) { + t->sum_from_above = sum; + if( t->decrement_ref_count()==0 ) + // Test using bypass to evaluate DAG + return t; + } + return NULL; + } + ~DagTask() {++destruction_count;} + static tbb::atomic<int> execution_count; + static tbb::atomic<int> destruction_count; +}; + +tbb::atomic<int> DagTask::execution_count; +tbb::atomic<int> DagTask::destruction_count; + +void TestDag( int p ) { + REMARK("testing evaluation of DAG for %d threads\n",p); + tbb::task_scheduler_init init(p); + DagTask::execution_count=0; + DagTask::destruction_count=0; + const int n = 10; + DagTask* a[n][n]; + for( int i=0; i<n; ++i ) + for( int j=0; j<n; ++j ) + a[i][j] = new( tbb::task::allocate_root() ) DagTask(i,j); + for( int i=0; i<n; ++i ) + for( int j=0; j<n; ++j ) { + a[i][j]->successor_to_below = i+1<n ? a[i+1][j] : NULL; + a[i][j]->successor_to_right = j+1<n ? a[i][j+1] : NULL; + a[i][j]->set_ref_count((i>0)+(j>0)); + } + a[n-1][n-1]->increment_ref_count(); + a[n-1][n-1]->spawn_and_wait_for_all(*a[0][0]); + ASSERT( DagTask::execution_count == n*n - 1, NULL ); + tbb::task::destroy(*a[n-1][n-1]); + ASSERT( DagTask::destruction_count > n*n - p, NULL ); + while ( DagTask::destruction_count != n*n ) + __TBB_Yield(); +} + +#include "harness_barrier.h" + +class RelaxedOwnershipTask: public tbb::task { + tbb::task &m_taskToSpawn, + &m_taskToDestroy, + &m_taskToExecute; + static Harness::SpinBarrier m_barrier; + + tbb::task* execute () { + tbb::task &p = *parent(); + tbb::task &r = *new( allocate_root() ) tbb::empty_task; + r.set_ref_count( 1 ); + m_barrier.wait(); + p.spawn( *new(p.allocate_child()) tbb::empty_task ); + p.spawn( *new(task::allocate_additional_child_of(p)) tbb::empty_task ); + p.spawn( m_taskToSpawn ); + p.destroy( m_taskToDestroy ); + r.spawn_and_wait_for_all( m_taskToExecute ); + p.destroy( r ); + return NULL; + } +public: + RelaxedOwnershipTask ( tbb::task& toSpawn, tbb::task& toDestroy, tbb::task& toExecute ) + : m_taskToSpawn(toSpawn) + , m_taskToDestroy(toDestroy) + , m_taskToExecute(toExecute) + {} + static void SetBarrier ( int numThreads ) { m_barrier.initialize( numThreads ); } +}; + +Harness::SpinBarrier RelaxedOwnershipTask::m_barrier; + +void TestRelaxedOwnership( int p ) { + if ( p < 2 ) + return; + + if( unsigned(p)>tbb::tbb_thread::hardware_concurrency() ) + return; + + REMARK("testing tasks exercising relaxed ownership freedom for %d threads\n", p); + tbb::task_scheduler_init init(p); + RelaxedOwnershipTask::SetBarrier(p); + tbb::task &r = *new( tbb::task::allocate_root() ) tbb::empty_task; + tbb::task_list tl; + for ( int i = 0; i < p; ++i ) { + tbb::task &tS = *new( r.allocate_child() ) tbb::empty_task, + &tD = *new( r.allocate_child() ) tbb::empty_task, + &tE = *new( r.allocate_child() ) tbb::empty_task; + tl.push_back( *new( r.allocate_child() ) RelaxedOwnershipTask(tS, tD, tE) ); + } + r.set_ref_count( 5 * p + 1 ); + int k=0; + GetTaskPtr(k)->spawn( tl ); + ASSERT(k==1,NULL); + r.wait_for_all(); + r.destroy( r ); +} + +//------------------------------------------------------------------------ +// Test for running TBB scheduler on user-created thread. +//------------------------------------------------------------------------ + +void RunSchedulerInstanceOnUserThread( int n_child ) { + tbb::task* e = new( tbb::task::allocate_root() ) tbb::empty_task; + e->set_ref_count(1+n_child); + for( int i=0; i<n_child; ++i ) + tbb::task::spawn( *new(e->allocate_child()) tbb::empty_task ); + e->wait_for_all(); + e->destroy(*e); +} + +void TestUserThread( int p ) { + tbb::task_scheduler_init init(p); + // Try with both 0 and 1 children. Only the latter scenario permits stealing. + for( int n_child=0; n_child<2; ++n_child ) { + tbb::tbb_thread t( RunSchedulerInstanceOnUserThread, n_child ); + t.join(); + } +} + +class TaskWithChildToSteal : public tbb::task { + const int m_Depth; + volatile bool m_GoAhead; + +public: + TaskWithChildToSteal( int depth_ ) + : m_Depth(depth_) + , m_GoAhead(false) + {} + + /*override*/ + tbb::task* execute() { + m_GoAhead = true; + if ( m_Depth > 0 ) { + TaskWithChildToSteal &t = *new( allocate_child() ) TaskWithChildToSteal(m_Depth - 1); + t.SpawnAndWaitOnParent(); + } + else + Harness::Sleep(50); // The last task in chain sleeps for 50 ms + return NULL; + } + + void SpawnAndWaitOnParent() { + parent()->set_ref_count( 2 ); + parent()->spawn( *this ); + while (!this->m_GoAhead ) + __TBB_Yield(); + parent()->wait_for_all(); + } +}; // TaskWithChildToSteal + +// Success criterion of this test is not hanging +void TestDispatchLoopResponsiveness() { + REMARK("testing that dispatch loops do not go into eternal sleep when all remaining children are stolen\n"); + // Recursion depth values test the following sorts of dispatch loops + // 0 - master's outermost + // 1 - worker's nested + // 2 - master's nested + tbb::task_scheduler_init init(2); + tbb::task &r = *new( tbb::task::allocate_root() ) tbb::empty_task; + for ( int depth = 0; depth < 3; ++depth ) { + TaskWithChildToSteal &t = *new( r.allocate_child() ) TaskWithChildToSteal(depth); + t.SpawnAndWaitOnParent(); + } + r.destroy(r); +} + +void TestWaitDiscriminativenessWithoutStealing() { + REMARK( "testing that task::wait_for_all is specific to the root it is called on (no workers)\n" ); + // The test relies on the strict LIFO scheduling order in the absence of workers + tbb::task_scheduler_init init(1); + tbb::task &r1 = *new( tbb::task::allocate_root() ) tbb::empty_task; + tbb::task &r2 = *new( tbb::task::allocate_root() ) tbb::empty_task; + const int NumChildren = 10; + r1.set_ref_count( NumChildren + 1 ); + r2.set_ref_count( NumChildren + 1 ); + for( int i=0; i < NumChildren; ++i ) { + tbb::empty_task &t1 = *new( r1.allocate_child() ) tbb::empty_task; + tbb::empty_task &t2 = *new( r2.allocate_child() ) tbb::empty_task; + tbb::task::spawn(t1); + tbb::task::spawn(t2); + } + r2.wait_for_all(); + ASSERT( r2.ref_count() <= 1, "Not all children of r2 executed" ); + ASSERT( r1.ref_count() > 1, "All children of r1 prematurely executed" ); + r1.wait_for_all(); + ASSERT( r1.ref_count() <= 1, "Not all children of r1 executed" ); + r1.destroy(r1); + r2.destroy(r2); +} + + +using tbb::internal::spin_wait_until_eq; + +//! Deterministic emulation of a long running task +class LongRunningTask : public tbb::task { + volatile bool& m_CanProceed; + + tbb::task* execute() { + spin_wait_until_eq( m_CanProceed, true ); + return NULL; + } +public: + LongRunningTask ( volatile bool& canProceed ) : m_CanProceed(canProceed) {} +}; + +void TestWaitDiscriminativenessWithStealing() { + if( tbb::tbb_thread::hardware_concurrency() < 2 ) + return; + REMARK( "testing that task::wait_for_all is specific to the root it is called on (one worker)\n" ); + volatile bool canProceed = false; + tbb::task_scheduler_init init(2); + tbb::task &r1 = *new( tbb::task::allocate_root() ) tbb::empty_task; + tbb::task &r2 = *new( tbb::task::allocate_root() ) tbb::empty_task; + r1.set_ref_count( 2 ); + r2.set_ref_count( 2 ); + tbb::task& t1 = *new( r1.allocate_child() ) tbb::empty_task; + tbb::task& t2 = *new( r2.allocate_child() ) LongRunningTask(canProceed); + tbb::task::spawn(t2); + tbb::task::spawn(t1); + r1.wait_for_all(); + ASSERT( r1.ref_count() <= 1, "Not all children of r1 executed" ); + ASSERT( r2.ref_count() == 2, "All children of r2 prematurely executed" ); + canProceed = true; + r2.wait_for_all(); + ASSERT( r2.ref_count() <= 1, "Not all children of r2 executed" ); + r1.destroy(r1); + r2.destroy(r2); +} + +struct MasterBody : NoAssign, Harness::NoAfterlife { + static Harness::SpinBarrier my_barrier; + + class BarrenButLongTask : public tbb::task { + volatile bool& m_Started; + volatile bool& m_CanProceed; + + tbb::task* execute() { + m_Started = true; + spin_wait_until_eq( m_CanProceed, true ); + volatile int k = 0; + for ( int i = 0; i < 1000000; ++i ) ++k; + return NULL; + } + public: + BarrenButLongTask ( volatile bool& started, volatile bool& can_proceed ) + : m_Started(started), m_CanProceed(can_proceed) + {} + }; + + class BinaryRecursiveTask : public tbb::task { + int m_Depth; + + tbb::task* execute() { + if( !m_Depth ) + return NULL; + set_ref_count(3); + spawn( *new( allocate_child() ) BinaryRecursiveTask(m_Depth - 1) ); + spawn( *new( allocate_child() ) BinaryRecursiveTask(m_Depth - 1) ); + wait_for_all(); + return NULL; + } + + void note_affinity( affinity_id ) { + ASSERT( false, "These tasks cannot be stolen" ); + } + public: + BinaryRecursiveTask ( int depth_ ) : m_Depth(depth_) {} + }; + + void operator() ( int id ) const { + if ( id ) { + tbb::task_scheduler_init init(2); + volatile bool child_started = false, + can_proceed = false; + tbb::task& r = *new( tbb::task::allocate_root() ) tbb::empty_task; + r.set_ref_count(2); + r.spawn( *new(r.allocate_child()) BarrenButLongTask(child_started, can_proceed) ); + spin_wait_until_eq( child_started, true ); + my_barrier.wait(); + can_proceed = true; + r.wait_for_all(); + r.destroy(r); + } + else { + my_barrier.wait(); + tbb::task_scheduler_init init(1); + Count = 0; + int depth = 16; + BinaryRecursiveTask& r = *new( tbb::task::allocate_root() ) BinaryRecursiveTask(depth); + tbb::task::spawn_root_and_wait(r); + } + } +public: + MasterBody ( int num_masters ) { my_barrier.initialize(num_masters); } +}; + +Harness::SpinBarrier MasterBody::my_barrier; + +/** Ensures that tasks spawned by a master thread or one of the workers servicing + it cannot be stolen by another master thread. **/ +void TestMastersIsolation ( int p ) { + // The test requires at least 3-way parallelism to work correctly + if ( p > 2 && tbb::task_scheduler_init::default_num_threads() >= p ) { + tbb::task_scheduler_init init(p); + NativeParallelFor( p, MasterBody(p) ); + } +} + +int TestMain () { +#if TBB_USE_EXCEPTIONS + TestUnconstructibleTask<1>(); + TestUnconstructibleTask<10000>(); +#endif + TestAlignment(); + TestNoteAffinityContext(); + TestDispatchLoopResponsiveness(); + TestWaitDiscriminativenessWithoutStealing(); + TestWaitDiscriminativenessWithStealing(); + for( int p=MinThread; p<=MaxThread; ++p ) { + TestSpawnChildren( p ); + TestSpawnRootList( p ); + TestSafeContinuation( p ); + TestLeftRecursion( p ); + TestDag( p ); + TestAffinity( p ); + TestUserThread( p ); + TestStealLimit( p ); + TestRelaxedOwnership( p ); + TestMastersIsolation( p ); + } + return Harness::Done; +} diff --git a/src/tbb/src/test/test_task_assertions.cpp b/src/tbb/src/test/test_task_assertions.cpp new file mode 100644 index 0000000..7fb623e --- /dev/null +++ b/src/tbb/src/test/test_task_assertions.cpp @@ -0,0 +1,118 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#if HARNESS_USE_PROXY + +// The test includes injects scheduler directly, so skip it when proxy tested. + +#undef HARNESS_USE_PROXY +#include "harness.h" + +int TestMain () { + return Harness::Skipped; +} + +#else // HARNESS_USE_PROXY + +// Test correctness of forceful TBB initialization before any dynamic initialization +// of static objects inside the library took place. +namespace tbb { +namespace internal { + // Forward declaration of the TBB general initialization routine from task.cpp + void DoOneTimeInitializations(); +}} + +struct StaticInitializationChecker { + StaticInitializationChecker () { tbb::internal::DoOneTimeInitializations(); } +} theChecker; + +//------------------------------------------------------------------------ +// Test that important assertions in class task fail as expected. +//------------------------------------------------------------------------ + +#include "harness_inject_scheduler.h" + +#define HARNESS_NO_PARSE_COMMAND_LINE 1 +#include "harness.h" +#include "harness_bad_expr.h" + +#if TRY_BAD_EXPR_ENABLED +//! Task that will be abused. +tbb::task* volatile AbusedTask; + +//! Number of times that AbuseOneTask +int AbuseOneTaskRan; + +//! Body used to create task in thread 0 and abuse it in thread 1. +struct AbuseOneTask { + void operator()( int ) const { + tbb::task_scheduler_init init; + // Thread 1 attempts to incorrectly use the task created by thread 0. + tbb::task_list list; + // spawn_root_and_wait over empty list should vacuously succeed. + tbb::task::spawn_root_and_wait(list); + + // Check that spawn_root_and_wait fails on non-empty list. + list.push_back(*AbusedTask); + + // Try abusing recycle_as_continuation + TRY_BAD_EXPR(AbusedTask->recycle_as_continuation(), "execute" ); + TRY_BAD_EXPR(AbusedTask->recycle_as_safe_continuation(), "execute" ); + TRY_BAD_EXPR(AbusedTask->recycle_to_reexecute(), "execute" ); + ++AbuseOneTaskRan; + } +}; + +//! Test various __TBB_ASSERT assertions related to class tbb::task. +void TestTaskAssertions() { + // Catch assertion failures + tbb::set_assertion_handler( AssertionFailureHandler ); + tbb::task_scheduler_init init; + // Create task to be abused + AbusedTask = new( tbb::task::allocate_root() ) tbb::empty_task; + NativeParallelFor( 1, AbuseOneTask() ); + ASSERT( AbuseOneTaskRan==1, NULL ); + tbb::task::destroy(*AbusedTask); + // Restore normal assertion handling + tbb::set_assertion_handler( NULL ); +} + +int TestMain () { + TestTaskAssertions(); + return Harness::Done; +} + +#else /* !TRY_BAD_EXPR_ENABLED */ + +int TestMain () { + return Harness::Skipped; +} + +#endif /* !TRY_BAD_EXPR_ENABLED */ + +#endif // HARNESS_USE_PROXY diff --git a/src/tbb/src/test/test_task_auto_init.cpp b/src/tbb/src/test/test_task_auto_init.cpp new file mode 100644 index 0000000..13dbdd1 --- /dev/null +++ b/src/tbb/src/test/test_task_auto_init.cpp @@ -0,0 +1,210 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Testing automatic initialization of TBB task scheduler, so do not use task_scheduler_init anywhere. + +#include "tbb/task.h" + +#define HARNESS_NO_PARSE_COMMAND_LINE 1 +#include "harness.h" +#include "tbb/atomic.h" + +static tbb::atomic<int> g_NumTestsExecuted; + +#define TEST_PROLOGUE() ++g_NumTestsExecuted + +// Global data used in testing use cases with cross-thread usage of TBB objects +static tbb::task *g_Root1 = NULL, + *g_Root2 = NULL, + *g_Root3 = NULL, + *g_Task = NULL; + +#if __TBB_TASK_GROUP_CONTEXT +static tbb::task_group_context* g_Ctx = NULL; +#endif /* __TBB_TASK_GROUP_CONTEXT */ + + +void TestTaskSelf () { + TEST_PROLOGUE(); + tbb::task& t = tbb::task::self(); + ASSERT( !t.parent() && t.ref_count() == 1 && !t.affinity(), "Master's default task properties changed?" ); +} + +void TestRootAllocation () { + TEST_PROLOGUE(); + tbb::task &r = *new( tbb::task::allocate_root() ) tbb::empty_task; + tbb::task::spawn_root_and_wait(r); +} + +inline void ExecuteChildAndCleanup ( tbb::task &r, tbb::task &t ) { + r.set_ref_count(2); + r.spawn_and_wait_for_all(t); + r.destroy(r); +} + +void TestChildAllocation () { + TEST_PROLOGUE(); + tbb::task &t = *new( g_Root1->allocate_child() ) tbb::empty_task; + ExecuteChildAndCleanup( *g_Root1, t ); +} + +void TestAdditionalChildAllocation () { + TEST_PROLOGUE(); + tbb::task &t = *new( tbb::task::allocate_additional_child_of(*g_Root2) ) tbb::empty_task; + ExecuteChildAndCleanup( *g_Root2, t ); +} + +#if __TBB_TASK_GROUP_CONTEXT +void TestTaskGroupContextCreation () { + TEST_PROLOGUE(); + tbb::task_group_context ctx; + tbb::task &r = *new( tbb::task::allocate_root(ctx) ) tbb::empty_task; + tbb::task::spawn_root_and_wait(r); +} + +void TestRootAllocationWithContext () { + TEST_PROLOGUE(); + tbb::task* root = new( tbb::task::allocate_root(*g_Ctx) ) tbb::empty_task; + tbb::task::spawn_root_and_wait(*root); +} +#endif /* __TBB_TASK_GROUP_CONTEXT */ + +void TestSpawn () { + TEST_PROLOGUE(); + tbb::task::spawn(*g_Task); +} + +void TestWaitForAll () { + TEST_PROLOGUE(); + g_Root3->wait_for_all(); + tbb::task::destroy(*g_Root3); +} + +typedef void (*TestFnPtr)(); + +const TestFnPtr TestFuncsTable[] = { + TestTaskSelf, TestRootAllocation, TestChildAllocation, TestAdditionalChildAllocation, +#if __TBB_TASK_GROUP_CONTEXT + TestTaskGroupContextCreation, TestRootAllocationWithContext, +#endif /* __TBB_TASK_GROUP_CONTEXT */ + TestSpawn, TestWaitForAll }; + +const int NumTestFuncs = sizeof(TestFuncsTable) / sizeof(TestFnPtr); + +struct TestThreadBody : NoAssign, Harness::NoAfterlife { + // Each invocation of operator() happens in a fresh thread with zero-based ID + // id, and checks a specific auto-initialization scenario. + void operator() ( int id ) const { + ASSERT( id >= 0 && id < NumTestFuncs, "Test diver: NativeParallelFor is used incorrectly" ); + TestFuncsTable[id](); + } +}; + + +#include "../tbb/tls.h" + +void UseAFewNewTlsKeys () { + tbb::internal::tls<intptr_t> tls1, tls2, tls3, tls4; + tls1 = tls2 = tls3 = tls4 = -1; +} + +using tbb::internal::spin_wait_until_eq; + +volatile bool FafStarted = false, + FafCanFinish = false, + FafCompleted = false; + +//! This task is supposed to be executed during termination of an auto-initialized master thread +class FireAndForgetTask : public tbb::task { + tbb::task* execute () { + // Let another master thread proceed requesting new TLS keys + FafStarted = true; + UseAFewNewTlsKeys(); + // Wait while another master thread dirtied its new TLS slots + spin_wait_until_eq( FafCanFinish, true ); + FafCompleted = true; + return NULL; + } +public: // to make gcc 3.2.3 happy + ~FireAndForgetTask() { + ASSERT(FafCompleted, "FireAndForgetTask got erroneously cancelled?"); + } +}; + +#include "harness_barrier.h" +Harness::SpinBarrier driver_barrier(2); + +struct DriverThreadBody : NoAssign, Harness::NoAfterlife { + void operator() ( int id ) const { + ASSERT( id < 2, "Only two test driver threads are expected" ); + // a barrier is required to ensure both threads started; otherwise the test may deadlock: + // the first thread would execute FireAndForgetTask at shutdown and wait for FafCanFinish, + // while the second thread wouldn't even start waiting for the loader lock hold by the first one. + if ( id == 0 ) { + driver_barrier.wait(); + // Prepare global data + g_Root1 = new( tbb::task::allocate_root() ) tbb::empty_task; + g_Root2 = new( tbb::task::allocate_root() ) tbb::empty_task; + g_Root3 = new( tbb::task::allocate_root() ) tbb::empty_task; + g_Task = new( g_Root3->allocate_child() ) tbb::empty_task; + g_Root3->set_ref_count(2); + // Run tests + NativeParallelFor( NumTestFuncs, TestThreadBody() ); + ASSERT( g_NumTestsExecuted == NumTestFuncs, "Test driver: Wrong number of tests executed" ); + + // This test checks the validity of temporarily restoring the value of + // the last TLS slot for a given key during the termination of an + // auto-initialized master thread (in governor::auto_terminate). + // If anything goes wrong, generic_scheduler::cleanup_master() will assert. + // The context for this task must be valid till the task completion. +#if __TBB_TASK_GROUP_CONTEXT + tbb::task &r = *new( tbb::task::allocate_root(*g_Ctx) ) FireAndForgetTask; +#else + tbb::task &r = *new( tbb::task::allocate_root() ) FireAndForgetTask; +#endif /* __TBB_TASK_GROUP_CONTEXT */ + tbb::task::spawn(r); + } + else { +#if __TBB_TASK_GROUP_CONTEXT + tbb::task_group_context ctx; + g_Ctx = &ctx; +#endif /* __TBB_TASK_GROUP_CONTEXT */ + driver_barrier.wait(); + spin_wait_until_eq( FafStarted, true ); + UseAFewNewTlsKeys(); + FafCanFinish = true; + spin_wait_until_eq( FafCompleted, true ); + } + } +}; + +int TestMain () { + // Do not use any TBB functionality in the main thread! + NativeParallelFor( 2, DriverThreadBody() ); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_task_enqueue.cpp b/src/tbb/src/test/test_task_enqueue.cpp new file mode 100644 index 0000000..a0ff46e --- /dev/null +++ b/src/tbb/src/test/test_task_enqueue.cpp @@ -0,0 +1,329 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "harness_task.h" +#include "harness_barrier.h" +#include "tbb/atomic.h" +#include "tbb/tbb_thread.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/tick_count.h" + +//////////////////////////////////////////////////////////////////////////////// +// Test for basic FIFO scheduling functionality + +const int PairsPerTrack = 100; + +class EnqueuedTask : public tbb::task { + task* my_successor; + int my_enqueue_order; + int* my_track; + tbb::task* execute() { + // Capture execution order in the very beginning + int execution_order = 2 - my_successor->decrement_ref_count(); + // Create some local work. + TaskGenerator& p = *new( allocate_root() ) TaskGenerator(2,2); + spawn_root_and_wait(p); + if( execution_order==2 ) { // the "slower" of two peer tasks + ++nCompletedPairs; + // Of course execution order can differ from dequeue order. + // But there is no better approximation at hand; and a single worker + // will execute in dequeue order, which is enough for our check. + if (my_enqueue_order==execution_order) + ++nOrderedPairs; + FireTwoTasks(my_track); + destroy(*my_successor); + } + return NULL; + } +public: + EnqueuedTask( task* successor, int enq_order, int* track ) + : my_successor(successor), my_enqueue_order(enq_order), my_track(track) {} + + // Create and enqueue two tasks + static void FireTwoTasks( int* track ) { + int progress = ++*track; + if( progress < PairsPerTrack ) { + task* successor = new (allocate_root()) tbb::empty_task; + successor->set_ref_count(2); + enqueue( *new (allocate_root()) EnqueuedTask(successor, 1, track) ); + enqueue( *new (allocate_root()) EnqueuedTask(successor, 2, track) ); + } + } + + static tbb::atomic<int> nCompletedPairs; + static tbb::atomic<int> nOrderedPairs; +}; + +tbb::atomic<int> EnqueuedTask::nCompletedPairs; +tbb::atomic<int> EnqueuedTask::nOrderedPairs; + +const int nTracks = 10; +static int TaskTracks[nTracks]; +const int stall_threshold = 100000; + +void TimedYield( double pause_time ) { + tbb::tick_count start = tbb::tick_count::now(); + while( (tbb::tick_count::now()-start).seconds() < pause_time ) + __TBB_Yield(); +} + +class ProgressMonitor { +public: + void operator() ( ) { + int track_snapshot[nTracks]; + int stall_count = 0, uneven_progress_count = 0, last_progress_mask = 0; + for(int i=0; i<nTracks; ++i) + track_snapshot[i]=0; + bool completed; + do { + // Yield repeatedly for at least 1 usec + TimedYield( 1E-6 ); + int overall_progress = 0, progress_mask = 0; + const int all_progressed = (1<<nTracks) - 1; + completed = true; + for(int i=0; i<nTracks; ++i) { + int ti = TaskTracks[i]; + int pi = ti-track_snapshot[i]; + if( pi ) progress_mask |= 1<<i; + overall_progress += pi; + completed = completed && ti==PairsPerTrack; + track_snapshot[i]=ti; + } + // The constants in the next asserts are subjective and may need correction. + if( overall_progress ) + stall_count=0; + else { + ++stall_count; + // no progress for at least 0.1 s; consider it dead. + ASSERT(stall_count < stall_threshold, "no progress on enqueued tasks; deadlock, or the machine is oversubsribed?"); + } + if( progress_mask==all_progressed || progress_mask^last_progress_mask ) { + uneven_progress_count = 0; + last_progress_mask = progress_mask; + } + else if ( overall_progress > 2 ) { + ++uneven_progress_count; + ASSERT(uneven_progress_count < 5, "some enqueued tasks seem stalling; no simultaneous progress?"); + } + } while( !completed ); + } +}; + +void TestEnqueue( int p ) { + REMARK("Testing task::enqueue for %d threads\n", p); + for(int mode=0;mode<3;++mode) { + tbb::task_scheduler_init init(p); + EnqueuedTask::nCompletedPairs = EnqueuedTask::nOrderedPairs = 0; + for(int i=0; i<nTracks; ++i) { + TaskTracks[i] = -1; // to accomodate for the starting call + EnqueuedTask::FireTwoTasks(TaskTracks+i); + } + ProgressMonitor pm; + tbb::tbb_thread thr( pm ); + if(mode==1) { + // do some parallel work in the meantime + for(int i=0; i<10; i++) { + TaskGenerator& g = *new( tbb::task::allocate_root() ) TaskGenerator(2,5); + tbb::task::spawn_root_and_wait(g); + TimedYield( 1E-6 ); + } + } + if( mode==2 ) { + // Additionally enqueue a bunch of empty tasks. The goal is to test that tasks + // allocated and enqueued by a thread are safe to use after the thread leaves TBB. + tbb::task* root = new (tbb::task::allocate_root()) tbb::empty_task; + root->set_ref_count(100); + for( int i=0; i<100; ++i ) + tbb::task::enqueue( *new (root->allocate_child()) tbb::empty_task ); + init.terminate(); // master thread deregistered + } + thr.join(); + ASSERT(EnqueuedTask::nCompletedPairs==nTracks*PairsPerTrack, NULL); + ASSERT(EnqueuedTask::nOrderedPairs<EnqueuedTask::nCompletedPairs, + "all task pairs executed in enqueue order; de facto guarantee is too strong?"); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Tests for Fire-And-Forget scheduling functionality + +const int NumRepeats = 200; +const int MaxNumThreads = 16; +static volatile bool Finished[MaxNumThreads] = {}; + +static volatile bool CanStart; + +//! Custom user task interface +class ITask { +public: + virtual ~ITask() {} + virtual void Execute() = 0; + virtual void Release() { delete this; } +}; + +class TestTask : public ITask { + volatile bool *m_pDone; +public: + TestTask ( volatile bool *pDone ) : m_pDone(pDone) {} + + /* override */ void Execute() { + *m_pDone = true; + } +}; + +class CarrierTask : public tbb::task { + ITask* m_pTask; +public: + CarrierTask(ITask* pTask) : m_pTask(pTask) {} + + /*override*/ task* execute() { + m_pTask->Execute(); + m_pTask->Release(); + return NULL; + } +}; + +class SpawnerTask : public ITask { + ITask* m_taskToSpawn; +public: + SpawnerTask(ITask* job) : m_taskToSpawn(job) {} + + void Execute() { + while ( !CanStart ) + __TBB_Yield(); + tbb::task::enqueue( *new( tbb::task::allocate_root() ) CarrierTask(m_taskToSpawn) ); + } +}; + +class EnqueuerBody { +public: + void operator() ( int id ) const { + tbb::task_scheduler_init init(tbb::task_scheduler_init::default_num_threads() + 1); + + SpawnerTask* pTask = new SpawnerTask( new TestTask(Finished + id) ); + tbb::task::enqueue( *new( tbb::task::allocate_root() ) CarrierTask(pTask) ); + } +}; + +//! Regression test for a bug that caused premature arena destruction +void TestCascadedEnqueue () { + REMARK("Testing cascaded enqueue\n"); + tbb::task_scheduler_init init(tbb::task_scheduler_init::default_num_threads() + 1); + + int minNumThreads = min(tbb::task_scheduler_init::default_num_threads(), MaxNumThreads) / 2; + int maxNumThreads = min(tbb::task_scheduler_init::default_num_threads() * 2, MaxNumThreads); + + for ( int numThreads = minNumThreads; numThreads <= maxNumThreads; ++numThreads ) { + for ( int i = 0; i < NumRepeats; ++i ) { + CanStart = false; + __TBB_Yield(); + NativeParallelFor( numThreads, EnqueuerBody() ); + CanStart = true; + int j = 0; + while ( j < numThreads ) { + if ( Finished[j] ) + ++j; + else + __TBB_Yield(); + } + for ( j = 0; j < numThreads; ++j ) + Finished[j] = false; + REMARK("%02d threads; Iteration %03d\r", numThreads, i); + } + } + REMARK( " \r" ); +} + +class DummyTask : public tbb::task { +public: + task *execute() { + Harness::Sleep(1); + return NULL; + } +}; + +class SharedRootBody { + tbb::task *my_root; +public: + SharedRootBody ( tbb::task *root ) : my_root(root) {} + + void operator() ( int ) const { + tbb::task::enqueue( *new( tbb::task::allocate_additional_child_of(*my_root) ) DummyTask ); + } +}; + +//! Test for enqueuing children of the same root from different master threads +void TestSharedRoot ( int p ) { + REMARK("Testing enqueuing siblings from different masters\n"); + tbb::task_scheduler_init init(p); + tbb::task *root = new ( tbb::task::allocate_root() ) tbb::empty_task; + root->set_ref_count(1); + for( int n = MinThread; n <= MaxThread; ++n ) { + REMARK("%d masters, %d requested workers\r", n, p-1); + NativeParallelFor( n, SharedRootBody(root) ); + } + REMARK( " \r" ); + root->wait_for_all(); + tbb::task::destroy(*root); +} + +class BlockingTask : public tbb::task { + Harness::SpinBarrier &m_Barrier; + + tbb::task* execute () { + m_Barrier.wait(); + return 0; + } + +public: + BlockingTask ( Harness::SpinBarrier& bar ) : m_Barrier(bar) {} +}; + +//! Test making sure that masters can dequeue tasks +/** Success criterion is not hanging. **/ +void TestDequeueByMaster () { + REMARK("Testing task dequeuing by master\n"); + tbb::task_scheduler_init init(1); + Harness::SpinBarrier bar(2); + tbb::task &r = *new ( tbb::task::allocate_root() ) tbb::empty_task; + r.set_ref_count(3); + tbb::task::enqueue( *new(r.allocate_child()) BlockingTask(bar) ); + tbb::task::enqueue( *new(r.allocate_child()) BlockingTask(bar) ); + r.wait_for_all(); + tbb::task::destroy(r); +} + +int TestMain () { + TestDequeueByMaster(); + TestCascadedEnqueue(); + for( int p=MinThread; p<=MaxThread; ++p ) { + TestEnqueue(p); + TestSharedRoot(p); + } + return Harness::Done; +} diff --git a/src/tbb/src/test/test_task_group.cpp b/src/tbb/src/test/test_task_group.cpp new file mode 100644 index 0000000..3896c67 --- /dev/null +++ b/src/tbb/src/test/test_task_group.cpp @@ -0,0 +1,859 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +//! task_handle<T> cannot be instantiated with a function ptr without explicit cast +#define __TBB_FUNC_PTR_AS_TEMPL_PARAM_BROKEN ((__linux__ || __APPLE__) && __INTEL_COMPILER && __INTEL_COMPILER < 1100) || __SUNPRO_CC +#define __TBB_UNQUALIFIED_CALL_OF_DTOR_BROKEN (__GNUC__==3 && __GNUC_MINOR__<=3) + +#ifndef TBBTEST_USE_TBB + #define TBBTEST_USE_TBB 1 +#endif + +#if !TBBTEST_USE_TBB + #if defined(_MSC_VER) && _MSC_VER < 1600 + #ifdef TBBTEST_USE_TBB + #undef TBBTEST_USE_TBB + #endif + #define TBBTEST_USE_TBB 1 + #endif +#endif + +#if TBBTEST_USE_TBB + + #include "tbb/compat/ppl.h" + #include "tbb/task_scheduler_init.h" + + #if _MSC_VER + typedef tbb::internal::uint32_t uint_t; + #else + typedef uint32_t uint_t; + #endif + +#else /* !TBBTEST_USE_TBB */ + + #if defined(_MSC_VER) + #pragma warning(disable: 4100 4180) + #endif + + #include <ppl.h> + + typedef unsigned int uint_t; + + #define __TBB_SILENT_CANCELLATION_BROKEN (_MSC_VER == 1600) + +#endif /* !TBBTEST_USE_TBB */ + +#if __TBB_TASK_GROUP_CONTEXT + +#include "tbb/atomic.h" +#include "harness_concurrency_tracker.h" + +unsigned g_MaxConcurrency = 0; + +typedef tbb::atomic<uint_t> atomic_t; +typedef Concurrency::task_handle<void(*)()> handle_type; + +//------------------------------------------------------------------------ +// Tests for the thread safety of the task_group manipulations +//------------------------------------------------------------------------ + +#include "harness_barrier.h" + +enum SharingMode { + VagabondGroup = 1, + ParallelWait = 2 +}; + +class SharedGroupBodyImpl : NoCopy, Harness::NoAfterlife { + static const uint_t c_numTasks0 = 4096, + c_numTasks1 = 1024; + + const uint_t m_numThreads; + const uint_t m_sharingMode; + + Concurrency::task_group *m_taskGroup; + atomic_t m_tasksSpawned, + m_threadsReady; + Harness::SpinBarrier m_barrier; + + static atomic_t s_tasksExecuted; + + struct TaskFunctor { + SharedGroupBodyImpl *m_pOwner; + void operator () () const { + if ( m_pOwner->m_sharingMode & ParallelWait ) { + while ( Harness::ConcurrencyTracker::PeakParallelism() < m_pOwner->m_numThreads ) + __TBB_Yield(); + } + ++s_tasksExecuted; + } + }; + + TaskFunctor m_taskFunctor; + + void Spawn ( uint_t numTasks ) { + for ( uint_t i = 0; i < numTasks; ++i ) { + ++m_tasksSpawned; + Harness::ConcurrencyTracker ct; + m_taskGroup->run( m_taskFunctor ); + } + ++m_threadsReady; + } + + void DeleteTaskGroup () { + delete m_taskGroup; + m_taskGroup = NULL; + } + + void Wait () { + while ( m_threadsReady != m_numThreads ) + __TBB_Yield(); + const uint_t numSpawned = c_numTasks0 + c_numTasks1 * (m_numThreads - 1); + ASSERT ( m_tasksSpawned == numSpawned, "Wrong number of spawned tasks. The test is broken" ); + REMARK("Max spawning parallelism is %u out of %u\n", Harness::ConcurrencyTracker::PeakParallelism(), g_MaxConcurrency); + if ( m_sharingMode & ParallelWait ) { + m_barrier.wait( &Harness::ConcurrencyTracker::Reset ); + { + Harness::ConcurrencyTracker ct; + m_taskGroup->wait(); + } + if ( Harness::ConcurrencyTracker::PeakParallelism() == 1 ) + REPORT ( "Warning: No parallel waiting detected in TestParallelWait\n" ); + m_barrier.wait(); + } + else + m_taskGroup->wait(); + ASSERT ( m_tasksSpawned == numSpawned, "No tasks should be spawned after wait starts. The test is broken" ); + ASSERT ( s_tasksExecuted == numSpawned, "Not all spawned tasks were executed" ); + } + +public: + SharedGroupBodyImpl ( uint_t numThreads, uint_t sharingMode = 0 ) + : m_numThreads(numThreads) + , m_sharingMode(sharingMode) + , m_taskGroup(NULL) + , m_barrier(numThreads) + { + ASSERT ( m_numThreads > 1, "SharedGroupBody tests require concurrency" ); + ASSERT ( !(m_sharingMode & VagabondGroup) || m_numThreads == 2, "In vagabond mode SharedGroupBody must be used with 2 threads only" ); + Harness::ConcurrencyTracker::Reset(); + s_tasksExecuted = 0; + m_tasksSpawned = 0; + m_threadsReady = 0; + m_taskFunctor.m_pOwner = this; + } + + void Run ( uint_t idx ) { +#if TBBTEST_USE_TBB + tbb::task_scheduler_init init; +#endif + AssertLive(); + if ( idx == 0 ) { + ASSERT ( !m_taskGroup && !m_tasksSpawned, "SharedGroupBody must be reset before reuse"); + m_taskGroup = new Concurrency::task_group; + Spawn( c_numTasks0 ); + Wait(); + if ( m_sharingMode & VagabondGroup ) + m_barrier.wait(); + else + DeleteTaskGroup(); + } + else { + while ( m_tasksSpawned == 0 ) + __TBB_Yield(); + ASSERT ( m_taskGroup, "Task group is not initialized"); + Spawn (c_numTasks1); + if ( m_sharingMode & ParallelWait ) + Wait(); + if ( m_sharingMode & VagabondGroup ) { + ASSERT ( idx == 1, "In vagabond mode SharedGroupBody must be used with 2 threads only" ); + m_barrier.wait(); + DeleteTaskGroup(); + } + } + AssertLive(); + } +}; + +atomic_t SharedGroupBodyImpl::s_tasksExecuted; + +class SharedGroupBody : NoAssign, Harness::NoAfterlife { + bool m_bOwner; + SharedGroupBodyImpl *m_pImpl; +public: + SharedGroupBody ( uint_t numThreads, uint_t sharingMode = 0 ) + : m_bOwner(true) + , m_pImpl( new SharedGroupBodyImpl(numThreads, sharingMode) ) + {} + SharedGroupBody ( const SharedGroupBody& src ) + : NoAssign() + , Harness::NoAfterlife() + , m_bOwner(false) + , m_pImpl(src.m_pImpl) + {} + ~SharedGroupBody () { + if ( m_bOwner ) + delete m_pImpl; + } + void operator() ( uint_t idx ) const { m_pImpl->Run(idx); } +}; + +void TestParallelSpawn () { + NativeParallelFor( g_MaxConcurrency, SharedGroupBody(g_MaxConcurrency) ); +} + +void TestParallelWait () { + NativeParallelFor( g_MaxConcurrency, SharedGroupBody(g_MaxConcurrency, ParallelWait) ); +} + +// Tests non-stack-bound task group (the group that is allocated by one thread and destroyed by the other) +void TestVagabondGroup () { + NativeParallelFor( 2, SharedGroupBody(2, VagabondGroup) ); +} + +//------------------------------------------------------------------------ +// Common requisites of the Fibonacci tests +//------------------------------------------------------------------------ + +const uint_t N = 20; +const uint_t F = 6765; + +atomic_t g_Sum; + +#define FIB_TEST_PROLOGUE() \ + const unsigned numRepeats = g_MaxConcurrency * (TBB_USE_DEBUG ? 4 : 16); \ + Harness::ConcurrencyTracker::Reset() + +#define FIB_TEST_EPILOGUE(sum) \ + ASSERT( sum == numRepeats * F, NULL ); \ + REMARK("Realized parallelism in Fib test is %u out of %u\n", Harness::ConcurrencyTracker::PeakParallelism(), g_MaxConcurrency) + +//------------------------------------------------------------------------ +// Test for a complex tree of task groups +// +// The test executes a tree of task groups of the same sort with asymmetric +// descendant nodes distribution at each level at each level. +// +// The chores are specified as functor objects. Each task group contains only one chore. +//------------------------------------------------------------------------ + +template<uint_t Func(uint_t)> +struct FibTask : NoAssign, Harness::NoAfterlife { + uint_t* m_pRes; + const uint_t m_Num; + FibTask( uint_t* y, uint_t n ) : m_pRes(y), m_Num(n) {} + void operator() () const { + *m_pRes = Func(m_Num); + } +}; + +uint_t Fib_SpawnRightChildOnly ( uint_t n ) { + Harness::ConcurrencyTracker ct; + if( n<2 ) { + return n; + } else { + uint_t y = ~0u; + Concurrency::task_group tg; + tg.run( FibTask<Fib_SpawnRightChildOnly>(&y, n-1) ); + uint_t x = Fib_SpawnRightChildOnly(n-2); + tg.wait(); + return y+x; + } +} + +void TestFib1 () { + FIB_TEST_PROLOGUE(); + uint_t sum = 0; + for( unsigned i = 0; i < numRepeats; ++i ) + sum += Fib_SpawnRightChildOnly(N); + FIB_TEST_EPILOGUE(sum); +} + + +//------------------------------------------------------------------------ +// Test for a mixed tree of task groups. +// +// The test executes a tree with multiple task of one sort at the first level, +// each of which originates in its turn a binary tree of descendant task groups. +// +// The chores are specified both as functor objects and as function pointers +//------------------------------------------------------------------------ + +uint_t Fib_SpawnBothChildren( uint_t n ) { + Harness::ConcurrencyTracker ct; + if( n<2 ) { + return n; + } else { + uint_t y = ~0u, + x = ~0u; + Concurrency::task_group tg; + tg.run( FibTask<Fib_SpawnBothChildren>(&x, n-2) ); + tg.run( FibTask<Fib_SpawnBothChildren>(&y, n-1) ); + tg.wait(); + return y + x; + } +} + +void RunFib2 () { + g_Sum += Fib_SpawnBothChildren(N); +} + +void TestFib2 () { + FIB_TEST_PROLOGUE(); + g_Sum = 0; + Concurrency::task_group rg; + for( unsigned i = 0; i < numRepeats - 1; ++i ) + rg.run( &RunFib2 ); + rg.wait(); + rg.run( &RunFib2 ); + rg.wait(); + FIB_TEST_EPILOGUE(g_Sum); +} + + +//------------------------------------------------------------------------ +// Test for a complex tree of task groups +// The chores are specified as task handles for recursive functor objects. +//------------------------------------------------------------------------ + +class FibTask_SpawnRightChildOnly : NoAssign, Harness::NoAfterlife { + uint_t* m_pRes; + mutable uint_t m_Num; + +public: + FibTask_SpawnRightChildOnly( uint_t* y, uint_t n ) : m_pRes(y), m_Num(n) {} + void operator() () const { + Harness::ConcurrencyTracker ct; + AssertLive(); + if( m_Num < 2 ) { + *m_pRes = m_Num; + } else { + uint_t y = ~0u; + Concurrency::task_group tg; + Concurrency::task_handle<FibTask_SpawnRightChildOnly> h = FibTask_SpawnRightChildOnly(&y, m_Num-1); + tg.run( h ); + m_Num -= 2; + tg.run_and_wait( *this ); + *m_pRes += y; + } + } +}; + +uint_t RunFib3 ( uint_t n ) { + uint_t res = ~0u; + FibTask_SpawnRightChildOnly func(&res, n); + func(); + return res; +} + +void TestTaskHandle () { + FIB_TEST_PROLOGUE(); + uint_t sum = 0; + for( unsigned i = 0; i < numRepeats; ++i ) + sum += RunFib3(N); + FIB_TEST_EPILOGUE(sum); +} + +//------------------------------------------------------------------------ +// Test for a mixed tree of task groups. +// The chores are specified as task handles for both functor objects and function pointers +//------------------------------------------------------------------------ + +template<class task_group_type> +class FibTask_SpawnBothChildren : NoAssign, Harness::NoAfterlife { + uint_t* m_pRes; + uint_t m_Num; +public: + FibTask_SpawnBothChildren( uint_t* y, uint_t n ) : m_pRes(y), m_Num(n) {} + void operator() () const { + Harness::ConcurrencyTracker ct; + AssertLive(); + if( m_Num < 2 ) { + *m_pRes = m_Num; + } else { + uint_t x = ~0u, // initialized only to suppress warning + y = ~0u; + task_group_type tg; + Concurrency::task_handle<FibTask_SpawnBothChildren> h1 = FibTask_SpawnBothChildren(&y, m_Num-1), + h2 = FibTask_SpawnBothChildren(&x, m_Num-2); + tg.run( h1 ); + tg.run( h2 ); + tg.wait(); + *m_pRes = x + y; + } + } +}; + +template<class task_group_type> +void RunFib4 () { + uint_t res = ~0u; + FibTask_SpawnBothChildren<task_group_type> func(&res, N); + func(); + g_Sum += res; +} + +template<class task_group_type> +void TestTaskHandle2 () { + FIB_TEST_PROLOGUE(); + g_Sum = 0; + task_group_type rg; + const unsigned hSize = sizeof(handle_type); + char *handles = new char [numRepeats * hSize]; + handle_type *h = NULL; + for( unsigned i = 0; ; ++i ) { + h = (handle_type*)(handles + i * hSize); +#if __TBB_FUNC_PTR_AS_TEMPL_PARAM_BROKEN + new ( h ) handle_type((void(*)())RunFib4<task_group_type>); +#else + new ( h ) handle_type(RunFib4<task_group_type>); +#endif + if ( i == numRepeats - 1 ) + break; + rg.run( *h ); +#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN + bool caught = false; + try { + rg.run( *h ); + } + catch ( Concurrency::invalid_multiple_scheduling& e ) { + ASSERT( e.what(), "Error message is absent" ); + caught = true; + } + catch ( ... ) { + ASSERT ( __TBB_EXCEPTION_TYPE_INFO_BROKEN, "Unrecognized exception" ); + } + ASSERT ( caught, "Expected invalid_multiple_scheduling exception is missing" ); +#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */ + } + rg.run_and_wait( *h ); + for( unsigned i = 0; i < numRepeats; ++i ) +#if __TBB_UNQUALIFIED_CALL_OF_DTOR_BROKEN + ((handle_type*)(handles + i * hSize))->Concurrency::task_handle<void(*)()>::~task_handle(); +#else + ((handle_type*)(handles + i * hSize))->~handle_type(); +#endif + delete []handles; + FIB_TEST_EPILOGUE(g_Sum); +} + +#if __TBB_LAMBDAS_PRESENT +//------------------------------------------------------------------------ +// Test for a mixed tree of task groups. +// The chores are specified as lambdas +//------------------------------------------------------------------------ + +void TestFibWithLambdas () { + REMARK ("Lambdas test"); + FIB_TEST_PROLOGUE(); + atomic_t sum; + sum = 0; + Concurrency::task_group rg; + for( unsigned i = 0; i < numRepeats; ++i ) + rg.run( [&](){sum += Fib_SpawnBothChildren(N);} ); + rg.wait(); + FIB_TEST_EPILOGUE(sum); +} + +//------------------------------------------------------------------------ +// Test for make_task. +// The chores are specified as lambdas converted to task_handles. +//------------------------------------------------------------------------ + +void TestFibWithMakeTask () { + REMARK ("Make_task test\n"); + atomic_t sum; + sum = 0; + Concurrency::task_group rg; + const auto &h1 = Concurrency::make_task( [&](){sum += Fib_SpawnBothChildren(N);} ); + const auto &h2 = Concurrency::make_task( [&](){sum += Fib_SpawnBothChildren(N);} ); + rg.run( h1 ); + rg.run_and_wait( h2 ); + ASSERT( sum == 2 * F, NULL ); +} +#endif /* __TBB_LAMBDAS_PRESENT */ + + +//------------------------------------------------------------------------ +// Tests for exception handling and cancellation behavior. +//------------------------------------------------------------------------ + +class test_exception : public std::exception +{ + const char* m_strDescription; +public: + test_exception ( const char* descr ) : m_strDescription(descr) {} + + const char* what() const throw() { return m_strDescription; } +}; + +#if TBB_USE_CAPTURED_EXCEPTION + #include "tbb/tbb_exception.h" + typedef tbb::captured_exception TestException; +#else + typedef test_exception TestException; +#endif + +#include <string.h> + +#define NUM_CHORES 512 +#define NUM_GROUPS 64 +#define SKIP_CHORES (NUM_CHORES/4) +#define SKIP_GROUPS (NUM_GROUPS/4) +#define EXCEPTION_DESCR1 "Test exception 1" +#define EXCEPTION_DESCR2 "Test exception 2" + +atomic_t g_ExceptionCount; +atomic_t g_TaskCount; +unsigned g_ExecutedAtCancellation; +bool g_Rethrow; +bool g_Throw; +#if __TBB_SILENT_CANCELLATION_BROKEN + volatile bool g_CancellationPropagationInProgress; + #define CATCH_ANY() \ + __TBB_CATCH( ... ) { \ + if ( g_CancellationPropagationInProgress ) { \ + if ( g_Throw ) { \ + exceptionCaught = true; \ + ++g_ExceptionCount; \ + } \ + } else \ + ASSERT( false, "Unknown exception" ); \ + } +#else + #define CATCH_ANY() __TBB_CATCH( ... ) { ASSERT( __TBB_EXCEPTION_TYPE_INFO_BROKEN, "Unknown exception" ); } +#endif + +inline +void ResetGlobals ( bool bThrow, bool bRethrow ) { + g_Throw = bThrow; + g_Rethrow = bRethrow; +#if __TBB_SILENT_CANCELLATION_BROKEN + g_CancellationPropagationInProgress = false; +#endif + g_ExceptionCount = 0; + g_TaskCount = 0; + Harness::ConcurrencyTracker::Reset(); +} + +class ThrowingTask : NoAssign, Harness::NoAfterlife { + atomic_t &m_TaskCount; +public: + ThrowingTask( atomic_t& counter ) : m_TaskCount(counter) {} + void operator() () const { + Harness::ConcurrencyTracker ct; + AssertLive(); + if ( g_Throw ) { + if ( ++m_TaskCount == SKIP_CHORES ) + __TBB_THROW( test_exception(EXCEPTION_DESCR1) ); + __TBB_Yield(); + } + else { + ++g_TaskCount; + while( !Concurrency::is_current_task_group_canceling() ) + __TBB_Yield(); + } + } +}; + +void LaunchChildren () { + atomic_t count; + count = 0; + Concurrency::task_group g; + bool exceptionCaught = false; + for( unsigned i = 0; i < NUM_CHORES; ++i ) + g.run( ThrowingTask(count) ); + Concurrency::task_group_status status = Concurrency::not_complete; + __TBB_TRY { + status = g.wait(); + } __TBB_CATCH ( TestException& e ) { +#if TBB_USE_EXCEPTIONS + ASSERT( e.what(), "Empty what() string" ); + ASSERT( __TBB_EXCEPTION_TYPE_INFO_BROKEN || strcmp(e.what(), EXCEPTION_DESCR1) == 0, "Unknown exception" ); +#endif /* TBB_USE_EXCEPTIONS */ + exceptionCaught = true; + ++g_ExceptionCount; + } CATCH_ANY(); + ASSERT( !g_Throw || exceptionCaught || status == Concurrency::canceled, "No exception in the child task group" ); + if ( g_Rethrow && g_ExceptionCount > SKIP_GROUPS ) { +#if __TBB_SILENT_CANCELLATION_BROKEN + g_CancellationPropagationInProgress = true; +#endif + __TBB_THROW( test_exception(EXCEPTION_DESCR2) ); + } +} + +#if TBB_USE_EXCEPTIONS +void TestEh1 () { + ResetGlobals( true, false ); + Concurrency::task_group rg; + for( unsigned i = 0; i < NUM_GROUPS; ++i ) + // TBB version does not require taking function address + rg.run( &LaunchChildren ); + try { + rg.wait(); + } catch ( ... ) { + ASSERT( false, "Unexpected exception" ); + } + ASSERT( g_ExceptionCount <= NUM_GROUPS, "Too many exceptions from the child groups. The test is broken" ); + ASSERT( g_ExceptionCount == NUM_GROUPS, "Not all child groups threw the exception" ); +} + +void TestEh2 () { + ResetGlobals( true, true ); + Concurrency::task_group rg; + bool exceptionCaught = false; + for( unsigned i = 0; i < NUM_GROUPS; ++i ) + // TBB version does not require taking function address + rg.run( &LaunchChildren ); + try { + rg.wait(); + } catch ( TestException& e ) { + ASSERT( e.what(), "Empty what() string" ); + ASSERT( __TBB_EXCEPTION_TYPE_INFO_BROKEN || strcmp(e.what(), EXCEPTION_DESCR2) == 0, "Unknown exception" ); + ASSERT ( !rg.is_canceling(), "wait() has not reset cancellation state" ); + exceptionCaught = true; + } CATCH_ANY(); + ASSERT( exceptionCaught, "No exception thrown from the root task group" ); + ASSERT( g_ExceptionCount >= SKIP_GROUPS, "Too few exceptions from the child groups. The test is broken" ); + ASSERT( g_ExceptionCount <= NUM_GROUPS - SKIP_GROUPS, "Too many exceptions from the child groups. The test is broken" ); + ASSERT( g_ExceptionCount < NUM_GROUPS - SKIP_GROUPS, "None of the child groups was cancelled" ); +} +#endif /* TBB_USE_EXCEPTIONS */ + +//------------------------------------------------------------------------ +// Tests for manual cancellation of the task_group hierarchy +//------------------------------------------------------------------------ + +void TestCancellation1 () { + ResetGlobals( false, false ); + Concurrency::task_group rg; + for( unsigned i = 0; i < NUM_GROUPS; ++i ) + // TBB version does not require taking function address + rg.run( &LaunchChildren ); + ASSERT ( !Concurrency::is_current_task_group_canceling(), "Unexpected cancellation" ); + ASSERT ( !rg.is_canceling(), "Unexpected cancellation" ); +#if __TBB_SILENT_CANCELLATION_BROKEN + g_CancellationPropagationInProgress = true; +#endif + while ( g_MaxConcurrency > 1 && g_TaskCount == 0 ) + __TBB_Yield(); + rg.cancel(); + g_ExecutedAtCancellation = g_TaskCount; + ASSERT ( rg.is_canceling(), "No cancellation reported" ); + rg.wait(); + ASSERT( g_TaskCount <= NUM_GROUPS * NUM_CHORES, "Too many tasks reported. The test is broken" ); + ASSERT( g_TaskCount < NUM_GROUPS * NUM_CHORES, "No tasks were cancelled. Cancellation model changed?" ); + ASSERT( g_TaskCount <= g_ExecutedAtCancellation + Harness::ConcurrencyTracker::PeakParallelism(), "Too many tasks survived cancellation" ); +} + +//------------------------------------------------------------------------ +// Tests for manual cancellation of the structured_task_group hierarchy +//------------------------------------------------------------------------ + +void StructuredLaunchChildren () { + atomic_t count; + count = 0; + Concurrency::structured_task_group g; + bool exceptionCaught = false; + typedef Concurrency::task_handle<ThrowingTask> throwing_handle_type; + static const unsigned hSize = sizeof(throwing_handle_type); + char handles[NUM_CHORES * hSize]; + for( unsigned i = 0; i < NUM_CHORES; ++i ) { + throwing_handle_type *h = (throwing_handle_type*)(handles + i * hSize); + new ( h ) throwing_handle_type( ThrowingTask(count) ); + g.run( *h ); + } + __TBB_TRY { + g.wait(); + } __TBB_CATCH( TestException& e ) { +#if TBB_USE_EXCEPTIONS + ASSERT( e.what(), "Empty what() string" ); + ASSERT( __TBB_EXCEPTION_TYPE_INFO_BROKEN || strcmp(e.what(), EXCEPTION_DESCR1) == 0, "Unknown exception" ); +#endif /* TBB_USE_EXCEPTIONS */ +#if __TBB_SILENT_CANCELLATION_BROKEN + ASSERT ( !g.is_canceling() || g_CancellationPropagationInProgress, "wait() has not reset cancellation state" ); +#else + ASSERT ( !g.is_canceling(), "wait() has not reset cancellation state" ); +#endif + exceptionCaught = true; + ++g_ExceptionCount; + } CATCH_ANY(); + ASSERT( !g_Throw || exceptionCaught, "No exception in the child task group" ); + for( unsigned i = 0; i < NUM_CHORES; ++i ) + ((throwing_handle_type*)(handles + i * hSize))->~throwing_handle_type(); + if ( g_Rethrow && g_ExceptionCount > SKIP_GROUPS ) { +#if __TBB_SILENT_CANCELLATION_BROKEN + g_CancellationPropagationInProgress = true; +#endif + __TBB_THROW( test_exception(EXCEPTION_DESCR2) ); + } +} + +class StructuredCancellationTestDriver { + static const unsigned hSize = sizeof(handle_type); + char m_handles[NUM_CHORES * hSize]; + +public: + void Launch ( Concurrency::structured_task_group& rg ) { + ResetGlobals( false, false ); + for( unsigned i = 0; i < NUM_GROUPS; ++i ) { + handle_type *h = (handle_type*)(m_handles + i * hSize); + new ( h ) handle_type( StructuredLaunchChildren ); + rg.run( *h ); + } + ASSERT ( !Concurrency::is_current_task_group_canceling(), "Unexpected cancellation" ); + ASSERT ( !rg.is_canceling(), "Unexpected cancellation" ); +#if __TBB_SILENT_CANCELLATION_BROKEN + g_CancellationPropagationInProgress = true; +#endif + while ( g_MaxConcurrency > 1 && g_TaskCount == 0 ) + __TBB_Yield(); + } + + void Finish () { + for( unsigned i = 0; i < NUM_GROUPS; ++i ) + ((handle_type*)(m_handles + i * hSize))->~handle_type(); + ASSERT( g_TaskCount <= NUM_GROUPS * NUM_CHORES, "Too many tasks reported. The test is broken" ); + ASSERT( g_TaskCount < NUM_GROUPS * NUM_CHORES, "No tasks were cancelled. Cancellation model changed?" ); + ASSERT( g_TaskCount <= g_ExecutedAtCancellation + g_MaxConcurrency, "Too many tasks survived cancellation" ); + } +}; // StructuredCancellationTestDriver + +void TestStructuredCancellation1 () { + StructuredCancellationTestDriver driver; + Concurrency::structured_task_group sg; + driver.Launch( sg ); + sg.cancel(); + g_ExecutedAtCancellation = g_TaskCount; + ASSERT ( sg.is_canceling(), "No cancellation reported" ); + sg.wait(); + driver.Finish(); +} + +#if TBB_USE_EXCEPTIONS +#if defined(_MSC_VER) + #pragma warning (disable: 4127) +#endif + +template<bool Throw> +void TestStructuredCancellation2 () { + bool exception_occurred = false, + unexpected_exception = false; + StructuredCancellationTestDriver driver; + try { + Concurrency::structured_task_group tg; + driver.Launch( tg ); + if ( Throw ) + throw int(); // Initiate stack unwinding + } + catch ( const Concurrency::missing_wait& e ) { + ASSERT( e.what(), "Error message is absent" ); + exception_occurred = true; + unexpected_exception = Throw; + } + catch ( int ) { + exception_occurred = true; + unexpected_exception = !Throw; + } + catch ( ... ) { + exception_occurred = unexpected_exception = true; + } + ASSERT( exception_occurred, NULL ); + ASSERT( !unexpected_exception, NULL ); + driver.Finish(); +} +#endif /* TBB_USE_EXCEPTIONS */ + +void EmptyFunction () {} + +void TestStructuredWait () { + Concurrency::structured_task_group sg; + handle_type h(EmptyFunction); + sg.run(h); + sg.wait(); + handle_type h2(EmptyFunction); + sg.run(h2); + sg.wait(); +} + +int TestMain () { + REMARK ("Testing %s task_group functionality\n", TBBTEST_USE_TBB ? "TBB" : "PPL"); + for( int p=MinThread; p<=MaxThread; ++p ) { + g_MaxConcurrency = p; +#if TBBTEST_USE_TBB + tbb::task_scheduler_init init(p); +#else + Concurrency::SchedulerPolicy sp( 4, + Concurrency::SchedulerKind, Concurrency::ThreadScheduler, + Concurrency::MinConcurrency, 1, + Concurrency::MaxConcurrency, p, + Concurrency::TargetOversubscriptionFactor, 1); + Concurrency::Scheduler *s = Concurrency::Scheduler::Create( sp ); +#endif /* !TBBTEST_USE_TBB */ + if ( p > 1 ) { + TestParallelSpawn(); + TestParallelWait(); + TestVagabondGroup(); + } + TestFib1(); + TestFib2(); + TestTaskHandle(); + TestTaskHandle2<Concurrency::task_group>(); + TestTaskHandle2<Concurrency::structured_task_group>(); +#if __TBB_LAMBDAS_PRESENT + TestFibWithLambdas(); + TestFibWithMakeTask(); +#endif + TestCancellation1(); + TestStructuredCancellation1(); +#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN + TestEh1(); + TestEh2(); + TestStructuredWait(); + TestStructuredCancellation2<true>(); + TestStructuredCancellation2<false>(); +#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */ +#if !TBBTEST_USE_TBB + s->Release(); +#endif + } +#if __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN + REPORT("Known issue: exception handling tests are skipped.\n"); +#endif + return Harness::Done; +} + +#else /* !__TBB_TASK_GROUP_CONTEXT */ + +#include "harness.h" + +int TestMain () { + return Harness::Skipped; +} + +#endif /* !__TBB_TASK_GROUP_CONTEXT */ diff --git a/src/tbb/src/test/test_task_leaks.cpp b/src/tbb/src/test/test_task_leaks.cpp new file mode 100644 index 0000000..4aa4f30 --- /dev/null +++ b/src/tbb/src/test/test_task_leaks.cpp @@ -0,0 +1,293 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/* The test uses "single produces multiple consumers" (SPMC )pattern to check + if the memory of the tasks stolen by consumer threads is returned to the + producer thread and is reused. + + The test consists of a series of iterations, which execute a task tree. + the test fails is the memory consumption is not stabilized during some + number of iterations. + + After the memory consumption stabilized the memory state is perturbed by + switching producer thread, and the check is repeated. +*/ + +#if HARNESS_USE_PROXY + +// The test includes injects scheduler directly, so skip it when proxy tested. + +#undef HARNESS_USE_PROXY +#include "harness.h" + +int TestMain () { + return Harness::Skipped; +} + +#else // HARNESS_USE_PROXY + +#define __TBB_COUNT_TASK_NODES 1 +#include "harness_inject_scheduler.h" + +#include "tbb/atomic.h" +#include "harness_assert.h" +#include <cstdlib> + + +// Test configuration parameters + +//! Maximal number of test iterations +const int MaxIterations = 600; +//! Number of iterations during which the memory consumption must stabilize +const int AsymptoticRange = 100; +//! Number of times the memory state is perturbed to repeat the check +const int NumProducerSwitches = 2; +//! Number of iterations after which the success of producer switch is checked +const int ProducerCheckTimeout = 10; +//! Number of initial iteration used to collect statistics to be used in later checks +const int InitialStatsIterations = 20; + +tbb::atomic<int> Count; +tbb::atomic<tbb::task*> Exchanger; +tbb::internal::scheduler* Producer; + +#include "tbb/task_scheduler_init.h" + +#define HARNESS_DEFAULT_MIN_THREADS -1 +#include "harness.h" + +using namespace tbb; +using namespace tbb::internal; + +class ChangeProducer: public tbb::task { +public: + /*override*/ tbb::task* execute() { + if( is_stolen_task() ) { + Producer = internal::governor::local_scheduler(); + } + return NULL; + } +}; + +class TaskGenerator: public tbb::task { + const int my_child_count; + int my_depth; +public: + TaskGenerator(int child_count, int d) : my_child_count(child_count), my_depth(d) { + ASSERT(my_child_count>1, "The TaskGenerator should produce at least two children"); + } + /*override*/ tbb::task* execute() { + if( my_depth>0 ) { + int child_count = my_child_count; + scheduler* my_sched = internal::governor::local_scheduler(); + tbb::task& c = *new( allocate_continuation() ) tbb::empty_task; + c.set_ref_count( child_count ); + recycle_as_child_of(c); + --child_count; + if( Producer==my_sched ) { + // produce a task and put it into Exchanger + tbb::task* t = new( c.allocate_child() ) tbb::empty_task; + --child_count; + t = Exchanger.fetch_and_store(t); + if( t ) spawn(*t); + } else { + tbb::task* t = Exchanger.fetch_and_store(NULL); + if( t ) spawn(*t); + } + while( child_count ) { + tbb::task* t = new( c.allocate_child() ) TaskGenerator(my_child_count, my_depth-1); + if( my_depth >4 ) enqueue(*t); + else spawn(*t); + --child_count; + } + --my_depth; + return this; + } else { + tbb::task* t = Exchanger.fetch_and_store(NULL); + if( t ) spawn(*t); + return NULL; + } + } +}; + +#include "harness_memory.h" +#if _MSC_VER==1500 && !defined(__INTEL_COMPILER) + // VS2008/VC9 seems to have an issue + #pragma warning( push ) + #pragma warning( disable: 4985 ) +#endif +#include <math.h> +#if _MSC_VER==1500 && !defined(__INTEL_COMPILER) + #pragma warning( pop ) +#endif + +void RunTaskGenerators( bool switchProducer = false, bool checkProducer = false ) { + if( switchProducer ) + Producer = NULL; + tbb::task* dummy_root = new( tbb::task::allocate_root() ) tbb::empty_task; + dummy_root->set_ref_count( 2 ); + // If no producer, start elections; some worker will take the role + if( Producer ) + tbb::task::spawn( *new( dummy_root->allocate_child() ) tbb::empty_task ); + else + tbb::task::spawn( *new( dummy_root->allocate_child() ) ChangeProducer ); + if( checkProducer && !Producer ) + REPORT("Warning: producer has not changed after 10 attempts; running on a single core?\n"); + for( int j=0; j<100; ++j ) { + if( j&1 ) { + tbb::task& t = *new( tbb::task::allocate_root() ) TaskGenerator(/*child_count=*/4, /*depth=*/6); + tbb::task::spawn_root_and_wait(t); + } else { + tbb::task& t = *new (tbb::task::allocate_additional_child_of(*dummy_root)) + TaskGenerator(/*child_count=*/4, /*depth=*/6); + tbb::task::enqueue(t); + } + } + dummy_root->wait_for_all(); + tbb::task::destroy( *dummy_root ); +} + +class TaskList: public tbb::task { + const int my_num_childs; +public: + TaskList(const int num_childs) : my_num_childs(num_childs) {} + tbb::task* execute() { + tbb::task_list list; + for (int i=0; i<my_num_childs; ++i) + { + list.push_back( *new( allocate_child() ) tbb::empty_task ); + } + set_ref_count(my_num_childs+1); + spawn(list); + + wait_for_all(); + return 0; + } +}; + +void RunTaskListGenerator() +{ + const int max_num_childs = 10000; + int num_childs=3; + + while ( num_childs < max_num_childs ) + { + tbb::task& root = *new( tbb::task::allocate_root() ) TaskList(num_childs); + + tbb::task::spawn_root_and_wait(root); + + num_childs = 3 * num_childs; + } +} + +//! Tests whether task scheduler allows thieves to hoard task objects. +/** The test takes a while to run, so we run it only with the default + number of threads. */ +void TestTaskReclamation() { + REMARK("testing task reclamation\n"); + + size_t initial_amount_of_memory = 0; + double task_count_sum = 0; + double task_count_sum_square = 0; + double average, sigma; + + tbb::task_scheduler_init init (MinThread); + REMARK("Starting with %d threads\n", MinThread); + // For now, the master will produce "additional" tasks; later a worker will replace it; + Producer = internal::governor::local_scheduler(); + int N = InitialStatsIterations; + // First N iterations fill internal buffers and collect initial statistics + for( int i=0; i<N; ++i ) { + // First N iterations fill internal buffers and collect initial statistics + RunTaskGenerators(); + RunTaskListGenerator(); + + size_t m = GetMemoryUsage(); + if( m-initial_amount_of_memory > 0) + initial_amount_of_memory = m; + + intptr_t n = internal::governor::local_scheduler()->get_task_node_count( /*count_arena_workers=*/true ); + task_count_sum += n; + task_count_sum_square += n*n; + + REMARK( "Consumed %ld bytes and %ld objects (iteration=%d)\n", long(m), long(n), i ); + } + // Calculate statistical values + average = task_count_sum / N; + sigma = sqrt( (task_count_sum_square - task_count_sum*task_count_sum/N)/N ); + REMARK("Average task count: %g, sigma: %g, sum: %g, square sum:%g \n", average, sigma, task_count_sum, task_count_sum_square); + + int last_error_iteration = 0, + producer_switch_iteration = 0, + producer_switches = 0; + bool switchProducer = false, + checkProducer = false; + for( int i=0; i < MaxIterations; ++i ) { + // These iterations check for excessive memory use and unreasonable task count + RunTaskGenerators( switchProducer, checkProducer ); + RunTaskListGenerator(); + + intptr_t n = internal::governor::local_scheduler()->get_task_node_count( /*count_arena_workers=*/true ); + size_t m = GetMemoryUsage(); + + if( (m-initial_amount_of_memory > 0) && (n > average+4*sigma) ) { + // Use 4*sigma interval (for normal distribution, 3*sigma contains ~99% of values). + REMARK( "Warning: possible leak of up to %ld bytes; currently %ld cached task objects (iteration=%d)\n", + static_cast<unsigned long>(m-initial_amount_of_memory), long(n), i ); + last_error_iteration = i; + initial_amount_of_memory = m; + } else { + REMARK( "Consumed %ld bytes and %ld objects (iteration=%d)\n", long(m), long(n), i ); + } + if ( i == last_error_iteration + AsymptoticRange ) { + if ( producer_switches++ == NumProducerSwitches ) + break; + else { + last_error_iteration = producer_switch_iteration = i; + switchProducer = true; + } + } + else { + switchProducer = false; + checkProducer = producer_switch_iteration && (i == producer_switch_iteration + ProducerCheckTimeout); + } + } + ASSERT( last_error_iteration < MaxIterations - AsymptoticRange, "The amount of allocated tasks keeps growing. Leak is possible." ); +} + +int TestMain () { + if( !GetMemoryUsage() ) { + REMARK("GetMemoryUsage is not implemented for this platform\n"); + return Harness::Skipped; + } + TestTaskReclamation(); + return Harness::Done; +} + +#endif // HARNESS_USE_PROXY + diff --git a/src/tbb/src/test/test_task_priority.cpp b/src/tbb/src/test/test_task_priority.cpp new file mode 100644 index 0000000..6c98ea0 --- /dev/null +++ b/src/tbb/src/test/test_task_priority.cpp @@ -0,0 +1,481 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "harness.h" + +#if __TBB_TASK_GROUP_CONTEXT + +#include "tbb/task.h" +#include "tbb/task_scheduler_init.h" +#include "tbb/atomic.h" +#include <cstdlib> + +const int NumIterations = 100; +const int NumLeafTasks = 2; +int MinBaseDepth = 9; +int MaxBaseDepth = 11; +int BaseDepth = 0; + +const int NumTests = 8; +const int TestRepeats = 4; + +int g_NumMasters = 0; +volatile intptr_t *g_LeavesExecuted = NULL; + +int g_TestFailures[NumTests]; +int g_CurConfig = 0; + +int P = 0; + +#if !__TBB_TASK_PRIORITY +namespace tbb { + enum priority_t { + priority_low = 0, + priority_normal = 1, + priority_high = 2 + }; +} +#endif /* __TBB_TASK_PRIORITY */ + +tbb::priority_t Low = tbb::priority_normal, + High = tbb::priority_high; +int PreemptionActivatorId = 1; + +enum Options { + NoPriorities = 0, + TestPreemption = 1, + Flog = 2, + FlogEncloser = Flog | 4 +}; + +const char *PriorityName(tbb::priority_t p) { + if( p == tbb::priority_high ) return "high"; + if( p == tbb::priority_normal ) return "normal"; + if( p == tbb::priority_low ) return "low"; + return "bad"; +} + +void PrepareGlobals ( int numMasters ) { + ASSERT( !g_NumMasters && !g_LeavesExecuted, NULL ); + g_NumMasters = numMasters; + if ( !g_LeavesExecuted ) + g_LeavesExecuted = new intptr_t[numMasters]; + g_CurConfig = 0; + memset( const_cast<intptr_t*>(g_LeavesExecuted), 0, sizeof(intptr_t) * numMasters ); + memset( g_TestFailures, 0, sizeof(int) * NumTests ); +} + +void ClearGlobals () { + ASSERT( g_LeavesExecuted, NULL ); + delete [] g_LeavesExecuted; + g_LeavesExecuted = NULL; + g_NumMasters = 0; + REMARK("\r \r"); +} + +class LeafTask : public tbb::task { + int m_tid; + uintptr_t m_opts; + + tbb::task* execute () { + volatile int anchor = 0; + for ( int i = 0; i < NumIterations; ++i ) + anchor += i; + __TBB_FetchAndAddW(g_LeavesExecuted + m_tid, 1); +#if __TBB_TASK_PRIORITY + ASSERT( !m_opts || (m_opts & Flog) || (!(m_opts & TestPreemption) ^ (m_tid == PreemptionActivatorId)), NULL ); + if ( (m_opts & TestPreemption) && g_LeavesExecuted[0] > P && group_priority() == tbb::priority_normal ) { + ASSERT( m_tid == PreemptionActivatorId, NULL ); + ASSERT( (PreemptionActivatorId == 1 ? High > tbb::priority_normal : Low < tbb::priority_normal), NULL ); + set_group_priority( PreemptionActivatorId == 1 ? High : Low ); + } +#endif /* __TBB_TASK_PRIORITY */ + return NULL; + } +public: + LeafTask ( int tid, uintptr_t opts ) : m_tid(tid), m_opts(opts) { + ASSERT( tid < g_NumMasters, NULL ); + } +}; + +template<class NodeType> +class NodeTask : public tbb::task { +protected: + int m_tid; + int m_depth; + uintptr_t m_opts; + task *m_root; + + void SpawnChildren ( task* parent_node ) { + ASSERT( m_depth > 0, NULL ); + if ( g_LeavesExecuted[m_tid] % (100 / m_depth) == 0 ) { + if ( m_opts & Flog ) { +#if __TBB_TASK_PRIORITY + task *r = m_opts & FlogEncloser ? this : m_root; + tbb::priority_t p = r->group_priority(); + r->set_group_priority( p == Low ? High : Low ); +#endif /* __TBB_TASK_PRIORITY */ + } + else + __TBB_Yield(); + } + parent_node->set_ref_count(NumLeafTasks + 1); + --m_depth; + for ( int i = 0; i < NumLeafTasks; ++i ) { + task *t = m_depth ? (task*) new(parent_node->allocate_child()) NodeType(m_tid, m_depth, m_opts, m_root) + : (task*) new(parent_node->allocate_child()) LeafTask(m_tid, m_opts); + task::spawn(*t); + } + } + +public: + NodeTask ( int tid, int _depth, uintptr_t opts, task *r = NULL ) + : m_tid(tid), m_depth(_depth), m_opts(opts), m_root(r) + {} +}; + +class NestedGroupNodeTask : public NodeTask<NestedGroupNodeTask> { + task* execute () { + tbb::task_group_context ctx; // Use bound context + tbb::empty_task &r = *new( task::allocate_root(ctx) ) tbb::empty_task; + SpawnChildren(&r); + r.wait_for_all(); + task::destroy(r); + return NULL; + } +public: + NestedGroupNodeTask ( int tid, int _depth, uintptr_t opts, task *r = NULL ) + : NodeTask<NestedGroupNodeTask>(tid, _depth, opts, r) + {} +}; + +class BlockingNodeTask : public NodeTask<BlockingNodeTask> { + task* execute () { + SpawnChildren(this); + wait_for_all(); + return NULL; + } +public: + BlockingNodeTask ( int tid, int _depth, uintptr_t opts, task *r = NULL ) + : NodeTask<BlockingNodeTask>(tid, _depth, opts, r) {} +}; + +class NonblockingNodeTask : public NodeTask<NonblockingNodeTask> { + task* execute () { + if ( m_depth < 0 ) + return NULL; // I'm just a continuation now + recycle_as_safe_continuation(); + SpawnChildren(this); + m_depth = -1; + return NULL; + } +public: + NonblockingNodeTask ( int tid, int _depth, uintptr_t opts, task *r = NULL ) + : NodeTask<NonblockingNodeTask>(tid, _depth, opts, r) + {} +}; + +template<class NodeType> +class MasterBodyBase : NoAssign, Harness::NoAfterlife { +protected: + uintptr_t m_opts; + +public: + void RunTaskForest ( int id ) const { + ASSERT( id < g_NumMasters, NULL ); + g_LeavesExecuted[id] = 0; + int d = BaseDepth + id; + tbb::task_scheduler_init init(P-1); + tbb::task_group_context ctx (tbb::task_group_context::isolated); + tbb::empty_task &r = *new( tbb::task::allocate_root(ctx) ) tbb::empty_task; + const int R = 4; + r.set_ref_count( R * P + 1 ); + // Only thread 1 changes its task tree priority in preemption test mode + uintptr_t opts = m_opts & (id == PreemptionActivatorId ? ~0u : ~(uintptr_t)TestPreemption); + for ( int i = 0; i < R; ++i ) { + for ( int j = 1; j < P; ++j ) + r.spawn( *new(r.allocate_child()) NodeType(id, MinBaseDepth + id, opts, &r) ); + r.spawn( *new(r.allocate_child()) NodeType(id, d, opts, &r) ); + } + int count = 1; + intptr_t lastExecuted = 0; + while ( r.ref_count() > 1 ) { + // Give workers time to make some progress. + for ( int i = 0; i < 10 * count; ++i ) + __TBB_Yield(); +#if __TBB_TASK_PRIORITY + if ( lastExecuted == g_LeavesExecuted[id] ) { + // No progress. Likely all workers left to higher priority arena, + // and then returned to RML. Request workers back from RML. + tbb::task::enqueue( *new(tbb::task::allocate_root() ) tbb::empty_task, id == 0 ? Low : High ); + Harness::Sleep(count); +#if __TBB_ipf + // Increased sleep periods are required on systems with unfair hyperthreading (Itanium(R) 2 processor) + count += 10; +#endif + } + else { + count = 1; + lastExecuted = g_LeavesExecuted[id]; + } +#else /* !__TBB_TASK_PRIORITY */ + (void)lastExecuted; + tbb::task::enqueue( *new(tbb::task::allocate_root() ) tbb::empty_task ); +#endif /* !__TBB_TASK_PRIORITY */ + } + ASSERT( g_LeavesExecuted[id] == R * ((1 << d) + ((P - 1) * (1 << (MinBaseDepth + id)))), NULL ); + g_LeavesExecuted[id] = -1; + tbb::task::destroy(r); + } + + MasterBodyBase ( uintptr_t opts ) : m_opts(opts) {} +}; + +template<class NodeType> +class MasterBody : public MasterBodyBase<NodeType> { + int m_testIndex; +public: + void operator() ( int id ) const { + this->RunTaskForest(id); + if ( this->m_opts & Flog ) + return; + if ( this->m_opts & TestPreemption ) { + if ( id == 1 && g_LeavesExecuted[0] == -1 ) { + //REMARK( "Warning: Low priority master finished too early [depth %d]\n", Depth ); + ++g_TestFailures[m_testIndex]; + } + } + else { + if ( id == 0 && g_LeavesExecuted[1] == -1 ) { + //REMARK( "Warning: Faster master takes too long [depth %d]\n", Depth ); + ++g_TestFailures[m_testIndex]; + } + } + } + + MasterBody ( int idx, uintptr_t opts ) : MasterBodyBase<NodeType>(opts), m_testIndex(idx) {} +}; + +template<class NodeType> +void RunPrioritySwitchBetweenTwoMasters ( int idx, uintptr_t opts ) { + ASSERT( idx < NumTests, NULL ); + REMARK( "Config %d\r", ++g_CurConfig ); + NativeParallelFor ( 2, MasterBody<NodeType>(idx, opts) ); + Harness::Sleep(50); +} + +void TestPrioritySwitchBetweenTwoMasters () { + REMARK( "Stress tests: %s / %s \n", Low == tbb::priority_low ? "Low" : "Normal", High == tbb::priority_normal ? "Normal" : "High" ); + PrepareGlobals( 2 ); + for ( int i = 0; i < TestRepeats; ++i ) { + for ( BaseDepth = MinBaseDepth; BaseDepth <= MaxBaseDepth; ++BaseDepth ) { + RunPrioritySwitchBetweenTwoMasters<BlockingNodeTask>( 0, NoPriorities ); + RunPrioritySwitchBetweenTwoMasters<BlockingNodeTask>( 1, TestPreemption ); + RunPrioritySwitchBetweenTwoMasters<NonblockingNodeTask>( 2, NoPriorities ); + RunPrioritySwitchBetweenTwoMasters<NonblockingNodeTask>( 3, TestPreemption ); + if ( i == 0 ) { + RunPrioritySwitchBetweenTwoMasters<BlockingNodeTask>( 4, Flog ); + RunPrioritySwitchBetweenTwoMasters<NonblockingNodeTask>( 5, Flog ); + RunPrioritySwitchBetweenTwoMasters<NestedGroupNodeTask>( 6, Flog ); + RunPrioritySwitchBetweenTwoMasters<NestedGroupNodeTask>( 7, FlogEncloser ); + } + } + } +#if __TBB_TASK_PRIORITY + const int NumRuns = TestRepeats * (MaxBaseDepth - MinBaseDepth + 1); + for ( int i = 0; i < NumTests; ++i ) { + if ( g_TestFailures[i] ) + REMARK( "Test %d: %d failures in %d runs\n", i, g_TestFailures[i], NumRuns ); + if ( g_TestFailures[i] * 100 / NumRuns > 50 ) { + if ( i == 1 ) + REPORT( "Known issue: priority effect is limited in case of blocking-style nesting\n" ); + else + REPORT( "Warning: test %d misbehaved too often (%d out of %d)\n", i, g_TestFailures[i], NumRuns ); + } + } +#endif /* __TBB_TASK_PRIORITY */ + ClearGlobals(); +} + +class SingleChildRootTask : public tbb::task { + tbb::task* execute () { + set_ref_count(2); + spawn ( *new(allocate_child()) tbb::empty_task ); + wait_for_all(); + return NULL; + } +}; + +int TestSimplePriorityOps ( tbb::priority_t prio ) { + tbb::task_scheduler_init init; + tbb::task_group_context ctx; +#if __TBB_TASK_PRIORITY + ctx.set_priority( prio ); +#else /* !__TBB_TASK_PRIORITY */ + (void)prio; +#endif /* !__TBB_TASK_PRIORITY */ + tbb::task *r = new( tbb::task::allocate_root(ctx) ) tbb::empty_task; + r->set_ref_count(2); + r->spawn ( *new(r->allocate_child()) tbb::empty_task ); + REMARK( "TestSimplePriorityOps: waiting for a child\n" ); + r->wait_for_all(); + ASSERT( !r->ref_count(), NULL ); + REMARK( "TestLowPriority: executing an empty root\n" ); + tbb::task::spawn_root_and_wait(*r); + r = new( tbb::task::allocate_root(ctx) ) SingleChildRootTask; + REMARK( "TestLowPriority: executing a root with a single child\n" ); + tbb::task::spawn_root_and_wait(*r); + return 0; +} + +#include "tbb/parallel_for.h" + +void EmulateWork( int ) { + for ( int i = 0; i < 1000; ++i ) + __TBB_Yield(); +} + +class PeriodicActivitiesBody { +public: + void operator() ( int id ) const { + tbb::task_group_context ctx; +#if __TBB_TASK_PRIORITY + ctx.set_priority( id ? High : Low ); +#else /* !__TBB_TASK_PRIORITY */ + (void)id; +#endif /* !__TBB_TASK_PRIORITY */ + for ( int i = 0; i < 5; ++i ) { + tbb::task_scheduler_init init; + tbb::parallel_for( 1, 10000, &EmulateWork, ctx ); + } + } +}; + +void TestPeriodicConcurrentActivities () { + REMARK( "TestPeriodicConcurrentActivities: %s / %s \n", Low == tbb::priority_low ? "Low" : "Normal", High == tbb::priority_normal ? "Normal" : "High" ); + NativeParallelFor ( 2, PeriodicActivitiesBody() ); +} + +#include "harness_bad_expr.h" + +void TestPriorityAssertions () { +#if TRY_BAD_EXPR_ENABLED && __TBB_TASK_PRIORITY + REMARK( "TestPriorityAssertions\n" ); + tbb::priority_t bad_low_priority = tbb::priority_t( tbb::priority_low - 1 ), + bad_high_priority = tbb::priority_t( tbb::priority_high + 1 ); + tbb::task_group_context ctx; + // Catch assertion failures + tbb::set_assertion_handler( AssertionFailureHandler ); + TRY_BAD_EXPR( ctx.set_priority( bad_low_priority ), "Invalid priority level value" ); + tbb::task &t = *new( tbb::task::allocate_root() ) tbb::empty_task; + TRY_BAD_EXPR( tbb::task::enqueue( t, bad_high_priority ), "Invalid priority level value" ); + // Restore normal assertion handling + tbb::set_assertion_handler( NULL ); +#endif /* TRY_BAD_EXPR_ENABLED && __TBB_TASK_PRIORITY */ +} + +#if __TBB_TASK_PRIORITY +tbb::atomic<tbb::priority_t> g_order; +tbb::atomic<bool> g_order_established; +class OrderedTask : public tbb::task { + tbb::priority_t my_priority; +public: + OrderedTask(tbb::priority_t p) : my_priority(p) {} + tbb::task* execute() { + tbb::priority_t prev = g_order.fetch_and_store(my_priority); + if( my_priority != prev) { + REMARK("prev:%s --> new:%s\n", PriorityName(prev), PriorityName(my_priority)); + // TODO: improve the test for concurrent workers + if(!g_order_established) { + // initial transition path allowed low->[normal]->high + if(my_priority == tbb::priority_high) + g_order_established = true; + else ASSERT(my_priority == tbb::priority_normal && prev == tbb::priority_low, NULL); + } else { //transition path allowed high->normal->low + if(prev == tbb::priority_high) ASSERT( my_priority == tbb::priority_normal, "previous priority is high - bad order"); + else if(prev == tbb::priority_normal) ASSERT( my_priority == tbb::priority_low, "previous priority is normal - bad order"); + else ASSERT(!g_order_established, "transition from low priority but not during initialization"); + } + } + EmulateWork(0); + return NULL; + } + static void start(int i) { + tbb::priority_t p = i%3==0? tbb::priority_low : (i%3==1? tbb::priority_normal : tbb::priority_high ); + OrderedTask &t = *new(tbb::task::allocate_root()) OrderedTask(p); + tbb::task::enqueue(t, p); + } +}; + +//Look for discussion of the issue at http://software.intel.com/en-us/forums/showthread.php?t=102159 +void TestEnqueueOrder () { + REMARK("Testing order of enqueued tasks\n"); + tbb::task_scheduler_init init(1); // to simplify transition checks only one extra worker for enqueue + g_order = tbb::priority_low; + g_order_established = false; + for( int i = 0; i < 1000; i++) + OrderedTask::start(i); + while( g_order == tbb::priority_low ) __TBB_Yield(); + while( g_order != tbb::priority_low ) __TBB_Yield(); +} +#endif /* __TBB_TASK_PRIORITY */ + +int TestMain () { +#if !__TBB_TASK_PRIORITY + REMARK( "Priorities disabled: Running as just yet another task scheduler test\n" ); +#else + TestEnqueueOrder(); +#endif /* __TBB_TASK_PRIORITY */ + TestPriorityAssertions(); + TestSimplePriorityOps(tbb::priority_low); + TestSimplePriorityOps(tbb::priority_high); + P = tbb::task_scheduler_init::default_num_threads(); + if ( P < 3 ) + return Harness::Skipped; + TestPeriodicConcurrentActivities(); + TestPrioritySwitchBetweenTwoMasters(); + Low = tbb::priority_low; + High = tbb::priority_normal; + PreemptionActivatorId = 0; + TestPeriodicConcurrentActivities(); + TestPrioritySwitchBetweenTwoMasters(); + High = tbb::priority_high; + TestPeriodicConcurrentActivities(); + TestPrioritySwitchBetweenTwoMasters(); + PreemptionActivatorId = 1; + TestPrioritySwitchBetweenTwoMasters(); + return Harness::Done; +} + +#else /* !__TBB_TASK_GROUP_CONTEXT */ + +int TestMain () { + return Harness::Skipped; +} + +#endif /* !__TBB_TASK_GROUP_CONTEXT */ diff --git a/src/tbb/src/test/test_task_scheduler_init.cpp b/src/tbb/src/test/test_task_scheduler_init.cpp new file mode 100644 index 0000000..57bf015 --- /dev/null +++ b/src/tbb/src/test/test_task_scheduler_init.cpp @@ -0,0 +1,151 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/task_scheduler_init.h" +#include <cstdlib> +#include "harness_assert.h" + +#include <cstdio> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include <stdexcept> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +#include "harness.h" + +//! Test that task::initialize and task::terminate work when doing nothing else. +/** maxthread is treated as the "maximum" number of worker threads. */ +void InitializeAndTerminate( int maxthread ) { + __TBB_TRY { + for( int i=0; i<200; ++i ) { + switch( i&3 ) { + default: { + tbb::task_scheduler_init init( std::rand() % maxthread + 1 ); + ASSERT(init.is_active(), NULL); + break; + } + case 0: { + tbb::task_scheduler_init init; + ASSERT(init.is_active(), NULL); + break; + } + case 1: { + tbb::task_scheduler_init init( tbb::task_scheduler_init::automatic ); + ASSERT(init.is_active(), NULL); + break; + } + case 2: { + tbb::task_scheduler_init init( tbb::task_scheduler_init::deferred ); + ASSERT(!init.is_active(), "init should not be active; initialization was deferred"); + init.initialize( std::rand() % maxthread + 1 ); + ASSERT(init.is_active(), NULL); + init.terminate(); + ASSERT(!init.is_active(), "init should not be active; it was terminated"); + break; + } + } + } + } __TBB_CATCH( std::runtime_error& error ) { +#if TBB_USE_EXCEPTIONS + REPORT("ERROR: %s\n", error.what() ); +#endif /* TBB_USE_EXCEPTIONS */ + } +} + +#if _WIN64 +namespace std { // 64-bit Windows compilers have not caught up with 1998 ISO C++ standard + using ::srand; +} +#endif /* _WIN64 */ + +struct ThreadedInit { + void operator()( int ) const { + InitializeAndTerminate(MaxThread); + } +}; + +#if _MSC_VER +#include "tbb/machine/windows_api.h" +#include <tchar.h> +#endif /* _MSC_VER */ + +#include "harness_concurrency_tracker.h" +#include "tbb/parallel_for.h" +#include "tbb/blocked_range.h" + +typedef tbb::blocked_range<int> Range; + +class ConcurrencyTrackingBody { +public: + void operator() ( const Range& ) const { + Harness::ConcurrencyTracker ct; + for ( volatile int i = 0; i < 1000000; ++i ) + ; + } +}; + +/** The test will fail in particular if task_scheduler_init mistakenly hooks up + auto-initialization mechanism. **/ +void AssertExplicitInitIsNotSupplanted () { + int hardwareConcurrency = tbb::task_scheduler_init::default_num_threads(); + tbb::task_scheduler_init init(1); + Harness::ConcurrencyTracker::Reset(); + tbb::parallel_for( Range(0, hardwareConcurrency * 2, 1), ConcurrencyTrackingBody(), tbb::simple_partitioner() ); + ASSERT( Harness::ConcurrencyTracker::PeakParallelism() == 1, + "Manual init provided more threads than requested. See also the comment at the beginning of main()." ); +} + +int TestMain () { + // Do not use tbb::task_scheduler_init directly in the scope of main's body, + // as a static variable, or as a member of a static variable. +#if _MSC_VER && !__TBB_NO_IMPLICIT_LINKAGE && !defined(__TBB_LIB_NAME) + #ifdef _DEBUG + ASSERT(!GetModuleHandle(_T("tbb.dll")) && GetModuleHandle(_T("tbb_debug.dll")), + "test linked with wrong (non-debug) tbb library"); + #else + ASSERT(!GetModuleHandle(_T("tbb_debug.dll")) && GetModuleHandle(_T("tbb.dll")), + "test linked with wrong (debug) tbb library"); + #endif +#endif /* _MSC_VER && !__TBB_NO_IMPLICIT_LINKAGE && !__TBB_LIB_NAME */ + std::srand(2); + InitializeAndTerminate(MaxThread); + for( int p=MinThread; p<=MaxThread; ++p ) { + REMARK("testing with %d threads\n", p ); + NativeParallelFor( p, ThreadedInit() ); + } + AssertExplicitInitIsNotSupplanted(); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_task_scheduler_observer.cpp b/src/tbb/src/test/test_task_scheduler_observer.cpp new file mode 100644 index 0000000..16e2170 --- /dev/null +++ b/src/tbb/src/test/test_task_scheduler_observer.cpp @@ -0,0 +1,128 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/task_scheduler_observer.h" + +typedef uintptr_t FlagType; +const int MaxFlagIndex = sizeof(FlagType)*8-1; + +class MyObserver: public tbb::task_scheduler_observer { + FlagType flags; + /*override*/ void on_scheduler_entry( bool is_worker ); + /*override*/ void on_scheduler_exit( bool is_worker ); +public: + MyObserver( FlagType flags_ ) : flags(flags_) { + observe(true); + } +}; + +#include "harness_assert.h" +#include "tbb/atomic.h" + +tbb::atomic<int> EntryCount; +tbb::atomic<int> ExitCount; + +struct State { + FlagType MyFlags; + bool IsMaster; + State() : MyFlags(), IsMaster() {} +}; + +#include "../tbb/tls.h" +tbb::internal::tls<State*> LocalState; + +void MyObserver::on_scheduler_entry( bool is_worker ) { + State& state = *LocalState; + ASSERT( is_worker==!state.IsMaster, NULL ); + ++EntryCount; + state.MyFlags |= flags; +} + +void MyObserver::on_scheduler_exit( bool is_worker ) { + State& state = *LocalState; + ASSERT( is_worker==!state.IsMaster, NULL ); + ++ExitCount; + state.MyFlags &= ~flags; +} + +#include "tbb/task.h" + +class FibTask: public tbb::task { + const int n; + FlagType flags; +public: + FibTask( int n_, FlagType flags_ ) : n(n_), flags(flags_) {} + /*override*/ tbb::task* execute() { + ASSERT( !(~LocalState->MyFlags & flags), NULL ); + if( n>=2 ) { + set_ref_count(3); + spawn(*new( allocate_child() ) FibTask(n-1,flags)); + spawn_and_wait_for_all(*new( allocate_child() ) FibTask(n-2,flags)); + } + return NULL; + } +}; + +void DoFib( FlagType flags ) { + tbb::task* t = new( tbb::task::allocate_root() ) FibTask(10,flags); + tbb::task::spawn_root_and_wait(*t); +} + +#include "tbb/task_scheduler_init.h" +#include "harness.h" + +class DoTest { + int nthread; +public: + DoTest( int n ) : nthread(n) {} + void operator()( int i ) const { + LocalState->IsMaster = true; + if( i==0 ) { + tbb::task_scheduler_init init(nthread); + DoFib(0); + } else { + FlagType f = i<=MaxFlagIndex? 1<<i : 0; + MyObserver w(f); + tbb::task_scheduler_init init(nthread); + DoFib(f); + } + } +}; + +void TestObserver( int p, int q ) { + NativeParallelFor( p, DoTest(q) ); +} + +int TestMain () { + for( int p=MinThread; p<=MaxThread; ++p ) + for( int q=MinThread; q<=MaxThread; ++q ) + TestObserver(p,q); + ASSERT( EntryCount>0, "on_scheduler_entry not exercised" ); + ASSERT( ExitCount>0, "on_scheduler_exit not exercised" ); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_task_steal_limit.cpp b/src/tbb/src/test/test_task_steal_limit.cpp new file mode 100644 index 0000000..5cb22c6 --- /dev/null +++ b/src/tbb/src/test/test_task_steal_limit.cpp @@ -0,0 +1,81 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/task.h" +#include "harness.h" +#include "tbb/task_scheduler_init.h" + +using tbb::task; + +#if __TBB_ipf + const unsigned StackSize = 1024*1024*6; +#else /* */ + const unsigned StackSize = 1024*1024*3; +#endif + +// GCC and ICC on Linux store TLS data in the stack space. This test makes sure +// that the stealing limiting heuristic used by the task scheduler does not +// switch off stealing when a large amount of TLS data is reserved. +#if _MSC_VER +__declspec(thread) +#elif __linux__ || ((__MINGW32__ || __MINGW64__) && __TBB_GCC_VERSION >= 40500) +__thread +#endif + char map2[1024*1024*2]; + +class TestTask : public task { +public: + static volatile int completed; + task* execute() { + completed = 1; + return NULL; + }; +}; + +volatile int TestTask::completed = 0; + +void TestStealingIsEnabled () { + tbb::task_scheduler_init init(2, StackSize); + task &r = *new( task::allocate_root() ) tbb::empty_task; + task &t = *new( r.allocate_child() ) TestTask; + r.set_ref_count(2); + r.spawn(t); + int count = 0; + while ( !TestTask::completed && ++count < 6 ) + Harness::Sleep(1000); + ASSERT( TestTask::completed, "Stealing is disabled or the machine is heavily oversubscribed" ); + r.wait_for_all(); + task::destroy(r); +} + +int TestMain () { + if ( tbb::task_scheduler_init::default_num_threads() == 1 ) + return Harness::Skipped; + TestStealingIsEnabled(); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_tbb_condition_variable.cpp b/src/tbb/src/test/test_tbb_condition_variable.cpp new file mode 100644 index 0000000..b2e8a89 --- /dev/null +++ b/src/tbb/src/test/test_tbb_condition_variable.cpp @@ -0,0 +1,45 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/tbb_config.h" + +#if !TBB_IMPLEMENT_CPP0X +#include "harness.h" + +int TestMain() { + return Harness::Skipped; +} +#else +#include "test_condition_variable.h" + +int TestMain() { + REMARK( "testing with tbb condvar\n" ); + DoCondVarTest<tbb::mutex,tbb::recursive_mutex>(); + return Harness::Done; +} +#endif diff --git a/src/tbb/src/test/test_tbb_header.cpp b/src/tbb/src/test/test_tbb_header.cpp new file mode 100644 index 0000000..38794dd --- /dev/null +++ b/src/tbb/src/test/test_tbb_header.cpp @@ -0,0 +1,212 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +/** + This test ensures that tbb.h brings in all the public TBB interface definitions, + and if all the necessary symbols are exported from the library. + + Most of the checks happen at the compilation or link phases. +**/ + +#include "tbb/tbb.h" +#if _MSC_VER +#pragma warning (disable : 4503) // decorated name length exceeded, name was truncated +#endif +#include "tbb/flow_graph.h" + +static volatile size_t g_sink; + +#define TestTypeDefinitionPresence( Type ) g_sink = sizeof(tbb::Type); +#define TestTypeDefinitionPresence2(TypeStart, TypeEnd) g_sink = sizeof(tbb::TypeStart,TypeEnd); +#define TestFuncDefinitionPresence(Fn, Args, ReturnType) { ReturnType (*pfn)Args = &tbb::Fn; (void)pfn; } + +//! Utility template function to prevent "unused" warnings by various compilers. +template<typename T> void squelch_unused_warning( const T& ) {} + +struct Body { + void operator() () const {} +}; +struct Body1 { + void operator() ( int ) const {} +}; +struct Body1a { + int operator() ( const tbb::blocked_range<int>&, const int ) const { return 0; } +}; +struct Body1b { + int operator() ( const int, const int ) const { return 0; } +}; +struct Body2 { + Body2 () {} + Body2 ( const Body2&, tbb::split ) {} + void operator() ( const tbb::blocked_range<int>& ) const {} + void join( const Body2& ) {} +}; +struct Body3 { + Body3 () {} + Body3 ( const Body3&, tbb::split ) {} + void operator() ( const tbb::blocked_range2d<int>&, tbb::pre_scan_tag ) const {} + void operator() ( const tbb::blocked_range2d<int>&, tbb::final_scan_tag ) const {} + void reverse_join( Body3& ) {} + void assign( const Body3& ) {} +}; + +#if !__TBB_TEST_SECONDARY + +#define HARNESS_NO_PARSE_COMMAND_LINE 1 +#include "harness.h" + +// Test if all the necessary symbols are exported for the exceptions thrown by TBB. +// Missing exports result either in link error or in runtime assertion failure. +#include "tbb/tbb_exception.h" + +template <typename E> +void TestExceptionClassExports ( const E& exc, tbb::internal::exception_id eid ) { + // The assertion here serves to shut up warnings about "eid not used". + ASSERT( eid<tbb::internal::eid_max, NULL ); +#if TBB_USE_EXCEPTIONS + for ( int i = 0; i < 2; ++i ) { + try { + if ( i == 0 ) + throw exc; +#if !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN + else + tbb::internal::throw_exception( eid ); +#endif + } + catch ( E& e ) { + ASSERT ( e.what(), "Missing what() string" ); + } + catch ( ... ) { + ASSERT ( __TBB_EXCEPTION_TYPE_INFO_BROKEN, "Unrecognized exception. Likely RTTI related exports are missing" ); + } + } +#else /* !TBB_USE_EXCEPTIONS */ + (void)exc; +#endif /* !TBB_USE_EXCEPTIONS */ +} + +void TestExceptionClassesExports () { + TestExceptionClassExports( std::bad_alloc(), tbb::internal::eid_bad_alloc ); + TestExceptionClassExports( tbb::bad_last_alloc(), tbb::internal::eid_bad_last_alloc ); + TestExceptionClassExports( std::invalid_argument("test"), tbb::internal::eid_nonpositive_step ); + TestExceptionClassExports( std::out_of_range("test"), tbb::internal::eid_out_of_range ); + TestExceptionClassExports( std::range_error("test"), tbb::internal::eid_segment_range_error ); + TestExceptionClassExports( std::range_error("test"), tbb::internal::eid_index_range_error ); + TestExceptionClassExports( tbb::missing_wait(), tbb::internal::eid_missing_wait ); + TestExceptionClassExports( tbb::invalid_multiple_scheduling(), tbb::internal::eid_invalid_multiple_scheduling ); + TestExceptionClassExports( tbb::improper_lock(), tbb::internal::eid_improper_lock ); +} +#endif /* !__TBB_TEST_SECONDARY */ + +#if __TBB_TEST_SECONDARY +/* This mode is used to produce a secondary object file that is linked with + the main one in order to detect "multiple definition" linker error. +*/ +void secondary() +#else +int TestMain () +#endif +{ + TestTypeDefinitionPresence2(aligned_space<int, 1> ); + TestTypeDefinitionPresence( atomic<int> ); + TestTypeDefinitionPresence( cache_aligned_allocator<int> ); + TestTypeDefinitionPresence( tbb_hash_compare<int> ); + TestTypeDefinitionPresence2(concurrent_hash_map<int, int> ); + TestTypeDefinitionPresence2(concurrent_unordered_map<int, int> ); + TestTypeDefinitionPresence( concurrent_bounded_queue<int> ); + TestTypeDefinitionPresence( deprecated::concurrent_queue<int> ); + TestTypeDefinitionPresence( strict_ppl::concurrent_queue<int> ); + TestTypeDefinitionPresence( combinable<int> ); + TestTypeDefinitionPresence( concurrent_vector<int> ); + TestTypeDefinitionPresence( enumerable_thread_specific<int> ); + TestTypeDefinitionPresence( flow::graph ); + TestTypeDefinitionPresence( flow::source_node<int> ); + TestTypeDefinitionPresence2( flow::function_node<int, int> ); + typedef std::tuple<int, int> intpair; + TestTypeDefinitionPresence2( flow::multifunction_node<int, intpair> ); + TestTypeDefinitionPresence( flow::split_node<intpair> ); + TestTypeDefinitionPresence( flow::continue_node<int> ); + TestTypeDefinitionPresence( flow::overwrite_node<int> ); + TestTypeDefinitionPresence( flow::write_once_node<int> ); + TestTypeDefinitionPresence( flow::broadcast_node<int> ); + TestTypeDefinitionPresence( flow::buffer_node<int> ); + TestTypeDefinitionPresence( flow::queue_node<int> ); + TestTypeDefinitionPresence( flow::sequencer_node<int> ); + TestTypeDefinitionPresence( flow::priority_queue_node<int> ); + TestTypeDefinitionPresence( flow::limiter_node<int> ); + typedef tbb::flow::interface6::internal::graph_policy_namespace::graph_buffer_policy join_policy; + const join_policy a = tbb::flow::interface6::internal::graph_policy_namespace::queueing; + TestTypeDefinitionPresence2( flow::join_node< intpair, a > ); + squelch_unused_warning(a); + TestTypeDefinitionPresence( mutex ); + TestTypeDefinitionPresence( null_mutex ); + TestTypeDefinitionPresence( null_rw_mutex ); + TestTypeDefinitionPresence( queuing_mutex ); + TestTypeDefinitionPresence( queuing_rw_mutex ); + TestTypeDefinitionPresence( recursive_mutex ); + TestTypeDefinitionPresence( spin_mutex ); + TestTypeDefinitionPresence( spin_rw_mutex ); + TestTypeDefinitionPresence( critical_section ); + TestTypeDefinitionPresence( reader_writer_lock ); +#if __TBB_TASK_GROUP_CONTEXT + TestTypeDefinitionPresence( tbb_exception ); + TestTypeDefinitionPresence( captured_exception ); + TestTypeDefinitionPresence( movable_exception<int> ); +#if !TBB_USE_CAPTURED_EXCEPTION + TestTypeDefinitionPresence( internal::tbb_exception_ptr ); +#endif /* !TBB_USE_CAPTURED_EXCEPTION */ + TestTypeDefinitionPresence( task_group_context ); + TestTypeDefinitionPresence( task_group ); + TestTypeDefinitionPresence( task_handle<Body> ); +#endif /* __TBB_TASK_GROUP_CONTEXT */ + TestTypeDefinitionPresence( blocked_range3d<int> ); + TestFuncDefinitionPresence( parallel_invoke, (const Body&, const Body&), void ); + TestFuncDefinitionPresence( parallel_do, (int*, int*, const Body1&), void ); + TestFuncDefinitionPresence( parallel_for_each, (int*, int*, const Body1&), void ); + TestFuncDefinitionPresence( parallel_for, (int, int, int, const Body1&), void ); + TestFuncDefinitionPresence( parallel_for, (const tbb::blocked_range<int>&, const Body2&, const tbb::simple_partitioner&), void ); + TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, const int&, const Body1a&, const Body1b&, const tbb::auto_partitioner&), int ); + TestFuncDefinitionPresence( parallel_reduce, (const tbb::blocked_range<int>&, Body2&, tbb::affinity_partitioner&), void ); + TestFuncDefinitionPresence( parallel_scan, (const tbb::blocked_range2d<int>&, Body3&, const tbb::auto_partitioner&), void ); + TestFuncDefinitionPresence( parallel_sort, (int*, int*), void ); + TestTypeDefinitionPresence( pipeline ); + TestFuncDefinitionPresence( parallel_pipeline, (size_t, const tbb::filter_t<void,void>&), void ); + TestTypeDefinitionPresence( task ); + TestTypeDefinitionPresence( empty_task ); + TestTypeDefinitionPresence( task_list ); + TestTypeDefinitionPresence( task_scheduler_init ); + TestTypeDefinitionPresence( task_scheduler_observer ); + TestTypeDefinitionPresence( tbb_thread ); + TestTypeDefinitionPresence( tbb_allocator<int> ); + TestTypeDefinitionPresence( zero_allocator<int> ); + TestTypeDefinitionPresence( tick_count ); +#if !__TBB_TEST_SECONDARY + TestExceptionClassesExports(); + return Harness::Done; +#endif +} diff --git a/src/tbb/src/test/test_tbb_thread.cpp b/src/tbb/src/test/test_tbb_thread.cpp new file mode 100644 index 0000000..d5e6076 --- /dev/null +++ b/src/tbb/src/test/test_tbb_thread.cpp @@ -0,0 +1,40 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#define THREAD tbb::tbb_thread +#define THIS_THREAD tbb::this_tbb_thread +#define THIS_THREAD_SLEEP THIS_THREAD::sleep +#include "test_thread.h" +#include "harness.h" + +/* we want to test tbb::tbb_thread */ +int TestMain () { + CheckSignatures(); + RunTests(); + return Harness::Done; +} diff --git a/src/tbb/src/test/test_tbb_version.cpp b/src/tbb/src/test/test_tbb_version.cpp new file mode 100644 index 0000000..298f17d --- /dev/null +++ b/src/tbb/src/test/test_tbb_version.cpp @@ -0,0 +1,283 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/tbb_stddef.h" + +#include <stdio.h> +#include <stdlib.h> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers + #pragma warning (push) + #pragma warning (disable: 4530) +#endif + +#include <vector> +#include <string> +#include <utility> + +#if !TBB_USE_EXCEPTIONS && _MSC_VER + #pragma warning (pop) +#endif + +#include "tbb/task_scheduler_init.h" + +#define HARNESS_CUSTOM_MAIN 1 +#define HARNESS_NO_PARSE_COMMAND_LINE 1 +#define HARNESS_NO_MAIN_ARGS 0 +#include "harness.h" + +#if defined (_WIN32) || defined (_WIN64) +#define TEST_SYSTEM_COMMAND "test_tbb_version.exe @" +#define putenv _putenv +#else +#define TEST_SYSTEM_COMMAND "./test_tbb_version.exe @" +#endif + +enum string_required { + required, + optional, + optional_multiple + }; + +typedef std::pair <std::string, string_required> string_pair; + +void initialize_strings_vector(std::vector <string_pair>* vector); + +const char stderr_stream[] = "version_test.err"; +const char stdout_stream[] = "version_test.out"; + +HARNESS_EXPORT +int main(int argc, char *argv[] ) { + char psBuffer[512]; +/* We first introduced runtime version identification in 3014 */ +#if TBB_INTERFACE_VERSION>=3014 + // For now, just test that run-time TBB version matches the compile-time version, + // since otherwise the subsequent test of "TBB: INTERFACE VERSION" string will fail anyway. + // We need something more clever in future. + if ( tbb::TBB_runtime_interface_version()!=TBB_INTERFACE_VERSION ){ + snprintf( psBuffer, + 512, + "%s %s %d %s %d.", + "Running with the library of different version than the test was compiled against.", + "Expected", + TBB_INTERFACE_VERSION, + "- got", + tbb::TBB_runtime_interface_version() + ); + ASSERT( tbb::TBB_runtime_interface_version()==TBB_INTERFACE_VERSION, psBuffer ); + } +#endif +#if __TBB_MIC + // Skip the test in offload mode. + // Run the test in 'true' native mode (because 'system()' works in 'true' native mode). + (argc, argv); + REPORT("skip\n"); +#else //__TBB_MIC +#if __TBB_MPI_INTEROP + REPORT("skip\n"); +#else + __TBB_TRY { + FILE *stream_out; + FILE *stream_err; + + if(argc>1 && argv[1][0] == '@' ) { + stream_err = freopen( stderr_stream, "w", stderr ); + if( stream_err == NULL ){ + REPORT( "Internal test error (freopen)\n" ); + exit( 1 ); + } + stream_out = freopen( stdout_stream, "w", stdout ); + if( stream_out == NULL ){ + REPORT( "Internal test error (freopen)\n" ); + exit( 1 ); + } + { + tbb::task_scheduler_init init(1); + } + fclose( stream_out ); + fclose( stream_err ); + exit(0); + } + //1st step check that output is empty if TBB_VERSION is not defined. + if ( getenv("TBB_VERSION") ){ + REPORT( "TBB_VERSION defined, skipping step 1 (empty output check)\n" ); + }else{ + if( ( system(TEST_SYSTEM_COMMAND) ) != 0 ){ + REPORT( "Error (step 1): Internal test error\n" ); + exit( 1 ); + } + //Checking output streams - they should be empty + stream_err = fopen( stderr_stream, "r" ); + if( stream_err == NULL ){ + REPORT( "Error (step 1):Internal test error (stderr open)\n" ); + exit( 1 ); + } + while( !feof( stream_err ) ) { + if( fgets( psBuffer, 512, stream_err ) != NULL ){ + REPORT( "Error (step 1): stderr should be empty\n" ); + exit( 1 ); + } + } + fclose( stream_err ); + stream_out = fopen( stdout_stream, "r" ); + if( stream_out == NULL ){ + REPORT( "Error (step 1):Internal test error (stdout open)\n" ); + exit( 1 ); + } + while( !feof( stream_out ) ) { + if( fgets( psBuffer, 512, stream_out ) != NULL ){ + REPORT( "Error (step 1): stdout should be empty\n" ); + exit( 1 ); + } + } + fclose( stream_out ); + } + + //Setting TBB_VERSION in case it is not set + if ( !getenv("TBB_VERSION") ){ + putenv(const_cast<char*>("TBB_VERSION=1")); + } + + if( ( system(TEST_SYSTEM_COMMAND) ) != 0 ){ + REPORT( "Error (step 2):Internal test error\n" ); + exit( 1 ); + } + //Checking pipe - it should contain version data + std::vector <string_pair> strings_vector; + std::vector <string_pair>::iterator strings_iterator; + + initialize_strings_vector( &strings_vector ); + strings_iterator = strings_vector.begin(); + + stream_out = fopen( stdout_stream, "r" ); + if( stream_out == NULL ){ + REPORT( "Error (step 2):Internal test error (stdout open)\n" ); + exit( 1 ); + } + while( !feof( stream_out ) ) { + if( fgets( psBuffer, 512, stream_out ) != NULL ){ + REPORT( "Error (step 2): stdout should be empty\n" ); + exit( 1 ); + } + } + fclose( stream_out ); + + stream_err = fopen( stderr_stream, "r" ); + if( stream_err == NULL ){ + REPORT( "Error (step 1):Internal test error (stderr open)\n" ); + exit( 1 ); + } + + while( !feof( stream_err ) ) { + if( fgets( psBuffer, 512, stream_err ) != NULL ){ + if (strstr( psBuffer, "TBBmalloc: " )) { + // TBB allocator might or might not be here, ignore it + continue; + } + bool match_found = false; + do{ + if ( strings_iterator == strings_vector.end() ){ + REPORT( "Error: version string dictionary ended prematurely.\n" ); + REPORT( "No match for: \t%s", psBuffer ); + exit( 1 ); + } + if ( strstr( psBuffer, strings_iterator->first.c_str() ) == NULL ){ // mismatch + if( strings_iterator->second == required ){ + REPORT( "Error: version strings do not match.\n" ); + REPORT( "Expected \"%s\" not found in:\n\t%s", strings_iterator->first.c_str(), psBuffer ); + exit( 1 ); + } + ++strings_iterator; + }else{ + match_found = true; + if( strings_iterator->second != optional_multiple ) + ++strings_iterator; + } + }while( !match_found ); + } + } + fclose( stream_err ); + } __TBB_CATCH(...) { + ASSERT( 0,"unexpected exception" ); + } + REPORT("done\n"); +#endif //__TBB_MPI_INTEROP +#endif //__TBB_MIC + return 0; +} + + +// Fill dictionary with version strings for platforms +void initialize_strings_vector(std::vector <string_pair>* vector) +{ + vector->push_back(string_pair("TBB: VERSION\t\t4.0", required)); // check TBB_VERSION + vector->push_back(string_pair("TBB: INTERFACE VERSION\t6005", required)); // check TBB_INTERFACE_VERSION + vector->push_back(string_pair("TBB: BUILD_DATE", required)); + vector->push_back(string_pair("TBB: BUILD_HOST", required)); + vector->push_back(string_pair("TBB: BUILD_OS", required)); +#if _WIN32||_WIN64 +#if !__MINGW32__ + vector->push_back(string_pair("TBB: BUILD_CL", required)); +#endif + vector->push_back(string_pair("TBB: BUILD_COMPILER", required)); +#elif __APPLE__ + vector->push_back(string_pair("TBB: BUILD_KERNEL", required)); + vector->push_back(string_pair("TBB: BUILD_GCC", required)); + vector->push_back(string_pair("TBB: BUILD_COMPILER", optional)); //if( getenv("COMPILER_VERSION") ) +#elif __sun + vector->push_back(string_pair("TBB: BUILD_KERNEL", required)); + vector->push_back(string_pair("TBB: BUILD_SUNCC", required)); + vector->push_back(string_pair("TBB: BUILD_COMPILER", optional)); //if( getenv("COMPILER_VERSION") ) +#else //We use version_info_linux.sh for unsupported OSes + vector->push_back(string_pair("TBB: BUILD_KERNEL", required)); + vector->push_back(string_pair("TBB: BUILD_GCC", required)); + vector->push_back(string_pair("TBB: BUILD_COMPILER", optional)); //if( getenv("COMPILER_VERSION") ) + vector->push_back(string_pair("TBB: BUILD_GLIBC", required)); + vector->push_back(string_pair("TBB: BUILD_LD", required)); +#endif + vector->push_back(string_pair("TBB: BUILD_TARGET", required)); + vector->push_back(string_pair("TBB: BUILD_COMMAND", required)); + vector->push_back(string_pair("TBB: TBB_USE_DEBUG", required)); + vector->push_back(string_pair("TBB: TBB_USE_ASSERT", required)); +#if __TBB_CPF_BUILD + vector->push_back(string_pair("TBB: TBB_PREVIEW_BINARY", required)); +#endif + vector->push_back(string_pair("TBB: DO_ITT_NOTIFY", required)); + vector->push_back(string_pair("TBB: ITT", optional)); //#ifdef DO_ITT_NOTIFY + vector->push_back(string_pair("TBB: ALLOCATOR", required)); +#if _WIN32||_WIN64 + vector->push_back(string_pair("TBB: Processor groups", required)); + vector->push_back(string_pair("TBB: ----- Group", optional_multiple)); +#endif + vector->push_back(string_pair("TBB: RML", optional)); + vector->push_back(string_pair("TBB: Intel(R) RML library built:", optional)); + vector->push_back(string_pair("TBB: Intel(R) RML library version:", optional)); + vector->push_back(string_pair("TBB: Tools support", required)); + return; +} diff --git a/src/tbb/src/test/test_thread.h b/src/tbb/src/test/test_thread.h new file mode 100644 index 0000000..ef0ee61 --- /dev/null +++ b/src/tbb/src/test/test_thread.h @@ -0,0 +1,290 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/tbb_thread.h" +#include "tbb/atomic.h" + +#define HARNESS_NO_PARSE_COMMAND_LINE 1 +#include "harness_report.h" +#include "harness_assert.h" + +static const int THRDS = 3; +static const int THRDS_DETACH = 2; +static tbb::atomic<int> sum; +static tbb::atomic<int> BaseCount; +static THREAD::id real_ids[THRDS+THRDS_DETACH]; + +class Base { + mutable int copy_throws; + friend void RunTests(); + friend void CheckExceptionSafety(); + void operator=( const Base& ); // Deny access +protected: + Base() : copy_throws(100) {++BaseCount;} + Base( const Base& c ) : copy_throws(c.copy_throws) { + if( --copy_throws<=0 ) + __TBB_THROW(0); + ++BaseCount; + } + ~Base() {--BaseCount;} +}; + +template<int N> +class Data: Base { + Data(); // Deny access + explicit Data(int v) : value(v) {} + + friend void RunTests(); + friend void CheckExceptionSafety(); +public: + int value; +}; + + +#include "harness_barrier.h" + +class ThreadFunc: Base { + ThreadFunc() {} + + static Harness::SpinBarrier init_barrier; + + friend void RunTests(); +public: + void operator()(){ + real_ids[0] = THIS_THREAD::get_id(); + init_barrier.wait(); + + sum.fetch_and_add(1); + } + void operator()(int num){ + real_ids[num] = THIS_THREAD::get_id(); + init_barrier.wait(); + + sum.fetch_and_add(num); + } + void operator()(int num, Data<0> dx) { + real_ids[num] = THIS_THREAD::get_id(); + + const double WAIT = .1; + const double SHORT_TOLERANCE = 1e-8; +#if _WIN32 || _WIN64 + const double LONG_TOLERANCE = 0.120; // maximal scheduling quantum for Windows Server +#else + const double LONG_TOLERANCE = 0.200; // reasonable upper bound +#endif + tbb::tick_count t0 = tbb::tick_count::now(); + tbb::this_tbb_thread::sleep( tbb::tick_count::interval_t(WAIT) ); + tbb::tick_count t1 = tbb::tick_count::now(); + double delta = (t1-t0).seconds() - WAIT; + if(delta+SHORT_TOLERANCE <= 0.0) + REPORT("ERROR: Sleep interval too short (%g outside short tolerance(%g))\n", (t1-t0).seconds(), WAIT - SHORT_TOLERANCE); + if(delta > LONG_TOLERANCE) + REPORT("Warning: Sleep interval too long (%g outside long tolerance(%g))\n", (t1-t0).seconds(), WAIT + LONG_TOLERANCE); + + init_barrier.wait(); + + sum.fetch_and_add(num); + sum.fetch_and_add(dx.value); + } + void operator()(Data<0> d) { + tbb::this_tbb_thread::sleep( tbb::tick_count::interval_t(d.value*1.) ); + } +}; + +Harness::SpinBarrier ThreadFunc::init_barrier(THRDS); + +void CheckRelations( const THREAD::id ids[], int n, bool duplicates_allowed ) { + for( int i=0; i<n; ++i ) { + const THREAD::id x = ids[i]; + for( int j=0; j<n; ++j ) { + const THREAD::id y = ids[j]; + ASSERT( (x==y)==!(x!=y), NULL ); + ASSERT( (x<y)==!(x>=y), NULL ); + ASSERT( (x>y)==!(x<=y), NULL ); + ASSERT( (x<y)+(x==y)+(x>y)==1, NULL ); + ASSERT( x!=y || i==j || duplicates_allowed, NULL ); + for( int k=0; k<n; ++k ) { + const THREAD::id z = ids[j]; + ASSERT( !(x<y && y<z) || x<z, "< is not transitive" ); + } + } + } +} + +class AnotherThreadFunc: Base { +public: + void operator()() {} + void operator()(const Data<1>&) {} + void operator()(const Data<1>&, const Data<2>&) {} + friend void CheckExceptionSafety(); +}; + +#if TBB_USE_EXCEPTIONS +void CheckExceptionSafety() { + int original_count = BaseCount; + // d loops over number of copies before throw occurs + for( int d=1; d<=3; ++d ) { + // Try all combinations of throw/nothrow for f, x, and y's copy constructor. + for( int i=0; i<8; ++i ) { + { + const AnotherThreadFunc f = AnotherThreadFunc(); + if( i&1 ) f.copy_throws = d; + const Data<1> x(0); + if( i&2 ) x.copy_throws = d; + const Data<2> y(0); + if( i&4 ) y.copy_throws = d; + bool exception_caught = false; + for( int j=0; j<3; ++j ) { + try { + switch(j) { + case 0: {THREAD t(f); t.join();} break; + case 1: {THREAD t(f,x); t.join();} break; + case 2: {THREAD t(f,x,y); t.join();} break; + } + } catch(...) { + exception_caught = true; + } + ASSERT( !exception_caught||(i&((1<<(j+1))-1))!=0, NULL ); + } + } +// Intel Compiler sometimes fails to destroy all implicitly generated copies +// of an object when a copy constructor throws an exception. +// Problem was reported as Quad issue 482935. +// This #if should be removed or tightened when the bug is fixed. +#if !((_WIN32 || _WIN64) && defined(__INTEL_COMPILER)) + ASSERT( BaseCount==original_count, "object leak detected" ); +#endif + } + } +} +#endif /* TBB_USE_EXCEPTIONS */ + +#include <cstdio> + +void RunTests() { + + ThreadFunc t; + Data<0> d100(100), d1(1), d0(0); + THREAD::id id; + THREAD::id id0, uniq_ids[THRDS]; + + THREAD thrs[THRDS]; + THREAD thr; + THREAD thr0(t); + THREAD thr1(t, 2); + THREAD thr2(t, 1, d100); + + ASSERT( thr0.get_id() != id, NULL ); + id0 = thr0.get_id(); + tbb::move(thrs[0], thr0); + ASSERT( thr0.get_id() == id, NULL ); + ASSERT( thrs[0].get_id() == id0, NULL ); + + THREAD::native_handle_type h1 = thr1.native_handle(); + THREAD::native_handle_type h2 = thr2.native_handle(); + THREAD::id id1 = thr1.get_id(); + THREAD::id id2 = thr2.get_id(); + tbb::swap(thr1, thr2); + ASSERT( thr1.native_handle() == h2, NULL ); + ASSERT( thr2.native_handle() == h1, NULL ); + ASSERT( thr1.get_id() == id2, NULL ); + ASSERT( thr2.get_id() == id1, NULL ); + thr1.swap(thr2); + ASSERT( thr1.native_handle() == h1, NULL ); + ASSERT( thr2.native_handle() == h2, NULL ); + ASSERT( thr1.get_id() == id1, NULL ); + ASSERT( thr2.get_id() == id2, NULL ); + thr1.swap(thr2); + + tbb::move(thrs[1], thr1); + ASSERT( thr1.get_id() == id, NULL ); + + tbb::move(thrs[2], thr2); + ASSERT( thr2.get_id() == id, NULL ); + + for (int i=0; i<THRDS; i++) + uniq_ids[i] = thrs[i].get_id(); + + ASSERT( thrs[2].joinable(), NULL ); + + for (int i=0; i<THRDS; i++) + thrs[i].join(); + for (int i=0; i<THRDS; i++) + ASSERT( real_ids[i] == uniq_ids[i], NULL ); + + int current_sum = sum; + ASSERT( current_sum == 104, NULL ); + ASSERT( ! thrs[2].joinable(), NULL ); + ASSERT( BaseCount==4, "object leak detected" ); + +#if TBB_USE_EXCEPTIONS + CheckExceptionSafety(); +#endif + + // Note: all tests involving BaseCount should be put before the tests + // involing detached threads, because there is no way of knowing when + // a detached thread destroys its arguments. + + THREAD thr_detach_0(t, d0); + real_ids[THRDS] = thr_detach_0.get_id(); + thr_detach_0.detach(); + ASSERT( thr_detach_0.get_id() == id, NULL ); + + THREAD thr_detach_1(t, d1); + real_ids[THRDS+1] = thr_detach_1.get_id(); + thr_detach_1.detach(); + ASSERT( thr_detach_1.get_id() == id, NULL ); + + CheckRelations(real_ids, THRDS+THRDS_DETACH, true); + + CheckRelations(uniq_ids, THRDS, false); + + for (int i=0; i<2; i++) { + AnotherThreadFunc empty_func; + THREAD thr_to(empty_func), thr_from(empty_func); + THREAD::id from_id = thr_from.get_id(); + if (i) thr_to.join(); + thr_to = thr_from; + ASSERT( thr_from.get_id() == THREAD::id(), NULL ); + ASSERT( thr_to.get_id() == from_id, NULL ); + } + + ASSERT( THREAD::hardware_concurrency() > 0, NULL); +} + +typedef bool (*id_relation)( THREAD::id, THREAD::id ); + +id_relation CheckSignatures() { + id_relation r[6] = {&tbb::operator==, + &tbb::operator!=, + &tbb::operator<, + &tbb::operator>, + &tbb::operator<=, + &tbb::operator>=}; + return r[1]; +} diff --git a/src/tbb/src/test/test_tick_count.cpp b/src/tbb/src/test/test_tick_count.cpp new file mode 100644 index 0000000..4a07f89 --- /dev/null +++ b/src/tbb/src/test/test_tick_count.cpp @@ -0,0 +1,148 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "tbb/tick_count.h" +#include "harness.h" +#include <cstdio> + +//! Assert that two times in seconds are very close. +void AssertNear( double x, double y ) { + ASSERT( -1.0E-10 <= x-y && x-y <=1.0E-10, NULL ); +} + +//! Test arithmetic operators on tick_count::interval_t +void TestArithmetic( const tbb::tick_count& t0, const tbb::tick_count& t1, const tbb::tick_count& t2 ) { + tbb::tick_count::interval_t i= t1-t0; + tbb::tick_count::interval_t j = t2-t1; + tbb::tick_count::interval_t k = t2-t0; + AssertSameType( tbb::tick_count::interval_t(), i-j ); + AssertSameType( tbb::tick_count::interval_t(), i+j ); + ASSERT( i.seconds()>1E-9, NULL ); + ASSERT( j.seconds()>1E-9, NULL ); + ASSERT( k.seconds()>2E-9, NULL ); + AssertNear( (i+j).seconds(), k.seconds() ); + AssertNear( (k-j).seconds(), i.seconds() ); + AssertNear( ((k-j)+(j-i)).seconds(), k.seconds()-i.seconds() ); + tbb::tick_count::interval_t sum; + sum += i; + sum += j; + AssertNear( sum.seconds(), k.seconds() ); + sum -= i; + AssertNear( sum.seconds(), j.seconds() ); + sum -= j; + AssertNear( sum.seconds(), 0.0 ); +} + +//------------------------------------------------------------------------ +// Test for overhead in calls to tick_count +//------------------------------------------------------------------------ + +//! Wait for given duration. +/** The duration parameter is in units of seconds. */ +static void WaitForDuration( double duration ) { + tbb::tick_count start = tbb::tick_count::now(); + while( (tbb::tick_count::now()-start).seconds() < duration ) + continue; +} + +//! Test that average timer overhead is within acceptable limit. +/** The 'tolerance' value inside the test specifies the limit. */ +void TestSimpleDelay( int ntrial, double duration, double tolerance ) { + double total_worktime = 0; + // Iteration -1 warms up the code cache. + for( int trial=-1; trial<ntrial; ++trial ) { + tbb::tick_count t0 = tbb::tick_count::now(); + if( duration ) WaitForDuration(duration); + tbb::tick_count t1 = tbb::tick_count::now(); + if( trial>=0 ) { + total_worktime += (t1-t0).seconds(); + } + } + // Compute average worktime and average delta + double worktime = total_worktime/ntrial; + double delta = worktime-duration; + REMARK("worktime=%g delta=%g tolerance=%g\n", worktime, delta, tolerance); + + // Check that delta is acceptable + if( delta<0 ) + REPORT("ERROR: delta=%g < 0\n",delta); + if( delta>tolerance ) + REPORT("%s: delta=%g > %g=tolerance where duration=%g\n",delta>3*tolerance?"ERROR":"Warning",delta,tolerance,duration); +} + +//------------------------------------------------------------------------ +// Test for subtracting calls to tick_count from different threads. +//------------------------------------------------------------------------ + +#include "tbb/atomic.h" +const int MAX_NTHREAD = 1000; +static tbb::atomic<int> Counter; +static volatile bool Flag; +static tbb::tick_count tick_count_array[MAX_NTHREAD]; + +struct TickCountDifferenceBody { + void operator()( int id ) const { + if( --Counter==0 ) Flag = true; + while( !Flag ) continue; + tick_count_array[id] = tbb::tick_count::now(); + } +}; + +//! Test that two tick_count values recorded on different threads can be meaningfully subtracted. +void TestTickCountDifference( int n ) { + double tolerance = 3E-4; + for( int trial=0; trial<10; ++trial ) { + Counter = n; + Flag = false; + NativeParallelFor( n, TickCountDifferenceBody() ); + ASSERT( Counter==0, NULL ); + for( int i=0; i<n; ++i ) + for( int j=0; j<i; ++j ) { + double diff = (tick_count_array[i]-tick_count_array[j]).seconds(); + if( diff<0 ) diff = -diff; + if( diff>tolerance ) { + REPORT("%s: cross-thread tick_count difference = %g > %g = tolerance\n", + diff>3*tolerance?"ERROR":"Warning",diff,tolerance); + } + } + } +} + +int TestMain () { + tbb::tick_count t0 = tbb::tick_count::now(); + TestSimpleDelay(/*ntrial=*/1000000,/*duration=*/0, /*tolerance=*/2E-6); + tbb::tick_count t1 = tbb::tick_count::now(); + TestSimpleDelay(/*ntrial=*/10, /*duration=*/0.125,/*tolerance=*/5E-6); + tbb::tick_count t2 = tbb::tick_count::now(); + TestArithmetic(t0,t1,t2); + + for( int n=MinThread; n<=MaxThread; ++n ) { + TestTickCountDifference(n); + } + return Harness::Done; +} diff --git a/src/tbb/src/test/test_tuple.cpp b/src/tbb/src/test/test_tuple.cpp new file mode 100644 index 0000000..03d7fd1 --- /dev/null +++ b/src/tbb/src/test/test_tuple.cpp @@ -0,0 +1,164 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// tbb::tuple + +#include "harness.h" +// this test should match that in graph.h, so we test whatever tuple is +// being used by the join_node. +#if !__SUNPRO_CC +#if TBB_IMPLEMENT_CPP0X && (!defined(_MSC_VER) || _MSC_VER < 1600) +#define __TESTING_STD_TUPLE__ 0 +#define TBB_PREVIEW_TUPLE 1 +#include "tbb/compat/tuple" +#else +#define __TESTING_STD_TUPLE__ 1 +#include <tuple> +#endif +#include <string> +#include <iostream> + +using namespace std; + +class non_trivial { +public: + non_trivial() {} + ~non_trivial() {} + non_trivial(const non_trivial& other) : my_int(other.my_int), my_float(other.my_float) { } + int get_int() const { return my_int; } + float get_float() const { return my_float; } + void set_int(int newval) { my_int = newval; } + void set_float(float newval) { my_float = newval; } +private: + int my_int; + float my_float; +}; + +void RunTests() { + +#if __TESTING_STD_TUPLE__ + REMARK("Testing platform tuple\n"); +#else + REMARK("Testing compat/tuple\n"); +#endif + tuple<int> ituple1(3); + tuple<int> ituple2(5); + tuple<double> ftuple2(4.1); + + ASSERT(!(ituple1 == ituple2), NULL); + ASSERT(ituple1 != ituple2, NULL); + ASSERT(!(ituple1 > ituple2), NULL); + ASSERT(ituple1 < ituple2, NULL); + ASSERT(ituple1 <= ituple2, NULL); + ASSERT(!(ituple1 >= ituple2), NULL); + ASSERT(ituple1 < ftuple2, NULL); + + typedef tuple<int,double,float> tuple_type1; + typedef tuple<int,int,int> int_tuple_type; + typedef tuple<int,non_trivial,int> non_trivial_tuple_type; + typedef tuple<double,std::string,char> stringy_tuple_type; + const tuple_type1 tup1(42,3.14159,2.0f); + int_tuple_type int_tup(4, 5, 6); + non_trivial_tuple_type nti; + stringy_tuple_type stv; + get<1>(stv) = "hello"; + get<2>(stv) = 'x'; + + ASSERT(get<0>(stv) == 0.0, NULL); + ASSERT(get<1>(stv) == "hello", NULL); + ASSERT(get<2>(stv) == 'x', NULL); + + ASSERT(tuple_size<tuple_type1>::value == 3, NULL); + ASSERT(get<0>(tup1) == 42, NULL); + ASSERT(get<1>(tup1) == 3.14159, NULL); + ASSERT(get<2>(tup1) == 2.0, NULL); + + get<1>(nti).set_float(1.0); + get<1>(nti).set_int(32); + ASSERT(get<1>(nti).get_int() == 32, NULL); + ASSERT(get<1>(nti).get_float() == 1.0, NULL); + + // converting constructor + tuple<double,double,double> tup2(1,2.0,3.0f); + tuple<double,double,double> tup3(9,4.0,7.0f); + ASSERT(tup2 != tup3, NULL); + + ASSERT(tup2 < tup3, NULL); + + // assignment + tup2 = tup3; + ASSERT(tup2 == tup3, NULL); + + tup2 = int_tup; + ASSERT(get<0>(tup2) == 4, NULL); + ASSERT(get<1>(tup2) == 5, NULL); + ASSERT(get<2>(tup2) == 6, NULL); + + // increment component of tuple + get<0>(tup2) += 1; + ASSERT(get<0>(tup2) == 5, NULL); + + std::pair<int,int> two_pair( 4, 8); + tuple<int,int> two_pair_tuple; + two_pair_tuple = two_pair; + ASSERT(get<0>(two_pair_tuple) == 4, NULL); + ASSERT(get<1>(two_pair_tuple) == 8, NULL); + + //relational ops + ASSERT(int_tuple_type(1,1,0) == int_tuple_type(1,1,0),NULL); + ASSERT(int_tuple_type(1,0,1) < int_tuple_type(1,1,1),NULL); + ASSERT(int_tuple_type(1,0,0) > int_tuple_type(0,1,0),NULL); + ASSERT(int_tuple_type(0,0,0) != int_tuple_type(1,0,1),NULL); + ASSERT(int_tuple_type(0,1,0) <= int_tuple_type(0,1,1),NULL); + ASSERT(int_tuple_type(0,0,1) <= int_tuple_type(0,0,1),NULL); + ASSERT(int_tuple_type(1,1,1) >= int_tuple_type(1,0,0),NULL); + ASSERT(int_tuple_type(0,1,1) >= int_tuple_type(0,1,1),NULL); + typedef tuple<int,float,double,char> mixed_tuple_left; + typedef tuple<float,int,char,double> mixed_tuple_right; + ASSERT(mixed_tuple_left(1,1.f,1,1) == mixed_tuple_right(1.f,1,1,1),NULL); + ASSERT(mixed_tuple_left(1,0.f,1,1) < mixed_tuple_right(1.f,1,1,1),NULL); + ASSERT(mixed_tuple_left(1,1.f,1,1) > mixed_tuple_right(1.f,1,0,1),NULL); + ASSERT(mixed_tuple_left(1,1.f,1,0) != mixed_tuple_right(1.f,1,1,1),NULL); + ASSERT(mixed_tuple_left(1,0.f,1,1) <= mixed_tuple_right(1.f,1,0,1),NULL); + ASSERT(mixed_tuple_left(1,0.f,0,1) <= mixed_tuple_right(1.f,0,0,1),NULL); + ASSERT(mixed_tuple_left(1,1.f,1,0) >= mixed_tuple_right(1.f,0,1,1),NULL); + ASSERT(mixed_tuple_left(0,1.f,1,0) >= mixed_tuple_right(0.f,1,1,0),NULL); + +} + +int TestMain() { + RunTests(); + return Harness::Done; +} +#else // __SUNPRO_CC + +int TestMain() { + return Harness::Skipped; +} + +#endif // __SUNPRO_CC diff --git a/src/tbb/src/test/test_write_once_node.cpp b/src/tbb/src/test/test_write_once_node.cpp new file mode 100644 index 0000000..86206e3 --- /dev/null +++ b/src/tbb/src/test/test_write_once_node.cpp @@ -0,0 +1,173 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +#include "harness_graph.h" + +#include "tbb/task_scheduler_init.h" + +#define N 300 +#define T 4 +#define M 4 + +template< typename R > +void simple_read_write_tests() { + tbb::flow::graph g; + tbb::flow::write_once_node<R> n(g); + + for ( int t = 0; t < T; ++t ) { + R v0(0); + harness_counting_receiver<R> r[M]; + + ASSERT( n.is_valid() == false, NULL ); + ASSERT( n.try_get( v0 ) == false, NULL ); + + if ( t % 2 ) { + ASSERT( n.try_put( static_cast<R>(N+1) ), NULL ); + ASSERT( n.is_valid() == true, NULL ); + ASSERT( n.try_get( v0 ) == true, NULL ); + ASSERT( v0 == R(N+1), NULL ); + } + + for (int i = 0; i < M; ++i) { + tbb::flow::make_edge( n, r[i] ); + } + + if ( t%2 ) { + for (int i = 0; i < M; ++i) { + size_t c = r[i].my_count; + ASSERT( int(c) == 1, NULL ); + } + } + + for (int i = 1; i <= N; ++i ) { + R v1(static_cast<R>(i)); + + bool result = n.try_put( v1 ); + if ( !(t%2) && i == 1 ) + ASSERT( result == true, NULL ); + else + ASSERT( result == false, NULL ); + + ASSERT( n.is_valid() == true, NULL ); + + for (int j = 0; j < N; ++j ) { + R v2(0); + ASSERT( n.try_get( v2 ), NULL ); + if ( t%2 ) + ASSERT( R(N+1) == v2, NULL ); + else + ASSERT( R(1) == v2, NULL ); + } + } + for (int i = 0; i < M; ++i) { + size_t c = r[i].my_count; + ASSERT( int(c) == 1, NULL ); + } + for (int i = 0; i < M; ++i) { + tbb::flow::remove_edge( n, r[i] ); + } + ASSERT( n.try_put( R(0) ) == false, NULL ); + for (int i = 0; i < M; ++i) { + size_t c = r[i].my_count; + ASSERT( int(c) == 1, NULL ); + } + n.clear(); + ASSERT( n.is_valid() == false, NULL ); + ASSERT( n.try_get( v0 ) == false, NULL ); + } +} + +template< typename R > +class native_body : NoAssign { + tbb::flow::write_once_node<R> &my_node; + +public: + + native_body( tbb::flow::write_once_node<R> &n ) : my_node(n) {} + + void operator()( int i ) const { + R v1(static_cast<R>(i)); + ASSERT( my_node.try_put( v1 ) == false, NULL ); + ASSERT( my_node.is_valid() == true, NULL ); + ASSERT( my_node.try_get( v1 ) == true, NULL ); + ASSERT( v1 == R(-1), NULL ); + } +}; + +template< typename R > +void parallel_read_write_tests() { + tbb::flow::graph g; + tbb::flow::write_once_node<R> n(g); + //Create a vector of identical nodes + std::vector< tbb::flow::write_once_node<R> > wo_vec(2, n); + + for (size_t node_idx=0; node_idx<wo_vec.size(); ++node_idx) { + for ( int t = 0; t < T; ++t ) { + harness_counting_receiver<R> r[M]; + + for (int i = 0; i < M; ++i) { + tbb::flow::make_edge( wo_vec[node_idx], r[i] ); + } + R v0; + ASSERT( wo_vec[node_idx].is_valid() == false, NULL ); + ASSERT( wo_vec[node_idx].try_get( v0 ) == false, NULL ); + + ASSERT( wo_vec[node_idx].try_put( R(-1) ), NULL ); + + NativeParallelFor( N, native_body<R>( wo_vec[node_idx] ) ); + + for (int i = 0; i < M; ++i) { + size_t c = r[i].my_count; + ASSERT( int(c) == 1, NULL ); + } + for (int i = 0; i < M; ++i) { + tbb::flow::remove_edge( wo_vec[node_idx], r[i] ); + } + ASSERT( wo_vec[node_idx].try_put( R(0) ) == false, NULL ); + for (int i = 0; i < M; ++i) { + size_t c = r[i].my_count; + ASSERT( int(c) == 1, NULL ); + } + wo_vec[node_idx].clear(); + ASSERT( wo_vec[node_idx].is_valid() == false, NULL ); + ASSERT( wo_vec[node_idx].try_get( v0 ) == false, NULL ); + } + } +} + +int TestMain() { + simple_read_write_tests<int>(); + simple_read_write_tests<float>(); + for( int p=MinThread; p<=MaxThread; ++p ) { + tbb::task_scheduler_init init(p); + parallel_read_write_tests<int>(); + parallel_read_write_tests<float>(); + } + return Harness::Done; +} + diff --git a/src/tbb/src/test/test_yield.cpp b/src/tbb/src/test/test_yield.cpp new file mode 100644 index 0000000..65aee4b --- /dev/null +++ b/src/tbb/src/test/test_yield.cpp @@ -0,0 +1,73 @@ +/* + Copyright 2005-2012 Intel Corporation. All Rights Reserved. + + This file is part of Threading Building Blocks. + + Threading Building Blocks is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Threading Building Blocks is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Threading Building Blocks; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, you may use this file as part of a free software + library without restriction. Specifically, if other files instantiate + templates or use macros or inline functions from this file, or you compile + this file and link it with other files to produce an executable, this + file does not by itself cause the resulting executable to be covered by + the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +// Test that __TBB_Yield works. +// On Red Hat EL4 U1, it does not work, because sched_yield is broken. + +#include "tbb/tbb_machine.h" +#include "tbb/tick_count.h" +#include "harness.h" + +static volatile long CyclicCounter; +static volatile bool Quit; +double SingleThreadTime; + +struct RoundRobin: NoAssign { + const int number_of_threads; + RoundRobin( long p ) : number_of_threads(p) {} + void operator()( long k ) const { + tbb::tick_count t0 = tbb::tick_count::now(); + for( long i=0; i<10000; ++i ) { + // Wait for previous thread to notify us + for( int j=0; CyclicCounter!=k && !Quit; ++j ) { + __TBB_Yield(); + if( j%100==0 ) { + tbb::tick_count t1 = tbb::tick_count::now(); + if( (t1-t0).seconds()>=1.0*number_of_threads ) { + REPORT("Warning: __TBB_Yield failing to yield with %d threads (or system is heavily loaded)\n",number_of_threads); + Quit = true; + return; + } + } + } + // Notify next thread that it can run + CyclicCounter = (k+1)%number_of_threads; + } + } +}; + +int TestMain () { + for( int p=MinThread; p<=MaxThread; ++p ) { + REMARK("testing with %d threads\n", p ); + CyclicCounter = 0; + Quit = false; + NativeParallelFor( long(p), RoundRobin(p) ); + } + return Harness::Done; +} + -- 2.47.3